k8S最小调度单元Pod概述

注:k8s集群节点信息如下:

[root@k8s-master1 ~]# kubectl get nodes
NAME          STATUS   ROLES                  AGE   VERSION
k8s-master1   Ready    control-plane,master   26d   v1.20.6
k8s-node1     Ready    worker                 26d   v1.20.6
k8s-node2     Ready    worker                 26d   v1.20.6

一、k8s核心资源Pod介绍

K8s官方文档:https://kubernetes.io/

K8s中文官方文档: https://kubernetes.io/zh/

K8s Github地址:https://github.com/kubernetes/

1、什么是pod

官方文档:https://kubernetes.io/docs/concepts/workloads/pods/

  Pod是Kubernetes中的最小调度单元,k8s是通过定义一个Pod的资源,然后在Pod里面运行容器,容器需要指定一个镜像,这样就可以用来运行具体的服务。

  一个Pod封装一个容器(也可以封装多个容器),Pod里的容器共享存储、网络等。也就是说,应该把整个pod看作虚拟机,然后每个容器相当于运行在虚拟机的进程。

  Pod是需要调度到k8s集群的工作节点来运行的,具体调度到哪个节点,是根据scheduler调度器实现的。

  从docker角度来讲,Pod 类似于一组具有共享命名空间和共享文件系统卷的 Docker 容器。

1.1  Pods 如何管理多个容器

  Pod中可以同时运行多个容器。同一个Pod中的容器会自动的分配到同一个 node上。同一个Pod中的容器共享资源、网络环境,它们总是被同时调度,在一个Pod中同时运行多个容器是一种比较高级的用法,只有当容器需要紧密配合协作的时候才考虑用这种模式。例如,有一个容器作为web服务器运行,需要用到共享的volume,有另一个“sidecar”容器来从远端获取资源更新这些文件,如图所示:

  

  一些 Pod 有初始化容器也应用容器. Init 容器在应用容器启动之前运行并完成。

Pod 本身为其组成容器提供两种共享资源: 网络和存储

1.2  pod网络

  Pod是有IP地址的,每个pod都被分配唯一的IP地址(IP地址是靠网络插件calico、flannel、weave等分配的),POD中的容器共享网络名称空间,包括IP地址和网络端口。

  Pod内部的容器可以使用localhost相互通信。 Pod中的容器也可以通过网络插件calico与其他节点的Pod通信。

1.3 pod存储

  创建pod的时候可以指定挂载的存储卷。 

  pod中的所有容器都可以访问共享卷,允许这些容器共享数据。

  pod只要挂载持久化数据卷,Pod重启之后数据还是会存在的。

2. pod的工作方式

  在K8s中,所有的资源都可以使用一个yaml文件来创建,创建Pod也可以使用yaml配置文件。或者使用kubectl run在命令行创建Pod(不常用)。

2.1 自主式pod

  所谓的自主式pod,就是直接定义一个pod资源。如下:

[root@k8s-master1 ~]# mkdir pod
[root@k8s-master1 ~]# cd pod/
[root@k8s-master1 pod]# vim pod-tomcat.yaml
[root@k8s-master1 pod]# cat pod-tomcat.yaml
apiVersion: v1
kind: Pod
metadata:
  name: tomcat-test
  namespace: default
  labels:
    app:  tomcat
spec:
  containers:
  - name:  tomcat-java
    ports:
    - containerPort: 8080
    image: tomcat:8.5-jre8-alpine
    imagePullPolicy: IfNotPresent

  更新yaml资源清单文件

[root@k8s-master1 pod]# kubectl apply -f pod-tomcat.yaml
pod/tomcat-test created

  查看pod是否创建成功

[root@k8s-master1 pod]# kubectl get pod -o wide
NAME          READY   STATUS    RESTARTS   AGE     IP               NODE        NOMINATED NODE   READINESS GATES
tomcat-test   1/1     Running   0          2m32s   10.244.169.129   k8s-node2   <none>           <none>

  自主式Pod是存在一个问题的,假如不小心删除了pod,pod将不存在。

