跳转至

第 04 章 Kubernetes 进阶

Kubernetes 进阶图

📚 章节概述

本章将深入讲解 Kubernetes 的进阶特性,包括 ConfigMap 和 Secret 配置管理、 Ingress 入口控制器、 Helm 包管理、 StatefulSet 有状态应用、 DaemonSet 守护进程集等。通过本章学习,你将能够掌握 Kubernetes 的高级功能,应对复杂的生产环境需求。

🎯 学习目标

完成本章后,你将能够:

  1. 熟练使用 ConfigMap 和 Secret 管理配置
  2. 掌握 Ingress 的配置和使用
  3. 了解 Helm 包管理器的使用
  4. 掌握 StatefulSet 有状态应用部署
  5. 理解 DaemonSet 的使用场景
  6. 掌握 Kubernetes 的网络策略
  7. 能够设计复杂的生产级 Kubernetes 架构

4.1 ConfigMap 配置管理

4.1.1 ConfigMap 概述

ConfigMap用于存储非敏感的配置数据,以键值对的形式提供给 Pod 使用。

ConfigMap 的特点

  1. 解耦配置
  2. 配置与镜像分离
  3. 支持配置热更新
  4. 便于版本管理

  5. 多种数据格式

  6. 键值对
  7. 完整的配置文件
  8. JSON/YAML 格式

  9. 灵活的注入方式

  10. 环境变量
  11. 命令行参数
  12. 配置文件挂载

4.1.2 创建 ConfigMap

从字面值创建

YAML
apiVersion: v1
kind: ConfigMap
metadata:
  name: app-config           # ConfigMap 名称
  namespace: default
data:
  # 数据库连接配置
  database_host: "mysql-service"
  database_port: "3306"
  database_name: "appdb"
  # Redis 缓存配置
  redis_host: "redis-service"
  redis_port: "6379"
  # 应用运行时配置
  app_env: "production"
  log_level: "info"
  debug_mode: "false"

从文件创建

Bash
# 从单个文件创建
kubectl create configmap nginx-config --from-file=nginx.conf

# 从目录创建
kubectl create configmap app-config --from-file=./config/

# 从多个文件创建
kubectl create configmap app-config \
  --from-file=app.properties \
  --from-file=logback.xml

从命令行创建

Bash
# 从字面值创建
kubectl create configmap app-config \
  --from-literal=database_host=mysql \
  --from-literal=database_port=3306 \
  --from-literal=app_env=production

4.1.3 使用 ConfigMap

作为环境变量

YAML
apiVersion: v1
kind: Pod
metadata:
  name: configmap-pod
spec:
  containers:
  - name: app
    image: nginx:1.27
    env:
    # 从 ConfigMap 中注入单个键值作为环境变量
    - name: DATABASE_HOST           # Pod 中的环境变量名
      valueFrom:
        configMapKeyRef:
          name: app-config          # 引用的 ConfigMap 名称
          key: database_host        # ConfigMap 中的键
    - name: DATABASE_PORT
      valueFrom:
        configMapKeyRef:
          name: app-config
          key: database_port
    - name: APP_ENV
      valueFrom:
        configMapKeyRef:
          name: app-config
          key: app_env

批量注入环境变量

YAML
apiVersion: v1
kind: Pod
metadata:
  name: configmap-pod
spec:
  containers:
  - name: app
    image: nginx:1.27
    # 一次性将 ConfigMap 中所有键值对注入为环境变量
    envFrom:
    - configMapRef:
        name: app-config           # 引用整个 ConfigMap

作为命令行参数

YAML
apiVersion: v1
kind: Pod
metadata:
  name: configmap-pod
spec:
  containers:
  - name: app
    image: nginx:1.27
    command: ["/bin/sh", "-c"]
    args: ["echo $(DATABASE_HOST) $(DATABASE_PORT)"]
    env:
    - name: DATABASE_HOST
      valueFrom:
        configMapKeyRef:
          name: app-config
          key: database_host
    - name: DATABASE_PORT
      valueFrom:
        configMapKeyRef:
          name: app-config
          key: database_port

作为配置文件挂载

YAML
apiVersion: v1
kind: Pod
metadata:
  name: configmap-pod
