kubernetes中的pod管理

一、Kubernetes 的资源

1. Kubernetes 的资源是什么

Kubernetes(简称 K8s)把集群里所有的东西(计算、网络、存储等)都抽象成"资源"。你想让 K8s 干活,本质就是在创建、修改或删除这些资源。

  • 集群系统:K8s 是一堆服务器连在一起组成的"团队"(集群)。你不用关心程序具体跑在哪台机器上,只管把服务部署到这个团队里。
  • 部署服务就是跑容器:把你的程序打包塞进容器里,让 K8s 在集群中的某台机器上把这个容器运行起来。
  • 最小管理单元是 Pod:K8s 不直接管理容器,它管理的最小单位叫 Pod。你得先把容器放进 Pod 这个"盒子"(或"豆荚")里,K8s 才认。一个 Pod 里通常可以放一个或多个关系紧密的容器。
  • 通过 Pod 控制器管理 Pod:K8s 会派一个"Pod 控制器"来统一管理 Pod。比如你要求跑 3 个 Pod,控制器就保证永远有 3 个;哪个 Pod 挂了,控制器立马给你拉起一个新的。
  • Service 实现服务访问 :Pod 随时可能被重建、IP 会变,K8s 提供 Service 这个组件,作为 Pod 的"固定前台/接线员",对外提供稳定访问入口,再把请求转发给后端 Pod。
  • 存储系统实现数据持久化:Pod 里的程序产生的数据如果只存在 Pod 内,Pod 一重启就没了。K8s 提供各种存储系统(如挂载网络硬盘),把重要数据存到 Pod 之外的地方,实现持久化。

2. 资源的管理方式

K8s 操作资源有三种方式:

  • 命令式对象管理:直接使用命令操作资源。

    bash 复制代码
    kubectl run nginx-pod --image=nginx:latest --port=80
  • 命令式对象配置:通过命令配合配置文件操作资源。

    bash 复制代码
    kubectl create/patch -f nginx-pod.yaml
  • 声明式对象配置 :通过 apply 命令配合配置文件操作资源。

    bash 复制代码
    kubectl apply -f nginx-pod.yaml

2.1 命令式对象管理

kubectl 命令语法:

复制代码
kubectl [command] [type] [name] [flags]
  • command :指定要对资源执行的操作,例如 creategetdelete
  • type :指定资源类型,比如 deploymentpodservice
  • name:指定资源的名称,大小写敏感。
  • flags:额外的可选参数。

2.2 资源类型

常见资源类型与命令参数详见 K8s 官方文档(kubectl api-resources 可列出当前集群支持的资源)。

二、什么是 Pod

Pod 是 K8s 最小的可部署计算单元,是一组一个或多个容器的集合,这些容器共享网络、存储和命名空间,总是被一起调度到同一台机器上。

核心概念类比:

  • 容器:宿舍里的一个人,跑着一个具体的程序。
  • Pod:一间宿舍,把关系紧密的几个容器塞进同一个房间。
  • Node(节点):一栋楼,即宿舍所在的物理机/虚拟机。
  • Pod 网络 :宿舍的门牌号+内线电话。Pod 有独立 IP,内部容器用 localhost 就能互相通话。

2.1 创建自主式 Pod

优点

  1. 灵活性极高:可以像写代码一样精确控制 Pod 的每个细节(镜像版本、CPU 限制、环境变量、启动命令等),不需要复杂的控制器配置,适合特定调试需求。
  2. 学习与调试的"活教材":手动创建 Pod 是理解 K8s 底层概念(镜像拉取、容器运行时、网络配置)的最佳途径;排查故障时可快速起一个 Pod 验证网络连通性或环境配置,用完即删。
  3. 适用于特殊场景:如一次性任务(运行 Job 导出数据库备份)、快速验证(测试某个新镜像能否跑通)。

缺点

  1. 管理极其复杂(无法规模化):跑 100 个同样的 Nginx 得敲 100 遍命令;无法自动扩缩容,流量变化不会自动调整副本数。
  2. 缺乏自愈与高级功能:宿主机宕机或容器崩溃时,K8s 不会尝试重启或在其他机器重建,像断了线的风筝;也无法使用服务发现、滚动更新等核心功能。
  3. 可维护性极差:配置只存在脑子或历史命令里,时间久了或迁移集群时难以复现,因为没有留下"说明书"(YAML 文件)。

