Pod 定义详解

Pod 是 Kubernetes 项目中的最小编排单位。容器(Container)是 Pod 属性里的一个普通的字段。Pod 就好像“虚拟机”的角色(并非类似虚拟机),容器就好像运作在“虚拟机”里面的主进程。凡是调度、网络、存储,以及安全相关的属性,基本是 Pod 级别的。
Pod yaml 文件介绍

  1. apiVersion: v1
  2. kind: Pod
  3. metadata: # 元数据
  4. name: string
  5. namespace: string
  6. labels: # 自定义标签列表
  7. - name: string
  8. annotations: # 自定义注解
  9. - name: string
  10. spec: # Pod 中容器的详细定义
  11. containers:
  12. - name: string
  13. image: string
  14. imagePullPolicy: [Always | Never | IfNotPresent] # 镜像拉取策略,Always:表示每次都尝试重新拉取镜像;IfNotPresent:表示如果本地有该镜像,则使用本地的镜像,本地不存在时拉取镜像。Never: 表示仅使用本地镜像。默认是Always
  15. command: [string]
  16. args: [string]
  17. workingDir: string
  18. volumeMounts: # 挂载到容器内部的存储卷配置
  19. - name: string
  20. mountPath: string
  21. readOnly: boolean # 是否为只读模式,默认为读写模式
  22. ports: # 容器需要暴露的端口号
  23. - name: string
  24. containerPort: int # 容器需要监听的端口号
  25. hostPort: int # 容器所在主机需要监听的端口号,默认与 containerPort 相同。
  26. protocol: string # 支持 TCP 和 UDP
  27. env:
  28. - name: string
  29. value: string
  30. resources:
  31. limits: # 容器使用资源的最大值,设置为 0 表示使用资源无上限
  32. cpu: string
  33. memory: string
  34. requests: # 容器使用的最小资源需求
  35. cpu: string
  36. memory: string
  37. volumes:
  38. - name: string # Volume 的类型包括: emptyDir,hostPath,geePersistentDisk,awsElasticBlockStore,gitRepo,secret,nfs,iscsi,glusterfs,rbd,cinder 。。。。。
  39. emptyDir: {} # 表示与 Pod 同生命周期的一个临时目录,其值为一个空对象
  40. hostPath: # 表示挂载 Pod 所在宿主机的目录
  41. path: string
  42. secret: # 表示类型为 secret 的存储卷,表示挂载集群预定义的 secret 对象到容器内部
  43. secretName: string
  44. items:
  45. - key: string
  46. path: string
  47. configMap: # 类型为 configMap 的存储卷,表示挂载集群预定义的 configMap 对象到容器内部
  48. name: string
  49. items:
  50. - key: string
  51. path: string
  52. livenessProbe: # 对 Pod 内各容器健康检查的设置,当探测无响应几次之后,系统将自动重新创建容器。
  53. exec: # 对 Pod 内各容器健康检查的设置,exec 方式
  54. command: [string]
  55. httpGet: # httpGet 方法,需指定 path,port
  56. path: string
  57. port: number
  58. host: string
  59. scheme: string
  60. httpHeaders:
  61. - name: string
  62. value: string
  63. tcpSocket:
  64. port: number
  65. initialDelaySeconds: 0 # 容器启动完成后首次探测的时间,单位为 s
  66. timeoutSeconds: 0 # 对容器健康检查的探测等待响应的超时时间设置,单位为 s,默认值为 1s。若超过该时间时间设置,则将认为容器不健康,会重启该容器
  67. periodSeconds: 0 # 对容器健康检查的定期探测时间设置,单位为 s,默认 10s 探测一次
  68. successThreshold: 0
  69. failureThreshold: 0
  70. securityContext:
  71. privileged: false # 是否启用特权模式,可以访问宿主机上所有设备
  72. restartPolicy: [Always | Never | OnFailure] # Pod 的重启策略,Always: Pod 一旦终止允许,则无论容器是如何终止的, Kubelet 都将重启它。 OnFailure : 只有 Pod 以非零退出码终止时,Kubelet 才会重启该容器。 Never: Pod 终止后,kubelet 将退出码报告给 Master,不会再重启该 Pod。
  73. nodeSelector: object # 用于创建 Pod 时的标签选择
  74. imagePullSecrets:
  75. - name: string
  76. hostNetwork: false # 是否以主机网络模式,默认值为 False

Pod 基本用法

创建容器的 Pod,要确保主程序一直在前台执行。否则会立刻销毁该 Pod。
对于无法改造为前台执行的应用,也可以使用开源工具 Supervisor 辅助进行前台运行的功能。Supervisor 提供了一种可以同时启动多个后台应用,并保持 Supervisor 自身在前台执行的机制。
并把相关连的容器捆绑成一个 Pod,在 containers 字段写多个

静态 Pod

