Skip to content

05_k8s_examples

yaml
# ============================================================
#           Kubernetes 实战配置示例大全
# ============================================================
# 本文件包含生产级别的 K8s 配置示例
# 所有配置都有详细的中文注释
#
# 目录:
# 1. 完整的 Web 应用部署示例
# 2. 数据库有状态应用部署
# 3. 微服务架构示例
# 4. 定时任务和批处理
# 5. 自动扩缩容配置
# 6. 网络策略和安全
# 7. 监控和日志收集
# ============================================================


# ============================================================
#     第一部分:完整的 Web 应用部署示例
# ============================================================
# 这是一个完整的前后端分离应用部署示例
# 包含:Nginx 前端 + Node.js 后端 + PostgreSQL 数据库


# ------------------------------------------------------------
#                    1.1 命名空间
# ------------------------------------------------------------
# 为应用创建独立的命名空间,实现资源隔离
apiVersion: v1
kind: Namespace
metadata:
  name: myapp
  labels:
    # 标签用于组织和选择资源
    name: myapp
    environment: production
    team: backend

---
# ------------------------------------------------------------
#                    1.2 ConfigMap - 应用配置
# ------------------------------------------------------------
# ConfigMap 存储非敏感的配置数据
apiVersion: v1
kind: ConfigMap
metadata:
  name: app-config
  namespace: myapp
  labels:
    app: myapp
data:
  # 简单的键值对配置
  APP_ENV: "production"
  LOG_LEVEL: "info"
  API_VERSION: "v1"

  # 完整的配置文件(多行字符串)
  # 使用 | 表示保留换行符的多行字符串
  nginx.conf: |
    # Nginx 配置文件
    server {
        listen 80;
        server_name localhost;

        # 静态文件
        location / {
            root /usr/share/nginx/html;
            index index.html;
            # SPA 应用的 history 模式
            try_files $uri $uri/ /index.html;
        }

        # API 代理
        location /api/ {
            # 转发到后端服务
            # 使用 K8s 服务名称作为主机名
            proxy_pass http://api-service:3000/;
            proxy_http_version 1.1;
            proxy_set_header Upgrade $http_upgrade;
            proxy_set_header Connection 'upgrade';
            proxy_set_header Host $host;
            proxy_set_header X-Real-IP $remote_addr;
            proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
            proxy_cache_bypass $http_upgrade;
        }

        # 健康检查端点
        location /health {
            return 200 'OK';
            add_header Content-Type text/plain;
        }
    }

  # 数据库初始化脚本
  init.sql: |
    -- 创建数据库表
    CREATE TABLE IF NOT EXISTS users (
        id SERIAL PRIMARY KEY,
        username VARCHAR(50) UNIQUE NOT NULL,
        email VARCHAR(100) UNIQUE NOT NULL,
        created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
    );

    CREATE TABLE IF NOT EXISTS posts (
        id SERIAL PRIMARY KEY,
        user_id INTEGER REFERENCES users(id),
        title VARCHAR(200) NOT NULL,
        content TEXT,
        created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
    );

    -- 创建索引
    CREATE INDEX idx_posts_user_id ON posts(user_id);

---
# ------------------------------------------------------------
#                    1.3 Secret - 敏感信息
# ------------------------------------------------------------
# Secret 存储敏感数据(密码、密钥等)
# 注意:生产环境建议使用外部密钥管理系统
apiVersion: v1
kind: Secret
metadata:
  name: app-secrets
  namespace: myapp
  labels:
    app: myapp
# Opaque 是最常见的 Secret 类型
type: Opaque
# data 中的值必须是 base64 编码
# 生成方式:echo -n 'your-value' | base64
data:
  # 数据库密码:mypassword123
  DB_PASSWORD: bXlwYXNzd29yZDEyMw==
  # JWT 密钥:my-super-secret-jwt-key
  JWT_SECRET: bXktc3VwZXItc2VjcmV0LWp3dC1rZXk=
  # API 密钥:api-key-12345
  API_KEY: YXBpLWtleS0xMjM0NQ==

# 也可以使用 stringData(明文,K8s 会自动编码)
# stringData:
#   DB_PASSWORD: mypassword123

---
# ------------------------------------------------------------
#              1.4 PersistentVolumeClaim - 持久存储
# ------------------------------------------------------------
# 为数据库请求持久存储
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: postgres-pvc
  namespace: myapp
  labels:
    app: postgres
spec:
  # 访问模式
  # ReadWriteOnce: 单节点读写
  # ReadOnlyMany: 多节点只读
  # ReadWriteMany: 多节点读写(需要特定存储类支持)
  accessModes:
    - ReadWriteOnce

  # 存储类名称
  # 不同云平台有不同的存储类
  # AWS: gp2, gp3, io1
  # GCP: standard, ssd
  # Azure: managed-premium, managed-standard
  storageClassName: standard

  resources:
    requests:
      # 请求 10GB 存储空间
      storage: 10Gi

