Kubernetes Pod

环境准备

root@master30~ 09:53:08# kubectl create ns pods
root@master30~ 10:04:48# kubectl config set-context --current --namespace pods

Pod 介绍

pod 代表一个deployment单元:a single instance of an application in Kubernetes。

k8s通过定义一个Pod的资源,然后在Pod里面运行容器,容器需要指定镜像,用来运行具体的服务。Pod代表集群上正在运行的一个进程,一个Pod封装一个容器(也可以封装多个容器),Pod里的容器共享存储、网络等。也就是说,应该把整个pod看作虚拟机,然后每个容器相当于运行在虚拟机的进程。

  • 运行单个容器的 Pod:将Pod看作是单个容器的包装器,kubernetes管理pods而不是直接管理容器。
  • 运行多个容器的 Pod:POD可以封装一个由多个共存容器组成的应用程序。pod中的容器会自动在集群中的同一物理机或虚拟机上运行。POD中多个容器共享资源和依赖项,彼此通信,以及协调何时以及如何终止它们。POD将这些容器、网络资源和存储资源作为一个单一的可管理实体包装在一起。pod中多个容器共享网络和存储资源。每个pod分配唯一的ip地址,pod中容器共享netns,包括ip地址和port端口。多个容器之间使用localhost通信。当pod中容器与其他pod通信,需要使用共享的网络资源。pod可以使用多个volume,pod中所有容器都可以访问这些卷。

白话解释: 可以把pod看成是一个“豌豆荚”,里面有很多“豆子”(容器)。一个豌豆荚里的豆子,它们吸收着共同的营养成分、肥料、水分等,Pod和容器的关系也是一样,Pod里面的容器共享pod的网络、存储等。

在这里插入图片描述

pod 基本管理

创建 pod

#语法
kubectl run NAME --image=image [--env="key=value"] [--port=port] [--dry-run=server|client] [--overrides=inline-json] [--command] -- [COMMAND] [args...] [options]
root@master30~ 10:05:39# mkdir pods
root@master30~ 10:05:47# cd pods

#空运行,只生成yaml文件
root@master30~/pods 10:21:43# kubectl run webapp --image=docker.io/library/nginx --dry-run client -o yaml
apiVersion: v1
kind: Pod
metadata:
  creationTimestamp: null
  labels:
    run: webapp
  name: webapp
spec:
  containers:
  - args:
    - client
    image: docker.io/library/nginx
    name: webapp
    resources: {}
  dnsPolicy: ClusterFirst
  restartPolicy: Always
status: {}

dry-run 两种模式区别

  1. --dry-run=client(最常用)
    

    本地生成 yaml,不请求集群,不校验集群资源,断网也能执行。

  2. --dry-run=server
    

    请求 apiserver,服务端模拟创建、校验权限 / 镜像 / 配额,但最终不落地存储;适合校验配置是否合法。

#直接创建pod
root@master30~/pods 10:24:56# kubectl run webapp --image=docker.io/library/nginx
pod/webapp created
root@master30~/pods 10:25:04# kubectl get pods
NAME     READY   STATUS    RESTARTS   AGE
webapp   1/1     Running   0          7s

查看 pod

#以yaml格式查看pod
root@master30~/pods 10:45:36# kubectl get pods webapp -o yaml
#查看pod详细信息
root@master30~/pods 10:40:33# kubectl describe pods webapp
# 查看pod标准输出,可以使用选项-f动态查看pod输出
root@master30~ 18:33:01# kubectl logs -f webapp

编辑 pod

root@master30~ 18:35:06# kubectl edit pod webapp

提示:并不是所有属性都可以编辑,例如pod名称。如果非要编辑特定属性,可以先删除pod,然后修改pod对的yaml文件,重新创建。

pod 中执行命令

root@master30~ 18:46:29# kubectl exec webapp -- hostname
webapp
root@master30~ 18:46:45# kubectl exec webapp -- pwd
/
root@master30~ 18:48:14# kubectl exec webapp -- id
uid=0(root) gid=0(root) groups=0(root)

cp 文件给 pod

