Always keep a beginner's mind, do|

园龄:粉丝:关注:

kubernets 资源对象--Pod

 

1.  概述

k8s 中特有的一个概念,可以理解为对容器的包装,是 k8s 的基本调度单位,实际的容器是运行在 Pod 中的,一个节点可以启动一个或多个 Pod。支持多容器。
Pod 里的容器共享存储、网络等。 也就是说,应该把整个 pod 看作虚拟机,然后每个容器相当于运行在虚拟机的进程。以通过进程间通信和文件共享这种简单高效的方式组合完成服务

 

2. pod基本概念

K8S不是直接调度容器的,而是将其封装成了一个个 POD,POD 才是 k8s 的基本调度单位。每个 POD 中可以运行一个或多个容器,共享 POD 的文件系统、IP 和网络等资源,每一个 POD 只有一个 IP,它的生命周期是短暂的(服务重启后的pod是新的)。

Pod 中的容器共享 IP 地址和端口号,它们之间可以通过 localhost 互相发现。它们之间可以通过进程间通信

Pod 中的容器共享 namespace 和 volume,不支持共享 PID 的 namespace。
就像每个应用容器,pod 被认为是临时(非持久的)实体。在 Pod 的生命周期中讨论过,pod 被创建后,被分配一个唯一的 ID(UID),调度到节点上,并一致维持期望的状态直到被终结(根据重启策略)或者被删除。如果 node 死掉了,分配到了这个 node 上的 pod,在经过一个超时时间后会被重新调度到其他 node 节点上。一个给定的 pod(如 UID 定义的)不会被“重新调度”到新的节点上,而是被一个同样的 pod 取代,如果期望的话甚至可以是相同的名字,但是会有一个新的 UID。
临时卷的生命周期跟 pod 相同,当 Pod 因为某种原因被删除或者被新创建的相同的 pod 取代时,pod 的附属物(例如 volume)也会被销毁和重新创建。Kubernetes 中提供了众多的卷类型,关于卷(Volume)的详细介绍请参考 Kubernetes 文档。

 

3. Pod的定义

• metadata: 关于 Pod 的元数据信息,包括名称,命名空间,标签和注解等
• spec: 描述 Pod 期望的运行状态,比如要运行的容器,运行参数,需要挂载的卷等
• status: 描述 Pod 当前的运行状态,如运行容器,容器的状态,Pod的IP等
可以通过 kubectl explain pods 和 kubectl explain pod.spec 查看对象包含的详细信息,添加参数 --recursive 递归列出简化的信息.

 

下面是yaml文件定义的Pod的完整内容:

复制代码
 1 apiVersion: v1              //版本 
 2 kind: Pod                   //类型,pod 
 3 metadata:                   //元数据 
 4   name: string              //元数据,pod的名字 
 5   namespace: string         //元数据,pod的命名空间 
 6   labels:                   //元数据,标签列表 
 7     - name: string          //元数据,标签的名字 
 8   annotations:              //元数据,自定义注解列表 
 9     - name: string          //元数据,自定义注解名字 
