(七)Kubernetes Service资源

By | 2019年11月29日
目录
[隐藏]

Service概述

为什么要使用Service

Kubernetes Pod是平凡的,由Deployment等控制器管理的Pod对象都是有生命周期的,它们会被创建,也会意外挂掉。虽然它们可以由控制器自动重建或者滚动更新,但是重建或更新之后的Pod对象的IP地址等都会发生新的变化。这样就会导致一个问题,如果一组Pod(称为backend)为其它Pod(称为 frontend)提供服务,那么那些frontend该如何发现,并连接到这组Pod中的哪些backend呢? 这时候就用到了:Service

示例说明为什么要使用Service

如下图所示,当Nginx Pod作为客户端访问Tomcat Pod中的应用时,IP的变动或应用规模的缩减会导致客户端访问错误。而Pod规模的扩容又会使得客户端无法有效的使用新增的Pod对象,从而影响达成规模扩展之目的。为此,Kubernetes特地设计了Service资源来解决此类问题。

Service实现原理

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

Service对象的IP地址也称为Cluster IP,它位于Kubernetes集群配置指定专用IP地址的范围之内,是一种虚拟IP地址,它在Service对象创建后既保持不变,并且能够被同一集群中的Pod资源所访问。Service端口用于接收客户端请求并将其转发至其后端的Pod中的相应端口之上,因此,这种代理机构也称为“端口代理”(port proxy)或四层代理,工作于TCP/IP协议栈的传输层。

Service资源会通过API Server持续监视着(watch)标签选择器匹配到的后端Pod对象,并实时跟踪各对象的变动,例如,IP地址变动、对象增加或减少等。Service并不直接链接至Pod对象,它们之间还有一个中间层——Endpoints资源对象,它是一个由IP地址和端口组成的列表,这些IP地址和端口则来自由Service的标签选择器匹配到的Pod资源。当创建service对象时,其关联的Endpoints对象会自动创建。

虚拟IP和服务代理

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

ipvs是借助于Netfilter实现的网络请求报文调度框架,支持rrwrrlcwlcshsednq等十余种调度算法,用户空间的命令行工具是ipvsadm,用于管理工作与ipvs之上的调度规则。

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

kube-proxy将请求代理至相应端点的方式有三种:userspace(用户空间)iptablesipvs

userspace代理模式

userspaceLinux操作系统的用户空间。这种模式下,kube-proxy负责跟踪API ServerServiceEndpoints对象的变动(创建或移除),并据此调整Service资源的定义。对于每个Service对象,它会随机打开一个本地端口(运行于用户控件的kube-proxy进程负责监听),任何到达此端口的连接请求都将代理至当前Service资源后端的各Pod对象上,至于会挑选中哪个Pod对象则取决于当前Service资源的调度方式(通过ServiceSessionAffinity来确定),默认的调度算法是轮循(round-robin)。

其代理的过程是:请求到达service后,其被转发至内核空间,经由套接字送往用户空间的kube-proxy,而后再由它送回内核空间,并调度至后端Pod。其传输效率太低,在1.1版本前是默认的转发策略。

iptables代理模式

iptables代理模式中,kube-proxy负责跟踪API ServerServiceEndpoints对象的变动(创建或移除),并据此作出Service资源定义的变动。同时,对于每个Service对象,它都会创建iptables规则直接捕获到达Cluster IP(虚拟IP)和Port的流量,并将其重定向至当前Service的后端。对于每个Endpoints对象,Service资源会为其创建iptables规则并关联至挑选的后端Pod资源,默认的调度算法是随机调度(random)。实现基于客户端IP的会话亲和性(来自同一个用户的请求始终调度到后端固定的一个Pod),可将service.spec.sessionAffinity的值设置为“ClientIP”(默认值为“None”)。

其代理过程是:请求到达service后,其请求被相关service上的iptables规则进行调度和目标地址转换(DNAT)后再转发至集群内的Pod对象之上。

