千家信息网

docker中pod生命周期的示例分析

发表于:2024-11-11 作者:千家信息网编辑
千家信息网最后更新 2024年11月11日,这篇文章给大家分享的是有关docker中pod生命周期的示例分析的内容。小编觉得挺实用的,因此分享给大家做个参考,一起跟随小编过来看看吧。查看资源配置清单帮助[root@master manifest
千家信息网最后更新 2024年11月11日docker中pod生命周期的示例分析

这篇文章给大家分享的是有关docker中pod生命周期的示例分析的内容。小编觉得挺实用的,因此分享给大家做个参考,一起跟随小编过来看看吧。

查看资源配置清单帮助

[root@master manifests]# kubectl explain pods.spec.containers #查看帮助

资源配置清单分类

自主式pod资源:

资源的清单格式:

一级字段:apiVersion(group/version组成),kind,metadata(包括name,namespace,labels,annotations),spec ,status。

pod资源-spec.containers

- name:pod名字

image:镜像名字

imagePullPolicy:表示从哪拉镜像,Always(不管本地有没有镜像,都要从仓库中下载镜像,也就是说,即使本地有镜像了,也不使用本地镜像,而是从仓库下载), Never(从来不从仓库下载镜像,也就是说本地有镜像就用,没有就算了), IfNotPresent(如果本地存在就直接使用,不存在才从仓库下载)。默认的策略是:当镜像标签版本是latest,默认策略就是Always;如果指定特定版本默认拉取策略就是IfNotPresent。


如上图,指定ImagePullPolicy策略为ifNotPresent后,即使image指定的版本未latest,这样每次启动容器,也不会从仓库重新下载镜像了。

ports:指定暴露容器端口号,可以指定多个端口,如下:

[root@master manifests]# cat pod-demo.yaml apiVersion: v1kind: Podmetadata:  name: pod-demo  namespace: default  labels:    app: myapp  #kv格式的,也可以用花括号表示    tier: frontend #定义所属的层次spec:  containers:   - name: myapp  #前面的-号表示这是一个列表格式的,也可以用中括号表示    image: tomcat     ports:    - name: http      containerPort: 80    - name: https      containerPort: 443  - name: busybox    image: busybox:latest    imagePullPolicy: IfNotPresent #指定ImagePullPolicy策略为ifNotPresent后,即使image指定的版本未latest,以后每次启动容器,也不会从仓库重新下载镜像了    command:    - "/bin/sh"    - "-c"    - "echo $(date) >> /usr/share/nginx/html/index.html; sleep 5"   #以上命令也可以写作:command: ["/bin/sh","-c","sleep 3600"]

args:相当于dockerfile里面的cmd

command:相当于docker里面的Entrypoint

如果既没有指定args,也没有指定command,那么会默认使用dockfile的cmd和entrypoint。

如果指定了command,但没有提供args,那么就直接运行command。

如果指定了args,但是没指定command,那么将使用镜像中的entrypoint命令,把我们写的args当做参数传递给镜像中的entrypoint。

如果既用来command,又用了args,那么镜像中的cmd和entrypoint将被忽略,而使用K8s提供的command with args。

参考文档:https://kubernetes.io/docs/tasks/inject-data-application/define-command-argument-container/

标签

标签是k8s极具特色的管理方式。一个标签可以对应多个资源,一个资源也可以有多个标签,它们是多对多的关系。

一个资源拥有多个标签,可以实现不同维度的管理。

标签是key=value格式的,key最大63个字符,只能是字母、数字、_、-、.五种类型的组合。只能以字母或数字开头结尾。

我们也可以使用标签选择器来指定能使用哪些标签。

可以使用如下命令看标签:

[root@master manifests]# kubectl get pods --show-labelsNAME                          READY     STATUS             RESTARTS   AGE       LABELSpod-demo                      1/2       CrashLoopBackOff   24         1h        app=myapp,tier=frontend

可以用-l来过滤包含app标签的pod

[root@master manifests]# kubectl get pods -l app --show-labelsNAME       READY     STATUS             RESTARTS   AGE       LABELSpod-demo   1/2       CrashLoopBackOff   25         1h        app=myapp,tier=frontend

给资源对象打标签,我们再给前面创建的pod-demo pod打个release=canary的标签:

[root@master manifests]# kubectl label pods pod-demo release=canarypod/pod-demo labeled
[root@master manifests]# kubectl get pods -l app --show-labelsNAME       READY     STATUS             RESTARTS   AGE       LABELSpod-demo   1/2       CrashLoopBackOff   27         1h        app=myapp,release=canary,tier=frontend

修改标签的值:

[root@master manifests]# kubectl label pods pod-demo release=stable --overwritepod/pod-demo labeled
[root@master manifests]# kubectl get pods -l app --show-labelsNAME       READY     STATUS             RESTARTS   AGE       LABELSpod-demo   1/2       CrashLoopBackOff   27         1h        app=myapp,release=stable,tier=frontend

查找既有release标签,又拥有app标签的:

[root@master manifests]# kubectl get pods -l app,release --show-labelsNAME       READY     STATUS             RESTARTS   AGE       LABELSpod-demo   1/2       CrashLoopBackOff   27         2h        app=myapp,release=stable,tier=frontend

标签选择器分为:等值关系的标签选择器和集合关系的标签选择器。

等值关系的标签选择器:可以用=或者==表示等于,!=表示不等于:

[root@master manifests]# kubectl get pods -l release=stable --show-labelsNAME       READY     STATUS             RESTARTS   AGE       LABELSpod-demo   1/2       CrashLoopBackOff   29         2h        app=myapp,release=stable,tier=frontend
[root@master manifests]# kubectl get pods -l release=stable,app=myapp --show-labelsNAME       READY     STATUS             RESTARTS   AGE       LABELSpod-demo   1/2       CrashLoopBackOff   30         2h        app=myapp,release=stable,tier=frontend
[root@master manifests]# kubectl get pods -l release!=stable --show-labelsNAME                          READY     STATUS             RESTARTS   AGE       LABELSclient                        1/1       Running            0          1d        run=clientmyapp-fcc5f7f7c-4x2p7         0/1       ImagePullBackOff   0          1d        pod-template-hash=977193937,run=myappmyapp-fcc5f7f7c-dnkdq         0/1       ImagePullBackOff   0          1d        pod-template-hash=977193937,run=myappmytomcat-5f8c6fdcb-7t5s2      1/1       Running            0          1d        pod-template-hash=194729876,run=mytomcatmytomcat-5f8c6fdcb-lhcsc      1/1       Running            0          1d        pod-template-hash=194729876,run=mytomcatmytomcat-5f8c6fdcb-rntrg      1/1       Running            0          1d        pod-template-hash=194729876,run=mytomcatnginx-deploy-5b595999-fpm8x   1/1       Running            0          1d        pod-template-hash=16151555,release=canary,run=nginx-deploy

集合关系的标签选择器:key in (value1,value2...),key notin (value1,value2...),!key

[root@master ~]# kubectl get pods -l "release in (canary,beta,alpha)" --show-labelsNAME                          READY     STATUS    RESTARTS   AGE       LABELSnginx-deploy-5b595999-fpm8x   1/1       Running   0          1d        pod-template-hash=16151555,release=canary,run=nginx-deploy
[root@master ~]# kubectl get pods -l "release notin (canary,beta,alpha)" --show-labelsNAME                       READY     STATUS             RESTARTS   AGE       LABELSclient                     1/1       Running            0          1d        run=clientmyapp-fcc5f7f7c-4x2p7      0/1       ImagePullBackOff   0          1d        pod-template-hash=977193937,run=myappmyapp-fcc5f7f7c-dnkdq      0/1       ImagePullBackOff   0          1d        pod-template-hash=977193937,run=myapp

我们知道pod控制器和service都是要通过标签来进行关联,通常使用matchLabels,matchExpressions。许多资源支持内嵌字段定义其使用的标签选择器。

matchLabels:直接给定键值,相当于使用等值关系一样;

matchExpressions:基于给定的表达式来定义使用标签选择器,格式为{key!"KEY",operator:"OPERATOR",values:[VAL1,VAL2,....]},常用的操作符有:

1)In,NotIn,:values字段的值必须为非空列表

