k8s--pod生命周期,pod调度

一:pod生命周期

1、基础概念

img

  1. pod生命周期

    1、pod创建过程

    2、运行初始化过程,这是容器的一种,在运行主容器之前运行,否则,一直重启,知道初始化成功,运行主容器

    3、运行主容器过程
    容器启动后钩子,容器终止前钩子,启动之后先执行的命令,和结束前,执行的命令

    容器的存活性探测,就绪性探测

    4、pod终止过程

  2. pod的状态

    1、挂起(pending),已经创建了pod资源对象,但是还没有被调度,或者是镜像仍然处于下载镜像过程

    2、运行中(running),pod已经被调度到某一个节点上面了,并且里面所有的容器都被kubelet创建完了

    3、成功(completed),pod中的所有容器都已经被终止了,并且不会被重启,就是运行一个容器,30秒后,打印,然后退出

    4、失败(failed),所有容器都已经被终止了,但是至少有一个容器终止失败,即容器退出时返回非0的状态

    5、未知(unknown),apiserver无法正常获取pod对象的状态信息,通常是网络通信失败的问题

  3. pod创建过程

    1、用户通过kubectl创建的pod的信息给apiserver

    2、apiserver开始生成pod对象信息,并将信息存储etcd中,然后确认信息到客户端

    3、apisever开始反映etcd中pod对象的变化,其他组件使用watch机制来跟踪检查apiserver上的变动

    4、scheduler发现有新的Pod对象创建,开始为pod分配主机并将信息更新至apiserver

    5、node节点上的kubelet发现有pod调度过来,创建容器,将结果告诉apiserver

    6、apiserver将信息存放到etcd中

img

  1. pod终止过程

    1、用户向apiserver发送删除pod命令

    2、apiserver中pod信息随着时间的推移更新,在(宽限期)默认30s内了,pod被视为dead

    3、将pod标记为terminating状态

    4、kubelet监控到pod的状态为terminating同时启动关闭pod过程

    5、端点控制器监控到pod对象关闭行为时,将其从所有匹配到端点的service资源的端点列表移除

    6、如果pod对象定义了prestop钩子处理器,则标记为terminating后,会以同步的方式执行,

    7、pod对象中容器进程收到了停止信号

    8、宽限期结束后,若Pod中还有存在运行的进程,那么pod会收到立即终止的信号

1、初始化容器

  1. 初始化容器
    • 初始化容器执行完成后,才能运行主容器,如果初始化失败了,那么就必须要不断的重启才行
#任务,就是mysql和redis2个服务器,先去连mysql,不成功,则一直处于连接,否则就去连接redis,2个条件都满足了,nginx主容器就会启动

myql 192.168.109.201
redis 192.168.109.202


apiVersion: v1
kind: Pod
metadata:
   name: nginx-init
   namespace: dev
kind: Pod
metadata:
   name: nginx-init
   namespace: dev
spec:
   containers:
     - name: nginx
       image: nginx:1.17.1
       ports:
       - name: nginx-port
         containerPort: 80
   initContainers:   #初始化容器
   - name: test-mysql
     image: busybox:1.30
     command: ["sh","-c","util ping 192.168.109.201 -c 1;do echo waiting for mysql;sleep 2;done;"]
   - name: test-redis
     image: busybox:1.30
     command: ["sh","-c","util ping 192.168.109.202 -c 1;do echo waiting for redis;sleep 2 ;done;"]


#由于没有初始化成功,所以的话,状态为初始化容器失败
[root@master pod]# kubectl get pod -n dev
NAME         READY   STATUS                  RESTARTS        AGE
nginx-init   0/1     Init:CrashLoopBackOff   5 (2m51s ago)   6m5s


#网卡的设置
ifconfig  ens33:1 192.168.109.201 netmask 255.255.255.0 up
ifconfig ens33:2 192.168.109.202 netmask 255.255.255.0 up