相对userspace模式来说,iptables模式无须将流量在用户空间和内核空间来回切换,因而更加高效和可靠。其缺点是iptables代理模型不会在被挑中的Pod资源无响应时自动进行重定向;而userspace模式则可以。

ipvs代理模式

kube-proxy跟踪API ServerServiceEndpoints对象的变动,据此来调用netlink接口创建ipvs规则,并确保与API Server中的变动保持同步,其请求流量的调度功能由ipvs实现,其余的功能由iptables实现。ipvs支持众多调度算法,如rrlcdhshsednq等。

Service资源的基础应用

创建Service对象的常用方法有两种,一是直接使用命令“kubectl expose”命令,二是使用资源清单配置文件。定义Service资源清单文件时,spec的两个较为常用的内嵌字段分别是selectorport,分别用于定义使用的标签选择器和要暴露的端口。

一、命令方式定义

1)首先创建一组pod资源

[root@k8s-master ~]# kubectl run nginx --image=nginx:1.12 --replicas=3    #创建pod资源指定副本数量为3个
[root@k8s-master ~]# kubectl get pods -o wide
NAME                     READY   STATUS    RESTARTS   AGE     IP            NODE        NOMINATED NODE   READINESS GATES
nginx-67685f79b5-688s7   1/1     Running   0          5s   10.244.2.61   k8s-node2   <none>           <none>
nginx-67685f79b5-gpc2f   1/1     Running   0          5s   10.244.1.63   k8s-node1   <none>           <none>
nginx-67685f79b5-grlrz   1/1     Running   0          5s   10.244.2.60   k8s-node2   <none>           <none>
[root@k8s-master ~]# kubectl get deployment    #查看deployment控制器资源
NAME    READY   UP-TO-DATE   AVAILABLE   AGE
nginx   3/3     3            3           35s

2)为其创建对应的service资源

#下面这条命令表示为deployment控制器资源nginx创建一个service对象,并取名为nginx、端口为80、pod内暴露端口80、协议为TCP协议。
[root@k8s-master ~]# kubectl expose deployment nginx --name=nginx --port=80 --target-port=80 --protocol=TCP
service/nginx exposed
[root@k8s-master ~]# kubectl get service    #查看创建的service资源
NAME         TYPE        CLUSTER-IP       EXTERNAL-IP   PORT(S)   AGE
kubernetes   ClusterIP   10.96.0.1        <none>        443/TCP   27d
nginx        ClusterIP   10.104.116.156   <none>        80/TCP    9s

3)查看生成的endpoints对应关系

[root@k8s-master ~]# kubectl get endpoints
NAME         ENDPOINTS                                      AGE
kubernetes   192.168.1.31:6443                              27d
nginx        10.244.1.63:80,10.244.2.60:80,10.244.2.61:80   29s

二、资源清单定义

1)编写资源清单文件(这里先定义一个Deployment控制器资源对象,然后定义Service进行关联)。注:同一个文件编写多个资源对象时,通过—进行分割。

[root@k8s-master ~]# vim manfests/service-demo.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: service-deploy
  namespace: default
spec:
  replicas: 3
  selector:
    matchLabels:
      app: service-deploy-demo
  template:
    metadata:
      name: svc-deploy
      labels:
        app: service-deploy-demo
    spec:
      containers:
      - name: svc-pod
        image: ikubernetes/myapp:v1
        imagePullPolicy: IfNotPresent
        ports: 
        - name: http
          containerPort: 80

---
#定义service
apiVersion: v1
kind: Service
metadata:
  name: service-demo    #service名称
spec:
  selector:    #用于匹配后端的Pod资源对象,需和上面定义pod的标签一致
    app: service-deploy-demo
  ports:
  - port: 80    #service端口号
    targetPort: 80    #后端Pod端口号
    protocol: TCP    #使用的协议

2)创建并查看

