跳转至

第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流水线技术。