#发现容器启动了
[root@master pod]# kubectl get pod -n dev
NAME         READY   STATUS    RESTARTS   AGE
nginx-init   1/1     Running   0          20m


#查看容器详细信息
Events:
  Type    Reason     Age   From               Message
  ----    ------     ----  ----               -------
  Normal  Scheduled  19m   default-scheduler  Successfully assigned dev/nginx-init to node1
  Normal  Pulled     19m   kubelet            Container image "busybox:1.30" already present on machine
  Normal  Created    19m   kubelet            Created container test-mysql
  Normal  Started    19m   kubelet            Started container test-mysql
  Normal  Pulled     19m   kubelet            Container image "busybox:1.30" already present on machine
  Normal  Created    19m   kubelet            Created container test-redis
  Normal  Started    19m   kubelet            Started container test-redis
  Normal  Pulled     19m   kubelet            Container image "nginx:1.17.1" already present on machine
  Normal  Created    19m   kubelet            Created container nginx
  Normal  Started    19m   kubelet            Started container nginx

2、主容器钩子函数

  1. post start

    1、容器启动后钩子,容器启动之后会立即执行,成功了,则启动,否则一直处于重启

  2. post stop

    1、容器终止前钩子,容器在删除之前执行,就terming状态,会阻塞容器删除,这个执行完才会删除容器

#格式有三种,start和stop一样的三种
##exec格式
lifecycle:
  podstart:
    exec:
      command:   ##command第一种写法,列表的形式
      - cat
      - /tmp/healthy

      command: ["cat"]   #第二种写法,当同事指定了这2个参数,command会覆盖容器镜像默认的ENTRYPOINT命令,args传入参数
      args: ["/tmp/healthy"]

      command: ["cat","/tmp/healthy"]  #第三种写法

#tcpsocket格式  在当前容器内尝试访问指定socket,在容器内访问8080端口
lifecycle:
  podstart:
    tcpsocket:
      port: 8080  #会尝试连接8080端口

#httpget  在当前的容器向url发起http请求
lifecycle:
  podstart:
    httpGet
      path: url地址
      host: 80
      schme: http支持的协议
#nginx容器在启动时,传入一个网页内容,在结束后停止优雅的停止nginx容器

apiVersion: v1
kind: Pod
metadata:
  name: nginx
  namespace: dev
spec:
  containers:
    - name: nginx
      image: nginx:1.17.1
      ports:
      - name: nginx-port
        containerPort: 80
      lifecycle:
        postStart:
          exec:
            command: ["/bin/sh","-c","echo poststart > /usr/share/nginx/html/index.html"]
        preStop:
          exec:
            command: ["/usr/sbin/nginx","-s","quit"]
#访问网页内容
[root@master pod]# kubectl get pod -n dev -o wide
NAME    READY   STATUS    RESTARTS   AGE   IP            NODE    NOMINATED NODE   READINESS GATES
nginx   1/1     Running   0          13s   10.244.1.54   node1   <none>           <none>
[root@master pod]# curl 10.244.1.54:80
poststart

#删除这个Pod
[root@master pod]# kubectl delete pod -n dev nginx
pod "nginx" deleted

3、容器探测

  1. liveness probes

    1、用于检测示例是否处于正常的状态,如果不是,k8s会重启容器,用于决定是否重启容器

  2. readiness probes

    1、用于检测实例是否可以接受请求,如果不能,k8s不会转发流量

    2、nginx需要读取很多的web文件,在读取的过程中,service认为nginx已经成功了,如果有个请求转发的话,那么就无法提供这个服务了,所以不会将请求转发到这里来

  3. 作用

    1、找出这些出来问题的pod

    2、服务是否已经准备成功了

#三种格式
livenessProbe
  exec:
    command: ["cat","/tmp/healthy"]

livenessProbe:
   tcpSocket:
     port: 8080

livenessProbe:
   httpGet:
     path: /url地址
     port: 80
     scheme: http

1、操作

#nginx容器如果有/hello.txt这个文件话,pod一直进行重启