root@master30~/pods 10:25:11# kubectl get pods webapp -o wide
NAME     READY   STATUS    RESTARTS   AGE   IP              NODE                 NOMINATED NODE   READINESS GATES
webapp   1/1     Running   0          27s   10.224.96.194   worker32.hgq.cloud   <none>           <none>
root@master30~/pods 10:26:17# echo "hello world" > index.html
root@master30~/pods 10:26:40# kubectl cp index.html webapp:/usr/share/nginx/html/index.html
root@master30~/pods 10:27:36# curl 10.224.96.194
hello world

删除 pod

root@master30~ 18:52:37# kubectl delete pod webapp
pod "webapp" deleted

yaml 文件创建 pod

#webapp.yaml
apiVersion: v1
kind: Pod
metadata:
  labels:
    run: webapp
  name: webapp
spec:
  containers:
  - image: docker.io/library/nginx
    imagePullPolicy: IfNotPresent
    name: webapp
root@master30~ 19:01:06# kubectl create -f webapp.yaml
pod/webapp created
#或者
root@master30~ 18:55:03# kubectl apply -f webapp.yaml
pod/web created

实验:构建wordpress

  1. 创建 pod-mysql 数据库
  2. 创建 pod-wordpress 博客
#创建 pod-mysql 数据库
root@master30~ 11:17:10# kubectl run wordpress-db --image=hub.laoma.cloud/library/mysql:latest --env MYSQL_ROOT_PASSWORD=123
pod/wordpress-db created

#查看wordpress-db详情可知被分配到worker32节点
root@master30~ 11:47:09# kubectl describe pods wordpress-db | tail
Tolerations:                 node.kubernetes.io/not-ready:NoExecute op=Exists for 300s
                             node.kubernetes.io/unreachable:NoExecute op=Exists for 300s
Events:
  Type    Reason     Age   From               Message
  ----    ------     ----  ----               -------
  Normal  Scheduled  22m   default-scheduler  Successfully assigned pods/wordpress-db to worker32.hgq.cloud
  Normal  Pulling    22m   kubelet            Pulling image "hub.laoma.cloud/library/mysql:latest"
  Normal  Pulled     19m   kubelet            Successfully pulled image "hub.laoma.cloud/library/mysql:latest" in 3m41.722s (3m41.722s including waiting). Image size: 266353003 bytes.
  Normal  Created    19m   kubelet            Created container wordpress-db
  Normal  Started    19m   kubelet            Started container wordpress-db

#创建 pod-wordpress 博客
root@master30~ 11:24:17# kubectl run wordpress-app --image=hub.laoma.cloud/library/wordpress:latest

#查看IP
root@master30~ 11:29:36# kubectl get pods -o wide
NAME            READY   STATUS    RESTARTS   AGE     IP              NODE                 NOMINATED NODE   READINESS GATES
wordpress-app   1/1     Running   0          4m51s   10.224.128.2    worker31.hgq.cloud   <none>           <none>
wordpress-db    1/1     Running   0          6m11s   10.224.96.197   worker32.hgq.cloud   <none>           <none>

#创建数据库
root@master30~ 11:31:29# kubectl exec -it wordpress-db -- mysql -uroot -p123
#创建数据库实例
mysql> create database wordpress;
#新建数据库普通用户wordpress,登录密码设为123
mysql> create user wordpress identified by '123';
#给用户wordpress授予wordpress库下全部权限
mysql> grant all privileges on wordpress.* to wordpress;
#刷新
mysql> flush privileges;
#退出
mysql> exit

#实现集群外访问集群内pod
root@master30~ 11:34:16# kubectl port-forward pod/wordpress-app --address 10.1.8.30 80:80
Forwarding from 10.1.8.30:80 -> 80
#该命令窗口不要关闭

访问web页面 http://10.1.8.30:80,即可配置站点。

在这里插入图片描述

多容器 pod

示例文件:

root@master30~ 19:03:11# vim pod-blog.yaml
apiVersion: v1
kind: Pod
metadata:
  name: bbs
  labels:
    run: bbs