2.2 利用控制器管理 Pod

优点

  1. 自愈能力(高可用):容器崩溃、Pod 被删、节点宕机,控制器都会自动在其他可用节点重建 Pod,服务不中断。
  2. 弹性伸缩:流量高峰一键(或自动)扩容副本数,低谷时缩容节省资源。
  3. 滚动更新与版本回滚:更新镜像时逐个替换旧 Pod,用户无感知;新版本有 Bug 可一条命令回滚到上一稳定版本。
  4. 批量统一管理:一个控制器管几百上千个 Pod,统一调度策略和资源配置,增删改查都在控制器层面操作。
  5. 无缝对接 Service:控制器新建的 Pod 自动带指定标签,Service 靠标签自动发现新 Pod 并加入负载均衡,前端访问地址不变。

缺点(局限性)

  1. 学习成本较高:需要理解不同控制器类型(Deployment、StatefulSet、DaemonSet 等)及其 YAML 字段含义。
  2. 配置不当有风险:副本数过大可能耗尽集群资源;滚动更新策略配错可能导致服务短暂不可用;存储卷绑定错误可能丢数据。
  3. 资源开销微增:控制器本身占用少量 etcd 存储和 API Server 通信资源,但相比稳定性收益几乎可忽略。
  4. 杀鸡用牛刀:临时调试、跑一次性脚本验证时用控制器反而麻烦,直接起个自主式 Pod 更快。

2.3 利用 YAML 文件部署应用

命令行操作是"命令式"的,要一步步指挥 K8s;YAML 是"声明式"的,只需在文件里写清楚最终想要的状态。

YAML 文件部署的优点

可重复性与版本控制:

  • 环境一致:测试、预发、生产环境用同一套 YAML,彻底解决"我这能跑、你那不能跑"的问题。
  • 历史追溯:谁修改了配置、什么时候修改、修改了什么,全部有迹可循。
  • 一键回滚:新版本出问题,直接回退到上一个正常的 YAML 版本,瞬间恢复应用。

无缝对接 CI/CD 与自动化工具:

  • 自动化部署:在 CI/CD 流程(Jenkins、GitLab CI)中,代码提交后自动触发脚本读取 YAML 并推送应用到不同环境,实现无人值守持续交付。
  • 工具链支持 :除 kubectl apply 外,还可使用静态分析工具对 YAML 做语法检查、安全策略扫描(如检查是否暴露数据库密码),确保交付质量。

2.4 资源清单

Pod YAML 常见字段说明:

顶层字段

  • apiVersion (String):K8s API 版本,目前基本是 v1,可用 kubectl api-versions 查询。
  • kind (String):资源类型/角色,如 Pod
  • metadata (Object):元数据对象。
    • metadata.name(String):资源名称,由用户编写(如 Pod 名字)。
    • metadata.namespace(String):命名空间,由用户定义。
  • spec(Object):详细定义对象。

