经验首页 前端设计 程序设计 Java相关 移动开发 数据库/运维 软件/图像 大数据/云计算 其他经验
当前位置:技术经验 » 数据库/运维 » Kubernetes » 查看文章
(五)Kubernetes Pod状态和生命周期管理别来无恙-
来源:cnblogs  作者:别来无恙-  时间:2019/11/5 14:49:27  对本文有异议

什么是Pod

Podkubernetes中你可以创建和部署的最小也是最简的单位。Pod代表着集群中运行的进程。

Pod中封装着应用的容器(有的情况下是好几个容器),存储、独立的网络IP,管理容器如何运行的策略选项。Pod代表着部署的一个单位:kubernetes中应用的一个实例,可能由一个或者多个容器组合在一起共享资源。

Dockerkubernetes中最常用的容器运行时,但是Pod也支持其他容器运行时。

Kubernetes集群中Pod有如下两种方式:

  • 一个Pod中运行一个容器。“每个Pod中一个容器”的模式是最常见的用法;在这种使用方式中,你可以把Pod想象成单个容器的封装,Kubernetes管理的是Pod而不是直接管理容器。

  • 在一个Pod中同时运行多个容器。一个Pod也可以同时封装几个需要紧密耦合互相协作的容器,它们之间共享资源。这些在同一个Pod中的容器可以互相协作成为一个service单位——一个容器共享文件,另一个“sidecar”容器来更新这些文件。Pod将这些容器的存储资源作为一个实体来管理。

Pod中共享的环境包括Linuxnamespacecgroup和其他可能的隔绝环境,这一点跟Docker容器一致。在Pod的环境中,每个容器可能还有更小的子隔离环境。

Pod中的容器共享IP地址和端口号,它们之间可以通过localhost互相发现。它们之间可以通过进程间通信,例如SystemV信号或者POSIX共享内存。不同Pod之间的容器具有不同的IP地址,不能直接通过IPC通信。

Pod中的容器也有访问共享volume的权限,这些volume会被定义成pod的一部分并挂载到应用容器的文件系统中。

就像每个应用容器,pod被认为是临时(非持久的)实体。在Pod的生命周期中讨论过,pod被创建后,被分配一个唯一的ID(UID),调度到节点上,并一致维持期望的状态直到被终结(根据重启策略)或者被删除。如果node死掉了,分配到了这个node上的pod,在经过一个超时时间后会被重新调度到其他node节点上。一个给定的pod(如UID定义的)不会被“重新调度”到新的节点上,而是被一个同样的pod取代,如果期望的话甚至可以是相同的名字,但是会有一个新的UID

Pod中如何管理多个容器

Pod中可以同时运行多个进程(作为容器运行)协同工作。同一个Pod中的容器会自动的分配到同一个node上。同一个Pod中的容器共享资源、网络环境和依赖,它们总是被同时调度。

注意在一个Pod中同时运行多个容器是一种比较高级的用法。只有当你的容器需要紧密配合协作的时候才考虑用这种模式。例如,你有一个容器作为web服务器运行,需要用到共享的volume,有另一个“sidecar”容器来从远端获取资源更新这些文件,如下图所示:

Pod中可以共享两种资源:网络和存储

网络:每个pod都会被分配一个唯一的IP地址。Pod中的所有容器共享网络空间,包括IP地址和端口。Pod内部的容器可以使用localhost互相通信。Pod中的容器与外界通信时,必须分配共享网络资源(例如使用宿主机的端口映射)。

存储:可以为一个Pod指定多个共享的VolumePod中的所有容器都可以访问共享的volumeVolume也可以用来持久化Pod中的存储资源,以防容器重启后文件丢失。

使用Pod

你很少会直接在kubernetes中创建单个Pod。因为Pod的生命周期是短暂的,用后即焚的实体。当Pod被创建后(不论是由你直接创建还是被其它Controller),都会被Kubernetes调度到集群的Node上。直到Pod的进程终止、被删掉、因为缺少资源而被驱逐、或者Node故障之前这个Pod都会一直保持在那个Node上。

注意:重启Pod中的容器跟重启Pod不是一回事。Pod只提供容器的运行环境并保持容器的运行状态,重启容器不会造成Pod重启。

Pod不会自愈。如果Pod运行的Node故障,或者是调度器本身故障,这个Pod就会被删除。同样的,如果Pod所在Node缺少资源或者Pod处于维护状态,Pod也会被驱逐。Kubernetes使用更高级的称为Controller的抽象层,来管理Pod实例。虽然可以直接使用Pod,但是在Kubernetes中通常是使用Controller来管理Pod的。

