目录

一、pod

1、pod标签

2、node节点选择器

3、节点亲和性

4、Pod常见的状态和重启策略

二、Service

1、Service简介

2、创建Service资源


一、pod

1、pod标签

1.1 标签的定义

• 标签其实就一对 key/value ,被关联到对象上(如Pod),可用来划分特定的对象(比如版本,服务类型等);

• 标签可以在创建一个对象的时候直接定义,也可以在后期随时修改;

• 每一个对象可以拥有多个标签,但是,key值必须是唯一的;

• 创建标签之后也可以方便我们对资源进行分组管理;

• 如果对pod打标签,之后就可以使用标签来查看、删除指定的pod;

• 在k8s中,大部分资源都可以打标签。

1.2 给pod资源打标签

#对已经存在的pod打标签
[root@hd1.com~]# kubectl label pods pod-first  release=v1
#查看标签是否打成功:
[root@hd1.com~]# kubectl get pods pod-first --show-labels
NAME         READY   STATUS    RESTARTS   AGE   LABELS
pod-first    1/1     Running   1          21h   release=v1, app=tomcat-pod-first

1.3 查看资源标签相关命令

• 查看所有pod资源的标签:

kubectl get pods --show-labels

• 查看指定pod具有的所有标签:

kubectl get pods pod名 --show-labels

• 列出标签key是release的pod,不显示标签:

kubectl get pods -l release

• 列出标签key是release、值是v1的pod,不显示标签:

kubectl get pods -l release=v1

• 列出标签key是release的所有pod,并打印对应的标签值:

kubectl get pods -L release

• 查看所有名称空间下的所有pod的标签:

kubectl get pods --all-namespaces --show-labels

   

• 查看key-value为release=v1的pod,且release独立显示一列

kubectl get pods -l release=v1 -L release

NAME        READY   STATUS    RESTARTS   AGE   RELEASE

pod-first     1/1           Running     0                  13h      v1

 

2、node节点选择器

2.1 基本介绍

        在创建pod资源的时候,pod会根据scheduler进行调度,那么默认会调度到随机的一个工作节点,若想pod调度到指定节点或者调度到一些具有相同特点的node节点,可以使用pod中的nodeName或者nodeSelector字段指定要调度到的node节点。

2.2 nodeName

        指定pod节点运行在哪个具体node上。

        在spec字段内,写法:nodeName: node节点名。

[root@hd1.com ~]# cat pod-node.yaml
apiVersion: v1
kind: Pod
metadata:
  name: demo-pod1
  namespace: default
  labels:
    app: myapp
    env: dev
spec:
  nodeName: hd2.com    #指定node节点
  containers:
  - name:  tomcat-pod-java
    ports:
    - containerPort: 8080
    image: tomcat:8.5-jre8-alpine
    imagePullPolicy: IfNotPresent
  - name: busybox
    image: busybox:1.28
    command:
    - "/bin/sh"
    - "-c"
- "sleep 3600"

[root@hd1.com ~]# kubectl apply -f pod-node.yaml
#查看pod调度到哪个节点
[root@hd1.com ~]# kubectl get pods  -o wide
NAME             READY   STATUS    RESTARTS            
demo-pod          1/1    Running     0            hd2.com 

3、nodeSelector

        指定pod调度到具有哪些标签的node节点上。

#给node节点打标签,打个具有disk=ceph的标签
[root@hd1.com ~]# kubectl label nodes hd3.com disk=ceph
node/hd3.com labeled
#查看节点的详细信息
[root@hd1 node]# kubectl describe nodes hd3.com
Name:               hd3.com
Roles:              worker
Labels:             beta.kubernetes.io/arch=amd64
                    beta.kubernetes.io/os=linux
                    disk=ceph
#定义pod的时候指定要调度到具有disk=ceph标签的node上
[root@hd1.com ~]# vim pod-1.yaml
apiVersion: v1
kind: Pod
metadata:
  name: demo-pod-1
  namespace: default
  labels:
    app: myapp
    env: dev
spec:
  nodeSelector:           #指定node标签
    disk: ceph
  containers:
  - name:  tomcat-pod-java
    ports:
    - containerPort: 8080
    image: tomcat:8.5-jre8-alpine
    imagePullPolicy: IfNotPresent

[root@hd1.com ~]# kubectl apply -f pod-1.yaml
#查看pod调度到哪个节点
[root@hd1.com ~]# kubectl get pods  -o wide
NAME             READY   STATUS    RESTARTS            
demo-pod-1        1/1     Running   0            hd3.com 

 