容器相关(spec.containers\[\])

  • spec.containers\[\](list):容器列表定义。
  • spec.containers\[\].name(String):容器名称。
  • spec.containers\[\].image(string):镜像名称。
  • spec.containers\[\].imagePullPolicy (String):镜像拉取策略。Always 每次重新拉取;IfNotPresent 本地有则用本地;Never 仅用本地镜像。
  • spec.containers\[\].command\[\](list):容器运行时启动命令,未指定则运行镜像打包时指定的命令。
  • spec.containers\[\].args\[\](list):容器运行参数,可指定多个。
  • spec.containers\[\].workingDir(String):容器工作目录。
  • spec.containers\[\].volumeMounts\[\] (list):容器内部存储卷配置。
    • spec.containers\[\].volumeMounts\[\].name(String):可被容器挂载的存储卷名称。
    • spec.containers\[\].volumeMounts\[\].mountPath(String):存储卷挂载路径。
    • spec.containers\[\].volumeMounts\[\].readOnly (String):读写模式,true/false,默认读写。
  • spec.containers\[\].ports\[\] (list):容器需要用到的端口列表。
    • spec.containers\[\].ports\[\].name(String):端口名称。
    • spec.containers\[\].ports\[\].containerPort(String):容器监听端口号。
    • spec.containers\[\].ports\[\].hostPort(String):容器所在主机监听端口号,默认同 containerPort。注意:设置 hostPort 后同一台主机无法启动该容器的相同副本(主机端口冲突)。
    • spec.containers\[\].ports\[\].protocol(String):端口协议,支持 TCP/UDP,默认 TCP。
  • spec.containers\[\].env\[\] (list):容器运行前需设置的环境变量列表。
    • spec.containers\[\].env\[\].name(String):环境变量名称。
    • spec.containers\[\].env\[\].value(String):环境变量值。
  • spec.containers\[\].resources (Object):资源限制与请求值(容器资源上限)。
    • spec.containers\[\].resources.limits (Object):容器运行时资源上限。
      • spec.containers\[\].resources.limits.cpu (String):CPU 限制,单位核心数,1 = 1000m
      • spec.containers\[\].resources.limits.memory(String):内存限制,单位 MiB/GiB。
    • spec.containers\[\].resources.requests (Object):容器启动和调度时的限制设置。
      • spec.containers\[\].resources.requests.cpu(String):CPU 请求,单位 core,容器启动初始化可用数量。
      • spec.containers\[\].resources.requests.memory(String):内存请求,单位 MiB/GiB,容器启动初始化可用数量。

Pod 级字段(spec)

  • spec.restartPolicy (string):Pod 重启策略,默认 Always
    • Always:Pod 一旦终止,无论容器如何终止,kubelet 都重启它。
    • OnFailure:只有 Pod 以非零退出码终止时 kubelet 才重启该容器;正常结束(退出码 0)不重启。
    • Never:Pod 终止后 kubelet 将退出码报告给 Master,不重启。
  • spec.nodeSelector (Object):Node 的 Label 过滤标签,以 key:value 格式指定。
  • spec.imagePullSecrets (Object):pull 镜像时使用的 secret 名称,以 name:secretkey 格式指定。
  • spec.hostNetwork (Boolean):是否使用主机网络模式,默认 false。设为 true 表示使用宿主机网络、不使用 docker 网桥,且同一台宿主机上无法启动第二个副本。

运行单个和多个容器

使用 YAML 模板创建单容器 Pod:

bash 复制代码
[root@k8s-master pod]# kubectl run test --image myapp:v1 --dry-run=client -o yaml > pod.yml
[root@k8s-master pod]# vim pod.yml
yaml 复制代码
apiVersion: v1          # API 版本号,v1 是 K8s 最核心的 API 组
kind: Pod               # 资源类型:Pod(最小部署单元)
metadata:               # 元数据,相当于 Pod 的"身份证信息"
  labels:               # 标签,便于分类、查找、被 Service 关联
    run: test           # 标签键值对:这个 Pod 用于跑测试任务
  name: test            # Pod 名字,同一命名空间内不能重名
spec:                   # 规格/蓝图,描述 Pod 最终长什么样
  containers:           # 容器列表(数组),Pod 里可跑一个或多个容器
  - image: myapp:v1     # 容器镜像(myapp,版本 v1)
    name: test          # 容器名,Pod 内部必须唯一
bash 复制代码
[root@k8s-master pod]# kubectl apply -f pod.yml
pod/test created

多容器 Pod(一个 Pod 跑两个容器):

bash 复制代码
[root@k8s-master pod]# vim pod.yml
yaml 复制代码
apiVersion: v1
kind: Pod
metadata:
  labels:
    run: test
  name: test
spec:
  containers:
  - image: myapp:v1
    name: test
  - image: myapp:v2     # 添加的第二个镜像
    name: test2          # 第二个容器的名字
bash 复制代码
[root@k8s-master pod]# kubectl apply -f pod.yml

理解 Pod 间的网络整合

一个 Pod 内两个容器共享网络,可用 localhost 直接互通:

bash 复制代码
[root@k8s-master ~]# vim pod.yml
yaml 复制代码
apiVersion: v1
kind: Pod
metadata:
  labels:
    run: timinglee
  name: test
spec:
  containers:
    - image: myapp:v1
      name: myapp1
    - image: busyboxplus:latest
      name: busyboxplus
      command: ["/bin/sh","-c","sleep 1000000"]
