Kubernetes——Service资源

Service资源

一、Service 资源概述

  Service 是 Kubernetes 的核心资源类型之一,通常可看作微服务的一种实现。事实上它是一种抽象:通过规则定义出由多个 Pod 对象组合而成的逻辑集合,以及访问这组 Pod 的策略。

  Service 关联 Pod 资源的规则要借助于标签选择器来完成。

  比如,由 Deployment 等控制器管理的 Pod 对象中断后,会由新建的资源对象所取代,而扩缩容后的应用则会带来 Pod 对象群体的变动,随之变化的还有 Pod 的 IP 地址访问接口等,这也是编排系统之上的应用程序必然要面临的问题。

  Service 资源基于标签选择器将一组 Pod 定义成一个逻辑组合,并通过自己的 IP 地址和端口调度代理请求至组内的 Pod 对象之上,如下图,它向客户端隐藏了真实的、处理用户请求的 Pod 资源,使得客户端的请求看上去就像是由 Service 直接处理并进行响应的一样:

  Servie 对象的 IP 地址也称为 Cluster IP ,它位于为 Kubernetes 集群配置指定专用 IP 地址的范围之内,而且是一种虚拟 IP 地址,它在 Service 对象创建后即保持不变,并且能够被同一集群中的 Pod 资源所反问。

  Service 端口用于接收客户端请求并将其转发至其后端的 Pod 中应用的相应端口之上,因此这种代理机制也被称为 "端口代理"(prot proxy)或 四层代理,它工作与 TCP/IP 协议栈的传输层。

  Service 资源会通过 API Server 持续监视着(watch)标签选择器匹配到的后端 Pod 对象,并实时跟踪各对象的变动,例如,IP地址变动、对象增加或减少等。不过,需要特别说明的是,Service 并不直接链接至 Pod 对象,它们之间还有一个中间层 —— Endpoints 资源对象,它是一个由 IP 地址和端口组成的列表,这些 IP 地址和端口则来自于由 Service 的标签选择器匹配到的 Pod 资源。这也是很多场景种会使用 "Service 的后端端点"(Endpoints)这一术语的原因。默认情况下,创建 Service 资源对象时,其关联的 Endpoints 对象会自动创建。

二、虚拟IP和服务代理

  简单来讲,一个 Service 对象就是工作节点上的一些 iptables 或 ipvs 规则,用于将到达 Service 对象 IP 地址的流量调度转发至相应的 Endpoints 对象指向的 IP 地址和端口之上。工作于每个工作节点的 kube-proxy 组件通过 API Server 持续监控着各 Service 及与其关联的 Pod 对象,并将其创建或变动实时反映至当前工作节点上相应的 iptables 或 ipvs 规则上。客户端、Service 及其 Pod 对象的关系如下图:

  Service IP 事实上是用于生成 iptables 或 ipvs 规则时使用的 IP 地址,它仅用于实现 Kubernetes 集群网络的内部通信,并且仅能够将规则中定义的转发服务的请求作为目标地址予以响应,这也是它被称为虚拟 IP 的原因之一。

  kube-proxy 将请求代理至相应端点的方法有三种:userspace(用户空间)、iptables 和 ipvs。userspace 已经淘汰,iptables 不常用,这里不描述,只描述 iptables 代理模型。

  iptables 代理模型:

Kubernetes 自 1.9-alpha 版本起引入了 ipvs 代理模型,且自 1.11 版本起成为默认设置。此模型中,kube-proxy 跟踪 API Server 上的 Service 和 Endpoints 对象的变动,据此来调动 netlink 接口创建 ipvs 规则,并确保与 API Server 中的变动保持同步。它与 iptables 规则的不同之处仅在于其请求流量的调度功能由 ipvs 实现,余下的其他功能仍由 iptables 完成。

  类似于 iptables 模型,ipvs 构建与 netfilter 的钩子函数之上,但它使用 hash 表作为底层数据结构并工作于内核空间,因此具有流量转发速度快、规则同步性能好的特性。另外,ipvs 支持众多调度算法,例如 rr、lc、dh、sh、sed和 nq 等。

 三、创建 Servcie 资源

  Service 资源本身并不提供任何服务,真正处理并响应客户端请求的是后端的 Pod 资源。

  创建 Service 对象的常用方法有两种:

    • 直接使用 "kubectl expose" 命令。
    • 使用资源配置文件。

  Service 资源对象配置定义文件如下:

[root@mh-k8s-master-prd-243-24 ~]# kubectl explain service
KIND:     Service
VERSION:  v1

DESCRIPTION:
     Service is a named abstraction of software service (for example, mysql)
     consisting of local port (for example 3306) that the proxy listens on, and
     the selector that determines which pods will answer requests sent through
     the proxy.

FIELDS:
   apiVersion	<string>
     APIVersion defines the versioned schema of this representation of an
     object. Servers should convert recognized schemas to the latest internal
     value, and may reject unrecognized values. More info:
     https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources

   kind	<string>
     Kind is a string value representing the REST resource this object
     represents. Servers may infer this from the endpoint the client submits
     requests to. Cannot be updated. In CamelCase. More info:
     https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds

   metadata	<Object>
     Standard object's metadata. More info:
     https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#metadata

   spec	<Object>
     Spec defines the behavior of a service.
     https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#spec-and-status

   status	<Object>
     Most recently observed status of the service. Populated by the system.
     Read-only. More info:
     https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#spec-and-status

[root@mh-k8s-master-prd-243-24 ~]# 

  service.spec 嵌套字段定义如下:

[root@mh-k8s-master-prd-243-24 ~]# kubectl explain service.spec
KIND:     Service
VERSION:  v1

RESOURCE: spec <Object>

DESCRIPTION:
     Spec defines the behavior of a service.
     https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#spec-and-status

     ServiceSpec describes the attributes that a user creates on a service.