spec:
  containers:
  - name: app
    image: nginx:1.27
    volumeMounts:
    - name: config-volume
      mountPath: /etc/config       # 挂载到容器内的路径
      readOnly: true               # 只读挂载,防止容器修改配置
  volumes:
  - name: config-volume
    configMap:
      name: app-config             # 引用的 ConfigMap
      items:                       # 选择性挂载特定的键
      - key: nginx.conf
        path: nginx.conf           # 映射为容器内的文件名
      - key: app.properties
        path: app.properties

4.1.4 ConfigMap 热更新

YAML
apiVersion: v1
kind: ConfigMap
metadata:
  name: app-config
data:
  app.properties: |
    server.port=8080
    server.host=0.0.0.0
    database.url=jdbc:mysql://localhost:3306/appdb
    log.level=INFO
YAML
apiVersion: apps/v1
kind: Deployment
metadata:
  name: app
spec:
  template:
    spec:
      containers:
      - name: app
        image: myapp:v1.0
        volumeMounts:
        - name: config-volume
          mountPath: /etc/config   # ConfigMap 挂载点
      volumes:
      - name: config-volume
        configMap:
          name: app-config         # ConfigMap 更新后,挂载的文件会自动更新

注意:ConfigMap 更新后,挂载的配置文件会自动更新,但环境变量不会自动更新,需要重启 Pod 。

4.2 Secret 密钥管理

4.2.1 Secret 概述

Secret用于存储敏感信息,如密码、 OAuth 令牌、 SSH 密钥等。

Secret 的类型

  1. Opaque:通用类型,默认类型
  2. Kubernetes.io/service-account-token:服务账号令牌
  3. Kubernetes.io/dockercfg: Docker registry 认证
  4. Kubernetes.io/dockerconfigjson: Docker registry 认证( JSON 格式)
  5. Kubernetes.io/basic-auth:基本认证
  6. Kubernetes.io/ssh-auth: SSH 认证
  7. Kubernetes.io/tls: TLS 证书
  8. bootstrap.Kubernetes.io/token: bootstrap 令牌

4.2.2 创建 Secret

从命令行创建

Bash
# 通用Secret
kubectl create secret generic app-secret \
  --from-literal=username=admin \
  --from-literal=password=secretpassword

# 从文件创建
kubectl create secret generic ssh-key \
  --from-file=ssh-privatekey=/path/to/id_rsa \
  --from-file=ssh-publickey=/path/to/id_rsa.pub

# TLS Secret
kubectl create secret tls tls-secret \
  --cert=path/to/cert.crt \
  --key=path/to/cert.key

# Docker registry Secret
kubectl create secret docker-registry regcred \
  --docker-server=registry.example.com \
  --docker-username=user \
  --docker-password=password \
  --docker-email=user@example.com

从 YAML 创建

YAML
# ⚠️ 安全警告:以下配置包含硬编码密码,仅用于演示目的。
# 在生产环境中,请务必使用环境变量或密钥管理服务来存储敏感信息。
apiVersion: v1
kind: Secret
metadata:
  name: app-secret
  namespace: default
type: Opaque
data:
  username: YWRtaW4=  # base64编码的admin
  password: c2VjcmV0cGFzc3dvcmQ=  # base64编码的secretpassword
  database_url: amRiYzpteXNxbDovL2xvY2FsaG9zdDozMzA2L2FwcGRi

编码示例:

Bash
# 编码
echo -n 'admin' | base64
echo -n 'secretpassword' | base64

# 解码
echo 'YWRtaW4=' | base64 -d

4.2.3 使用 Secret

作为环境变量

YAML
apiVersion: v1
kind: Pod
metadata:
  name: secret-pod
spec:
  containers:
  - name: app
    image: nginx:1.27
    env:
    # 从 Secret 中注入敏感信息作为环境变量
    - name: USERNAME
      valueFrom:
        secretKeyRef:
          name: app-secret          # 引用的 Secret 名称
          key: username             # Secret 中的键
    - name: PASSWORD
      valueFrom:
        secretKeyRef:
          name: app-secret
          key: password

批量注入环境变量

YAML
apiVersion: v1
kind: Pod
metadata:
  name: secret-pod
spec:
  containers:
  - name: app
    image: nginx:1.27
    envFrom:
    - secretRef:
        name: app-secret

作为配置文件挂载

YAML
apiVersion: v1
kind: Pod
metadata:
  name: secret-pod