bash 复制代码
[root@k8s-master ~]# kubectl apply -f pod.yml
[root@k8s-master pod]# kubectl get pods
NAME   READY   STATUS    RESTARTS   AGE
test   2/2     Running   0          8m1s
# 在 busyboxplus 容器里通过 localhost 访问同 Pod 的 myapp1 容器
[root@k8s-master pod]# kubectl exec test -c busyboxplus -- curl -s localhost
Hello MyApp | Version: v1 | <a href="hostname.html">Pod Name</a>

端口映射

bash 复制代码
[root@k8s-master pod]# vim pod.yml
yaml 复制代码
apiVersion: v1
kind: Pod
metadata:
  labels:
    run: test
  name: test
spec:
  containers:
  - image: myapp:v1
    name: test
    ports:
    - name: http
      containerPort: 80   # 容器端口
      hostPort: 80         # 主机端口
      protocol: tcp        # 协议

hostPort 会把容器端口映射到宿主机网络,生产环境建议改用 Service 暴露服务。

如何设定环境变量

bash 复制代码
[root@k8s-master ~]# vim pod.yml
yaml 复制代码
apiVersion: v1
kind: Pod
metadata:
  labels:
    run: timinglee
  name: test
spec:
  containers:
    - image: busybox:latest
      name: busybox
      command: ["/bin/sh","-c","echo $NAME;sleep 3000000"]
      env:
      - name: NAME
        value: ttt
bash 复制代码
[root@k8s-master pod]# kubectl apply -f pod.yml
pod/test created
[root@k8s-master pod]# kubectl logs pods/test busybox
ttt

资源限制

bash 复制代码
[root@k8s-master pod]# vim pod.yml
yaml 复制代码
apiVersion: v1
kind: Pod
metadata:
  labels:
    run: test
  name: test
spec:
  containers:
    - image: myapp:v1
      name: myapp
      resources:
        limits:             # 最高资源限制
          cpu: 500m
          memory: 50M
        requests:           # 期望使用资源
          cpu: 500m
          memory: 50M
bash 复制代码
[root@k8s-master pod]# kubectl describe pods test
    Restart Count:  0
    Limits:
      cpu:     500m
      memory:  50M
    Requests:
      cpu:        500m
      memory:     50M

运行节点选择

查看各节点标签:

bash 复制代码
[root@k8s-master pod]# kubectl get nodes --show-labels
NAME         STATUS   ROLES           AGE    VERSION   LABELS
k8s-master   Ready    control-plane   5d7h   v1.35.7   beta.kubernetes.io/arch=amd64,...,kubernetes.io/hostname=k8s-master,...
k8s-node1    Ready    <none>          5d7h   v1.35.7   ...,kubernetes.io/hostname=k8s-node1,...
k8s-node2    Ready    <none>          5d7h   v1.35.7   ...,kubernetes.io/hostname=k8s-node2,...

通过 nodeSelector 指定 Pod 调度到 k8s-node1

bash 复制代码
[root@k8s-master pod]# vim pod.yml
yaml 复制代码
apiVersion: v1
kind: Pod
metadata:
  labels:
    run: test
  name: test
spec:
  nodeSelector:
    kubernetes.io/hostname: k8s-node1
  containers:
    - image: myapp:v1
      name: myapp
bash 复制代码
[root@k8s-master pod]# kubectl apply -f pod.yml
pod/test created
[root@k8s-master pod]# kubectl get pods -o wide
NAME   READY   STATUS    RESTARTS   AGE   IP           NODE        NOMINATED NODE   READINESS GATES
test   1/1     Running   0          36s   10.244.2.4   k8s-node1   <none>           <none>

共享宿主机网络

设置 hostNetwork: true 让 Pod 使用宿主机网络命名空间(此时 Pod 内的网络即宿主机网络):

bash 复制代码
[root@k8s-master pod]# vim pod.yml
yaml 复制代码
apiVersion: v1
kind: Pod
metadata:
  labels:
    run: test
  name: test
spec:
  hostNetwork: true      # 使用宿主机网络,不使用 docker 网桥
  containers:
    - image: myapp:v1
      name: myapp