---
# ------------------------------------------------------------
#              1.5 PostgreSQL 数据库 Deployment
# ------------------------------------------------------------
apiVersion: apps/v1
kind: Deployment
metadata:
  name: postgres
  namespace: myapp
  labels:
    app: postgres
    tier: database
spec:
  # 数据库通常只需要 1 个副本
  # 如果需要高可用,考虑使用 StatefulSet 或数据库 Operator
  replicas: 1

  selector:
    matchLabels:
      app: postgres

  # 更新策略
  strategy:
    # 数据库使用 Recreate 策略
    # 确保同时只有一个实例访问存储
    type: Recreate

  template:
    metadata:
      labels:
        app: postgres
        tier: database
    spec:
      containers:
        - name: postgres
          image: postgres:15-alpine

          ports:
            - containerPort: 5432
              name: postgres

          # 环境变量配置
          env:
            # 从 Secret 获取密码
            - name: POSTGRES_PASSWORD
              valueFrom:
                secretKeyRef:
                  name: app-secrets
                  key: DB_PASSWORD

            # 直接设置的环境变量
            - name: POSTGRES_USER
              value: "appuser"
            - name: POSTGRES_DB
              value: "appdb"

            # 指定数据目录
            - name: PGDATA
              value: /var/lib/postgresql/data/pgdata

          # 资源限制
          resources:
            requests:
              # 请求的最小资源
              memory: "256Mi"
              cpu: "250m"
            limits:
              # 最大可用资源
              memory: "512Mi"
              cpu: "500m"

          # 存储卷挂载
          volumeMounts:
            # 数据目录
            - name: postgres-data
              mountPath: /var/lib/postgresql/data

            # 初始化脚本
            - name: init-script
              mountPath: /docker-entrypoint-initdb.d
              readOnly: true

          # 存活探针
          # 检测容器是否还在运行
          livenessProbe:
            exec:
              command:
                - pg_isready
                - -U
                - appuser
                - -d
                - appdb
            initialDelaySeconds: 30
            periodSeconds: 10
            timeoutSeconds: 5
            failureThreshold: 3

          # 就绪探针
          # 检测容器是否准备好接收流量
          readinessProbe:
            exec:
              command:
                - pg_isready
                - -U
                - appuser
                - -d
                - appdb
            initialDelaySeconds: 5
            periodSeconds: 5
            timeoutSeconds: 3
            failureThreshold: 3

      # 卷定义
      volumes:
        # 持久化数据卷
        - name: postgres-data
          persistentVolumeClaim:
            claimName: postgres-pvc

        # 配置文件卷
        - name: init-script
          configMap:
            name: app-config
            items:
              - key: init.sql
                path: init.sql

---
# ------------------------------------------------------------
#              1.6 PostgreSQL Service
# ------------------------------------------------------------
apiVersion: v1
kind: Service
metadata:
  name: postgres-service
  namespace: myapp
  labels:
    app: postgres
spec:
  # ClusterIP: 只在集群内部访问
  type: ClusterIP

  selector:
    app: postgres

  ports:
    - port: 5432
      targetPort: 5432
      name: postgres

---
# ------------------------------------------------------------
#              1.7 后端 API Deployment
# ------------------------------------------------------------
apiVersion: apps/v1
kind: Deployment
metadata:
  name: api
  namespace: myapp
  labels:
    app: api
    tier: backend
