K8S学习笔录 - Service基本用法

原文连接html

Service能够为一组具备相同功能的容器应用提供一个统一的入口地址,而且将请求负载分发到后端的各个容器应用上。前端

为何须要Service

Service的存在主要为了解决 客户端没法肯定为它提供服务的Pod的地址 的问题。node

可能因为一些问题(Pod调度、异常等),该Pod从该节点被驱逐到其余节点上,此时Pod的IP可能会变; 或者因为Pod的水平伸缩,多出来或者少几个提供一样服务的Pod。nginx

此时须要一个中间层转发客户端的请求,为客户端提供稳定的服务。 同时该中间层也能够作负载均衡、服务暴露等工做。git

Service是如何工做的

Service在配置过程当中,会要求配置一个Pod选择规则。经过该规则找到提供服务的Pod列表。 而后客户端不会直接访问这些Pod,而是经过Service来访问这些Pod。github

例如客户端要访问前端,前端要访问后端。web

外部客户端不关心前端Pod数量,而直接链接到前端服务上,由前端服务选择一个Pod来提供服务。 前端服务也不关心后端Pod数量,而直接链接到后端服务商,由后端服务选择一个Pod来提供服务。 在此期间,不管是Pod变动、迁移,上游都不须要关心。json

svc-overview.png

Service配置定义

经过Service的结构能够清晰地了解Service完整的配置内容。后端

更多说明能够经过kubernetes.io/docs/concep…查看。api

列出经常使用的Service配置结构。

type Service struct {
    metav1.TypeMeta `json:",inline"`
    metav1.ObjectMeta `json:"metadata,omitempty"`

    // Service的定义
    Spec ServiceSpec `json:"spec,omitempty"`

    // Service最近的状态,由系统维护。只读。
    Status ServiceStatus `json:"status,omitempty"`
}