10 spec:                      //pod中容器的详细定义
11     containers:             //pod中的容器列表,可以有多个容器 
12     - name: string          //容器的名称 
13     image: string           //容器中的镜像 
14     imagesPullPolicy: [Always|Never|IfNotPresent]       //获取镜像的策略,默认值为Always,每次都尝试重新下载镜像
15     command: [string]       //容器的启动命令列表(不配置的话使用镜像内部的命令) 
16     args: [string]          //启动参数列表 
17     workingDir: string      //容器的工作目录 
18     volumeMounts:           //挂载到到容器内部的存储卷设置 
19     - name: string 
20       mountPath: string     //存储卷在容器内部Mount的绝对路径 
21       readOnly: boolean     //默认值为读写 
22     ports:                  //容器需要暴露的端口号列表 
23     - name: string 
24       containerPort: int    //容器要暴露的端口 
25       hostPort: int         //容器所在主机监听的端口(容器暴露端口映射到宿主机的端口,设置hostPort时同一台宿主机将不能再启动该容器的第2份副本) 
26       protocol: string      //TCP和UDP,默认值为TCP 
27     env:                    //容器运行前要设置的环境列表 
28     - name: string 
29       value: string 
30     resources: 
31       limits:               //资源限制,容器的最大可用资源数量 
32         cpu: Srting 
33         memory: string 
34       requeste:              //资源限制,容器启动的初始可用资源数量 
35         cpu: string 
36         memory: string 
37     livenessProbe:           //pod内容器健康检查的设置 
38       exec: 
39         command: [string]    //exec方式需要指定的命令或脚本 
40       httpGet:               //通过httpget检查健康 
41         path: string 
42         port: number 
43         host: string 
44         scheme: Srtring 
45         httpHeaders: 
46         - name: Stirng 
47           value: string 
48       tcpSocket:                //通过tcpSocket检查健康 
49         port: number 
50       initialDelaySeconds: 0    //首次检查时间 
51       timeoutSeconds: 0         //检查超时时间 
52       periodSeconds: 0          //检查间隔时间 
53       successThreshold: 0 
54       failureThreshold: 0 
55       securityContext:          //安全配置 
56         privileged: falae 
57     restartPolicy: [Always|Never|OnFailure]   //重启策略,默认值为Always 
58     nodeSelector: object                      //节点选择,表示将该Pod调度到包含这些label的Node上,以key:value格式指定 
59     imagePullSecrets: 
60     - name: string 
61 
62     hostNetwork: false                        //是否使用主机网络模式,弃用Docker网桥,默认否
63   volumes:                                    //在该pod上定义共享存储卷列表 
64   - name: string 
65     emptyDir: {}                              //是一种与Pod同生命周期的存储卷,是一个临时目录,内容为空 
66     hostPath:                                 //Pod所在主机上的目录,将被用于容器中mount的目录 
67       path: string 
68     secret:                                   //类型为secret的存储卷 
69       secretName: string 
70       item: 
71       - key: string 
72           path: string 
73      configMap:                               //类型为configMap的存储卷 
74        name: string 
75        items: 
76        - key: string 
77          path: string
复制代码

Pod可以由1个或多个容器组合而成。

  • 由一个容器组成的Pod示例

复制代码
# 一个容器组成的Pod 
apiVersion: v1 
kind: Pod 
metadata: 
  name: mytomcat 
  labels: 
    name: mytomcat 
spec: 
  containers: 
  - name: mytomcat 
    image: tomcat 
    ports: 
    - containerPort: 8000 
复制代码
  • 由两个为紧耦合的容器组成的Pod示例

复制代码
 1 #两个紧密耦合的容器 
 2 apiVersion: v1 
 3 kind: Pod 
 4 metadata: 
 5   name: myweb 
 6   labels: 
 7     name: tomcat-redis
 8 spec: 
 9   containers: 
10   - name: tomcat 
11     image: tomcat 
12     ports: 
13     - containerPort: 8080 
14   - name: redis 
15     image: redis 
16     ports: 
17     - containerPort: 6379 
复制代码

 

4. Pod的创建/查看/删除

  • 创建
kubectl create -f xxx.yaml 
  • 查看
kubectl get pod/po <Pod_name> 

kubectl get pod/po <Pod_name> -o wide 

kubectl describe pod/po <Pod_name> 
  • 删除
kubectl delete -f pod pod_name.yaml 

kubectl delete pod --all/[pod_name]
按照名字删除 kubectl delete po kubia-manual
同时删除多个Pod kubectl delete po pod1 pod2
按照 label 删除 kubectl delete po -l creation method=manual

 

5. Pod的分类

Pod有两种类型

  •  普通Pod

普通Pod一旦被创建,就会被放入到etcd中存储,随后会被Kubernetes Master调度到某个具体的Node上并进行绑定,随后该Pod对应的Node上的kubelet进程实例化成一组相关的Docker容器并启动起来。在默认情况下,当Pod里某个容器停止时,Kubernetes会自动检测到这个问题并且重新启动这个Pod里某所有容器,如果Pod所在的Node宕机,则会将这个Node上的所有Pod重新调度到其它节点上。

  • 静态Pod

静态 Pod(Static Pod) 直接由特定节点上的 kubelet 守护进程管理, 不需要 API 服务器看到它们。 尽管大多数 Pod 都是通过控制面(例如,Deployment) 来管理的,对于静态 Pod 而言,kubelet 直接监控每个 Pod,并在其失效时重启之。
静态 Pod 通常绑定到某个节点上的 kubelet。 其主要用途是运行自托管的控制面。 在自托管场景中,使用 kubelet 来管理各个独立的控制面组件。
kubelet 自动尝试为每个静态 Pod 在 Kubernetes API 服务器上创建一个镜像 Pod。 这意味着在节点上运行的 Pod 在 API 服务器上是可见的,但不可以通过 API 服务器来控制。 有关更多信息,请参阅创建静态 Pod 的指南。
说明:静态 Pod 的 spec 不能引用其他的 API 对象(例如: ServiceAccount、 ConfigMap、 Secret 等)。