[root@k8s-master1 pod]# kubectl delete pod tomcat-test
pod "tomcat-test" deleted
You have new mail in /var/spool/mail/root
[root@k8s-master1 pod]# kubectl get pod -o wide
No resources found in default namespace.

  通过上面可以看到,如果直接定义一个Pod资源,那Pod被删除,就彻底被删除了,不会再创建一个新的Pod,这在生产环境还是具有非常大风险的,所以一般使用pod时,都是由控制器管理的。

2.2 控制器管理的Pod

  常见的管理Pod的控制器:Replicaset、Deployment、Job、CronJob、Daemonset、Statefulset。

  控制器管理Pod可以确保Pod始终维持在指定的副本数运行。

  如:通过Deployment管理Pod。

  创建资源清单文件

[root@k8s-master1 pod]# vim nginx-deploy.yaml
[root@k8s-master1 pod]# cat nginx-deploy.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx-test
  labels:
    app: nginx-deploy
spec:
  selector:
    matchLabels:
      app: nginx
  replicas: 2
  template:
    metadata:
      labels:
        app: nginx
    spec:
      containers:
      - name: my-nginx
        image: nginx:latest
        imagePullPolicy: IfNotPresent
        ports:
        - containerPort: 80

  更新资源清单文件,查看资源

[root@k8s-master1 pod]# kubectl get deployment
NAME         READY   UP-TO-DATE   AVAILABLE   AGE
nginx-test   2/2     2            2           32s
[root@k8s-master1 pod]# kubectl get rs
NAME                    DESIRED   CURRENT   READY   AGE
nginx-test-7d464f958f   2         2         2       34s
[root@k8s-master1 pod]# kubectl get pod -o wide
NAME                          READY   STATUS    RESTARTS   AGE   IP               NODE        NOMINATED NODE   READINESS GATES
nginx-test-7d464f958f-4srgk   1/1     Running   0          39s   10.244.36.76     k8s-node1   <none>           <none>
nginx-test-7d464f958f-k5nmh   1/1     Running   0          39s   10.244.169.130   k8s-node2   <none>           <none>

  删除pod:nginx-test-7d464f958f-4srgk,再次查看pod资源

[root@k8s-master1 pod]# kubectl delete pod nginx-test-7d464f958f-4srgk
pod "nginx-test-7d464f958f-4srgk" deleted
[root@k8s-master1 pod]# kubectl get deployment
NAME         READY   UP-TO-DATE   AVAILABLE   AGE
nginx-test   2/2     2            2           2m6s
[root@k8s-master1 pod]# kubectl get rs
NAME                    DESIRED   CURRENT   READY   AGE
nginx-test-7d464f958f   2         2         2       2m11s
[root@k8s-master1 pod]# kubectl get pod -o wide
NAME                          READY   STATUS    RESTARTS   AGE     IP               NODE        NOMINATED NODE   READINESS GATES
nginx-test-7d464f958f-k5nmh   1/1     Running   0          2m14s   10.244.169.130   k8s-node2   <none>           <none>
nginx-test-7d464f958f-pxwkv   1/1     Running   0          18s     10.244.36.77     k8s-node1   <none>           <none>

  发现又重新创建一个新的pod :nginx-test-7d464f958f-pxwkv

  通过上面可以发现通过deployment管理的pod,可以确保pod始终维持在指定副本数量。

2.3  通过kubectl run创建Pod

[root@k8s-master1 pod]# kubectl run tomcat-test --image=tomcat:8.5-jre8-alpine  --image-pull-policy='IfNotPresent'  --port=8080
pod/tomcat-test created
You have new mail in /var/spool/mail/root
[root@k8s-master1 pod]# kubectl get pod
NAME                          READY   STATUS    RESTARTS   AGE
nginx-test-7d464f958f-k5nmh   1/1     Running   0          18m
nginx-test-7d464f958f-pxwkv   1/1     Running   0          17m
tomcat-test                   1/1     Running   0          4s