type ServiceSpec struct {
    // 服务暴露端口配置列表
    Ports []ServicePort `json:"ports,omitempty"`

    // 服务的路由配置
    // 使用该字段配置和Pod的Label配置进行匹配
    // 若是该字段为空或者未定义,会假设有一个外部的Endpoints
    // 只能在Type字段为ClusterIP、NodePort和LoadBalancer时生效,在Type是ExternalName时被忽略
    Selector map[string]string `json:"selector,omitempty"`

    // 集群IP。
    // 一般状况下该值是由master随机分配的,可是若是手动声明了,就要保证在集群中未被使用,不然该服务会建立失败。
    // 该字段不能被更新
    // 有效值为None,空字符串("")和有效的IP地址
    // 若是使用Headeless服务,不须要代理时,可使用None
    // 该字段只在Type为ClusterIP、NodePOrt和LoadBalancer生效,在Type是ExternalName时被忽略
    ClusterIP string `json:"clusterIP,omitempty"`

    // 服务类型,声明了服务如何暴露出去
    // 有效值为ClusterIP(默认)、ExternalName、NodePort和LoadBalancer时起做用
    // ClusterIP 分配一个集群内网IP给该服务。经过Selector配置选择指定的服务Pod,若是未配置Selector,则根据已有的Endpoints对象来肯定。
    // 若是cluserIP为None,则不会分配虚拟IP,endpoints也会被定为一组endpoints而非一个肯定的IP
    // NodePort 在分配了集群IP的基础上(不论是指定的仍是master分配的),额外在节点上分配一个端口,能够该端口将请求路由到该集群IP上
    // LoadBalancer 在NodePort的基础上,额外建立一个负载均衡器来路由到该集群IP上
    Type ServiceType `json:"type,omitempty"`

    // 集群中节点的IP地址列表。
    // 服务将会在该列表中的节点上暴露服务端口。
    // 这些端口暴露行为不属于K8S系统的管理部分。
    ExternalIPs []string `json:"externalIPs,omitempty"`

    // Session亲和配置
    // 该字段可使用ClientIP和None(默认)做为值
    // ClientIP,则相同IP每次访问都会访问到同一个Pod
    SessionAffinity ServiceAffinity `json:"sessionAffinity,omitempty"`

    // Only applies to Service Type: LoadBalancer
    // LoadBalancer will get created with the IP specified in this field.
    // This feature depends on whether the underlying cloud-provider supports specifying
    // the loadBalancerIP when a load balancer is created.
    // This field will be ignored if the cloud-provider does not support the feature.
    LoadBalancerIP string `json:"loadBalancerIP,omitempty"`

    // If specified and supported by the platform, this will restrict traffic through the cloud-provider
    // load-balancer will be restricted to the specified client IPs. This field will be ignored if the
    // cloud-provider does not support the feature."
    // More info: https://kubernetes.io/docs/tasks/access-application-cluster/configure-cloud-provider-firewall/
    LoadBalancerSourceRanges []string `json:"loadBalancerSourceRanges,omitempty"`

    // 使用该字段后,服务在被访问的时候kubedns将会将该字段的值做为CNAME返回。
    // 使用该字段Type必须为ExternalName
    ExternalName string `json:"externalName,omitempty"`

    // 定义了服务将外部请求路由到本地节点仍是集群中其余节点。
    // 该字段值能够为Local和Cluster
    // 若是该字段值为Local,则能够保留客户端的IP,而且避免了Loadbalancer和Nodeport中网络的第二跳,但存在流量不均衡的问题。
    // 若是该字段为Cluster,则不会保留真正客户端的IP,可是流量分布均匀
    ExternalTrafficPolicy ServiceExternalTrafficPolicyType `json:"externalTrafficPolicy,omitempty"`

    // 该字段为服务健康检查使用的端口
    // 若是未定义,则service api后端会自动分配一个端口
    // 若是定义了,则使用用户定义的端口
    // 该字段只会在Type设置为LoadBalancer 和 ExternalTrafficPolicy设置为Local时生效
    HealthCheckNodePort int32 `json:"healthCheckNodePort,omitempty"`

    // publishNotReadyAddresses,意为发布未准备好的地址到DNS,默认为false
    // 当该字段设置为true时,DNS则会为Endpoints查找Service发布notReadyAddresses。
    // 防止readinessProbe在服务没启动时找不到DNS。
    PublishNotReadyAddresses bool `json:"publishNotReadyAddresses,omitempty"`

    // sessionAffinityConfig能够配置Session的最大过时时间,默认为3小时
    SessionAffinityConfig *SessionAffinityConfig `json:"sessionAffinityConfig,omitempty"`

    // 定义了服务的IP类型偏好(IPv四、IPv6)
    // 若是定义了该字段而且集群支持该IP类型,则clusterIP字段将会被分配该类的IP
    // 若是未定义,则使用集群IP的类型
    IPFamily *IPFamily `json:"ipFamily,omitempty"`
}

type ServicePort struct {

    // 服务内端口的名称,必须是一个DNS_LABEL
    // 全部在ServiceSpec中声明的端口必须有一个惟一名称
    // 若是须要定义Endpoint的话,该名字必须和定义的Endpoint中的EndpointPort同样
    Name string `json:"name,omitempty"`

    // 该端口的IP协议,当前支持TCP(默认)、UDP和SCTP
    Protocol Protocol `json:"protocol,omitempty"`

    // 要暴露的服务端口
    Port int32 `json:"port"`

    // 与服务对应的Pod上的端口号或者端口名
    // 端口号须要在1-65535之间,名字必须是一个IANA_SVC_NAME
    // 若是是名字(字符串),将会在Pod的容器中查找与之对应的端口。若是未找到,则port字段的值将会被使用
    // 当Service的ClusterIP=None时,忽略此字段,会缺省为port字段的值
    // 更多信息 : https://kubernetes.io/docs/concepts/services-networking/service/#defining-a-service
    TargetPort intstr.IntOrString `json:"targetPort,omitempty"`

    // 节点端口
    // 当type=NodePort或者LoadBalancer时会使用该值。一般状况下该字段的值由操做系统来分配。
    // 若是定义了,若是端口被占用,则服务建立失败
    // 在须要该字段的时候,默认为自动分配
    // 更多信息:https://kubernetes.io/docs/concepts/services-networking/service/#type-nodeport
    NodePort int32 `json:"nodePort,omitempty"`
}

