K8S 深入学习 (一) --- POD 篇
一、 Pod 概念
在 Kubernetes(K8s)里,
Pod
是最小的可部署单元
- 它不是单纯的一个容器,而是一个 容器组(可能有一个或多个容器)
- 这些容器共享:
- 网络(同一个 IP、端口空间)
- 存储卷(可以共享数据)
Pod
的生命周期是短暂的(ephemeral),它是由 控制器(Deployment
、StatefulSet
、DaemonSet
等)创建和管理的,而不是你直接长期维护的。- 可以把 Pod 想成一个 小房子:
- 房子里可能有一个人(单容器)或者几个人(多容器),他们共用一个厨房(存储)和一个 Wi-Fi(网络)。
- 房子本身(
Pod
)可以被拆掉重建,但人(容器)也会跟着一起走
说明:
Pod 通常不是直接创建的,而是使用工作负载资源创建的。(Deployment
(部署)、 StatefulSet
(有状态集)、 DaemonSet
(守护进程集) 等 )
二、 Pod 特性
类别 | 描述 |
---|---|
网络共享 | Pod 内的所有容器共享一个网络命名空间(同 IP、同端口空间),用 localhost 就能互相通信 |
存储共享 | 可以挂载同一个 Volume,让多个容器共享读写数据 |
生命周期 | Pod 会跟着其控制器策略进行启动、重建、终止。支持初始化容器(InitContainer)和探针(健康检查) |
调度与伸缩 | Pod 会被调度到集群中的某个节点上,支持副本数扩缩容和分布策略(亲和/反亲和) |
2.1 网络共享
示例: 创建名为 network-demo
的 pod, 包含两个容器, app
(nginx), sidecar
(busybox)
kubectl apply -f network-demo.yaml
apiVersion: v1
kind: Pod
metadata:
name: network-demo
spec:
containers:
- name: app
image: nginx
ports:
- containerPort: 80
- name: sidecar
image: busybox
command: ["sh", "-c", "wget -qO- http://localhost:80"]
结果如下:
root@debian:~/k8s/pod# kubectl get pods |
上述结果中,
READY
的状态 1/2 是正常的, 应为容器sidecar
实际上是busybox
, 在执行完 COMMAND 之后就挂了, Kubernetes 期望容器能持续运行,当容器退出时,它会认为Pod不健康,并将其重启。这就形成了CrashLoopBackOff
循环
我们查看下容器 sidecar 最后的日志输出
kubectl logs network-demo -c sidecar --previous
--previous
标志来查看容器上一次崩溃时的日志root@debian:~/k8s/pod# kubectl logs network-demo -c sidecar --previous
<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
<style>
html { color-scheme: light dark; }
body { width: 35em; margin: 0 auto;
font-family: Tahoma, Verdana, Arial, sans-serif; }
</style>
</head>
<body>
<h1>Welcome to nginx!</h1>
<p>If you see this page, the nginx web server is successfully installed a
working. Further configuration is required.</p>
<p>For online documentation and support please refer to
<a href="http://nginx.org/">nginx.org</a>.<br/>
Commercial support is available at
<a href="http://nginx.com/">nginx.com</a>.</p>
<p><em>Thank you for using nginx.</em></p>
</body>
</html>
root@debian:~/k8s/pod#
让我们进入容器查看下
kubectl exec -it network-demo -- /bin/sh
root@debian:~/k8s/pod# kubectl exec -it network-demo
error: you must specify at least one command for the container
当 pod 只有一个容器的时候, kubectl 会自动进入该容器, 但是
kubectl exec
不会自动进入 Pod 中唯一存活的容器。当一个 Pod 包含多个容器时,你必须显式地指定要进入的容器名称
kubectl exec -it network-demo -c app -- /bin/sh
kubectl exec -it pods/network-demo -c app -- /bin/sh
保持 sidecar
存活, 修改 sidecar 执行的命令
command: ["/bin/sh", "-c", "wget -qO- http://localhost && sleep infinity"]
重新发布
kubectl apply -f network-demo.yaml
报错如下
the Pod "network-demo" is invalid: spec: Forbidden: pod updates may not change fields other than `spec.containers[*].image`,`spec.initContainers[*].image`,`spec.activeDeadlineSeconds`,`spec.tolerations` (only additions to existing tolerations),`spec.terminationGracePeriodSeconds` (allow it to be set to 1 if it was previously negative)
解释
你正在尝试以一种不被允许的方式更新一个 Pod。Kubernetes Pod 的更新策略非常严格,因为 Pod 是最基础的调度和运行单元,许多关键配置在创建后是不可变的
Pod 更新时下面字段可以被修改:
spec.containers[*].image
: 容器镜像spec.initContainers[*].image
: 初始化容器镜像spec.activeDeadlineSeconds
: 活跃截止秒数。spec.tolerations
: 容忍度(仅限于添加新的容忍度)spec.terminationGracePeriodSeconds
: 终止优雅期限
上述列表之外的任何其他字段,例如:
command
和args
:容器的启动命令和参数。ports
:容器暴露的端口。volumes
:挂载的卷。securityContext
:安全上下文。restartPolicy
:重启策略。
正确做法
kubectl delete pod network-demo
kubectl apply -f your-pod.yaml