二、Pod对象生命周期

  pod对象自从其创建开始至其终止退出的时间范围称为其生命周期。在这段时间中,Pod会处于多种不同的状态,并执行一些操作;其中,创建主容器为必需的操作,其他可选的操作还包括运行初始化容器,容器启动后钩子,容器存活性探测,就绪性探测以及容器终止前钩子等。这些操作是否执行取决于Pod的定义。

1. pod的状态

  Pod的status定义在PodStatus对象中,其中有一个phase字段。它简单描述了Pod在其生命周期的阶段。熟悉Pod的各种状态对理解如何设置Pod的调度策略、重启策略是很有必要的。下面是 phase 可能的值,也就是pod常见的状态:

  pending:API Server创建了pod资源对象并已存入etcd中,但它未被调度完成,或者仍处于从仓库下载镜像的过程中。

  running:Pod已经被调度至某节点,并且所有容器都已经被kubelet创建完成。

  succeeded:Pod中的所有容器都已经成功终止并且不会被重启

  failed:所有容器都已经终止,但至少有一个容器终止失败,即容器返回了非0值的退出状态或已经被系统终止。

  unknown:API Server无法正常获取到pod对象状态信息,通常是由于其无法与所有工作节点的kubelet通信所致。

  Evicted状态:出现这种情况,多见于系统内存或硬盘资源不足,可df-h查看docker存储所在目录的资源使用情况,如果百分比大于85%,就要及时清理下资源,尤其是一些大文件、docker镜像。

  CrashLoopBackOff:容器曾经启动了,但可能又异常退出了

  Error 状态:Pod 启动过程中发生了错误

2. pod创建过程

  Pod是Kubernetes中最基本的部署调度单元,可以包含container,逻辑上表示某种应用的一个实例。
  例如一个web站点应用由前端、后端及数据库构建而成,这三个组件将运行在各自的容器中,那么也可以创建包含三个container的pod。

  创建pod资源的流程,如下图所示:

第一步:用户通过kubectl或其他API客户端提交Pod Spec给API Server

第二步:API Server 尝试着将Pod对象的相关信息存入到etcd中,待写入操作执行完成,API Server即会返回确认信息至客户端。

第三步:API Server开始反映etcd中的状态变化

第四步:所有kubernetes组件均使用“watch”机制来跟踪检查API Server上相关的变动

第五步:kube-scheduler 通过其“watcher”察觉到API Server创建了新的Pod对象但尚未绑定到任何工作节点

第六步:kube-scheduler为pod对象挑选一个工作节点并将结果信息更新至API Server

第七步:调度结果信息由API Server更新至etcd存储系统,而且API Server也开始反映此Pod对象的调度结果

第八步:Pod被调度到的目标工作节点上的kubelet尝试在当前节点上调用docker启动容器,并将容器的结果状态回送至API Server

第九步:API Server将pod状态信息存入etcd系统中

第十步:在etcd确认写入操作成功完成后,API Server将确认信息发送至相关的kubelet,事件将通过它被接受。

3. pod生命周期中的重要行为

  除了创建应用容器(主容器机器辅助容器)之外,用户还可以为pod对象定义其生命周期中的多种行为,如初始化容器,存活性探测及就绪性探测等。

3.1 初始化容器

  初始化容器的官方地址:https://kubernetes.io/docs/concepts/workloads/pods/init-containers/#init-containers-in-use

  Init Container就是用来做初始化工作的容器,可以是一个或者多个,如果有多个的话,这些容器会按定义的顺序依次执行,只有所有的Init Container执行完后,主容器才会被启动。

  一个Pod里面的所有容器是共享数据卷和网络命名空间的,所以Init Container里面产生的数据可以被主容器使用到的。

  Init容器与普通的容器区别是:

  1)Init 容器不支持 Readiness,因为它们必须在Pod就绪之前运行完成

  2)每个Init容器必须运行成功,下一个才能够运行

  3)如果 Pod 的 Init 容器失败,Kubernetes 会不断地重启该 Pod,直到 Init 容器成功为止,然而,如果Pod对应的restartPolicy值为 Never,它不会重新启动。

  Init Container主要是来做初始化容器工作的,那么它有哪些应用场景呢:

  1)用于运行特定的工具程序,处于安全等方面的原因,这些程序不适于包含在主容器镜像中。

  2)提供主容器镜像中不具备的工具程序或自定义代码

  3)为容器镜像的构架和部署人员提供了分离、独立工作的途径,使得他们不必协同起来制作单个镜像文件。

  4)初始化容器和主容器处于不同的文件系统视图中,因此可以分别安全的使用敏感数据,例如Secrets资源

  5)初始化容器要先于主容器串行启动并运行完成,因此可用于延后应用容器的启动直至其依赖的条件得到满足。