FIELDS:
   clusterIP    <string>
     clusterIP is the IP address of the service and is usually assigned randomly
     by the master. If an address is specified manually and is not in use by
     others, it will be allocated to the service; otherwise, creation of the
     service will fail. This field can not be changed through updates. Valid
     values are "None", empty string (""), or a valid IP address. "None" can be
     specified for headless services when proxying is not required. Only applies
     to types ClusterIP, NodePort, and LoadBalancer. Ignored if type is
     ExternalName. More info:
     https://kubernetes.io/docs/concepts/services-networking/service/#virtual-ips-and-service-proxies

   externalIPs    <[]string>
     externalIPs is a list of IP addresses for which nodes in the cluster will
     also accept traffic for this service. These IPs are not managed by
     Kubernetes. The user is responsible for ensuring that traffic arrives at a
     node with this IP. A common example is external load-balancers that are not
     part of the Kubernetes system.

   externalName    <string>
     externalName is the external reference that kubedns or equivalent will
     return as a CNAME record for this service. No proxying will be involved.
     Must be a valid RFC-1123 hostname (https://tools.ietf.org/html/rfc1123) and
     requires Type to be ExternalName.

   externalTrafficPolicy    <string>
     externalTrafficPolicy denotes if this Service desires to route external
     traffic to node-local or cluster-wide endpoints. "Local" preserves the
     client source IP and avoids a second hop for LoadBalancer and Nodeport type
     services, but risks potentially imbalanced traffic spreading. "Cluster"
     obscures the client source IP and may cause a second hop to another node,
     but should have good overall load-spreading.

   healthCheckNodePort    <integer>
     healthCheckNodePort specifies the healthcheck nodePort for the service. If
     not specified, HealthCheckNodePort is created by the service api backend
     with the allocated nodePort. Will use user-specified nodePort value if
     specified by the client. Only effects when Type is set to LoadBalancer and
     ExternalTrafficPolicy is set to Local.

   ipFamily    <string>
     ipFamily specifies whether this Service has a preference for a particular
     IP family (e.g. IPv4 vs. IPv6). If a specific IP family is requested, the
     clusterIP field will be allocated from that family, if it is available in
     the cluster. If no IP family is requested, the cluster's primary IP family
     will be used. Other IP fields (loadBalancerIP, loadBalancerSourceRanges,
     externalIPs) and controllers which allocate external load-balancers should
     use the same IP family. Endpoints for this Service will be of this family.
     This field is immutable after creation. Assigning a ServiceIPFamily not
     available in the cluster (e.g. IPv6 in IPv4 only cluster) is an error
     condition and will fail during clusterIP assignment.

   loadBalancerIP    <string>
     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.

   loadBalancerSourceRanges    <[]string>
     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/

   ports    <[]Object>
     The list of ports that are exposed by this service. More info:
     https://kubernetes.io/docs/concepts/services-networking/service/#virtual-ips-and-service-proxies

   publishNotReadyAddresses    <boolean>
     publishNotReadyAddresses, when set to true, indicates that DNS
     implementations must publish the notReadyAddresses of subsets for the
     Endpoints associated with the Service. The default value is false. The
     primary use case for setting this field is to use a StatefulSet's Headless
     Service to propagate SRV records for its Pods without respect to their
     readiness for purpose of peer discovery.

   selector    <map[string]string>
     Route service traffic to pods with label keys and values matching this
     selector. If empty or not present, the service is assumed to have an
     external process managing its endpoints, which Kubernetes will not modify.
     Only applies to types ClusterIP, NodePort, and LoadBalancer. Ignored if
     type is ExternalName. More info:
     https://kubernetes.io/docs/concepts/services-networking/service/

   sessionAffinity    <string>
     Supports "ClientIP" and "None". Used to maintain session affinity. Enable
     client IP based session affinity. Must be ClientIP or None. Defaults to
     None. More info:
     https://kubernetes.io/docs/concepts/services-networking/service/#virtual-ips-and-service-proxies

   sessionAffinityConfig    <Object>
     sessionAffinityConfig contains the configurations of session affinity.

   topologyKeys    <[]string>
     topologyKeys is a preference-order list of topology keys which
     implementations of services should use to preferentially sort endpoints
     when accessing this Service, it can not be used at the same time as
     externalTrafficPolicy=Local. Topology keys must be valid label keys and at
     most 16 keys may be specified. Endpoints are chosen based on the first
     topology key with available backends. If this field is specified and all
     entries have no backends that match the topology of the client, the service
     has no backends for that client and connections should fail. The special
     value "*" may be used to mean "any topology". This catch-all value, if
     used, only makes sense as the last value in the list. If this is not
     specified or empty, no topology constraints will be applied.

   type    <string>
     type determines how the Service is exposed. Defaults to ClusterIP. Valid
     options are ExternalName, ClusterIP, NodePort, and LoadBalancer.
     "ExternalName" maps to the specified externalName. "ClusterIP" allocates a
     cluster-internal IP address for load-balancing to endpoints. Endpoints are
     determined by the selector or if that is not specified, by manual
     construction of an Endpoints object. If clusterIP is "None", no virtual IP
     is allocated and the endpoints are published as a set of endpoints rather
     than a stable IP. "NodePort" builds on ClusterIP and allocates a port on
     every node which routes to the clusterIP. "LoadBalancer" builds on NodePort
     and creates an external load-balancer (if supported in the current cloud)
     which routes to the clusterIP. More info:
     https://kubernetes.io/docs/concepts/services-networking/service/#publishing-services-service-types

[root@mh-k8s-master-prd-243-24 ~]# 

  一个简单的配置清单文件 Service 资源示例如下:

kind: Service
apiVersion: v1
metadata:
  name: XXX-oms-view
  namespace: XXX-oms-view
  labels:
    XXX-env: prd
    XXX-org: XXX
spec:
  ports:
    - protocol: TCP
      port: 80
      targetPort: 80
      nodePort: 31527
  selector:
    app: XXX-oms-view
    XXX-env: prd
    XXX-org: XXX
  clusterIP: 10.233.37.76
  type: NodePort
  sessionAffinity: None
  externalTrafficPolicy: Cluster

  Servie 资源 name: XXX-oms-view 通过标签选择器关联至标签为 "app: XXX-oms-view" 的各 Pod 对象,它会自动创建名为 XXX-oms-view 的 Endpoints 资源对象,并自动配置一个 ClusterIP,暴露的端口由 port 字段进行制定,后端各 Pod 对象的端口则由 targetPort 给出,也可以使用同 port 字段的默认值。

 四、向Service对象请求服务

  Service 资源的默认类型为 ClusterIP,它仅能够接收来自集群中的 Pod 对象中的客户端程序的访问请求。

[root@mh-k8s-master-prd-243-24 ~]#  kubectl get svc -n kubesphere-system
NAME                    TYPE        CLUSTER-IP      EXTERNAL-IP   PORT(S)              AGE
ks-apiserver            ClusterIP   10.233.18.170   <none>        80/TCP               69d
ks-console              NodePort    10.233.29.142   <none>        80:30880/TCP         69d
ks-controller-manager   ClusterIP   10.233.48.67    <none>        443/TCP              69d
minio                   ClusterIP   10.233.61.26    <none>        9000/TCP             69d
openldap                ClusterIP   None            <none>        389/TCP              69d
redis                   ClusterIP   10.233.54.138   <none>        6379/TCP             69d
redis-ha                ClusterIP   None            <none>        6379/TCP,26379/TCP   69d
redis-ha-announce-0     ClusterIP   10.233.7.171    <none>        6379/TCP,26379/TCP   69d
redis-ha-announce-1     ClusterIP   10.233.57.0     <none>        6379/TCP,26379/TCP   69d
redis-ha-announce-2     ClusterIP   10.233.38.140   <none>        6379/TCP,26379/TCP   69d
[root@mh-k8s-master-prd-243-24 ~]# curl -I http://10.255.243.24:30880
HTTP/1.1 302 Found
Vary: Accept-Encoding
Location: /login
Content-Type: text/html; charset=utf-8
Content-Length: 43
Date: Mon, 20 Jun 2022 09:02:26 GMT
Connection: keep-alive
Keep-Alive: timeout=5

[root@mh-k8s-master-prd-243-24 ~]# 

五、Service会话粘性

  Service 资源还支持 Session affinity(粘性会话或会话粘性)机制,它能够将来自同一个客户端的请求始终转发至同一个后端的 Pod 对象,这意味着它会影响调度算法的流量分发功能,进而降低其负载均衡的效果。

  因此,当客户端访问 Pod 中的应用程序时,如果有基于客户端身份保存某些私有信息,并基于这些私有信息追踪用户的活动等一类的需求时,那么应该启动 session affinity 机制。

  Session affinity 的效果仅会在一定时间期限内生效,默认值为 10800秒,超出此时长之后,客户端的再次访问会被调度算法重新调度。另外,Service 资源的 Session affinity 机制仅能基于客户端 IP 地址识别客户端身份,它会把经由同一个 NAT 服务器进行源地址转换的所有客户端识别为同一个客户端,调度粒度粗糙且效果不佳,因此实践中并不推荐使用此种方法实现粘性会话。

[root@mh-k8s-master-prd-243-24 ~]# kubectl explain service.spec.sessionAffinity
KIND:     Service
VERSION:  v1

FIELD:    sessionAffinity <string>

DESCRIPTION:
     Supports "ClientIP" and "None". Used to maintain session affinity. Enable
     client IP based session affinity. Must be ClientIP or None. Defaults to
     None. More info:
     https://kubernetes.io/docs/concepts/services-networking/service/#virtual-ips-and-service-proxies
[root@mh-k8s-master-prd-243-24 ~]# 
[root@mh-k8s-master-prd-243-24 ~]# kubectl explain service.spec.sessionAffinityConfig
KIND:     Service
VERSION:  v1

RESOURCE: sessionAffinityConfig <Object>

DESCRIPTION:
     sessionAffinityConfig contains the configurations of session affinity.

     SessionAffinityConfig represents the configurations of session affinity.

FIELDS:
   clientIP	<Object>
     clientIP contains the configurations of Client IP based session affinity.

[root@mh-k8s-master-prd-243-24 ~]# 
posted @ 2022-06-20 16:04  左扬  阅读(245)  评论(0编辑  收藏  举报
levels of contents