k8s工作负载-Pod学习
k8s Pod学习
- 一、Pod是什么?
- 二、运行Pod
- 1. 创建单个容器的Pod
- 2. 创建多个容器的pod
- 3. 重启Pod中的容器
- 4. 使用docker查看Pod中所有的容器
- 三、静态Pod
- 1. 什么是静态Pod
- 2. 创建静态Pod
- 2.1 创建自定义Pod
- 2.2 kubelet是如何创建静态Pod的
- 3. 删除静态Pod
一、Pod是什么?
官网手册:https://kubernetes.io/zh-cn/docs/concepts/workloads/pods/#pods-and-controllers
Pod 是可以在 Kubernetes 中创建和管理的、最小的可部署的计算单元,例如docker管理的最小单元是容器,而k8s管理的最小单元是pod,docker中的应用跑在容器中,k8s的应用跑到pod中,pod是一个或多个容器组成的一个抽象的东西。
如上图:
(1)在pod启动前会创建一个Pasue容器,将后面创建得到容器加入到自己的net、ipc
命名空间,这样所有的容器就可以通过localhost访问,并且容器之间内存共享
(2)所有容器共享Pod的Cgroup,例如在创建pod时,分配100M内存,那么所有容器共享这100M内存。
(3)所有容器共享一个Volume,例如将一个pvc分配给pod时,所有容器都可以将这个volume挂载到自己的目录。
二、运行Pod
使用kubectl explain pod
查看pod的资源清单语法
创建一个test命名空间用于测试
kubectl create ns test
1. 创建单个容器的Pod
cat nginx-pod.yaml
:
apiVersion: v1
kind: Pod
metadata:name: nginxnamespace: test
spec:containers:- name: nginximage: nginx:latestports:- name: web-portcontainerPort: 80
kubectl apply -f nginx-pod.yaml
--dry-run=server
预运行查看输出结果
kubectl apply -f nginx-pod.yaml
kubectl get pod -n test
NAME READY STATUS RESTARTS AGE
nginx 1/1 Running 0 22s
查看pod的中所有的容器:
kubectl describe pod nginx -n test
Containers:字段下查看所有容器,或者使用kubectl get pod nginx -n test -o jsonpath='{.spec.containers[*].name}{"\n"}'
查看yaml文件containers下的配置。
Containers:nginx:
2. 创建多个容器的pod
创建一个nginx主应用容器,一个filebeat日志收集器,收集ng的日志
nginx-with-filebeat-po.yaml
:
apiVersion: v1
kind: Pod
metadata:name: nginx-with-filebeatnamespace: testlabels:app: web-with-logging
spec:volumes:- name: nginx-logs # 声明一个emptyDir类型的卷,pod重建后数据会丢失。后面会用到,用于挂载到容器。emptyDir: {}- name: filebeat-config # 声明一个filebeat-config的卷,类型是configMap配置文件名称是filebeat-configconfigMap:name: filebeat-config- name: filebeat-dataemptyDir: {}containers:- name: nginximage: nginx:latestimagePullPolicy: IfNotPresentports:- containerPort: 80volumeMounts:- name: nginx-logs # 将声明的nginx-logs卷挂载到容器nginx的/var/log/nginx目录下mountPath: /var/log/nginx- name: filebeatimage: docker.elastic.co/beats/filebeat:8.6.0imagePullPolicy: IfNotPresentvolumeMounts:- name: nginx-logs # 将nginx-logs卷挂载到filebeat容器的/var/log/nginx目录下,这样filebeat容器也可以读取nginx的日志mountPath: /var/log/nginxreadOnly: true # 只读模式,避免意外修改日志- name: filebeat-config # 将配置文件configMap/filebeat-config挂载到filebeat的/usr/share/filebeat/filebeat.ymlmountPath: /usr/share/filebeat/filebeat.ymlsubPath: filebeat.yml # 指定挂载的filebeat.yml是一个文件,而不是目录。- name: filebeat-data # 挂载数据卷,保存日志偏移量mountPath: /usr/share/filebeat/datacommand: ["/usr/share/filebeat/filebeat", "-c", "/usr/share/filebeat/filebeat.yml", "run"]
---
# Filebeat配置:定义日志收集规则和输出目的地
apiVersion: v1
kind: ConfigMap
metadata:name: filebeat-confignamespace: test
data:filebeat.yml: |# 日志输入filebeat.inputs:- type: logenabled: truepaths:- /var/log/nginx/access.log # 收集Nginx访问日志- /var/log/nginx/error.log # 收集Nginx错误日志# 日志输出到控制台fields:service: nginxfields_under_root: trueoutput.console:enabled: truecodec.json:pretty: truelogging.level: info
kubectl apply -f nginx-with-filebeat-po.yaml
使用 kubectl port-forward pod/nginx-with-filebeat 80
临时转发一下到pod,访问一下nginx
curl 127.0.0.1
查看filebeat日志
kubectl logs --tail=32 pod/nginx-with-filebeat -c filebeat -n test
{"@timestamp": "2025-09-11T15:01:31.097Z","@metadata": {"beat": "filebeat","type": "_doc","version": "8.6.0"},"agent": {"type": "filebeat","version": "8.6.0","ephemeral_id": "b6500742-4195-4e6c-9482-452b86bec792","id": "03906163-f29e-436c-b5bf-ef1b9f7dd383","name": "nginx-with-filebeat"},"log": {"file": {"path": "/var/log/nginx/access.log"},"offset": 89},"message": "127.0.0.1 - - [11/Sep/2025:15:01:25 +0000] \"GET / HTTP/1.1\" 200 615 \"-\" \"curl/8.9.1\" \"-\"","input": {"type": "log"},"service": "nginx","ecs": {"version": "8.0.0"},"host": {"name": "nginx-with-filebeat"}
}
3. 重启Pod中的容器
重启Pod中的容器就是先停止容器,kubectl会检测到容器状态,如果停掉了,会将它重启。
使用kubectl get pod nginx-with-filebeat -o wide -n test
查看Pod运行的主机
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
nginx-with-filebeat 2/2 Running 1 29m 10.244.1.5 k8s-node01 <none> <none>
登录上那台主机,找到那两个容器
通过Pod名称获取Pod的Pause容器id
crictl pods --name nginx-with-filebeat --output json
{"id": "e3a81b72527ffcb1163894dd86880d59a587e7a19d8d28490b566aa64b8f8591","metadata": {"name": "nginx-with-filebeat","uid": "e88aed22-9658-4842-8724-ae877dc6ea49","namespace": "test","attempt": 0}
通过Pod的id获取所有的容器
crictl ps --pod e3a81b72527ffcb1163894dd86880d59a587e7a19d8d28490b566aa64b8f8591
CONTAINER IMAGE CREATED STATE NAME ATTEMPT POD ID POD NAMESPACE
2f4b00d61fb24 41f689c209100 About an hour ago Running nginx 1 e3a81b72527ff nginx-with-filebeat test
a94c8c281f8f5 ae85851efb60e 2 hours ago Running filebeat 0 e3a81b72527ff nginx-with-filebeat test
使用crictl stop <容器 ID>,
删除容器
DEBU[0000] Get runtime connection
DEBU[0000] Using runtime connection timeout: 2s
DEBU[0000] Stopping container: 2f4b00d61fb24 (timeout = 0)
2f4b00d61fb24
在再次查看容器:
CONTAINER IMAGE CREATED STATE NAME ATTEMPT POD ID POD NAMESPACE
77fc54b45c90e 41f689c209100 4 seconds ago Running nginx 2 e3a81b72527ff nginx-with-filebeat test
a94c8c281f8f5 ae85851efb60e 2 hours ago Running filebeat 0 e3a81b72527ff nginx-with-filebeat test
可以看到容器77fc54b45c90e的创建时间变成了4 seconds ago
,ATTEMPT
由1变成了2,这是由于之前我还停止过一次,所有这里的意思就是容器77fc54b45c90e重启2次了,关于重启次数可以在:
kubectl get pod nginx-with-filebeat -o wide -n test
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
nginx-with-filebeat 2/2 Running 2 121m 10.244.1.5 k8s-node01 <none> <none>
Pod的RESTARTS 字段也由显示,或者:
kubectl describe pod nginx-with-filebeat -n test
Restart Count: 2
可以查看重启计数器次数。
4. 使用docker查看Pod中所有的容器
记住Pod的id,这里会使用到:e3a81b72527ffcb1163894dd86880d59a587e7a19d8d28490b566aa64b8f8591
先或者Pod的uid(k8s唯一标识符)
"uid": "e88aed22-9658-4842-8724-ae877dc6ea49"
Pod创建的容器会带有uid的标识,通过uid去筛选出容器
docker ps | grep e88aed22-9658-4842-8724-ae877dc6ea49
56216f107732 41f689c20910 "/docker-entrypoint.…" 15 minutes ago Up 15 minutes k8s_nginx_nginx-with-filebeat_test_e88aed22-9658-4842-8724-ae877dc6ea49_3
a94c8c281f8f ae85851efb60 "/usr/share/filebeat…" 3 hours ago Up 3 hours k8s_filebeat_nginx-with-filebeat_test_e88aed22-9658-4842-8724-ae877dc6ea49_0
e3a81b72527f registry.aliyuncs.com/google_containers/pause:3.10 "/pause" 3 hours ago Up 3 hours k8s_POD_nginx-with-filebeat_test_e88aed22-9658-4842-8724-ae877dc6ea49_0
可以看出Pod中包含3个容器,两个主容器,一个Pause容器,而且Pause容器id等于Pod id,由此可见Pause就是代表Pod
在容器名中也能体现:k8s_POD_nginx-with-filebeat_test_e88aed22-9658-4842-8724-ae877dc6ea49_0
容器名的最后一位是重启计数器,如:k8s_nginx_nginx-with-filebeat_test_e88aed22-9658-4842-8724-ae877dc6ea49_3
我们之前在谈到什么是Pod时说到,Pod是由Pause容器作为根容器,其他容器共享这个容器的ipc,net
namespace,我们可以通过查看这3个容器的namespace来验证。
通过容器在宿主机上的pid来查看namespace:
Pause:
docker inspect -f '{{.State.Pid}}' e3a81b72527f
304569
# 通过pid查看所属namespace,主要看,ipc,net
lsns -p 304569
NS TYPE NPROCS PID USER COMMAND
4026532779 ipc 5 304569 65535 /pause
4026532782 net 5 304569 65535 /pause
其他两个容器一样查看一下namespace
nginx:
4026532779 ipc 5 304569 65535 /pause
4026532782 net 5 304569 65535 /pause
filebeat:
NS TYPE NPROCS PID USER COMMAND
4026532779 ipc 5 304569 65535 /pause
4026532782 net 5 304569 65535 /pause
如图对比可以看出,filebeat和nginx容器使用的都是Pause容器的ipc,net命名空间,当然你还可以共享pid命名空间,使容器之间pid可见,配置方法查看手册:https://kubernetes.io/zh-cn/docs/tasks/configure-pod-container/share-process-namespace/
三、静态Pod
官网手册:https://kubernetes.io/zh-cn/docs/concepts/workloads/pods/#static-pods
1. 什么是静态Pod
静态Pod是由kubelet单独创建管理,不需要注册到api-server,但是kubelet创建静态Pod也会向api-server服务器创建一个只读的Pod镜像,用于使用kubectl查看。
静态Pod默认会以主机名为后缀如下:
[root@k8s-master01 ~]# hostname
k8s-master01
[root@k8s-master01 ~]# kubectl get po -A | grep k8s-master01
kube-system etcd-k8s-master01 1/1 Running 1 2d4h
kube-system kube-apiserver-k8s-master01 1/1 Running 1 2d4h
kube-system kube-controller-manager-k8s-master01 1/1 Running 2 (4h5m ago) 2d4h
kube-system kube-scheduler-k8s-master01 1/1 Running 2 (4h5m ago) 2d4h
如上可以看出k8s控制平台组件都是由静态Pod创建的。
2. 创建静态Pod
静态Pod的创建分为两种,第一种是在本地声明资源文件,第二种是使用远程的资源文件,
k8s的静态Pod资源文件都在本地,路径在kubelet配置staticPodPath:
定义下,kubelet默认读取/var/lib/kubelet/config.yaml
配置文件
kubelet配置参数:https://kubernetes.io/zh-cn/docs/reference/config-api/kubelet-config.v1beta1/
grep staticPodPath /var/lib/kubelet/config.yaml
staticPodPath: /etc/kubernetes/manifests
可看出静态Pod路径在/etc/kubernetes/manifests目录下面
ls /etc/kubernetes/manifests
etcd.yaml kube-apiserver.yaml kube-controller-manager.yaml kube-scheduler.yaml
也可以通过将资源文件放到web服务器,kubelet去读取web资源,后面的实验是展示文件访问,web方式参考官网:https://kubernetes.io/zh-cn/docs/tasks/configure-pod-container/static-pod/#pods-created-via-http
2.1 创建自定义Pod
静态Pod和正常Pod创建差不多,但是有些选项不支持,官网有列出:
静态 Pod 的 spec 不能引用其他 API 对象 (如:ServiceAccount、 ConfigMap、 Secret 等)。
kubectl create ns test
apiVersion: v1
kind: Pod
metadata:namespace: testname: static-nginxlabels:app: nginx
spec:containers:- name: nginximage: nginxports:- name: webcontainerPort: 80protocol: TCP
kubectl get pod -n test
NAME READY STATUS RESTARTS AGE
static-nginx-k8s-master01 1/1 Running 0 86s
可以看出pod已经被kubelet创建出来了
2.2 kubelet是如何创建静态Pod的
kubelet 会定期去扫描/etc/kubernetes/manifests
下的变化,如果检测到有新的Pod文件就会创建,同样有Pod文件减少就会删除Pod,使用kubectl delete pod是无法删除Pod的,上面已经介绍过了,api-server中保存的静态Pod是只读的。
kubelet 定期扫描时间有配置fileCheckFrequency
决定,默认是20s,但是我使用的k8s版本是v1.34fileCheckFrequency
配置默认是0s:
fileCheckFrequency: 0s
但是我修改了pod静态文件,它依旧能帮我生效配置,而且不是定期检查而是马上生效,可能是配置了inotify监控。
3. 删除静态Pod
在2.2 小节中有讲过,删除静态Pod就是将静态文件移除/etc/kubernetes/manifests目录
[root@k8s-master01 manifests]# mv static-nginx.yaml ~
[root@k8s-master01 manifests]# kubectl get pod -n test --show-labels
No resources found in test namespace.
如上立马生效。