演示服务依赖的场景下初始化容器的使用方法,如下Pod的定义方法

[root@k8s-master1 pod]# vim init.yaml
You have new mail in /var/spool/mail/root
[root@k8s-master1 pod]# cat init.yaml
apiVersion: v1
kind: Pod
metadata:
  name: myapp-pod
  labels:
    app: myapp
spec:
  containers:
  - name: myapp-container
    image: busybox:1.28
    imagePullPolicy: IfNotPresent
    command: ['sh', '-c', 'echo The app is running! && sleep 3600']
  initContainers:
  - name: init-myservice
    image: busybox:1.28
    imagePullPolicy: IfNotPresent
    command: ['sh', '-c', "until nslookup myservice.$(cat /var/run/secrets/kubernetes.io/serviceaccount/namespace).svc.cluster.local; do echo waiting for myservice; sleep 2; done"]
  - name: init-mydb
    image: busybox:1.28
    imagePullPolicy: IfNotPresent
    command: ['sh', '-c', "until nslookup mydb.$(cat /var/run/secrets/kubernetes.io/serviceaccount/namespace).svc.cluster.local; do echo waiting for mydb; sleep 2; done"]

Service的对应YAML内容:

[root@k8s-master1 pod]# vim service.yaml
[root@k8s-master1 pod]# cat service.yaml
---
apiVersion: v1
kind: Service
metadata:
  name: myservice
spec:
  ports:
  - protocol: TCP
    port: 80
    targetPort: 9376
---
apiVersion: v1
kind: Service
metadata:
  name: mydb
spec:
  ports:
  - protocol: TCP
    port: 80
    targetPort: 9377

  先创建上面的Pod,然后查看下Pod的状态,然后再创建下面的Service,对比下前后状态

[root@k8s-master1 pod]# kubectl apply -f init.yaml
pod/myapp-pod created
You have new mail in /var/spool/mail/root
[root@k8s-master1 pod]# kubectl get pod -o wide
NAME        READY   STATUS     RESTARTS   AGE   IP             NODE        NOMINATED NODE   READINESS GATES
myapp-pod   0/1     Init:0/2   0          7s    10.244.36.85   k8s-node1   <none>           <none>

 pod处于Init状态,更新service资源清单

[root@k8s-master1 pod]# kubectl apply -f service.yaml
service/myservice created
service/mydb created
[root@k8s-master1 pod]# kubectl get svc -o wide
NAME         TYPE        CLUSTER-IP      EXTERNAL-IP   PORT(S)          AGE   SELECTOR
kubernetes   ClusterIP   10.96.0.1       <none>        443/TCP          28d   <none>
mydb         ClusterIP   10.96.64.149    <none>        80/TCP           9s    <none>
myservice    ClusterIP   10.96.241.154   <none>        80/TCP           9s    <none>
tomcat       NodePort    10.103.38.162   <none>        8080:30080/TCP   28d   app=myapp,env=dev
[root@k8s-master1 pod]# kubectl get pod -o wide
NAME        READY   STATUS     RESTARTS   AGE   IP             NODE        NOMINATED NODE   READINESS GATES
myapp-pod   0/1     Init:0/2   0          52s   10.244.36.85   k8s-node1   <none>           <none>
[root@k8s-master1 pod]# kubectl get pod -o wide
NAME        READY   STATUS    RESTARTS   AGE   IP             NODE        NOMINATED NODE   READINESS GATES
myapp-pod   1/1     Running   0          74s   10.244.36.85   k8s-node1   <none>           <none>

  在所有的初始化容器没有成功之前,Pod将不会变成running状态。