2)Exists,NotExists:values字段的值必须为空列表

不光pods有标签,nodes等对象都有标签,如下:

[root@master ~]# kubectl get nodes --show-labelsNAME      STATUS    ROLES     AGE       VERSION   LABELSmaster    Ready     master    4d        v1.11.2   beta.kubernetes.io/arch=amd64,beta.kubernetes.io/os=linux,kubernetes.io/hostname=master,node-role.kubernetes.io/master=node1     Ready         4d        v1.11.2   beta.kubernetes.io/arch=amd64,beta.kubernetes.io/os=linux,kubernetes.io/hostname=node1node2     Ready         4d        v1.11.2   beta.kubernetes.io/arch=amd64,beta.kubernetes.io/os=linux,kubernetes.io/hostname=node2

上面的标签是内建的标签,其中beta.kubernetes.io这部分是能在dns中解析的,该部分字符长度不能超过253个字符。

同样,我们也可以给nodes打标签,比如我们下面给node1节点打个disktype=ssd的标签

[root@master ~]# kubectl label nodes node1 disktype=ssdnode/node1 labeled
[root@master ~]# kubectl get nodes --show-labelsNAME      STATUS    ROLES     AGE       VERSION   LABELSmaster    Ready     master    4d        v1.11.2   beta.kubernetes.io/arch=amd64,beta.kubernetes.io/os=linux,kubernetes.io/hostname=master,node-role.kubernetes.io/master=node1     Ready         4d        v1.11.2   beta.kubernetes.io/arch=amd64,beta.kubernetes.io/os=linux,disktype=ssd,kubernetes.io/hostname=node1node2     Ready         4d        v1.11.2   beta.kubernetes.io/arch=amd64,beta.kubernetes.io/os=linux,kubernetes.io/hostname=node2

