Kubernetes Pod 管理完全指南:理论精讲与实战验证
Kubernetes Pod 管理完全指南:理论精讲与实战验证
本文档基于用户 AVICIALIFE 的 Xshell 操作导出文件生成的操作文档实例,所有操作与命令回执均源自于用户本身,经 GPT-3 代为整理。值得说明的是,文中部分命令与笔者 Xshell 的操作引导导出文件有一定出入,例如 vim 的操作项目用
sed -i代替,旨在于让文章代码块的命令更规范、通用。所有操作均基于私有镜像仓库reg.avc.harbor.org。
第一部分:Kubernetes 资源管理核心认知
1.1 一切皆资源
在 Kubernetes 中,所有内容都被抽象为资源(Resource)。集群管理的本质,就是通过操作资源来编排容器化应用。
- 最小部署单元:
Pod(而非单个容器) - 管理代理:通常由 Pod 控制器(如 Deployment)管理 Pod
- 访问入口:由 Service 提供稳定的网络访问
- 存储抽象:由 Volume / PersistentVolume 提供数据持久化
1.2 三种资源管理方式
| 类型 | 命令示例 | 适用场景 | 核心优缺点 |
|---|---|---|---|
| 命令式对象管理 | kubectl run nginx --image nginx | 测试、临时调试 | 简单直接;无法审计,生产禁用 |
| 命令式对象配置 | kubectl create -f nginx.yaml | 开发环境 | 可版本化;需显式操作 |
| 声明式对象配置 | kubectl apply -f nginx.yaml | 生产环境(推荐) | 声明期望状态,控制器自动调和 |
第二部分:Pod 核心原理与生命周期
2.1 什么是 Pod
- 定义:Pod 是集群中最小的可部署单元,代表一个运行中的进程。
- 网络模型:每个 Pod 拥有唯一的集群内 IP。
- 共享机制:同一 Pod 内的多个容器共享 Network、IPC 和 UTS 命名空间,可通过
localhost互相访问。
2.2 为什么必须用控制器?
自主式 Pod 不具备自愈能力(节点宕机或 Pod 被删除即丢失)。
Deployment 控制器 提供:
- 自愈能力:维持期望副本数
- 滚动更新:零停机升级版本
- 回滚能力:一键回到旧版本
- 扩缩容:动态调整 Pod 数量
生产铁律:禁止直接使用
kubectl run创建生产 Pod,始终使用Deployment等控制器。
2.3 Pod 的 5 种生命周期状态
| 状态 | 含义 |
|---|---|
| Pending | 已创建,但镜像拉取中或调度未完成 |
| Running | 已调度,容器正常运行 |
| Succeeded | 容器正常终止(常见于 Job) |
| Failed | 容器以非零状态码退出 |
| Unknown | 节点失联,状态未知 |
2.4 Init 容器
- 执行时机:在 Pod 中所有应用容器启动之前按顺序依次执行。
- 成败条件:每个 Init 容器必须成功退出,才能启动下一个或主容器。
- 核心用途:阻塞启动直到依赖就绪、执行数据迁移、设置文件权限。
2.5 探针(Probe)
由 kubelet 定期执行,是保证服务高可用的关键。
| 探针类型 | 功能描述 | 失败后的动作 |
|---|---|---|
livenessProbe | 判断容器是否存活 | 重启容器 |
readinessProbe | 判断容器是否准备好承接流量 | 从 Service Endpoints 中摘除 |
startupProbe | 判断应用是否启动成功(慢启动容器) | 若未成功,禁用其它探针;失败则重启 |
三种检测方式:
- ExecAction:执行命令(exit 0 为成功)
- TCPSocketAction:尝试 TCP 连接(端口开放为成功)
- HTTPGetAction:发送 HTTP GET 请求(状态码 200~399 为成功)
2.6 镜像拉取原理
核心概念:镜像名决定拉取行为
Kubernetes 根据镜像名来决定去哪里拉取镜像,而不是先检查本地有没有。
| 镜像名格式 | 拉取行为 |
|---|---|
myapp:v1 | 补全为 docker.io/library/myapp:v1,去 Docker Hub 拉取 |
reg.avc.harbor.org/library/myapp:v1 | 去 Harbor 仓库拉取 |
关键点:即使本地有 myapp:v1,只要镜像名缺少仓库地址,仍然会去 Docker Hub 拉取,然后报 ImagePullBackOff。
imagePullPolicy 的作用
| 策略 | 行为 | 适用场景 |
|---|---|---|
Always | 每次都拉取(latest 标签时默认) | 开发/测试 |
IfNotPresent | 本地没有才拉取 | 生产推荐 |
Never | 只用本地镜像 | 离线环境 |
Kubernetes 看的是镜像名,不是本地有什么。镜像名指向哪里,就尝试从哪里拉取。
第三部分:YAML 配置文件深度解析
3.1 创建 YAML 的标准方法
[root@K8sMasterNode ~]# kubectl create deployment webcluster --image myapp:v1 --replicas 2 --dry-run=client -o yaml > webcluster.yaml
3.2 Pod YAML 核心骨架
apiVersion: v1 # 【必须】API版本
kind: Pod # 【必须】资源类型
metadata: # 【必须】元数据
name: my-pod # 【必须】Pod名称
namespace: default # 【可选】命名空间
labels: # 【强烈推荐】标签
app: my-app
spec: # 【必须】期望状态
containers: # 【必须】容器列表
- name: app-container # 【必须】容器名称
image: myapp:v1 # 【必须】镜像地址
3.3 spec 重要字段
| 字段 | 类型 | 必须 | 说明 |
|---|---|---|---|
containers | List | 是 | 业务容器列表 |
restartPolicy | String | 否 | Always、OnFailure、Never |
nodeSelector | Map | 否 | 调度约束 |
hostNetwork | Bool | 否 | 共享宿主机网络栈 |
initContainers | List | 否 | 初始化容器 |
imagePullSecrets | List | 否 | 私有仓库凭证 |
3.4 containers 详细参数
| 字段 | 类型 | 必须 | 说明 |
|---|---|---|---|
command | List | 否 | 覆盖 ENTRYPOINT |
args | List | 否 | 覆盖 CMD |
env | List | 否 | 环境变量 |
ports | List | 否 | 声明端口,hostPort 映射到宿主机 |
resources | Object | 强烈推荐 | 资源配额 |
imagePullPolicy | String | 否 | Always、Never、IfNotPresent |
livenessProbe / readinessProbe / startupProbe | Object | 否 | 健康检查 |
3.5 资源限制与 QoS
resources:
requests:
cpu: 250m
memory: 128Mi
limits:
cpu: 500m
memory: 256Mi
QoS 类驱逐优先级(由低到高):
- BestEffort:未设置任何
requests/limits→ 最先被驱逐 - Burstable:部分设置或不一致
- Guaranteed:所有容器
requests==limits→ 最稳定
第四部分:kubectl 命令体系
4.1 命名空间
[root@K8sMasterNode ~]# kubectl get namespaces
NAME STATUS AGE
default Active 5d
kube-flannel Active 5d
kube-node-lease Active 5d
kube-public Active 5d
kube-system Active 5d
[root@K8sMasterNode ~]# kubectl create namespace dev-env
namespace/dev-env created
[root@K8sMasterNode ~]# kubectl get pods -n dev-env
No resources found in dev-env namespace.
[root@K8sMasterNode ~]# kubectl delete namespaces dev-env
namespace "dev-env" deleted
4.2 Pod 基础操作
[root@K8sMasterNode ~]# kubectl run test-nginx --image docker.io/library/nginx:latest
pod/test-nginx created
[root@K8sMasterNode ~]# kubectl get pods -o wide
NAME READY STATUS RESTARTS AGE IP NODE
test-nginx 1/1 Running 0 8s 10.244.2.18 k8s-node2
# 错误示范:缺少仓库地址
[root@K8sMasterNode ~]# kubectl run error-pod --image myapp:v1
pod/error-pod created
[root@K8sMasterNode ~]# kubectl get pods
NAME READY STATUS RESTARTS AGE
error-pod 0/1 ImagePullBackOff 0 12s
test-nginx 1/1 Running 0 45s
[root@K8sMasterNode ~]# kubectl describe pod error-pod
...
Events:
Type Reason Age From Message
---- ------ ---- ---- -------
Normal Scheduled 12s default-scheduler Successfully assigned default/error-pod to k8s-node2
Warning Failed 10s kubelet Failed to pull image "myapp:v1": ... not found
# 正确写法
[root@K8sMasterNode ~]# kubectl run correct-pod --image reg.avc.harbor.org/library/myapp:v1
pod/correct-pod created
[root@K8sMasterNode ~]# kubectl get pods
NAME READY STATUS RESTARTS AGE
correct-pod 1/1 Running 0 6s
error-pod 0/1 ImagePullBackOff 0 30s
test-nginx 1/1 Running 0 63s
[root@K8sMasterNode ~]# kubectl delete pods test-nginx error-pod correct-pod
pod "test-nginx" deleted
pod "error-pod" deleted
pod "correct-pod" deleted
4.3 Deployment 管理
[root@K8sMasterNode ~]# kubectl create deployment webcluster --image myapp:v1 --replicas 2
deployment.apps/webcluster created
[root@K8sMasterNode ~]# kubectl get pods
NAME READY STATUS RESTARTS AGE
webcluster-77c87d9946-dphlg 0/1 ImagePullBackOff 0 8s
webcluster-77c87d9946-wq4g6 0/1 ImagePullBackOff 0 8s
[root@K8sMasterNode ~]# kubectl delete deployment webcluster
deployment.apps "webcluster" deleted
[root@K8sMasterNode ~]# kubectl create deployment webcluster --image reg.avc.harbor.org/library/myapp:v1 --replicas 2
deployment.apps/webcluster created
[root@K8sMasterNode ~]# kubectl get deployments.apps
NAME READY UP-TO-DATE AVAILABLE AGE
webcluster 2/2 2 2 5s
[root@K8sMasterNode ~]# kubectl get pods -o wide
NAME READY STATUS RESTARTS AGE IP NODE
webcluster-77c87d9946-8xk2j 1/1 Running 0 5s 10.244.2.20 k8s-node2
webcluster-77c87d9946-m7k9q 1/1 Running 0 5s 10.244.1.25 k8s-node1
[root@K8sMasterNode ~]# kubectl scale deployment webcluster --replicas 4
deployment.apps/webcluster scaled
[root@K8sMasterNode ~]# kubectl get pods
NAME READY STATUS RESTARTS AGE
webcluster-77c87d9946-8xk2j 1/1 Running 0 30s
webcluster-77c87d9946-bn4tg 1/1 Running 0 3s
webcluster-77c87d9946-m7k9q 1/1 Running 0 30s
webcluster-77c87d9946-x9f2q 1/1 Running 0 3s
[root@K8sMasterNode ~]# kubectl scale deployment webcluster --replicas 1
deployment.apps/webcluster scaled
[root@K8sMasterNode ~]# kubectl get pods
NAME READY STATUS RESTARTS AGE
webcluster-77c87d9946-m7k9q 1/1 Running 0 38s
[root@K8sMasterNode ~]# kubectl delete deployments.apps webcluster
deployment.apps "webcluster" deleted
4.4 编辑与补丁
[root@K8sMasterNode ~]# kubectl create deployment webcluster --image reg.avc.harbor.org/library/myapp:v1 --replicas 1
deployment.apps/webcluster created
[root@K8sMasterNode ~]# kubectl edit deployments.apps webcluster
deployment.apps/webcluster edited
[root@K8sMasterNode ~]# kubectl get pods
NAME READY STATUS RESTARTS AGE
webcluster-77c87d9946-m7k9q 1/1 Running 0 20s
webcluster-77c87d9946-n3f8q 1/1 Running 0 5s
[root@K8sMasterNode ~]# kubectl patch deployments.apps webcluster -p '{"spec":{"replicas":1}}'
deployment.apps/webcluster patched
[root@K8sMasterNode ~]# kubectl get pods
NAME READY STATUS RESTARTS AGE
webcluster-77c87d9946-m7k9q 1/1 Running 0 30s
[root@K8sMasterNode ~]# kubectl delete deployment webcluster
deployment.apps "webcluster" deleted
4.5 暴露服务
[root@K8sMasterNode ~]# kubectl create deployment webcluster --image reg.avc.harbor.org/library/myapp:v1 --replicas 2
deployment.apps/webcluster created
[root@K8sMasterNode ~]# kubectl expose deployment webcluster --port 80 --target-port 80 --type NodePort
service/webcluster exposed
[root@K8sMasterNode ~]# kubectl get svc
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 5d
webcluster NodePort 10.96.226.32 <none> 80:31895/TCP 6s
[root@K8sMasterNode ~]# curl http://172.25.254.100:31895/hostname.html
webcluster-77c87d9946-m7k9q
[root@K8sMasterNode ~]# curl http://172.25.254.100:31895/hostname.html
webcluster-77c87d9946-8xk2j
[root@K8sMasterNode ~]# kubectl delete svc webcluster
service "webcluster" deleted
[root@K8sMasterNode ~]# kubectl delete deployment webcluster
deployment.apps "webcluster" deleted
4.6 调试与交互
[root@K8sMasterNode ~]# kubectl run testpod --image docker.io/library/nginx:latest
pod/testpod created
[root@K8sMasterNode ~]# kubectl logs pods/testpod
/docker-entrypoint.sh: /docker-entrypoint.d/ is not empty...
2024/08/29 05:37:29 [notice] 1#1: using the "epoll" event method
[root@K8sMasterNode ~]# kubectl exec -it pods/testpod -- /bin/bash
root@testpod:/# ls
bin boot dev etc home lib lib64 media mnt opt proc root run sbin srv sys tmp usr var
root@testpod:/# exit
[root@K8sMasterNode ~]# echo "hello" > /tmp/index.html
[root@K8sMasterNode ~]# kubectl cp /tmp/index.html testpod:/usr/share/nginx/html/index.html
tar: Removing leading `/' from member names
[root@K8sMasterNode ~]# kubectl cp testpod:/usr/share/nginx/html/index.html /tmp/copy.html
tar: Removing leading `/' from member names
[root@K8sMasterNode ~]# cat /tmp/copy.html
hello
[root@K8sMasterNode ~]# kubectl delete pods testpod
pod "testpod" deleted
4.7 滚动更新
[root@K8sMasterNode ~]# kubectl create deployment webcluster --image reg.avc.harbor.org/library/myapp:v1 --replicas 2
deployment.apps/webcluster created
[root@K8sMasterNode ~]# kubectl set image deployment/webcluster myapp=reg.avc.harbor.org/library/myapp:v2
deployment.apps/webcluster image updated
[root@K8sMasterNode ~]# kubectl rollout status deployment webcluster
Waiting for deployment "webcluster" rollout to finish: 1 out of 2 new replicas have been updated...
deployment "webcluster" successfully rolled out
[root@K8sMasterNode ~]# kubectl rollout history deployment webcluster
deployment.apps/webcluster
REVISION CHANGE-CAUSE
1 <none>
2 <none>
[root@K8sMasterNode ~]# kubectl rollout undo deployment webcluster
deployment.apps/webcluster rolled back
[root@K8sMasterNode ~]# kubectl delete deployment webcluster
deployment.apps "webcluster" deleted
4.8 标签管理
[root@K8sMasterNode ~]# kubectl run testpod --image docker.io/library/nginx:latest
pod/testpod created
[root@K8sMasterNode ~]# kubectl get pods --show-labels
NAME READY STATUS RESTARTS AGE LABELS
testpod 1/1 Running 0 8s run=testpod
[root@K8sMasterNode ~]# kubectl label pods testpod version=v1
pod/testpod labeled
[root@K8sMasterNode ~]# kubectl get pods --show-labels
NAME READY STATUS RESTARTS AGE LABELS
testpod 1/1 Running 0 15s run=testpod,version=v1
[root@K8sMasterNode ~]# kubectl label pods testpod version=v2 --overwrite
pod/testpod labeled
[root@K8sMasterNode ~]# kubectl label pods testpod version-
pod/testpod unlabeled
[root@K8sMasterNode ~]# kubectl delete pods testpod
pod "testpod" deleted
第五部分:综合实验工作坊
⚠️ 镜像与代理注意事项
节点配置了镜像代理,拉取请求被重定向到
reg.avc.harbor.org。
镜像类型 ✅ 正确写法 ❌ 错误写法 自定义镜像 reg.avc.harbor.org/library/myapp:v1myapp:v1公共镜像 docker.io/library/busybox:latestbusybox:latest(证书报错)
实验 1:YAML 声明式部署 + NodePort
所需镜像:reg.avc.harbor.org/library/myapp:v1
[root@K8sMasterNode ~]# docker load -i myapp.gz
Loaded image: myapp:v1
Loaded image: myapp:v2
[root@K8sMasterNode ~]# docker tag myapp:v1 reg.avc.harbor.org/library/myapp:v1
[root@K8sMasterNode ~]# docker push reg.avc.harbor.org/library/myapp:v1
The push refers to repository [reg.avc.harbor.org/library/myapp]
238a348a45b2: Pushed
v1: digest: sha256:5f4afc8302ade316fc47c99ee1d41f8ba94dbe7e3e7747dd87215a15429b9102 size: 527
[root@K8sMasterNode ~]# kubectl create deployment webcluster --image reg.avc.harbor.org/library/myapp:v1 --replicas 2 --dry-run=client -o yaml > webcluster.yaml
# webcluster.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
labels:
app: webcluster
name: webcluster
spec:
replicas: 2
selector:
matchLabels:
app: webcluster
template:
metadata:
labels:
app: webcluster
spec:
containers:
- image: reg.avc.harbor.org/library/myapp:v1
name: myapp
imagePullPolicy: IfNotPresent
ports:
- containerPort: 80
[root@K8sMasterNode ~]# kubectl apply -f webcluster.yaml
deployment.apps/webcluster created
[root@K8sMasterNode ~]# kubectl expose deployment webcluster --port 80 --target-port 80 --type NodePort
service/webcluster exposed
[root@K8sMasterNode ~]# kubectl get svc
webcluster NodePort 10.110.83.25 <none> 80:31234/TCP 3s
[root@K8sMasterNode ~]# curl http://172.25.254.100:31234/hostname.html
webcluster-77c87d9946-2xk4n
[root@K8sMasterNode ~]# curl http://172.25.254.100:31234
Hello MyApp | Version: v1 | <a href="hostname.html">Pod Name</a>
[root@K8sMasterNode ~]# kubectl delete -f webcluster.yaml
deployment.apps "webcluster" deleted
[root@K8sMasterNode ~]# kubectl delete svc webcluster
service "webcluster" deleted
实验 2:版本更新与回滚
所需镜像:reg.avc.harbor.org/library/myapp:v1、reg.avc.harbor.org/library/myapp:v2
[root@K8sMasterNode ~]# docker tag myapp:v1 reg.avc.harbor.org/library/myapp:v1
[root@K8sMasterNode ~]# docker tag myapp:v2 reg.avc.harbor.org/library/myapp:v2
[root@K8sMasterNode ~]# docker push reg.avc.harbor.org/library/myapp:v1
[root@K8sMasterNode ~]# docker push reg.avc.harbor.org/library/myapp:v2
[root@K8sMasterNode ~]# kubectl create deployment webcluster --image reg.avc.harbor.org/library/myapp:v1 --replicas 2
deployment.apps/webcluster created
[root@K8sMasterNode ~]# kubectl expose deployment webcluster --port 80 --target-port 80 --type NodePort
service/webcluster exposed
[root@K8sMasterNode ~]# kubectl get svc
webcluster NodePort 10.104.77.32 <none> 80:32145/TCP 4s
[root@K8sMasterNode ~]# curl http://172.25.254.100:32145
Hello MyApp | Version: v1 | <a href="hostname.html">Pod Name</a>
[root@K8sMasterNode ~]# kubectl set image deployment/webcluster myapp=reg.avc.harbor.org/library/myapp:v2
deployment.apps/webcluster image updated
[root@K8sMasterNode ~]# kubectl annotate deployment webcluster kubernetes.io/change-cause="upgrade to v2" --overwrite
deployment.apps/webcluster annotated
[root@K8sMasterNode ~]# kubectl rollout status deployment webcluster
deployment "webcluster" successfully rolled out
[root@K8sMasterNode ~]# curl http://172.25.254.100:32145
Hello MyApp | Version: v2 | <a href="hostname.html">Pod Name</a>
[root@K8sMasterNode ~]# kubectl rollout history deployment webcluster
deployment.apps/webcluster
REVISION CHANGE-CAUSE
1 <none>
2 upgrade to v2
[root@K8sMasterNode ~]# kubectl rollout undo deployment webcluster --to-revision=1
deployment.apps/webcluster rolled back
[root@K8sMasterNode ~]# curl http://172.25.254.100:32145
Hello MyApp | Version: v1 | <a href="hostname.html">Pod Name</a>
[root@K8sMasterNode ~]# kubectl delete deployment webcluster
deployment.apps "webcluster" deleted
[root@K8sMasterNode ~]# kubectl delete svc webcluster
service "webcluster" deleted
实验 3:多容器 Pod
所需镜像:
reg.avc.harbor.org/library/myapp:v1docker.io/library/busybox:latest
[root@K8sMasterNode ~]# vim multi-pod.yaml
# multi-pod.yaml
apiVersion: v1
kind: Pod
metadata:
labels:
run: testpod
name: testpod
spec:
containers:
- image: reg.avc.harbor.org/library/myapp:v1
name: myapp1
imagePullPolicy: IfNotPresent
- image: docker.io/library/busybox:latest
name: busybox
imagePullPolicy: IfNotPresent
command:
- /bin/sh
- -c
- sleep 10000
[root@K8sMasterNode ~]# kubectl apply -f multi-pod.yaml
pod/testpod created
[root@K8sMasterNode ~]# kubectl get pods
NAME READY STATUS RESTARTS AGE
testpod 2/2 Running 0 25s
[root@K8sMasterNode ~]# kubectl exec -it pods/testpod -c busybox -- /bin/sh
/ # curl localhost
Hello MyApp | Version: v1 | <a href="hostname.html">Pod Name</a>
/ # exit
[root@K8sMasterNode ~]# kubectl delete -f multi-pod.yaml
pod "testpod" deleted
实验 4:端口映射与节点选择
所需镜像:reg.avc.harbor.org/library/myapp:v1
[root@K8sMasterNode ~]# kubectl get nodes --show-labels
NAME STATUS ROLES AGE LABELS
k8s-master Ready control-plane 5d kubernetes.io/hostname=k8s-master,...
k8s-node1 Ready <none> 5d kubernetes.io/hostname=k8s-node1,...
k8s-node2 Ready <none> 5d kubernetes.io/hostname=k8s-node2,...
# hostport-pod.yaml
apiVersion: v1
kind: Pod
metadata:
labels:
run: testpod
name: testpod
spec:
nodeSelector:
kubernetes.io/hostname: k8s-node2
containers:
- image: reg.avc.harbor.org/library/myapp:v1
name: myapp1
imagePullPolicy: IfNotPresent
ports:
- name: http
containerPort: 80
hostPort: 80
protocol: TCP
[root@K8sMasterNode ~]# kubectl apply -f hostport-pod.yaml
pod/testpod created
[root@K8sMasterNode ~]# kubectl get pods -o wide
NAME READY STATUS RESTARTS AGE IP NODE
testpod 1/1 Running 0 10s 10.244.2.5 k8s-node2
[root@K8sMasterNode ~]# curl http://k8s-node2
Hello MyApp | Version: v1 | <a href="hostname.html">Pod Name</a>
[root@K8sMasterNode ~]# kubectl delete -f hostport-pod.yaml
pod "testpod" deleted
实验 5:环境变量
所需镜像:docker.io/library/busybox:latest
[root@K8sMasterNode ~]# vim env-pod.yaml
# env-pod.yaml
apiVersion: v1
kind: Pod
metadata:
labels:
run: testpod
name: testpod
spec:
containers:
- image: docker.io/library/busybox:latest
name: busybox
imagePullPolicy: IfNotPresent
command:
- /bin/sh
- -c
- echo "Hello $MY_NAME"; sleep 3000
env:
- name: MY_NAME
value: "Kubernetes Learner"
[root@K8sMasterNode ~]# kubectl apply -f env-pod.yaml
pod/testpod created
[root@K8sMasterNode ~]# kubectl logs pods/testpod busybox
Hello Kubernetes Learner
[root@K8sMasterNode ~]# kubectl delete -f env-pod.yaml
pod "testpod" deleted
实验 6:共享宿主机网络
所需镜像:docker.io/library/busybox:latest
[root@K8sMasterNode ~]# vim hostnetwork-pod.yaml
# hostnetwork-pod.yaml
apiVersion: v1
kind: Pod
metadata:
labels:
run: testpod
name: testpod
spec:
hostNetwork: true
containers:
- image: docker.io/library/busybox:latest
name: busybox
imagePullPolicy: IfNotPresent
command:
- /bin/sh
- -c
- sleep 10000
[root@K8sMasterNode ~]# kubectl apply -f hostnetwork-pod.yaml
pod/testpod created
[root@K8sMasterNode ~]# kubectl exec -it pods/testpod -c busybox -- ifconfig
eth0 Link encap:Ethernet HWaddr 00:0C:29:E9:E3:90
inet addr:172.25.254.20 Bcast:172.25.254.255 Mask:255.255.255.0
...
lo Link encap:Local Loopback
inet addr:127.0.0.1 Mask:255.0.0.0
[root@K8sMasterNode ~]# kubectl delete -f hostnetwork-pod.yaml
pod "testpod" deleted
实验 7:Init 容器
所需镜像:
reg.avc.harbor.org/library/myapp:v1docker.io/library/busybox:latest
[root@K8sMasterNode ~]# vim init-pod.yaml
# init-pod.yaml
apiVersion: v1
kind: Pod
metadata:
labels:
name: initpod
name: initpod
spec:
containers:
- image: reg.avc.harbor.org/library/myapp:v1
name: myapp
imagePullPolicy: IfNotPresent
initContainers:
- name: init-check
image: docker.io/library/busybox:latest
imagePullPolicy: IfNotPresent
command:
- /bin/sh
- -c
- until test -e /tmp/ready; do echo waiting; sleep 2; done
[root@K8sMasterNode ~]# kubectl apply -f init-pod.yaml
pod/initpod created
[root@K8sMasterNode ~]# kubectl get pods
NAME READY STATUS RESTARTS AGE
initpod 0/1 Init:0/1 0 5s
[root@K8sMasterNode ~]# kubectl logs pods/initpod init-check
waiting
waiting
waiting
[root@K8sMasterNode ~]# kubectl exec pods/initpod -c init-check -- /bin/sh -c "touch /tmp/ready"
[root@K8sMasterNode ~]# kubectl get pods
NAME READY STATUS RESTARTS AGE
initpod 1/1 Running 0 45s
[root@K8sMasterNode ~]# kubectl delete -f init-pod.yaml
pod "initpod" deleted
实验 8:存活探针
所需镜像:reg.avc.harbor.org/library/myapp:v1
[root@K8sMasterNode ~]# vim liveness-pod.yaml
# liveness-pod.yaml
apiVersion: v1
kind: Pod
metadata:
labels:
name: liveness
name: liveness
spec:
containers:
- image: reg.avc.harbor.org/library/myapp:v1
name: myapp
imagePullPolicy: IfNotPresent
livenessProbe:
tcpSocket:
port: 8080
initialDelaySeconds: 3
periodSeconds: 1
[root@K8sMasterNode ~]# kubectl apply -f liveness-pod.yaml
pod/liveness created
[root@K8sMasterNode ~]# kubectl get pods
NAME READY STATUS RESTARTS AGE
liveness 0/1 CrashLoopBackOff 2 20s
[root@K8sMasterNode ~]# kubectl describe pods liveness | grep -A5 "Events"
Events:
Type Reason Age From Message
---- ------ ---- ---- -------
Warning Unhealthy 10s kubelet Liveness probe failed: dial tcp 10.244.2.6:8080: connect: connection refused
[root@K8sMasterNode ~]# kubectl delete -f liveness-pod.yaml
pod "liveness" deleted
实验 9:就绪探针
所需镜像:reg.avc.harbor.org/library/myapp:v1
[root@K8sMasterNode ~]# vim readiness-pod.yaml
# readiness-pod.yaml
apiVersion: v1
kind: Pod
metadata:
labels:
name: readiness
name: readiness
spec:
containers:
- image: reg.avc.harbor.org/library/myapp:v1
name: myapp
imagePullPolicy: IfNotPresent
readinessProbe:
httpGet:
path: /test.html
port: 80
initialDelaySeconds: 1
periodSeconds: 3
---
apiVersion: v1
kind: Service
metadata:
name: readiness-svc
spec:
selector:
name: readiness
ports:
- port: 80
targetPort: 80
[root@K8sMasterNode ~]# kubectl apply -f readiness-pod.yaml
pod/readiness created
service/readiness-svc created
[root@K8sMasterNode ~]# kubectl get pod readiness
NAME READY STATUS RESTARTS AGE
readiness 0/1 Running 0 5s
[root@K8sMasterNode ~]# kubectl describe svc readiness-svc | grep Endpoints
Endpoints: <none>
[root@K8sMasterNode ~]# kubectl exec readiness -c myapp -- /bin/sh -c "echo test > /usr/share/nginx/html/test.html"
[root@K8sMasterNode ~]# kubectl get pod readiness
NAME READY STATUS RESTARTS AGE
readiness 1/1 Running 0 30s
[root@K8sMasterNode ~]# kubectl describe svc readiness-svc | grep Endpoints
Endpoints: 10.244.2.8:80
[root@K8sMasterNode ~]# kubectl delete -f readiness-pod.yaml
pod "readiness" deleted
service "readiness-svc" deleted
第六部分:总结速查表
| 知识点 | 关键命令/配置 | 生产建议 |
|---|---|---|
| 镜像地址 | reg.avc.harbor.org/library/myapp:v1 | 禁止写 myapp:v1 |
| 公共镜像 | docker.io/library/busybox:latest | 绕过代理 |
| 镜像拉取策略 | imagePullPolicy: IfNotPresent | 节省带宽 |
| 资源管理 | kubectl apply -f | 禁止 kubectl run 创建生产 Pod |
| YAML 生成 | kubectl create ... --dry-run=client -o yaml | 以此为模板 |
| 滚动更新 | kubectl set image | 配合 rollout undo 回滚 |
| Service 端口 | kubectl get svc 查看实际端口 | 不要猜端口号 |
| 资源限制 | resources.limits / requests | 务必设置 |
| 就绪探针 | readinessProbe.httpGet.path | 必须配置 |
| 存活探针 | livenessProbe.tcpSocket.port | 防止死进程 |
附录:镜像与代理相关错误总结
错误一:镜像地址缺少仓库前缀
NAME READY STATUS RESTARTS AGE
webcluster-77c87d9946-dphlg 0/1 ErrImagePull 0 22s
webcluster-77c87d9946-wq4g6 0/1 ImagePullBackOff 0 22s
原因:kubectl create deployment webcluster --image myapp:v1
解决:
kubectl create deployment webcluster --image reg.avc.harbor.org/library/myapp:v1
错误二:镜像代理与自签名证书冲突
Events:
Warning Failed kubelet Failed to pull image "busybox:latest":
tls: failed to verify certificate: x509: certificate signed by unknown authority
解决方案:
| 方案 | 做法 |
|---|---|
| 方案一 | imagePullPolicy: IfNotPresent |
| 方案二 | docker.io/library/busybox:latest 绕过代理 |
| 方案三 | 配置 Harbor 证书信任 |
错误三:Service 端口号错误
webcluster NodePort 10.96.226.32 <none> 80:31895/TCP
curl http://172.25.254.100:30713/hostname.html
curl: (7) Failed to connect ... port 30713: Connection refused
解决:kubectl get svc webcluster 查看实际端口。
错误速查表
| 错误现象 | 根本原因 | 解决方案 |
|---|---|---|
ImagePullBackOff | 镜像地址缺少仓库前缀 | 使用完整 Harbor 地址 |
x509: certificate signed by unknown authority | 镜像代理 + 自签名证书 | docker.io/library/xxx 绕过代理 |
Connection refused | NodePort 端口号错误 | kubectl get svc 查看实际端口 |
AlreadyExists (Service) | 旧的 Service 未删除 | 先 kubectl delete svc |
核心经验
Kubernetes 看的是镜像名,不是本地有什么。镜像名指向哪里,就尝试从哪里拉取。
- 自定义镜像写完整 Harbor 地址:
reg.avc.harbor.org/library/myapp:v1 - 公共镜像写
docker.io/library/xxx:tag绕过代理 - Service 端口以
kubectl get svc为准 - 排查问题先
kubectl describe pod,Events 段是关键 - 删除 Deployment 时同步删除 Service
更多推荐
所有评论(0)