[root@master pod]# cat liveness.yaml 
apiVersion: v1
kind: Pod
metadata:
   name: nginx-111
   namespace: dev
spec:
  containers:
  - name: nginx
    image: nginx:1.17.2
    ports:
    - name: nginx-port
      containerPort: 80
    livenessProbe:
      exec:
        command: ["/bin/cat","/hello.txt"]


[root@master pod]# kubectl get pod -n dev
NAME        READY   STATUS    RESTARTS      AGE
nginx-111   1/1     Running   2 (28s ago)   88s



#查看详细信息
Normal   Scheduled  33s               default-scheduler  Successfully assigned dev/nginx-111 to node2
  Normal   Pulled     3s (x2 over 33s)  kubelet            Container image "nginx:1.17.2" already present on machine
  Normal   Created    3s (x2 over 33s)  kubelet            Created container nginx
  Normal   Started    3s (x2 over 33s)  kubelet            Started container nginx
  Warning  Unhealthy  3s (x3 over 23s)  kubelet            Liveness probe failed: /bin/cat: /hello.txt: No such file or directory
  Normal   Killing    3s                kubelet            Container nginx failed liveness probe, will be restarted

2、补充

initialDelaySeconds <integer>  容器启动后等待多少秒执行第一次探测
timeoutSeconds  <integer>   探测超时时间,默认是1秒,最小1秒
periodSeconds   <integer>   执行探测的频率,默认是10秒,最小是1秒
failureThreshold    <integer>    连续探测失败多少次后才被认为失败,默认是3,最小值是1
successThreshold    <integer>  连续探测成功多少次后才被认定为成功,默认是1

4、重启策略

  1. 重启
    1、容器探测出现了问题,k8s对容器所在的Pod进行重启,这个有pod的重启策略决定的

    2、always,容器失效时,自动重启容器,默认值

    3、onfailure,容器终止运行退出码不为0时重启,异常的终止

    4、never,不论状态为什么,都不重启容器

apiVersion: v1
kind: Pod
metadata:
   name: nginx-111
   namespace: dev
spec:
  containers:
  - name: nginx
    image: nginx:1.17.2
    ports:
    - name: nginx-port
      containerPort: 80
    livenessProbe:
      exec:
        command: ["/bin/cat","/hello.txt"]
  restartPolicy: Never

#设置了重启策略后,不会对其进行反复的重启了
[root@master pod]# kubectl get pod -n dev
NAME        READY   STATUS      RESTARTS   AGE
nginx-111   0/1     Completed   0          84s

二、pod调度

1、概念

  1. 调度
    1、pod在哪个节点上面运行,是有scheduler计算出来的,这个过程是不受人工控制的,但是在实际中,需要控制pod在哪个节点上面运行,就需要调度的规则了

2、自动调度,定向调度,亲和性调度,容忍调度

2、定向调度

  1. 就是以nodename,nodeselector,依次进行调度,强制性的,即使不存在node节点,也会进行调度,失败而已

1. nodename

apiVersion: v1
kind: Pod
metadata:
  name: nginx-pod
  namespace: dev
spec:
  nodeName: node1
  containers:
  - name: nginx
    image: nginx:1.17.2

2、nodeselector

#查看标签
[root@master pod]# kubectl get node --show-labels 
NAME     STATUS   ROLES           AGE     VERSION   LABELS
master   Ready    control-plane   6d13h   v1.28.2   beta.kubernetes.io/arch=amd64,beta.kubernetes.io/os=linux,kubernetes.io/arch=amd64,kubernetes.io/hostname=master,kubernetes.io/os=linux,node-role.kubernetes.io/control-plane=,node.kubernetes.io/exclude-from-external-load-balancers=
node1    Ready    <none>          6d13h   v1.28.2   app=nginx-1,beta.kubernetes.io/arch=amd64,beta.kubernetes.io/os=linux,kubernetes.io/arch=amd64,kubernetes.io/hostname=node1,kubernetes.io/os=linux
node2    Ready    <none>          6d13h   v1.28.2   app=nginx-2,beta.kubernetes.io/arch=amd64,beta.kubernetes.io/os=linux,kubernetes.io/arch=amd64,kubernetes.io/hostname=node2,kubernetes.io/os=linux