spec:
  # 后端服务 3 个副本,实现负载均衡
  replicas: 3

  selector:
    matchLabels:
      app: api

  # 滚动更新策略
  strategy:
    type: RollingUpdate
    rollingUpdate:
      # 更新时最多额外创建的 Pod 数量
      maxSurge: 1
      # 更新时最多不可用的 Pod 数量
      maxUnavailable: 0

  template:
    metadata:
      labels:
        app: api
        tier: backend
      # 添加 annotation 触发滚动更新
      annotations:
        # 当配置更改时,修改这个值触发重新部署
        rollout-version: "1"
    spec:
      # 初始化容器
      # 在主容器启动前执行,常用于等待依赖服务
      initContainers:
        - name: wait-for-postgres
          image: busybox:1.36
          command:
            - sh
            - -c
            # 等待 PostgreSQL 服务可用
            - |
              until nc -z postgres-service 5432; do
                echo "等待 PostgreSQL 启动..."
                sleep 2
              done
              echo "PostgreSQL 已就绪!"

      # 主容器
      containers:
        - name: api
          image: node:18-alpine

          # 工作目录
          workingDir: /app

          # 启动命令
          command: ["npm", "run", "start:prod"]

          ports:
            - containerPort: 3000
              name: http

          # 环境变量
          env:
            # 从 ConfigMap 获取
            - name: NODE_ENV
              valueFrom:
                configMapKeyRef:
                  name: app-config
                  key: APP_ENV

            - name: LOG_LEVEL
              valueFrom:
                configMapKeyRef:
                  name: app-config
                  key: LOG_LEVEL

            # 数据库连接信息
            - name: DB_HOST
              value: "postgres-service"
            - name: DB_PORT
              value: "5432"
            - name: DB_USER
              value: "appuser"
            - name: DB_NAME
              value: "appdb"

            # 从 Secret 获取敏感信息
            - name: DB_PASSWORD
              valueFrom:
                secretKeyRef:
                  name: app-secrets
                  key: DB_PASSWORD

            - name: JWT_SECRET
              valueFrom:
                secretKeyRef:
                  name: app-secrets
                  key: JWT_SECRET

          # 资源配置
          resources:
            requests:
              memory: "128Mi"
              cpu: "100m"
            limits:
              memory: "256Mi"
              cpu: "500m"

          # 挂载应用代码
          volumeMounts:
            - name: app-code
              mountPath: /app

          # 健康检查
          livenessProbe:
            httpGet:
              path: /health
              port: 3000
            initialDelaySeconds: 30
            periodSeconds: 10
            timeoutSeconds: 5
            failureThreshold: 3

          readinessProbe:
            httpGet:
              path: /ready
              port: 3000
            initialDelaySeconds: 5
            periodSeconds: 5
            timeoutSeconds: 3
            failureThreshold: 3

          # 启动探针(适用于启动慢的应用)
          startupProbe:
            httpGet:
              path: /health
              port: 3000
            # 最多等待 300 秒(10 * 30)
            failureThreshold: 30
            periodSeconds: 10

      # 反亲和性:尽量将 Pod 分散到不同节点
      affinity:
        podAntiAffinity:
          preferredDuringSchedulingIgnoredDuringExecution:
            - weight: 100
              podAffinityTerm:
                labelSelector:
                  matchLabels:
                    app: api
                topologyKey: kubernetes.io/hostname

      # 卷定义
      volumes:
        - name: app-code
          emptyDir: {}

---
# ------------------------------------------------------------
#              1.8 后端 API Service
# ------------------------------------------------------------
apiVersion: v1
kind: Service
metadata:
  name: api-service
  namespace: myapp
  labels:
    app: api
spec:
  type: ClusterIP

  selector:
    app: api

  ports:
    - port: 3000
      targetPort: 3000
      name: http

---
# ------------------------------------------------------------
#              1.9 前端 Nginx Deployment
# ------------------------------------------------------------
apiVersion: apps/v1
kind: Deployment
metadata:
  name: frontend
  namespace: myapp
  labels:
    app: frontend
    tier: frontend
spec:
  replicas: 2

  selector:
    matchLabels:
      app: frontend

  template:
    metadata:
      labels:
        app: frontend
        tier: frontend
    spec:
      containers:
        - name: nginx
          image: nginx:alpine

          ports:
            - containerPort: 80
              name: http

          # 挂载 Nginx 配置
          volumeMounts:
            - name: nginx-config
              mountPath: /etc/nginx/conf.d/default.conf
              subPath: nginx.conf
              readOnly: true

            # 挂载静态文件(实际项目中通常使用持久卷或 ConfigMap)
            - name: static-files
              mountPath: /usr/share/nginx/html

          resources:
            requests:
              memory: "64Mi"
              cpu: "50m"
            limits:
              memory: "128Mi"
              cpu: "100m"

          livenessProbe:
            httpGet:
              path: /health
              port: 80
            initialDelaySeconds: 10
            periodSeconds: 10

          readinessProbe:
            httpGet:
              path: /health
              port: 80
            initialDelaySeconds: 5
            periodSeconds: 5

      volumes:
        - name: nginx-config
          configMap:
            name: app-config

        - name: static-files
          emptyDir: {}

---
# ------------------------------------------------------------
#              1.10 前端 Service
# ------------------------------------------------------------
apiVersion: v1
kind: Service
metadata:
  name: frontend-service
  namespace: myapp
  labels:
    app: frontend
spec:
  type: ClusterIP

  selector:
    app: frontend

  ports:
    - port: 80
      targetPort: 80
      name: http