spec:
  containers:
  - image: hub.laoma.cloud/library/mysql:latest
    imagePullPolicy: IfNotPresent
    name: mysql
    env:
    - name: MYSQL_ROOT_PASSWORD
      value: "123"
    - name: MYSQL_USER
      value: tom
    - name: MYSQL_PASSWORD
      value: "123"
    - name: MYSQL_DATABASE
      value: bbs
    ports:
    - containerPort: 3306
      name: mysql
      protocol: TCP
  - image: hub.laoma.cloud/library/wordpress:latest
    imagePullPolicy: IfNotPresent
    name: wordpress
    env:
    - name: WORDPRESS_DB_USER
      value: tom
    - name: WORDPRESS_DB_PASSWORD
      value: "123"
    - name: WORDPRESS_DB_NAME
      value: bbs
    - name: WORDPRESS_DB_HOST
      value: 127.0.0.1
    ports:
    - containerPort: 80
      name: wordpress
      protocol: TCP
      hostPort: 80
root@master30~ 19:04:57# kubectl apply -f pod-blog.yaml
pod/bbs created
root@master30~ 19:07:35# kubectl get pods -o wide
NAME   READY   STATUS    RESTARTS   AGE   IP              NODE                 NOMINATED NODE   READINESS GATES
bbs    2/2     Running   0          33s   10.224.96.209   worker32.hgq.cloud   <none>           <none>

此时端口绑定在单个节点上,只有运行这个 Pod 的那台机器的 IP + 80 端口才能访问,即使用worker32节点IP才可以访问

在这里插入图片描述

#多容器Pod中执行命令,可通过-c指定容器
root@master30~ 19:10:46# kubectl exec bbs -c wordpress -- hostname
bbs
#指定容器复制命令
root@master30~ 19:13:36# kubectl cp /etc/hosts bbs:/new_hosts -c wordpress
root@master30~ 19:14:21# kubectl exec bbs -c wordpress -- ls /new_hosts
/new_hosts
#如果不加-c,则kubectl cp默认取Pod第一个容器
root@master30~ 19:19:14# kubectl cp /etc/hosts bbs:/new-hosts
Defaulted container "mysql" out of: mysql, wordpress

数据库访问测试:

root@master30~ 19:20:41# kubectl exec -it bbs -c mysql -- mysql -uroot -p123
mysql: [Warning] Using a password on the command line interface can be insecure.
Welcome to the MySQL monitor.  Commands end with ; or \g.
Your MySQL connection id is 13
Server version: 9.6.0 MySQL Community Server - GPL

Copyright (c) 2000, 2026, Oracle and/or its affiliates.

Oracle is a registered trademark of Oracle Corporation and/or its
affiliates. Other names may be trademarks of their respective
owners.

Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.

mysql>
#创建svc
root@master30~ 19:28:36#  kubectl expose pod bbs --type NodePort
service/bbs exposed

#查看现有服务详情
root@master30~ 19:30:02# kubectl get svc bbs
NAME   TYPE       CLUSTER-IP       EXTERNAL-IP   PORT(S)                       AGE
bbs    NodePort   10.109.204.172   <none>        3306:31070/TCP,80:30203/TCP   34s
#端口映射格式“容器端口:NodePort外部端口”,此时集群中的任一节点都可通过30203端口访问wordpress页面

root@master30~ 19:30:11# kubectl describe svc bbs
Name:                     bbs
Namespace:                pods
Labels:                   run=bbs
Annotations:              <none>
Selector:                 run=bbs
Type:                     NodePort
IP Family Policy:         SingleStack
IP Families:              IPv4
IP:                       10.109.204.172
IPs:                      10.109.204.172
Port:                     port-1  3306/TCP
TargetPort:               3306/TCP
NodePort:                 port-1  31070/TCP
Endpoints:                10.224.96.209:3306
Port:                     port-2  80/TCP
TargetPort:               80/TCP
NodePort:                 port-2  30203/TCP
Endpoints:                10.224.96.209:80
Session Affinity:         None
External Traffic Policy:  Cluster
Events:                   <none>

#删除已有的svc
root@master30~ 19:27:37# kubectl delete svc bbs