3、节点亲和性

3.1 亲和性定义

• 第一个pod随机选则一个节点,做为评判后续的pod能否到达这个pod所在的节点上的运行方式,这就称为pod亲和性;

• 以节点名称为标准,这个节点名称相同的表示是同一个位置,节点名称不相同的表示不是一个位置。

3.2 亲和性调度的表现形式

• podAffinity:把相近的pod结合到相近的位置,如同一区域,同一机架,这样的话pod和pod之间更好通信,比方说有两个机房,这两个机房部署的集群有1000台主机,那么我们希望把nginx和tomcat都部署同一个地方的node节点上,可以提高通信效率;

• podAntiAffinity:pod和pod更倾向不处于相近的位置,如果部署两套程序,那么这两套程序更倾向于反亲和性,这样相互之间不会有影响;

• 同样从node出发,也可以分成亲和性和反亲和性,分别对应nodeAffinity和nodeAntiAffinity。

3.3 键值运算关系

• In:label 的值在某个列表中

• NotIn:label 的值不在某个列表中

• Gt:label 的值大于某个值

• Lt:label 的值小于某个值

• Exists:某个 label 存在

• DoesNotExist:某个 label 不存在

3.4 硬亲和与软亲和

preferredDuringSchedulingIgnoredDuringExecution 软亲和

        软策略举例:结合上面的 “operator: NotIn”,意思就是尽量不要将 pod 调度到匹配到的节点,但是如果只有匹配的节点的话,也可以调度到匹配到的节点。

requiredDuringSchedulingIgnoredDuringExecution 硬亲和

        硬策略举例:结合上面的 “operator: In”,意思就是必须调度到满足条件的节点上,否则就等着 Pending

3.5 pod节点亲和性举例

• 例1:定义两个pod,第一个pod做为基准,第二个pod跟着它走。

[root@hd1.com]# kubectl delete pods pod-first
[root@hd1.com ~]# vim pod-required-affinity-demo.yaml
apiVersion: v1
kind: Pod
metadata:
  name: pod-first
  labels:
    app2: myapp2
    tier: frontend
spec:
  containers:
  - name: myapp
    image: ikubernetes/myapp:v1
    imagePullPolicy: IfNotPresent
---
apiVersion: v1
kind: Pod
metadata:
  name: pod-second
  labels:
    app: backend
    tier: db
spec:
  containers:
  - name: busybox
    image: busybox:1.28
    imagePullPolicy: IfNotPresent
    command: ["sh","-c","sleep 3600"]
  affinity:
    podAffinity:
      requiredDuringSchedulingIgnoredDuringExecution:
      - labelSelector:
          matchExpressions:
          - {key: app2, operator: In, values: ["myapp2"]}
        topologyKey: kubernetes.io/hostname


[root@hd1 node]# kubectl get nodes --show-labels
NAME      STATUS   ROLES                  AGE    VERSION   LABELS
kubernetes.io/hostname=hd1.com,kubernetes.io/os=linux,node
-
#上面表示创建的pod必须与拥有app=myapp2标签的pod在一个节点上
[root@hd1.com ~]# kubectl apply -f pod-required-affinity-demo.yaml
kubectl get pods -o wide 
pod-first            running        hd2.com
pod-second           running        hd2.com

        上面说明第一个pod调度到哪,第二个pod也调度到哪,这就是pod节点亲和性。

• pod节点反亲和性:定义两个pod,第一个pod做为基准,第二个pod跟它调度节点相反。

[root@hd1.com ~]# vim pod-required-anti-affinity-demo.yaml
apiVersion: v1
kind: Pod
metadata:
  name: pod-first
  labels:
    app1: myapp1
    tier: frontend
spec:
    containers:
    - name: myapp
      image: ikubernetes/myapp:v1
---
apiVersion: v1
kind: Pod
metadata:
  name: pod-second
  labels:
    app: backend
    tier: db
spec:
    containers:
    - name: busybox
      image: busybox:1.28
      imagePullPolicy: IfNotPresent
      command: ["sh","-c","sleep 3600"]
    affinity:
      podAntiAffinity:
         requiredDuringSchedulingIgnoredDuringExecution:
         - labelSelector:
              matchExpressions:
              - {key: app1, operator: In, values: ["myapp1"]}
           topologyKey: kubernetes.io/hostname
