Skip to content

YAML基础

概述

YAML(YAML Ain't Markup Language)是一种人类可读的数据序列化语言,Kubernetes使用YAML作为其资源定义的标准格式。掌握YAML语法是使用Kubernetes的基础技能。

核心概念

YAML的特点

  • 简洁易读:使用缩进表示层级关系
  • 结构清晰:支持列表、字典等数据结构
  • 可扩展:支持注释、多文档、引用等高级特性
  • 兼容性强:可转换为JSON格式

Kubernetes中的YAML

  • 所有K8S资源对象都使用YAML定义
  • 声明式配置:描述期望状态而非操作步骤
  • 版本控制友好:便于GitOps实践
  • 模板化支持:结合Helm、Kustomize等工具

YAML语法基础

基本语法规则

yaml
# 1. 大小写敏感
Name: nginx
name: nginx

# 2. 使用缩进表示层级关系(空格,不用Tab)
apiVersion: v1
kind: Pod
metadata:
  name: my-pod
  namespace: default

# 3. 缩进空格数不重要,但同一层级必须对齐
spec:
  containers:
    - name: nginx
      image: nginx:1.20
      ports:
        - containerPort: 80

# 4. 注释使用 # 符号
# 这是一个注释
key: value  # 行尾注释

数据类型

yaml
# 标量类型(Scalar)
string: "hello world"
integer: 42
float: 3.14
boolean: true
null_value: null
date: 2024-01-15
datetime: 2024-01-15T10:30:00Z

# 列表(List)- 使用短横线
fruits:
  - apple
  - banana
  - orange

# 行内列表格式
fruits: [apple, banana, orange]

# 字典(Dictionary)- 使用键值对
person:
  name: John
  age: 30
  city: Beijing

# 行内字典格式
person: {name: John, age: 30, city: Beijing}

# 嵌套结构
company:
  name: TechCorp
  employees:
    - name: Alice
      role: Developer
    - name: Bob
      role: Manager

多行字符串

yaml
# 保留换行符(使用 |)
script: |
  echo "Hello"
  echo "World"
  exit 0

# 折叠换行符(使用 >)
description: >
  This is a long
  description that
  will be folded into
  a single line.

# 保留换行并去除首尾空格(使用 |-)
clean_script: |-
  echo "Hello"
  echo "World"

引用与锚点

yaml
# 定义锚点
defaults: &defaults
  image: nginx:1.20
  port: 80

# 引用锚点
service1:
  <<: *defaults
  name: web1

service2:
  <<: *defaults
  name: web2
  port: 8080  # 覆盖默认值

# 合并多个锚点
base: &base
  image: nginx

config: &config
  replicas: 3

deployment:
  <<: [*base, *config]
  name: my-app

Kubernetes资源定义

资源清单结构

yaml
apiVersion: apps/v1          # API版本
kind: Deployment             # 资源类型
metadata:                    # 元数据
  name: nginx-deployment
  namespace: default
  labels:
    app: nginx
  annotations:
    description: "Nginx deployment"
spec:                        # 规格定义
  replicas: 3
  selector:
    matchLabels:
      app: nginx
  template:
    metadata:
      labels:
        app: nginx
    spec:
      containers:
      - name: nginx
        image: nginx:1.20
        ports:
        - containerPort: 80
status:                      # 状态(由系统维护)
  availableReplicas: 3

常见资源类型及API版本

yaml
# 核心资源(apiVersion: v1)
- Pod
- Service
- ConfigMap
- Secret
- PersistentVolume
- PersistentVolumeClaim
- Namespace
- Node

# apps组(apiVersion: apps/v1)
- Deployment
- StatefulSet
- DaemonSet
- ReplicaSet

# batch组(apiVersion: batch/v1)
- Job
- CronJob

# networking.k8s.io组(apiVersion: networking.k8s.io/v1)
- Ingress
- NetworkPolicy

# rbac.authorization.k8s.io组(apiVersion: rbac.authorization.k8s.io/v1)
- Role
- RoleBinding
- ClusterRole
- ClusterRoleBinding

必需字段

yaml
apiVersion: apps/v1  # 必需:API版本
kind: Deployment     # 必需:资源类型
metadata:            # 必需:元数据
  name: my-app       # 必需:资源名称
spec:                # 必需:规格定义
  # 根据资源类型不同而不同

模板化配置

使用环境变量

yaml
apiVersion: v1
kind: Pod
metadata:
  name: env-pod
spec:
  containers:
  - name: app
    image: nginx:1.20
    env:
    - name: ENVIRONMENT
      value: "production"
    - name: DB_HOST
      valueFrom:
        configMapKeyRef:
          name: app-config
          key: database_host
    - name: DB_PASSWORD
      valueFrom:
        secretKeyRef:
          name: app-secret
          key: password

使用ConfigMap

yaml
# configmap.yaml
apiVersion: v1
kind: ConfigMap
metadata:
  name: app-config
data:
  database_host: "mysql.default.svc.cluster.local"
  database_port: "3306"
  app.properties: |
    server.port=8080
    log.level=INFO
---
# 使用ConfigMap
apiVersion: v1
kind: Pod
metadata:
  name: configmap-pod
spec:
  containers:
  - name: app
    image: nginx:1.20
    envFrom:
    - configMapRef:
        name: app-config
    volumeMounts:
    - name: config-volume
      mountPath: /etc/config
  volumes:
  - name: config-volume
    configMap:
      name: app-config

使用Secret

yaml
# secret.yaml
apiVersion: v1
kind: Secret
metadata:
  name: app-secret
type: Opaque
data:
  username: YWRtaW4=        # base64编码
  password: MWYyZDFlMmU2N2Rm
stringData:                  # 明文形式(自动编码)
  api-key: "my-api-key-123"
---
# 使用Secret
apiVersion: v1
kind: Pod
metadata:
  name: secret-pod
spec:
  containers:
  - name: app
    image: nginx:1.20
    env:
    - name: DB_USERNAME
      valueFrom:
        secretKeyRef:
          name: app-secret
          key: username
    - name: DB_PASSWORD
      valueFrom:
        secretKeyRef:
          name: app-secret
          key: password

实用kubectl操作命令

创建和管理资源

bash
# 创建资源
kubectl apply -f deployment.yaml

# 创建多个资源
kubectl apply -f ./configs/

# 从URL创建
kubectl apply -f https://raw.githubusercontent.com/kubernetes/website/main/content/en/examples/application/nginx-deployment.yaml

# 查看资源
kubectl get pods
kubectl get deployments
kubectl get all

# 详细查看
kubectl describe pod nginx-pod
kubectl get pod nginx-pod -o yaml
kubectl get pod nginx-pod -o json

# 编辑资源
kubectl edit deployment nginx-deployment

# 删除资源
kubectl delete -f deployment.yaml
kubectl delete pod nginx-pod

YAML验证和调试

bash
# 验证YAML语法
kubectl apply -f deployment.yaml --dry-run=client

# 验证并查看生成的资源
kubectl apply -f deployment.yaml --dry-run=client -o yaml

# 查看资源差异
kubectl diff -f deployment.yaml

# 转换为YAML格式
kubectl get pod nginx-pod -o yaml > pod.yaml

# 从命令行生成YAML模板
kubectl create deployment nginx --image=nginx --dry-run=client -o yaml > deployment.yaml

# 导出当前资源为YAML
kubectl get deployment nginx -o yaml --export > nginx-deployment.yaml

高级操作

bash
# 使用标签选择器
kubectl get pods -l app=nginx

# 查看特定命名空间
kubectl get pods -n production

# 查看所有命名空间
kubectl get pods --all-namespaces

# 使用字段选择器
kubectl get pods --field-selector status.phase=Running

# 输出特定字段
kubectl get pods -o jsonpath='{.items[*].metadata.name}'
kubectl get pods -o custom-columns=NAME:.metadata.name,IMAGE:.spec.containers[0].image

实践示例

示例1:多容器Pod配置

yaml
apiVersion: v1
kind: Pod
metadata:
  name: multi-container-pod
  labels:
    app: webapp
spec:
  containers:
  - name: app
    image: nginx:1.20
    ports:
    - containerPort: 80
    volumeMounts:
    - name: shared-logs
      mountPath: /var/log/nginx
    resources:
      requests:
        memory: "128Mi"
        cpu: "100m"
      limits:
        memory: "256Mi"
        cpu: "200m"
  
  - name: log-collector
    image: busybox
    command: ["sh", "-c", "tail -f /var/log/nginx/access.log"]
    volumeMounts:
    - name: shared-logs
      mountPath: /var/log/nginx
  
  volumes:
  - name: shared-logs
    emptyDir: {}

应用场景:主容器运行应用,辅助容器收集日志或同步数据。

示例2:完整的应用栈配置

yaml
# 数据库配置
apiVersion: v1
kind: ConfigMap
metadata:
  name: mysql-config
data:
  MYSQL_DATABASE: "myapp"
  MYSQL_USER: "appuser"
---
apiVersion: v1
kind: Secret
metadata:
  name: mysql-secret
type: Opaque
stringData:
  MYSQL_ROOT_PASSWORD: "rootpassword123"
  MYSQL_PASSWORD: "userpassword123"
---
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: mysql-pvc
spec:
  accessModes:
    - ReadWriteOnce
  resources:
    requests:
      storage: 5Gi
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: mysql
spec:
  selector:
    matchLabels:
      app: mysql
  strategy:
    type: Recreate
  template:
    metadata:
      labels:
        app: mysql
    spec:
      containers:
      - name: mysql
        image: mysql:8.0
        envFrom:
        - configMapRef:
            name: mysql-config
        - secretRef:
            name: mysql-secret
        ports:
        - containerPort: 3306
        volumeMounts:
        - name: mysql-storage
          mountPath: /var/lib/mysql
      volumes:
      - name: mysql-storage
        persistentVolumeClaim:
          claimName: mysql-pvc
---
# 应用配置
apiVersion: v1
kind: ConfigMap
metadata:
  name: app-config
data:
  APP_ENV: "production"
  DB_HOST: "mysql-service"
  DB_PORT: "3306"
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: webapp
spec:
  replicas: 3
  selector:
    matchLabels:
      app: webapp
  template:
    metadata:
      labels:
        app: webapp
    spec:
      containers:
      - name: webapp
        image: myapp:latest
        envFrom:
        - configMapRef:
            name: app-config
        - secretRef:
            name: mysql-secret
        ports:
        - containerPort: 8080
        livenessProbe:
          httpGet:
            path: /health
            port: 8080
          initialDelaySeconds: 30
          periodSeconds: 10
        readinessProbe:
          httpGet:
            path: /ready
            port: 8080
          initialDelaySeconds: 5
          periodSeconds: 5
---
# 服务配置
apiVersion: v1
kind: Service
metadata:
  name: mysql-service
spec:
  selector:
    app: mysql
  ports:
  - port: 3306
    targetPort: 3306
---
apiVersion: v1
kind: Service
metadata:
  name: webapp-service
spec:
  selector:
    app: webapp
  ports:
  - port: 80
    targetPort: 8080
  type: LoadBalancer

应用场景:部署完整的三层应用架构(应用层、服务层、数据层)。

示例3:使用Kustomize进行配置管理

yaml
# kustomization.yaml
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization

# 基础资源
resources:
  - deployment.yaml
  - service.yaml
  - configmap.yaml

# 命名空间
namespace: production

# 通用标签
commonLabels:
  env: production
  team: platform

# 通用注解
commonAnnotations:
  contact: "platform-team@company.com"

# 配置补丁
patchesStrategicMerge:
  - deployment-patch.yaml

# 环境变量替换
configMapGenerator:
  - name: app-config
    behavior: merge
    literals:
      - ENVIRONMENT=production
      - LOG_LEVEL=INFO

# 镜像替换
images:
  - name: myapp
    newTag: v1.2.3
---
# deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: webapp
spec:
  replicas: 3
  selector:
    matchLabels:
      app: webapp
  template:
    metadata:
      labels:
        app: webapp
    spec:
      containers:
      - name: webapp
        image: myapp:latest
        ports:
        - containerPort: 8080
---
# deployment-patch.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: webapp
spec:
  replicas: 5
  template:
    spec:
      containers:
      - name: webapp
        resources:
          requests:
            memory: "512Mi"
            cpu: "500m"
          limits:
            memory: "1Gi"
            cpu: "1000m"

应用场景:多环境配置管理,避免重复YAML文件。

bash
# 应用Kustomize配置
kubectl apply -k ./overlays/production/

# 查看生成的YAML
kubectl kustomize ./overlays/production/

故障排查指南

常见YAML错误

1. 缩进错误

yaml
# ❌ 错误示例
spec:
containers:
  - name: nginx

# ✅ 正确示例
spec:
  containers:
    - name: nginx

排查方法

bash
# 使用yamllint验证
yamllint deployment.yaml

# 使用kubectl验证
kubectl apply -f deployment.yaml --dry-run=client

2. 字段名称错误

yaml
# ❌ 错误示例
apiVersion: apps/v1
kind: deployment  # 应该是Deployment(首字母大写)

# ✅ 正确示例
apiVersion: apps/v1
kind: Deployment

排查方法

bash
# 查看API资源类型
kubectl api-resources

# 查看资源字段说明
kubectl explain deployment.spec
kubectl explain pod.spec.containers

3. API版本错误

yaml
# ❌ 错误示例
apiVersion: extensions/v1beta1  # 已废弃
kind: Deployment

# ✅ 正确示例
apiVersion: apps/v1
kind: Deployment

排查方法

bash
# 查看支持的API版本
kubectl api-versions

# 查看资源支持的版本
kubectl explain deployment

4. 必需字段缺失

yaml
# ❌ 错误示例
apiVersion: v1
kind: Pod
metadata:
  name: my-pod
# 缺少spec字段

# ✅ 正确示例
apiVersion: v1
kind: Pod
metadata:
  name: my-pod
spec:
  containers:
  - name: nginx
    image: nginx:1.20

排查方法

bash
# 查看资源结构
kubectl explain pod --recursive

# 使用dry-run验证
kubectl apply -f pod.yaml --dry-run=client

5. 引号和特殊字符问题

yaml
# ❌ 错误示例
password: my@password#123  # 特殊字符未转义

# ✅ 正确示例
password: "my@password#123"

# 或使用单引号
password: 'my@password#123'

调试技巧

bash
# 1. 查看资源定义模板
kubectl create deployment nginx --image=nginx --dry-run=client -o yaml

# 2. 查看字段说明
kubectl explain deployment.spec.template.spec.containers

# 3. 验证YAML语法
cat deployment.yaml | python -m yaml

# 4. 比较资源差异
kubectl diff -f deployment.yaml

# 5. 查看事件日志
kubectl get events --sort-by='.lastTimestamp'

# 6. 查看资源状态
kubectl get pods -o wide
kubectl describe pod <pod-name>

# 7. 查看容器日志
kubectl logs <pod-name> -c <container-name>

# 8. 进入容器调试
kubectl exec -it <pod-name> -- /bin/sh

常见错误信息

bash
# 错误1:资源已存在
Error from server (AlreadyExists): error when creating "deployment.yaml": deployments.apps "nginx" already exists

# 解决方案:
kubectl apply -f deployment.yaml  # 使用apply而不是create

# 错误2:字段类型错误
Error from server (BadRequest): error when creating "deployment.yaml": Deployment in version "v1" cannot be handled as a Deployment: v1.Deployment: Spec: v1.DeploymentSpec: Replicas: readUint32: unexpected character: 错误

# 解决方案:检查字段类型,replicas应该是整数
replicas: 3  # 正确
replicas: "3"  # 错误

# 错误3:验证失败
Error from server (Forbidden): error when creating "deployment.yaml": deployments.apps is forbidden: user cannot create resource "deployments" in API group "apps" in the namespace "default"

# 解决方案:检查RBAC权限
kubectl auth can-i create deployments

最佳实践建议

1. YAML文件组织

bash
# 推荐的目录结构
project/
├── base/                    # 基础配置
   ├── deployment.yaml
   ├── service.yaml
   └── kustomization.yaml
├── overlays/                # 环境覆盖
   ├── dev/
   ├── kustomization.yaml
   └── patches/
   ├── staging/
   └── production/
└── manifests/               # 单独的资源文件
    ├── namespace.yaml
    ├── configmap.yaml
    └── secret.yaml

2. 命名规范

yaml
# 资源命名规范
metadata:
  name: <app-name>-<resource-type>
  # 例如:nginx-deployment, mysql-service, app-configmap

# 标签命名规范
labels:
  app.kubernetes.io/name: nginx
  app.kubernetes.io/instance: nginx-prod
  app.kubernetes.io/version: "1.20"
  app.kubernetes.io/component: web-server
  app.kubernetes.io/part-of: webapp
  app.kubernetes.io/managed-by: kubectl

3. 注释和文档

yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: webapp
  annotations:
    description: "Web application deployment"
    owner: "platform-team"
    documentation: "https://wiki.company.com/webapp"
spec:
  replicas: 3  # 生产环境建议3个副本以上
  selector:
    matchLabels:
      app: webapp
  template:
    spec:
      containers:
      - name: webapp
        image: webapp:v1.2.3
        resources:
          requests:
            memory: "256Mi"  # 根据实际负载调整
            cpu: "250m"
          limits:
            memory: "512Mi"
            cpu: "500m"

4. 版本控制

yaml
# 使用Git管理YAML文件
# .gitignore
*.swp
*.tmp
secrets/          # 不要提交Secret到Git
*.key
*.pem

# 使用Sealed Secrets或External Secrets管理敏感信息

5. 验证和测试

bash
# CI/CD流程中的验证步骤
# 1. 语法验证
yamllint manifests/

# 2. Schema验证
kubeval manifests/

# 3. 安全扫描
kubesec scan deployment.yaml

# 4. Dry-run测试
kubectl apply -f manifests/ --dry-run=client

# 5. 差异检查
kubectl diff -f manifests/

6. 使用模板工具

yaml
# Helm模板示例
# templates/deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: {{ include "myapp.fullname" . }}
  labels:
    {{- include "myapp.labels" . | nindent 4 }}
spec:
  replicas: {{ .Values.replicaCount }}
  selector:
    matchLabels:
      {{- include "myapp.selectorLabels" . | nindent 6 }}
  template:
    spec:
      containers:
      - name: {{ .Chart.Name }}
        image: "{{ .Values.image.repository }}:{{ .Values.image.tag }}"
        imagePullPolicy: {{ .Values.image.pullPolicy }}
        ports:
        - containerPort: {{ .Values.service.port }}

7. 安全配置

yaml
apiVersion: v1
kind: Pod
metadata:
  name: secure-pod
spec:
  securityContext:
    runAsNonRoot: true
    runAsUser: 1000
    fsGroup: 2000
  containers:
  - name: app
    image: nginx:1.20
    securityContext:
      allowPrivilegeEscalation: false
      readOnlyRootFilesystem: true
      capabilities:
        drop:
        - ALL
    volumeMounts:
    - name: tmp
      mountPath: /tmp
  volumes:
  - name: tmp
    emptyDir: {}

总结

核心要点

  1. YAML语法基础

    • 使用空格缩进,不用Tab
    • 支持列表、字典、多行字符串等数据结构
    • 使用锚点和引用减少重复
  2. K8S资源定义

    • 必需字段:apiVersion、kind、metadata、spec
    • 使用kubectl explain查看资源结构
    • 使用--dry-run验证配置
  3. 配置管理

    • 使用ConfigMap管理配置
    • 使用Secret管理敏感信息
    • 使用Kustomize或Helm进行模板化
  4. 最佳实践

    • 版本控制所有YAML文件
    • 使用命名规范和标签规范
    • 在CI/CD中集成验证步骤

常用命令速查

bash
# 创建资源
kubectl apply -f <file.yaml>

# 验证YAML
kubectl apply -f <file.yaml> --dry-run=client

# 查看资源
kubectl get <resource> -o yaml

# 编辑资源
kubectl edit <resource> <name>

# 删除资源
kubectl delete -f <file.yaml>

# 查看字段说明
kubectl explain <resource>.<field>

# 生成YAML模板
kubectl create <resource> <name> --dry-run=client -o yaml

下一步学习

参考资源