节点选择器-nodeSelector和nodeName

nodeSelector:可以使pod运行在指定的node节点上,我们如下举例演示该功能。

[root@master ~]# kubectl get pods -o wideNAME                          READY     STATUS             RESTARTS   AGE       IP            NODEclient                        1/1       Running            0          2d        10.244.2.4    node2myapp-fcc5f7f7c-4x2p7         0/1       ImagePullBackOff   0          1d        10.244.1.9    node1myapp-fcc5f7f7c-dnkdq         0/1       ImagePullBackOff   0          1d        10.244.2.6    node2mytomcat-5f8c6fdcb-7t5s2      1/1       Running            0          1d        10.244.2.8    node2mytomcat-5f8c6fdcb-lhcsc      1/1       Running            0          1d        10.244.2.7    node2mytomcat-5f8c6fdcb-rntrg      1/1       Running            0          1d        10.244.1.10   node1nginx-deploy-5b595999-fpm8x   1/1       Running            0          1d        10.244.1.7    node1pod-demo                      1/2       CrashLoopBackOff   303        1d        10.244.2.11   node2

上面我们看到pod-demo运行在node2节点上,下面我们让它运行在node1节点上。我们刚才在node1上打了个disktype=ssd的标签,所以我们用nodeSelector在资源清单中如下定义:

[root@master manifests]# cat pod-demo.yaml apiVersion: v1kind: Podmetadata:  name: pod-demo  namespace: default  labels:    app: myapp  #kv格式的,也可以用花括号表示    tier: frontend #定义所属的层次spec:  containers:   - name: myapp  #前面的-号表示这是一个列表格式的,也可以用中括号表示    image: tomcat     ports:    - name: http      containerPort: 80    - name: https      containerPort: 443  - name: busybox    image: busybox:latest    imagePullPolicy: IfNotPresent #指定ImagePullPolicy策略为ifNotPresent后,即使image指定的版本未latest,以后每次启动容器,也不会从仓库重新下载镜像了    command:    - "/bin/sh"    - "-c"    - "echo $(date) >> /usr/share/nginx/html/index.html; sleep 5"   #以上命令也可以写作:command: ["/bin/sh","-c","sleep 3600"]  nodeSelector: #指定该pod运行在有disktype=ssd标签的node节点上    disktype: ssd
[root@master manifests]# kubectl delete -f pod-demo.yaml pod "pod-demo" deleted
[root@master manifests]# kubectl create  -f pod-demo.yaml pod/pod-demo created
[root@master manifests]# kubectl get pods -o wideNAME                          READY     STATUS             RESTARTS   AGE       IP            NODEclient                        1/1       Running            0          2d        10.244.2.4    node2myapp-fcc5f7f7c-4x2p7         0/1       ImagePullBackOff   0          1d        10.244.1.9    node1myapp-fcc5f7f7c-dnkdq         0/1       ImagePullBackOff   0          1d        10.244.2.6    node2mytomcat-5f8c6fdcb-7t5s2      1/1       Running            0          1d        10.244.2.8    node2mytomcat-5f8c6fdcb-lhcsc      1/1       Running            0          1d        10.244.2.7    node2mytomcat-5f8c6fdcb-rntrg      1/1       Running            0          1d        10.244.1.10   node1nginx-deploy-5b595999-fpm8x   1/1       Running            0          1d        10.244.1.7    node1pod-demo                      2/2       Running            2          37s       10.244.1.14   node1