[root@hd1.com ~]# kubectl apply -f pod-required-anti-affinity-demo.yaml
[root@hd1.com ~]# kubectl get pods -o wide
pod-first            running        hd2.com
pod-second           running        hd3.com
[root@hd1.com ~]# kubectl delete -f pod-required-anti-affinity-demo.yaml

        上述显示两个pod不在一个node节点上,这就是pod节点反亲和性。

4、Pod常见的状态和重启策略

4.1 常见Pod状态

• 挂起(Pending):我们在请求创建pod时,条件不满足,调度没有完成,没有任何一个节点能满足调度条件,已经创建了pod但是没有适合它运行的节点叫做挂起,调度没有完成,处于pending的状态会持续一段时间:包括调度Pod的时间和通过网络下载镜像的时间。

• 运行中(Running):Pod已经绑定到了一个节点上,Pod 中所有的容器都已被创建。至少有一个容器正在运行。

• 成功(Succeeded):Pod 中的所有容器都被成功终止,并且不会再重启。

• 失败(Failed):Pod 中的所有容器都已终止了,并且至少有一个容器是因为失败终止。也就是说,容器以非0状态退出或者被系统终止。

• 未知(Unknown):未知状态,所谓pod是什么状态是apiserver和运行在pod节点的kubelet进行通信获取状态信息的,如果节点之上的kubelet本身出故障,那么apiserver就连不上kubelet,得不到信息了,就会看Unknown

4.2 Pod重启策略

• Pod的重启策略(RestartPolicy)应用于Pod内的所有容器,并且仅在Pod所处的Node上由kubelet进行判断和重启操作。当某个容器异常退出或者健康检查失败时,kubelet将根据 RestartPolicy 的设置来进行相应的操作。

• Pod的重启策略包括 Always、OnFailure和Never,默认值为Always

Always:当容器失败时,由kubelet自动重启该容器。

OnFailure:当容器终止运行且退出码不为0时,由kubelet自动重启该容器。

Never:不论容器运行状态如何,kubelet都不会重启该容器。

• yaml举例:

[root@hd1.com ~]# vim pod.yaml
apiVersion: v1
kind: Pod
metadata:
  name: demo-pod
  namespace: default
  labels:
    app: myapp
spec:
  restartPolicy: Always
  containers:
  - name:  tomcat-pod-java
    ports:
    - containerPort: 8080
    image: tomcat:8.5-jre8-alpine
    imagePullPolicy: IfNotPresent

4.3 存活性探测和就绪性探测

1) livenessProbe:存活性探测

Liveness探测器是让Kubernetes知道你的应用是否活着。如果你的应用还活着,那么Kubernetes就让它继续存在。如果你的应用程序已经死了,Kubernetes将移除Pod并重新启动一个来替换它。

2) readinessProbe:就绪性探测

就绪探针旨在让Kubernetes知道你的应用是否准备好为请求提供服务。Kubernetes只有在就绪探针通过才会把流量转发到Pod。如果就绪探针检测失败,Kubernetes将停止向该容器发送流量,直到它通过。

3) 目前LivenessProbe和ReadinessProbe两种探针都支持下面三种探测方法:

◇ ExecAction:在容器中执行指定的命令,如果执行成功,退出码为 0 则探测成功。

◇ TCPSocketAction:通过容器的IP 地址和端口号执行TCP 检查,如果能够建立 TCP 连接,则表明容器健康。

◇ HTTPGetAction:通过容器的IP地址、端口号及路径调用 HTTP Get方法,如果响应的状态码大于等于200且小于400,则认为容器健康

4) 探针探测结果有以下值:

◇ Success:表示通过检测。

◇ Failure:表示未通过检测。

◇ Unknown:表示检测没有正常进行。

5) Pod探针相关的属性:

◇ initialDelaySeconds: Pod启动后首次进行检查的等待时间,单位“秒”。

◇ periodSeconds: 检查的间隔时间,默认为10s,单位“秒”。

◇ timeoutSeconds: 探针执行检测请求后,等待响应的超时时间,默认为1s,单位“秒”。

◇ successThreshold:连续探测几次成功,才认为探测成功,默认为 1,在 Liveness 探针中必须为1,最小值为1。

◇ failureThreshold: 探测失败的重试次数,重试一定次数后将认为失败,在 readiness 探针中,Pod会被标记为未就绪,默认为 3,最小值为 1

6) 两种探针区别:

ReadinessProbe 和 livenessProbe 可以使用相同探测方式,只是对 Pod 的处置方式不同:

◇ readinessProbe 当检测失败后,将Pod的IP:Port从对应的EndPoint 列表中删除。