spec:
  containers:
  - name: app
    image: nginx:1.27
    volumeMounts:
    - name: secret-volume
      mountPath: /etc/secrets     # Secret 挂载到容器内的路径
      readOnly: true              # 必须只读,保护敏感数据
  volumes:
  - name: secret-volume
    secret:
      secretName: app-secret      # 引用的 Secret
      items:                      # 按键映射为单独的文件
      - key: username
        path: username.txt        # 挂载为 /etc/secrets/username.txt
      - key: password
        path: password.txt        # 挂载为 /etc/secrets/password.txt

拉取私有镜像

YAML
apiVersion: v1
kind: Pod
metadata:
  name: private-pod
spec:
  containers:
  - name: app
    image: registry.example.com/myapp:v1.0  # 私有镜像地址
  imagePullSecrets:
  - name: regcred               # 引用 Docker Registry 认证 Secret

4.2.4 Secret 最佳实践

  1. 使用 RBAC 限制访问
  2. 定期轮换 Secret
  3. 使用外部密钥管理系统(如 Vault )
  4. 避免在日志中打印 Secret
  5. 使用加密存储( etcd 加密)

4.3 Ingress 入口控制器

4.3.1 Ingress 概述

Ingress是 Kubernetes 的 API 对象,管理外部访问集群内服务的规则,提供 HTTP 和 HTTPS 路由。

Ingress vs Service

特性 Service Ingress
协议 TCP/UDP HTTP/HTTPS
路由 基于端口 基于主机名/路径
负载均衡 L4 L7
TLS 不支持 支持
复杂度 简单 复杂

4.3.2 Ingress Controller

Ingress Controller 是实现 Ingress 规则的组件,常见的有:

  1. Nginx Ingress Controller
  2. Traefik
  3. HAProxy
  4. Contour
  5. AWS ALB Ingress Controller

安装 Nginx Ingress Controller

Bash
# 添加Helm仓库
helm repo add ingress-nginx https://kubernetes.github.io/ingress-nginx
helm repo update

# 安装
helm install ingress-nginx ingress-nginx/ingress-nginx \
  --namespace ingress-nginx --create-namespace

# 验证安装
kubectl get pods -n ingress-nginx
kubectl get svc -n ingress-nginx

4.3.3 创建 Ingress

基本 Ingress

YAML
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: basic-ingress
  namespace: default
  annotations:
    nginx.ingress.kubernetes.io/rewrite-target: /  # URL 重写目标
spec:
  ingressClassName: nginx        # 指定使用的 Ingress Controller
  rules:
  - host: app.example.com        # 域名规则
    http:
      paths:
      - path: /                  # 匹配根路径
        pathType: Prefix         # 前缀匹配模式
        backend:
          service:
            name: app-service    # 后端服务名称
            port:
              number: 80         # 服务端口

多路径路由

YAML
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: multi-path-ingress
  namespace: default
spec:
  ingressClassName: nginx
  rules:
  - host: app.example.com
    http:
      paths:
      # 多路径路由:不同 URL 路径转发到不同后端服务
      - path: /api               # API 请求转发到 api-service
        pathType: Prefix
        backend:
          service:
            name: api-service
            port:
              number: 8000
      - path: /web               # Web 页面转发到 web-service
        pathType: Prefix
        backend:
          service:
            name: web-service
            port:
              number: 80
      - path: /static            # 静态资源转发到 static-service
        pathType: Prefix
        backend:
          service:
            name: static-service
            port:
              number: 80

多主机路由

YAML
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: multi-host-ingress
  namespace: default
spec:
  ingressClassName: nginx
  # 多主机路由:不同域名转发到不同服务
  rules:
  - host: api.example.com        # API 域名转发到 api-service
    http:
      paths:
      - path: /
        pathType: Prefix
        backend:
          service:
            name: api-service
            port:
              number: 8000
  - host: web.example.com        # Web 域名转发到 web-service
    http:
      paths:
      - path: /
        pathType: Prefix
        backend:
          service:
            name: web-service
            port:
              number: 80

TLS 配置

YAML
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: tls-ingress
  namespace: default
spec:
  ingressClassName: nginx
  # TLS 配置:启用 HTTPS 加密访问
  tls:
  - hosts:
    - app.example.com            # 开启 TLS 的域名
    secretName: tls-secret       # 存储 TLS 证书的 Secret
  rules:
  - host: app.example.com
    http:
      paths:
      - path: /
        pathType: Prefix
        backend:
          service:
            name: app-service
            port:
              number: 80