#修改现有svc
root@master30~ 19:35:39# kubectl edit svc bbs

在这里插入图片描述

pod 关键属性

root@master30~ 19:55:38# kubectl explain pod | grep '^  [a-zA-Z]'
  apiVersion    <string>
  kind  <string>
  metadata      <ObjectMeta>
  spec  <PodSpec>
  status        <PodStatus>

pod.metadata

root@master30~ 19:55:46# kubectl explain pod.metadata | grep '^  [a-zA-Z]'
  annotations   <map[string]string>
  creationTimestamp     <string>
  deletionGracePeriodSeconds    <integer>
  deletionTimestamp     <string>
  finalizers    <[]string>
  generateName  <string>
  generation    <integer>
  labels        <map[string]string>
  managedFields <[]ManagedFieldsEntry>
  name  <string>
  namespace     <string>
  ownerReferences       <[]OwnerReference>
  resourceVersion       <string>
  selfLink      <string>
  uid   <string>

需要关注的属性:labels,name,namespace,deletionGracePeriodSeconds。

pod.spec

root@master30~ 19:56:52# kubectl explain pod.spec | grep '^  [a-zA-Z]'
  activeDeadlineSeconds <integer>
  affinity      <Affinity>
  automountServiceAccountToken  <boolean>
  containers    <[]Container> -required-
  dnsConfig     <PodDNSConfig>
  dnsPolicy     <string>
  enum: ClusterFirst, ClusterFirstWithHostNet, Default, None
  enableServiceLinks    <boolean>
  ephemeralContainers   <[]EphemeralContainer>
  hostAliases   <[]HostAlias>
  hostIPC       <boolean>
  hostNetwork   <boolean>
  hostPID       <boolean>
  hostUsers     <boolean>
  hostname      <string>
  imagePullSecrets      <[]LocalObjectReference>
  initContainers        <[]Container>
  nodeName      <string>
  nodeSelector  <map[string]string>
  os    <PodOS>
  overhead      <map[string]Quantity>
  preemptionPolicy      <string>
  enum: Never, PreemptLowerPriority
  priority      <integer>
  priorityClassName     <string>
  readinessGates        <[]PodReadinessGate>
  resourceClaims        <[]PodResourceClaim>
  restartPolicy <string>
  enum: Always, Never, OnFailure
  runtimeClassName      <string>
  schedulerName <string>
  schedulingGates       <[]PodSchedulingGate>
  securityContext       <PodSecurityContext>
  serviceAccount        <string>
  serviceAccountName    <string>
  setHostnameAsFQDN     <boolean>
  shareProcessNamespace <boolean>
  subdomain     <string>
  terminationGracePeriodSeconds <integer>
  tolerations   <[]Toleration>
  topologySpreadConstraints     <[]TopologySpreadConstraint>
  volumes       <[]Volume>

重点关注:containers、nodeName、volumes等。

pod.spec.containers
root@master30~ 19:58:35# kubectl explain pod.spec.containers | grep '^  [a-zA-Z]'
  args  <[]string>
  command       <[]string>
  env   <[]EnvVar>
  envFrom       <[]EnvFromSource>
  image <string>
  imagePullPolicy       <string>
  enum: Always, IfNotPresent, Never
  lifecycle     <Lifecycle>
  livenessProbe <Probe>
  name  <string> -required-
  ports <[]ContainerPort>
  readinessProbe        <Probe>
  resizePolicy  <[]ContainerResizePolicy>
  resources     <ResourceRequirements>
  restartPolicy <string>
  securityContext       <SecurityContext>
  startupProbe  <Probe>
  stdin <boolean>
  stdinOnce     <boolean>
  terminationMessagePath        <string>
  terminationMessagePolicy      <string>
  enum: FallbackToLogsOnError, File
  tty   <boolean>
  volumeDevices <[]VolumeDevice>
  volumeMounts  <[]VolumeMount>
  workingDir    <string>

重点关注:command、env、image、imagePullPolicy、volumeMounts等。

pod.spec.containers.ImagePullPolicy
  • Always,总是从仓库下载镜像。
  • Never,只使用本地镜像,不下载。
  • IfNotPresent,优先使用本地镜像,如果没有才从仓库下载镜像。
