Logo
活死人の行知路

Kubernetes Pod


📅 | 📝 481 字
#Kubernetes

Pod 与 Docker

基本概念

  • Docker 三要素:镜像、容器、仓库。
  • Pod:K8S 的基本单元。K8S中部署容器,容器处于Pod中。

区别

  • Docker 为单进程设计(类似单机应用),这个进程对应我们部署的一个单一应用项目,比如运行一个Go项目。
  • Pod 为多进程设计(类似集群应用),创建一个Pod,这个Pod中有多个容器,对应多个项目。

Pod 优势

  • 方便K8s管理,与底层容器解耦
  • 同一Pod不需要IP就能调用
  • 定义一组容器,统一监控

Pod 定义参数

首先需要强调下记忆:Pod 是一组容器的集合。

创建一个简单Pod

创建并编辑 pod-busybox.yaml:

apiVersion: v1
kind: Pod

metadata:
  name: busybox
  namespace: test
  labels:
    app: busybox

spec:
  containers:
  - name: busybox
    # 将原来的 image: busybox 替换为国内可用的代理节点
    image: docker.m.daocloud.io/library/busybox:latest
    # 核心:让 busybox 保持运行状态,防止启动后立刻退出
    command: ["sleep", "3600"]
  • 这个yaml文件会用于kubectl来创建Pod。Yaml 文件由3不分组成:

  • 头部:资源的API信息和资源类型

  • 元数据信息:名称、命名空间、标签等信息。

  • 规格信息:

    什么是命名空间?

    命名空间,就是将资源进行隔离的单位,例如相同名称的Pod,但是命名空间不同是允许的。命名空间类似学校的班级,将不同学生分成不同的班级,将这些学生隔离成了不同的班级。 不同的命名空间名字可以相同,同一个命名空间,名字不能相同。

创建Pod

在 vm-1 Master 节点中执行:

kubectl apply -f pod_busybox.yaml

由于yaml定义中指定了 命名空间test,首次创建时一般会出错 Error from server (NotFound): error when creating "pod_busybox.yaml": namespaces "test" not found: 这是因为如果不指定命名空间,会默认放到 default命名空间中,可以通过下面方式创建test并查看命名空间:

kubectl create ns test
kubectl get ns

创建完后需要注意命名空间的状态一定要为 Active,然后重新创建 Pod:

kubectl apply -f pod_busybox.yaml

查看:

kubectl get pod -n test

补充

如果Pod启动失败可以通过下面命令查看错误原因:

# 使用 describe 查看详细事件
kubectl describe pod busybox -n test
# 删除之前失败的 Pod
kubectl delete pod busybox -n test
# 应用新的 YAML
kubectl apply -f pod_busybox.yaml

为 Pod 添加参数

apiVersion: v1
kind: Pod

metadata:
  name: busybox
  namespace: test
  labels:
    app: busybox

spec:
  containers:
  - name: busybox
    # ⭐ 核心调整:结合之前的网络问题,将 image 替换为国内镜像源
    image: docker.m.daocloud.io/library/busybox:latest
    # 可选值: Always|IfNotPresent|Never
    imagePullPolicy: IfNotPresent
    # 环境变量
    env:
    - name: app
      value: busybox
    # 运行终端
    tty: true
    # 特权模式 对宿主机有root权限
    securityContext:
      privileged: true
    # 工作目录
    workingDir: /test
    # 命令
    command: ["/bin/sh"]
    # 参数(每10秒打印一次hello,保持容器一直处于Running状态)
    args: ["-c", "while true; do echo hello; sleep 10;done"]
  • imagePullPolicy:镜像拉取策略,Always表示始终拉取最新镜像,IfNotPresent表示主机上存在就不去远端拉取,Never表示始终不去拉取
  • env:环境变量,比如MySQL的连接信息等环境变量。
  • tty:
  • securityContext:
  • workingDir:
  • command:

删除之前卡在错误状态的旧 Pod

# 命令式删除(直接指名道姓)
kubectl delete pod busybox -n test
# 声明式删除(按图索骥)
kubectl delete -f pod_busybox.yaml

重新创建:

kubectl apply -f pod-busybox.yaml

检查 Pod 状态:

kubectl get pod -n test -w

验证日志输出(测试你的脚本是否正常运行):