4.3.4 Ingress 注解

常用注解

YAML
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: annotated-ingress
  namespace: default
  annotations:
    # 重写目标
    nginx.ingress.kubernetes.io/rewrite-target: /$2

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

    # 限流
    nginx.ingress.kubernetes.io/limit-rps: "10"

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

    # 超时设置
    nginx.ingress.kubernetes.io/proxy-connect-timeout: "30"
    nginx.ingress.kubernetes.io/proxy-send-timeout: "600"
    nginx.ingress.kubernetes.io/proxy-read-timeout: "600"

    # 代理缓冲
    nginx.ingress.kubernetes.io/proxy-buffering: "on"
    nginx.ingress.kubernetes.io/proxy-buffer-size: "16k"

    # WebSocket
    nginx.ingress.kubernetes.io/proxy-http-version: "1.1"
    nginx.ingress.kubernetes.io/proxy-set-headers: "Upgrade: $http_upgrade\nConnection: upgrade"

    # 白名单
    nginx.ingress.kubernetes.io/whitelist-source-range: "10.0.0.0/8,172.16.0.0/12,192.168.0.0/16"

    # 认证
    nginx.ingress.kubernetes.io/auth-type: basic
    nginx.ingress.kubernetes.io/auth-secret: basic-auth
    nginx.ingress.kubernetes.io/auth-realm: "Authentication Required"
spec:
  ingressClassName: nginx
  rules:
  - host: app.example.com
    http:
      paths:
      - path: /api(/|$)(.*)
        pathType: Prefix
        backend:
          service:
            name: api-service
            port:
              number: 8000

4.4 Helm 包管理

4.4.1 Helm 概述

Helm是 Kubernetes 的包管理器,类似于 Linux 的 yum 或 apt ,用于管理 Kubernetes 应用。

Helm 的核心概念

  1. Chart: Helm 包,包含运行应用所需的所有资源
  2. Repository: Chart 仓库,存储和分发 Chart
  3. Release: Chart 的实例化部署
  4. Config:配置值,用于自定义 Chart

4.4.2 安装 Helm

Bash
# 下载Helm
curl https://raw.githubusercontent.com/helm/helm/main/scripts/get-helm-3 | bash  # |管道:将前一命令的输出作为后一命令的输入

# 验证安装
helm version

# 添加官方仓库
helm repo add bitnami https://charts.bitnami.com/bitnami
helm repo update

# 搜索Chart
helm search repo nginx

4.4.3 创建 Chart

Bash
# 创建Chart
helm create mychart

# Chart结构
mychart/
├── Chart.yaml          # Chart元数据
├── values.yaml         # 默认配置值
├── charts/             # 依赖的Chart
├── templates/          # Kubernetes资源模板
   ├── deployment.yaml
   ├── service.yaml
   ├── ingress.yaml
   └── _helpers.tpl   # 模板助手
└── templates/NOTES.txt # 使用说明

Chart.YAML

YAML
apiVersion: v2
name: mychart
description: A Helm chart for Kubernetes  # Chart 描述
type: application              # 类型:application 或 library
version: 0.1.0                 # Chart 版本号
appVersion: "1.0"              # 应用版本号
keywords:
  - web
  - application
maintainers:                   # 维护者信息
  - name: Your Name
    email: your.email@example.com

values.YAML

YAML
# 默认配置值
replicaCount: 3

image:
  repository: nginx
  pullPolicy: IfNotPresent
  tag: "1.27"

service:
  type: ClusterIP
  port: 80

podSecurityContext:
  runAsNonRoot: true
  seccompProfile:
    type: RuntimeDefault

securityContext:
  allowPrivilegeEscalation: false
  readOnlyRootFilesystem: true
  capabilities:
    drop: ["ALL"]

ingress:
  enabled: false
  className: "nginx"
  annotations: {}
  hosts:
    - host: chart-example.local
      paths:
        - path: /
          pathType: Prefix
  tls: []

resources:
  limits:
    cpu: 500m
    memory: 512Mi
  requests:
    cpu: 250m
    memory: 256Mi

autoscaling:
  enabled: false
  minReplicas: 1
  maxReplicas: 100
  targetCPUUtilizationPercentage: 80

