在Kubernetes中,Pod的生命周期经历了几个重要的阶段。下面是Pod生命周期的详细介绍:
-
-
资源分配
### 初始化容器的生命周期1. 定义阶段:- 在Pod的定义中,初始化容器与主容器一起列在Pod的规范(spec)中。每个初始化容器都可以有自己的镜像、命令、环境变量等配置。 2. 创建阶段:- 当Pod被创建时,初始化容器会根据Pod的规范进行启动。它们按照定义的顺序逐个启动。每个初始化容器都必须成功完成后,才会启动下一个初始化容器。 3. 启动阶段:- 顺序执行: 初始化容器会按照Pod规范中定义的顺序依次启动。如果一个初始化容器启动失败,Kubernetes会重试这个容器,直到成功或达到最大重试次数。- 完成任务: 每个初始化容器会执行其定义的任务,并且必须成功退出(以状态码0结束)。如果容器失败退出(以非零状态码结束),Kubernetes会重试,直到容器成功完成或者重试次数达到限制。 4. 过渡到运行阶段:- 成功: 当所有的初始化容器成功完成其任务后,Pod会进入“Running”状态,随后主容器(Containers)才会启动。- 失败: 如果某个初始化容器失败并且达到重试次数限制,整个Pod会标记为失败,主容器不会启动。 5. 终止阶段:- 终止: 一旦Pod的生命周期结束(无论是正常完成还是失败),初始化容器也会随之终止。Kubernetes会处理容器的清理工作,包括删除容器的日志和其他临时文件。> ### 初始化容器的特点 > > - 顺序性: 初始化容器按定义顺序执行,一个初始化容器完成后,才会开始下一个初始化容器。 > - 隔离性: 初始化容器在Pod中的主容器之前运行,它们可以有不同的镜像和配置,与主容器的环境相互隔离。 > - 重试机制: 如果初始化容器失败,Kubernetes会根据配置的重试策略重试该容器,直到成功或者达到重试限制。 > > ### 使用场景 > > 初始化容器非常适用于以下场景: > > - 数据库初始化: 在应用启动之前执行数据库迁移或初始化操作。 > - 配置检查: 检查或生成配置文件,确保主容器启动所需的环境准备好。 > - 依赖服务检查: 确保所需的外部服务或资源在主容器启动之前可用。 > > 初始化容器提供了一种在Pod启动之前执行预处理任务的灵活方式,使得Pod的主容器能够在正确的环境中运行。
-
-
健康检查
5.Unknown(未知):
-
-
Grace Period: Kubernetes会尊重Pod的终止宽限期(Grace Period),允许容器在关闭前完成它们的清理工作。终止宽限期可以通过Pod的
terminationGracePeriodSeconds
了解这些状态对于管理和调试Kubernetes中的应用非常重要。每个阶段和状态都有其特定的含义和影响,掌握它们可以帮助你更好地理解和控制Pod的行为。
二、Pod的探针
Kubernetes中的Pod探针用于检测容器的健康状态和就绪状态。主要有三种探针:
-
Liveness Probe(存活探针): 检查容器是否正常运行。如果探针失败,Kubernetes会重启容器。适用于检测容器是否陷入了死循环或挂起状态。
-
Readiness Probe(就绪探针): 确定容器是否准备好接受流量。探针失败会导致Pod从服务的负载均衡池中移除,直到容器恢复就绪状态。
-
Startup Probe(启动探针): 检测容器是否已启动。用于处理启动时需要较长时间的应用,避免在启动阶段被误判为不健康。(常用于脚本)
探针通常通过HTTP请求、TCP连接或执行命令来进行检查。
在Kubernetes中,Pod的两个钩子是:
-
-
postStart
: 在容器启动后立即执行的钩子。适用于需要在容器启动后执行某些任务的场景,例如初始化配置或启动一些后台进程。 -
preStop
: 在容器停止之前执行的钩子。适用于在容器停止之前进行清理操作或保存状态等操作。
生命周期钩子允许在容器的生命周期中特定的时间点执行自定义的脚本或命令。它们帮助开发者在容器的启动或停止时执行必要的操作。
-
-
终止钩子(Termination Hooks):
-
终止钩子是一个与生命周期钩子相似的概念,但在Kubernetes中并没有明确标记为“终止钩子”。而是在
preStop
-
apiVersion: v1 kind: Pod metadata:name: example-pod spec:containers:- name: example-containerimage: example-imagelifecycle:postStart:exec:command: ["/bin/sh", "-c", "echo 'Container started' > /var/log/startup.log"]preStop:exec:command: ["/bin/sh", "-c", "echo 'Container is stopping' > /var/log/shutdown.log"]
-
: 用于在容器启动后执行操作,比如配置、启动服务、或者进行一些初始化工作。需要注意的是,
postStart
-
preStop
: 用于在容器停止之前执行清理任务,比如关闭连接、清理缓存或保存数据。preStop
钩子是同步的,Kubernetes会等待钩子完成后才会真正停止容器。
这些钩子提供了一种在容器生命周期特定阶段执行自定义操作的方式,有助于确保容器的状态管理和资源清理。
Pod的删除过程在Kubernetes中涉及几个关键步骤。了解这些步骤有助于更好地管理Pod的生命周期和确保应用的平稳运行。以下是Pod删除的基本流程:
Pod running----Terminating----prestop hook----SIGTRM----terminationGracePeriodSeconds----SIGKILL----Deleted
当你通过kubectl delete pod <pod-name>
命令或通过API请求删除Pod时,Kubernetes会开始删除过程。
Kubernetes将Pod的状态标记为Terminating
。此时,Pod仍然存在,但已经不再接受新的流量或请求。
preStop
钩子(如果有)
如果Pod配置了preStop
生命周期钩子,Kubernetes会在停止容器之前执行这个钩子。preStop
钩子是同步的,Kubernetes会等待钩子完成后才会继续删除容器。
一旦preStop
钩子(如果有)完成,Kubernetes会向容器发送终止信号(通常是SIGTERM
)。容器接收到信号后应该开始优雅地关闭。
Kubernetes会等待容器在设定的terminationGracePeriodSeconds
(默认30秒)内完成关闭过程。这个时间可以通过Pod的spec配置项进行调整。如果容器在规定时间内没有优雅地关闭,Kubernetes会发送强制终止信号(SIGKILL
)来强制关闭容器。
容器关闭后,Kubernetes会从集群中删除Pod对象,包括相关的所有资源(例如日志、事件记录等)。Pod的终止状态也会被更新到Terminated
。
如果Pod是由ReplicaSet或Deployment管理的,ReplicaSet或Deployment控制器会检测到Pod的删除,并根据策略创建新的Pod以维持期望的副本数。
8. 清理如果Pod在删除之前进行了任何网络连接、挂载卷或存储的操作,Kubernetes会在Pod删除过程中清理这些资源,确保系统资源得到释放和回收。
#示例: apiVersion: v1 kind: Pod metadata:name: example-pod spec:containers:- name: example-containerimage: example-imagelifecycle:preStop:exec:command: ["/bin/sh", "-c", "echo 'Cleaning up before shutdown' > /var/log/shutdown.log"]
总结:
name: (string) ReplicaSet 的名字。 namespace: (string) ReplicaSet 所在的命名空间。 labels: (map[string]string) 一组标签,用于标识和选择对象。 annotations: (map[string]string) 由用户定义的附加信息,用于存储任意的元数据。 creationTimestamp: (string) ReplicaSet 的创建时间。
replicas: (int32) 要维持的 Pod 副本数量。这个字段是可选的,如果未指定,默认值为 1。
selector: (LabelSelector) 选择器,用于指定要管理的 Pod。这个字段定义了一个标签选择器,用于选择 ReplicaSet 要管理的 Pod。matchLabels: (map[string]string) 一组标签键值对,用于匹配 Pod。matchExpressions: ([]LabelSelectorRequirement) 用于选择 Pod 的表达式。
template: (PodTemplateSpec) Pod 模板,用于创建管理的 Pod。包含以下字段:metadata: (ObjectMeta) Pod 的元数据,通常包含标签和注释。spec: (PodSpec) Pod 的规范,定义了容器、卷、网络等。containers: ([]Container) Pod 中的容器列表,每个容器定义了镜像、端口等。volumes: ([]Volume) Pod 中的卷定义,用于存储数据。
replicas: (int32) 当前 Pod 副本的数量。
fullyLabeledReplicas: (int32) 完全符合选择器的 Pod 数量。
readyReplicas: (int32) 准备就绪的 Pod 数量。
availableReplicas: (int32) 可用的 Pod 数量。
observedGeneration: (int64) 观察到的 ReplicaSet 的版本号。用于检测状态的更新。
在 Kubernetes 中,Pod 节点选择器(Node Selector)是一种用于指定 Pod 应该调度到哪个节点的机制。通过节点选择器,您可以控制 Pod 在集群中运行的节点,确保它们在符合特定条件的节点上运行。
如何使用节点选择器
kubectl label nodes <node-name> role=frontend
apiVersion: v1 kind: Pod metadata:name: my-pod spec:containers:- name: my-containerimage: my-imagenodeSelector:role: frontend
示例:Pod 将只会调度到具有 `disktype=ssd` 标签的节点上 apiVersion: v1 kind: Pod metadata:name: example-pod spec:containers:- name: example-containerimage: nginxnodeSelector:disktype: ssd
注意事项:
-
节点选择器的限制:节点选择器只能基于节点的标签来做选择,比较简单。如果需要更复杂的调度策略,可以使用
affinity
或taints and tolerations
。 -
节点标签:确保节点已经正确地标记了标签,否则 Pod 可能会因为找不到符合条件的节点而无法调度。
-
多重标签匹配:如果节点有多个标签,节点选择器会匹配所有指定的标签条件。
通过合理配置节点选择器,您可以优化资源分配,提高 Pod 的性能和稳定性。
kubectl label pod <pod-name> <key>=<value>
-
<pod-name>
-
<key>
:标签的键。 -
<value>
:标签的值。
例如,为名为 my-pod
的 Pod 打上标签 env=production
:
kubectl label pod my-pod env=production
查看所有 Pods 的标签
kubectl get pods --show-labels
查看特定 Pod 的标签
kubectl describe pod <pod-name>
只显示特定 Pod 的标签
kubectl get pod <pod-name> --template '{{range $k, $v := .metadata.labels}}{{$k}}: {{$v}}{{"\n"}}{{end}}'
这条命令只显示指定 Pod 的标签,以键值对的形式。
查看指定标签名的pod信息
kubectl get pods -L project,app
kubectl get pods -l app=myapp
查看所有 Nodes 的标签
kubectl get nodes --show-labels
查看特定 Node 的标签
kubectl describe node <node-name>
只显示特定 Node 的标签
kubectl get node <node-name> --template '{{range $k, $v := .metadata.labels}}{{$k}}: {{$v}}{{"\n"}}{{end}}'
这条命令只显示指定 Node 的标签,以键值对的形式。
kubectl get nodes -L project
kubectl get node -l nodemaster=yes
kubectl label pod <pod-name> <key>-
-
<pod-name>
:Pod 的名称。 -
<key>
:要删除的标签的键。
例如,删除名为 my-pod
的 Pod 上的 env
kubectl label pod my-pod env-
5.指定节点
方法一:通过nodeName方式
apiVersion: apps/v1 kind: ReplicaSet metadata:name: my-replicaset spec:replicas: 4selector:matchLabels:app: myapptemplate:metadata:labels:app: myappspec:nodeName: node1containers:- name: mycontainerimage: harbor.hiuiu.com/nginx/nginx:1.21.5imagePullPolicy: Neverports:- containerPort: 80kubectl apply -f replicaset.yamlkubectl get pod -o wide
方法二:通过nodeSelector方式
#将pod加入标签为nodemaster=yes的node中,ReplicaSet只管理label为app=myapp的pod
kubectl explain rs.spec.template.spec.nodeSelectorapiVersion: apps/v1 kind: ReplicaSet metadata:name: my-replicaset spec:replicas: 4selector:matchLabels:app: myapptemplate:metadata:labels:app: myappspec:nodeSelector:nodemaster: "yes"containers:- name: mycontainerimage: harbor.hiuiu.com/nginx/nginx:1.21.5imagePullPolicy: Neverports:- containerPort: 80kubectl apply -f replicaset.yamlkubectl get pod -o wide
Kubernetes 的节点亲和性(Node Affinity)是一种调度机制,用于控制 Pod 被调度到哪些节点上。它允许你指定 Pod 应该运行在哪些特定的节点上,基于节点的标签。
节点亲和性是节点选择的扩展,它的配置方式类似于 Pod 的调度策略,通过在 Pod 的 spec.affinity.nodeAffinity
部分进行定义。
节点亲和性的基本概念
节点亲和性定义了 Pod 对节点的选择规则。它可以是:
-
必需亲和性(RequiredDuringSchedulingIgnoredDuringExecution):这些规则必须满足,否则 Pod 将不会被调度到节点上。它是强制性的。
-
优先亲和性(PreferredDuringSchedulingIgnoredDuringExecution):这些规则是优先考虑的,但不是强制性的。Kubernetes 将尽量满足这些规则,但如果无法满足,也不会阻止 Pod 调度。
必需亲和性
kubectl explain pods.spec.affinity.nodeAffinity.requiredDuringSchedulingIgnoredDuringExecution
#pod必须加入标签为zone=ky36或zone=ccc的node中
apiVersion: v1 kind: Pod metadata:name: pod-node-affinity-demonamespace: defaultlabels:app: myapp spec:containers:- name: myappimage: harbor.hiuiu.com/nginx/nginx:1.21.5affinity:nodeAffinity:requiredDuringSchedulingIgnoredDuringExecution:nodeSelectorTerms:- matchExpressions:- key: zoneoperator: Invalues:- ky36- ccckubectl apply -f replicaset.yamlkubectl get pod -o wide
优先亲和性
kubectl explain pods.spec.affinity.nodeAffinity.preferredDuringSchedulingIgnoredDuringExecution
apiVersion: v1 kind: Pod metadata:name: pod-node-affinity-demonamespace: defaultlabels:app: myapp spec:containers:- name: myappimage: harbor.hiuiu.com/nginx/nginx:1.21.5affinity:nodeAffinity:preferredDuringSchedulingIgnoredDuringExecution:nodeSelectorTerms:- matchExpressions:- key: zoneoperator: Invalues:- ky36- ccckubectl apply -f replicaset.yaml kubectl get pod -o wide
kubectl explain pods.spec.affinity.podAffinity.requiredDuringSchedulingIgnoredDuringExecution.topologyKey yaml1 apiVersion: v1 kind: Pod metadata:name: pod-firstlabels:app2: myapp2tier: frontend spec:containers:- name: myappimage: harbor.hiuiu.com/nginx/nginx:1.21.5yaml2 apiVersion: v1 kind: Pod metadata:name: pod-secondlabels:app: backendtier: db spec:containers:- name: mysqlimage: harbor.hiuiu.com/nginx/nginx:1.21.5imagePullPolicy: IfNotPresentaffinity:podAffinity:requiredDuringSchedulingIgnoredDuringExecution:- labelSelector:matchExpressions:- key: app2operator: Invalues:- myapp2topologyKey: kubernetes.io/hostname
kubectl apply -f pod1.yaml
kubectl apply -f pod2.yaml
kubectl get pod -o wide
3.Pod 反亲和性
kubectl explain pods.spec.affinity.podAntiAffinity.requiredDuringSchedulingIgnoredDuringExecution.topologyKey
kubectl explain pod.spec.containers.imagePullPolicy
##imagePullPolicy (镜像拉取策略)::IfNotPresent:node节点没有此镜像就去指定的镜像仓库拉取,node有就使用node本地镜像。Always:每次重建pod都会重新拉取镜像Never:从不到镜像中心拉取镜像,只使用本地镜
kubectl explain pod.spec.restartPolicyrestartPolicy- `"Always"` - `"Never"` - `"OnFailure"`