[root@k8s-master1 pod]# kubectl describe pod myapp-pod
Name:         myapp-pod
Namespace:    default
Priority:     0
Node:         k8s-node1/10.0.0.132
Start Time:   Mon, 29 Aug 2022 23:17:41 +0800
Labels:       app=myapp
Annotations:  cni.projectcalico.org/podIP: 10.244.36.85/32
              cni.projectcalico.org/podIPs: 10.244.36.85/32
Status:       Running
IP:           10.244.36.85
IPs:
  IP:  10.244.36.85
Init Containers:
  init-myservice:
    Container ID:  docker://45e0a8d562738fbee853e18cc476df87e21e2ade49a16b0471d5258a125854f0
    Image:         busybox:1.28
    Image ID:      docker://sha256:8c811b4aec35f259572d0f79207bc0678df4c736eeec50bc9fec37ed936a472a
    Port:          <none>
    Host Port:     <none>
    Command:
      sh
      -c
      until nslookup myservice.$(cat /var/run/secrets/kubernetes.io/serviceaccount/namespace).svc.cluster.local; do echo waiting for myservice; sleep 2; done
    State:          Terminated
      Reason:       Completed
      Exit Code:    0
      Started:      Mon, 29 Aug 2022 23:17:44 +0800
      Finished:     Mon, 29 Aug 2022 23:18:47 +0800
    Ready:          True
    Restart Count:  0
    Environment:    <none>
    Mounts:
      /var/run/secrets/kubernetes.io/serviceaccount from default-token-5n29f (ro)
  init-mydb:
    Container ID:  docker://9c2c14804368491c536032deb088784e017f7832ed47111c9316b30697ee3df6
    Image:         busybox:1.28
    Image ID:      docker://sha256:8c811b4aec35f259572d0f79207bc0678df4c736eeec50bc9fec37ed936a472a
    Port:          <none>
    Host Port:     <none>
    Command:
      sh
      -c
      until nslookup mydb.$(cat /var/run/secrets/kubernetes.io/serviceaccount/namespace).svc.cluster.local; do echo waiting for mydb; sleep 2; done
    State:          Terminated
      Reason:       Completed
      Exit Code:    0
      Started:      Mon, 29 Aug 2022 23:18:48 +0800
      Finished:     Mon, 29 Aug 2022 23:18:48 +0800
    Ready:          True
    Restart Count:  0
    Environment:    <none>
    Mounts:
      /var/run/secrets/kubernetes.io/serviceaccount from default-token-5n29f (ro)
Containers:
  myapp-container:
    Container ID:  docker://be6b71d2925901e1e50c9a7d87292d45689bfa2cf668f7cf5feedbe4243ebfd9
    Image:         busybox:1.28
    Image ID:      docker://sha256:8c811b4aec35f259572d0f79207bc0678df4c736eeec50bc9fec37ed936a472a
    Port:          <none>
    Host Port:     <none>
    Command:
      sh
      -c
      echo The app is running! && sleep 3600
    State:          Running
      Started:      Mon, 29 Aug 2022 23:18:49 +0800
    Ready:          True
    Restart Count:  0
    Environment:    <none>
    Mounts:
      /var/run/secrets/kubernetes.io/serviceaccount from default-token-5n29f (ro)
Conditions:
  Type              Status
  Initialized       True
  Ready             True
  ContainersReady   True
  PodScheduled      True
Volumes:
  default-token-5n29f:
    Type:        Secret (a volume populated by a Secret)
    SecretName:  default-token-5n29f
    Optional:    false
QoS Class:       BestEffort
Node-Selectors:  <none>
Tolerations:     node.kubernetes.io/not-ready:NoExecute op=Exists for 300s
                 node.kubernetes.io/unreachable:NoExecute op=Exists for 300s