上面看到,pod-demo运行在了带有disktype=ssd标签的node1节点上了。

那么有人可能会问了,我们可不可以指定pod-demo运行在指定node上呢。当然可以了,这个选项就是nodeName。大家可以自定去测试。

资源注解annotations

与labels的区别是,annotaitons不能用于挑选资源对象,仅用于为对象提供原数据。这些元数据可能被某些程序所用到,而且很重要。annotations的键值对没有字符数限制。

查看资源的注解:

[root@master manifests]# kubectl delete -f pod-demo.yaml pod "pod-demo" deleted
[root@master manifests]# cat cat pod-demo.yaml cat: cat: No such file or directoryapiVersion: v1kind: Podmetadata:  name: pod-demo  namespace: default  labels:    app: myapp  #kv格式的,也可以用花括号表示    tier: frontend #定义所属的层次  annotations:    chenzx.com/created-by: "cluster-admin" #这是注解的键值对spec:  containers:   - name: myapp  #前面的-号表示这是一个列表格式的,也可以用中括号表示    image: tomcat     ports:    - name: http      containerPort: 80    - name: https      containerPort: 443  - name: busybox    image: busybox:latest    imagePullPolicy: IfNotPresent #指定ImagePullPolicy策略为ifNotPresent后,即使image指定的版本未latest,以后每次启动容器,也不会从仓库重新下载镜像了    command:    - "/bin/sh"    - "-c"    - "echo $(date) >> /usr/share/nginx/html/index.html; sleep 5"   #以上命令也可以写作:command: ["/bin/sh","-c","sleep 3600"]  nodeSelector: #指定该pod运行在有disktype=ssd标签的node节点上    disktype: ssd
[root@master manifests]# kubectl create -f pod-demo.yaml pod/pod-demo created
[root@master manifests]# kubectl describe pods pod-demoAnnotations:        chenzx.com/created-by=cluster-adminStatus:             RunningIP:                 10.244.1.15

pod的生命周期

一个容器里面可以运行多个进程,但是通常我们只在容器里面运行一个进程。

在一个pod中,可以运行多个容器,但是通常我们只在一个pod里面运行一个容器。

一个容器在创建之前,有多个初始化容器(init container)用来进行初始化环境,init container执行完,它就退出了。接下来是主容器(main container)开始启动,主容器启动时也要初始化主容器里面的环境。在主容器刚刚启动之后,用户可以手动嵌入做一个操作叫post start。在主容器结束前,也可以做一个收尾操作pre stop,用来在主容器结束前做一个清理。

在post start后,就开始做健康检查,第一个健康检查叫存活状态检查(liveness probe ),用来检查主容器存活状态的;第二个健康检查叫准备就绪检查(readyness probe),用来检查主容器是否启动就绪。

pod的状态有:

a) Pending:当启动一个容器时,发现条件不满足,就会进入pending状态;

b) Runing

c)Failed

d)Succeeded

e) Unknown;如果kubelete出现故障,那么apiserver就连不上kubelete了,就会出现未知的错误

创建pod的过程:pod创建时先和apiserver沟通,然后把信息存储在etcd中;接下来apiserver会请求scheduler,并把调度的结果也保存在etcd中。假如scheduler把pod调度到node1节点上了,此时node1节点上的kublete会从etcd中拿到用户创建的清单,根据清单在node1上运行这个pod。不管pod在node1上运行成功还是失败,都会把结果反馈给apiserver,同时把运行结果保存在etcd中。