6. Pod 的终止

由于 Pod 所代表的是在集群中节点上运行的进程,当不再需要这些进程时允许其体面地终止是很重要的。 一般不应武断地使用 KILL 信号终止它们,导致这些进程没有机会完成清理操作。

设计的目标是令你能够请求删除进程,并且知道进程何时被终止,同时也能够确保删除操作终将完成。 当你请求删除某个 Pod 时,集群会记录并跟踪 Pod 的体面终止周期, 而不是直接强制地杀死 Pod。在存在强制关闭设施的前提下, kubelet 会尝试体面地终止 Pod。

通常 Pod 体面终止的过程为:kubelet 先发送一个带有体面超时限期的 TERM(又名 SIGTERM) 信号到每个容器中的主进程,将请求发送到容器运行时来尝试停止 Pod 中的容器。 停止容器的这些请求由容器运行时以异步方式处理。 这些请求的处理顺序无法被保证。许多容器运行时遵循容器镜像内定义的 STOPSIGNAL 值, 如果不同,则发送容器镜像中配置的 STOPSIGNAL,而不是 TERM 信号。 一旦超出了体面终止限期,容器运行时会向所有剩余进程发送 KILL 信号,之后 Pod 就会被从 API 服务器上移除。 如果 kubelet 或者容器运行时的管理服务在等待进程终止期间被重启, 集群会从头开始重试,赋予 Pod 完整的体面终止限期。

Pod 终止流程,如下例所示:

  1. 你使用 kubectl 工具手动删除某个特定的 Pod,而该 Pod 的体面终止限期是默认值(30 秒)。

  2. API 服务器中的 Pod 对象被更新,记录涵盖体面终止限期在内 Pod 的最终死期,超出所计算时间点则认为 Pod 已死(dead)。 如果你使用 kubectl describe 来查验你正在删除的 Pod,该 Pod 会显示为 "Terminating" (正在终止)。 在 Pod 运行所在的节点上:kubelet 一旦看到 Pod 被标记为正在终止(已经设置了体面终止限期),kubelet 即开始本地的 Pod 关闭过程。

    1. 如果 Pod 中的容器之一定义了 preStop 回调 且 Pod 规约中的 terminationGracePeriodSeconds 未设为 0, kubelet 开始在容器内运行该回调逻辑。默认的 terminationGracePeriodSeconds 设置为 30 秒.

      如果 preStop 回调在体面期结束后仍在运行,kubelet 将请求短暂的、一次性的体面期延长 2 秒。

    说明:

    如果 preStop 回调所需要的时间长于默认的体面终止限期,你必须修改 terminationGracePeriodSeconds 属性值来使其正常工作。
    1. kubelet 接下来触发容器运行时发送 TERM 信号给每个容器中的进程 1。

      如果 Pod 中定义了Sidecar 容器, 则存在特殊排序。否则,Pod 中的容器会在不同的时间和任意的顺序接收 TERM 信号。如果关闭顺序很重要,考虑使用 preStop 钩子进行同步(或者切换为使用 Sidecar 容器)。

  1. kubelet 启动 Pod 的体面关闭逻辑的同时,控制平面会评估是否将关闭的 Pod 从对应的 EndpointSlice(和端点)对象中移除,过滤条件是 Pod 被对应的服务以某 选择算符选定。 ReplicaSet 和其他工作负载资源不再将关闭进程中的 Pod 视为合法的、能够提供服务的副本。

    关闭动作很慢的 Pod 不应继续处理常规服务请求,而应开始终止并完成对打开的连接的处理。 一些应用程序不仅需要完成对打开的连接的处理,还需要更进一步的体面终止逻辑 - 比如:排空和完成会话。

    任何正在终止的 Pod 所对应的端点都不会立即从 EndpointSlice 中被删除,EndpointSlice API(以及传统的 Endpoints API)会公开一个状态来指示其处于 终止状态。 正在终止的端点始终将其 ready 状态设置为 false(为了向后兼容 1.26 之前的版本), 因此负载均衡器不会将其用于常规流量。

    如果需要排空正被终止的 Pod 上的流量,可以将 serving 状况作为实际的就绪状态。你可以在教程 探索 Pod 及其端点的终止行为 中找到有关如何实现连接排空的更多详细信息。

  1. kubelet 确保 Pod 被关闭和终止

    1. 超出终止宽限期限时,如果 Pod 中仍有容器在运行,kubelet 会触发强制关闭过程。 容器运行时会向 Pod 中所有容器内仍在运行的进程发送 SIGKILL 信号。 kubelet 也会清理隐藏的 pause 容器,如果容器运行时使用了这种容器的话。

    2. kubelet 将 Pod 转换到终止阶段(Failed 或 Succeeded,具体取决于其容器的结束状态)。

    3. kubelet 通过将宽限期设置为 0(立即删除),触发从 API 服务器强制移除 Pod 对象的操作。

    4. API 服务器删除 Pod 的 API 对象,从任何客户端都无法再看到该对象。

 