Events:
  Type    Reason     Age    From               Message
  ----    ------     ----   ----               -------
  Normal  Scheduled  4m15s  default-scheduler  Successfully assigned default/myapp-pod to k8s-node1
  Normal  Pulled     4m13s  kubelet            Container image "busybox:1.28" already present on machine
  Normal  Created    4m13s  kubelet            Created container init-myservice
  Normal  Started    4m12s  kubelet            Started container init-myservice
  Normal  Pulled     3m8s   kubelet            Container image "busybox:1.28" already present on machine
  Normal  Created    3m8s   kubelet            Created container init-mydb
  Normal  Started    3m8s   kubelet            Started container init-mydb
  Normal  Pulled     3m7s   kubelet            Container image "busybox:1.28" already present on machine
  Normal  Created    3m7s   kubelet            Created container myapp-container
  Normal  Started    3m7s   kubelet            Started container myapp-container

  可以看到在Pod启动过程中,初始化容器会按顺序启动。每个容器必须在下一个容器启动之前成功退出。

3.2 Pod Hook

  容器生命周期钩子使它能够感知其自身生命周期管理中的事件,并在相应的时间到来时运行由用户指定的处理程序代码。

  Pod Hook 是由 kubelet 发起的,当容器中的进程启动前或者容器中的进程终止之前运行,这是包含在容器的生命周期之中。可以同时为 Pod 中的所有容器都配置 hook。

  Kubernetes 提供了两种钩子函数:

  PostStart:在容器创建完成后立即触发,通知容器它已经被创建。但是,并不能保证钩子将在容器ENTRYPOINT之前运行,因为没有参数传递给处理程序。主要用于资源部署、环境准备等。不过需要注意的是如果钩子花费太长时间以至于不能运行或者挂起, 容器将不能达到running状态。如果该钩子对应的hook handler执行失败,则该容器会被杀死,并根据该容器的重启策略决定是否要重启该容器,这个钩子不需要传递任何参数

  PreStop:该钩子在容器被删除前触发,其所对应的hook handler必须在删除该容器的请求发送给Docker daemon之前完成。在该钩子对应的hook handler完成后不论执行的结果如何,Docker daemon会发送一个SGTERN信号量给Docker daemon来删除该容器。它以同步的方式调用, 所以在其完成之前会阻塞删除容器的操作。主要用于优雅关闭应用程序、通知其他系统等。如果钩子在执行期间挂起, Pod阶段将停留在running状态并且永不会达到failed状态。

  如果PostStart或者PreStop钩子失败, 它会杀死容器。所以应该让钩子函数尽可能的轻量。当然有些情况下,长时间运行命令是合理的, 比如在停止容器之前预先保存状态。

  钩子处理器的实现方式有“Exec” 和“HTTP”两种方式:

  Exec - 用于执行一段特定的命令,不过要注意的是该命令消耗的资源会被计入容器。即在钩子事件触发时直接在当前容器中运行由用户定义的命令。
  HTTP - 对容器上的特定的端点执行HTTP请求,即是在当前容器中向某URL发起HTTP请求。

演示postStart和preStop示例如下:

......
containers:
- image: sample:v2  
     name: war
     lifecycle:
      postStart:
       exec:
         command:
          - "cp"
          - "/sample.war"
          - "/app"
      prestop:
       httpGet:
        host: monitor.com
        path: /waring
        port: 8080
        scheme: HTTP
......

  以上示例定义了一个Pod,包含一个JAVA的web应用容器,其中设置了PostStart和PreStop回调函数。即在容器创建成功后,复制/sample.war到/app文件夹中。而在容器终止之前,发送HTTP请求到http://monitor.com:8080/waring,即向监控系统发送警告。

4. 容器的重启策略

  Pod的重启策略(RestartPolicy)应用于Pod内的所有容器,而且它仅用于控制在同一个节点上的重新启动pod对象的相关容器。当某个容器异常退出或者健康检查失败时,kubelet将根据 RestartPolicy 的设置来进行相应的操作。

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

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

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

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

  注意:首次需要重启的容器,将在其需要时立即进行重启,随后再次需要重启的操作将由kubelet延迟一段时间后进行,且反复的重启操作的延迟时长依次为10秒,20秒,40秒,80秒,160秒和300秒,300秒是最大延迟时长。事实上,一旦绑定到一个节点,pod对象将永远不会被重新绑定到另外一个节点,它要么被重启,要么终止,直至节点发生故障或被删除。

