一、Kubernetes 中的 Pod 概述
-
Pod 的定义和作用
- Pod 是一个或多个容器的组合,是 Kubernetes 的最小管理单元。
- Pod 中所有容器共享存储、网络和命名空间,以及运行规范。
- Pod 是一组具有共享命名空间、IP 地址和端口的容器的集合,包含业务相关的多个应用容器,是应用的逻辑主机。
-
Pod 与容器的关系
- 单个容器往往无法单独支撑应用,需要多个微服务组成系统,且存在服务依赖和共享目录等问题,而 Pod 可以解决这些问题。
- Docker 是一种容器 Runtime,Kubernetes 需要支持各个 Runtime 且不依赖于底层实现技术,因此抽象出 Pod 概念来管理多个紧密相连的符合 CRI 标准的容器。
- Pod 包含一个 Pause 容器,负责僵尸进程的回收管理,使同一个 Pod 中的不同容器共享存储、网络、PID、IPC 等。
二、Pod 的状态
-
常见的 Pod 状态及说明
- Pending(挂起):Pod 已经被 Kubernetes 系统接收,但仍有一个或多个容器未被创建,可通过
kubectl describe
查看原因。 - Running(运行中):Pod 已被绑定到一个节点上,所有容器都已创建,至少有一个容器正在运行、正在启动或重启,可通过
kubectl logs
查看日志。 - Succeeded:所有容器执行成功并终止,且不会再次重启,可通过
kubectl logs
查看日志。 - Failed(失败):所有容器都已终止,至少有一个容器以失败方式终止,容器要么以非零状态退出,要么被系统终止,可通过
logs
和describe
查看日志和状态。 - Unknown(未知):通常由于通信问题造成无法获得 Pod 的状态。
- ImagePullBackOff/ErrImagePull:镜像拉取失败,一般是由于镜像不存在、网络不通或需要登录认证引起,可使用
describe
命令查看具体原因。 - CrashLoopBackOff:容器启动失败,可通过
logs
命令查看具体原因,一般为启动命令不正确、健康检查不通过等。 - OOMKilled:容器内存溢出,一般是容器的内存 Limit 设置过小,或者程序本身有内存溢出,可通过
logs
查看程序的启动日志。 - Terminating:Pod 正在被删除,可通过
describe
查看状态。 - SysctlForbiden:Pod 自定义了内核配置,但
kubectl
没有添加内核配置或配置的内核参数不支持,可通过describe
查看具体原因。 - Completed:容器内部主进程退出,一般计划任务执行结束会显示该状态,此时可通过
logs
查看容器日志。 - ContainerCreating:Pod 正在创建,一般正在下载镜像,或者有配置不当的地方,可通过
describe
查看具体原因。
- Pending(挂起):Pod 已经被 Kubernetes 系统接收,但仍有一个或多个容器未被创建,可通过
-
查看 Pod 状态的命令
kubectl get pods -n default
:查看默认命名空间下的 Pod。kubectl get pod nginx -o wide
:显示 Pod 的更多信息,包括 IP、NODE 等。kubectl describe pod nginx
:显示 Pod 的详细描述信息。
三、Pod 探针
-
Pod 探针的检测方式
- ExecAction:在容器内执行指定命令,若命令返回值为 0,则认为容器健康。
- TCPSocketAction:通过 TCP 连接检查容器指定端口,若端口开放,则认为容器健康。
- HTTPGetAction:对指定 URL 进行 Get 请求,若状态码在 200 - 400 之间,则认为容器健康。
-
Pod 探针的类型及作用
- livenessProbe(存活探针):判断容器是否正常运行,如果失败则杀掉容器(不是 Pod),再根据重启策略决定是否重启容器。
- readinessProbe(就绪探针):判断容器是否能够进入 ready 状态,探针失败则进入 noredy 状态,并从 service 的 endpoints 中剔除此容器。
- startupProbe(启动探针):判断容器内的应用是否启动成功,在 success 状态前,其它探针都处于无效状态。
四、Pod 镜像拉取策略和重启策略
-
镜像拉取策略的说明
- Always:总是拉取,无论镜像是否存在,总是拉取。
- Never:无论是否存在都不会拉取。
- IfNotPresent:镜像不存在时拉取镜像,是 Kubernetes 默认的策略,但是如果 tag 为 latest,则总是拉取。
- 指定拉取策略的命令:
kubectl run nginx --image=nginx:1.7.9 --labels="app=nginx" --image-pull-policy=Never
。
-
重启策略的操作方式
- Always:默认策略,容器失效时,自动重启该容器。
- OnFailure:容器以不为 0 的状态码终止,自动重启该容器。
- Never:无论何种状态,都不会重启。
- 指定重启策略的命令:
kubectl delete pod nginx
,kubectl run nginx --image=nginx:1.7.9 --labels="app=nginx" --restartOnFailure
。
五、创建 Pod 的步骤
-
编写 Pod 配置文件
- 例如:
vim nginx-pod.yaml
,内容如下:
- 例如:
apiVersion: v1
kind: Pod
metadata:
name: nginx
labels:
name: nginx
spec:
containers:
- name: nginx
image: nginx:1.7.9
ports:
- containerPort: 80
-
运行命令创建 Pod
kubectl create -f frontend-localredis-pod.yaml
。
-
查看 Pod 信息
kubectl get pods
:查看已经创建的 Pod。kubectl describe pod redis-php
:查看 Pod 详细创建信息。kubectl delete -f frontend-localredis-pod.yaml
:删除 Pod。
六、Pod 的基本用法
-
将容器放在同一个 Pod 中
- 编写
nginx-php.yaml
文件,内容如下:
- 编写
apiVersion: v1
kind: Pod
metadata:
name: nginx-php
labels:
name: nginx-php
spec:
containers:
- name: nginx-app
image: nginx:1.7.9
ports:
- containerPort: 80
- name: php-app
image: bitnami/php-fpm
imagePullPolicy: Never
ports:
- containerPort: 9000
-
部署 Pod 文件
kubectl apply -f nginx-php.yaml
。kubectl get pods
:查看 Pod 状态。
-
查看 Pod 详细信息
kubectl describe pod nginx-php
。
-
暴露端口
kubectl expose pod nginx-php --port=88 --target-port=80 --type=NodePort --name=nginx-php
。
-
查看端口映射
kubectl get pod,svc nginx-php -o wide
。
-
测试访问
- 用外部主机,访问 master 的 ip 地址:映射的端口,例如:
http://192.168.10.101:32598/
。
- 用外部主机,访问 master 的 ip 地址:映射的端口,例如:
-
删除 Pod
kubectl delete -f nginx-php.yaml
。
静态 Pod
- 静态 Pod 的管理方式
- 由 kubelet 进行管理,仅存在于各个 Node 上,不能通过 API Server 进行管理,无法与 ReplicationController、Deployment 或者 DaemonSet 进行关联,kubelet 无法对它们进行健康检查。
- 总是由 kubelet 创建,且总在 kubelet 所在的 Node 上运行。
- 删除静态 Pod 的方法
rm -rf /etc/kubernetes/manifests/nginx-pod.yaml
。- 不能用
kubectl delete pod static-web-k8s-master01
删除,会让 Pod 处于 pending 状态,但无法删除。
七、Pod 启动阶段
-
Pod 启动过程的步骤
- 调度到某台 node 上,Kubernetes 根据一定的优先级算法选择一台 node 节点将其作为 Pod 运行的 node。
- 拉取镜像。
- 挂载存储配置等。
- 运行起来,如果有健康检查,会根据检查的结果来设置其状态。
-
phase 的可能状态
- Pending:表示 APIServer 创建了 Pod 资源对象并已经存入了 etcd 中,但是它并未被调度完成(比如还没有调度到某台 node 上),或者仍然处于从仓库下载镜像的过程中。
- Running:Pod 已经被调度到某节点之上,并且 Pod 中所有容器都已经被 kubelet 创建,至少有一个容器正在运行,或者正处于启动或者重启状态(也就是说 Running 状态下的 Pod 不一定能被正常访问)。
- Succeeded:有些 Pod 不是长久运行的,比如 job、cronjob,一段时间后 Pod 中的所有容器都被成功终止,并且不会再重启,需要反馈任务执行的结果。
- Failed:Pod 中的所有容器都已终止了,并且至少有一个容器是因为失败终止,也就是说,容器以非 0 状态退出或者被系统终止,比如 command 写的有问题。
- Unknown:表示无法读取 Pod 状态,通常是 kube - controller - manager 无法与 Pod 通信。
八、故障排除步骤
- 查看 Pod 事件:
kubectl describe TYPE NAME_PREFIX
。 - 查看 Pod 日志(Failed 状态下):
kubectl logs <POD_NAME> [-C Container_NAME]
。 - 进入 Pod(状态为 running,但是服务没有提供):
kubectl exec -it <POD_NAME> bash
。 - 查看集群信息:
kubectl get nodes
,kubectl cluster-info
。 - 查看 kubelet 日志发现:
journalctl -xefu kubelet
。