健康检查分三个层次:1、直接执行命令;2、向tcp连接请求;3、向http发get请求。

总结:pod生命周期中的重要行为:

1)初始化容器

2)容器探测(liveness存活行探测和readness准备就绪探测)

livenessProbe(存活状态探测)

 存活不一定就绪。
[root@master manifests]# kubectl explain pods.spec.containers.livenessProbe

可以看到有三种探针,exec、 httpGet、tcpSocket

failureThreshold表示探测失败次数,默认是3探测次失败,才认为是真失败了。

periodSeconds:周期间隔时长,默认10s探测一次;

timeoutSeconds:超时时间,表示发出探测,对方始终没有响应,需要等多久,默认等1s

initialDelaySeconds:默认是容器一启动就开始探测,但是此时容器可能还没启动完呢,所以这时探测肯定是失败的。所以initialDelaySeconds表示容器启动多长时间后才开始探测。

[root@master manifests]# kubectl explain pods.spec.containers.livenessProbe.exec
[root@master manifests]# cat liveness.exec.ymal apiVersion: v1kind: Podmetadata:  name: liveness-exec-pod  namespace: defaultspec:  containers:  - name: liveness-exec-container    image: busybox:latest    imagePullPolicy: IfNotPresent #如果存在就不要下载了    command: ["/bin/sh","-c","touch /tmp/healthy;sleep 60;rm -f /tmp/healthy;sleep 3600"]    livenessProbe: #存活性探测      exec:         command: ["test","-e","/tmp/healthy"] #-e表示探测文件是否存在      initialDelaySeconds: 1 #表示容器启动后多长时间开始探测      periodSeconds: 3 #表示每隔3s钟探测一次
[root@master manifests]# kubectl create -f liveness.exec.ymal pod/liveness-exec-pod created
[root@master manifests]# kubectl get pods -wNAME                          READY     STATUS             RESTARTS   AGEliveness-exec-pod             1/1       Running            2          4m
[root@master manifests]# kubectl get pods -wNAME                          READY     STATUS             RESTARTS   AGEliveness-exec-pod             1/1       Running            4          6m
[root@master manifests]# kubectl get pods -wNAME                          READY     STATUS             RESTARTS   AGEclient                        1/1       Running            0          3dliveness-exec-pod             1/1       Running            5          9m
[root@master manifests]#  kubectl get pods -wNAME                          READY     STATUS             RESTARTS   AGEclient                        1/1       Running            0          3dliveness-exec-pod             1/1       Running            9          23m

可以看到restart此时在随着时间增长。

上面的例子是用exec执行命令进行探测的。

下面我们看看基于tcp和httpget探测的选项。

[root@master manifests]kubectl explain pods.spec.containers.livenessProbe.tcpSocket
[root@master manifests]# kubectl explain pods.spec.containers.livenessProbe.httpGet

下面举个例子:

[root@master manifests]# cat liveness.httpget.yaml apiVersion: v1kind: Podmetadata:  name: liveness-httpget-pod  namespace: defaultspec:  containers:  - name: liveness-httpget-container    image: nginx:latest    imagePullPolicy: IfNotPresent #如果存在就不要下载了    ports:    - name: http      containerPort: 80    livenessProbe: #存活性探测      httpGet:        port: http        path: /index.html      initialDelaySeconds: 1      periodSeconds: 3 #表示每隔3s钟探测一次
[root@master manifests]# kubectl  create -f liveness.httpget.yaml
[root@master manifests]# kubectl get podsNAME                          READY     STATUS             RESTARTS   AGEliveness-httpget-pod          1/1       Running            0          4m
[root@master manifests]# kubectl exec -it liveness-httpget-pod  -- /bin/sh# rm -rf  /usr/share/nginx/html/index.html
[root@master manifests]#  kubectl get podsNAME                          READY     STATUS             RESTARTS   AGEliveness-httpget-pod          1/1       Running            1          27m

上面可以看到,当删除pod里面的/usr/share/nginx/html/index.html,liveness监测到index.html文件被删除了,所以restarts次数为1,但是只重启一次,不会再重启了。这是因为重启一次后,nginx容器就重新初始化了,里面就会又生成index.html文件。所以里面就会有新的index.html文件了。

readlinessProbe(准备就绪型探针)

