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 内的多个容器共享 NetworkIPCUTS 命名空间,可通过 localhost 互相访问。

2.2 为什么必须用控制器?

自主式 Pod 不具备自愈能力(节点宕机或 Pod 被删除即丢失)。

Deployment 控制器 提供:

  1. 自愈能力:维持期望副本数
  2. 滚动更新:零停机升级版本
  3. 回滚能力:一键回到旧版本
  4. 扩缩容:动态调整 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 重要字段

字段类型必须说明
containersList业务容器列表
restartPolicyStringAlwaysOnFailureNever
nodeSelectorMap调度约束
hostNetworkBool共享宿主机网络栈
initContainersList初始化容器
imagePullSecretsList私有仓库凭证

3.4 containers 详细参数

字段类型必须说明
commandList覆盖 ENTRYPOINT
argsList覆盖 CMD
envList环境变量
portsList声明端口,hostPort 映射到宿主机
resourcesObject强烈推荐资源配额
imagePullPolicyStringAlwaysNeverIfNotPresent
livenessProbe / readinessProbe / startupProbeObject健康检查

3.5 资源限制与 QoS

resources:
  requests:
    cpu: 250m
    memory: 128Mi
  limits:
    cpu: 500m
    memory: 256Mi

QoS 类驱逐优先级(由低到高)

  1. BestEffort:未设置任何 requests/limits → 最先被驱逐
  2. Burstable:部分设置或不一致
  3. 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:v1reg.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:v1
  • docker.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:v1
  • docker.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 refusedNodePort 端口号错误kubectl get svc 查看实际端口
AlreadyExists (Service)旧的 Service 未删除kubectl delete svc

核心经验

Kubernetes 看的是镜像名,不是本地有什么。镜像名指向哪里,就尝试从哪里拉取。

  1. 自定义镜像写完整 Harbor 地址:reg.avc.harbor.org/library/myapp:v1
  2. 公共镜像写 docker.io/library/xxx:tag 绕过代理
  3. Service 端口以 kubectl get svc 为准
  4. 排查问题先 kubectl describe pod,Events 段是关键
  5. 删除 Deployment 时同步删除 Service

更多推荐