[root@k8s-master1 pod]# cat demo-pod.yaml
apiVersion: v1
kind: Pod
metadata:
  name: pod-test
  namespace: default
  labels:
    app: myapp
    env: dev
spec:
  restartPolicy: Always
  containers:
  - name:  pod-test
    ports:
    - containerPort: 80
    image: nginx:latest
    imagePullPolicy: IfNotPresent
[root@k8s-master1 pod]# kubectl apply -f demo-pod.yaml
pod/pod-test created
[root@k8s-master1 pod]# kubectl get pods
NAME       READY   STATUS    RESTARTS   AGE
pod-test   1/1     Running   0          5s

5. Pod的终止过程

  Pod对象代表了在kubernetes集群节点上运行的进程,它可能曾用于处理生产数据或向用户提供服务等,于是,当pod本身不再具有存在价值时,如何将其优雅的终止就非常重要了,而用户也需要能够在正常提交删除操作后可以获知其何时开始终止并最终完成。

  操作中,当用户提交删除请求后,系统就会进行强制删除操作的宽限期倒计时,并将TERM信息发送给pod对象的每个容器中的主进程。宽限期倒计时结束后,这些进程将收到强制终止的KILL信号,pod对象随即也将由API Server删除。如果在等待进程终止的过程中,kubelet或容器管理器发生了重启,那么终止操作会重新获得一个满额的删除宽限期并重新执行删除操作。

  1)用户发送删除pod对象的命令

  2)API服务器中的pod对象会随时间的推移而更新,在宽限期内(默认30秒)pod被视为“dead”

  3)将pod标记为“Terminating”状态

  4)(与第3步同时运行)kubelet在监控到pod对象转为“Terminating”状态的同时启动pod关闭过程

  5)(与第3步同时运行)端点控制器监控到pod对象的关闭行为时将其从所有匹配到此端点的Service资源的端点列表中移除

  6)如果当前pod对象定义了preStop钩子处理器,则在器标记为“terminating”后即会以同步的方式启动执行;若宽限期结束后,preStop仍未执行结束,则第2步会被重新执行并额外获取一个时长为2秒的小宽限期。

  7)pod对象中的容器进程收到TERM信号

  8)宽限期结束后,若存在任何一个仍在运行的进程,那么pod对象即会收到SIGKILL信号

  9)kubelet请求API Server将此pod资源的宽限期设置为0从而完成删除操作,它变得对用户不再可见。

  默认情况下,所有删除操作的宽限期都是30秒。不过,kubectl delete命令可以通过使用“--grace-period=<seconds>”选项自定义时长,若使用0表示直接强制删除指定的资源,不过,此时需要同时为命令使用“--force”选项。

三、编写yaml文件的方法

        创建pod资源的yaml文件

  通过kubectl explain 查看定义Pod资源包含哪些字段。

[root@k8s-master1 pod]# kubectl explain pod
KIND:     Pod
VERSION:  v1

DESCRIPTION:
     Pod is a collection of containers that can run on a host. This resource is
     created by clients and scheduled onto hosts.

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>
     Specification of the desired behavior of the pod. More info:
     https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#spec-and-status

   status       <Object>
     Most recently observed status of the pod. This data may not be up to date.
     Populated by the system. Read-only. More info:
     https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#spec-and-status

  查看pod.metadata字段如何定义

[root@k8s-master1 pod]# kubectl explain pod.metadata

  查看pod.spec字段如何定义

[root@k8s-master1 pod]# kubectl explain pod.spec

  查看pod.spec.containers字段如何定义

[root@k8s-master1 pod]# kubectl explain pod.spec.containers

  查看pod.spec.container.ports字段如何定义

[root@k8s-master1 pod]# kubectl explain pod.spec.containers.ports

四、pod资源清单详情说明

apiVersion: v1       #版本号,例如v1
kind: Pod       #资源类型,如Pod
metadata:       #元数据
  name: string       # Pod名字
  namespace: string    # Pod所属的命名空间
  labels:      #自定义标签
    - name: string     #自定义标签名字
  annotations:       #自定义注释列表
    - name: string