nodeSelector: {}

tolerations: []

affinity: {}

templates/deployment.YAML

YAML
apiVersion: apps/v1
kind: Deployment
metadata:
  # 使用模板函数生成完整名称(发布名-Chart名)
  name: {{ include "mychart.fullname" . }}
  labels:
    {{- include "mychart.labels" . | nindent 4 }}
spec:
  # 副本数从 values.yaml 中读取,实现可配置化
  replicas: {{ .Values.replicaCount }}
  selector:
    matchLabels:
      {{- include "mychart.selectorLabels" . | nindent 6 }}
  template:
    metadata:
      labels:
        {{- include "mychart.selectorLabels" . | nindent 8 }}
    spec:
      # Pod 安全上下文(可选配置)
      {{- with .Values.podSecurityContext }}
      securityContext:
        {{- toYaml . | nindent 8 }}
      {{- end }}
      containers:
      - name: {{ .Chart.Name }}
        # 镜像地址:从 values.yaml 拼接 repository:tag
        image: "{{ .Values.image.repository }}:{{ .Values.image.tag | default .Chart.AppVersion }}"
        imagePullPolicy: {{ .Values.image.pullPolicy }}
        # 容器安全上下文(可选配置)
        {{- with .Values.securityContext }}
        securityContext:
          {{- toYaml . | nindent 10 }}
        {{- end }}
        ports:
        - name: http
          containerPort: {{ .Values.service.port }}
          protocol: TCP
        # 存活探针:检测容器是否还在运行
        livenessProbe:
          httpGet:
            path: /
            port: http
        # 就绪探针:检测容器是否准备好接受流量
        readinessProbe:
          httpGet:
            path: /
            port: http
        # 资源限制从 values.yaml 中读取
        resources:
          {{- toYaml .Values.resources | nindent 10 }}

templates/service.YAML

YAML
apiVersion: v1
kind: Service
metadata:
  # 服务名称使用模板函数自动生成
  name: {{ include "mychart.fullname" . }}
  labels:
    {{- include "mychart.labels" . | nindent 4 }}
spec:
  type: {{ .Values.service.type }}      # 服务类型(ClusterIP/NodePort/LoadBalancer)
  ports:
  - port: {{ .Values.service.port }}    # 服务端口
    targetPort: http                    # 目标端口(对应容器的命名端口)
    protocol: TCP
    name: http
  selector:
    # 通过标签选择器关联到对应的 Pod
    {{- include "mychart.selectorLabels" . | nindent 4 }}

4.4.4 使用 Helm

安装 Chart

Bash
# 安装Chart
helm install my-release ./mychart

# 指定配置值
helm install my-release ./mychart --set replicaCount=5

# 使用配置文件
helm install my-release ./mychart -f custom-values.yaml

# 查看Release
helm list
helm status my-release

更新 Release

Bash
# 更新Release
helm upgrade my-release ./mychart

# 更新配置
helm upgrade my-release ./mychart --set replicaCount=10

# 回滚Release
helm rollback my-release
helm rollback my-release 2  # 回滚到第2个版本

卸载 Release

Bash
# 卸载Release
helm uninstall my-release

# 保留历史记录
helm uninstall my-release --keep-history

4.5 StatefulSet 有状态应用

4.5.1 StatefulSet 概述

StatefulSet用于管理有状态应用,如数据库、消息队列等。

StatefulSet 的特点

  1. 稳定的网络标识
  2. 每个 Pod 有唯一的、稳定的网络标识
  3. 格式:<statefulset-name>-<ordinal>

  4. 稳定的持久化存储

  5. 每个 Pod 绑定独立的 PVC
  6. Pod 重新调度后仍能访问相同的存储

  7. 有序的部署和扩展

  8. 按顺序部署 Pod ( 0, 1, 2, ...)
  9. 按顺序删除 Pod ( N, N-1, N-2, ...)

  10. 有序的滚动更新

  11. 按逆序更新 Pod ( N, N-1, N-2, ...)

4.5.2 创建 StatefulSet

YAML
apiVersion: apps/v1
kind: StatefulSet
metadata:
  name: mysql
  namespace: default