[root@k8s-master ~]# kubectl apply -f manfests/service-demo.yaml    #创建资源对象
deployment.apps/service-deploy created
service/service-demo created
[root@k8s-master ~]# kubectl get svc    #查看service资源对象,"kubectl get svc"等于"kubectl get service"
NAME           TYPE        CLUSTER-IP       EXTERNAL-IP   PORT(S)   AGE
kubernetes     ClusterIP   10.96.0.1        <none>        443/TCP   27d
nginx          ClusterIP   10.104.116.156   <none>        80/TCP    80m
service-demo   ClusterIP   10.98.31.157     <none>        80/TCP    7s
[root@k8s-master ~]# kubectl get pods -o wide -l app=service-deploy-demo    #查看pod资源对象
NAME                              READY   STATUS    RESTARTS   AGE     IP            NODE        NOMINATED NODE   READINESS GATES
service-deploy-66548cc57f-982cd   1/1     Running   0          15s   10.244.2.63   k8s-node2   <none>           <none>
service-deploy-66548cc57f-blnvg   1/1     Running   0          15s   10.244.1.67   k8s-node1   <none>           <none>
service-deploy-66548cc57f-vcmxb   1/1     Running   0          15s   10.244.2.62   k8s-node2   <none>           <none>
[root@k8s-master ~]# kubectl get endpoints service-demo    查看生成的endpoints对应关系
NAME           ENDPOINTS                                      AGE
service-demo   10.244.1.67:80,10.244.2.62:80,10.244.2.63:80   43s

3)节点访问测试(这里使用创建一个新的pod资源模拟客户端进行访问)

Service资源的默认类型为ClusterIP,仅能接收kubernetes集群节点访问、或集群内部的pod对象中的客户端程序访问。

[root@k8s-master ~]# kubectl run busybox --image=busybox --rm -it -- /bin/sh    #使用busybox创建一个临时pod客户端
/ # wget -O - -q http://10.98.31.157/    #访问上面创建的service对象的Cluster IP
Hello MyApp | Version: v1 | <a href="hostname.html">Pod Name</a>
/ # for i in 1 2 3 4; do wget -O - -q http://10.98.31.157/hostname.html; done    #循环访问测试站点下的hostname.html页面,可以看出是轮循的分配给后端的pod资源。
service-deploy-66548cc57f-982cd
service-deploy-66548cc57f-blnvg
service-deploy-66548cc57f-982cd
service-deploy-66548cc57f-982cd

#说明:myapp容器中的“/hostname.html"页面能够输出当前容器的主机名。

Service会话粘性

Service资源支持Session affinity(粘性会话或会话粘性)机制,能够将来自同一个客户端的请求始终转发至同一个后端的Pod对象。这意味着会影响调度算法的流量分发功能,进而降低其负载均衡的效果。所以,当客户端访问pod中的应用程序时,如果有基于客户端身份保存某些私有信息,并基于这些私有信息追踪用户的活动等一类的需求时,就可以启用session affinity机制。

Session affinity的效果仅在一段时间期限内生效,默认值为10800秒,超出此时长之后,客户端的再次访问会被调度算法重新调度。Service资源的Session affinity机制仅能基于客户端的IP地址识别客户端身份,把经由同一个NAT服务器进行源地址转换的所有客户端识别为同一个客户端,便导致调度效果不佳,所以,这种方法并不常用。

Service资源通过service.spec.sessionAffinityservice.spec.sessionAffinityConfig两个字段配置粘性会话。sessionAffinity字段用于定义要使用的粘性会话的类型,仅支持使用“None”“ClientIp”两种属性值。

  • None:不使用sessionAffinity,默认值。

  • ClientIP:基于客户端IP地址识别客户端身份,把来自同一个源IP地址的请求始终调度至同一个Pod对象。

示例

这里将上面创建的service-demo资源对象进行修改