Controller可以创建和管理多个Pod,提供副本管理、滚动升级和集群级别的自愈能力。例如,如果一个Node故障,Controller就能自动将该节点上的Pod调度到其他健康的Node上。

Pod对象的生命周期

官方文档

中文文档

Pod对象自从其创建开始至其终止退出的时间范围称为其生命周期。在这段时间中,Pod会处于多种不同的状态,并执行一些操作;其中,创建主容器(main container)为必需的操作,其他可选的操作还包括运行初始化容器(init container)、容器启动后钩子(post start hook)、容器的存活性探测(liveness probe)、就绪性探测(readiness probe)以及容器终止前钩子(pre stop hook)等,这些操作是否执行则取决于Pod的定义。如下图所示:

Pod phase

Podstatus字段是一个PodStatus的对象,PodStatus中有一个phase字段。

无论是手动创建还是通过Deployment等控制器创建,Pod对象总是应该处于其生命进程中以下几个相位(phase)之一。

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

  • 运行中(Running):Pod已经被调度至某节点,并且所有容器都已经被kubelet创建完成。

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

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

  • 未知(Unknown):Api Server无法正常获取到Pod对象的状态信息,通常是由于无法与所在工作节点的kubelet通信所致。

Pod的创建过程

Podkubernetes的基础单元,理解它的创建过程对于了解系统运作大有裨益。如下图描述了一个Pod资源对象的典型创建过程。

  1. 用户通过kubectl或其他API客户端提交了Pod SpecAPI Server

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

  3. API Server开始反映etcd中的状态变化。

  4. 所有的kubernetes组件均使用“watch”机制来跟踪检查API Server上的相关的变动。

  5. kube-scheduler(调度器)通过其“watcher”觉察到API Server创建了新的Pod对象但尚未绑定至任何工作节点。

  6. kube-schedulerPod对象挑选一个工作节点并将结果信息更新至API Server

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

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

  9. API ServerPod状态信息存入etcd系统中。

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

Pod生命周期中的重要行为

1)初始化容器

初始化容器(init container)即应用程序的主容器启动之前要运行的容器,常用于为主容器执行一些预置操作,它们具有两种典型特征。

1)初始化容器必须运行完成直至结束,若某初始化容器运行失败,那么kubernetes需要重启它直到成功完成。(注意:如果podspec.restartPolicy字段值为“Never”,那么运行失败的初始化容器不会被重启。)

2)每个初始化容器都必须按定义的顺序串行运行。

2)容器探测

容器探测(container probe)是Pod对象生命周期中的一项重要的日常任务,它是kubelet对容器周期性执行的健康状态诊断,诊断操作由容器的处理器(handler)进行定义。Kubernetes支持三种处理器用于Pod探测:

  • ExecAction:在容器内执行指定命令,并根据其返回的状态码进行诊断的操作称为Exec探测,状态码为0表示成功,否则即为不健康状态。

  • TCPSocketAction:通过与容器的某TCP端口尝试建立连接进行诊断,端口能够成功打开即为正常,否则为不健康状态。

  • HTTPGetAction:通过向容器IP地址的某指定端口的指定path发起HTTP GET请求进行诊断,响应码为2xx3xx时即为成功,否则为失败。

任何一种探测方式都可能存在三种结果:“Success”(成功)“Failure”(失败)“Unknown”(未知),只有success表示成功通过检测。

容器探测分为两种类型:

  • 存活性探测(livenessProbe):用于判定容器是否处于“运行”(Running)状态;一旦此类检测未通过,kubelet将杀死容器并根据重启策略(restartPolicy)决定是否将其重启;未定义存活检测的容器的默认状态为“Success”。

  • 就绪性探测(readinessProbe):用于判断容器是否准备就绪并可对外提供服务;未通过检测的容器意味着其尚未准备就绪,端点控制器(如Service对象)会将其IP从所有匹配到此Pod对象的Service对象的端点列表中移除;检测通过之后,会再将其IP添加至端点列表中。

什么时候使用存活(liveness)和就绪(readiness)探针?

如果容器中的进程能够在遇到问题或不健康的情况下自行崩溃,则不一定需要存活探针,kubelet将根据PodrestartPolicy自动执行正确的操作。

如果希望容器在探测失败时被杀死并重新启动,那么请指定一个存活探针,并指定restartPolicyAlwaysOnFailure