spec:
  serviceName: mysql-headless    # 关联的 Headless Service,提供稳定网络标识
  replicas: 3                    # 3 个副本,按序号 0/1/2 创建
  selector:
    matchLabels:
      app: mysql
  template:
    metadata:
      labels:
        app: mysql
    spec:
      containers:
      - name: mysql
        image: mysql:8.4
        ports:
        - containerPort: 3306
          name: mysql
        env:
        # 从 Secret 中获取数据库 root 密码
        - name: MYSQL_ROOT_PASSWORD
          valueFrom:
            secretKeyRef:
              name: mysql-secret
              key: root-password
        volumeMounts:
        - name: mysql-data
          mountPath: /var/lib/mysql   # 数据持久化挂载点
        resources:
          requests:
            memory: "512Mi"
            cpu: "500m"
          limits:
            memory: "1Gi"
            cpu: "1000m"
        # 存活探针:检测 MySQL 是否运行
        livenessProbe:
          exec:
            command: ["mysqladmin", "ping", "-h", "localhost"]
          initialDelaySeconds: 30    # 启动后 30s 开始探测
          periodSeconds: 10          # 每 10s 探测一次
        # 就绪探针:检测 MySQL 是否可接受流量
        readinessProbe:
          exec:
            command: ["mysql", "-h", "127.0.0.1", "-e", "SELECT 1"]
          initialDelaySeconds: 5
          periodSeconds: 5
  # PVC 模板:为每个 Pod 自动创建独立的持久化存储
  volumeClaimTemplates:
  - metadata:
      name: mysql-data
    spec:
      accessModes: [ "ReadWriteOnce" ]  # 单节点读写
      storageClassName: "standard"
      resources:
        requests:
          storage: 10Gi              # 每个副本 10Gi 存储

4.5.3 Headless Service

YAML
apiVersion: v1
kind: Service
metadata:
  name: mysql-headless
  namespace: default
spec:
  clusterIP: None  # Headless Service:无集群 IP,直接解析到 Pod IP
  selector:
    app: mysql
  ports:
  - port: 3306
    name: mysql
    # Pod 的 DNS 格式:mysql-0.mysql-headless.default.svc.cluster.local

4.5.4 StatefulSet 操作

Bash
# 创建StatefulSet
kubectl apply -f statefulset.yaml

# 查看StatefulSet
kubectl get statefulsets
kubectl get sts

# 查看Pod
kubectl get pods -l app=mysql

# 查看PVC
kubectl get pvc

# 扩展StatefulSet
kubectl scale statefulset mysql --replicas=5

# 删除特定Pod
kubectl delete pod mysql-2

# 滚动更新
kubectl set image statefulset mysql mysql=mysql:8.4.0

# 查看更新状态
kubectl rollout status statefulset/mysql

4.6 DaemonSet 守护进程集

4.6.1 DaemonSet 概述

DaemonSet确保在每个节点上运行一个 Pod 副本,常用于日志收集、监控代理等。

DaemonSet 的使用场景

  1. 日志收集: Fluentd 、 Filebeat
  2. 监控代理: Node Exporter 、 Datadog Agent
  3. 网络插件: Calico 、 Flannel
  4. 存储插件: Ceph 、 GlusterFS

4.6.2 创建 DaemonSet

YAML
apiVersion: apps/v1
kind: DaemonSet
metadata:
  name: node-exporter
  namespace: monitoring
  labels:
    app: node-exporter
spec:
  selector:
    matchLabels:
      app: node-exporter
  template:
    metadata:
      labels:
        app: node-exporter
    spec:
      hostNetwork: true          # 使用宿主机网络,直接采集节点网络指标
      hostPID: true              # 访问宿主机 PID 命名空间
      containers:
      - name: node-exporter
        image: prom/node-exporter:latest
        args:
        - '--path.procfs=/host/proc'     # 指定宿主机 proc 路径
        - '--path.sysfs=/host/sys'       # 指定宿主机 sys 路径
        - '--collector.filesystem.mount-points-exclude=^/(sys|proc|dev|host|etc)($$|/)'  # 排除系统目录
        ports:
        - name: metrics
          containerPort: 9100
          hostPort: 9100           # 映射到宿主机端口,便于 Prometheus 拉取
        volumeMounts:
        # 挂载宿主机的 /proc 和 /sys 目录用于采集指标
        - name: proc
          mountPath: /host/proc
        - name: sys
          mountPath: /host/sys
        resources:
          requests:
            memory: "64Mi"
            cpu: "100m"
          limits:
            memory: "128Mi"
            cpu: "200m"
      volumes:
      - name: proc
        hostPath:
          path: /proc
      - name: sys
        hostPath:
          path: /sys
      # 容忍所有污点,确保在每个节点都能调度
      tolerations:
      - effect: NoSchedule
        operator: Exists
      - effect: NoExecute
        operator: Exists