---
# ------------------------------------------------------------
#              1.11 Ingress - 外部访问入口
# ------------------------------------------------------------
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: app-ingress
  namespace: myapp
  labels:
    app: myapp
  annotations:
    # Nginx Ingress Controller 注解
    nginx.ingress.kubernetes.io/proxy-body-size: "10m"
    nginx.ingress.kubernetes.io/proxy-read-timeout: "60"
    nginx.ingress.kubernetes.io/proxy-send-timeout: "60"

    # SSL 重定向
    nginx.ingress.kubernetes.io/ssl-redirect: "true"

    # 启用 CORS
    nginx.ingress.kubernetes.io/enable-cors: "true"
    nginx.ingress.kubernetes.io/cors-allow-origin: "*"

    # 速率限制
    nginx.ingress.kubernetes.io/limit-rps: "100"

    # 自动申请 Let's Encrypt 证书(需要 cert-manager)
    # cert-manager.io/cluster-issuer: "letsencrypt-prod"
spec:
  # 指定 Ingress 类
  ingressClassName: nginx

  # TLS 配置
  tls:
    - hosts:
        - myapp.example.com
        - api.myapp.example.com
      # 引用包含 TLS 证书的 Secret
      secretName: myapp-tls-secret

  rules:
    # 主域名 - 前端
    - host: myapp.example.com
      http:
        paths:
          - path: /
            pathType: Prefix
            backend:
              service:
                name: frontend-service
                port:
                  number: 80

          # API 路径转发到后端
          - path: /api
            pathType: Prefix
            backend:
              service:
                name: api-service
                port:
                  number: 3000

    # API 子域名
    - host: api.myapp.example.com
      http:
        paths:
          - path: /
            pathType: Prefix
            backend:
              service:
                name: api-service
                port:
                  number: 3000


---
# ============================================================
#     第二部分:StatefulSet - 有状态应用部署
# ============================================================
# StatefulSet 用于部署有状态应用,如数据库集群
# 特点:
# - 稳定的网络标识(Pod 名称固定)
# - 稳定的存储(每个 Pod 有自己的 PVC)
# - 有序部署和删除


# ------------------------------------------------------------
#              2.1 Headless Service
# ------------------------------------------------------------
# StatefulSet 需要 Headless Service 来实现稳定的网络标识
apiVersion: v1
kind: Service
metadata:
  name: redis-headless
  namespace: myapp
  labels:
    app: redis
spec:
  # ClusterIP 设为 None,创建 Headless Service
  clusterIP: None

  selector:
    app: redis

  ports:
    - port: 6379
      name: redis

---
# ------------------------------------------------------------
#              2.2 Redis Cluster StatefulSet
# ------------------------------------------------------------
apiVersion: apps/v1
kind: StatefulSet
metadata:
  name: redis
  namespace: myapp
  labels:
    app: redis
spec:
  # 关联的 Headless Service
  serviceName: redis-headless

  # 3 个副本组成集群
  replicas: 3

  selector:
    matchLabels:
      app: redis

  # Pod 管理策略
  # OrderedReady: 按顺序创建和删除(默认)
  # Parallel: 并行创建和删除
  podManagementPolicy: OrderedReady

  # 更新策略
  updateStrategy:
    type: RollingUpdate
    rollingUpdate:
      # 一次更新一个 Pod
      partition: 0

  template:
    metadata:
      labels:
        app: redis
    spec:
      # 终止宽限期
      terminationGracePeriodSeconds: 30

      containers:
        - name: redis
          image: redis:7-alpine

          ports:
            - containerPort: 6379
              name: redis

          # 启动命令配置 Redis 集群
          command:
            - redis-server
          args:
            - --appendonly
            - "yes"
            - --appendfsync
            - everysec
            # 集群模式配置
            # - --cluster-enabled
            # - "yes"

          resources:
            requests:
              memory: "128Mi"
              cpu: "100m"
            limits:
              memory: "256Mi"
              cpu: "200m"

          volumeMounts:
            - name: redis-data
              mountPath: /data

          livenessProbe:
            exec:
              command:
                - redis-cli
                - ping
            initialDelaySeconds: 30
            periodSeconds: 10

          readinessProbe:
            exec:
              command:
                - redis-cli
                - ping
            initialDelaySeconds: 5
            periodSeconds: 5

  # 卷声明模板
  # StatefulSet 会为每个 Pod 创建独立的 PVC
  volumeClaimTemplates:
    - metadata:
        name: redis-data
        labels:
          app: redis
      spec:
        accessModes:
          - ReadWriteOnce
        storageClassName: standard
        resources:
          requests:
            storage: 5Gi


---
# ============================================================
#     第三部分:DaemonSet - 每个节点运行一个 Pod
# ============================================================
# DaemonSet 确保每个(或指定的)节点运行一个 Pod
# 常用于:日志收集、监控代理、网络插件