◇ livenessProbe 当检测失败后,将杀死容器并根据Pod的重启策略来决定作出对应的措施。

7) Pod探针使用示例:

◇ LivenessProbe 探针使用示例

(1)通过exec方式做健康探测

vim liveness-http.yaml
apiVersion: v1
kind: Pod
metadata:
  name: liveness-http
  labels:
    test: liveness
spec:
  containers:
  - name: liveness
    image: mydlqclub/springboot-helloworld:0.0.1
    livenessProbe:
      initialDelaySeconds: 20   #延迟加载时间
      periodSeconds: 5          #重试时间间隔
      timeoutSeconds: 10        #超时时间设置
      httpGet:
        scheme: HTTP
        port: 8081
        path: /actuator/health

        - 上面 Pod 中启动的容器是一个 SpringBoot 应用,其中引用了 Actuator 组件,提供了 /actuator/health 健康检查地址,存活探针可以使用 HTTPGet 方式向服务发起请求,请求 8081 端口的 /actuator/health 路径来进行存活判断:

        - 任何大于或等于200且小于400的代码表示探测成功。

        - 任何其他代码表示失败。

        - 如果探测失败,则会杀死 Pod 进行重启操作。

▪ httpGet探测方式有如下可选的控制字段:

        - scheme: 用于连接host的协议,默认为HTTP。

        - host:要连接的主机名,默认为Pod IP,可以在http request head中设置host头部。

        - port:容器上要访问端口号或名称。

        - path:http服务器上的访问URI。

        - httpHeaders:自定义HTTP请求headers,HTTP允许重复headers。

(3)通过TCP方式做健康探测

vim liveness-tcp.yaml
apiVersion: v1
kind: Pod
metadata:
  name: liveness-tcp
  labels:
    app: liveness
spec:
  containers:
  - name: liveness
    image: nginx
    livenessProbe:
      initialDelaySeconds: 15
      periodSeconds: 20
      tcpSocket:
        port: 80

        - TCP 检查方式和 HTTP 检查方式非常相似,在容器启动 initialDelaySeconds 参数设定的时间后,kubelet 将发送第一个 livenessProbe 探针,尝试连接容器的 80 端口,如果连接失败则将杀死 Pod 重启容器。

◇ ReadinessProbe 探针使用示例

        ▪ Pod 的ReadinessProbe 探针使用方式和 LivenessProbe 探针探测方法一样,也是支持三种,只是一个是用于探测应用的存活,一个是判断是否对外提供流量的条件。

        ▪ 这里用一个 Springboot 项目,设置 ReadinessProbe 探测 SpringBoot 项目的 8081 端口下的 /actuator/health 接口,如果探测成功则代表内部程序以及启动,就开放对外提供接口访问,否则内部应用没有成功启动,暂不对外提供访问,直到就绪探针探测成功。

vim readiness-exec.yaml
apiVersion: v1
kind: Service
metadata:
  name: springboot
  labels:
    app: springboot
spec:
  type: NodePort
  ports:
  - name: server
    port: 8080
    targetPort: 8080
    nodePort: 31180
  - name: management
    port: 8081
    targetPort: 8081
    nodePort: 31181
  selector:
    app: springboot
---
apiVersion: v1
kind: Pod
metadata:
  name: springboot
  labels:
    app: springboot
spec:
  containers:
  - name: springboot
    image: mydlqclub/springboot-helloworld:0.0.1
    ports:
    - name: server
      containerPort: 8080
    - name: management
      containerPort: 8081
    readinessProbe:
      initialDelaySeconds: 20  
      periodSeconds: 5         
      timeoutSeconds: 10  
      httpGet:
        scheme: HTTP
        port: 8081
        path: /actuator/health

二、Service

1、Service简介

1.1 Service的作用

• 在kubernetes中,Pod是有生命周期的,如果Pod重启它的IP很有可能会发生变化。如果我们的服务都是将Pod的IP地址写死,Pod挂掉或者重启,和刚才重启的pod相关联的其他服务将会找不到它所关联的Pod。

• 为了解决这个问题,在kubernetes中定义了service资源对象,Service 定义了一个服务访问的入口,客户端通过这个入口即可访问服务背后的应用集群实例,service是一组Pod的逻辑集合,这一组Pod能够被Service访问到,通常通过Label Selector实现。

1.2 Service概述

