Kubernetes Manifests 资源清单核心概念

一、什么是 Kubernetes Manifests ?

Manifests 就是用 YAML(或 JSON)文件描述“你希望 Kubernetes 集群长什么样子”的一份声明性配置。

Kubernetes 是声明式系统(Declarative),你只需要告诉它“我想要什么”,不需要告诉它“怎么一步步去做”。 只要写好 Manifests 通过 kubectl apply -f xxx.yaml 应用到 Kubernetes 会自动把集群变成你描述的样子。

对比命令式(Imperative):

  • 命令式:kubectl run nginx --image=nginx:1.14 --port=80 --replicas=3(不推荐长期使用)
  • 声明式:写一个 YAML 文件,然后 kubectl apply -f nginx.yaml(生产)

二、为什么一定要用 Manifests?

优势说明
声明式管理只关心最终状态,不关心执行路径,出错自动修复(自愈)
可版本化(GitOps 基础)YAML 文件可以放进 Git,历史可追溯、代码审查、回滚一键完成
环境一致性开发、测试、生产环境使用同一份文件(稍改参数即可),杜绝“在我机器上能跑”问题
自动化部署配合 ArgoCD、Flux、Jenkins 等 CI/CD 工具实现自动化甚至零人工干预
团队协作所有人修改的都是同一份配置文件,避免口口相传或脚本到处飞

三、一个最经典的 Manifests 示例

nginx-deployment.yaml

apiVersion: apps/v1                  # 1. 必须字段:用哪个 API 版本
kind: Deployment                     # 2. 必须字段:资源类型,这里是 Deployment
metadata:                            # 3. 必须字段:资源的元数据
  name: nginx-deployment             # Deployment 的名字
  labels:                            # (可选)给 Deployment 自己打标签
    app: nginx
spec:                                # 4. 必须字段:期望的状态(Specification)
  replicas: 2                        # 我想要 2 个副本
  selector:                          # 【关键!】Deployment 通过这个选择器找到它要管理的 Pod
    matchLabels:
      app: nginx                     # 必须和下面 template 中的 label 完全一致!
  template:                          # Pod 模板:真正的 Pod 长什么样子
    metadata:
      labels:                        # 【关键!】这里必须和上面的 selector.matchLabels 保持一致
        app: nginx
    spec:                              # Pod 里面容器的详细定义
      containers:
      - name: nginx                  # 容器名字
        image: nginx:1.14-alpine     # 使用哪个镜像
        ports:
        - containerPort: 80         # 容器暴露的端口(只是声明,Service 才能真正对外访问)
        resources:                  # (可选)资源限制
          limits:
            cpu: "500m"
            memory: "512Mi"
          requests:
            cpu: "200m"
            memory: "256Mi"

执行:

kubectl apply -f nginx-deployment.yaml

效果:

Kubernetes 会自动创建 1 个 Deployment + 1 个 ReplicaSet + 2 个 Pod

四、Manifests 必填的 4 个顶级字段

所有 Kubernetes 资源清单都必须包含这四个字段:

字段含义
apiVersion使用哪个版本的 Kubernetes API
kind创建什么资源(Pod、Deployment、Service…)
metadata资源的元数据(名字、标签、注解等)
spec你期望的详细状态

五、YAML 语法规范

# 1. Maps(字典/键值对) → 用冒号 :
name: zhangsan
age: 18

# 2. Lists(列表) → 用短横线 -
fruits:
  - apple
  - banana
  - orange

# 3. 嵌套(最常见)
spec:
  containers:
  - name: nginx
    image: nginx:1.14
    ports:
    - containerPort: 80

注意事项

  • 缩进只能用空格,绝对不能用 Tab(很多编辑器会偷偷帮你转 Tab)
  • 冒号后面必须加一个空格(如 image: nginximage:nginx错误写法 )
  • 大小写敏感:apiVersion ≠ apiversion

六、如何知道每个资源有哪些字段

使用explain命令查看层级字段