spec:         # Pod中容器的详细定义
  containers:      # Pod中容器列表
  - name: string     #容器名称
    image: string    #容器的镜像名称
    imagePullPolicy: [Always | Never | IfNotPresent] #获取镜像的策略 Alawys表示下载镜像 IfnotPresent表示优先使用本地镜像,否则下载镜像,Nerver表示仅使用本地镜像
    command: [string]    #容器的启动命令列表,如不指定,使用打包时使用的启动命令
    args: [string]     #容器的启动命令参数列表
    workingDir: string     #容器的工作目录
    volumeMounts:    #挂载到容器内部的存储卷配置
    - name: string     #引用pod定义的共享存储卷的名称,需用volumes[]部分定义的的卷名
      mountPath: string    #存储卷在容器内mount的绝对路径,应少于512字符
      readOnly: boolean    #是否为只读模式
    ports:       #需要暴露的端口库号
    - name: string     #端口号名称
      containerPort: int   #容器需要监听的端口号
      hostPort: int    #容器所在主机需要监听的端口号,默认与Container相同
      protocol: string     #端口协议,支持TCP和UDP,默认TCP
    env:       #容器运行前需设置的环境变量列表
    - name: string     #环境变量名称
      value: string    #环境变量的值
    resources:       #资源限制和请求的设置
      limits:      #资源限制的设置
        cpu: string    #cpu的限制,单位为core数
        memory: string     #内存限制,单位可以为Mib/Gib
      requests:      #资源请求的设置
        cpu: string    #cpu请求,容器启动的初始可用数量
        memory: string     #内存请求,容器启动的初始可用内存
    livenessProbe:     #对Pod内个容器健康检查的设置,当探测无响应几次后将自动重启该容器,检查方法有exec、httpGet和tcpSocket,对一个容器只需设置其中一种方法即可
      exec:      #对Pod容器内检查方式设置为exec方式
        command: [string]  #exec方式需要制定的命令或脚本
      httpGet:       #对Pod内个容器健康检查方法设置为HttpGet,需要制定Path、port
        path: string
        port: number
        host: string
        scheme: string
        HttpHeaders:
        - name: string
          value: string
      tcpSocket:     #对Pod内个容器健康检查方式设置为tcpSocket方式
         port: number
       initialDelaySeconds: 0  #容器启动完成后首次探测的时间,单位为秒
       timeoutSeconds: 0   #对容器健康检查探测等待响应的超时时间,单位秒,默认1秒
       periodSeconds: 0    #对容器监控检查的定期探测时间设置,单位秒,默认10秒一次
       successThreshold: 0
       failureThreshold: 0
       securityContext:
         privileged:false
    restartPolicy: [Always | Never | OnFailure]   #Pod的重启策略,Always表示一旦不管以何种方式终止运行,kubelet都将重启,OnFailure表示只有Pod以非0退出码退出才重启,Nerver表示不再重启该Pod
    nodeSelector: obeject  #设置NodeSelector表示将该Pod调度到包含这个label的node上,以key:value的格式指定
    imagePullSecrets:    #Pull镜像时使用的secret名称,以key:secretkey格式指定
    - name: string
    hostNetwork:false      #是否使用主机网络模式,默认为false,如果设置为true,表示使用宿主机网络
    volumes:       #在该pod上定义共享存储卷列表
    - name: string     #共享存储卷名称 (volumes类型有很多种)
      emptyDir: {}     #类型为emtyDir的存储卷,与Pod同生命周期的一个临时目录。为空值
      hostPath: string     #类型为hostPath的存储卷,表示挂载Pod所在宿主机的目录
        path: string     #Pod所在宿主机的目录,将被用于同期中mount的目录
      secret:      #类型为secret的存储卷,挂载集群与定义的secre对象到容器内部
        scretname: string 
        items:    
        - key: string
          path: string
      configMap:     #类型为configMap的存储卷,挂载预定义的configMap对象到容器内部
        name: string
        items:
        - key: string
          path: string

  

posted @ 2022-08-28 22:23  出水芙蓉·薇薇  阅读(269)  评论(0编辑  收藏  举报