kubectl logs -f busybox -n test

为Pod容器分配资源

apiVersion: v1
kind: Pod

metadata:
  name: busybox
  namespace: test
  labels:
    app: busybox

spec:
  containers:
  - name: busybox
    # ⭐ 核心调整:结合之前的网络问题,将 image 替换为国内镜像源
    image: docker.m.daocloud.io/library/busybox:latest
    # 可选值: Always|IfNotPresent|Never
    imagePullPolicy: IfNotPresent
    # 环境变量
    env:
    - name: app
      value: busybox
    # 运行终端
    tty: true
    # 特权模式 对宿主机有root权限
    securityContext:
      privileged: true
    # 工作目录
    workingDir: /test
    # 命令
    command: ["/bin/sh"]
    # 参数(每10秒打印一次hello,保持容器一直处于Running状态)
    args: ["-c", "while true; do echo hello; sleep 10;done"]
    resources:
      requests:
        memory: "100Mi"
        cpu: "1000m"
      limits:
        memory: "200Mi"
        cpu: "1000m"

资源的配额并不是针对Pod,而是针对的Pod中的容器。

重新创建并查看分配节点:

kubectl apply -f pod_busybox_3.yaml
kubectl get pod -n test -o wide

网络

apiVersion: v1
kind: Pod
metadata:
  name: nginx
  namespace: test
  labels:
    app: nginx
spec:
  hostNetwork: true
  #可选值: Default|ClusterFirst|ClusterFirstWithHostNet|None
  dnsPolicy: "Default"
  #dns配置
  dnsConfig:
    nameservers:
    - 8.8.8.8
  #域名映射
  hostAliases:
  - ip: 192.168.1.18
    hostnames:
    - "foo.local"
    - "bar.local"
  containers:
  - name: nginx
    image: nginx
    imagePullPolicy: IfNotPresent
    ports:
  • 比如指定是否使用宿主机的网络,比如Docker中–host参数可以让容器和宿主机共享局域网,
  • dns策略:K8S默认是有DNS的,还可以配置DNS的IP,比如8.8.8.8,114.114.114.114
  • hostAliases域名映射,

Pod Container 健康检查

Pod 卷挂载

作用于Pod的全局参数


首先恭喜你,看到一连串的 hello,说明 Pod 终于成功拉取镜像并正常运行起来了! 之前的网络问题已经完美解决。

至于你现在遇到的新错误 failed to create fsnotify watcher: too many open files,这并不是你的 Pod 或 YAML 写错了,而是操作系统的限制。

🔍 错误原因分析

当你使用 kubectl logs -f(-f 代表 follow,实时追踪)时,底层依赖于 Linux 系统的 inotify 机制来监听日志文件的实时变化。

这个错误提示你的宿主机(从你的提示符看是 vm-1 这台机器)上的 文件监听器(inotify instances/watches)数量已经达到了系统的最大上限。在运行容器化环境(Docker/Kubernetes)的节点上,这是一个非常常见的系统级瓶颈。


🛠️ 解决办法:调高操作系统的 inotify 上限

你需要在报错的这台机器(即 vm-1)上修改内核参数。

第一步:临时修改并立即生效

直接在终端执行以下命令,将最大实例数和监听数调高:

sudo sysctl fs.inotify.max_user_instances=8192
sudo sysctl fs.inotify.max_user_watches=524288

执行完这两行命令后,你再次运行 kubectl logs -f busybox -n test,应该就不会再报错了,日志会持续平滑地输出。

第二步:永久修改(防止重启后失效)

为了让机器下次重启后依然生效,你需要将配置写入系统的 sysctl 配置文件中。

执行以下命令追加配置:

cat <<EOF | sudo tee -a /etc/sysctl.conf
fs.inotify.max_user_instances=8192
fs.inotify.max_user_watches=524288
EOF

然后刷新配置使其生效:

sudo sysctl -p

💡 补充提示

如果你是一个多节点的集群(比如有 vm-1、vm-2 等),强烈建议你在所有节点上都执行一下上述操作。Kubernetes 节点上通常运行着大量的容器和系统组件(如 kubelet、kube-proxy),它们都会消耗大量的文件监听资源,提前调优可以避免日后出现类似 “too many open files” 的诡异报错。