pod lifecycle 和 status
pod lifecycle
  • pod的生命周期取决于pod中所有容器的生命周期。
  • 容器的生命周期取决于容器中进程的生命周期。
Pod status

常见 pod 状态如下:

  • ContainerCreating 正在创建
  • Running 正在运行
  • Completed 运行完成
  • Error/RunContainerError 运行错误
  • CrashLoopBackOff 重新创建
  • ErrImagePull 获取镜像错误
  • ImagePullBackOff 重新获取镜像
  • Terminating,正在终止(删除)
实验1:pod中包含1个容器,验证pod状态

监控命令: watch -n 1 kubectl get pod(另开窗口观察)

创建资源:kubectl apply -f test.yaml

示例1:test.yaml

apiVersion: v1
kind: Pod
metadata:
  name: busybox
  labels:
    app: busybox
spec:
  restartPolicy: Never
  containers:
  - name: busybox
    image: docker.io/library/busybox
    imagePullPolicy: IfNotPresent
    command: ['sh', '-c', 'echo Hello Kubernetes! && sleep 10']

command命令可以改写如下:

command:
- sh
- -c
- echo OK! && sleep 10

args:
- sh
- -c
- echo OK! && sleep 10

观察pod状态为:ContainerCreating–>Running–>Completed

示例2:test.yaml

apiVersion: v1
kind: Pod
metadata:
  name: busybox
  labels:
    app: busybox
spec:
  restartPolicy: Never
  containers:
  - name: busybox
    image: docker.io/library/busybox
    imagePullPolicy: IfNotPresent
    command: ['sh', '-c', 'echoxxx Hello Kubernetes! && sleep 5']

观察pod状态为:ContainerCreating–>Error

实验2:pod中包含2个容器,验证pod状态

示例1:test.yaml

apiVersion: v1
kind: Pod
metadata:
  name: busybox
  labels:
    app: busybox
spec:
  restartPolicy: Never
  containers:
  - name: busybox1
    image: docker.io/library/busybox
    imagePullPolicy: IfNotPresent
    command: ['sh', '-c', 'echo Hello Kubernetes! && sleep 5']
  - name: busybox2
    image: docker.io/library/busybox
    imagePullPolicy: IfNotPresent
    command: ['sh', '-c', 'echo Hello Kubernetes! && sleep 10']

观察pod状态为:ContainerCreating–>Running–>NotReady(其中一个先完成)–>Completed(两个都完成)

示例2:test.yaml

apiVersion: v1
kind: Pod
metadata:
  name: busybox
  labels:
    app: busybox
spec:
  restartPolicy: Never
  containers:
  - name: busybox1
    image: docker.io/library/busybox
    imagePullPolicy: IfNotPresent
    command: ['sh', '-c', 'echoxx Hello Kubernetes! && sleep 5']
  - name: busybox2
    image: docker.io/library/busybox
    imagePullPolicy: IfNotPresent
    command: ['sh', '-c', 'echo Hello Kubernetes! && sleep 20']

观察pod状态为:ContainerCreating–>Error

pod.spec.restartPolicy

示例:

  restartPolicy: Never
  containers:
  - name: myapp-container
    image: docker.io/library/busybox
    command: ['sh', '-c', 'echo The app is running! && sleep 5'] 

restartPolicy,针对pod中所有容器生效。

  • Always,除了 Running 状态,其他状态总是重启,默认值。
  • OnFailure,失败了才重启。
  • Never,从不重启。
实验1:验证pod中含有单个容器重启策略。

验证OnFailure重启策略:

apiVersion: v1
kind: Pod
metadata:
  name: busybox
  labels:
    app: busybox
spec:
  restartPolicy: OnFailure
  containers:
  - name: busybox
    image: docker.io/library/busybox
    imagePullPolicy: IfNotPresent
    command: ['sh', '-c', 'echoxxx Hello Kubernetes! && sleep 5']

验证 Never 重启策略:

apiVersion: v1
kind: Pod
metadata:
  name: busybox
  labels:
    app: busybox