如果要仅在探测成功时才开始向Pod发送流量,请指定就绪探针。在这种情况下,就绪探针可能与存活探针相同,但是spec中的就绪探针的存在意味着Pod将在没有接收到任何流量的情况下启动,并且只有在探针探测成功才开始接收流量。

如果希望容器能够自行维护,可以指定一个就绪探针,该探针检查与存活探针不同的端点。

注意:如果只想在Pod被删除时能够排除请求,则不一定需要使用就绪探针;在删除Pod时,Pod会自动将自身置于未完成状态,无论就绪探针是否存在。当等待Pod中的容器停止时,Pod仍处于未完成状态。

容器的重启策略

PodSpec中有一个restartPolicy字段,可能的值为AlwaysOnFailureNever。默认为AlwaysrestartPolicy适用于Pod中的所有容器。而且它仅用于控制在同一节点上重新启动Pod对象的相关容器。首次需要重启的容器,将在其需要时立即进行重启,随后再次需要重启的操作将由kubelet延迟一段时间后进行,且反复的重启操作的延迟时长依次为10秒、20秒、40秒... 300秒是最大延迟时长。事实上,一旦绑定到一个节点,Pod对象将永远不会被重新绑定到另一个节点,它要么被重启,要么终止,直到节点发生故障或被删除。

  • Always:但凡Pod对象终止就将其重启,默认值

  • OnFailure:仅在Pod对象出现错误时方才将其重启

  • Never:从不重启

Pod存活性探测示例

设置exec探针示例

  1. [root@k8s-master ~]# vim manfests/liveness-exec.yaml
  2. apiVersion: v1
  3. kind: Pod
  4. metadata:
  5. name: liveness-exec-pod
  6. namespace: default
  7. labels:
  8. test: liveness-exec
  9. spec:
  10. containers:
  11. - name: liveness-exec-container
  12. image: busybox:latest
  13. imagePullPolicy: IfNotPresent
  14. command: ["/bin/sh","-c","touch /tmp/healthy; sleep 30; rm -f /tmp/healthy; sleep 3600"]
  15. livenessProbe:
  16. exec:
  17. command: ["test","-e","/tmp/healthy"]
  18. initialDelaySeconds: 1
  19. periodSeconds: 3
  20. [root@k8s-master ~]# kubectl create -f manfests/liveness-exec.yaml #创建pod
  21. pod/liveness-exec-pod created
  22. [root@k8s-master ~]# kubectl get pods #查看pod
  23. NAME READY STATUS RESTARTS AGE
  24. liveness-exec-pod 1/1 Running 0 6s
  25. #等待一段时间后再次查看其状态
  26. [root@k8s-master ~]# kubectl get pods
  27. NAME READY STATUS RESTARTS AGE
  28. liveness-exec-pod 1/1 Running 2 2m46s

上面的资源清单中定义了一个pod对象,基于busybox镜像启动一个运行“touch /tmp/healthy; sleep 30; rm -rf /tmp/healthy; sleep 3600"命令的容器,此命令在容器启动时创建了/tmp/healthy文件,并于60秒之后将其删除。存活性探针运行”test -e /tmp/healthy"命令检查/tmp/healthy文件的存在性,若文件存在则返回状态码0,表示成功通过测试。在60秒内使用“kubectl describe pods/liveness-exec-pod”查看其详细信息,其存活性探测不会出现错误。而超过60秒之后,再执行该命令查看详细信息,可以发现存活性探测出现了故障,并且还可通过“kubectl get pods"查看该pod的重启的相关信息。

设置HTTP探针示例