# ------------------------------------------------------------
#              3.1 日志收集 DaemonSet
# ------------------------------------------------------------
apiVersion: apps/v1
kind: DaemonSet
metadata:
  name: fluentd
  namespace: kube-system
  labels:
    app: fluentd
    component: logging
spec:
  selector:
    matchLabels:
      app: fluentd

  # 更新策略
  updateStrategy:
    type: RollingUpdate
    rollingUpdate:
      # 最大不可用节点数
      maxUnavailable: 1

  template:
    metadata:
      labels:
        app: fluentd
        component: logging
    spec:
      # 容忍 master 节点的污点
      tolerations:
        - key: node-role.kubernetes.io/master
          effect: NoSchedule
        - key: node-role.kubernetes.io/control-plane
          effect: NoSchedule

      # 使用主机网络
      hostNetwork: true

      # 使用主机 PID 命名空间
      hostPID: true

      containers:
        - name: fluentd
          image: fluent/fluentd-kubernetes-daemonset:v1.16-debian-elasticsearch8

          env:
            # Elasticsearch 配置
            - name: FLUENT_ELASTICSEARCH_HOST
              value: "elasticsearch.logging.svc.cluster.local"
            - name: FLUENT_ELASTICSEARCH_PORT
              value: "9200"
            - name: FLUENT_ELASTICSEARCH_SCHEME
              value: "http"

          resources:
            requests:
              memory: "200Mi"
              cpu: "100m"
            limits:
              memory: "500Mi"
              cpu: "500m"

          volumeMounts:
            # 挂载容器日志目录
            - name: varlog
              mountPath: /var/log
              readOnly: true

            # 挂载 Docker 容器日志
            - name: containers
              mountPath: /var/lib/docker/containers
              readOnly: true

            # Fluentd 配置
            - name: config
              mountPath: /fluentd/etc

      volumes:
        - name: varlog
          hostPath:
            path: /var/log

        - name: containers
          hostPath:
            path: /var/lib/docker/containers

        - name: config
          configMap:
            name: fluentd-config


---
# ============================================================
#     第四部分:Job 和 CronJob - 任务调度
# ============================================================


# ------------------------------------------------------------
#              4.1 一次性 Job
# ------------------------------------------------------------
# Job 用于运行一次性任务
apiVersion: batch/v1
kind: Job
metadata:
  name: database-migration
  namespace: myapp
  labels:
    app: migration
spec:
  # 任务完成后保留多少秒(用于查看日志)
  ttlSecondsAfterFinished: 3600

  # 并行度
  parallelism: 1

  # 完成数(需要成功完成的 Pod 数量)
  completions: 1

  # 重试次数
  backoffLimit: 3

  # 活动截止时间(秒)
  activeDeadlineSeconds: 600

  template:
    metadata:
      labels:
        app: migration
    spec:
      # Job 的 Pod 不重启
      restartPolicy: Never

      # 等待数据库就绪
      initContainers:
        - name: wait-for-db
          image: busybox:1.36
          command:
            - sh
            - -c
            - until nc -z postgres-service 5432; do sleep 2; done

      containers:
        - name: migration
          image: myapp/migration:latest

          command: ["npm", "run", "migrate"]

          env:
            - name: DB_HOST
              value: "postgres-service"
            - name: DB_PORT
              value: "5432"
            - name: DB_PASSWORD
              valueFrom:
                secretKeyRef:
                  name: app-secrets
                  key: DB_PASSWORD

          resources:
            requests:
              memory: "128Mi"
              cpu: "100m"
            limits:
              memory: "256Mi"
              cpu: "200m"

---
# ------------------------------------------------------------
#              4.2 定时任务 CronJob
# ------------------------------------------------------------
# CronJob 用于周期性执行任务
apiVersion: batch/v1
kind: CronJob
metadata:
  name: database-backup
  namespace: myapp
  labels:
    app: backup