spec:
  restartPolicy: Never
  containers:
  - name: busybox
    image: docker.io/library/busybox
    imagePullPolicy: IfNotPresent
    command: ['sh', '-c', 'echoxxx Hello Kubernetes! && sleep 5']
实验2:验证pod中含有多个容器重启策略。

验证结果:只要有一个容器满足重启策略条件,就会重启。

示例1:

apiVersion: v1
kind: Pod
metadata:
  name: busybox
  labels:
    app: busybox
spec:
  restartPolicy: Always/OnFailure/Never
  containers:
  - name: busybox1
    image: docker.io/library/busybox
    imagePullPolicy: IfNotPresent
    command: ['sh', '-c', 'echo Hello Kubernetes! && sleep 5']
  - name: busybox2
    image: docker.io/library/busybox
    imagePullPolicy: IfNotPresent
    command: ['sh', '-c', 'echo Hello Kubernetes! && sleep 5']

使用Always重启策略时,当容器busybox1状态为Completed时,容器busybox2还未创建成功,此时会根据重启策略重启pod。当然也可以将容器的生命周期延长,sleep 5改为sleep 50,运行50s之后还会重启pod。

使用OnFailure/Never重启策略就不会出现这种情况。

示例2:

apiVersion: v1
kind: Pod
metadata:
  name: busybox
  labels:
    app: busybox
spec:
  restartPolicy: Always/OnFailure/Never
  containers:
  - name: busybox1
    image: docker.io/library/busybox
    imagePullPolicy: IfNotPresent
    command: ['sh', '-c', 'echo Hello Kubernetes! && sleep 5']
  - name: busybox2
    image: docker.io/library/busybox
    imagePullPolicy: IfNotPresent
    command: ['sh', '-c', 'echoxxx Hello Kubernetes! && sleep 5']

由于第二个command是错误的,故Always和OnFailure重启策略总是会重启pod;Never重启策略就不会重启pod。

Init Containers

一个pod可以有多个容器在其中运行应用程序,也可以有一个或多个initContainers。initContainers中容器状态必须是complete,containers容器才能运行。

如果pod的initContainers fail,kubernetes根据restartpolicy重启pod,直到initContainers状态为complete。

如果pod中initContainers有多个容器,那么会按顺序创建和执行。按顺序执行的initContainers必须成功才能执行下一个initContainers。所有init全部成功执行完成后,才开始执行pod中常规容器。

静态 pod

**问题:**正常情况下,pod 由 master 节点统一管理。那么 master 上的kube-apiserver、kube-scheduler、kube-controller-manager等pod又是由谁来管理的呢?

答案kubelet 服务。master节点上组件以静态Pod方式运行,由本地kubelet进行管理。它们不能通过API Server进行管理,无法与ReplicationController、Deployment或DaemonSet进行关联,并且kubelet也无法对其健康检查。

kubelet.service 配置

root@master30~ 20:13:57# systemctl status kubelet.service | cat
● kubelet.service - kubelet: The Kubernetes Node Agent
     Loaded: loaded (/usr/lib/systemd/system/kubelet.service; enabled; preset: enabled)
    Drop-In: /usr/lib/systemd/system/kubelet.service.d
             └─10-kubeadm.conf
     Active: active (running) since Wed 2026-06-24 17:56:37 CST; 2h 20min ago
       Docs: https://kubernetes.io/docs/
   Main PID: 1305 (kubelet)
      Tasks: 18 (limit: 4554)
     Memory: 46.5M (peak: 48.2M)
        CPU: 2min 46.496s
     CGroup: /system.slice/kubelet.service
             └─1305 /usr/bin/kubelet --bootstrap-kubeconfig=/etc/kubernetes/bootstrap-kubelet.conf --kubeconfig=/etc/kubernetes/kubelet.conf --config=/var/lib/kubelet/config.yaml --container-runtime-endpoint=unix:///var/run/containerd/containerd.sock --pod-infra-container-image=registry.k8s.io/pause:3.9
......

root@master30~ 20:17:59# cat /usr/lib/systemd/system/kubelet.service
[Unit]
Description=kubelet: The Kubernetes Node Agent
Documentation=https://kubernetes.io/docs/
Wants=network-online.target
After=network-online.target