7. 强制终止 Pod

注意:
对于某些工作负载及其 Pod 而言,强制删除很可能会带来某种破坏。

默认情况下,所有的删除操作都会附有 30 秒钟的宽限期限。 kubectl delete 命令支持 --grace-period=<seconds> 选项,允许你重载默认值, 设定自己希望的期限值。

将宽限期限强制设置为 0 意味着立即从 API 服务器删除 Pod。 如果 Pod 仍然运行于某节点上,强制删除操作会触发 kubelet 立即执行清理操作。

使用 kubectl 时,你必须在设置 --grace-period=0 的同时额外设置 --force 参数才能发起强制删除请求。

执行强制删除操作时,API 服务器不再等待来自 kubelet 的、关于 Pod 已经在原来运行的节点上终止执行的确认消息。 API 服务器直接删除 Pod 对象,这样新的与之同名的 Pod 即可以被创建。 在节点侧,被设置为立即终止的 Pod 仍然会在被强行杀死之前获得一点点的宽限时间。

注意:
马上删除时不等待确认正在运行的资源已被终止。这些资源可能会无限期地继续在集群上运行。

如果你需要强制删除 StatefulSet 的 Pod, 请参阅从 StatefulSet 中删除 Pod 的任务文档

 

8. Pod 关闭和 Sidecar 容器

如果你的 Pod 包含一个或多个 Sidecar 容器 (重启策略为 Always 的 Init 容器),kubelet 将延迟向这些 Sidecar 容器发送 TERM 信号, 直到最后一个主容器已完全终止。Sidecar 容器将按照它们在 Pod 规约中被定义的相反顺序被终止。 这样确保了 Sidecar 容器继续为 Pod 中的其他容器提供服务,直到完全不再需要为止。

这意味着主容器的慢终止也会延迟 Sidecar 容器的终止。 如果在终止过程完成之前宽限期已到,Pod 可能会进入强制终止阶段。 在这种情况下,Pod 中所有剩余的容器将在某个短宽限期内被同时终止。

同样地,如果 Pod 有一个 preStop 钩子超过了终止宽限期,可能会发生紧急终止。 总体而言,如果你以前使用 preStop 钩子来控制没有 Sidecar 的 Pod 中容器的终止顺序, 你现在可以移除这些钩子,允许 kubelet 自动管理 Sidecar 的终止。

9. Pod 的垃圾收集

对于已失败的 Pod 而言,对应的 API 对象仍然会保留在集群的 API 服务器上, 直到用户或者控制器进程显式地将其删除。

Pod 的垃圾收集器(PodGC)是控制平面的控制器,它会在 Pod 个数超出所配置的阈值 (根据 kube-controller-manager 的 terminated-pod-gc-threshold 设置)时删除已终止的 Pod(阶段值为 Succeeded 或 Failed)。 这一行为会避免随着时间演进不断创建和终止 Pod 而引起的资源泄露问题。

此外,PodGC 会清理满足以下任一条件的所有 Pod:

  1. 孤儿 Pod - 绑定到不再存在的节点,
  2. 计划外终止的 Pod
  3. 终止过程中的 Pod,绑定到有 node.kubernetes.io/out-of-service 污点的未就绪节点。

在清理 Pod 的同时,如果它们处于非终止状态阶段,PodGC 也会将它们标记为失败。 此外,PodGC 在清理孤儿 Pod 时会添加 Pod 干扰状况。参阅 Pod 干扰状况 了解更多详情

10. pod存在意义

我们使用docker创建容器,一个docker对应一个容器,一个容器有一个进程,一个容器运行一个应用实例,当然一个容器也可以运行多个,但是不方便管理,所以docker采用单进程设计。
pod是多进程设计,可以运行多个应用实例,一个pod有多个容器,一个容器里面运行一个应用程序。
pod的存在是为了亲密性应用(两个应用之间可以进行交互,或是两个应用之间需要频繁性交互)。

 

11. pod的实现机制