spec:
  # Cron 表达式
  # 格式:分 时 日 月 周
  # 每天凌晨 2 点执行
  schedule: "0 2 * * *"

  # 时区(K8s 1.24+)
  # timeZone: "Asia/Shanghai"

  # 并发策略
  # Allow: 允许并发
  # Forbid: 禁止并发
  # Replace: 替换正在运行的
  concurrencyPolicy: Forbid

  # 如果错过调度,在多少秒内仍然执行
  startingDeadlineSeconds: 3600

  # 保留的成功历史数量
  successfulJobsHistoryLimit: 3

  # 保留的失败历史数量
  failedJobsHistoryLimit: 3

  # 是否暂停调度
  suspend: false

  jobTemplate:
    spec:
      template:
        metadata:
          labels:
            app: backup
        spec:
          restartPolicy: OnFailure

          containers:
            - name: backup
              image: postgres:15-alpine

              command:
                - /bin/sh
                - -c
                - |
                  # 生成备份文件名
                  BACKUP_FILE="/backup/db_$(date +%Y%m%d_%H%M%S).sql"

                  # 执行备份
                  pg_dump -h postgres-service -U appuser -d appdb > $BACKUP_FILE

                  # 压缩备份
                  gzip $BACKUP_FILE

                  # 删除 7 天前的备份
                  find /backup -name "*.sql.gz" -mtime +7 -delete

                  echo "备份完成: ${BACKUP_FILE}.gz"

              env:
                - name: PGPASSWORD
                  valueFrom:
                    secretKeyRef:
                      name: app-secrets
                      key: DB_PASSWORD

              volumeMounts:
                - name: backup-storage
                  mountPath: /backup

              resources:
                requests:
                  memory: "128Mi"
                  cpu: "100m"
                limits:
                  memory: "256Mi"
                  cpu: "200m"

          volumes:
            - name: backup-storage
              persistentVolumeClaim:
                claimName: backup-pvc


---
# ============================================================
#     第五部分:HorizontalPodAutoscaler - 自动扩缩容
# ============================================================


# ------------------------------------------------------------
#              5.1 基于 CPU 的自动扩缩容
# ------------------------------------------------------------
apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
  name: api-hpa
  namespace: myapp
  labels:
    app: api
spec:
  # 目标 Deployment
  scaleTargetRef:
    apiVersion: apps/v1
    kind: Deployment
    name: api

  # 副本数范围
  minReplicas: 2
  maxReplicas: 10

  # 扩缩容指标
  metrics:
    # CPU 使用率
    - type: Resource
      resource:
        name: cpu
        target:
          type: Utilization
          # CPU 使用率超过 70% 时扩容
          averageUtilization: 70

    # 内存使用率
    - type: Resource
      resource:
        name: memory
        target:
          type: Utilization
          # 内存使用率超过 80% 时扩容
          averageUtilization: 80

    # 自定义指标(需要 Prometheus Adapter)
    # - type: Pods
    #   pods:
    #     metric:
    #       name: http_requests_per_second
    #     target:
    #       type: AverageValue
    #       averageValue: "1000"

  # 扩缩容行为(K8s 1.23+)
  behavior:
    # 扩容行为
    scaleUp:
      # 稳定窗口(秒)
      stabilizationWindowSeconds: 0
      policies:
        # 每 60 秒最多增加 4 个 Pod
        - type: Pods
          value: 4
          periodSeconds: 60
        # 每 60 秒最多增加 100%
        - type: Percent
          value: 100
          periodSeconds: 60
      # 使用最大的扩容值
      selectPolicy: Max

    # 缩容行为
    scaleDown:
      # 稳定窗口,防止频繁缩容
      stabilizationWindowSeconds: 300
      policies:
        # 每 60 秒最多减少 1 个 Pod
        - type: Pods
          value: 1
          periodSeconds: 60
      selectPolicy: Min


---
# ============================================================
#     第六部分:NetworkPolicy - 网络策略
# ============================================================
# NetworkPolicy 用于控制 Pod 之间的网络流量
# 需要支持 NetworkPolicy 的 CNI 插件(如 Calico、Cilium)


# ------------------------------------------------------------
#              6.1 默认拒绝所有入站流量
# ------------------------------------------------------------
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: default-deny-ingress
  namespace: myapp
spec:
  # 选择所有 Pod
  podSelector: {}

  # 策略类型
  policyTypes:
    - Ingress

---
# ------------------------------------------------------------
#              6.2 允许特定流量
# ------------------------------------------------------------
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: api-network-policy
  namespace: myapp
spec:
  # 应用到 API Pod
  podSelector:
    matchLabels:
      app: api

  policyTypes:
    - Ingress
    - Egress

  # 入站规则
  ingress:
    # 允许来自前端的流量
    - from:
        - podSelector:
            matchLabels:
              app: frontend
      ports:
        - protocol: TCP
          port: 3000

    # 允许来自 Ingress Controller 的流量
    - from:
        - namespaceSelector:
            matchLabels:
              name: ingress-nginx
      ports:
        - protocol: TCP
          port: 3000

  # 出站规则
  egress:
    # 允许访问数据库
    - to:
        - podSelector:
            matchLabels:
              app: postgres
      ports:
        - protocol: TCP
          port: 5432

    # 允许访问 Redis
    - to:
        - podSelector:
            matchLabels:
              app: redis
      ports:
        - protocol: TCP
          port: 6379

    # 允许 DNS 查询
    - to:
        - namespaceSelector: {}
          podSelector:
            matchLabels:
              k8s-app: kube-dns
      ports:
        - protocol: UDP
          port: 53