• service是一个固定接入层,客户端可以通过访问service的ip和端口访问到service关联的后端pod,这个service工作依赖于在kubernetes集群之上部署的一个附件,就是kubernetes的dns服务(不同kubernetes版本的dns默认使用的也是不一样的,1.11之前的版本使用的是kubeDNs,较新的版本使用的是coredns),service的名称解析是依赖于dns附件的,因此在部署完k8s之后需要再部署dns附件。

• kubernetes要想给客户端提供网络功能,需要依赖第三方的网络插件(flannel,calico等)。

• 每个K8s节点上都有一个组件叫做kube-proxy,kube-proxy这个组件将始终监视着apiserver中有关service资源的变动信息,需要跟master之上的apiserver交互,随时连接到apiserver上获取任何一个与service资源相关的资源变动状态,这种是通过kubernetes中固有的一种请求方法watch(监视)来实现的,一旦有service资源的内容发生变动(如创建,删除),kube-proxy都会将它转化成当前节点之上的能够实现service资源调度,把我们请求调度到后端特定的pod资源之上的规则,这个规则可能是iptables,也可能是ipvs,取决于service的实现方式。

1.3 Service工作原理

• k8s在创建Service时,会根据标签选择器selector(lable selector)来查找Pod,据此创建与Service同名的endpoint对象,当Pod 地址发生变化时,endpoint也会随之发生变化,service接收前端client请求的时候,就会通过endpoint,找到转发到哪个Pod进行访问的地址。(至于转发到哪个节点的Pod,由负载均衡kube-proxy决定)

1.4 k8s集群中的三类IP地址

Node Network(节点网络):物理节点或者虚拟节点的网络,如ens33接口上的网路地址

Pod network(pod 网络),创建的Pod具有的IP地址

Cluster Network(集群地址,也称为service network):这个地址是虚拟的地址(virtual ip),没有配置在某个接口上,只是出现在service的规则当中。

• Node Network和Pod network这两种网络地址是我们实实在在配置的,其中节点网络地址是配置在节点接口之上,而pod网络地址是配置在pod资源之上的,因此这些地址都是配置在某些设备之上的,这些设备可能是硬件,也可能是软件模拟的。

2、创建Service资源

2.1 查看定义Service资源所用字段

[root@hd1.com ~]# kubectl explain service
FIELDS:
   apiVersion  <string>  #service资源使用的api组
   kind<string>           #创建的资源类型
   metadata<Object>      #定义元数据
   spec<Object>    

2.2 Service的四种类型

1) ExternalName:适用于k8s集群内部容器访问外部资源,它没有指定selector去选择pod,也没有定义任何的端口和Endpoint。

2) ClusterIP:通过k8s集群内部IP暴露服务,选择该值,服务只能够在集群内部访问,这也是默认的ServiceType。

3) NodePort:通过每个Node节点上的IP和静态端口暴露k8s集群内部的服务。通过请求<NodeIP>:<NodePort>可以把请求代理到内部的pod。Client----->NodeIP:NodePort----->Service Ip:ServicePort----->PodIP:ContainerPort。

4) LoadBalancer:使用云提供商的负载均衡器,可以向外部暴露服务。外部的负载均衡器可以路由到NodePort服务和ClusterIP服务。

2.3 Service端口

[root@hd1.com ~]# kubectl explain service.spec.ports

FIELDS:
   appProtocol <string>
   name<string>  #定义端口的名字
   nodePort<integer> 
#宿主机上映射的端口,比如一个Web应用需要被k8s集群之外的其他用户访问,
#那么需要配置type=NodePort,若配置nodePort=30001,那么其他机器就
#可以通过浏览器访问scheme://k8s集群中的任何一个节点ip:30001即可访问
#到该服务,例如http://192.168.1.12:30001。如果在k8s中部署MySQL数据库,
#MySQL可能不需要被外界访问,只需被内部服务访问,那么就不需要设置NodePort
   port<integer> -required-  #service的端口,这个是k8s集群内部服务可访问的端口
   protocol<string>
   targetPort  <string>
# targetPort是pod上的端口,从port和nodePort上来的流量,
#经过kube-proxy流入到后端pod的targetPort上,最后进入容器。
#与制作容器时暴露的端口一致(使用DockerFile中的EXPOSE),
#例如官方的nginx暴露80端口。

2.4 创建Service:type类型为ClusterIP

1)创建Pod