[root@k8s-master ~]# vim manfests/service-demo.yaml
......
spec:
  selector:
    app: service-deploy-demo
  ports:
  - port: 80
    targetPort: 80
    protocol: TCP
  sessionAffinity: ClientIP    #指定使用ClientIP
  sessionAffinityConfig:
    clientIP:
      timeoutSeconds: 10    #配置session超时时间,这里为了看效果设置的比较短
[root@k8s-master ~]# kubectl apply -f manfests/service-demo.yaml 
deployment.apps/service-deploy unchanged

#同样使用pod客户端访问测试
/ # for i in 1 2 3 4; do wget -O - -q http://10.98.31.157/hostname.html; done
service-deploy-66548cc57f-blnvg
service-deploy-66548cc57f-blnvg
service-deploy-66548cc57f-blnvg
service-deploy-66548cc57f-blnvg
#等待10秒过后再次访问
/ # for i in 1 2 3 4; do wget -O - -q http://10.98.31.157/hostname.html; done
service-deploy-66548cc57f-vcmxb
service-deploy-66548cc57f-vcmxb
service-deploy-66548cc57f-vcmxb
service-deploy-66548cc57f-vcmxb

Service类型

ServiceIP地址只能够在集群内部可访问,对一些应用(如frontend)的某些部分,可能希望通过外部(kubernetes集群外部)IP地址暴露Service,这时候就需要使用到NodePortkubernetes ServiceTypes支持四种类型:ClusterIPNodePortLoadBalancerExternalName,其默认是Cluster IP类型。

  • ClusterIP:通过集群内部IP地址暴露服务,此地址仅在集群内部可进行通行,无法被集群外部的客户端访问。

  • NodePort:通过每个Node上的IP和静态端口(NodePort)暴露服务,会自动为Service分配集群IP地址,并将此作为NodePort的路有目标。通过请求<NodePort>:<NodePort> --> <ClusterIP>:<ClusterPort> --> <PodIP>:<ContainerPort>访问到一个NodePort服务。

  • LoadBalancer:构建在NodePort之上,并创建一个外部负载均衡器,路由到ClusterIP。因此LoadBalancer一样具有NodePortClusterIP

  • EXternalName:通过返回CNAME和它的值,可以将服务映射到externalName字段的内容。换言之,此种类型并非定义由Kubernetes集群提供的服务,而是把集群外部的某服务以DNS CNAME记录的方式映射到集群内,从而让集群内的Pod资源能够访问外部的Service的一种实现方式。这种类型的Service没有ClusterIPNodePort,也没有标签选择器用于选择Pod资源,因此也不会有Endpoints存在。

ClusterIP类型的Service示例

1)编写配置清单文件(这里使用redis作为示例);先创建一个deployment,启动redis pod;再使用service绑定这个deployment下的pod资源。

[root@k8s-master ~]# vim manfests/redis-svc.yaml    #编写yaml格式的清单文件
apiVersion: apps/v1
kind: Deployment
metadata:
  name: redis-deploy
  namespace: default
spec:
  replicas: 2
  selector:
    matchLabels:
      app: redis
  template:
    metadata:
      labels:
        app: redis
    spec:
      containers:
      - name: redis-pod
        image: redis
        ports:
        - name: redis
          containerPort: 6379
---
apiVersion: v1
kind: Service
metadata:
  name: redis-svc    #service对象名
spec:
  type: ClusterIP    #这里指定使用ClusterIP,默认也是ClusterIP,这里可有可无
  selector:
    app: redis    #匹配上面定义的pod资源
  ports:
  - port: 6379    #service端口
    targetPort: 6379    #后端pod端口
    protocol: TCP    #协议
    
[root@k8s-master ~]# kubectl apply -f manfests/redis-svc.yaml     #创建资源对象
deployment.apps/redis-deploy created
service/redis-svc created

2)查看创建的资源对象