[Service]
ExecStart=/usr/bin/kubelet
Restart=always
StartLimitInterval=0
RestartSec=10

[Install]
WantedBy=multi-user.target

# kubelet.service服务启动参数通过 Drop-In 文件 10-kubeadm.conf 配置
root@master30~ 20:17:47# cat /usr/lib/systemd/system/kubelet.service.d/10-kubeadm.conf
# Note: This dropin only works with kubeadm and kubelet v1.11+
[Service]
Environment="KUBELET_KUBECONFIG_ARGS=--bootstrap-kubeconfig=/etc/kubernetes/bootstrap-kubelet.conf --kubeconfig=/etc/kubernetes/kubelet.conf"
Environment="KUBELET_CONFIG_ARGS=--config=/var/lib/kubelet/config.yaml"
# This is a file that "kubeadm init" and "kubeadm join" generates at runtime, populating the KUBELET_KUBEADM_ARGS variable dynamically
EnvironmentFile=-/var/lib/kubelet/kubeadm-flags.env
# This is a file that the user can use for overrides of the kubelet args as a last resort. Preferably, the user should use
# the .NodeRegistration.KubeletExtraArgs object in the configuration files instead. KUBELET_EXTRA_ARGS should be sourced from this file.
EnvironmentFile=-/etc/default/kubelet
ExecStart=
ExecStart=/usr/bin/kubelet $KUBELET_KUBECONFIG_ARGS $KUBELET_CONFIG_ARGS $KUBELET_KUBEADM_ARGS $KUBELET_EXTRA_ARGS

# 以下参数定义了kubelet配置文件位置
# KUBELET_CONFIG_ARGS=--config=/var/lib/kubelet/config.yaml
# 该文件中的 staticPodPath 参数定义了一个目录
# kubelet会定期扫描该目录中pod文件,并根据目标中文件变动创建和删除pod
root@master30~ 20:20:00# grep staticPodPath /var/lib/kubelet/config.yaml
staticPodPath: /etc/kubernetes/manifests

root@master30~ 20:20:57# ls -1 /etc/kubernetes/manifests/
etcd.yaml
kube-apiserver.yaml
kube-controller-manager.yaml
kube-scheduler.yaml

**注意:**不要修改 staticPodPath 参数配置,否则需要将集群组件4个yaml文件也要复制过去。

总结

1.kubernetes 中 pod 和 container 的区别

容器是运行时概念真正跑应用的进程环境

kubernetes 中 Pod:是 K8s 独有的概念,是 K8s 中最小调度、管理、自愈单元,是容器的“外壳 + 运行环境”

  • **一个 Pod 里可以有 1 个或多个容器,**pod中所有容器:
    • 同住一个房间,共用网络、存储
    • 一起被调度到同一台机器,一起销毁。
image-20260305090903197
特性容器Pod
K8s 最小调度单位❌ 不是✅ 是
独立 IP✅ 有✅ 有
独立 存储✅ 有✅ 有
多容器支持❌ 不支持✅ 天然支持
网络/存储共享❌ 不能✅ 内部容器可共享
生命周期管理❌ 弱✅ 完整(重启、自愈)
属于谁运行时(Docker/containerd)Kubernetes

2.kubernetes 为什么直接管理 pod 而不是容器

  1. 容器太“原子”,不适合直接调度。K8s 需要一个能直接被调度、能独立运行、有完整身份的对象–Pod
  • 容器:只是一个进程/运行环境(Docker/containerd)。

  • Pod:是容器的封装 + 网络/存储/配置/生命周期的统一抽象。K8s 调度、扩缩容、自愈、服务发现、监控……全都以 Pod 为单位

  1. Pod 支持“多容器协同”(最关键设计)。

    很多场景必须多个容器一起跑、共享资源

    • 业务容器 + Sidecar(日志、监控、代理)
    • 业务容器 + InitContainer(初始化)
    • 业务容器 + 网络/安全代理容器

    它们需要:

    • 共享 Network Namespace(同一个 IP、端口空间)
    • 共享 Volume
    • 一起调度到同一台机器
  2. Pod 提供统一的生命周期与自愈

    K8s 要做:

    • 重启失败容器
    • 替换崩溃节点上的实例
    • 滚动更新、回滚
    • 扩缩容

    这些行为必须作用在一个稳定、标准、独立的单元上:

    • 如果直接管容器,多容器应用会乱
    • 以 Pod 为单位,管理语义清晰、一致
  3. 解耦底层容器运行时。

    Pod 屏蔽了底层实现:

    • Docker
    • containerd
    • cri-o
    • 其他 CRI 运行时

    K8s 只跟 Pod/CRI 打交道,不绑定某一种容器技术。