基于HTTP的探测(HTTPGetAction)向目标容器发起一个HTTP请求,根据其响应码进行结果判定,响应码如2xx3xx时表示测试通过。通过该命令”# kubectl explain pod.spec.containers.livenessProbe.httpGet“查看httpGet定义的字段

  1. host <string>:请求的主机地址,默认为Pod IP,也可以在httpHeaders中使用“Host:”来定义。
  2. httpHeaders <[]Object>:自定义的请求报文首部。
  3. port <string>:请求的端口,必选字段。
  4. path <string>:请求的HTTP资源路径,即URL path
  5. scheme <string>:建立连接使用的协议,仅可为HTTPHTTPS,默认为HTTP
  1. [root@k8s-master ~]# vim manfests/liveness-httpget.yaml
  2. apiVersion: v1
  3. kind: Pod
  4. metadata:
  5. name: liveness-http
  6. namespace: default
  7. labels:
  8. test: liveness
  9. spec:
  10. containers:
  11. - name: liveness-http-demo
  12. image: nginx:1.12
  13. imagePullPolicy: IfNotPresent
  14. ports:
  15. - name: http
  16. containerPort: 80
  17. lifecycle:
  18. postStart:
  19. exec:
  20. command: ["/bin/sh", "-c", "echo Healthz > /usr/share/nginx/html/healthz"]
  21. livenessProbe:
  22. httpGet:
  23. path: /healthz
  24. port: http
  25. scheme: HTTP
  26. [root@k8s-master ~]# kubectl create -f manfests/liveness-httpget.yaml #创建pod
  27. pod/liveness-http created
  28. [root@k8s-master ~]# kubectl get pods #查看pod
  29. NAME READY STATUS RESTARTS AGE
  30. liveness-http 1/1 Running 0 7s
  31. [root@k8s-master ~]# kubectl describe pods/liveness-http #查看liveness-http详细信息
  32. ......
  33. Containers:
  34. liveness-http-demo:
  35. ......
  36. Port: 80/TCP
  37. Host Port: 0/TCP
  38. State: Running
  39. Started: Mon, 09 Sep 2019 15:43:29 +0800
  40. Ready: True
  41. Restart Count: 0
  42. ......

上面清单中定义的httpGet测试中,通过lifecycle中的postStart hook创建了一个专用于httpGet测试的页面文件healthz,请求的资源路径为"/healthz",地址默认为Pod IP,端口使用了容器中顶一个端口名称http,这也是明确了为容器指明要暴露的端口的用途之一。并查看健康状态检测相关的信息,健康状态检测正常时,容器也将正常运行。下面通过“kubectl exec”命令进入容器删除由postStart hook创建的测试页面healthz。再次查看容器状态

  1. [root@k8s-master ~]# kubectl exec pods/liveness-http -it -- /bin/sh #进入到上面创建的pod中
  2. # rm -rf /usr/share/nginx/html/healthz #删除healthz测试页面
  3. #
  4. [root@k8s-master ~]# kubectl get pods
  5. NAME READY STATUS RESTARTS AGE
  6. liveness-http 1/1 Running 1 10m
  7. [root@k8s-master ~]# kubectl describe pods/liveness-http
  8. ......
  9. Containers:
  10. liveness-http-demo:
  11. ......
  12. Port: 80/TCP
  13. Host Port: 0/TCP
  14. State: Running
  15. Started: Mon, 09 Sep 2019 15:53:04 +0800
  16. Last State: Terminated
  17. Reason: Completed
  18. Exit Code: 0
  19. Started: Mon, 09 Sep 2019 15:43:29 +0800
  20. Finished: Mon, 09 Sep 2019 15:53:03 +0800
  21. Ready: True
  22. Restart Count: 1
  23. ......

通过上面测试可以看出,当发起http请求失败后,容器将被杀掉后进行了重新构建。

设置TCP探针

基于TCP的存活性探测(TCPSocketAction)用于向容器的特定端口发起TCP请求并建立连接进行结果判定,连接建立成功即为通过检测。相比较来说,它比基于HTTP的探测要更高效、更节约资源,但精确度略低,毕竟连接建立成功未必意味着页面资源可用。通过该命令”# kubectl explain pod.spec.containers.livenessProbe.tcpSocket“查看tcpSocket定义的字段

  1. host <string>:请求连接的目标IP地址,默认为Pod IP
  2. port <string>:请求连接的目标端口,必选字段
  1. [root@k8s-master ~]# vim manfests/liveness-tcp.yaml
  2. apiVersion: v1
  3. kind: Pod
  4. metadata:
  5. name: liveness-tcp-pod
  6. namespace: default
  7. labels:
  8. test: liveness-tcp
  9. spec:
  10. containers:
  11. - name: liveness-tcp-demo
  12. image: nginx:1.12
  13. imagePullPolicy: IfNotPresent
  14. ports:
  15. - name: http
  16. containerPort: 80
  17. livenessProbe:
  18. tcpSocket:
  19. port: http

上面清单中定义的tcpSocket测试中,通过向容器的80端口发起请求,如果端口正常,则表明正常运行。

