k8s工作负载-Pod学习

发布于:2025-09-13 ⋅ 阅读:(15) ⋅ 点赞:(0)

一、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: nginx
  namespace: test
spec:
  containers:
  - name: nginx
    image: nginx:latest
    
    ports:
    - name: web-port
      containerPort: 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-filebeat
  namespace: test
  labels:
    app: web-with-logging
spec:
  volumes:
  - name: nginx-logs    # 声明一个emptyDir类型的卷,pod重建后数据会丢失。后面会用到,用于挂载到容器。
    emptyDir: {}
  - name: filebeat-config       # 声明一个filebeat-config的卷,类型是configMap配置文件名称是filebeat-config
    configMap:
      name: filebeat-config
  - name: filebeat-data
    emptyDir: {}
  containers:
  - name: nginx
    image: nginx:latest
    imagePullPolicy: IfNotPresent
    ports:
    - containerPort: 80
    volumeMounts:
    - name: nginx-logs          # 将声明的nginx-logs卷挂载到容器nginx的/var/log/nginx目录下
      mountPath: /var/log/nginx
  - name: filebeat
    image: docker.elastic.co/beats/filebeat:8.6.0
    imagePullPolicy: IfNotPresent
    volumeMounts:
    - name: nginx-logs          # 将nginx-logs卷挂载到filebeat容器的/var/log/nginx目录下,这样filebeat容器也可以读取nginx的日志
      mountPath: /var/log/nginx
      readOnly: true  # 只读模式,避免意外修改日志
    - name: filebeat-config # 将配置文件configMap/filebeat-config挂载到filebeat的/usr/share/filebeat/filebeat.yml
      mountPath: /usr/share/filebeat/filebeat.yml
      subPath: filebeat.yml  # 指定挂载的filebeat.yml是一个文件,而不是目录。
    - name: filebeat-data    # 挂载数据卷,保存日志偏移量
      mountPath: /usr/share/filebeat/data
    command: ["/usr/share/filebeat/filebeat", "-c", "/usr/share/filebeat/filebeat.yml", "run"]
---
# Filebeat配置:定义日志收集规则和输出目的地
apiVersion: v1
kind: ConfigMap
metadata:
  name: filebeat-config
  namespace: test
data:
  filebeat.yml: |
    # 日志输入
    filebeat.inputs:
    - type: log
      enabled: true
      paths:
        - /var/log/nginx/access.log  # 收集Nginx访问日志
        - /var/log/nginx/error.log   # 收集Nginx错误日志
    # 日志输出到控制台
      fields:
        service: nginx
      fields_under_root: true
    output.console:
      enabled: true
      codec.json:
        pretty: true
    logging.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 agoATTEMPT 由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: test
  name: static-nginx
  labels:
    app: nginx
spec:
  containers:
    - name: nginx
      image: nginx
      ports:
        - name: web
          containerPort: 80
          protocol: 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.

如上立马生效。


网站公告

今日签到

点亮在社区的每一天
去签到