4.6.3 DaemonSet 操作

Bash
# 创建DaemonSet
kubectl apply -f daemonset.yaml

# 查看DaemonSet
kubectl get daemonsets
kubectl get ds

# 查看Pod
kubectl get pods -l app=node-exporter

# 更新DaemonSet
kubectl set image daemonset node-exporter node-exporter=prom/node-exporter:v1.5.0

# 查看更新状态
kubectl rollout status daemonset/node-exporter

4.7 网络策略

4.7.1 网络策略概述

NetworkPolicy用于控制 Pod 之间的网络流量,实现网络隔离。

网络策略的类型

  1. Ingress 规则:控制入站流量
  2. Egress 规则:控制出站流量
  3. Both 规则:同时控制入站和出站流量

4.7.2 创建网络策略

默认拒绝所有入站流量

YAML
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: default-deny-ingress
  namespace: default
spec:
  podSelector: {}          # 空选择器:匹配命名空间内所有 Pod
  policyTypes:
  - Ingress                # 仅控制入站流量,未指定 ingress 规则则全部拒绝

允许特定 Pod 访问

YAML
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: allow-frontend-to-backend
  namespace: default
spec:
  # 目标 Pod:带有 app=backend 标签的 Pod
  podSelector:
    matchLabels:
      app: backend
  policyTypes:
  - Ingress
  ingress:
  - from:
    # 允许来源:仅允许带有 app=frontend 标签的 Pod 访问
    - podSelector:
        matchLabels:
          app: frontend
    ports:
    - protocol: TCP
      port: 8000               # 仅允许访问 8000 端口

允许特定命名空间访问

YAML
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: allow-namespace-access
  namespace: default
spec:
  # 目标 Pod:带有 app=backend 标签的 Pod
  podSelector:
    matchLabels:
      app: backend
  policyTypes:
  - Ingress
  ingress:
  - from:
    # 允许来自带有 name=frontend 标签的命名空间的所有 Pod
    - namespaceSelector:
        matchLabels:
          name: frontend
    ports:
    - protocol: TCP
      port: 8000

控制出站流量

YAML
apiVersion: networking.k8s.io/v1  # apiVersion指定K8s API版本
kind: NetworkPolicy  # kind指定资源类型
metadata:
  name: allow-dns-access
  namespace: default
spec:  # spec定义资源的期望状态
  podSelector:
    matchLabels:
      app: backend
  policyTypes:
  - Egress                     # 控制出站流量
  egress:
  # 规则1:允许 DNS 查询(必须允许,否则服务发现失败)
  - to:
    - namespaceSelector: {}    # 所有命名空间
    ports:
    - protocol: UDP
      port: 53                 # DNS 端口
  # 规则2:允许 HTTPS 出站访问,排除元数据服务地址
  - to:
    - ipBlock:
        cidr: 0.0.0.0/0
        except:
        - 169.254.169.254/32   # 排除云平台元数据服务(安全最佳实践)
    ports:
    - protocol: TCP
      port: 443                # 仅允许 HTTPS

4.8 完整实战项目

4.8.1 项目概述

部署一个完整的微服务应用,包括: - ConfigMap 配置管理 - Secret 密钥管理 - Ingress 入口控制器 - StatefulSet 数据库 - DaemonSet 监控 - 网络策略

4.8.2 项目结构

Text Only
k8s-advanced-project/
├── namespace.yaml
├── configmap.yaml
├── secret.yaml
├── network-policy.yaml
├── mysql/
│   ├── statefulset.yaml
│   ├── service.yaml
│   └── headless-service.yaml
├── redis/
│   ├── statefulset.yaml
│   └── service.yaml
├── backend/
│   ├── deployment.yaml
│   ├── service.yaml
│   └── hpa.yaml
├── frontend/
│   ├── deployment.yaml
│   └── service.yaml
├── monitoring/
│   └── daemonset.yaml
└── ingress/
    └── ingress.yaml