#调度到node2上面去
[root@master pod]# kubectl create -f nodeselector.yaml 
pod/nginx-2 created
[root@master pod]# kubectl get pod -n dev -o wide
NAME        READY   STATUS    RESTARTS   AGE     IP            NODE    NOMINATED NODE   READINESS GATES
nginx-2     1/1     Running   0          5s      10.244.2.53   node2   <none>           <none>
nginx-pod   1/1     Running   0          5m32s   10.244.1.57   node1   <none>           <none>

3、亲和性调度

1、node亲和性

  1. 主要就是关于node上面的标签来决定的,

  2. 有软和硬限制的操作

格式

spec:
   affinity:
      nodeAffinity:
        requiredDuringSchedulingIgnoredDuringExecution: #硬亲和性
           nodeSelectorTerms:
           - matchExpressions:
             - key:
               operator:
               values:
软亲和性
spec:
   affinity:
     nodeAffinity:
       preferredDuringSchedulingIgnoredDuringExecution:
       - weight:
         preference:
           matchExpressions:  #按照节点的标签列出的节点
           - key:
             operator:
             values:

操作

#将pod调度到node1上面去
[root@master pod]# cat node-aff.yaml 
apiVersion: v1
kind: Pod
metadata:
  name: nginx-pod
  namespace: dev
spec:
  affinity:
    nodeAffinity:
      requiredDuringSchedulingIgnoredDuringExecution:
        nodeSelectorTerms:
        - matchExpressions:
            - key: app
              operator: In
              values: ["nginx-1"]
  containers:
  - name: nginx
    image: nginx:1.17.2
[root@master pod]# kubectl get pod -n dev -o wide
NAME        READY   STATUS    RESTARTS   AGE   IP            NODE    NOMINATED NODE   READINESS GATES
nginx-pod   1/1     Running   0          44s   10.244.1.58   node1   <none>           <none>

2、pod亲和性调度

  1. 主要就是pod上面的标签来决定的
spec:
  affinity:
    podAffinity:
      requiredDuringSchedulingIgnoredDuringExecution:
      - topologyKey:   #调度作用域,靠近节点,
        labelSelector:  #标签选择器
          matchExpressions:  #按照标签列出
          - key:
            operator:
            values:

spec:
  affinity:
    podAffinity:
      preferredDuringSchedulingIgnoredDuringExecution:
      - weight:
        podAffinityTerm:
          topologyKey:
          labelSelector:
            matchExpressions:
            - key:
              operator:
              values:
#创建一个pod出来,node2上面,根据node2上面pod中的标签进行调度

[root@master pod]# cat podaff.yaml 
apiVersion: v1
kind: Pod
metadata:
  name: pod-nginx1
  namespace: dev
spec:
  affinity:
    podAffinity:
      preferredDuringSchedulingIgnoredDuringExecution:
      - weight: 1
        podAffinityTerm:
          labelSelector:
             matchExpressions:
             - key: app
               values: ["nginx-111"]
               operator: In
          topologyKey: kubernetes.io/hostname
  containers:
  - name: nginx
    image: nginx:1.17.2

[root@master pod]# kubectl get pod -n dev --show-labels -o wide
NAME         READY   STATUS    RESTARTS      AGE     IP            NODE    NOMINATED NODE   READINESS GATES   LABELS
nginx-2      1/1     Running   0             7m10s   10.244.2.56   node2   <none>           <none>            app=nginx-111
nginx-pod    1/1     Running   1 (29m ago)   139m    10.244.1.60   node1   <none>           <none>            <none>
pod-nginx1   1/1     Running   0             63s     10.244.2.57   node2   <none>           <none>            <none>


  1. 反亲和性调度
    1、也是按照pod上面的标签来进行调度的,如果这个pod上面有标签的话,就不在pod上面调度即可,在其他的地方进行调度