---
# ------------------------------------------------------------
#              6.3 数据库网络策略
# ------------------------------------------------------------
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: postgres-network-policy
  namespace: myapp
spec:
  podSelector:
    matchLabels:
      app: postgres

  policyTypes:
    - Ingress
    - Egress

  ingress:
    # 只允许 API Pod 访问
    - from:
        - podSelector:
            matchLabels:
              app: api
      ports:
        - protocol: TCP
          port: 5432

  # 数据库通常不需要出站流量
  egress: []


---
# ============================================================
#     第七部分:PodDisruptionBudget - Pod 中断预算
# ============================================================
# PDB 确保在自愿中断(如升级、维护)期间
# 保持最少数量的 Pod 可用


apiVersion: policy/v1
kind: PodDisruptionBudget
metadata:
  name: api-pdb
  namespace: myapp
spec:
  selector:
    matchLabels:
      app: api

  # 最少可用数量(二选一)
  minAvailable: 2

  # 最多不可用数量
  # maxUnavailable: 1


---
# ============================================================
#     第八部分:ResourceQuota 和 LimitRange
# ============================================================
# 资源配额和限制范围,用于多租户集群


# ------------------------------------------------------------
#              8.1 ResourceQuota - 命名空间资源配额
# ------------------------------------------------------------
apiVersion: v1
kind: ResourceQuota
metadata:
  name: myapp-quota
  namespace: myapp
spec:
  hard:
    # CPU 和内存限制
    requests.cpu: "10"
    requests.memory: "20Gi"
    limits.cpu: "20"
    limits.memory: "40Gi"

    # Pod 数量限制
    pods: "50"

    # 服务数量限制
    services: "20"
    services.loadbalancers: "2"
    services.nodeports: "5"

    # 存储限制
    persistentvolumeclaims: "10"
    requests.storage: "100Gi"

    # ConfigMap 和 Secret 限制
    configmaps: "20"
    secrets: "20"

---
# ------------------------------------------------------------
#              8.2 LimitRange - 默认资源限制
# ------------------------------------------------------------
apiVersion: v1
kind: LimitRange
metadata:
  name: myapp-limits
  namespace: myapp
spec:
  limits:
    # 容器级别限制
    - type: Container
      # 默认限制(如果 Pod 没有指定)
      default:
        cpu: "500m"
        memory: "512Mi"
      # 默认请求
      defaultRequest:
        cpu: "100m"
        memory: "128Mi"
      # 最大限制
      max:
        cpu: "2"
        memory: "4Gi"
      # 最小限制
      min:
        cpu: "50m"
        memory: "64Mi"

    # Pod 级别限制
    - type: Pod
      max:
        cpu: "4"
        memory: "8Gi"

    # PVC 级别限制
    - type: PersistentVolumeClaim
      max:
        storage: "50Gi"
      min:
        storage: "1Gi"


---
# ============================================================
#     第九部分:ServiceAccount 和 RBAC
# ============================================================
# 服务账户和基于角色的访问控制


# ------------------------------------------------------------
#              9.1 ServiceAccount
# ------------------------------------------------------------
apiVersion: v1
kind: ServiceAccount
metadata:
  name: api-service-account
  namespace: myapp
  labels:
    app: api
# 自动挂载 API 凭证
automountServiceAccountToken: true

---
# ------------------------------------------------------------
#              9.2 Role - 命名空间级别角色
# ------------------------------------------------------------
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
  name: api-role
  namespace: myapp
rules:
  # 允许读取 ConfigMap 和 Secret
  - apiGroups: [""]
    resources: ["configmaps", "secrets"]
    verbs: ["get", "list", "watch"]

  # 允许读取 Pod 信息
  - apiGroups: [""]
    resources: ["pods"]
    verbs: ["get", "list", "watch"]

  # 允许创建事件
  - apiGroups: [""]
    resources: ["events"]
    verbs: ["create"]

---
# ------------------------------------------------------------
#              9.3 RoleBinding - 绑定角色到服务账户
# ------------------------------------------------------------
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
  name: api-role-binding
  namespace: myapp
subjects:
  - kind: ServiceAccount
    name: api-service-account
    namespace: myapp
roleRef:
  kind: Role
  name: api-role
  apiGroup: rbac.authorization.k8s.io


---
# ============================================================
#     第十部分:常用工具部署示例
# ============================================================


# ------------------------------------------------------------
#              10.1 Prometheus 监控
# ------------------------------------------------------------
# 简化版 Prometheus 部署(生产环境建议使用 Helm Chart)
apiVersion: apps/v1
kind: Deployment
metadata:
  name: prometheus
  namespace: monitoring
  labels:
    app: prometheus
