Kubernetes集群核心概念 Pod ¶
什么是工作负载
工作负载(workload)是在kubernetes集群中运行的应用程序。无论你的工作负载是单一服务还是多个一同工作的服务构成,在kubernetes中都可以使用pod来运行它。
workloads 分为 pod 与 controllers,pod 与控制器之间通过 label-selector 相关联,是唯一的关联方式
pod 通过控制器实现应用的运行,如何伸缩,升级等
在 pod yaml 中指定 pod 标签
labels:
app: nginx
controllers 在集群中管理 pod
selector:
matchLabels:
app: nginx
pod 介绍 ¶
pod 定义与分类 ¶
参考链接: https://kubernetes.io/zh/docs/concepts/workloads/pods/
Pod 定义
- Pod(豌豆荚) 是Kubernetes集群管理(创建、部署)与调度的最小计算单元,表示处于运行状态的一组容器。
- Pod不是进程,而是容器运行的环境。
- 一个Pod可以封装一个容器或多个容器(主容器或sidecar边车容器)
- 一个pod内的多个容器之间共享部分命名空间,例如:Net Namespace,UTS Namespace,IPC Namespace及存储资源
- 用户pod默认会被调度运行在node节点之上(不运行在master节点上,但也有例外情况)
- pod内的IP不是固定的,集群外不能直接访问pod
Pod 分类
-
静态 Pod: 也称之为“无控制器管理的自主式pod”,直接由特定节点上的
kubelet
守护进程管理, 不需要API 服务器看到它们,尽管大多数 Pod 都是通过控制面(例如,Deployment) 来管理的,对于静态 Pod 而言,kubelet
直接监控每个 Pod,并在其失效时重启之。 -
控制器管理的 pod: 控制器可以控制pod的副本数,扩容与裁剪,版本更新与回滚等
查看 pod ¶
pod 是一种计算资源,可以通过 kubectl get pod
命令来查看
kubectl get pod # pod 或 pods都可以,不指定 namespace,默认是名为 default 的namespace
kubectl get pod -n kube-system # 指定查看命名空间的 pod
pod 的 YAML 资源清单格式 ¶
YAML格式查找帮助
kubectl explain namespace
kubectl explain pod
kubectl explain pod.spec
kubectl explain pod.spec.containers
# yaml格式的pod定义文件完整内容:
apiVersion: v1 #必选,api版本号,例如v1
kind: Pod #必选,Pod
metadata: #必选,元数据
name: string #必选,Pod名称
namespace: string #Pod所属的命名空间,默认在default的namespace
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数,将用于docker run --cpu-shares参数
memory: string #内存限制,单位可以为Mib/Gib,将用于docker run --memory参数
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的存储卷,挂载集群与定义的secret对象到容器内部
scretname: string
items:
- key: string
path: string
configMap: #类型为configMap的存储卷,挂载预定义的configMap对象到容器内部
name: string
items:
- key: string
path: string
pod 创建与验证 ¶
创建一个名为 pod-hello 的 pod ¶
- 编写 yaml 文件
pod-hello.yaml
apiVersion: v1 kind: Pod metadata: name: hello namespace: default spec: containers: - name: hello image: busybox:1.28 command: ['sh', '-c', 'echo "Hello, Kubernetes!" && sleep 3600'] restartPolicy: OnFailure
- 通过 yaml 文件创建 pod
[root@k8smaster001 pod]# kubectl apply -f pod-hello.yaml pod/hello created
查看 Pod 信息 ¶
查看 pod 信息
[root@k8smaster001 pod]# kubectl get pod
NAME READY STATUS RESTARTS AGE
hello 1/1 Running 0 2m24s
查看 pod 详细信息
[root@k8smaster001 pod]# kubectl get pods -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
hello 1/1 Running 0 2m32s 10.244.35.25 k8sworker002 <none> <none>
查看描述 pod 详细信息
[root@k8smaster001 pod]# kubectl describe pod hello
Events:
Type Reason Age From Message
---- ------ ---- ---- -------
Normal Scheduled 3m50s default-scheduler Successfully assigned default/hello to k8sworker002
Normal Pulled 3m49s kubelet Container image "busybox:1.28" already present on machine
Normal Created 3m49s kubelet Created container hello
Normal Started 3m49s kubelet Started container hello
查看 pod 日志
[root@k8smaster001 pod]# kubectl logs hello
Hello, Kubernetes!
删除 Pod ¶
单个 pod 删除
-
指定 pod 名称删除
[root@k8smaster001 pod]# kubectl delete pod hello pod "hello" deleted
-
指定文件删除
[root@k8smaster001 pod]# kubectl delete -f pod-hello.yaml pod "hello" deleted
多个 pod 删除
- 指定多个 pod 名称
[root@k8smaster001 pod]# kubectl delete pod pod-1 pod-2 pod-3 ...
Pod 镜像拉取策略 ¶
镜像拉取策略由 imagePullPolicy 参数控制,有以下三种
策略 | 解释 | |
---|---|---|
Always | 不管本地有没有镜像,都要从仓库中下载镜像 | |
Never | 从来不从仓库下载镜像, 只用本地镜像,本地没有就算了 | |
IfNotPresent | 如果本地存在就直接使用, 不存在才从仓库下载 |
-
当镜像标签版本是latest,默认策略就是Always
-
如果指定特定版本默认拉取策略就是IfNotPresent。
pod 的标签 ¶
为pod设置label,用于控制器通过label与pod关联
- 查看pod的标签
[root@k8smaster001 pod]# kubectl get pod --show-labels NAME READY STATUS RESTARTS AGE LABELS hello 1/1 Running 0 96s <none>
- 打标签,再查看
[root@k8smaster001 pod]# kubectl label pod hello env=test zone=A region=china pod/hello labeled [root@k8smaster001 pod]# kubectl get pod hello --show-labels NAME READY STATUS RESTARTS AGE LABELS hello 1/1 Running 0 3m42s env=test,region=china,zone=A
- 通过等值关系标签查询
[root@k8smaster001 pod]# kubectl get pod -l region=china NAME READY STATUS RESTARTS AGE hello 1/1 Running 0 4m27s
- 通过集合关系标签查询
[root@k8smaster001 pod]# kubectl get pod -l "env in (test,prod)" NAME READY STATUS RESTARTS AGE hello 1/1 Running 0 5m14s
- 删除标签后再验证
[root@k8smaster001 pod]# kubectl label pod hello env- region- zone- pod/hello unlabeled [root@k8smaster001 pod]# kubectl get pod hello --show-labels NAME READY STATUS RESTARTS AGE LABELS hello 1/1 Running 0 6m44s <none>
总结
- pod 的 abel 与 node 的 label 操作方式相同
- node 的 label 用于 pod 调度到指定 label 的 node 节点
- pod 的 label 用于 controller 关联控制的 pod
- 编写 yaml 文件
pod-hello-labels.yaml
apiVersion: v1 kind: Pod metadata: name: hello namespace: default labels: env: test app: hello # 直接在原来的yaml里加上多个标签 spec: containers: - name: hello image: busybox:1.28 command: ['sh', '-c', 'echo "Hello, Kubernetes!" && sleep 3600'] restartPolicy: OnFailure
-
通过 yaml 文件创建 pod
[root@k8smaster001 pod]# kubectl apply -f pod-hello.yaml pod/hello created
-
验证标签
[root@k8smaster001 pod]# kubectl get pod hello --show-labels NAME READY STATUS RESTARTS AGE LABELS hello 1/1 Running 0 4s app=hello,env=test
pod资源限制 ¶
- 编写 两个 yaml 文件
apiVersion: v1
kind: Namespace
metadata:
name: pod-memory
---
apiVersion: v1
kind: Pod
metadata:
name: pod-memory1
namespace: pod-memory
spec:
containers:
- name: c1
image: polinux/stress
imagePullPolicy: IfNotPresent
resources:
limits:
memory: "200Mi"
requests:
memory: "100Mi"
command: ["stress"] # 启动容器时执行的命令
args: ["--vm", "1", "--vm-bytes", "150M", "--vm-hang", "1"] # 产生1个进程分配150M内存1秒后释放
apiVersion: v1
kind: Namespace
metadata:
name: pod-memory
---
apiVersion: v1
kind: Pod
metadata:
name: pod-memory2
namespace: pod-memory
spec:
containers:
- name: c2
image: polinux/stress
imagePullPolicy: IfNotPresent
resources:
limits:
memory: "200Mi"
requests:
memory: "150Mi"
command: ["stress"] # 启动容器时执行的命令
args: ["--vm", "1", "--vm-bytes", "300M", "--vm-hang", "1"] # 产生1个进程分配300M内存1秒后释放
-
通过 yaml 文件创建 pod
[root@k8smaster001 pod]# kubectl apply -f pod-memory-1.yaml pod-memory-2.yaml
-
验证标签
[root@k8smaster001 pod]# kubectl get pod -n pod-memory NAME READY STATUS RESTARTS AGE pod-memory1 1/1 Running 0 4m13s pod-memory2 0/1 OOMKilled 5 (23s ago) 4m11s
查看发现 pod-memory2 这个 pod 状态变为 OOMKilled ,因为内存不足显示 Container 被杀死
pod 包含多个容器 ¶
- 编写 yaml 文件
apiVersion: v1
kind: Pod
metadata:
name: hello
namespace: default
spec:
containers:
- name: hello1
image: busybox:1.28
command: ['sh', '-c', 'echo "Hello, I am pod1 !" && sleep 3600']
- name: hello2
image: busybox:1.28
command: ['sh', '-c', 'echo "Hello, I am pod2 !" && sleep 3600']
-
通过 yaml 文件创建 pod
yaml [root@k8smaster001 pod]# kubectl apply -f pods.yaml pod/hello created
-
验证标签
yaml [root@k8smaster001 pod]# kubectl get pod -o wide NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES hello 2/2 Running 0 26s 10.244.35.28 k8sworker002 <none> <none>
对 pod 里的容器进行操作 ¶
命令帮助 ¶
[root@k8smaster001 pod]# kubectl exec --help
不用交互直接执行命令 ¶
格式为: kubectl exec pod名 -c 容器名 -- 命令
Note
- -c 容器名为可选项,如果是 1 个 pod 中 1 个容器,则不用指定;
- 如果是 1 个 pod 中多个容器,不指定默认为第 1 个。
[root@k8smaster001 pod]# kubectl exec hello -c hello1 -- touch /aaa
[root@k8smaster001 pod]# kubectl exec hello -c hello2 -- ls /aaa
ls: /aaa: No such file or directory
不指定容器名,则默认为pod里的第1个容器
[root@k8smaster001 pod]# kubectl exec hello -- ls /aaa
Defaulted container "hello1" out of: hello1, hello2
/aaa
和容器交互操作 ¶
和 docker exec 一样
[root@k8smaster001 pod]# kubectl exec -it hello -c hello1 -- sh
/ # ls /aaa
/aaa
/ # exit
验证pod中多个容器网络共享 ¶
- 编写 yaml 文件
apiVersion: v1
kind: Pod
metadata:
name: nginx-network
spec:
containers:
- name: c1
image: nginx:1.15-alpine
- name: c2
image: nginx:1.15-alpine
-
通过 yaml 文件创建 pod
[root@k8smaster001 pod]# kubectl apply -f pod-nginx-network.yaml pod/nginx-network created
-
查看 pod 信息与状态
[root@k8smaster001 pod]# kubectl describe pod nginx-network Events: Type Reason Age From Message ---- ------ ---- ---- ------- Normal Scheduled 45s default-scheduler Successfully assigned default/nginx-network to k8sworker002 Normal Pulling 45s kubelet Pulling image "nginx:1.15-alpine" Normal Pulled 2s kubelet Successfully pulled image "nginx:1.15-alpine" in 42.162s (42.162s including waiting) Normal Created 2s kubelet Created container c1 Normal Started 2s kubelet Started container c1 Normal Pulled 2s kubelet Container image "nginx:1.15-alpine" already present on machine Normal Created 2s kubelet Created container c2 Normal Started 2s kubelet Started container c2
[root@k8smaster001 pod]# kubectl get pod
NAME READY STATUS RESTARTS AGE
nginx-network 1/2 CrashLoopBackOff 2 (15s ago) 82s
# 有一个启动失败,因为一个 pod 中两个容器是共用网络的,所以不能两个都占用 80 端口
[root@k8smaster001 pod]# kubectl logs nginx-network -c c2
2024/03/29 11:44:54 [emerg] 1#1: bind() to 0.0.0.0:80 failed (98: Address in use)
nginx: [emerg] bind() to 0.0.0.0:80 failed (98: Address in use)
2024/03/29 11:44:54 [emerg] 1#1: bind() to 0.0.0.0:80 failed (98: Address in use)
nginx: [emerg] bind() to 0.0.0.0:80 failed (98: Address in use)
2024/03/29 11:44:54 [emerg] 1#1: bind() to 0.0.0.0:80 failed (98: Address in use)
nginx: [emerg] bind() to 0.0.0.0:80 failed (98: Address in use)
2024/03/29 11:44:54 [emerg] 1#1: bind() to 0.0.0.0:80 failed (98: Address in use)
nginx: [emerg] bind() to 0.0.0.0:80 failed (98: Address in use)
2024/03/29 11:44:54 [emerg] 1#1: bind() to 0.0.0.0:80 failed (98: Address in use)
nginx: [emerg] bind() to 0.0.0.0:80 failed (98: Address in use)
2024/03/29 11:44:54 [emerg] 1#1: still could not bind()
nginx: [emerg] still could not bind()
调度约束方法 node 节点选择器 ¶
node 节点选择器
Note
-
我们在创建 pod 资源的时候,pod 会根据 schduler 进行调度,那么默认会调度到随机的一个工作节点,如果我们想要 pod 调度到指定节点或者调度到一些具有相同特点的 node 节点,怎么办呢?
-
可以使用 pod 中的 nodeName 或者 nodeSelector 字段指定要调度到的 node 节点
给节点添加标签 ¶
-
列出你的集群中的节点, 包括这些节点上的标签:
kubectl get nodes --show-labels
-
从你的节点中选择一个,为它添加标签:
kubectl label nodes <your-node-name> disktype=ssd
注意
'<your-node-name>' 是你选择的节点的名称。
-
验证你选择的节点确实带有
disktype=ssd
标签:kubectl get nodes --show-labels | grep disktype=ssd
注意
在前面的输出中,你可以看到 linuxnbg-1 节点有 disktype=ssd 标签。
创建一个将被调度到你选择的节点的 nodeSelector
此 Pod 配置文件描述了一个拥有节点选择器 disktype: ssd 的 Pod。这表明该 Pod 将被调度到有 disktype=ssd 标签的节点。
apiVersion: v1
kind: Pod
metadata:
name: nginx
labels:
env: test
spec:
containers:
- name: nginx
image: nginx
imagePullPolicy: IfNotPresent
nodeSelector:
disktype: ssd
-
使用该配置文件创建一个 Pod,该 Pod 将被调度到你选择的节点上:
kubectl apply -f nodeSelector.yaml
-
验证 Pod 确实运行在你选择的节点上:
kubectl get pod nginx --output=wide
创建一个会被调度到特定节点上的 nodeName
-
可以通过设置 nodeName 将某个 Pod 调度到特定的节点。
-
nodeName 是比亲和性或者 nodeSelector 更为直接的形式。nodeName 是 Pod 规约中的一个字段。如果 nodeName 字段不为空,调度器会忽略该 Pod, 而指定节点上的 kubelet 会尝试将 Pod 放到该节点上。 使用 nodeName 规则的优先级会高于使用 nodeSelector 或亲和性与非亲和性的规则。
apiVersion: v1
kind: Pod
metadata:
name: nginx
spec:
nodeName: linuxnbg-1 # 调度 Pod 到特定的节点
containers:
- name: nginx
image: nginx
imagePullPolicy: IfNotPresent
-
使用此配置文件来创建一个 Pod,该 Pod 将只能被调度到定义的 linuxnbg-1 节点
kubectl apply -f nodeName.yaml
-
验证 Pod 确实运行在你选择的节点上:
kubectl get pod nginx --output=wide
pod 的生命周期 ¶
容器启动
- pod中的容器在创建前,有初始化容器(init container)来进行初始化环境
-
初化完后,主容器(main container)开始启动
-
主容器启动后,有一个post start的操作(启动后的触发型操作,或者叫启动后钩子)
-
post start后,就开始做健康检查
-
第一个健康检查叫存活状态检查(liveness probe ),用来检查主容器存活状态的
-
第二个健康检查叫准备就绪检查(readiness probe),用来检查主容器是否启动就绪
-
容器终止
- 可以在容器终止前设置pre stop操作(终止前的触发型操作,或者叫终止前钩子)
- 当出现特殊情况不能正常销毁pod时,大概等待30秒会强制终止
- 终止容器后还可能会重启容器(视容器重启策略而定)。
容器重启策略
-
Always:表示容器挂了总是重启,这是默认策略
-
OnFailures:表示容器状态为错误时才重启,也就是容器正常终止时不重启
-
Never:表示容器挂了不予重启
-
对于Always这种策略,容器只要挂了,就会立即重启,这样是很耗费资源的。所以Always重启策略是这么做的:第一次容器挂了立即重启,如果再挂了就要延时10s重启,第三次挂了就等20s重启...... 依次类推
生命周期相关介绍
-
Pod 遵循预定义的生命周期,起始于 Pending 阶段, 如果至少其中有一个主要容器正常启动,则进入 Running,之后取决于 Pod 中是否有容器以失败状态结束而进入 Succeeded 或者 Failed 阶段。
-
在 Pod 运行期间,kubelet 能够重启容器以处理一些失效场景。 在 Pod 内部,Kubernetes 跟踪不同容器的状态并确定使 Pod 重新变得健康所需要采取的动作。
-
在 Kubernetes API 中,Pod 包含规约部分和实际状态部分。 Pod 对象的状态包含了一组 Pod 状况(Conditions)。 如果应用需要的话,你也可以向其中注入自定义的就绪态信息。
-
Pod 在其生命周期中只会被调度一次。 一旦 Pod 被调度(分派)到某个节点,Pod 会一直在该节点运行,直到 Pod 停止或者被终止
Pod生命周期是指从Pod创建开始到终止退出的整个过程,其中包含了一些重要的流程和操作。
以下是Pod生命周期中的几个关键流程:
-
初始化init容器
:除了主容器外,你可以在Pod中定义一些初始化容器(init container)。这些容器在主容器启动之前运行,用于执行初始化任务,例如数据库初始化、数据加载等。 -
创建主容器 containers
:Pod创建时,主容器会被创建并启动。主容器通常是应用程序容器,负责运行你的应用程序。 -
启动后钩子
:在主容器启动之后,你可以定义一些启动后的钩子(postStart hook)。这些钩子是容器内的可执行命令或脚本,用于在容器启动后执行特定的操作,例如数据初始化、配置加载等。 -
存活性探测
:为了确保Pod内的容器正常运行,Kubernetes提供了存活性探测(liveness probe)机制。通过定义存活性探测,系统可以检测容器是否处于活动状态。如果探测失败,Kubernetes可以采取相应的行动,例如重启容器或重新调度Pod。 -
就绪性探测
:就绪性探测(readiness probe)用于确定容器是否已准备好接收流量。通过定义就绪性探测,Kubernetes可以确保只有在容器准备好之后才将流量引导到该容器。这有助于确保应用程序在完全就绪之前不会接收到流量。 -
停止前钩子
:在Pod终止之前,你可以定义一些停止前的钩子(preStop hook)。这些钩子是容器内的可执行命令或脚本,用于在容器终止之前执行特定的操作,例如保存状态、清理资源等。
Pod 的 status 字段是一个 PodStatus 对象,其中包含一个 phase 字段。
- Pod 的阶段(Phase)是 Pod 在其生命周期中所处位置的简单宏观概述。 该阶段并不是对容器或 Pod 状态的综合汇总,也不是为了成为完整的状态机。
- Pod 阶段的数量和含义是严格定义的,下面是 phase 可能的值:
取值 | 描述 |
---|---|
Pending (悬决) |
Pod 已被 Kubernetes 系统接受,但有一个或者多个容器尚未创建亦未运行。此阶段包括等待 Pod 被调度的时间和通过网络下载镜像的时间。 |
Running (运行中) |
Pod 已经绑定到了某个节点,Pod 中所有的容器都已被创建。至少有一个容器仍在运行,或者正处于启动或重启状态。 |
Succeeded (成功) |
Pod 中的所有容器都已成功终止,并且不会再重启。 |
Failed (失败) |
Pod 中的所有容器都已终止,并且至少有一个容器是因为失败终止。也就是说,容器以非 0 状态退出或者被系统终止。 |
Unknown (未知) |
因为某些原因无法取得 Pod 的状态。这种情况通常是因为与 Pod 所在主机通信失败。 |
说明
-
当一个 Pod 被删除时,执行一些 kubectl 命令会展示这个 Pod 的状态为 Terminating(终止)。 这个 Terminating 状态并不是 Pod 阶段之一。 Pod 被赋予一个可以体面终止的期限,默认为 30 秒。 你可以使用 --force 参数来强制终止 Pod。
-
如果某节点死掉或者与集群中其他节点失联,Kubernetes 会实施一种策略,将失去的节点上运行的所有 Pod 的 phase 设置为 Failed。
-
用户通过 kubectl 或其他api客户端提交应用资源清单文件(yaml格式)需要创建的pod信息给 apiServer 发送 create pod 请求
-
api server接收到pod创建请求后,生成一个包含创建信息资源清单文件。
-
apiserver 将资源清单文件中信息写入etcd数据库,然后返回确认信息至客户端
-
apiServer 开始反映 etcd 中的 pod 对象的变化,其它组件使用 watch 机制来跟踪检查 apiServer 上的变动
-
Scheduler启动后会一直 watch API Server,获取 podSpec.NodeName为空的Pod,即判断pod.spec.Node == null? 若为null,表示这个Pod请求是新的,需要创建,因此先进行调度计算(共计2步:1、过滤不满足条件的,2、选择优先级高的),找到合适的node
-
Scheduler 将结果信息更新至 apiServer。
-
apiserver 将信息在 etcd 数据库中更新分配结果:pod.spec.Node = nodeA (设置一个具体的节点)
-
kubelet 进程通过 API Server ,查看 etcd 数据库(kubelet通过API Server的WATCH接口监听Pod信息,如果监听到新的pod副本被调度绑定到本节点)监听到 apiServer 返回的 kube-scheduler 产生的 Pod 绑定事件后获取对应的 Pod 清单,然后调用(被选中node)本机中的Container Runtime - docker-api 初始化 volume、分配IP、下载image镜像,创建容器并启动服务。并将创建后的结果返回到给api server
-
apiServer 将接收到的pod状态信息更新 etcd 数据库中数据状态。
-
用户向apiServer发送删除pod对象的命令 kubectl delete pods
-
apiServcer 中的 pod 对象信息会随着时间的推移而更新,在宽限期内(默认30s),pod被视为dead
-
将pod标记为terminating状态
-
kubelet 在监控到 pod 对象转为 terminating 状态的同时启动 pod 关闭过程
-
endpoints 控制器监控到 pod 对象的关闭行为时将其从所有匹配到此端点的 service 资源的端点列表中移除
-
如果当前 pod 对象定义了 preStop 钩子处理器,则在其标记为 terminating 后即会以同步的方式启动执行
-
pod 对象中的容器进程收到 (TERM) 停止信号
-
宽限期结束后,若pod中还存在仍在运行的进程,那么pod对象会收到 (SIGKILL) 立即终止的信号
-
kubelet 请求 apiServer 将此 pod 资源的宽限期设置为0从而完成删除操作,此时pod对于用户已不可见
Kubernetes 会跟踪 Pod 中每个容器的状态,就像它跟踪 Pod 总体上的阶段一样。 你可以使用容器生命周期回调 来在容器生命周期中的特定时间点触发事件
-
一旦调度器将 Pod 分派给某个节点,kubelet 就通过容器运行时开始为 Pod 创建容器。容器的状态有三种:Waiting(等待)、Running(运行中)和 Terminated(已终止)。
-
要检查 Pod 中容器的状态,你可以使用
kubectl describe pod <pod 名称>
。 其输出中包含 Pod 中每个容器的状态。
Waiting
(等待) ¶
如果容器并不处在 Running
或 Terminated
状态之一,它就处在 Waiting
状态。 处于 Waiting
状态的容器仍在运行它完成启动所需要的操作:例如, 从某个容器镜像仓库拉取容器镜像,或者向容器应用 Secret
数据等等。 当你使用 kubectl
来查询包含 Waiting
状态的容器的 Pod 时,你也会看到一个 Reason 字段,其中给出了容器处于等待状态的原因。
Running
(运行中) ¶
Running
状态表明容器正在执行状态并且没有问题发生。 如果配置了 postStart
回调,那么该回调已经执行且已完成。 如果你使用 kubectl
来查询包含 Running
状态的容器的 Pod 时, 你也会看到关于容器进入 Running
状态的信息。
Terminated
(已终止) ¶
处于 Terminated
状态的容器已经开始执行并且或者正常结束或者因为某些原因失败。 如果你使用 kubectl
来查询包含 Terminated
状态的容器的 Pod 时, 你会看到容器进入此状态的原因、退出代码以及容器执行期间的起止时间。
如果容器配置了 preStop
回调,则该回调会在容器进入 Terminated
状态之前执行
pod在整个生命周期中有非常多的用户行为:
- 1、初始化容器完成初始化
- 2、主容器启动后可以做启动后钩子
- 3、主容器结束前可以做结束前钩子
- 4、在主容器运行中可以做一些健康检测,如liveness probe,readness probet