共享网络
  pod里面有多个docker,而docker之间是隔离的。所以一个pod首先会创建一个pause容器(根容器,info容器),然后再创建业务容器,并加入到pause中。pause会有独立的ip、mac、port和namespace等,所以相当于一个pod中的容器共享一个namespace,在一个namespace下的容器可以实现网络共享。
共享存储
  引入了volumn(数据卷),做持久化存储。假设有多个node,其中一个node宕机了,需要将这个node的pod移到其他node上,但是又想使用原来的数据,就需要对数据做持久化存储。下图是一个共享存储示例yaml文件demo。

 

12. pod的资源限制

  • Requests 该资源最小申请数量,系统必须满足要求
  • Limits 该资源最大允许使用的量,不能突破,当容器试图使用超过这个量的资源时,可能会被Kubernetes Kill并重启

 

 13.  pod的重启策略

  1. Always
    这是默认的重启策略。如果设置了为“Always”,那么无论容器停止运行的原因是什么(无论是正常退出还是异常终止),kubelet都会自动重启该容器。这意味着只要Pod尚存在,即使容器连续出错,kubelet也会不断地尝试重启容器。

  2. OnFailure
    如果设置为“OnFailure”,则只有当容器以非0状态退出码结束时,kubelet才会尝试重启该容器。若容器正常退出(即退出码为0),kubelet将不会进行重启操作。

  3. Never
    当设置为“Never”时,kubelet将不会对任何原因导致停止运行的容器进行重启。一旦容器停止,它将保持停止状态,直到手动干预或关联的控制器采取行动。

  4. OnCrash(崩溃时重启)

    该策略主要用于DaemonSet中的Pod。只有在节点重启或Pod崩溃后,才会触发Pod的重启。

综上所述,每个Pod中的所有容器共享相同的重启策略,由Pod的spec.restartPolicy字段指定。需要注意的是,当Pod被控制器(如Deployment、StatefulSet等)管理时,即使Pod未明确指定重启策略,控制器也会根据自身逻辑控制Pod副本的重启行为

 

 

 14. pod的健康检查

 

15. Pod 中容器的特权模式

  从 Kubernetes1.1 版本开始,pod 中的容器就可以开启 privileged 模式,在容器定义文件的 SecurityContext 下使用 privileged flag。这在使用 Linux 的网络操作和访问设备的能力时是很有用的。容器内进程可获得近乎等同于容器外进程的权限。在不需要修改和重新编译 kubelet 的情况下就可以使用 pod 来开发节点的网络和存储插件。
如果 master 节点运行的是 kuberentes1.1 或更高版本,而 node 节点的版本低于 1.1 版本,则 API server 将也可以接受新的特权模式的 pod,但是无法启动,pod 将处于 pending 状态。
  执行 kubectl describe pod FooPodName,可以看到为什么 pod 处于 pending 状态。输出的 event 列表中将显示: Error validating pod "FooPodName"."FooPodNamespace" from api, ignoring: spec.containers[0].securityContext.privileged: forbidden '<*>(0xc2089d3248)true'
如果 master 节点的版本低于 1.1,无法创建特权模式的 pod。如果你仍然试图去创建的话,你得到如下错误:
The Pod "FooPodName" is invalid. spec.containers[0].securityContext.privileged: forbidden '<*>(0xc20b222db0)true'

 

16. Pod资源配置

每个Pod都可以对其能使用的服务器上的计算资源设置限额,Kubernetes中可以设置限额的计算资源有CPU与Memory两种,其中CPU的资源单位为CPU数量,是一个绝对值而非相对值。Memory配额也是一个绝对值,它的单位是内存字节数。

Kubernetes里,一个计算资源进行配额限定需要设定以下两个参数:

  • Requests 该资源最小申请数量,系统必须满足要求

  • Limits 该资源最大允许使用的量,不能突破,当容器试图使用超过这个量的资源时,可能会被Kubernetes Kill并重启

复制代码
sepc
  containers: 
  - name: db 
    image: mysql 
    resources: 
      requests: 
        memory: "64Mi" 
        cpu: "250m" 
      limits: 
        memory: "128Mi" 
        cpu: "500m" 
复制代码

详细:https://kubernetes.io/zh-cn/docs/concepts/configuration/manage-resources-containers/

 

本文作者:云龙

本文链接:https://www.cnblogs.com/yunlong-study/p/18721528

版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 2.5 中国大陆许可协议进行许可。

posted @   云long  阅读(31)  评论(0编辑  收藏  举报
点击右上角即可分享
微信分享提示
评论
收藏
关注
推荐
深色
回顶
展开