spec:
  replicas: 1
  selector:
    matchLabels:
      app: prometheus
  template:
    metadata:
      labels:
        app: prometheus
    spec:
      serviceAccountName: prometheus
      containers:
        - name: prometheus
          image: prom/prometheus:v2.47.0

          ports:
            - containerPort: 9090

          args:
            - "--config.file=/etc/prometheus/prometheus.yml"
            - "--storage.tsdb.path=/prometheus"
            - "--storage.tsdb.retention.time=15d"
            - "--web.enable-lifecycle"

          resources:
            requests:
              memory: "512Mi"
              cpu: "250m"
            limits:
              memory: "1Gi"
              cpu: "500m"

          volumeMounts:
            - name: config
              mountPath: /etc/prometheus
            - name: data
              mountPath: /prometheus

          livenessProbe:
            httpGet:
              path: /-/healthy
              port: 9090
            initialDelaySeconds: 30
            periodSeconds: 15

          readinessProbe:
            httpGet:
              path: /-/ready
              port: 9090
            initialDelaySeconds: 5
            periodSeconds: 5

      volumes:
        - name: config
          configMap:
            name: prometheus-config
        - name: data
          persistentVolumeClaim:
            claimName: prometheus-pvc

---
# ------------------------------------------------------------
#              10.2 Grafana 可视化
# ------------------------------------------------------------
apiVersion: apps/v1
kind: Deployment
metadata:
  name: grafana
  namespace: monitoring
  labels:
    app: grafana
spec:
  replicas: 1
  selector:
    matchLabels:
      app: grafana
  template:
    metadata:
      labels:
        app: grafana
    spec:
      containers:
        - name: grafana
          image: grafana/grafana:10.1.0

          ports:
            - containerPort: 3000

          env:
            - name: GF_SECURITY_ADMIN_USER
              value: "admin"
            - name: GF_SECURITY_ADMIN_PASSWORD
              valueFrom:
                secretKeyRef:
                  name: grafana-secrets
                  key: admin-password

            # 匿名访问(可选)
            - name: GF_AUTH_ANONYMOUS_ENABLED
              value: "false"

            # 数据源配置
            - name: GF_INSTALL_PLUGINS
              value: "grafana-piechart-panel,grafana-clock-panel"

          resources:
            requests:
              memory: "256Mi"
              cpu: "100m"
            limits:
              memory: "512Mi"
              cpu: "200m"

          volumeMounts:
            - name: data
              mountPath: /var/lib/grafana
            - name: datasources
              mountPath: /etc/grafana/provisioning/datasources
            - name: dashboards
              mountPath: /etc/grafana/provisioning/dashboards

          livenessProbe:
            httpGet:
              path: /api/health
              port: 3000
            initialDelaySeconds: 60
            periodSeconds: 10

          readinessProbe:
            httpGet:
              path: /api/health
              port: 3000
            initialDelaySeconds: 5
            periodSeconds: 5

      volumes:
        - name: data
          persistentVolumeClaim:
            claimName: grafana-pvc
        - name: datasources
          configMap:
            name: grafana-datasources
        - name: dashboards
          configMap:
            name: grafana-dashboards


---
# ============================================================
#           附录:常用 kubectl 命令
# ============================================================
#
# 应用配置:
#   kubectl apply -f 05_k8s_examples.yaml
#   kubectl apply -f . --recursive
#
# 查看资源:
#   kubectl get all -n myapp
#   kubectl get pods -n myapp -o wide
#   kubectl describe pod <pod-name> -n myapp
#
# 查看日志:
#   kubectl logs <pod-name> -n myapp
#   kubectl logs -f <pod-name> -n myapp  # 实时日志
#   kubectl logs <pod-name> -c <container-name> -n myapp  # 指定容器
#
# 进入容器:
#   kubectl exec -it <pod-name> -n myapp -- /bin/sh
#
# 端口转发:
#   kubectl port-forward svc/api-service 3000:3000 -n myapp
#
# 扩缩容:
#   kubectl scale deployment api --replicas=5 -n myapp
#
# 滚动更新:
#   kubectl set image deployment/api api=myapp/api:v2 -n myapp
#   kubectl rollout status deployment/api -n myapp
#   kubectl rollout undo deployment/api -n myapp
#
# 调试:
#   kubectl run debug --rm -it --image=busybox -- /bin/sh
#   kubectl debug <pod-name> -it --image=busybox -n myapp
#
# 资源使用:
#   kubectl top nodes
#   kubectl top pods -n myapp
#
# ============================================================

💬 讨论

使用 GitHub 账号登录后即可参与讨论

基于 MIT 许可发布