# 查看某种资源有哪些一级字段
kubectl explain deployment

# 继续深挖某个字段
kubectl explain deployment.spec
kubectl explain deployment.spec.template.spec

# 查看 Pod 所有字段(最全参考)
kubectl explain pod

# 甚至可以直接生成模板
kubectl create deployment nginx --image=nginx --dry-run=client -o yaml > nginx.yaml

七、写 Manifests 的正确姿势

  1. 先想清楚要创建什么资源(Pod?Deployment?Service?Ingress?)
  2. kubectl explain 资源名 查看字段
  3. 推荐做法:先用命令生成模板,再修改如:
kubectl create deployment myapp --image=nginx --dry-run=client -o yaml > myapp.yaml`

改完后再用kubectl apply -f myapp.yaml部署

4.放入 Git仓库,拥抱 GitOps 时代

这样写出来的 Manifests 既规范又不容易出错,团队协作也完全没问题。

八、完整资源清单参考

下面是一份完整、规范、最新(Kubernetes 1.30+ 适用)且经过实际生产验证的 Pod 资源清单参考模板,包含所有常用字段、正确层级、官方推荐写法仅供参考。

apiVersion: v1                     # 必填:Pod 属于 core/v1 组,几乎永远是 v1
kind: Pod                          # 必填:资源类型为 Pod
metadata:                          # 必填:元数据
  name: nginx-pod                  # 必填:Pod 名字,全集群 + namespace 唯一
  namespace: default               # 可选:命名空间,默认 default
  labels:                          # 推荐:标签,用于 Service、Deployment 选择
    app.kubernetes.io/name: nginx
    app.kubernetes.io/instance: nginx-01
    env: production
  annotations:                     # 可选:注解,常用于工具标记、配置下发等
    prometheus.io/scrape: "true"
    prometheus.io/port: "80"
    k8s.aliyun.com/ingress: "true"

spec:                              # 必填:Pod 的详细规格(期望状态)
  restartPolicy: Always            # 可选:重启策略,Pod 直接使用时推荐 Always(默认)
                                   # Always(默认) / OnFailure / Never
  terminationGracePeriodSeconds: 30   # 可选:优雅终止等待时间,默认 30s
  dnsPolicy: ClusterFirst          # 可选:DNS 策略,常用 ClusterFirst | Default | None
  nodeSelector:                    # 可选:节点选择器
    kubernetes.io/hostname: node-01
  nodeName: node-02                # 可选:直接调度到指定节点(强绑定,慎用)
  hostNetwork: false               # 可选:是否使用宿主机网络(常用于 DaemonSet)
  hostPID: false                   # 可选:是否共享宿主机 PID 命名空间
  hostIPC: false                   # 可选:是否共享宿主机 IPC 命名空间
  hostname: my-nginx               # 可选:设置 Pod 内的 hostname
  subdomain: nginx-service         # 可选:配合 headless Service 设置子域名
  serviceAccountName: nginx-sa     # 可选:使用的 ServiceAccount(RBAC 权限相关)
  automountServiceAccountToken: true  # 是否自动挂载 SA token
  imagePullSecrets:                # 可选:拉取私有镜像仓库需要的 secret
  - name: docker-registry-secret
  tolerations:                     # 可选:容忍污点,让 Pod 可以调度到有污点的节点
  - key: "node-type"
    operator: "Equal"
    value: "special"
    effect: "NoSchedule"

  containers:                      # 必填:容器列表(至少一个)
  - name: nginx                    # 必填:容器名称(同一个 Pod 内唯一)
    image: nginx:1.25-alpine       # 必填:镜像地址(建议带具体 tag)
    imagePullPolicy: IfNotPresent  # 可选:拉取策略
                                   # Always(每次都拉) / IfNotPresent(默认,本地有就不拉) / Never(只用本地)
    command:                       # 可选:覆盖镜像 Entrypoint
    - nginx
    - -g
    - daemon off;
    args: []                       # 可选:覆盖镜像 CMD(command 和 args 不能同时有内容时都用 args)
    workingDir: /usr/share/nginx/html   # 可选:容器工作目录
    ports:                         # 可选:仅声明,不真正暴露(Service 负责暴露)
    - name: http
      containerPort: 80
      protocol: TCP
    - name: https
      containerPort: 443
      protocol: TCP

    env:                           # 可选:环境变量(明文)
    - name: ENV
      value: "production"
    - name: NGINX_PORT
      value: "80"
    envFrom:                       # 可选:从 ConfigMap 或 Secret 批量导入环境变量
    - configMapRef:
        name: nginx-config
    - secretRef:
        name: nginx-secret

    resources:                     # 强烈推荐:资源请求与限制
      requests:                    # 调度时最低保证
        cpu: "100m"                # 0.1 核
        memory: "128Mi"
      limits:                      # 硬限制,超过会被 OOM 或 CPU 节流
        cpu: "500m"
        memory: "512Mi"

    volumeMounts:                  # 可选:挂载卷到容器内
    - name: web-root
      mountPath: /usr/share/nginx/html
      readOnly: false
    - name: config-volume
      mountPath: /etc/nginx/conf.d
    - name: secret-volume
      mountPath: /etc/ssl/certs
      readOnly: true

    livenessProbe:                 # 存活探针(不健康 → 重启容器)
      httpGet:
        path: /healthz
        port: 80
        scheme: HTTP
      initialDelaySeconds: 15
      periodSeconds: 10
      timeoutSeconds: 5
      successThreshold: 1
      failureThreshold: 3

    readinessProbe:                # 就绪探针(不就绪 → 从 Service 剔除流量)
      httpGet:
        path: /ready
        port: 80
      initialDelaySeconds: 5
      periodSeconds: 5
      timeoutSeconds: 3
      failureThreshold: 3

    startupProbe:                  # 启动探针(慢启动应用专用,避免被 liveness 误杀)
      httpGet:
        path: /startup
        port: 80
      initialDelaySeconds: 10
      periodSeconds: 10
      failureThreshold: 30     # 允许 5 分钟启动时间
      timeoutSeconds: 5

    lifecycle:                     # 生命周期钩子
      postStart:
        exec:
          command: ["/bin/sh", "-c", "echo Pod started >> /var/log/start.log"]
      preStop:
        exec:
          command: ["/bin/sh", "-c", "nginx -s quit; sleep 10"]

    securityContext:               # 容器级安全上下文
      privileged: false
      runAsUser: 1001              # 推荐非 root 用户运行
      runAsGroup: 1001
      fsGroup: 1001
      capabilities:
        drop:
        - ALL
        # add: ["NET_ADMIN"]       # 如需特殊权限再加

  initContainers:                  # 可选:Init 容器(先于业务容器运行,常用于初始化)
  - name: init-config
    image: busybox:1.36
    command: ['sh', '-c', 'wget -O /data/config.yaml http://config-server/config.yaml']
    volumeMounts:
    - name: web-root
      mountPath: /data

  volumes:                         # 可选:在 Pod 级别定义共享卷
  - name: web-root
    emptyDir: {}                   # 临时目录,Pod 删就没了
  - name: config-volume
    configMap:
      name: nginx-conf
      items:
      - key: nginx.conf
        path: nginx.conf
  - name: secret-volume
    secret:
      secretName: nginx-tls
      items:
      - key: tls.crt
        path: nginx.crt
      - key: tls.key
        path: nginx.key
  - name: persistent-data
    persistentVolumeClaim:
      claimName: nginx-pvc

  # 以下为较少用但偶尔需要的字段
  # affinity: ...                  # 亲和性与反亲和性调度
  # topologySpreadConstraints: ... # 拓扑分布约束(1.21+)
  # priorityClassName: high-priority
  # schedulerName: my-scheduler
  # shareProcessNamespace: true    # 容器间共享 PID namespace(如调试)

原文链接:https://www.rzzz.net/cloudnative/k8s/7-k8s-Manifests.html

更多推荐