bash 复制代码
[root@k8s-master pod]# kubectl exec -it pods/test -c myapp -- /bin/sh
/ # ip a
# 此时看到的是宿主机的网络接口(eth0、docker0、flannel.1、cni0 等)

注意:开启 hostNetwork 后,同一台宿主机上无法启动该 Pod 的第二个副本(端口冲突)。

三、Pod 的生命周期

Pod 启动时先按顺序执行 Init 容器 (完成初始化前置条件),Init 容器全部成功退出后,主容器才并行启动。主容器运行期间可通过 探针(Probe) 进行存活、就绪和启动检测。

Init 容器的 5 个特点:

  1. 自带"专业工具箱"(包含特定工具) :主容器追求精简常缺 curl 等工具;Init 容器携带这些工具临时执行初始化任务,完成后即退出,避免工具残留主容器,保持镜像精简安全。
  2. 绝不"污染"主环境(安全性):Init 容器在独立环境执行下载证书等"脏活",与主容器隔离。主容器不装额外工具,保持镜像纯净安全。
  3. 各干各的,互不干扰(独立工作):开发只管把应用代码打包进镜像,运维用 Init 容器动态注入配置或证书,双方无需互相修改对方镜像。
  4. 拥有"特权视角"(文件系统隔离与 Secrets 权限):Init 容器有权访问 K8s Secrets 取出数据库密码等敏感信息,处理后传给主容器;主容器无直接访问权限,降低密码泄露风险。
  5. 严格的"前置检查"(阻塞启动机制):Init 容器持续检测依赖服务(如数据库)是否就绪,未就绪则一直等待,阻塞主容器启动,确保主应用运行时依赖一定可用,避免崩溃。

3.1 Init 容器示例

创建带 Init 容器的 Pod:Init 容器循环检测 /testfile 是否存在,不存在则持续等待;手动创建该文件后 Init 容器退出,主容器启动。

bash 复制代码
[root@k8s-master pod]# vim pod.yml
yaml 复制代码
apiVersion: v1
kind: Pod
metadata:
  labels:
    name: initpod
  name: initpod
spec:
  containers:
    - image: myapp:v1
      name: myapp
  initContainers:
    - name: init-myservice
      image: busybox
      command: ["sh","-c","until test -e /testfile;do echo wating for myservice; sleep 2;done"]
bash 复制代码
[root@k8s-master ~]# kubectl apply -f pod.yml
[root@k8s-master pod]# kubectl get pods
NAME      READY   STATUS     RESTARTS   AGE
initpod   0/1     Init:0/1   0          114s

# 查看 Init 容器日志,正在等待 /testfile
[root@k8s-master pod]# kubectl logs pods/initpod init-myservice
wating for myservice
wating for myservice
...

# 在 Init 容器内创建 /testfile,解除阻塞
[root@k8s-master pod]# kubectl exec pods/initpod -c init-myservice -- /bin/sh -c "touch /testfile"
[root@k8s-master pod]# kubectl get pods
NAME      READY   STATUS    RESTARTS   AGE
initpod   1/1     Running   0          3m4s

3.2 探针

探针类型(诊断方式)

  • ExecAction:在容器内执行自定义命令,退出码为 0 则判定健康,适合检查特定进程是否存在或执行自定义脚本。
  • TCPSocketAction:尝试建立 TCP 连接,指定端口成功连通则判定健康,常用于数据库等需网络连通性的服务检查。
  • HTTPGetAction:向容器发送 HTTP GET 请求,响应状态码在 200-400 之间则判定健康,专用于 Web 服务存活探测。

探针作用(故障处理)

  • LivenessProbe(存活):检测容器是否存活。失败则杀掉容器并按重启策略重建;不配置则默认容器始终存活,可能导致死锁。
  • ReadinessProbe(就绪):检测容器能否接收流量。失败则从 Service Endpoints 剔除,确保应用未就绪时不转发请求。
  • StartupProbe(启动):检测应用是否启动完成。存在时暂时禁用其他探针直至成功,专用于慢启动应用,防止启动中被误判为宕机。

探针区别

  • Readiness vs Liveness:Readiness 决定"是否接收流量"(影响路由),Liveness 决定"是否重启容器"(影响生命周期);前者防脏数据,后者保自愈。
  • Startup vs 其他:Startup 专治"慢启动",容器刚启动时仅执行它,成功后才激活 Liveness/Readiness;其他探针是周期性持续进行的。