#把nginx.tar.gz上传到hd3.com和hd2.com,手动解压
[root@hd2.com ~]# docker load -i nginx.tar.gz
[root@hd3.com ~]# docker load -i nginx.tar.gz
[root@hd1.com ~]# cat pod_test.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: my-nginx
spec:
  selector:
    matchLabels:
      run: my-nginx
  replicas: 2
  template:
    metadata:
      labels:
        run: my-nginx
    spec:
      containers:
      - name: my-nginx
        image: nginx
        imagePullPolicy: IfNotPresent
        ports:
        - containerPort: 80  #pod中的容器需要暴露的端口
#更新资源清单文件
[root@hd1.com ~]# kubectl apply -f pod_test.yaml
#查看刚才创建的Pod ip地址
[root@hd1.com ~]# kubectl get pods -l run=my-nginx -o wide  
NAME                             STATUS           IP                   NODE
my-nginx-5b56ccd65f-26vcz       Running          10.244.187.101      hd3.com
my-nginx-5b56ccd65f-95n7p       Running          10.244.209.149      hd2.com
#请求pod ip地址,查看结果
[root@hd1.com ~]# curl 10.244.187.101
<!DOCTYPE html>
<html>
<h1>Welcome to nginx!</h1>
</body>
</html>
[root@hd1.com ~]# curl 10.244.209.149
<!DOCTYPE html>
<html>
<h1>Welcome to nginx!</h1>
</body>
</html>
[root@hd1.com ~]# kubectl exec -it my-nginx-5b56ccd65f-26vcz -- /bin/bash
root@my-nginx-5b56ccd65f-26vcz:/# curl 10.244.209.149
<!DOCTYPE html>
<html>
<h1>Welcome to nginx!</h1>
</html>
root@my-nginx-5b56ccd65f-26vcz:/#exit

2)创建Service

[root@hd1.com service]# cat service_test.yaml
apiVersion: v1
kind: Service
metadata:
  name: my-nginx
  labels:
    run: my-nginx
spec:
  type: ClusterIP #只能在集群内部访问
  ports:
  - port: 80   #service的端口,暴露给k8s集群内部服务访问
    protocol: TCP
    targetPort: 80    #pod容器中定义的端口
  selector:
    run: my-nginx  #选择拥有run=my-nginx标签的pod

[root@hd1.com service]# kubectl apply -f service_test.yaml
service/my-nginx created
[root@hd1.com ~]# kubectl get svc -l run=my-nginx
NAME       TYPE        CLUSTER-IP      EXTERNAL-IP   PORT(S)   AGE
my-nginx   ClusterIP   10.99.198.177   <none>        80/TCP    143m

#在k8s控制节点访问service的ip:端口就可以把请求代理到后端pod
[root@hd1.com ~]# curl 10.99.198.177:80
<!DOCTYPE html>
<html>
<h1>Welcome to nginx!</h1>
</html>
#通过上面可以看到请求service IP:port跟直接访问pod ip:port看到的结果一样,
#这就说明service可以把请求代理到它所关联的后端pod
#注意:上面的10.99.198.177:80地址只能是在k8s集群内部可以访问,在外部无法访问
#若想在k8s集群之外访问,需要把service type类型改成NodePort

#查看service详细信息
[root@hd1.com ~]# kubectl describe svc my-nginx
Name:              my-nginx
Namespace:         default
Labels:            run=my-nginx
Annotations:       <none>
Selector:          run=my-nginx
Type:              ClusterIP
IP Families:       <none>
IP:                10.99.198.177
IPs:               10.99.198.177
Port:              <unset>  80/TCP
TargetPort:        80/TCP
Endpoints:         10.244.187.102:80,10.244.209.149:80
Session Affinity:  None
Events:            <none>
[root@hd1.com ~]# kubectl get ep my-nginx
NAME       ENDPOINTS                             AGE
my-nginx   10.244.187.102:80,10.244.209.149:80   142m

        ◇ service可以对外提供统一固定的ip地址,并将请求重定向至集群中的pod。其中“将请求重定向至集群中的pod”就是通过endpoint与selector协同工作实现。selector是用于选择pod,由selector选择出来的pod的ip地址和端口号,将会被记录在endpoint中。

        ◇ endpoint便记录了所有pod的ip地址和端口号。当一个请求访问到service的ip地址时,就会从endpoint中选择出一个ip地址和端口号,然后将请求重定向至pod中。具体把请求代理到哪个pod,需要的就是kube-proxy的轮询实现的。

        ◇ service不会直接到pod,service是直接到endpoint资源,就是地址加端口,再由endpoint再关联到pod。

Logo

K8S/Kubernetes社区为您提供最前沿的新闻资讯和知识内容

更多推荐