静态 Pod 是由 Kubelet 进行管理的仅存在于特定 Node 上的 Pod。它们不能通过 API Server 进行管理,无法与 ReplicationController,Deployment 或者 DaemonSet 进行关联,并且Kubelet 无法对它们进行健康检查。
创建静态 Pod 的两种方法:
配置文件方式:定期扫描配置文件所在目录,自动拉起 Pod; 删除只能删除定义的 yaml 配置文件,正常 delete 只会处于 pending 状态
HTTP 方式:配置文件变成 url,”—manifest-url” ,定期下载并创建 Pod

应用配置管理 ConfigMap

ConfigMap 是一种 API 对象,用来将非机密性的数据保存到键值对中。ConfigMap 将环境配置信息和容器镜像解耦,便于应用配置的修改。

Downward API

Downward API 可以通过以下两种方式将 Pod 信息注入容器内部。

  • 环境变量:用于单个变量,可以将 Pod 信息和 Container 信息注入容器内部。

image.png

  • Volume 挂载:将数组类信息生成为文件并挂载到容器内部;

Pod 生命周期和重启策略

状态值 描 述
pending API Server 已经创建该 Pod,但在 Pod 内还有一个或多个容器的镜像没有创建,包括正在下载镜像的过程
Running Pod 内所有容器均已创建,且至少有一个容器处于运行状态、正在启动状态或正在重启状态
Succeeded Pod 内所有容器均成功执行后退出,且不会再重启
Failed Pod 内所有容器均已退出,但至少有一个容器退出为失败状态
Unknown 由于某种原因无法获取该 Pod 的状态,可能由于网络通信不畅导致

Pod 调度

副本控制器

RC(Replication Controller):独立所控制的 Pod,并通过 Label 标签松耦合关联关系控制目标 Pod 实例创建和销毁;
👇
ReplicaSet :增强了 RC 标签选择器的灵活性,集合式,可以选择多个 Pod 标签
👇
Deployment : 通过 ReplicaSet 实现 Pod 副本控制,NodeSelector 自定义节点;NodeAffinity 动态解决 Pod 的 Node 选择问题

  - 不同 Pod 之间的亲和性:Affinity
  - 有状态集群的调度:StatefulSet , kubernetes 1.9 版本后支持
  - 系统监控类在部署时需要部署到每一个节点且只有一份: DaemonSet 
  - Pod 运行且只运行一次:CronJob 定时作业的调度控制器

kubernetes 1.9 之前,如果删除控制器,归属于控制器的 Pod 不会被删除;但是 1.9 版本之后,会一并被删除。
cascade=false 可以通过这个参数定义取消这一默认特性。
Deployment 或 RC : 全自动调度

NodeSelector 定向调度

通过指定标签控制 Pod 自定义调度,kubernetes 也提供 Node 预定义标签。

Affinity 亲和性

节点亲和性(NodeAffinity):

  - RequiredDuringSchedulingIgnoredDuringExecution : 必须满足指定的规则才可以调度 Pod 到 Node 上
  - PreferredDuringSchedulingIgnoredDuringExecution:强调优先满足指定规则,

IgnoredDuringExecution :如果一个 Pod 所在的节点在 Pod 运行期间标签发生了变更,不再符合该 Pod 的节点亲和性需求,则系统忽略 Node 上 Label 的变化,该 Pod 继续运行。
Pod 亲和性(PodAffinity):
根据在节点上正在运行的 Pod 的标签而不是节点的标签进行判断和调度,

Pod Priority Preemption

依据: Priority,QoS,Others
抢占调度策略:

  • 驱逐 Eviction: kubelet 进程行为
  • 抢占 Preemption: scheduler 行为

DaemonSet

image.png

Job 批处理调度

Job Template Expansion 模式: 一个 job 处理 一个 Work item
Queue with Pod Per Work Item : 采用一个任务队列存放 Work Iterm,Job 启动 N 个 Pod ,每个 Pod 对应一个 Work iterm;
Queue with Variable Pod Count : Job 启动可变数量的 Pod
Single Job with Static Work Assignment : 采用程序静态方式分配任务项。
image.png

  • Non-parallel Jobs : 通常一个 Job 只启动一个 Pod,除非 Pod 异常,才会重启该 Pod,一旦此 Pod 正常结束,Job 将结束
  • Parallel Jobs with a fixed completion count : 并行 Job 启动多个 Pod
  • Parallel Jobs with a work queue:Work 队列处理

Pod 常见字段说明

NodeSelector

用于 Pod 与 Node 绑定字段。指定 Pod 只能允许在 Node 的标签 disktype 是 ssd 上

apiVersion: v1
kind: Pod
...
spec:
 nodeSelector:
   disktype: ssd

NodeName

当 Pod 这个字段被赋值时, Kubernetes 就认为 Pod 已经经过调度,调度的结果就是赋值的节点名称。一般我们也认为当前 Pod 所运行的节点。由调度器来负责设置。

HostAliases

定义 Pod 的 hosts 文件里的内容

apiVersion: v1
kind: Pod
...
spec:
  hostAliases:
  - ip: "10.1.2.3"
    hostnames:
    - "foo.remote"
    - "bar.remote"