[root@master manifests]# cat  readiness-httpget.ymal apiVersion: v1kind: Podmetadata:  name: readdliness-httpget-pod  namespace: defaultspec:  containers:  - name: readliness-httpget-container    image: nginx:latest    imagePullPolicy: IfNotPresent #如果存在就不要下载了    ports:    - name: http      containerPort: 80    readinessProbe: #准备型探针      httpGet:        port: http        path: /index.html      initialDelaySeconds: 1      periodSeconds: 3 #表示每隔3s钟探测一次
[root@master manifests]# kubectl create -f readiness-httpget.ymal pod/readdliness-httpget-pod created
[root@master ~]# kubectl get podsNAME                          READY     STATUS             RESTARTS   AGEreaddliness-httpget-pod       1/1       Running            0          16h
[root@master ~]# kubectl exec -it readdliness-httpget-pod -- /bin/sh# rm -rf /usr/share/nginx/html/index.html
[root@master ~]# kubectl get podsNAME                          READY     STATUS             RESTARTS   AGEreaddliness-httpget-pod       0/1       Running            0          16h

上面可以看到,ready变成0/1了,但是status是runing的,这就是说nginx进程是在的,只是index.html不见了,可以判定nginx没有就绪。

postStart(启动后钩子)

[root@master ~]# kubectl  explain pods.spec.containers.lifecycle.postStart

postStart是指容器在启动之后立即执行的操作,如果执行操作失败了,容器将被终止并且重启。而重启与否是由重启策略。

[root@master manifests]# cat poststart-pod.yaml apiVersion: v1kind: Podmetadata:  name: poststart-pod  namespace: defaultspec:  containers:  - name: busybox-httpd    image: busybox:latest    imagePullPolicy: IfNotPresent    lifecycle: #生命周期事件      postStart:        exec:          command: ["mkdir", "-p","/data/web/html"] #这个command是定义postStart后的需要执行的命令    command: ["/bin/sh","-c","sleep 3600"] #这是定义容器里面执行的命令,不过这个命令要先于postStart里面的command    #args: ["-f","-h /data/web/html"]  #-f是前台,-h是家目录
[root@master manifests]# kubectl create -f poststart-pod.yaml pod/posttart-pod created

说明:删除的方法

[root@master manifests]# kubectl delete -f poststart-pod.yaml pod "posttart-pod" deleted
[root@master manifests]# kubectl get podsNAME                          READY     STATUS             RESTARTS   AGEpoststart-pod                 1/1       Running            0          3m
[root@master manifests]#  kubectl exec -it poststart-pod -- /bin/sh/ # ls /dataweb/ # ls /data/web/html/

上面看到在容器启动后,建立了/data/web/html目录。这就是postStart的用法。

preStop(终止之前钩子)

[root@master ~]# kubectl  explain pods.spec.containers.lifecycle.preStop

preStop是指容器在终止前要立即执行的命令,等这些命令执行完了,容器才能终止。

容器的重启策略-restartPolicy

一旦pod中的容器挂了,我们就把容器重启。

策略包括如下:

Always:表示容器挂了总是重启,这是默认策略

OnFailures:表容器状态为错误时才重启,也就是容器正常终止时才重启

Never:表示容器挂了不予重启

对于Always这种策略,容器只要挂了,就会立即重启,这样是很耗费资源的。所以Always重启策略是这么做的:第一次容器挂了立即重启,如果再挂了就要延时10s重启,第三次挂了就等20s重启...... 依次类推

容器的终止策略

k8s会给容器30s的时间进行终止,如果30s后还没终止,就会强制终止。

总结

pod:        apiVersion        kind        metadata        spec        status(只读)        spec:                containers                nodeSelector                nodeName                restartPolicy: Always,Never,OnFailure                containers:                        name                        image                        imagePullPolicy: Always、Never、IfNotPresent                        ports:                                name                                containerPort                        livenessProbe                        readinessProbe                        liftcycle                ExecAction: exec                TCPSocketAction: tcpSocket                HTTPGetAction: httpGet

感谢各位的阅读!关于"docker中pod生命周期的示例分析"这篇文章就分享到这里了,希望以上内容可以对大家有一定的帮助,让大家可以学到更多知识,如果觉得文章不错,可以把它分享出去让更多的人看到吧!

0