3.pod中pause容器作用

在 Kubernetes 里,每个 Pod 都会自动创建一个 pause 容器(也叫 infra 容器),它是 Pod 里第一个启动、最后退出的容器,作用非常关键。

  1. pause 容器就是为了“占坑”,把 Pod 的网络和命名空间先 hold 住。

  2. 它的 3 个核心作用

    创建并持有 Pod 的 Linux Namespace

    Pod 里所有容器要共享:

    • Network namespace(同一个 IP、端口)
    • PID namespace(可选)
    • IPC namespace

    这些共享空间必须由一个“永远不死”的容器来持有,否则共享空间会消失。这个容器就是 pause

    让 Pod 生命周期独立于业务容器

    • 业务容器挂了 → 重启
    • pause 容器不挂 → Pod 就不会消失
    • 网络、IP、存储挂载都能保持不变

    如果没有 pause:业务容器一退出,整个 Pod 的网络就没了,重启也没用。

    实现多容器共享网络

    nginx、业务容器、sidecar 都加入 pause 的 network namespace:

    • 共享同一个 IP
    • 可以用 127.0.0.1 互相访问
    • 端口不能冲突
  3. 超形象比喻

    • pause = 房东
    • Pod = 房子
    • 业务容器 = 租客

    房东(pause)先占好房子(网络/命名空间),租客(业务容器)才能住进来。租客换了一波又一波,房子一直都在。

  4. 一个 Pod 内部结构(最标准)

    Pod
    ├── pause 容器(infra)—— 永远第一个启动
    │    持有:网络命名空间、IP、IPC
    └── 业务容器 1、2、3...
         都加入 pause 的命名空间
    
  5. 最精炼总结

    pause 容器 = Pod 的基石

    • 只负责 holding namespace
    • 保证 Pod 网络、IP、生命周期稳定
      Pod 的网络和命名空间先 hold 住。**
  6. 它的 3 个核心作用

    创建并持有 Pod 的 Linux Namespace

    Pod 里所有容器要共享:

    • Network namespace(同一个 IP、端口)
    • PID namespace(可选)
    • IPC namespace

    这些共享空间必须由一个“永远不死”的容器来持有,否则共享空间会消失。这个容器就是 pause

    让 Pod 生命周期独立于业务容器

    • 业务容器挂了 → 重启
    • pause 容器不挂 → Pod 就不会消失
    • 网络、IP、存储挂载都能保持不变

    如果没有 pause:业务容器一退出,整个 Pod 的网络就没了,重启也没用。

    实现多容器共享网络

    nginx、业务容器、sidecar 都加入 pause 的 network namespace:

    • 共享同一个 IP
    • 可以用 127.0.0.1 互相访问
    • 端口不能冲突
  7. 超形象比喻

    • pause = 房东
    • Pod = 房子
    • 业务容器 = 租客

    房东(pause)先占好房子(网络/命名空间),租客(业务容器)才能住进来。租客换了一波又一波,房子一直都在。

  8. 一个 Pod 内部结构(最标准)

    Pod
    ├── pause 容器(infra)—— 永远第一个启动
    │    持有:网络命名空间、IP、IPC
    └── 业务容器 1、2、3...
         都加入 pause 的命名空间
    
  9. 最精炼总结

    pause 容器 = Pod 的基石

    • 只负责 holding namespace
    • 保证 Pod 网络、IP、生命周期稳定

更多推荐