...

Lifecycle

Container Lifecycle Hooks,在容器状态发生变化时触发一系列“钩子”。


apiVersion: v1
kind: Pod
metadata:
  name: lifecycle-demo
spec:
  containers:
  - name: lifecycle-demo-container
    image: nginx
    lifecycle:
      postStart: # 容器启动后,立刻执行一个指定操作。 和 ENTRYPONIT 是异步
        exec:
          command: ["/bin/sh", "-c", "echo Hello from the postStart handler > /usr/share/message"]
      preStop: # 容器被杀死之前,立刻执行一个指定操作。同步执行       
        exec:
          command: ["/usr/sbin/nginx","-s","quit"]

Pod 的状态 pod.status.phase

表示 pod 的状态

  • pending : Pod 的 YAML 已经提及给了 Kubernetes,API 对象已经被创建并保存在 ETCD 中。但因为某些原因而无法被顺利创建;
  • Running:Pod 已经调度成功,跟一个具体的节点绑定。它包含的容器都已经创建成功,并且至少有一个正在运行中;
  • Succeeded:Pod 里的所有容器都正常运行完成,并且已经退出了。运行一次性的任务时常见;
  • Failed:Pod 里至少有一个容器以不正常的状态(非 0 的返回码)退出;
  • Unknown:这是一个异常状态,意味着 Pod 的状态不能持续地被 kubelet 汇报给 Kube-apiserver。

pod.status.Conditions 会更细粒度地反馈问题。这些细分状态的值包括:PodScheduled、Ready、Initialized,以及 Unschedulable。

Projected Volume

用于存放容器提供预先定义好的数据,不存放容器里的数据,也不存放进行容器和宿主机之间的数据交换。四种 projected Volume

  1. Secret:将 Pod 想要访问的加密数据,存放到 Etcd 中
  2. ConfigMap:保存不需要加密,应用所需的配置信息,方式和 Secret 一致
  3. Downward API:让 Pod 里的容器能够直接获取到这个 Pod API 对象本身的信息;
  4. ServiceAccountToken:K8S 进行权限分配的特殊 Secret 对象

Secret 两种创建方式:

  1. 声明 volume,创建 Secret 对象: kubelet create secret generic user —from-file=./user.txt
  2. 通过 YamL 的方式声明:需要做一次转码,不能明文显示;通过这种方式的好处是可以被 kubelet 组件自动维护。 ```yaml

apiVersion: v1 kind: Secret metadata: name: mysecret type: Opaque data: user: YWRtaW4= pass: MWYyZDFlMmU2N2Rm

```shell
xxx$ echo -n 'admin' | base64
YWRtaW4=
xxx$ echo -n 'YWRtaW4=' | base64 -d
admin

Downward API 支持丰富的字段,通过这种声明方式,当前 Pod 的 Labels 字段的值,会被 Kubernetes 自动挂载成为容器里的 /etc/podinfo/labels 文件。它能够获取到的信息,一定是 Pod 里的容器进程启动之前就能够确定下来的信息。

1. 使用fieldRef可以声明使用:
spec.nodeName - 宿主机名字
status.hostIP - 宿主机IP
metadata.name - Pod的名字
metadata.namespace - Pod的Namespace
status.podIP - Pod的IP
spec.serviceAccountName - Pod的Service Account的名字
metadata.uid - Pod的UID
metadata.labels['<KEY>'] - 指定<KEY>的Label值
metadata.annotations['<KEY>'] - 指定<KEY>的Annotation值
metadata.labels - Pod的所有Label
metadata.annotations - Pod的所有Annotation

2. 使用resourceFieldRef可以声明使用:
容器的CPU limit
容器的CPU request
容器的memory limit
容器的memory request

k8s 已经提供了一个默认“服务账户”(default Service Account),也允许不自动挂载。如果把 K8S Client 以容器的方式运行在集群里,然后使用 default Service Account 自动授权的方式,被称作 InClsuterConfig,是比较推荐的 API 授权方式。

Pod 恢复机制

restartPolicy ,它是 Pod 的 Spec 部分的一个标准字段(pod.spec.restartPolicy),默认是 Always,即:任何时候这个容器发生了异常,它一定会被重新创建。还有 OnFailure(只在容器异常时才自动重启容器) 和 Never (从来不重启容器)两种方式。Always 的方式可能会使得容器重启前后的信息被垃圾回收。
Pod 恢复永远只在当前节点恢复,即重新拉起一个容器,只有以 Deployment 的方式才会自动调度到其他节点。
两个重要的 Pod 容器状态基本原理:

  • 只要 Pod 的 restartPolicy 指定的策略允许重启异常的容器,那么这个 Pod 就会保持 Running 状态,并进行容器重启,否则 Pod 就会进入 Failed 状态。
  • 对于包含多个容器的 Pod ,只有它里面所有的容器都进入异常状态后, Pod 才会进入 Failed 状态。