存活探针

myapp:v1 使用 TCP 存活探针检测 8080 端口(该镜像实际未开启 8080,因此探针失败,Pod 反复重启):

yaml 复制代码
apiVersion: v1
kind: Pod
metadata:
  labels:
    name: liveness
  name: liveness
spec:
  containers:
    - image: myapp:v1
      name: myapp
      livenessProbe:
        tcpSocket:             # 检测端口
          port: 8080
        initialDelaySeconds: 3 # 容器启动后多少秒探针开始工作
        periodSeconds: 1       # 探针探测周期
        timeoutSeconds: 1      # 等待响应超时时间
bash 复制代码
[root@k8s-master pod]# kubectl apply -f pod.yml
[root@k8s-master pod]# kubectl get pods
NAME       READY   STATUS             RESTARTS      AGE
liveness   0/1     CrashLoopBackOff   5 (58s ago)   2m50s
# 容器未启动,因为镜像未开启 8080 端口,探针持续失败

就绪探针

myapp:v1 使用 HTTP 就绪探针检测 /test.html(该文件默认不存在,Pod 处于未就绪状态;创建文件后变为 Ready):

bash 复制代码
[root@k8s-master ~]# vim pod.yml
yaml 复制代码
apiVersion: v1
kind: Pod
metadata:
  labels:
    name: readiness
  name: readiness
spec:
  containers:
    - image: myapp:v1
      name: myapp
      readinessProbe:
        httpGet:
          path: /test.html
          port: 80
        initialDelaySeconds: 1
        periodSeconds: 3
        timeoutSeconds: 1
bash 复制代码
[root@k8s-master pod]# kubectl apply -f pod.yml

# 暴露 80 端口
[root@k8s-master ~]# kubectl expose pod readiness --port 80 --target-port 80
service/readiness exposed

[root@k8s-master pod]# kubectl get pods
NAME        READY   STATUS             RESTARTS        AGE
liveness    0/1     CrashLoopBackOff   7 (3m30s ago)   9m38s
readiness   0/1     Running            0               56s
# readiness 为 0/1:因为 /usr/share/nginx/html/test.html 不存在,未满足就绪条件

# 创建 test.html 文件
[root@k8s-master pod]# kubectl exec pods/readiness -c myapp -- /bin/sh -c "echo test > /usr/share/nginx/html/test.html"

# 再次查看,readiness 变为 1/1 Ready
[root@k8s-master pod]# kubectl get pods
NAME        READY   STATUS             RESTARTS      AGE
liveness    0/1     CrashLoopBackOff   9 (58s ago)   12m
readiness   1/1     Running            0             3m49s

# 查看 Service,Endpoints 已填入 Pod IP(满足条件后端口暴露)
[root@k8s-master pod]# kubectl describe svc readiness
Name:                     readiness
Namespace:                default
Labels:                   name=readiness
Selector:                 name=readiness
Type:                     ClusterIP
IP:                       10.104.48.94
Port:                     <unset>  80/TCP
TargetPort:               80/TCP
Endpoints:                10.244.2.7:80
Session Affinity:         None
Events:                   <none>
相关推荐
lxw202302711642 分钟前
k8s的pod管理
linux·容器·kubernetes
Yiiz.1 小时前
Kubernetes Pod 与控制器知识点
云原生·容器·kubernetes
高磊20052 小时前
Kubernetes Pod 管理实战详解
linux·容器·kubernetes
流星白龙2 小时前
【Docker】9.Docker 镜像仓库实战
运维·docker·容器
想要成为老金高手2 小时前
Kubernetes 实战笔记(一):Pod 管理与 kubectl 核心命令全解
笔记·容器·kubernetes
张洛闻Eren2 小时前
云原生k8s【第六课】:K8s 访问控制
运维·docker·云原生·容器·kubernetes·k8s
Kina_C2 小时前
Kubernetes Pod 全生命周期管理:从命令实操到控制器版本更替
云原生·容器·kubernetes
奇特認2 小时前
kubernetes pod管理
云原生·容器·kubernetes
mohesashou3 小时前
k8s控制器管理
云原生·容器·kubernetes