4.8.3 部署脚本

Bash
#!/bin/bash

# 部署脚本

set -e

echo "开始部署高级Kubernetes应用..."

# 1. 创建Namespace
echo "创建Namespace..."
kubectl apply -f namespace.yaml

# 2. 创建ConfigMap和Secret
echo "创建ConfigMap和Secret..."
kubectl apply -f configmap.yaml
kubectl apply -f secret.yaml

# 3. 创建网络策略
echo "创建网络策略..."
kubectl apply -f network-policy.yaml

# 4. 部署MySQL StatefulSet
echo "部署MySQL..."
kubectl apply -f mysql/
kubectl wait --for=condition=ready pod -l app=mysql -n webapp --timeout=600s

# 5. 部署Redis StatefulSet
echo "部署Redis..."
kubectl apply -f redis/
kubectl wait --for=condition=ready pod -l app=redis -n webapp --timeout=600s

# 6. 部署Backend
echo "部署Backend..."
kubectl apply -f backend/
kubectl wait --for=condition=ready pod -l app=backend -n webapp --timeout=300s

# 7. 部署Frontend
echo "部署Frontend..."
kubectl apply -f frontend/
kubectl wait --for=condition=ready pod -l app=frontend -n webapp --timeout=300s

# 8. 部署Monitoring DaemonSet
echo "部署Monitoring..."
kubectl apply -f monitoring/

# 9. 创建Ingress
echo "创建Ingress..."
kubectl apply -f ingress/

# 10. 查看部署状态
echo "查看部署状态..."
kubectl get all -n webapp

echo "部署完成!"

4.9 练习题

基础题

  1. 选择题
  2. ConfigMap 和 Secret 的主要区别是什么?

    • A. ConfigMap 用于存储敏感数据
    • B. Secret 数据是明文存储
    • C. Secret 数据是 base64 编码
    • D. ConfigMap 不能挂载为文件
  3. 简答题

  4. 解释 Ingress 的作用和使用场景。
  5. 说明 StatefulSet 和 Deployment 的区别。

进阶题

  1. 实践题
  2. 创建一个包含 ConfigMap 和 Secret 的完整应用。
  3. 配置 Ingress 实现多路径路由。
  4. 部署一个 StatefulSet 数据库。

  5. 设计题

  6. 设计一个生产级的微服务架构。
  7. 设计一个高可用的数据库部署方案。

答案

1. 选择题答案

  1. C ( Secret 数据是 base64 编码, ConfigMap 是明文)

2. 简答题答案

Ingress 的作用和使用场景: - 作用:管理外部访问集群内服务的 HTTP/HTTPS 路由 - 使用场景:多域名路由、多路径路由、 TLS 终止、负载均衡

StatefulSet 和 Deployment 的区别: - StatefulSet :有状态应用,稳定的网络标识和存储,有序部署 - Deployment :无状态应用, Pod 标识不固定,并发部署

3. 实践题答案

参见 4.8 节的完整实战项目。

4. 设计题答案

参见 4.8 节的完整项目设计。

4.10 面试准备

大厂面试题

字节跳动

  1. ConfigMap 和 Secret 的区别是什么?
  2. Ingress 的工作原理是什么?
  3. StatefulSet 的使用场景是什么?
  4. 如何实现 Kubernetes 的网络隔离?

腾讯

  1. Helm 的 Chart 结构是怎样的?
  2. StatefulSet 的有序部署是如何实现的?
  3. DaemonSet 的使用场景有哪些?
  4. 如何实现 Kubernetes 的灰度发布?

阿里云

  1. ConfigMap 热更新的机制是什么?
  2. Ingress Controller 的选择标准是什么?
  3. 如何实现 Kubernetes 的配置管理?
  4. StatefulSet 的存储管理是怎样的?

📚 参考资料

🎯 本章小结

本章深入讲解了 Kubernetes 的进阶特性,包括:

  1. ConfigMap 和 Secret 配置管理
  2. Ingress 入口控制器
  3. Helm 包管理器
  4. StatefulSet 有状态应用
  5. DaemonSet 守护进程集
  6. 网络策略
  7. 完整的实战项目案例

通过本章学习,你掌握了 Kubernetes 的高级功能,能够应对复杂的生产环境需求。下一章将深入学习 CI/CD 流水线技术。