// 服务类型
type ServiceType string
const (
    // 集群IP,服务只能在集群内被发现
    ServiceTypeClusterIP ServiceType = "ClusterIP"

    // ClusterIP的扩展,额外使用节点端口,将会在全部部署了该服务的节点上都暴露一个端口
    ServiceTypeNodePort ServiceType = "NodePort"

    // NodePort的扩展,额外使用负载均衡,服务将会被暴露在一个已经存在的负载均衡器中,由负载均衡器负责分发访问
    ServiceTypeLoadBalancer ServiceType = "LoadBalancer"

    // 额外的名字,在访问服务的时候将会返回一个CNAME记录。使用该字段的Service不会暴露或者代理任何的Pod。
    ServiceTypeExternalName ServiceType = "ExternalName"
)

// Session亲和类型
type ServiceAffinity string
const (
    ServiceAffinityClientIP ServiceAffinity = "ClientIP"
    ServiceAffinityNone ServiceAffinity = "None"
)

// Service External Traffic Policy Type string
type ServiceExternalTrafficPolicyType string
const (
    // 该值定义了使用节点本地的行为
    ServiceExternalTrafficPolicyTypeLocal ServiceExternalTrafficPolicyType = "Local"

    // 该值定义了使用节全局节点的行为
    ServiceExternalTrafficPolicyTypeCluster ServiceExternalTrafficPolicyType = "Cluster"
)

type SessionAffinityConfig struct {
    // 针对客户端IP的配置信息
    ClientIP *ClientIPConfig `json:"clientIP,omitempty"`
}

type ClientIPConfig struct {
    // 超时时间定义,单位秒,值必须在0~86400之间
    TimeoutSeconds *int32 `json:"timeoutSeconds,omitempty"`
}

type IPFamily string
const (
    // IPv4Protocol IPv4协议
    IPv4Protocol IPFamily = "IPv4"
    // IPv6Protocol IPv6协议
    IPv6Protocol IPFamily = "IPv6"
    // 服务最多支持的拓扑域个数
    MaxServiceTopologyKeys = 16
)
复制代码

基本用法

以此Deployment配置为基础,进行Service的测试

apiVersion: apps/v1
kind: Deployment
metadata:
 name: nginx
spec:
 replicas: 2
 selector:
 matchLabels:
 app: nginx
 template:
 metadata:
 labels:
 app: nginx
 spec:
 containers:
 - name: nginx
 image: nginx
 ports:
 - name: http
 containerPort: 80
---
apiVersion: v1
kind: Service
metadata:
 name: nginx
spec:
 ports:
 - name: web-8080
 port: 8080
 targetPort: http
 selector:
 app: nginx
复制代码

建立该Service,再建立一个busybox执行 wget nginx:8080 进行验证

上述配置建立了一个名称为nginx的Service对象,该对象对外暴露了8080端口。Service会将请求代理到使用具备标签app=nginx的Pod的80端口上。

服务的默认协议是tcp,除此以外也支持udp和sctp。

因为许多服务须要公开多个端口,所以在服务对象上支持多个端口定义。每一个端口定义的协议能够不一样。

须要注意的是 若是配置的是多端口Service,那么配置端口的时候须要配置每一个端口的name属性,单端口则不须要

$ kubectl run -it --rm --generator=run-pod/v1 busybox --image=busybox /bin/sh
If you don't see a command prompt, try pressing enter. / # wget nginx:8080 Connecting to nginx:8080 (10.96.100.16:8080) saving to 'index.html' index.html 100% |*******************************| 612 0:00:00 ETA 'index.html' saved 复制代码
相关文章
相关标签/搜索