[root@k8s-master ~]# kubectl get svc    #查看service资源
NAME           TYPE        CLUSTER-IP       EXTERNAL-IP   PORT(S)    AGE
kubernetes     ClusterIP   10.96.0.1        <none>        443/TCP    27d
nginx          ClusterIP   10.104.116.156   <none>        80/TCP     17h
redis-svc      ClusterIP   10.102.44.127    <none>        6379/TCP   8s
service-demo   ClusterIP   10.98.31.157     <none>        80/TCP     16h

[root@k8s-master ~]# kubectl get pods -l app=redis -o wide     #查看标签app=redis的pod资源
NAME                            READY   STATUS    RESTARTS   AGE   IP            NODE        NOMINATED NODE   READINESS GATES
redis-deploy-6559cc4c4c-5v7kx   1/1     Running   0          33s   10.244.2.65   k8s-node2   <none>           <none>
redis-deploy-6559cc4c4c-npdtf   1/1     Running   0          33s   10.244.1.69   k8s-node1   <none>           <none>

[root@k8s-master ~]# kubectl describe svc redis-svc    #查看redis-svc资源对象详细信息
Name:              redis-svc
Namespace:         default
Labels:            <none>
Annotations:       kubectl.kubernetes.io/last-applied-configuration:
                     {"apiVersion":"v1","kind":"Service","metadata":{"annotations":{},"name":"redis-svc","namespace":"default"},"spec":{"ports":[{"port":6379,"...
Selector:          app=redis
Type:              ClusterIP
IP:                10.102.44.127
Port:              <unset>  6379/TCP
TargetPort:        6379/TCP
Endpoints:         10.244.1.69:6379,10.244.2.65:6379    #可以看出这里已经和上面的pod资源绑定
Session Affinity:  None
Events:            <none>

3)集群内部进行测试

#(1)集群内部的节点上面测试
[root@k8s-master ~]# redis-cli -h 10.102.44.127
10.102.44.127:6379> ping
PON

#(2)在后端pod上面进行测试
[root@k8s-master ~]# kubectl exec redis-deploy-6559cc4c4c-5v7kx -it -- /bin/sh
# redis-cli -h 10.102.44.127
10.102.44.127:6379> ping
PONG

NodePort类型的Service示例

NodePort即节点Port,通常在安装部署Kubernetes集群系统时会预留一个端口范围用于NodePort,默认为30000~32767之间的端口。定义NodePort类型的Service资源时,需要使用.spec.type明确指定类型为NodePort

1)编写配置清单文件(这里使用nginx作为示例);先创建一个deployment,启动nginx pod;再使用service绑定这个deployment下的pod资源。

[root@k8s-master ~]# vim manfests/nginx-svc.yaml    #编写yaml格式的清单文件
apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx-deploy
  namespace: default
spec:
  replicas: 2
  selector:
    matchLabels:
      app: nginx 
  template:
    metadata:
      labels:
        app: nginx 
    spec:
      containers:
      - name: nginx-pod
        image: nginx:1.12 
        ports:
        - name: nginx 
          containerPort: 6379
---
apiVersion: v1
kind: Service
metadata:
  name: nginx-svc    #service对象名
spec:
  type: NodePort    #这里指定使用ClusterIP,默认也是ClusterIP,这里可有可无
  selector:
    app: nginx    #匹配上面定义的pod资源
  ports:
  - port: 80    #service端口
    targetPort: 80    #后端pod端口
    nodePort: 30080    #节点端口
    protocol: TCP    #协议
    
[root@k8s-master ~]# kubectl apply -f manfests/nginx-svc.yaml    #创建资源对象
deployment.apps/nginx-deploy created
service/nginx-svc created

2)查看创建的资源对象

[root@k8s-master ~]# kubectl get svc    #查看service资源
NAME           TYPE        CLUSTER-IP      EXTERNAL-IP   PORT(S)        AGE
kubernetes     ClusterIP   10.96.0.1       <none>        443/TCP        27d
nginx-svc      NodePort    10.105.21.137   <none>        80:30080/TCP   4s
redis-svc      ClusterIP   10.102.44.127   <none>        6379/TCP       55m
service-demo   ClusterIP   10.98.31.157    <none>        80/TCP         16h

[root@k8s-master ~]# kubectl get pods -l app=nginx -o wide    #查看标签app=nginx的pod资源
NAME                           READY   STATUS    RESTARTS   AGE   IP            NODE        NOMINATED NODE   READINESS GATES
nginx-deploy-b6f876447-nlv6h   1/1     Running   0          33s   10.244.1.71   k8s-node1   <none>           <none>
nginx-deploy-b6f876447-xmn2t   1/1     Running   0          33s   10.244.2.66   k8s-node2   <none>           <none>

[root@k8s-master ~]# kubectl describe svc nginx-svc    #查看nginx-svc资源对象详细信息
Name:                     nginx-svc
Namespace:                default
Labels:                   <none>
Annotations:              kubectl.kubernetes.io/last-applied-configuration:
                            {"apiVersion":"v1","kind":"Service","metadata":{"annotations":{},"name":"nginx-svc","namespace":"default"},"spec":{"ports":[{"nodePort":30...
Selector:                 app=nginx
Type:                     NodePort
IP:                       10.105.21.137
Port:                     <unset>  80/TCP
TargetPort:               80/TCP
NodePort:                 <unset>  30080/TCP    #这里可以看到多了NodePort且端口为30080
Endpoints:                10.244.1.71:80,10.244.2.66:80
Session Affinity:         None
External Traffic Policy:  Cluster
Events:                   <none>

3)集群外部进行测试

[root@courtoap ~]# curl 192.168.1.31:30080    #访问集群master节点的30080端口
<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
<style>
    body {
        width: 35em;
        margin: 0 auto;
        font-family: Tahoma, Verdana, Arial, sans-serif;
    }
</style>
[root@courtoap ~]# curl 192.168.1.32:30080    #访问集群node节点的30080端口
<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
<style>
    body {
        width: 35em;
        margin: 0 auto;
        font-family: Tahoma, Verdana, Arial, sans-serif;
    }
</style>

通过上面的测试可以看到通过NodePort的方式实现了从集群外部端口进行访问,实践中并不建议自定义使用的节点端口,因为容易产生冲突。建议让其自动生成即可。

Headless类型的Service资源

Service对象隐藏了各Pod资源,并负责将客户端请求流量调度至该组Pod对象之上,但也可能存在客户端直接访问Service资源后端的所有Pod资源,这时就应该向客户端暴露每个Pod资源的IP地址,而不是中间层Service对象的ClusterIP,这种类型的Service资源便称为Headless Service(无头服务)。

Headless Service对象没有ClusterIP,因此便没有相关负载均衡或代理问题,其如何为此类Service配置IP地址,其取决于标签选择器的定义。

  • 具有标签选择器:端点控制器(Endpoints Controller)会在API中为其创建Endpoints记录,并将ClusterDNS服务中的A记录直接解析到此Service后端的各Pod对象的IP地址上。

  • 没有标签选择器:端点控制器(Endpoints Controller)不会再API中为其创建Endpoints记录,ClusterDNS的配置分为两种情形,对ExternalName类型的服务创建CNAME记录,对其他三种类型来说,为那些与当前Service共享名称的所有Endpoints对象创建一条记录。

Headless类型的Service示例

配置Service资源配置清单时,只需要将ClusterIP字段的值设置为“None”即为其定义为Headless类型。

1)编写配置清单文件(这里使用apache作为示例);先创建一个deployment,启动apache pod;再使用service绑定这个deployment下的pod资源。

[root@k8s-master ~]# vim manfests/httpd-svc-headless.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: httpd-deploy
  namespace: default
spec:
  replicas: 3 
  selector:
    matchLabels:
      app: httpd 
  template:
    metadata:
      labels:
        app: httpd
    spec:
      containers:
      - name: httpd-pod
        image: httpd
        ports:
        - name: httpd
          containerPort: 80
---
apiVersion: v1
kind: Service
metadata:
  name: httpd-svc    #service对象名
spec:
  clusterIP: None    #将ClusterIP字段设置为None即表示为headless类型的service资源对象
  selector:
    app: httpd    #匹配上面定义的pod资源
  ports:
  - port: 80    #service端口
    targetPort: 80    #后端pod端口
    protocol: TCP    #协议
    
[root@k8s-master ~]# kubectl apply -f manfests/httpd-svc-headless.yaml 
deployment.apps/httpd-deploy created
service/httpd-svc created

2)查看创建的资源对象

[root@k8s-master ~]# kubectl get svc    #查看service资源
NAME           TYPE        CLUSTER-IP      EXTERNAL-IP   PORT(S)        AGE
httpd-svc      ClusterIP   None            <none>        80/TCP         4s
kubernetes     ClusterIP   10.96.0.1       <none>        443/TCP        27d
nginx-svc      NodePort    10.105.21.137   <none>        80:30080/TCP   112m
redis-svc      ClusterIP   10.102.44.127   <none>        6379/TCP       168m
service-demo   ClusterIP   10.98.31.157    <none>        80/TCP         18h

[root@k8s-master ~]# kubectl get pods -l app=httpd -o wide     #查看标签app=httpd的pod资源
NAME                            READY   STATUS    RESTARTS   AGE   IP            NODE        NOMINATED NODE   READINESS GATES
httpd-deploy-5494485b74-4vx64   1/1     Running   0          27s   10.244.2.72   k8s-node2   <none>           <none>
httpd-deploy-5494485b74-j6hwm   1/1     Running   0          27s   10.244.2.71   k8s-node2   <none>           <none>
httpd-deploy-5494485b74-jn48q   1/1     Running   0          27s   10.244.1.74   k8s-node1   <none>           <none>

[root@k8s-master ~]# kubectl describe svc/httpd-svc    #查看httpd-svc资源对象详细信息
Name:              httpd-svc
Namespace:         default
Labels:            <none>
Annotations:       kubectl.kubernetes.io/last-applied-configuration:
                     {"apiVersion":"v1","kind":"Service","metadata":{"annotations":{},"name":"httpd-svc","namespace":"default"},"spec":{"clusterIP":"None","por...
Selector:          app=httpd
Type:              ClusterIP
IP:                None
Port:              <unset>  80/TCP
TargetPort:        80/TCP
Endpoints:         10.244.1.74:80,10.244.2.71:80,10.244.2.72:80
Session Affinity:  None
Events:            <none>

3)测试资源发现

Headless Service工作特性可知,它记录于ClusterDNSA记录的相关解析结果是后端Pod资源的IP地址。意味着客户端通过Service资源的名称发现的是各Pod资源。

#(1)通过创建一个专用的测试Pod资源对象,而后通过其交互式接口进行测试
[root@k8s-master ~]# kubectl run cirror-$RANDOM --rm -it --image=cirros -- /bin/sh
/ # nslookup httpd-svc
Server:    10.96.0.10
Address 1: 10.96.0.10 kube-dns.kube-system.svc.cluster.local

Name:      httpd-svc
Address 1: 10.244.2.71 10-244-2-71.httpd-svc.default.svc.cluster.local
Address 2: 10.244.1.74 10-244-1-74.httpd-svc.default.svc.cluster.local
Address 3: 10.244.2.72 10-244-2-72.httpd-svc.default.svc.cluster.local

#(2)直接在kubernetes集群上解析
[root@k8s-master ~]# dig -t A  httpd-svc.default.svc.cluster.local. @10.96.0.10
......
;; ANSWER SECTION:
httpd-svc.default.svc.cluster.local. 26    IN A    10.244.2.72
httpd-svc.default.svc.cluster.local. 26    IN A    10.244.2.71
httpd-svc.default.svc.cluster.local. 26    IN A    10.244.1.74
......

发表评论

您的电子邮箱地址不会被公开。 必填项已用*标注