livenessProbe行为属性

  1. [root@k8s-master ~]# kubectl explain pods.spec.containers.livenessProbe
  2. KIND: Pod
  3. VERSION: v1
  4. RESOURCE: livenessProbe <Object>
  5.  
  6. exec command 的方式探测,例如 ps 一个进程是否存在
  7. failureThreshold 探测几次失败 才算失败, 默认是连续三次
  8. initialDelaySeconds 初始化延迟探测,即容器启动多久之后再开始探测,默认为0
  9. periodSeconds 每隔多久探测一次,默认是10
  10. successThreshold 处于失败状态时,探测操作至少连续多少次的成功才算通过检测,默认为1
  11. timeoutSeconds 存活性探测的超时时长,默认为1
  12. httpGet http请求探测
  13. tcpSocket 端口探测

Pod就绪性探测示例

Pod对象启动后,容器应用通常需要一段时间才能完成其初始化过程,例如加载配置或数据,甚至有些程序需要运行某类的预热过程,若在这个阶段完成之前即接入客户端的请求,势必会等待太久。因此,这时候就用到了就绪性探测(readinessProbe)。

与存活性探测机制类似,就绪性探测是用来判断容器就绪与否的周期性(默认周期为10秒钟)操作,它用于探测容器是否已经初始化完成并可服务于客户端请求,探测操作返回”success“状态时,即为传递容器已经”就绪“的信号。

就绪性探测也支持ExecHTTPGetTCPSocket三种探测方式,且各自的定义机制也都相同。但与存活性探测触发的操作不同的是,探测失败时,就绪探测不会杀死或重启容器以保证其健康性,而是通知其尚未就绪,并触发依赖于其就绪状态的操作(例如,从Service对象中移除此Pod对象)以确保不会有客户端请求接入此Pod对象。

这里只是示例http探针示例,不论是httpGet还是exec还是tcpSocket和存活性探针类似。

设置HTTP探针示例

  1. #终端1:
  2. [root@k8s-master ~]# vim manfests/readiness-httpget.yaml #编辑readiness-httpget测试pod的yaml文件
  3. apiVersion: v1
  4. kind: Pod
  5. metadata:
  6. name: readiness-http
  7. namespace: default
  8. labels:
  9. test: readiness-http
  10. spec:
  11. containers:
  12. - name: readiness-http-demo
  13. image: nginx:1.12
  14. imagePullPolicy: IfNotPresent
  15. ports:
  16. - name: http
  17. containerPort: 80
  18. readinessProbe:
  19. httpGet:
  20. path: /index.html
  21. port: http
  22. scheme: HTTP
  23. [root@k8s-master ~]# kubectl create -f manfests/readiness-httpget.yaml #创建pod
  24. pod/readiness-http created
  25. [root@k8s-master ~]# kubectl get pods 查看pod状态
  26. NAME READY STATUS RESTARTS AGE
  27. liveness-tcp-pod 1/1 Running 1 7d18h
  28. readiness-http 1/1 Running 0 7s
  29. #新打开一个终端2进入到容器里面
  30. [root@k8s-master ~]# kubectl exec pods/readiness-http -it -- /bin/sh #进入上面创建的pod
  31. # rm -f /usr/share/nginx/html/index.html #删除nginx的主页面文件
  32. # ls /usr/share/nginx/html
  33. 50x.html
  34. #
  35.  
  36.  
  37. #回到终端1上面查看pod状态
  38. [root@k8s-master ~]# kubectl get pods #查看pod状态
  39. NAME READY STATUS RESTARTS AGE
  40. liveness-tcp-pod 1/1 Running 1 7d18h
  41. readiness-http 0/1 Running 0 2m44s

通过上面测试可以看出,当我们删除了nginx主页文件后,readinessProbe发起的测试就会失败,此时我们再查看pod的状态会发现并不会将pod删除重新启动,只是在READY字段可以看出,当前的Pod处于未就绪状态。

 

 

 

 

 

 

原文链接:http://www.cnblogs.com/yanjieli/p/11798222.html

 友情链接:直通硅谷  点职佳  北美留学生论坛

本站QQ群:前端 618073944 | Java 606181507 | Python 626812652 | C/C++ 612253063 | 微信 634508462 | 苹果 692586424 | C#/.net 182808419 | PHP 305140648 | 运维 608723728

W3xue 的所有内容仅供测试,对任何法律问题及风险不承担任何责任。通过使用本站内容随之而来的风险与本站无关。
关于我们  |  意见建议  |  捐助我们  |  报错有奖  |  广告合作、友情链接(目前9元/月)请联系QQ:27243702 沸活量
皖ICP备17017327号-2 皖公网安备34020702000426号