spec:
  affinity:
    podAntiAffinity:
      requiredDuringSchedulingIgnoredDuringExecution:
      - topologyKey:
        labelSelector:
          matchExpressions:
          - key:
            operator:
            values:
[root@master podaff]# cat podanti.yaml 
apiVersion: v1
kind: Pod
metadata:
  name: nginx2
  namespace: dev
spec:
  affinity:
    podAntiAffinity:
      requiredDuringSchedulingIgnoredDuringExecution:
      - topologyKey: kubernetes.io/hostname
        labelSelector:
          matchExpressions:
          - key: app
            values: ["nginx-2"]
            operator: In
  containers:
    - name: nginx2
      image: nginx:1.17.2  

[root@master podaff]# kubectl create -f podanti.yaml 
pod/nginx2 created
[root@master podaff]# kubectl get pod -n dev -o wide
NAME     READY   STATUS    RESTARTS   AGE   IP            NODE    NOMINATED NODE   READINESS GATES
centos   1/1     Running   0          29h   10.244.2.25   node2   <none>           <none>
nginx2   1/1     Running   0          6s    10.244.1.16   node1   <none>           <none>

4、污点和容忍

1、污点

  1. 污点解释

    1、就是节点上面有一个污点,pod的调度不能调度到这个上面

    2、污点有三个等级,NoExecute(节点上已有的pod全部销毁,不能调度到这个上面),PreferNoSchedule(万不得已才能在这个上面调度),NoSchedule(已有的可以在上面,但是不能进行调度)

  2. 污点操作

#打上一个污点
[root@master /]# kubectl describe  node node1 | grep -i taint
Taints:             <none>

[root@master /]# kubectl taint node node1 app=qq:NoExecute
node/node1 tainted

[root@master /]# kubectl describe node node1 | grep -i taint
Taints:             app=qq:NoExecute

#发现node1上面的pod没有了
[root@master /]# kubectl get pod -n dev -o wide
NAME     READY   STATUS    RESTARTS   AGE   IP            NODE    NOMINATED NODE   READINESS GATES
centos   1/1     Running   0          29h   10.244.2.25   node2   <none>           <none>

#取消一个污点
##取消所有的污点
[root@master /]# kubectl taint node node1 app-
node/node1 untainted
[root@master /]# kubectl describe  node node1 | grep -i taint
Taints:             <none>

##取消单个污点
[root@master /]# kubectl taint node node1 app:NoExecute-

2、容忍

  1. 容忍

    1、主要就是在pod上面,容忍节点的污点,可以在有污点的节点上面进行调度pod

  2. 格式

spec:
  tolerations: #添加容忍
  - key:   #容忍的key
    operator:   
    value:  #容忍的值
    effect: #添加的容忍的规划,这里必须是标记的污点
[root@master /]# kubectl taint node node1 app=nginx1:NoExecute
node/node1 tainted

[root@master podaff]# cat pod-tolerat.yaml 
apiVersion: v1
kind: Pod
metadata:
  name: nginx1
  namespace: dev
spec:
  affinity:  #亲和性
    nodeAffinity:
      requiredDuringSchedulingIgnoredDuringExecution:
        nodeSelectorTerms:
        - matchExpressions:
          - key: app
            values: ["node1"]
            operator: In
  tolerations:   #容忍的key
    - key: app
      value: nginx1
      operator: Equal
      effect: NoExecute
  containers:
    - name: nginx1
      image: nginx:1.17.2

三:总结

在同一个名称空间下面,如果2个pod中的容器都监听的是80端口的话,不会发生冲突,因为这个有网络隔离,不同的pod之间,共享ip地址和网络空间

1、

posted @ 2026-04-14 08:54  q_7  阅读(11)  评论(0)    收藏  举报