一、什么是「云原生架构师 开箱学习法」

就是:不从头啃书,不先学理论,直接从「环境 + 工具 + 场景」入手,边跑边懂,边用边体系化。

核心三句话:

  1. 先有环境,再学概念
  2. 先跑通流程,再抠原理
  3. 先做项目,再补理论

二、K8S + AI 云原生架构师「开箱即用学习方法」

1)环境开箱:1 天内拥有自己的云原生实验场

最简可落地方案:

  • 本地:Docker Desktop + Kind / Minikube
  • 云:阿里云 / 腾讯云 / 华为云 轻量 K8s 集群

目标:10 分钟内 kubectl get nodes 能出来结果。

Docker Desktop + Kind / Minikube

基于 Docker Desktop 分别搭建 Kind 和 Minikube 这两种本地 Kubernetes 环境,我会为你提供分步、可落地的搭建教程,包括环境准备、安装步骤、验证方法和常见问题解决,两种方案都会覆盖。

一、前置环境准备(通用)

无论搭建 Kind 还是 Minikube,都需要先完成以下基础配置:

  1. 安装 Docker Desktop
    • 下载地址:https://www.docker.com/products/docker-desktop/
    • 安装完成后,打开 Docker Desktop,确保:
      • Settings > Resources > Advanced 中,分配至少 2 CPU4GB 内存(推荐 8GB),避免集群资源不足。
      • Settings > Kubernetes 中,不要勾选 "Enable Kubernetes"(避免和 Kind/Minikube 冲突)。
    • 验证 Docker 正常运行:

      bash

      运行

      docker --version  # 输出 Docker 版本,如 Docker version 25.0.3
      docker info       # 无报错即正常
      
  2. 安装 kubectl 命令行工具
    • Windows/macOS(推荐):通过 Docker Desktop 自动安装(Docker Desktop > Settings > Kubernetes > 勾选 "Install kubectl")。
    • 手动安装(适用于所有系统):

      bash

      运行

      # macOS
      brew install kubectl
      # Windows(PowerShell)
      winget install Kubernetes.kubectl
      # Linux
      curl -LO "https://dl.k8s.io/release/$(curl -L -s https://dl.k8s.io/release/stable.txt)/bin/linux/amd64/kubectl"
      chmod +x kubectl
      sudo mv kubectl /usr/local/bin/
      
    • 验证:kubectl version --client(输出客户端版本即正常)。

二、方案 1:Docker Desktop + Kind 搭建

Kind(Kubernetes IN Docker)是纯 Docker 容器化的 K8s 集群,轻量、启动快,适合开发 / 测试。

步骤 1:安装 Kind
  • macOS

    bash

    运行

    brew install kind
    
  • Windows(PowerShell)

    bash

    运行

    winget install Kind.Kind
    
  • Linux / 通用

    bash

    运行

    curl -Lo ./kind https://kind.sigs.k8s.io/dl/v0.22.0/kind-linux-amd64
    chmod +x ./kind
    sudo mv ./kind /usr/local/bin/kind
    
  • 验证:kind version(输出 Kind 版本即正常)。
步骤 2:创建 Kind 集群
  1. 基础集群(单节点,推荐新手)

    bash

    运行

    # 创建默认集群(名称为 kind)
    kind create cluster
    
    • 说明:Kind 会自动拉取 K8s 节点镜像,启动一个单节点集群,耗时约 1-3 分钟(取决于网络)。
  2. 自定义集群(可选,多节点):创建 kind-config.yaml 文件:

    yaml

    kind: Cluster
    apiVersion: kind.x-k8s.io/v1alpha4
    nodes:
      - role: control-plane  # 控制节点
      - role: worker         # 工作节点1
      - role: worker         # 工作节点2
    

    执行创建:

    bash

    运行

    kind create cluster --config kind-config.yaml --name my-cluster
    
步骤 3:验证集群

bash

运行

# 查看 Kind 集群列表
kind get clusters

# 查看集群节点(kubectl 会自动关联 Kind 集群)
kubectl get nodes
# 输出示例(STATUS 为 Ready 即正常):
# NAME                 STATUS   ROLES           AGE   VERSION
# kind-control-plane   Ready    control-plane   10s   v1.29.0
步骤 4:删除集群(可选)

bash

运行

# 删除默认集群
kind delete cluster
# 删除指定名称的集群
kind delete cluster --name my-cluster

三、方案 2:Docker Desktop + Minikube 搭建

Minikube 是经典的本地 K8s 工具,支持多种驱动(这里用 Docker 驱动),功能更全,适合模拟生产环境。

步骤 1:安装 Minikube
  • macOS

    bash

    运行

    brew install minikube
    
  • Windows(PowerShell)

    bash

    运行

    winget install Kubernetes.minikube
    
  • Linux / 通用

    bash

    运行

    curl -LO https://storage.googleapis.com/minikube/releases/latest/minikube-linux-amd64
    sudo install minikube-linux-amd64 /usr/local/bin/minikube
    
  • 验证:minikube version(输出版本即正常)。
步骤 2:启动 Minikube 集群

bash

运行

# 用 Docker 驱动启动(核心,指定 K8s 版本可选)
minikube start --driver=docker --kubernetes-version=v1.29.0
# 说明:
# --driver=docker:强制使用 Docker 驱动(依赖 Docker Desktop)
# --kubernetes-version:指定 K8s 版本(可选,不指定则用默认)
# 首次启动会拉取 Minikube 镜像和 K8s 节点镜像,耗时稍长(约 3-5 分钟)
步骤 3:验证集群

bash

运行

# 查看 Minikube 状态
minikube status
# 输出示例:
# minikube
# type: Control Plane
# host: Running
# kubelet: Running
# apiserver: Running

# 查看节点(STATUS 为 Ready 即正常)
kubectl get nodes
# 输出示例:
# NAME       STATUS   ROLES           AGE   VERSION
# minikube   Ready    control-plane   20s   v1.29.0

# 启动 Minikube 仪表盘(可视化界面)
minikube dashboard
步骤 4:常用 Minikube 操作

bash

运行

# 停止集群(保留数据)
minikube stop

# 重启集群
minikube start

# 删除集群(清理所有数据)
minikube delete

# 查看 Minikube 配置
minikube config view

四、常见问题解决
  1. Kind/Minikube 启动失败:Docker 未运行
    • 解决:确保 Docker Desktop 已启动,且 docker ps 能正常执行。
  2. 拉取镜像超时
    • 解决:给 Docker Desktop 配置国内镜像源(如阿里云、网易云),或手动拉取镜像:

      bash

      运行

      # Kind 手动拉取镜像(示例)
      docker pull kindest/node:v1.29.0
      # Minikube 手动拉取镜像(示例)
      minikube start --image-mirror-country cn --driver=docker
      
  3. kubectl 无法连接集群
    • 解决:Kind/Minikube 会自动配置 ~/.kube/config,执行以下命令重置上下文:

      bash

      运行

      # Kind 切换上下文
      kubectl config use-context kind-kind
      # Minikube 切换上下文
      kubectl config use-context minikube
      
总结
  1. Kind 特点:超轻量、启动快(1 分钟内)、基于 Docker 容器,适合快速测试 K8s 命令 / 配置,无额外虚拟机开销。
  2. Minikube 特点:功能更全(支持仪表盘、Ingress、Metrics 等插件),模拟生产环境更真实,启动稍慢但稳定性更高。
  3. 核心验证步骤:无论哪种方案,最终通过 kubectl get nodes 看到节点 STATUS 为 Ready,即集群搭建成功。

你可根据需求选择:快速测试选 Kind,模拟生产环境选 Minikube,两者均基于 Docker Desktop,无需额外安装虚拟机(如 VirtualBox)。

阿里云、腾讯云、华为云的轻量 K8s 集群

基于 Docker Desktop + Kind/Minikube 的本地 K8s 搭建思路,适配到阿里云、腾讯云、华为云的轻量 K8s 集群上,我会针对三大云厂商的轻量 K8s 产品(托管版 / 轻量版),提供适配性的搭建步骤,包括集群创建、kubectl 连接、核心操作适配,同时说明云厂商环境和本地环境的核心差异。

核心前提说明

云厂商的轻量 K8s 集群和本地 Kind/Minikube 有本质区别:

  • 本地:基于 Docker 模拟的单 / 多节点集群,仅用于测试,无公网暴露能力;
  • 云厂商:托管式 K8s 集群(如阿里云 ACK 轻量版、腾讯云 TKE 轻量版、华为云 CCE 轻量版),由云厂商维护控制平面,你只需管理工作节点,支持公网访问、弹性扩缩容、高可用,且无需手动部署 Docker / 容器运行时。

因此无需在云服务器上安装 Kind/Minikube,而是直接使用云厂商的托管 K8s 服务,以下是三大云厂商的标准化搭建步骤。


一、阿里云 ACK 轻量版集群搭建

阿里云轻量 K8s 集群(ACK Serverless 版 / 轻量版)是性价比最高的托管 K8s 方案,无需购买专用控制节点。

步骤 1:创建 ACK 轻量版集群
  1. 登录阿里云控制台:https://cs.console.aliyun.com/
  2. 进入「容器服务 K8s 版」→「集群」→「创建集群」;
  3. 选择「轻量版集群」(或 Serverless 版,更省成本):
    • 地域:选择就近地域(如华东 2 上海);
    • 集群版本:选择稳定版(如 v1.28);
    • 节点配置:选择轻量应用服务器(2 核 4G 起步),设置节点数量(1 节点即可测试);
    • 网络:使用默认 VPC / 交换机(自动创建),开启公网访问;
    • 其他:关闭「节点池自动扩缩容」(测试环境无需),密码 / 密钥登录二选一。
  4. 点击「创建」,等待 5-10 分钟,集群状态变为「运行中」。
步骤 2:配置 kubectl 连接集群
  1. 在集群列表页,点击目标集群→「连接信息」→「KubeConfig 」;
  2. 复制 KubeConfig 内容,替换本地 ~/.kube/config 文件(或新建文件);
  3. 验证连接:

    bash

    运行

    # 查看集群节点(云厂商节点 STATUS 为 Ready 即正常)
    kubectl get nodes
    # 输出示例:
    # NAME          STATUS   ROLES    AGE   VERSION
    # cn-hangzhou.i-xxxx   Ready    <none>   5m    v1.28.0
    
步骤 3:核心操作适配(和本地 Kind/Minikube 一致)

云厂商集群的 kubectl 命令和本地完全通用,例如:

bash

运行

# 部署 Nginx 测试(和本地命令无区别)
kubectl create deployment nginx --image=nginx:1.25
kubectl expose deployment nginx --port=80 --type=NodePort
# 查看 Service(NodePort 可通过云服务器公网 IP 访问)
kubectl get svc nginx

二、腾讯云 TKE 轻量版集群搭建

腾讯云 TKE 轻量版基于轻量应用服务器,成本低、部署快,适配个人 / 小型团队。

步骤 1:创建 TKE 轻量版集群
  1. 登录腾讯云控制台:https://console.cloud.tencent.com/tke
  2. 进入「集群」→「新建」→ 选择「轻量应用集群」;
  3. 配置参数:
    • 集群名称:自定义(如 tke-light-cluster);
    • 地域 / 可用区:就近选择(如广州);
    • K8s 版本:选择 v1.26+ 稳定版;
    • 节点配置:轻量应用服务器(2 核 4G,1 节点),设置登录密码 / 密钥;
    • 网络:默认私有网络,开启「公网访问」。
  4. 点击「创建集群」,等待 3-8 分钟,集群状态变为「运行中」。
步骤 2:配置 kubectl 连接
  1. 集群列表页→目标集群→「基本信息」→「获取 KubeConfig」;
  2. 将 KubeConfig 内容写入本地 ~/.kube/config
  3. 验证:

    bash

    运行

    kubectl get nodes
    # 输出腾讯云轻量节点信息,STATUS 为 Ready 即成功
    
步骤 3:关键适配点
  • 腾讯云 TKE 轻量版默认开启「容器网络插件」(CNI),无需手动配置;
  • 暴露服务时,NodePort 范围为 30000-32767,需在轻量服务器的「防火墙」中放行对应端口。

三、华为云 CCE 轻量版集群搭建

华为云 CCE 轻量版(又称「CCE 边缘集群」/「轻量版」)适配轻量服务器,操作逻辑和阿里云 / 腾讯云一致。

步骤 1:创建 CCE 轻量版集群
  1. 登录华为云控制台:https://console.huaweicloud.com/cce/
  2. 进入「集群」→「创建集群」→ 选择「轻量版集群」;
  3. 配置参数:
    • 集群名称:自定义;
    • 地域 / 可用区:就近选择(如北京四);
    • K8s 版本:v1.27+;
    • 节点配置:轻量应用服务器(2 核 4G,1 节点),设置登录凭证;
    • 网络:使用默认 VPC,开启「公网访问」。
  4. 点击「立即创建」,等待 5-10 分钟完成部署。
步骤 2:配置 kubectl 连接
  1. 集群详情页→「连接集群」→「KubeConfig」→ 复制配置内容;
  2. 覆盖本地 ~/.kube/config
  3. 验证:

    bash

    运行

    kubectl get pods --all-namespaces  # 查看系统组件是否正常运行
    

四、云厂商集群 vs 本地 Kind/Minikube 核心适配点

表格

操作场景 本地 Kind/Minikube 云厂商轻量 K8s 集群
集群创建 kind create cluster/minikube start 云控制台可视化创建(无需命令)
kubectl 连接 自动生成 ~/.kube/config 从云控制台复制 KubeConfig 手动配置
网络访问 仅本地端口转发(port-forward 支持 NodePort/LoadBalancer 公网访问
资源限制 依赖本地 Docker 资源(CPU / 内存) 依赖云服务器配置,可弹性扩容
核心 kubectl 命令 完全通用(get/apply/logs等) 完全通用,无差异
云厂商集群的额外实用操作(适配本地习惯)
  1. 端口转发(和本地一致)

    bash

    运行

    # 本地访问云集群的 Nginx 服务(无需暴露公网)
    kubectl port-forward svc/nginx 8080:80
    
  2. 部署本地 YAML 文件(和本地一致)

    bash

    运行

    # 本地写好的 deployment.yaml 直接部署到云集群
    kubectl apply -f deployment.yaml
    
  3. 查看云集群日志(和本地一致)

    bash

    运行

    kubectl logs -f <pod-name>
    

五、常见问题解决
  1. kubectl 连接云集群超时
    • 检查云服务器「安全组」:放行 6443 端口(K8s API 端口);
    • 确认 KubeConfig 中的 server 地址是公网 IP / 域名,且能 ping 通。
  2. NodePort 服务无法访问
    • 云服务器防火墙 / 安全组放行对应 NodePort 端口(如 30080);
    • 访问地址:云服务器公网 IP:NodePort(如 120.78.xxx.xxx:30080)。
  3. 镜像拉取失败
    • 云厂商集群默认可访问公网镜像源(如 Docker Hub),若拉取慢,可配置云厂商私有镜像仓库(如阿里云 ACr、腾讯云 TCR)。
总结
  1. 核心适配逻辑:云厂商轻量 K8s 集群无需安装 Kind/Minikube,直接通过控制台创建托管集群,kubectl 核心命令和本地完全通用;
  2. 关键差异:集群创建由云控制台完成(替代本地 kind create/minikube start),连接集群需手动配置云厂商提供的 KubeConfig;
  3. 操作一致性:部署应用、查看日志、端口转发等核心操作和本地 Kind/Minikube 无区别,只需注意云服务器安全组 / 端口放行。

你可根据成本和地域选择云厂商:阿里云 ACK 生态最完善,腾讯云 TKE 轻量版性价比高,华为云 CCE 适配国产化场景,三者操作逻辑基本一致,核心 kubectl 命令无需修改即可复用。

        

2)命令开箱:只背 20 条高频 kubectl 命令

不用全学,架构师只需要能排查、能发布、能观测

学习法:每条命令只练 3 分钟,跑通就过。

20 条高频 kubectl 命令(附说明 + 示例)

一、集群 / 节点信息查看
  1. 查看集群信息

    bash

    运行

    kubectl cluster-info
    

    说明:显示集群的控制平面、Kubernetes DNS 等核心组件的地址,快速确认集群是否正常运行。

  2. 查看节点列表

    bash

    运行

    kubectl get nodes
    # 查看节点详细信息(含标签、污点、状态)
    kubectl get nodes -o wide
    # 查看节点描述(排查节点异常)
    kubectl describe node <节点名称>
    

    说明:核心命令,用于确认节点状态(Ready/NotReady)、角色、资源配置等。

二、核心资源查看(Pod/Deployment/Service 等)
  1. 查看所有命名空间的 Pod

    bash

    运行

    kubectl get pods --all-namespaces
    # 简写:kubectl get pods -A
    # 查看指定命名空间的 Pod(最常用)
    kubectl get pods -n <命名空间>
    # 查看 Pod 详细信息(IP、节点、容器等)
    kubectl get pods -n <命名空间> -o wide
    

    说明:日常排查 Pod 状态(Running/CrashLoopBackOff 等)的首要命令。

  2. 查看 Deployment

    bash

    运行

    # 查看指定命名空间的 Deployment
    kubectl get deploy -n <命名空间>
    # 查看 Deployment 详细描述(含副本数、镜像、更新策略)
    kubectl describe deploy <deployment名称> -n <命名空间>
    

    说明:管理无状态应用的核心命令,确认部署的副本数、镜像版本等。

  3. 查看 Service

    bash

    运行

    kubectl get svc -n <命名空间>
    # 查看 Service 详细信息(含 ClusterIP、端口映射、关联 Pod)
    kubectl get svc -n <命名空间> -o wide
    

    说明:确认服务的访问方式(ClusterIP/NodePort/LoadBalancer)和端口配置。

  4. 查看所有资源类型

    bash

    运行

    # 查看指定命名空间的所有资源
    kubectl get all -n <命名空间>
    

    说明:快速概览命名空间内的 Pod、Deployment、Service、ConfigMap 等所有资源,适合快速排查。

  5. 查看 ConfigMap/Secret

    bash

    运行

    # 查看 ConfigMap
    kubectl get cm -n <命名空间>
    # 查看 Secret(默认加密显示,-o yaml 可看明文)
    kubectl get secret <secret名称> -n <命名空间> -o yaml
    

    说明:管理配置和敏感信息(如密码、token)的核心命令。

三、资源管理(创建 / 删除 / 更新)
  1. 通过 YAML 文件创建资源

    bash

    运行

    kubectl apply -f <yaml文件路径>
    # 示例:kubectl apply -f deployment.yaml
    

    说明:最推荐的资源创建方式(幂等,重复执行不会报错),优于 create

  2. 删除资源

    bash

    运行

    # 删除指定 Pod
    kubectl delete pod <pod名称> -n <命名空间>
    # 删除 YAML 文件定义的资源
    kubectl delete -f <yaml文件路径>
    # 强制删除卡住的 Pod(慎用)
    kubectl delete pod <pod名称> -n <命名空间> --force --grace-period=0
    
  3. 更新 Deployment 镜像

    bash

    运行

    kubectl set image deployment/<deployment名称> <容器名>=<新镜像>:<版本> -n <命名空间>
    # 示例:kubectl set image deployment/myapp app=nginx:1.25 -n default
    

    说明:无需修改 YAML 文件,快速更新镜像版本,会自动触发滚动更新。

  4. 扩缩容 Deployment 副本数

    bash

    运行

    # 缩放到 3 个副本
    kubectl scale deployment <deployment名称> --replicas=3 -n <命名空间>
    
四、调试 / 排障(核心高频)
  1. 查看 Pod 日志

    bash

    运行

    # 查看 Pod 实时日志(最常用)
    kubectl logs -f <pod名称> -n <命名空间>
    # 查看指定容器的日志(Pod 多容器时)
    kubectl logs -f <pod名称> -c <容器名> -n <命名空间>
    # 查看最近的日志(如最近 100 行)
    kubectl logs <pod名称> -n <命名空间> --tail=100
    

    说明:排查 Pod 启动失败、运行异常的核心命令。

  2. 进入 Pod 容器执行命令

    bash

    运行

    # 进入容器交互终端(类似 ssh)
    kubectl exec -it <pod名称> -n <命名空间> -- /bin/bash
    # 若没有 bash,用 sh
    kubectl exec -it <pod名称> -n <命名空间> -- /bin/sh
    # 直接执行单条命令(无需进入容器)
    kubectl exec <pod名称> -n <命名空间> -- ls /app
    
  3. 查看 Pod 事件(排查启动失败)

    bash

    运行

    kubectl describe pod <pod名称> -n <命名空间>
    

    说明:重点看 Events 部分,会显示 Pod 调度失败、镜像拉取失败、权限不足等关键原因。

  4. 端口转发(本地访问 Pod/Service)

    bash

    运行

    # 将本地 8080 端口转发到 Pod 的 80 端口
    kubectl port-forward <pod名称> 8080:80 -n <命名空间>
    # 转发到 Service(更稳定,Service 会自动转发到 Pod)
    kubectl port-forward svc/<service名称> 8080:80 -n <命名空间>
    

    说明:本地调试集群内服务的常用方式,无需暴露公网地址。

五、其他高频命令
  1. 查看资源标签

    bash

    运行

    # 查看 Pod 的标签
    kubectl get pods -n <命名空间> --show-labels
    # 根据标签筛选 Pod(常用)
    kubectl get pods -n <命名空间> -l app=myapp
    

    说明:标签是 Kubernetes 资源分组的核心,常用于筛选、调度。

  2. 编辑资源(临时修改)

    bash

    运行

    kubectl edit deployment <deployment名称> -n <命名空间>
    

    说明:直接编辑资源的 YAML 配置(临时修改,推荐优先改 YAML 文件后 apply)。

  3. 查看资源的 YAML 配置

    bash

    运行

    kubectl get pod <pod名称> -n <命名空间> -o yaml
    # 仅查看关键字段(精简输出)
    kubectl get pod <pod名称> -n <命名空间> -o jsonpath='{.status.podIP}'
    
  4. 查看资源使用情况(CPU / 内存)

    bash

    运行

    # 查看节点资源使用
    kubectl top nodes
    # 查看 Pod 资源使用
    kubectl top pods -n <命名空间>
    

    说明:需集群部署 metrics-server 才能使用,排查资源不足的核心命令。

  5. 设置默认命名空间(简化命令)

    bash

    运行

    # 设置默认命名空间为 default(后续命令无需加 -n default)
    kubectl config set-context --current --namespace=default
    # 查看当前上下文
    kubectl config current-context
    
总结
  1. 核心查看类kubectl get pods/deploy/svc -A -o widekubectl describe 是日常排查的基础,优先掌握。
  2. 调试排障类kubectl logs -fkubectl exec -itkubectl port-forward 是解决 Pod 异常的核心命令。
  3. 资源管理类kubectl apply -f(创建)、kubectl set image(更新镜像)、kubectl scale(扩缩容)是运维高频操作,推荐优先用 YAML 文件管理资源。

这些命令覆盖了 90% 以上的日常 Kubernetes 操作场景,建议结合实际场景多练习,可通过 kubectl <命令> --help 查看更多参数。


3)资源开箱:只学 8 个核心对象(足够做架构)

按优先级:

  1. Pod
  2. Deployment
  3. Service
  4. Ingress
  5. ConfigMap / Secret
  6. StatefulSet(AI 训练常用)
  7. PV/PVC
  8. Job / CronJob(AI 任务调度)

学习法:每个资源只做 1 件事:写 YAML → 部署 → 看效果 → 改配置。

POD

一、第一步:编写 Pod YAML 配置文件

我们先从最简单的 Nginx 单容器 Pod 入手,这是新手最易上手的示例。

1. 创建 YAML 文件(nginx-pod.yaml)

yaml

# API 版本,K8s 1.9+ 推荐使用 v1
apiVersion: v1
# 资源类型,这里是 Pod
kind: Pod
# 元数据:Pod 名称、标签等
metadata:
  # Pod 名称(必须唯一)
  name: nginx-demo
  # 标签(用于筛选、关联其他资源)
  labels:
    app: nginx
    env: test
# 核心配置:Pod 规约(容器、资源、重启策略等)
spec:
  # 容器列表(Pod 可包含多个容器)
  containers:
  # 第一个容器(单容器 Pod 仅需这一个)
  - name: nginx-container
    # 容器镜像(默认从 Docker Hub 拉取)
    image: nginx:1.25-alpine
    # 端口配置(声明容器监听的端口,仅用于展示,非强制映射)
    ports:
    - containerPort: 80
    # 资源限制(可选,避免容器占用过多节点资源)
    resources:
      requests:
        cpu: "100m"    # 最小申请 CPU(100毫核 = 0.1核)
        memory: "128Mi" # 最小申请内存
      limits:
        cpu: "200m"    # 最大可用 CPU
        memory: "256Mi" # 最大可用内存
  # 重启策略(Always:总是重启;OnFailure:失败时重启;Never:永不重启)
  restartPolicy: Always
2. 关键配置解释
  • apiVersion + kind:固定组合,标识要创建的 K8s 资源类型(Pod 对应 v1 + Pod)。
  • metadata.name:Pod 的唯一标识,部署后不能修改。
  • spec.containers:Pod 的核心,定义容器的镜像、端口、资源等。
  • image:建议指定具体版本(如 1.25-alpine),避免拉取 latest 镜像导致版本不一致。
  • resources:新手建议配置,防止单个 Pod 占满节点资源。
二、第二步:部署 Pod 到 K8s 集群

部署前请确保:

  1. 已安装并配置好 kubectl 命令行工具。
  2. kubectl config get-contexts 能看到可用的 K8s 集群(本地可使用 Minikube、Kind 或 Docker Desktop 内置的 K8s)。
1. 执行部署命令

bash

运行

# 应用 YAML 文件创建 Pod
kubectl apply -f nginx-pod.yaml

成功输出pod/nginx-demo created

2. 验证部署是否提交

bash

运行

# 查看所有 Pod 的状态
kubectl get pods

初始状态可能是 Pending(拉取镜像),等待几秒后变为 Running 即部署成功。

三、第三步:查看 Pod 运行效果

部署成功后,通过一系列命令验证 Pod 的状态、日志、网络等,确认运行符合预期。

1. 基础状态查看

bash

运行

# 查看 Pod 详细信息(名称、状态、重启次数、所在节点)
kubectl get pod nginx-demo
# 查看 Pod 详细描述(包含事件、容器状态、IP 等)
kubectl describe pod nginx-demo

重点关注:

  • StatusRunning 表示正常运行。
  • IP:Pod 的唯一内网 IP(如 10.244.0.5)。
  • Events:无 ErrorWarning 即无异常。
2. 访问 Pod 内的 Nginx 服务

Pod 运行在 K8s 内网,有两种方式访问:

方式 1:端口转发(本地直接访问)

bash

运行

# 将本地 8080 端口转发到 Pod 的 80 端口
kubectl port-forward nginx-demo 8080:80

打开浏览器访问 http://localhost:8080,能看到 Nginx 默认页面即成功。

方式 2:进入 Pod 内部验证

bash

运行

# 进入 Pod 的容器内执行命令
kubectl exec -it nginx-demo -- /bin/sh
# 验证 Nginx 是否运行
ps aux | grep nginx
# 测试本地访问
curl http://localhost
# 退出容器
exit
3. 查看 Pod 日志

bash

运行

# 查看实时日志
kubectl logs nginx-demo -f
# 查看指定时间段的日志
kubectl logs nginx-demo --since=10m
四、第四步:修改配置并重新部署

实际开发中常需调整 Pod 配置(如镜像版本、资源限制、端口等),我们以「升级 Nginx 版本 + 调整资源限制」为例演示。

1. 修改 YAML 文件(nginx-pod.yaml)

yaml

apiVersion: v1
kind: Pod
metadata:
  name: nginx-demo
  labels:
    app: nginx
    env: test
spec:
  containers:
  - name: nginx-container
    # 1. 升级镜像版本到 1.26-alpine
    image: nginx:1.26-alpine
    ports:
    - containerPort: 80
    resources:
      requests:
        cpu: "150m"    # 2. 提高最小 CPU 申请
        memory: "128Mi"
      limits:
        cpu: "300m"    # 3. 提高最大 CPU 限制
        memory: "512Mi" # 4. 提高最大内存限制
  restartPolicy: Always
2. 注意:Pod 是「不可变资源」

K8s 不支持直接修改已运行 Pod 的核心配置(如镜像、资源限制),必须先删除旧 Pod,再重新创建:

bash

运行

# 1. 删除旧 Pod
kubectl delete pod nginx-demo
# 2. 应用修改后的 YAML 重新部署
kubectl apply -f nginx-pod.yaml
3. 验证修改效果

bash

运行

# 查看 Pod 状态
kubectl get pod nginx-demo
# 查看容器镜像是否更新
kubectl describe pod nginx-demo | grep "Image:"
# 验证 Nginx 版本
kubectl exec -it nginx-demo -- nginx -v

输出 nginx version: nginx/1.26.0 即版本升级成功。

拓展:生产环境更优方案

新手阶段用「删除重建」没问题,但生产环境建议用 Deployment 管理 Pod(支持滚动更新、回滚),只需将 YAML 中的 kind 改为 Deployment,并增加 replicas(副本数)即可,示例:

yaml

apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx-deployment
spec:
  replicas: 2 # 运行 2 个 Pod 副本
  selector:
    matchLabels:
      app: nginx
  template:
    metadata:
      labels:
        app: nginx
    spec:
      containers:
      - name: nginx-container
        image: nginx:1.26-alpine
        ports:
        - containerPort: 80

部署后修改配置可直接 kubectl apply -f xxx.yaml,Deployment 会自动滚动更新 Pod,无需手动删除。

总结
  1. 核心流程:编写 YAML(定义 Pod 规格)→ kubectl apply 部署 → kubectl get/describe/logs 验证 → 修改 YAML 后删除重建(或用 Deployment 滚动更新)。
  2. 关键特性:Pod 是 K8s 最小部署单元,不可直接修改核心配置,需重建;单容器 Pod 是最常用形式。
  3. 实用命令kubectl apply(部署)、kubectl get pods(查状态)、kubectl describe pod(查详情)、kubectl exec(进容器)、kubectl logs(看日志)。

这套流程覆盖了 Pod 从创建到修改的全生命周期,掌握后可以尝试修改更多配置(如添加环境变量、挂载存储卷),进一步加深理解。

Deploment

Deployment 是 K8s 中管理 Pod 最核心的控制器,解决了 Pod 「不可变」和「无自愈能力」的问题,我会延续「写 YAML → 部署 → 看效果 → 改配置」的流程,带你完整掌握 Deployment 的使用。

一、第一步:编写 Deployment YAML 配置文件

Deployment 本质是管理 Pod 的控制器,它会自动创建、维护指定数量的 Pod 副本,还支持滚动更新、回滚等核心能力。我们基于之前的 Nginx Pod 改造为 Deployment。

1. 创建 YAML 文件(nginx-deployment.yaml)

yaml

# API 版本:Deployment 属于 apps 组,1.9+ 推荐使用 apps/v1
apiVersion: apps/v1
# 资源类型:Deployment
kind: Deployment
# 元数据:Deployment 名称、标签
metadata:
  name: nginx-deployment
  labels:
    app: nginx
    type: deployment
# 核心配置:Deployment 规约
spec:
  # 副本数:指定要运行的 Pod 数量(核心特性)
  replicas: 2
  # 标签选择器:匹配要管理的 Pod(必须和 Pod 模板中的 labels 一致)
  selector:
    matchLabels:
      app: nginx
      env: test
  # 更新策略:默认 RollingUpdate(滚动更新),可选 Recreate(先删所有再重建)
  strategy:
    type: RollingUpdate
    rollingUpdate:
      maxSurge: 1        # 滚动更新时最多可超出的 Pod 数(1 个或 25%)
      maxUnavailable: 0  # 滚动更新时最多不可用的 Pod 数(0 表示始终保证可用)
  # Pod 模板:定义要创建的 Pod 规格(和之前的 Pod YAML 几乎一致)
  template:
    metadata:
      # Pod 的标签:必须被上面的 selector.matchLabels 匹配
      labels:
        app: nginx
        env: test
    spec:
      containers:
      - name: nginx-container
        image: nginx:1.25-alpine
        ports:
        - containerPort: 80
        resources:
          requests:
            cpu: "100m"
            memory: "128Mi"
          limits:
            cpu: "200m"
            memory: "256Mi"
      restartPolicy: Always
2. 关键配置解释(对比 Pod 的核心差异)

表格

配置项 作用
replicas: 2 自动维护 2 个 Pod 副本,若某个 Pod 挂了,Deployment 会自动重建
selector.matchLabels 关联 Deployment 和 Pod,必须和 template.metadata.labels 完全匹配
strategy 滚动更新策略:保证更新过程中服务不中断(生产环境核心需求)
template 嵌套的 Pod 模板:Deployment 会根据这个模板创建 / 重建 Pod
二、第二步:部署 Deployment 到 K8s 集群

部署前仍需确保 kubectl 已连接 K8s 集群(Minikube/Kind/Docker Desktop)。

1. 执行部署命令

bash

运行

# 应用 YAML 文件创建 Deployment
kubectl apply -f nginx-deployment.yaml

成功输出deployment.apps/nginx-deployment created

2. 验证部署提交

bash

运行

# 查看 Deployment 状态
kubectl get deployments
# 简写:kubectl get deploy

输出示例(READY 为 2/2 表示所有 Pod 已就绪):

plaintext

NAME               READY   UP-TO-DATE   AVAILABLE   AGE
nginx-deployment   2/2     2            2           10s
三、第三步:查看 Deployment 运行效果

Deployment 的核心价值是「管理 Pod」,所以除了看 Deployment 本身,重点要验证它对 Pod 的管控能力。

1. 查看 Deployment 详情

bash

运行

# 查看 Deployment 详细信息(包含事件、更新策略、Pod 模板等)
kubectl describe deployment nginx-deployment

重点关注:

  • Replicas:Desired(期望)2 → Current(当前)2 → Ready(就绪)2。
  • Events:无 Error/Warning,且有 SuccessfulCreate 事件(表示成功创建 Pod)。
2. 查看 Deployment 管理的 Pod

bash

运行

# 查看所有 Pod(会看到 2 个以 nginx-deployment-xxx 命名的 Pod)
kubectl get pods -l app=nginx  # 通过标签筛选 Deployment 管理的 Pod

输出示例(Pod 名称包含随机后缀,由 Deployment 自动生成):

plaintext

NAME                                READY   STATUS    RESTARTS   AGE
nginx-deployment-7f987d6c74-2x89s   1/1     Running   0          30s
nginx-deployment-7f987d6c74-9k75b   1/1     Running   0          30s
3. 验证 Deployment 的「自愈能力」

这是 Deployment 对比原生 Pod 的核心优势:手动删除一个 Pod,Deployment 会自动重建。

bash

运行

# 手动删除其中一个 Pod(替换为你的 Pod 名称)
kubectl delete pod nginx-deployment-7f987d6c74-2x89s
# 立即查看 Pod 状态
kubectl get pods -l app=nginx

你会发现:被删除的 Pod 状态变为 Terminating,同时会立即出现一个新的 Pod(名称不同),最终仍保持 2 个运行中的 Pod 副本。

4. 访问 Pod 内的 Nginx 服务

和之前一样,用端口转发访问(任选一个 Pod 即可):

bash

运行

kubectl port-forward nginx-deployment-7f987d6c74-9k75b 8080:80

访问 http://localhost:8080 即可看到 Nginx 默认页面。

四、第四步:修改配置并重新部署

Deployment 最大的优势是支持无中断的滚动更新,无需手动删除 Pod,直接修改 YAML 后重新 apply 即可。我们以「升级 Nginx 版本 + 调整副本数」为例。

1. 修改 YAML 文件(nginx-deployment.yaml)

yaml

apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx-deployment
  labels:
    app: nginx
    type: deployment
spec:
  replicas: 3  # 1. 副本数从 2 增加到 3
  selector:
    matchLabels:
      app: nginx
      env: test
  strategy:
    type: RollingUpdate
    rollingUpdate:
      maxSurge: 1
      maxUnavailable: 0
  template:
    metadata:
      labels:
        app: nginx
        env: test
    spec:
      containers:
      - name: nginx-container
        image: nginx:1.26-alpine  # 2. 镜像版本从 1.25 升级到 1.26
        ports:
        - containerPort: 80
        resources:
          requests:
            cpu: "100m"
            memory: "128Mi"
          limits:
            cpu: "200m"
            memory: "256Mi"
      restartPolicy: Always
2. 应用修改后的配置(滚动更新)

bash

运行

# 直接 apply,Deployment 会自动执行滚动更新
kubectl apply -f nginx-deployment.yaml

成功输出deployment.apps/nginx-deployment configured

3. 查看更新过程

bash

运行

# 实时查看 Deployment 状态(watch 表示实时刷新)
kubectl get deploy nginx-deployment -w
# 查看 Pod 滚动更新过程
kubectl get pods -l app=nginx -w

你会看到:

  • 先创建新的 Pod(使用 1.26 镜像)→ 新 Pod 就绪后,删除旧 Pod(1.25 镜像)→ 最终保留 3 个新 Pod。
  • 整个过程中始终有至少 2 个 Pod 运行,服务不中断(因为 maxUnavailable: 0)。
4. 验证更新效果

bash

运行

# 查看 Deployment 副本数是否为 3
kubectl get deploy nginx-deployment
# 验证 Pod 镜像版本
kubectl exec -it $(kubectl get pod -l app=nginx -o jsonpath="{.items[0].metadata.name}") -- nginx -v

输出 nginx version: nginx/1.26.0 即版本升级成功,且 Pod 数量为 3。

拓展:Deployment 回滚(生产必备)

如果更新后发现问题,可快速回滚到上一个版本:

bash

运行

# 查看 Deployment 版本历史
kubectl rollout history deployment/nginx-deployment
# 回滚到上一个版本
kubectl rollout undo deployment/nginx-deployment
# 验证回滚结果(镜像回到 1.25-alpine,副本数回到 2)
kubectl describe deployment nginx-deployment | grep "Image:"
总结
  1. 核心定位:Deployment 是 K8s 管理 Pod 的首选控制器,解决了 Pod 「不可变」「无自愈」「更新易中断」的问题。
  2. 核心流程:写 Deployment YAML(包含 Pod 模板 + 副本数 + 更新策略)→ kubectl apply 部署 → 验证 Pod 副本数和自愈能力 → 修改配置后 kubectl apply 实现滚动更新(支持回滚)。
  3. 关键优势:自动维护 Pod 副本数、滚动更新不中断服务、支持版本回滚,是生产环境部署应用的标准方式(而非直接创建 Pod)。

掌握这套流程后,你可以尝试修改更多配置(如更新策略、添加环境变量),或结合 Service 暴露 Deployment 管理的 Pod 服务,进一步贴近生产场景。

Service

Service 解决了 Deployment 管理的 Pod 「IP 动态变化」「无法统一访问」的问题,是 K8s 中暴露应用服务的标准方式。我依然按「写 YAML → 部署 → 看效果 → 改配置」的流程,带你完整掌握 Service 的使用,且和之前的 Deployment 无缝衔接。

一、第一步:编写 Service YAML 配置文件

Service 本质是固定访问入口 + 负载均衡器,通过标签选择器关联 Deployment 管理的 Pod,无论 Pod 如何重建、IP 如何变化,Service 的访问地址始终不变。

我们基于之前的 nginx-deployment 创建对应的 Service(以最常用的 ClusterIP 类型为例,后续拓展其他类型)。

1. 创建 YAML 文件(nginx-service.yaml)

yaml

# API 版本:Service 属于核心组,使用 v1
apiVersion: v1
# 资源类型:Service
kind: Service
# 元数据:Service 名称、标签
metadata:
  name: nginx-service
  labels:
    app: nginx
    type: service
# 核心配置:Service 规约
spec:
  # Service 类型(核心):
  # - ClusterIP:仅集群内可访问(默认)
  # - NodePort:集群内 + 节点端口访问
  # - LoadBalancer:云厂商提供外部负载均衡器
  # - ExternalName:映射到外部域名
  type: ClusterIP
  # 标签选择器:匹配要关联的 Pod(必须和 Deployment 的 Pod 模板 labels 一致)
  selector:
    app: nginx
    env: test
  # 端口映射:Service 端口 → Pod 容器端口
  ports:
  - name: http  # 端口名称(可选,建议配置,便于区分)
    protocol: TCP  # 协议(TCP/UDP,默认 TCP)
    port: 80  # Service 暴露的端口(集群内访问用这个端口)
    targetPort: 80  # Pod 容器的端口(必须和容器监听的端口一致)
  # sessionAffinity: ClientIP  # 可选,会话亲和性(同一客户端始终访问同一个 Pod)
2. 关键配置解释(和 Deployment 关联的核心)

表格

配置项 作用
type: ClusterIP 最基础的 Service 类型,分配一个集群内唯一的虚拟 IP(ClusterIP),仅集群内可访问
selector 核心!通过标签匹配 Deployment 管理的 Pod,必须和 Pod 的 labels 完全匹配
ports.port Service 自身的端口(集群内访问 Service 时用这个端口)
ports.targetPort 映射到 Pod 容器的端口(必须和容器的 containerPort 一致)
二、第二步:部署 Service 到 K8s 集群

部署前确保:

  1. 之前的 nginx-deployment 已正常运行(有 3 个 Pod 副本)。
  2. kubectl 已连接 K8s 集群。
1. 执行部署命令

bash

运行

# 应用 YAML 文件创建 Service
kubectl apply -f nginx-service.yaml

成功输出service/nginx-service created

2. 验证部署提交

bash

运行

# 查看 Service 状态
kubectl get services
# 简写:kubectl get svc

输出示例(重点看 CLUSTER-IPPORT(S)):

plaintext

NAME            TYPE        CLUSTER-IP      EXTERNAL-IP   PORT(S)   AGE
kubernetes      ClusterIP   10.96.0.1       <none>        443/TCP   1d
nginx-service   ClusterIP   10.96.123.45    <none>        80/TCP    10s
三、第三步:查看 Service 运行效果

Service 的核心价值是「固定访问入口 + 负载均衡」,我们从集群内、集群外两个维度验证效果。

1. 查看 Service 详情

bash

运行

# 查看 Service 详细信息(包含关联的 Pod、ClusterIP 等)
kubectl describe service nginx-service

重点关注:

  • Selectorapp=nginx,env=test(和 Deployment 的 Pod 标签匹配)。
  • Endpoints:列出关联的所有 Pod 的 IP + 端口(如 10.244.0.5:80,10.244.0.6:80,10.244.0.7:80),表示 Service 已成功关联 Pod。
  • ClusterIP:Service 的虚拟 IP(如 10.96.123.45),集群内可通过这个 IP+80 端口访问。
2. 验证集群内访问(核心)

Service 的 ClusterIP 仅集群内可访问,我们通过「临时 Pod」模拟集群内访问:

bash

运行

# 创建一个临时的 busybox Pod,用于测试访问
kubectl run test-pod --image=busybox:1.36 --rm -it -- /bin/sh
# 进入 Pod 后,执行以下命令访问 Service
wget -q -O - http://nginx-service:80  # 用 Service 名称访问(K8s 内置 DNS 解析)
# 或用 ClusterIP 访问
wget -q -O - http://10.96.123.45:80

输出 Nginx 默认页面的 HTML 内容,说明访问成功!且多次执行会发现请求被负载均衡到不同的 Pod(可通过 Pod 日志验证)。

3. 验证「IP 变化不影响访问」(Service 核心优势)

手动删除一个 Pod,Deployment 会重建新 Pod(IP 变化),但 Service 会自动更新 Endpoints,访问不受影响:

bash

运行

# 1. 删除一个 Pod(替换为你的 Pod 名称)
kubectl delete pod nginx-deployment-7f987d6c74-2x89s
# 2. 等待新 Pod 创建完成
kubectl get pods -l app=nginx
# 3. 再次用 test-pod 访问 Service
wget -q -O - http://nginx-service:80

依然能正常访问,说明 Service 自动感知了 Pod 的变化。

四、第四步:修改配置(切换 Service 类型)

实际场景中,常需要将 Service 从「仅集群内访问」改为「对外暴露」,我们以切换为 NodePort 类型为例(适合测试 / 小规模场景)。

1. 修改 YAML 文件(nginx-service.yaml)

yaml

apiVersion: v1
kind: Service
metadata:
  name: nginx-service
  labels:
    app: nginx
    type: service
spec:
  type: NodePort  # 1. 改为 NodePort 类型
  selector:
    app: nginx
    env: test
  ports:
  - name: http
    protocol: TCP
    port: 80
    targetPort: 80
    nodePort: 30080  # 2. 指定节点端口(可选,范围 30000-32767)
2. 应用修改后的配置

bash

运行

# 直接 apply,Service 会自动更新类型
kubectl apply -f nginx-service.yaml

成功输出service/nginx-service configured

3. 验证 NodePort 访问

bash

运行

# 查看 Service 状态,确认 NodePort 已分配
kubectl get svc nginx-service

输出示例(PORT(S) 列显示 80:30080/TCP):

plaintext

NAME            TYPE       CLUSTER-IP      EXTERNAL-IP   PORT(S)        AGE
nginx-service   NodePort   10.96.123.45    <none>        80:30080/TCP   5m

现在可以通过「节点 IP + 30080 端口」访问 Nginx:

  • 如果是 Minikube:先执行 minikube ip 获取节点 IP,然后访问 http://<minikube-ip>:30080
  • 如果是 Docker Desktop:直接访问 http://localhost:30080
  • 如果是云服务器集群:访问 http://<节点公网IP>:30080
拓展:生产环境常用 Service 类型

表格

类型 适用场景 访问方式
ClusterIP 集群内服务间通信(默认) 集群内 Pod 访问 Service 名称 / IP
NodePort 测试 / 小流量对外暴露 节点 IP + 固定端口
LoadBalancer 生产环境对外暴露(云厂商) 云厂商分配的外部 IP
Ingress 多服务统一入口(替代 LB) 域名 + HTTP/HTTPS(需部署 Ingress Controller)
总结
  1. 核心定位:Service 是 K8s 中应用服务的「固定访问入口」,解决了 Pod IP 动态变化、无法统一访问的问题,且内置负载均衡能力。
  2. 核心流程:写 Service YAML(指定类型 + 标签选择器 + 端口映射)→ kubectl apply 部署 → 验证集群内 / 外访问 → 修改配置切换 Service 类型(如 ClusterIP → NodePort)。
  3. 关键关联:Service 通过 selector 与 Deployment/Pod 关联,无需手动绑定,Pod 变化时 Service 自动更新 Endpoints,保证访问不中断。

至此,你已掌握 K8s 应用部署的核心三件套:Deployment(管理 Pod) + Service(暴露服务) + Pod(运行容器),这是 K8s 部署无状态应用的标准架构。接下来可以尝试结合 Ingress 实现域名访问,或部署有状态应用(StatefulSet),进一步完善 K8s 知识体系。

Ingress

Ingress 解决了 Service(尤其是 NodePort/LoadBalancer)「端口有限」「无域名 / 路径路由」「无 HTTPS 支持」的问题,是 K8s 中多服务统一入口的标准方案。我依然按「写 YAML → 部署 → 看效果 → 改配置」的流程,带你完整掌握 Ingress,且和之前的 Deployment + Service 无缝衔接。

一、前置说明

Ingress 分为两部分:

  1. Ingress 资源:定义路由规则(域名、路径 → Service)。
  2. Ingress Controller:执行路由规则的组件(如 Nginx Ingress Controller),需先部署,否则 Ingress 资源仅为「空规则」。

我们先部署 Ingress Controller(以最常用的 Nginx Ingress 为例),再编写 Ingress 规则。

二、第一步:部署 Ingress Controller + 编写 Ingress YAML
1. 部署 Nginx Ingress Controller(环境适配)

不同环境部署命令不同,选择对应方式:

bash

运行

# 方式 1:Minikube(一键部署)
minikube addons enable ingress

# 方式 2:Docker Desktop/K8s 集群(官方推荐,适用于 1.19+)
kubectl apply -f https://raw.githubusercontent.com/kubernetes/ingress-nginx/controller-v1.11.0/deploy/static/provider/cloud/deploy.yaml

# 验证 Controller 运行(等待 STATUS 为 Running)
kubectl get pods -n ingress-nginx
2. 编写 Ingress YAML 配置文件(nginx-ingress.yaml)

基于之前的 nginx-service 创建 Ingress 规则,实现「域名访问 → Service → Pod」的路由:

yaml

# API 版本:Ingress 属于 networking.k8s.io 组,1.19+ 推荐 v1
apiVersion: networking.k8s.io/v1
# 资源类型:Ingress
kind: Ingress
# 元数据:Ingress 名称、注解(核心!用于配置 Ingress Controller 特性)
metadata:
  name: nginx-ingress
  labels:
    app: nginx
  # 注解:针对 Nginx Ingress Controller 的配置(如默认后端、SSL、重定向等)
  annotations:
    # 指定使用 Nginx Ingress Controller(多 Controller 时必须)
    kubernetes.io/ingress.class: "nginx"
    # 可选:将 HTTP 重定向到 HTTPS(后续配置证书后启用)
    # nginx.ingress.kubernetes.io/ssl-redirect: "true"
    # 可选:设置客户端请求超时时间
    nginx.ingress.kubernetes.io/proxy-connect-timeout: "30s"
# 核心配置:Ingress 规则
spec:
  # 规则列表(可配置多个域名)
  rules:
  # 第一个域名规则
  - host: nginx.example.com  # 访问域名(需配置本地 hosts 解析)
    http:
      paths:
      # 路径规则 1:根路径 → nginx-service
      - path: /
        pathType: Prefix  # 路径匹配类型:Prefix(前缀匹配)/ Exact(精确匹配)
        backend:
          service:
            # 关联的 Service 名称
            name: nginx-service
            # 关联的 Service 端口
            port:
              number: 80
  # 可选:添加第二个域名/路径规则(演示多服务路由)
  # - host: app.example.com
  #   http:
  #     paths:
  #     - path: /app
  #       pathType: Prefix
  #       backend:
  #         service:
  #           name: app-service
  #           port:
  #             number: 8080
  # 可选:配置 HTTPS 证书(需先创建 Secret 存储证书)
  # tls:
  # - hosts:
  #   - nginx.example.com
  #   secretName: nginx-tls-secret
3. 关键配置解释

表格

配置项 作用
annotations 针对 Ingress Controller 的自定义配置,不同 Controller 注解不同(如 Nginx vs Traefik)
rules.host 访问域名(如 nginx.example.com),需在本地 hosts 或 DNS 解析到 Ingress Controller 的 IP
paths.path 域名下的路径(如 /),支持前缀 / 精确匹配
paths.backend 路由目标:关联的 Service 名称 + 端口,Ingress 会将请求转发到该 Service
pathType 匹配规则:Prefix(前缀匹配,如 / 匹配所有路径)、Exact(精确匹配,如 / 仅匹配根路径)
三、第二步:部署 Ingress 并配置域名解析
1. 部署 Ingress 资源

bash

运行

# 应用 YAML 文件创建 Ingress
kubectl apply -f nginx-ingress.yaml

成功输出ingress.networking.k8s.io/nginx-ingress created

2. 配置本地域名解析(关键)

Ingress 的 hostnginx.example.com,需将该域名解析到 Ingress Controller 的 IP:

bash

运行

# 步骤 1:获取 Ingress Controller 的 IP
# Minikube 环境
minikube ip  # 输出如 192.168.49.2
# Docker Desktop 环境
kubectl get svc ingress-nginx-controller -n ingress-nginx  # 查看 EXTERNAL-IP(通常是 localhost/127.0.0.1)
# 云服务器集群
kubectl get svc ingress-nginx-controller -n ingress-nginx  # 查看 EXTERNAL-IP(云厂商分配的公网 IP)

# 步骤 2:修改本地 hosts 文件(Windows: C:\Windows\System32\drivers\etc\hosts;Linux/Mac: /etc/hosts)
# 添加一行:Ingress Controller IP + 域名
# 示例:
192.168.49.2 nginx.example.com
四、第三步:查看 Ingress 运行效果
1. 查看 Ingress 状态

bash

运行

# 查看 Ingress 资源
kubectl get ingress
# 简写:kubectl get ing

输出示例(HOSTS 为配置的域名,ADDRESS 为 Ingress Controller IP):

plaintext

NAME           CLASS   HOSTS              ADDRESS        PORTS   AGE
nginx-ingress  nginx   nginx.example.com  192.168.49.2   80      10s
2. 验证域名访问(核心)

bash

运行

# 方式 1:curl 访问(直接验证路由)
curl http://nginx.example.com

# 方式 2:浏览器访问
# 打开 http://nginx.example.com,能看到 Nginx 默认页面即成功

此时请求流程:浏览器/客户端 → nginx.example.com → Ingress Controller → nginx-service → 负载均衡到 Pod

3. 验证「多路径 / 多服务路由」(拓展)

如果添加了第二个路径规则(如 /appapp-service),可验证:

bash

运行

curl http://nginx.example.com/app

请求会被 Ingress 路由到 app-service 对应的 Pod,实现「一个域名 + 不同路径 → 不同服务」的核心能力。

五、第四步:修改配置(添加 HTTPS 支持)

生产环境中,Ingress 最常用的扩展是配置 HTTPS,我们以「自签名证书」为例演示(生产需用 Let's Encrypt 等合法证书)。

1. 生成自签名证书并创建 Secret

bash

运行

# 生成自签名证书(替换域名为 nginx.example.com)
openssl req -x509 -nodes -days 365 -newkey rsa:2048 \
  -keyout tls.key -out tls.crt \
  -subj "/CN=nginx.example.com/O=nginx-example"

# 创建 K8s Secret 存储证书(名称需和 Ingress 的 tls.secretName 一致)
kubectl create secret tls nginx-tls-secret --key tls.key --cert tls.crt
2. 修改 Ingress YAML(启用 HTTPS)

yaml

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: nginx-ingress
  labels:
    app: nginx
  annotations:
    kubernetes.io/ingress.class: "nginx"
    nginx.ingress.kubernetes.io/ssl-redirect: "true"  # 强制 HTTP 重定向到 HTTPS
spec:
  rules:
  - host: nginx.example.com
    http:
      paths:
      - path: /
        pathType: Prefix
        backend:
          service:
            name: nginx-service
            port:
              number: 80
  # 添加 TLS 配置
  tls:
  - hosts:
    - nginx.example.com  # 证书对应的域名
    secretName: nginx-tls-secret  # 存储证书的 Secret 名称
3. 应用修改并验证 HTTPS 访问

bash

运行

# 应用更新后的 Ingress 配置
kubectl apply -f nginx-ingress.yaml

# 验证 HTTPS 访问(-k 忽略自签名证书警告)
curl -k https://nginx.example.com

此时访问 http://nginx.example.com 会自动重定向到 https://nginx.example.com,实现 HTTPS 访问。

总结
  1. 核心定位:Ingress 是 K8s 多服务的「统一入口」,解决了 Service 无域名 / 路径路由、无 HTTPS 的问题,由「Ingress 资源(规则) + Ingress Controller(执行)」组成。
  2. 核心流程:部署 Ingress Controller → 编写 Ingress YAML(定义域名 / 路径 → Service 路由规则)→ 配置域名解析 → 验证域名访问 → 修改配置启用 HTTPS 等高级特性。
  3. 关键优势:支持域名 / 路径路由、HTTPS、请求重定向、负载均衡,是生产环境暴露多服务的标准方案(替代多个 NodePort/LoadBalancer Service)。

至此,你已掌握 K8s 无状态应用部署的完整架构:Pod(运行容器) → Deployment(管理 Pod) → Service(固定访问入口) → Ingress(统一域名入口)。这是 K8s 最核心、最常用的部署模式,后续可进一步学习 StatefulSet(有状态应用)、ConfigMap/Secret(配置管理)等进阶内容。

ConfigMap

ConfigMap 解决了「配置和容器镜像解耦」的问题,能将配置文件、环境变量等抽离出来,避免修改配置时重新构建镜像。我依然按「写 YAML → 部署 → 看效果 → 改配置」的流程,结合之前的 Nginx Deployment 来讲解,让你直观理解 ConfigMap 的使用场景和价值。

一、第一步:编写 ConfigMap YAML 配置文件

ConfigMap 本质是K8s 中存储非敏感配置的键值对资源,支持两种存储形式:

  1. 键值对形式(适合零散配置,如环境变量);
  2. 文件形式(适合完整配置文件,如 Nginx 配置、应用配置文件)。

我们以「替换 Nginx 默认配置」为例,编写 ConfigMap YAML(覆盖 Nginx 的默认首页和基础配置)。

1. 创建 ConfigMap YAML 文件(nginx-configmap.yaml)

yaml

# API 版本:ConfigMap 属于核心组,使用 v1
apiVersion: v1
# 资源类型:ConfigMap
kind: ConfigMap
# 元数据:ConfigMap 名称、标签
metadata:
  name: nginx-config
  labels:
    app: nginx
# 核心配置:配置数据(键值对/文件内容)
data:
  # 形式 1:零散键值对(可作为环境变量注入 Pod)
  nginx_port: "80"
  nginx_worker_processes: "auto"
  
  # 形式 2:完整配置文件(键为文件名,值为文件内容)
  default.conf: |
    server {
        listen       ${NGINX_PORT};  # 引用环境变量(需配合 envsubst)
        server_name  localhost;

        # 修改默认首页
        location / {
            root   /usr/share/nginx/html;
            index  index.html index.htm;
        }

        # 新增健康检查接口
        location /health {
            access_log off;
            return 200 '{"status":"ok"}';
            add_header Content-Type application/json;
        }
    }
  
  # 自定义 Nginx 首页内容
  index.html: |
    <!DOCTYPE html>
    <html>
    <head>
        <title>ConfigMap Demo</title>
        <meta charset="utf-8">
    </head>
    <body>
        <h1>Hello from ConfigMap!</h1>
        <p>This page is loaded from K8s ConfigMap.</p>
    </body>
    </html>
2. 关键配置解释

表格

配置项 作用
data ConfigMap 的核心,存储所有配置数据,支持「键值对」和「多行文本(文件)」两种形式
key: "value" 零散键值对:适合作为环境变量注入 Pod,如 nginx_port: "80"
`filename: ` 多行文本:模拟配置文件,键为文件名(如 default.conf),值为文件内容
` ` 符号 保留多行文本的格式(换行、缩进),确保配置文件语法正确
二、第二步:部署 ConfigMap + 修改 Deployment 挂载配置

ConfigMap 本身不运行,需通过「环境变量」或「挂载卷」的方式注入到 Pod 中,我们结合之前的 Nginx Deployment 来演示。

1. 部署 ConfigMap

bash

运行

# 应用 YAML 创建 ConfigMap
kubectl apply -f nginx-configmap.yaml

成功输出configmap/nginx-config created

2. 验证 ConfigMap 部署

bash

运行

# 查看 ConfigMap 列表
kubectl get configmaps
# 简写:kubectl get cm

# 查看 ConfigMap 详情(验证配置内容)
kubectl describe cm nginx-config
3. 修改 Deployment YAML(挂载 ConfigMap 到 Pod)

修改之前的 nginx-deployment.yaml,添加「环境变量注入」和「配置文件挂载」:

yaml

apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx-deployment
spec:
  replicas: 2
  selector:
    matchLabels:
      app: nginx
      env: test
  template:
    metadata:
      labels:
        app: nginx
        env: test
    spec:
      containers:
      - name: nginx-container
        image: nginx:1.26-alpine
        ports:
        - containerPort: 80
        # 方式 1:从 ConfigMap 注入环境变量
        env:
        - name: NGINX_PORT  # Pod 内的环境变量名
          valueFrom:
            configMapKeyRef:
              name: nginx-config  # 关联的 ConfigMap 名称
              key: nginx_port     # 要引用的 ConfigMap 键
        # 方式 2:挂载 ConfigMap 为文件(覆盖 Nginx 配置和首页)
        volumeMounts:
        # 挂载自定义 Nginx 配置文件
        - name: nginx-conf-volume
          mountPath: /etc/nginx/conf.d/default.conf  # 覆盖默认配置文件
          subPath: default.conf  # 指定 ConfigMap 中的键(文件名)
        # 挂载自定义首页
        - name: nginx-html-volume
          mountPath: /usr/share/nginx/html/index.html  # 覆盖默认首页
          subPath: index.html
        resources:
          requests:
            cpu: "100m"
            memory: "128Mi"
          limits:
            cpu: "200m"
            memory: "256Mi"
      # 定义要挂载的卷(关联 ConfigMap)
      volumes:
      - name: nginx-conf-volume
        configMap:
          name: nginx-config  # 关联的 ConfigMap 名称
          items:
          - key: default.conf  # ConfigMap 中的键
            path: default.conf # 卷内的文件名(和 subPath 对应)
      - name: nginx-html-volume
        configMap:
          name: nginx-config
          items:
          - key: index.html
            path: index.html
4. 重新部署 Deployment

bash

运行

# 应用修改后的 Deployment 配置(触发滚动更新)
kubectl apply -f nginx-deployment.yaml
三、第三步:查看 ConfigMap 运行效果

验证 ConfigMap 中的配置是否成功注入 Pod 并生效。

1. 验证环境变量注入

bash

运行

# 进入任意一个 Nginx Pod
kubectl exec -it $(kubectl get pod -l app=nginx -o jsonpath="{.items[0].metadata.name}") -- /bin/sh

# 查看环境变量
echo $NGINX_PORT
# 输出:80(和 ConfigMap 中的 nginx_port 一致)

# 退出 Pod
exit
2. 验证配置文件挂载(自定义首页)

通过之前的 Ingress/Service 访问 Nginx:

bash

运行

# 方式 1:通过 Service 访问
curl http://nginx-service

# 方式 2:通过 Ingress 域名访问
curl http://nginx.example.com

输出内容应为 ConfigMap 中定义的自定义首页:

html

预览

<!DOCTYPE html>
<html>
<head>
    <title>ConfigMap Demo</title>
    <meta charset="utf-8">
</head>
<body>
    <h1>Hello from ConfigMap!</h1>
    <p>This page is loaded from K8s ConfigMap.</p>
</body>
</html>
3. 验证健康检查接口(自定义 Nginx 配置)

bash

运行

curl http://nginx.example.com/health
# 输出:{"status":"ok"}

说明 ConfigMap 中的 default.conf 已成功覆盖 Nginx 默认配置。

四、第四步:修改 ConfigMap 并验证热更新

ConfigMap 支持「热更新」(部分场景无需重启 Pod),我们修改首页内容,验证配置生效。

1. 修改 ConfigMap YAML(更新 index.html 内容)

yaml

apiVersion: v1
kind: ConfigMap
metadata:
  name: nginx-config
data:
  nginx_port: "80"
  nginx_worker_processes: "auto"
  default.conf: |
    # 保持不变
    server {
        listen       ${NGINX_PORT};
        server_name  localhost;
        location / {
            root   /usr/share/nginx/html;
            index  index.html index.htm;
        }
        location /health {
            access_log off;
            return 200 '{"status":"ok"}';
            add_header Content-Type application/json;
        }
    }
  index.html: |
    <!DOCTYPE html>
    <html>
    <head>
        <title>ConfigMap Updated</title>
        <meta charset="utf-8">
    </head>
    <body>
        <h1>ConfigMap Updated!</h1>
        <p>This page is updated from ConfigMap (hot reload).</p>
    </body>
    </html>
2. 应用 ConfigMap 修改

bash

运行

kubectl apply -f nginx-configmap.yaml
3. 验证热更新效果

bash

运行

# 等待 10 秒(ConfigMap 同步到 Pod 有延迟)
sleep 10

# 再次访问首页
curl http://nginx.example.com

输出内容会变为修改后的新首页,无需重启 Pod(因为是通过「文件挂载」方式,Nginx 会自动读取新文件;若为环境变量注入,需重启 Pod 才生效)。

拓展:ConfigMap 热更新说明

表格

注入方式 热更新是否生效 生效方式
文件挂载 ConfigMap 修改后,Pod 内文件自动更新(应用需支持读取最新文件)
环境变量注入 需重启 Pod 或滚动更新 Deployment
总结
  1. 核心定位:ConfigMap 是 K8s 管理「非敏感配置」的核心资源,实现「配置和镜像解耦」,避免修改配置时重建镜像。
  2. 核心流程:编写 ConfigMap YAML(存储键值对 / 配置文件)→ 部署 ConfigMap → 修改 Deployment 以「环境变量」或「文件挂载」方式注入 → 验证配置生效 → 修改 ConfigMap 实现热更新(文件挂载方式)。
  3. 关键注意:ConfigMap 不存储敏感信息(如密码、密钥),敏感信息需用 Secret 管理;文件挂载支持热更新,环境变量需重启 Pod 生效。

至此,你已掌握 K8s 配置管理的基础方案,接下来可学习 Secret(敏感配置)、Volume(存储)等进阶内容,进一步完善配置和存储管理体系。

Secret

Secret 解决了 ConfigMap 「不适合存储敏感信息」的问题,专门用来存放密码、密钥、证书、Token 等敏感数据,且会以加密形式存储(相比 ConfigMap 的明文存储更安全)。我依然按「写 YAML → 部署 → 看效果 → 改配置」的流程,结合之前的 Nginx 示例讲解,让你清晰区分 Secret 和 ConfigMap 的使用场景。

一、第一步:编写 Secret YAML 配置文件

Secret 本质是K8s 中存储敏感键值对的资源,核心特性是:

  1. 数据会被 Base64 编码(注意:Base64 是编码而非加密,生产需开启 K8s 静态加密);
  2. 支持三种常用类型:Opaque(通用键值对)、kubernetes.io/tls(TLS 证书)、kubernetes.io/dockerconfigjson(镜像仓库凭证)。

我们以「存储 Nginx 基础认证密码 + TLS 证书」为例,编写 Secret YAML。

1. 准备敏感数据(Base64 编码)

Secret 的 data 字段要求值为 Base64 编码字符串,先手动编码测试数据:

bash

运行

# 编码用户名(admin)
echo -n "admin" | base64  # 输出:YWRtaW4=
# 编码密码(123456)
echo -n "123456" | base64  # 输出:MTIzNDU2
2. 创建 Secret YAML 文件(nginx-secret.yaml)

yaml

# API 版本:Secret 属于核心组,使用 v1
apiVersion: v1
# 资源类型:Secret
kind: Secret
# 元数据:Secret 名称、标签
metadata:
  name: nginx-secret
  labels:
    app: nginx
# Secret 类型:Opaque 为通用类型(默认)
type: Opaque
# 核心配置:敏感数据(Base64 编码的键值对)
data:
  # 基础认证的用户名(Base64 编码:admin → YWRtaW4=)
  auth_user: YWRtaW4=
  # 基础认证的密码(Base64 编码:123456 → MTIzNDU2)
  auth_pass: MTIzNDU2
# 可选:stringData(明文输入,K8s 会自动编码为 Base64,适合手动编写)
# stringData:
#   auth_user: admin
#   auth_pass: 123456
3. 关键配置解释

表格

配置项 作用
type: Opaque 通用 Secret 类型,适用于大部分键值对场景;若存储 TLS 证书,需用 kubernetes.io/tls
data 存储 Base64 编码的敏感数据(必须编码),生产推荐用这个字段
stringData 存储明文敏感数据(K8s 自动编码),适合测试 / 手动编写,优先级高于 data
安全性提示 Base64 编码可被反向解码(`echo"YWRtaW4=" base64 -d`),生产需开启 K8s APIServer 的静态加密功能
二、第二步:部署 Secret + 修改 Deployment 挂载 / 注入

和 ConfigMap 类似,Secret 需通过「环境变量」或「文件挂载」注入 Pod,我们基于之前的 Nginx Deployment 改造,添加「基础认证」功能(使用 Secret 中的用户名密码)。

1. 部署 Secret

bash

运行

# 应用 YAML 创建 Secret
kubectl apply -f nginx-secret.yaml

成功输出secret/nginx-secret created

2. 验证 Secret 部署

bash

运行

# 查看 Secret 列表
kubectl get secrets
# 简写:kubectl get secret

# 查看 Secret 详情(K8s 会隐藏 data 字段的具体值,保证安全)
kubectl describe secret nginx-secret

注意:kubectl describe 不会显示 Base64 编码的具体值,需用 kubectl get secret nginx-secret -o yaml 查看(仅测试环境使用)。

3. 修改 ConfigMap + Deployment(集成 Secret 实现基础认证)
步骤 1:更新 ConfigMap(添加 Nginx 基础认证配置)

修改 nginx-configmap.yaml,新增基础认证规则:

yaml

apiVersion: v1
kind: ConfigMap
metadata:
  name: nginx-config
data:
  nginx_port: "80"
  nginx_worker_processes: "auto"
  default.conf: |
    server {
        listen       ${NGINX_PORT};
        server_name  localhost;

        # 启用基础认证
        auth_basic "Restricted Access";
        auth_basic_user_file /etc/nginx/conf.d/.htpasswd;

        location / {
            root   /usr/share/nginx/html;
            index  index.html index.htm;
        }

        location /health {
            access_log off;
            return 200 '{"status":"ok"}';
            add_header Content-Type application/json;
        }
    }
  index.html: |
    <!DOCTYPE html>
    <html>
    <head>
        <title>ConfigMap Demo</title>
        <meta charset="utf-8">
    </head>
    <body>
        <h1>Hello from ConfigMap!</h1>
        <p>This page is loaded from K8s ConfigMap.</p>
    </body>
    </html>
步骤 2:更新 Deployment(挂载 Secret 并生成认证文件)

修改 nginx-deployment.yaml,添加 Secret 挂载 + 初始化脚本生成 .htpasswd 文件:

yaml

apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx-deployment
spec:
  replicas: 2
  selector:
    matchLabels:
      app: nginx
      env: test
  template:
    metadata:
      labels:
        app: nginx
        env: test
    spec:
      initContainers:
      # 初始化容器:生成 Nginx 基础认证文件(使用 Secret 中的用户名密码)
      - name: create-htpasswd
        image: nginx:1.26-alpine
        command:
        - /bin/sh
        - -c
        - |
          # 从 Secret 挂载的文件中读取用户名和密码(Base64 解码)
          USER=$(cat /etc/secret/auth_user | base64 -d)
          PASS=$(cat /etc/secret/auth_pass | base64 -d)
          # 生成 .htpasswd 文件(nginx 基础认证格式)
          htpasswd -bc /etc/nginx/conf.d/.htpasswd $USER $PASS
        # 挂载 Secret 到初始化容器
        volumeMounts:
        - name: nginx-secret-volume
          mountPath: /etc/secret
        - name: htpasswd-volume
          mountPath: /etc/nginx/conf.d
      containers:
      - name: nginx-container
        image: nginx:1.26-alpine
        ports:
        - containerPort: 80
        env:
        - name: NGINX_PORT
          valueFrom:
            configMapKeyRef:
              name: nginx-config
              key: nginx_port
        # 挂载 ConfigMap(配置文件)、Secret(认证文件)
        volumeMounts:
        - name: nginx-conf-volume
          mountPath: /etc/nginx/conf.d/default.conf
          subPath: default.conf
        - name: nginx-html-volume
          mountPath: /usr/share/nginx/html/index.html
          subPath: index.html
        - name: htpasswd-volume
          mountPath: /etc/nginx/conf.d/.htpasswd
          subPath: .htpasswd
        resources:
          requests:
            cpu: "100m"
            memory: "128Mi"
          limits:
            cpu: "200m"
            memory: "256Mi"
      # 定义卷(关联 ConfigMap/Secret/空目录)
      volumes:
      - name: nginx-conf-volume
        configMap:
          name: nginx-config
          items:
          - key: default.conf
            path: default.conf
      - name: nginx-html-volume
        configMap:
          name: nginx-config
          items:
          - key: index.html
            path: index.html
      - name: nginx-secret-volume
        secret:
          secretName: nginx-secret  # 关联的 Secret 名称
      - name: htpasswd-volume
        emptyDir: {}  # 临时目录,用于存储初始化生成的 .htpasswd 文件
步骤 3:重新部署 ConfigMap + Deployment

bash

运行

# 更新 ConfigMap
kubectl apply -f nginx-configmap.yaml
# 更新 Deployment(触发滚动更新)
kubectl apply -f nginx-deployment.yaml
三、第三步:查看 Secret 运行效果

验证 Secret 中的用户名密码是否生效,访问 Nginx 需输入认证信息。

1. 验证基础认证(核心)

bash

运行

# 方式 1:未输入认证信息访问(返回 401 未授权)
curl -v http://nginx.example.com

# 方式 2:输入 Secret 中的用户名密码访问(成功返回页面)
curl -u admin:123456 http://nginx.example.com

成功输出 ConfigMap 定义的首页内容,说明 Secret 中的敏感数据已成功注入 Pod 并生效。

2. 验证 Secret 挂载内容

bash

运行

# 进入 Pod 查看 Secret 挂载的文件
kubectl exec -it $(kubectl get pod -l app=nginx -o jsonpath="{.items[0].metadata.name}") -- /bin/sh

# 查看 Secret 挂载的编码文件(自动解码)
cat /etc/secret/auth_user  # 输出:admin
cat /etc/secret/auth_pass  # 输出:123456

# 查看生成的 .htpasswd 文件
cat /etc/nginx/conf.d/.htpasswd  # 输出:admin:$apr1$...(加密后的密码)

# 退出 Pod
exit

注意:K8s 会自动将 Secret 的 Base64 编码数据解码后挂载到 Pod 中,无需手动解码。

四、第四步:修改 Secret 并验证更新

Secret 同样支持热更新(文件挂载方式),我们修改密码并验证认证效果。

1. 修改 Secret YAML(更新密码为 654321)

先编码新密码:

bash

运行

echo -n "654321" | base64  # 输出:NjU0MzIx

更新 nginx-secret.yaml

yaml

apiVersion: v1
kind: Secret
metadata:
  name: nginx-secret
type: Opaque
data:
  auth_user: YWRtaW4=
  auth_pass: NjU0MzIx  # 新密码 654321 的 Base64 编码
2. 应用 Secret 修改

bash

运行

kubectl apply -f nginx-secret.yaml
3. 重建初始化容器(使新密码生效)

Secret 热更新后,需重启 Pod 让初始化容器重新生成 .htpasswd 文件:

bash

运行

# 滚动更新 Deployment(重启所有 Pod)
kubectl rollout restart deployment/nginx-deployment
4. 验证密码更新效果

bash

运行

# 旧密码访问(失败)
curl -u admin:123456 http://nginx.example.com  # 返回 401
# 新密码访问(成功)
curl -u admin:654321 http://nginx.example.com  # 返回首页内容
拓展:Secret 常用类型

表格

类型 适用场景 示例用途
Opaque 通用键值对(默认) 用户名密码、API Token
kubernetes.io/tls TLS 证书 HTTPS 证书(替代手动创建 Secret)
kubernetes.io/dockerconfigjson 镜像仓库凭证 拉取私有镜像的用户名密码
总结
  1. 核心定位:Secret 是 K8s 管理「敏感配置」的核心资源,专门存储密码、证书等敏感数据,相比 ConfigMap 更安全(Base64 编码 + 访问权限控制)。
  2. 核心流程:编写 Secret YAML(Base64 编码敏感数据)→ 部署 Secret → 修改 Deployment 以「环境变量」或「文件挂载」方式注入 → 验证敏感配置生效 → 修改 Secret 并重启 Pod 实现更新。
  3. 关键区别(vs ConfigMap)
    • 用途:ConfigMap 存非敏感配置(如 Nginx 配置),Secret 存敏感数据(如密码);
    • 存储:ConfigMap 明文,Secret Base64 编码;
    • 权限:Secret 默认仅挂载到需要的 Pod,访问权限更严格。

至此,你已掌握 K8s 配置管理的完整方案:ConfigMap(非敏感配置) + Secret(敏感配置),结合之前的 Deployment/Service/Ingress,形成了 K8s 无状态应用部署的完整闭环。后续可学习 StatefulSet(有状态应用)、PersistentVolume(持久化存储)等进阶内容。

StatefulSet

StatefulSet 解决了 Deployment(无状态)「Pod 名称随机、无固定网络标识、存储不持久」的问题,专门用于部署数据库(MySQL/PostgreSQL)、中间件(Redis/Zookeeper)等有状态应用。我依然按「写 YAML → 部署 → 看效果 → 改配置」的流程,以 Redis 主从集群为例,带你理解 StatefulSet 的核心特性和使用方式。

一、前置说明:StatefulSet vs Deployment

先明确核心差异,帮你理解 StatefulSet 的设计初衷:

表格

特性 Deployment(无状态) StatefulSet(有状态)
Pod 名称 随机后缀(如 xxx-7f987d6c74-2x89s) 固定名称(如 redis-0、redis-1)
网络标识 无固定 DNS 名称 固定 Headless Service 域名(redis-0.redis-svc.default.svc.cluster.local)
存储 共享 Volume(删除则丢失) 固定 PersistentVolumeClaim(PVC),每个 Pod 独享存储
部署 / 扩缩容顺序 无序 有序(0→1→2 部署,2→1→0 缩容)
更新策略 滚动更新 有序更新(默认)/ 分区更新
二、第一步:编写 StatefulSet 相关 YAML

StatefulSet 依赖两个核心组件:

  1. Headless Service:为 StatefulSet 提供固定网络标识(无 ClusterIP,仅做 DNS 解析);
  2. StatefulSet 资源:定义有状态 Pod 的模板、存储、有序部署规则;
  3. PersistentVolumeClaim(PVC)模板:为每个 Pod 分配独享的持久化存储。

我们以 Redis 主从集群为例,编写完整 YAML(redis-statefulset.yaml):

yaml

# 1. 先创建 Headless Service(为 StatefulSet 提供固定 DNS)
apiVersion: v1
kind: Service
metadata:
  name: redis-headless
  labels:
    app: redis
spec:
  clusterIP: None  # 关键:Headless Service 无 ClusterIP
  selector:
    app: redis
  ports:
  - name: redis
    port: 6379
    targetPort: 6379

---
# 2. 创建 StatefulSet(管理 Redis 有状态 Pod)
apiVersion: apps/v1
kind: StatefulSet
metadata:
  name: redis-statefulset
  labels:
    app: redis
spec:
  serviceName: redis-headless  # 关联上面的 Headless Service(核心!)
  replicas: 2  # 2 个 Pod:redis-0(主)、redis-1(从)
  selector:
    matchLabels:
      app: redis
  # 存储模板:每个 Pod 独享一个 PVC
  volumeClaimTemplates:
  - metadata:
      name: redis-data
    spec:
      accessModes: [ "ReadWriteOnce" ]  # 单节点读写
      resources:
        requests:
          storage: 1Gi  # 每个 Pod 申请 1Gi 存储
      # 存储类(根据集群环境调整,如 minikube 的 standard、云厂商的 cbs)
      storageClassName: "standard"
  # Pod 模板
  template:
    metadata:
      labels:
        app: redis
    spec:
      containers:
      - name: redis
        image: redis:7.2-alpine
        ports:
        - containerPort: 6379
        # 挂载持久化存储(对应 volumeClaimTemplates)
        volumeMounts:
        - name: redis-data
          mountPath: /data  # Redis 数据存储目录
        # 初始化 Redis 主从配置(通过环境变量区分主从)
        env:
        - name: REDIS_REPLICATION_MODE
          valueFrom:
            fieldRef:
              fieldPath: metadata.name  # 获取 Pod 名称(redis-0/redis-1)
        command:
        - /bin/sh
        - -c
        - |
          # redis-0 作为主节点,redis-1 作为从节点
          if [ "$REDIS_REPLICATION_MODE" = "redis-statefulset-0" ]; then
            redis-server --appendonly yes  # 主节点开启 AOF 持久化
          else
            redis-server --appendonly yes --replicaof redis-statefulset-0.redis-headless 6379  # 从节点关联主节点
          fi
        resources:
          requests:
            cpu: "100m"
            memory: "128Mi"
          limits:
            cpu: "200m"
            memory: "256Mi"
      restartPolicy: Always
  # 更新策略:有序更新(默认)
  updateStrategy:
    type: RollingUpdate
    rollingUpdate:
      partition: 0  # 从第 0 个 Pod 开始有序更新
关键配置解释

表格

配置项 作用
serviceName 核心!关联 Headless Service,为每个 Pod 生成固定 DNS 域名(如 redis-statefulset-0.redis-headless)
volumeClaimTemplates PVC 模板:每个 Pod 自动创建一个同名 PVC(redis-data-redis-statefulset-0),独享存储
replicas 有序部署的 Pod 数量,名称为 {statefulset-name}-{序号}(从 0 开始)
updateStrategy 有序更新:默认从序号大的 Pod 开始更新,保证主节点最后更新(数据库场景关键)
三、第二步:部署 StatefulSet 及依赖资源

部署前确保集群支持 PersistentVolume(PV):

  • Minikube:默认支持 standard 存储类,会自动创建 PV;
  • 云厂商集群:需提前创建存储类(如阿里云 alicloud-disk-efficiency);
  • 本地集群:需手动创建 PV 或部署存储插件。
1. 执行部署命令

bash

运行

# 应用 YAML 创建 Headless Service + StatefulSet
kubectl apply -f redis-statefulset.yaml

成功输出

plaintext

service/redis-headless created
statefulset.apps/redis-statefulset created
2. 验证部署过程(有序性)

bash

运行

# 实时查看 Pod 创建过程(先创建 redis-statefulset-0,再创建 redis-statefulset-1)
kubectl get pods -l app=redis -w

输出示例(有序创建):

plaintext

NAME                    READY   STATUS              RESTARTS   AGE
redis-statefulset-0     0/1     ContainerCreating   0          0s
redis-statefulset-0     1/1     Running             0          5s
redis-statefulset-1     0/1     ContainerCreating   0          5s
redis-statefulset-1     1/1     Running             0          10s
3. 验证 PVC 自动创建

bash

运行

# 查看 PVC(每个 Pod 对应一个 PVC)
kubectl get pvc

输出示例:

plaintext

NAME                         STATUS   VOLUME                                     CAPACITY   ACCESS MODES   STORAGECLASS   AGE
redis-data-redis-statefulset-0   Bound    pvc-xxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx   1Gi        RWO            standard       15s
redis-data-redis-statefulset-1   Bound    pvc-yyyyyy-yyyy-yyyy-yyyy-yyyyyyyyyyyy   1Gi        RWO            standard       10s
四、第三步:查看 StatefulSet 运行效果

重点验证「固定网络标识」「持久化存储」「主从复制」三大核心特性。

1. 验证固定 DNS 解析(Headless Service)

bash

运行

# 创建临时 Pod 测试 DNS 解析
kubectl run test-pod --image=busybox:1.36 --rm -it -- /bin/sh

# 解析 redis-statefulset-0 的固定域名
nslookup redis-statefulset-0.redis-headless
# 输出:Address: 10.244.0.10(redis-0 的 Pod IP)

# 解析 redis-statefulset-1 的固定域名
nslookup redis-statefulset-1.redis-headless
# 输出:Address: 10.244.0.11(redis-1 的 Pod IP)

# 退出临时 Pod
exit

关键:即使 Pod 重建(IP 变化),DNS 域名仍指向新 Pod 的 IP,保证网络标识不变。

2. 验证 Redis 主从复制

bash

运行

# 进入 redis-0(主节点)
kubectl exec -it redis-statefulset-0 -- redis-cli

# 设置测试数据
set test "hello statefulset"
get test  # 输出:"hello statefulset"

# 退出主节点
exit

# 进入 redis-1(从节点)
kubectl exec -it redis-statefulset-1 -- redis-cli

# 读取主节点同步的数据(验证主从复制)
get test  # 输出:"hello statefulset"

# 查看复制状态
info replication
# 输出中会显示 "role:slave"、"master_host:redis-statefulset-0.redis-headless"

# 退出从节点
exit
3. 验证持久化存储(核心)

bash

运行

# 1. 删除 redis-0 Pod(模拟故障)
kubectl delete pod redis-statefulset-0

# 2. 等待 StatefulSet 重建 redis-0
kubectl get pods -l app=redis

# 3. 进入重建后的 redis-0,验证数据未丢失
kubectl exec -it redis-statefulset-0 -- redis-cli
get test  # 输出:"hello statefulset"(数据从 PVC 中恢复)
exit

关键:Deployment 删除 Pod 后数据丢失,StatefulSet 因独享 PVC,重建后数据仍存在。

五、第四步:修改配置(扩缩容 + 分区更新)
1. 扩缩容(有序)

bash

运行

# 扩容到 3 个 Pod(会创建 redis-statefulset-2,作为从节点)
kubectl scale statefulset redis-statefulset --replicas=3

# 验证扩容结果
kubectl get pods -l app=redis
# 输出:redis-statefulset-0、redis-statefulset-1、redis-statefulset-2

# 缩容到 2 个 Pod(先删除 redis-statefulset-2,再保留 0/1)
kubectl scale statefulset redis-statefulset --replicas=2
2. 分区更新(生产常用)

分区更新可指定「仅更新部分 Pod」,适合灰度发布:

yaml

# 修改 StatefulSet YAML 的 updateStrategy
updateStrategy:
  type: RollingUpdate
  rollingUpdate:
    partition: 1  # 仅更新序号 ≥1 的 Pod(即 redis-statefulset-1)

应用修改并验证:

bash

运行

# 应用配置
kubectl apply -f redis-statefulset.yaml

# 查看更新状态(仅 redis-statefulset-1 重启,redis-statefulset-0 不变)
kubectl rollout status statefulset/redis-statefulset
总结
  1. 核心定位:StatefulSet 是 K8s 管理「有状态应用」的核心控制器,解决了 Deployment 无固定标识、无独享存储、无序部署的问题,适用于数据库、中间件等有状态场景。
  2. 核心流程:创建 Headless Service(固定网络)→ 编写 StatefulSet YAML(含 PVC 模板、有序规则)→ 部署并验证有序创建 / 固定 DNS / 持久化存储 → 测试扩缩容 / 分区更新。
  3. 关键特性:固定 Pod 名称 + 固定 DNS 标识、每个 Pod 独享 PVC 存储、有序部署 / 扩缩容 / 更新,是部署有状态应用的标准方案。

至此,你已掌握 K8s 核心资源的完整体系:

  • 无状态应用:Pod → Deployment → Service → Ingress;
  • 配置管理:ConfigMap(非敏感) + Secret(敏感);
  • 有状态应用:StatefulSet + Headless Service + PVC/PV。

后续可学习 Operator(自动化运维有状态应用)、Namespace(资源隔离)、ResourceQuota(资源限制)等进阶内容,进一步完善 K8s 知识体系。

PV/PVC

PV(PersistentVolume)和 PVC(PersistentVolumeClaim) 解决了「存储和应用解耦」的问题,是 K8s 实现持久化存储的标准方案 ——StatefulSet 中用到的 volumeClaimTemplates 本质就是自动创建 PVC,而 PVC 又会绑定集群中的 PV。我依然按「写 YAML → 部署 → 看效果 → 改配置」的流程,带你理解 PV/PVC 的核心逻辑,以及和 StatefulSet 的联动关系。

一、前置说明:PV/PVC 核心逻辑

先理清 PV/PVC 的分工(类比「租房」更易理解):

表格

角色 类比 作用
PV(持久卷) 房东的房子 集群级别的存储资源(独立于 Pod 生命周期),由管理员创建,定义存储类型、大小、访问模式
PVC(持久卷声明) 租客的租房申请 Pod 对存储的「申请单」,由开发 / 运维创建,声明需要的存储大小、访问模式,K8s 自动绑定匹配的 PV
StorageClass 房屋中介 自动创建 PV(动态供给),无需管理员手动创建 PV,是生产环境首选(StatefulSet 示例中已用到)
二、第一步:编写 PV/PVC YAML 配置文件

我们分「静态供给(手动创建 PV)」和「动态供给(StorageClass 自动创建 PV)」两种场景演示,覆盖新手最常用的两种方式。

场景 1:静态供给(手动创建 PV + PVC)

适合测试 / 小规模集群,需先创建 PV,再创建 PVC 绑定。

1. 创建 PV YAML(redis-pv.yaml)

yaml

# API 版本:PV 属于核心组,使用 v1
apiVersion: v1
kind: PersistentVolume
metadata:
  name: redis-pv-0  # PV 名称(唯一)
  labels:
    app: redis
    pv: redis-pv-0
spec:
  capacity:
    storage: 1Gi  # PV 大小(需 ≥ PVC 申请的大小)
  accessModes:
    - ReadWriteOnce  # 访问模式:单节点读写(RWO),其他模式:ROX(多节点只读)、RWX(多节点读写)
  persistentVolumeReclaimPolicy: Retain  # 回收策略:Retain(保留)/ Delete(删除)/ Recycle(回收,已废弃)
  storageClassName: "standard"  # 存储类名称(需和 PVC 一致)
  # 存储后端(根据环境选择,这里以 Minikube 本地存储为例)
  hostPath:
    path: /data/redis-pv-0  # Minikube 节点上的本地路径(需提前创建)
    type: DirectoryOrCreate  # 路径不存在则自动创建
2. 创建 PVC YAML(redis-pvc.yaml)

yaml

apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: redis-pvc-0  # PVC 名称
  labels:
    app: redis
spec:
  accessModes:
    - ReadWriteOnce  # 必须和 PV 的访问模式匹配
  resources:
    requests:
      storage: 1Gi  # 申请的存储大小(必须 ≤ PV 的容量)
  storageClassName: "standard"  # 必须和 PV 的存储类名称匹配
  # 可选:通过标签选择器绑定指定 PV
  selector:
    matchLabels:
      pv: redis-pv-0
场景 2:动态供给(StorageClass + PVC)

生产环境首选,无需手动创建 PV,StorageClass 会自动创建匹配的 PV。

1. 创建 StorageClass YAML(redis-storageclass.yaml)

yaml

apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
  name: redis-sc  # 存储类名称
provisioner: k8s.io/minikube-hostpath  # 存储供给者(Minikube 专用,云厂商需替换:如阿里云 alicloud/disk)
reclaimPolicy: Delete  # PV 回收策略(删除 PVC 时自动删除 PV)
volumeBindingMode: Immediate  # 立即绑定 PVC 和 PV
2. 创建 PVC YAML(redis-pvc-dynamic.yaml)

yaml

apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: redis-pvc-dynamic
  labels:
    app: redis
spec:
  accessModes:
    - ReadWriteOnce
  resources:
    requests:
      storage: 1Gi
  storageClassName: "redis-sc"  # 关联上面的 StorageClass
三、第二步:部署 PV/PVC 并验证绑定
场景 1:静态供给部署流程
1. 准备 Minikube 本地路径(仅 hostPath 需执行)

bash

运行

# 进入 Minikube 节点并创建存储路径
minikube ssh
mkdir -p /data/redis-pv-0
exit
2. 部署 PV

bash

运行

kubectl apply -f redis-pv.yaml

成功输出persistentvolume/redis-pv-0 created

3. 部署 PVC

bash

运行

kubectl apply -f redis-pvc.yaml

成功输出persistentvolumeclaim/redis-pvc-0 created

4. 验证 PV/PVC 绑定

bash

运行

# 查看 PV 状态(STATUS 为 Bound 表示已绑定)
kubectl get pv redis-pv-0
# 查看 PVC 状态(STATUS 为 Bound 表示绑定成功)
kubectl get pvc redis-pvc-0

输出示例:

plaintext

NAME         CAPACITY   ACCESS MODES   RECLAIM POLICY   STATUS   CLAIM               STORAGECLASS   REASON   AGE
redis-pv-0   1Gi        RWO            Retain           Bound    default/redis-pvc-0   standard                10s

NAME           STATUS   VOLUME       CAPACITY   ACCESS MODES   STORAGECLASS   AGE
redis-pvc-0    Bound    redis-pv-0   1Gi        RWO            standard       5s
场景 2:动态供给部署流程
1. 部署 StorageClass

bash

运行

kubectl apply -f redis-storageclass.yaml

成功输出storageclass.storage.k8s.io/redis-sc created

2. 部署 PVC

bash

运行

kubectl apply -f redis-pvc-dynamic.yaml

成功输出persistentvolumeclaim/redis-pvc-dynamic created

3. 验证自动创建 PV

bash

运行

# 查看 PVC(STATUS 为 Bound)
kubectl get pvc redis-pvc-dynamic
# 查看自动创建的 PV(名称为 pvc-xxxxxx,STATUS 为 Bound)
kubectl get pv

关键:动态供给下,无需手动创建 PV,K8s 会根据 StorageClass 自动创建匹配的 PV 并绑定到 PVC。

四、第三步:将 PVC 挂载到 Pod/StatefulSet 验证效果

我们将静态供给的 PVC 挂载到 Pod,验证持久化存储效果。

1. 创建测试 Pod YAML(redis-pod-pvc.yaml)

yaml

apiVersion: v1
kind: Pod
metadata:
  name: redis-pod-with-pvc
spec:
  containers:
  - name: redis
    image: redis:7.2-alpine
    ports:
    - containerPort: 6379
    # 挂载 PVC 到容器
    volumeMounts:
    - name: redis-storage
      mountPath: /data  # Redis 数据存储目录
  # 关联 PVC
  volumes:
  - name: redis-storage
    persistentVolumeClaim:
      claimName: redis-pvc-0  # 绑定的 PVC 名称
  restartPolicy: Always
2. 部署 Pod

bash

运行

kubectl apply -f redis-pod-pvc.yaml
3. 验证持久化存储

bash

运行

# 1. 进入 Pod 写入测试数据
kubectl exec -it redis-pod-with-pvc -- redis-cli
set test "hello pv/pvc"
get test  # 输出:"hello pv/pvc"
exit

# 2. 删除 Pod(模拟故障)
kubectl delete pod redis-pod-with-pvc

# 3. 重新部署 Pod(使用同一个 PVC)
kubectl apply -f redis-pod-pvc.yaml

# 4. 进入新 Pod 验证数据未丢失
kubectl exec -it redis-pod-with-pvc -- redis-cli
get test  # 输出:"hello pv/pvc"(数据从 PV 中恢复)
exit

核心:PV/PVC 独立于 Pod 生命周期,即使 Pod 被删除重建,只要 PVC 绑定的 PV 存在,数据就不会丢失 —— 这也是 StatefulSet 能实现数据持久化的核心原因。

五、第四步:修改 PV/PVC 配置(扩容 + 回收策略)
1. PVC 扩容(K8s 1.11+ 支持)
1. 修改 PVC YAML(将存储大小改为 2Gi)

yaml

apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: redis-pvc-0
spec:
  accessModes:
    - ReadWriteOnce
  resources:
    requests:
      storage: 2Gi  # 扩容到 2Gi
  storageClassName: "standard"
  selector:
    matchLabels:
      pv: redis-pv-0
2. 应用修改(需确保 PV 支持扩容,hostPath 仅测试用,云厂商存储如 EBS 支持)

bash

运行

kubectl apply -f redis-pvc.yaml
3. 验证扩容

bash

运行

kubectl get pvc redis-pvc-0
# 输出 CAPACITY 为 2Gi
2. 修改 PV 回收策略
1. 编辑 PV 配置

bash

运行

kubectl edit pv redis-pv-0

persistentVolumeReclaimPolicy: Retain 改为 persistentVolumeReclaimPolicy: Delete

2. 验证修改

bash

运行

kubectl describe pv redis-pv-0 | grep "Reclaim Policy"
# 输出:Reclaim Policy: Delete
拓展:PV 回收策略说明

表格

策略 作用 适用场景
Retain 删除 PVC 后,PV 保留(状态变为 Released),需手动清理数据 / 删除 PV 生产环境(防止误删数据)
Delete 删除 PVC 后,PV 自动删除(底层存储也会删除,如云盘) 测试环境 / 临时存储
Recycle 删除 PVC 后,PV 格式化并重置(已废弃,推荐用 Retain/Delete) 老旧集群(不推荐)
总结
  1. 核心定位:PV/PVC 是 K8s 实现持久化存储的核心方案,通过「存储资源(PV)」和「存储申请(PVC)」解耦,让应用无需关心底层存储细节。
  2. 核心流程
    • 静态供给:创建 PV → 创建 PVC 绑定 PV → 挂载 PVC 到 Pod/StatefulSet;
    • 动态供给:创建 StorageClass → 创建 PVC → K8s 自动创建 PV 并绑定 → 挂载 PVC 到应用。
  3. 关键联动:StatefulSet 的 volumeClaimTemplates 本质是为每个 Pod 自动创建 PVC,结合 StorageClass 动态供给 PV,实现「每个 Pod 独享持久化存储」,这是有状态应用(如数据库)的核心需求。

至此,你已掌握 K8s 存储管理的核心方案,结合之前的 StatefulSet/Deployment/Service/Ingress/ConfigMap/Secret,形成了 K8s 应用部署的完整技术栈。后续可学习 CSI(容器存储接口)、动态存储扩容、存储快照等进阶内容,进一步适配生产环境的复杂存储需求。

JOB/CRONJOB

Job 解决了 Deployment/StatefulSet 「长期运行」的问题,专门用于执行一次性任务(如数据备份、批量计算);CronJob 则基于 Job 实现定时 / 周期性任务(如定时备份、日志清理)。我依然按「写 YAML → 部署 → 看效果 → 改配置」的流程,带你理解这两个资源的核心用法和场景差异。

一、前置说明:Job/CronJob 核心定位

先明确 Job/CronJob 与之前控制器的差异:

表格

控制器 适用场景 核心特性
Deployment 长期运行的无状态服务 持续运行、自动重启、滚动更新
StatefulSet 长期运行的有状态服务 固定标识、独享存储、有序部署
Job 一次性任务(执行完即结束) 执行完成后 Pod 状态为 Completed,可重试
CronJob 定时 / 周期性任务 基于 Cron 表达式触发 Job,支持并发策略
二、第一步:编写 Job/CronJob YAML 配置文件
场景 1:Job(一次性任务)

以「批量生成测试数据并写入文件」为例,编写 Job YAML(data-generate-job.yaml):

yaml

# API 版本:Job 属于 batch 组,1.21+ 推荐使用 batch/v1
apiVersion: batch/v1
# 资源类型:Job
kind: Job
metadata:
  name: data-generate-job
  labels:
    app: data-job
spec:
  # 并行执行的 Pod 数(默认 1,适合批量任务)
  parallelism: 1
  # 完成的 Pod 数(需 ≤ parallelism,默认 1)
  completions: 1
  # 失败重试次数(默认 6,超出则 Job 标记为 Failed)
  backoffLimit: 3
  # 任务超时时间(可选,超出则终止 Pod)
  activeDeadlineSeconds: 300
  # Pod 模板(和 Deployment 类似,但重启策略仅支持 Never/OnFailure)
  template:
    metadata:
      labels:
        app: data-job
    spec:
      containers:
      - name: data-generator
        image: alpine:3.19
        # 执行一次性任务:生成 100 行测试数据写入文件
        command:
        - /bin/sh
        - -c
        - |
          echo "Generating test data..."
          for i in $(seq 1 100); do
            echo "Test data line $i: $(date +%Y-%m-%d_%H:%M:%S)" >> /data/test-data.txt
            sleep 0.1
          done
          echo "Data generation completed!"
          cat /data/test-data.txt
        # 挂载 PV/PVC 持久化生成的文件(可选,测试也可不用)
        volumeMounts:
        - name: data-volume
          mountPath: /data
      # Job 的重启策略仅支持 Never(永不重启)或 OnFailure(失败时重启)
      restartPolicy: Never
      # 定义卷(这里用 EmptyDir 测试,生产可替换为 PVC)
      volumes:
      - name: data-volume
        emptyDir: {}
场景 2:CronJob(定时任务)

以「每天凌晨 2 点执行数据备份」为例,编写 CronJob YAML(backup-cronjob.yaml):

yaml

# API 版本:CronJob 属于 batch 组,1.21+ 推荐使用 batch/v1
apiVersion: batch/v1
kind: CronJob
metadata:
  name: backup-cronjob
  labels:
    app: backup-cron
spec:
  # Cron 表达式(分时日月周,和 Linux Crontab 一致)
  # 示例:每天凌晨 2 点执行 → 0 2 * * *
  schedule: "*/1 * * * *"  # 测试用:每分钟执行一次
  # 任务执行超时时间(超出则终止)
  jobTimeoutSeconds: 300
  # 并发策略:Allow(允许并发)/ Forbid(禁止)/ Replace(替换)
  concurrencyPolicy: Forbid
  # 错过执行的任务是否运行(默认 false,适合非关键任务)
  startingDeadlineSeconds: 60
  # 保留成功的 Job 历史记录数(默认 3)
  successfulJobsHistoryLimit: 5
  # 保留失败的 Job 历史记录数(默认 1)
  failedJobsHistoryLimit: 3
  # 暂停 CronJob(默认 false,设为 true 则停止触发任务)
  suspend: false
  # Job 模板(和上面的 Job 配置一致)
  jobTemplate:
    spec:
      backoffLimit: 3
      template:
        spec:
          containers:
          - name: backup
            image: alpine:3.19
            command:
            - /bin/sh
            - -c
            - |
              echo "Starting backup at $(date)..."
              # 模拟备份操作:压缩 /data 目录(这里用空操作测试)
              tar -czf /backup/backup-$(date +%Y%m%d_%H%M%S).tar.gz /data || echo "Backup completed!"
              ls -l /backup/
          volumeMounts:
          - name: backup-volume
            mountPath: /backup
          restartPolicy: Never
          volumes:
          - name: backup-volume
            emptyDir: {}
关键配置解释

表格

配置项(Job) 作用
parallelism 并行执行的 Pod 数,适合拆分大任务为多个子任务并行处理
completions 需完成的 Pod 数,全部完成后 Job 状态为 Completed
backoffLimit 失败重试次数,防止任务无限重试(如依赖的服务不可用)
restartPolicy 仅支持 Never/OnFailure(Job 是一次性任务,不支持 Always)

表格

配置项(CronJob) 作用
schedule Cron 表达式(* * * * *):分 (0-59) 时 (0-23) 日 (1-31) 月 (1-12) 周 (0-6)
concurrencyPolicy 并发策略:Forbid 禁止并发(避免重复执行备份),生产推荐
successfulJobsHistoryLimit 保留成功 Job 记录数,便于排查历史任务执行情况
suspend 暂停 CronJob,无需删除资源即可停止任务触发(运维常用)
三、第二步:部署 Job/CronJob 并验证执行
场景 1:部署 Job(一次性任务)
1. 执行部署命令

bash

运行

kubectl apply -f data-generate-job.yaml

成功输出job.batch/data-generate-job created

2. 查看 Job 状态

bash

运行

# 查看 Job 列表(COMPLETIONS 为 1/1 表示执行完成)
kubectl get jobs
# 查看 Job 详情(包含执行事件、Pod 信息)
kubectl describe job data-generate-job

输出示例:

plaintext

NAME                COMPLETIONS   DURATION   AGE
data-generate-job   1/1           12s        20s
3. 查看 Job 对应的 Pod 及日志

bash

运行

# 查看 Job 创建的 Pod(名称格式:{job-name}-{随机后缀})
kubectl get pods -l app=data-job
# 查看 Pod 日志(验证任务执行结果)
kubectl logs <pod-name>  # 替换为实际 Pod 名称

日志会输出「生成 100 行测试数据」的内容,确认任务执行成功。

场景 2:部署 CronJob(定时任务)
1. 执行部署命令

bash

运行

kubectl apply -f backup-cronjob.yaml

成功输出cronjob.batch/backup-cronjob created

2. 查看 CronJob 状态

bash

运行

# 查看 CronJob 列表
kubectl get cronjobs
# 简写:kubectl get cj

输出示例:

plaintext

NAME           SCHEDULE      SUSPEND   ACTIVE   LAST SCHEDULE   AGE
backup-cronjob */1 * * * *   False     0        10s             30s
3. 验证定时触发 Job

bash

运行

# 等待 1 分钟,查看 CronJob 触发的 Job
kubectl get jobs -l app=backup-cron
# 查看触发的 Pod 及日志
kubectl get pods -l app=backup-cron
kubectl logs <backup-pod-name>

日志会输出「备份开始 / 完成」的内容,确认定时任务每 1 分钟执行一次。

四、第三步:修改配置并验证更新
场景 1:修改 Job(重新执行一次性任务)

Job 执行完成后无法直接修改配置重新执行,需先删除旧 Job,再部署新配置:

1. 修改 Job YAML(将生成数据行数改为 200)

yaml

command:
- /bin/sh
- -c
- |
  echo "Generating test data..."
  for i in $(seq 1 200); do  # 改为 200 行
    echo "Test data line $i: $(date +%Y-%m-%d_%H:%M:%S)" >> /data/test-data.txt
    sleep 0.1
  done
  echo "Data generation completed!"
  cat /data/test-data.txt
2. 删除旧 Job 并重新部署

bash

运行

# 删除旧 Job
kubectl delete job data-generate-job
# 部署新 Job
kubectl apply -f data-generate-job.yaml
3. 验证修改效果

bash

运行

kubectl logs <new-pod-name> | wc -l  # 查看输出行数(约 200 行)
场景 2:修改 CronJob(调整执行频率)
1. 修改 CronJob YAML(将执行频率改为每 5 分钟一次)

yaml

schedule: "*/5 * * * *"  # 每 5 分钟执行一次
2. 应用修改

bash

运行

kubectl apply -f backup-cronjob.yaml
3. 验证更新效果

bash

运行

# 查看 CronJob 配置(确认 schedule 已更新)
kubectl describe cronjob backup-cronjob | grep Schedule
# 等待 5 分钟,验证仅每 5 分钟触发一次 Job
kubectl get jobs -l app=backup-cron -w
拓展:CronJob 常用操作

bash

运行

# 手动触发一次 CronJob(无需等待定时时间)
kubectl create job --from=cronjob/backup-cronjob manual-backup-job

# 暂停 CronJob(停止触发新任务)
kubectl patch cronjob backup-cronjob -p '{"spec":{"suspend":true}}'

# 恢复 CronJob
kubectl patch cronjob backup-cronjob -p '{"spec":{"suspend":false}}'

# 删除 CronJob 及所有历史 Job/Pod
kubectl delete cronjob backup-cronjob
kubectl delete jobs --all -l app=backup-cron
总结
  1. 核心定位
    • Job 用于执行「一次性任务」(如数据备份、批量计算),执行完成后 Pod 终止,支持并行 / 重试配置;
    • CronJob 基于 Job 实现「定时 / 周期性任务」(如定时备份、日志清理),通过 Cron 表达式触发,支持并发控制和历史记录管理。
  2. 核心流程
    • Job:编写 YAML(定义一次性任务)→ 部署 → 查看 Pod 日志验证执行结果 → 删除重建修改配置;
    • CronJob:编写 YAML(定义 Cron 表达式 + Job 模板)→ 部署 → 验证定时触发 → 修改 schedule 调整执行频率。
  3. 关键注意
    • Job 重启策略仅支持 Never/OnFailure,执行完成后需删除重建才能重新执行;
    • CronJob 的 concurrencyPolicy 推荐设为 Forbid,避免任务并发执行导致数据冲突;
    • 生产环境中,Job/CronJob 建议挂载 PVC 持久化任务输出(如备份文件)。

至此,你已掌握 K8s 核心控制器的全量场景:

  • 长期运行服务:Deployment(无状态)、StatefulSet(有状态);
  • 一次性 / 定时任务:Job、CronJob;
  • 服务暴露:Service、Ingress;
  • 配置管理:ConfigMap、Secret;
  • 存储管理:PV/PVC、StorageClass。

这些覆盖了 K8s 日常运维的 90% 场景,后续可学习 RBAC(权限控制)、Namespace(资源隔离)、HPA(自动扩缩容)等进阶内容,进一步适配生产环境的复杂需求。

进阶内容

一、第一梯队:基础进阶(必学,覆盖日常运维 80% 场景)
1. Namespace(命名空间)—— 资源隔离与环境划分
核心定位

K8s 中最基础的资源隔离机制,将集群内的资源(Pod/Deployment/Service 等)按「环境 / 团队 / 项目」划分,避免资源名称冲突、权限混乱,是多团队 / 多环境共用集群的必备能力。

学习重点

表格

知识点 核心内容
核心特性 ① 每个 Namespace 内资源名称唯一,跨 Namespace 需通过「名称 + Namespace」访问;② Namespace 独立分配资源配额;③ 部分系统资源(Node/PV)不属于任何 Namespace。
常用操作 ① 创建 / 删除 Namespace:kubectl create ns dev;② 指定 Namespace 部署资源:kubectl apply -f xxx.yaml -n dev;③ 切换默认 Namespace:kubectl config set-context --current --namespace=dev
核心配置 编写资源 YAML 时通过 metadata.namespace 指定所属 Namespace(默认 default)。
典型场景 ① 划分环境:dev(开发)、test(测试)、prod(生产);② 划分团队:team-a、team-b。
实操方向
  • 练习:为之前的 Nginx Deployment/Service 分别部署到 devprod Namespace,验证跨 Namespace 访问(需用 service-name.namespace.svc.cluster.local 域名);
  • 进阶:为不同 Namespace 配置 ResourceQuota(资源配额),限制每个 Namespace 最多使用 2CPU/4Gi 内存。
2. RBAC(基于角色的访问控制)—— 权限精细化管理
核心定位

K8s 原生的权限控制体系,替代老旧的 ABAC 模式,通过「角色(Role)+ 角色绑定(RoleBinding)」实现「谁(User/ServiceAccount)能对哪些资源(Pod/Deployment)执行哪些操作(get/create/delete)」的精细化管控,是生产集群安全的核心。

学习重点

表格

知识点 核心内容
核心组件 Subject(主体):User(普通用户)、Group(用户组)、ServiceAccount(Pod 访问 API 的账户);② Role/ClusterRole(角色):定义权限规则(如允许 get pods、create deployments);③ RoleBinding/ClusterRoleBinding(绑定):将 Subject 和 Role 关联。
作用域 ① Role/RoleBinding:仅作用于单个 Namespace;② ClusterRole/ClusterRoleBinding:作用于整个集群(如管理所有 Namespace 的 Pod)。
ServiceAccount 核心 ① Pod 默认使用 default ServiceAccount;② 可为 Pod 指定自定义 ServiceAccount,控制 Pod 访问 K8s API 的权限;③ 避免使用 default ServiceAccount 赋予过高权限。
常用操作 ① 创建 Role:kubectl create role pod-reader --verb=get,list --resource=pods -n dev;② 创建 RoleBinding:kubectl create rolebinding user1-pod-reader --role=pod-reader --user=user1 -n dev;③ 查看权限:kubectl auth can-i delete pods -n dev --as=user1
实操方向
  • 基础:创建一个仅允许「查看 dev Namespace 下 Pod」的 Role,绑定给测试用户,验证权限;
  • 进阶:为 StatefulSet 的 Pod 创建自定义 ServiceAccount,仅允许其访问 K8s API 获取自身标签,禁止删除资源;
  • 生产要点:避免给 ServiceAccount 赋予 cluster-admin 超级权限,遵循「最小权限原则」。
3. HPA(Horizontal Pod Autoscaler)—— 自动扩缩容
核心定位

根据 Pod 的 CPU / 内存使用率、自定义指标(如 QPS)自动调整 Deployment/StatefulSet 的 Pod 副本数,实现「负载高时扩容、负载低时缩容」,提升资源利用率,是应对流量波动的核心能力。

学习重点

表格

知识点 核心内容
核心指标 ① 基础指标:CPU 使用率(默认)、内存使用率;② 自定义指标:需部署 Metrics Server + 自定义监控(如 Prometheus),支持 QPS、请求数等;③ 指标来源:Metrics Server(基础指标)、Prometheus Adapter(自定义指标)。
配置规则 ① 最小 / 最大副本数:minReplicas: 2maxReplicas: 10;② 目标指标:targetCPUUtilizationPercentage: 80(CPU 使用率 80% 触发扩容);③ 扩缩容冷却时间:避免频繁扩缩(默认 3 分钟扩容冷却,5 分钟缩容冷却)。
常用操作 ① 创建 HPA:kubectl autoscale deployment nginx-deployment --min=2 --max=10 --cpu-percent=80;② 查看 HPA 状态:kubectl get hpa;③ 手动触发扩缩容验证:kubectl run -it --rm load-generator --image=busybox -- /bin/sh -c "while true; do wget -q -O - http://nginx-service; done"
限制条件 ① 仅支持 Deployment/StatefulSet(不支持裸 Pod/Job);② 需提前部署 Metrics Server(集群默认未安装);③ 扩缩容依赖节点资源充足。
实操方向
  • 基础:部署 Metrics Server,为 Nginx Deployment 创建 HPA(CPU 阈值 50%),用压测工具模拟流量,验证 Pod 自动扩容;
  • 进阶:配置基于内存 + CPU 双指标的 HPA,或基于 Prometheus 自定义指标(如 Nginx QPS)的 HPA;
  • 生产要点:设置合理的 minReplicas 避免缩容到 0,配置 PodDisruptionBudget 保证扩缩容时服务可用性。
二、第二梯队:进阶扩展(生产环境必备,适配复杂场景)
4. ResourceQuota & LimitRange —— 资源管控
核心定位
  • ResourceQuota:限制 Namespace 级别的总资源使用(如最多 10 个 Pod、总 CPU 不超过 4 核),防止单个团队 / 环境占用过多集群资源;
  • LimitRange:限制 Pod/Container 级别的资源(如每个容器最小 / 最大 CPU 0.1-1 核),避免单个 Pod 占用过多资源。
学习重点
  • ResourceQuota 配置:为 Namespace 设定 hard 限制(如 pods: 10requests.cpu: 4);
  • LimitRange 配置:为容器设定默认资源限制(如默认 request CPU 0.1 核,limit CPU 0.5 核),避免用户未配置资源导致的资源竞争;
  • 实操:为 dev Namespace 配置 ResourceQuota + LimitRange,验证超出限制时部署 Pod 会失败。
5. PodDisruptionBudget(PDB)—— 服务高可用保障
核心定位

限制「自愿中断」的 Pod 数量(如 HPA 缩容、节点维护、Deployment 更新),保证至少有 N 个 Pod 可用,避免服务中断。例如:配置 PDB 保证 Nginx 至少有 1 个 Pod 运行,即使缩容 / 更新也不会全部下线。

学习重点
  • 核心配置:minAvailable: 1(至少 1 个 Pod 可用)或 maxUnavailable: 1(最多 1 个 Pod 不可用);
  • 适配场景:Deployment 滚动更新、HPA 缩容、节点驱逐;
  • 实操:为 Nginx Deployment 创建 PDB,验证滚动更新时始终有 Pod 可用。
6. Taints & Tolerations —— 节点调度管控
核心定位

实现「节点污点(Taint)+ Pod 容忍(Toleration)」的调度规则,控制 Pod 只能调度到指定节点。例如:给 GPU 节点加污点,只有带对应容忍的 Pod 才能调度到该节点;给生产节点加污点,避免测试 Pod 调度到生产节点。

学习重点
  • 污点类型:NoSchedule(不调度新 Pod)、PreferNoSchedule(尽量不调度)、NoExecute(驱逐已有 Pod);
  • 核心操作:① 给节点加污点:kubectl taint nodes node1 key=value:NoSchedule;② 给 Pod 加容忍:在 spec.tolerations 中配置对应 key/value/effect;
  • 实操:给 Minikube 节点加污点,仅让 Nginx Pod (带容忍)调度到该节点。
7. Node Affinity —— 节点亲和性
核心定位

更灵活的节点调度规则(替代老旧的 nodeSelector),支持「硬亲和性」(必须满足条件)和「软亲和性」(尽量满足),控制 Pod 调度到符合标签的节点。例如:将数据库 Pod 调度到「磁盘类型 = SSD」的节点,将测试 Pod 调度到「环境 = test」的节点。

学习重点
  • 硬亲和性:requiredDuringSchedulingIgnoredDuringExecution(调度时必须满足,否则 Pod Pending);
  • 软亲和性:preferredDuringSchedulingIgnoredDuringExecution(调度时尽量满足,不满足也能调度);
  • 实操:为 StatefulSet 的 Redis Pod 配置硬亲和性,仅调度到带 disk=ssd 标签的节点。
三、第三梯队:高级进阶(适配大规模 / 高可用集群)
8. Operator —— 有状态应用自动化运维
核心定位

基于 CRD(自定义资源)+ Controller 实现有状态应用(如 MySQL/Elasticsearch/Zookeeper)的自动化运维,替代手动管理 StatefulSet/PVC。例如:MySQL Operator 可自动实现主从切换、备份恢复、扩缩容,大幅降低运维成本。

学习重点
  • 核心组件:CRD(自定义资源,如 MySQLCluster)+ Controller(监听 CRD 变化,自动创建 StatefulSet/PVC/Service);
  • 常用 Operator:MySQL Operator、Elasticsearch Operator、Prometheus Operator;
  • 实操:部署 Prometheus Operator,通过 CRD 快速创建 Prometheus/Grafana 实例。
9. Ingress-NGINX 高级配置 —— 生产级网关
核心定位

在基础 Ingress 路由的基础上,配置 HTTPS 证书自动续期(Let's Encrypt)、请求限流、跨域、重定向、灰度发布(Canary)等生产级特性,将 Ingress 作为集群统一网关。

学习重点
  • HTTPS 自动续期:结合 cert-manager 实现 Let's Encrypt 证书自动申请 / 续期;
  • 灰度发布:通过 Ingress 注解实现基于权重 / Header 的流量切分;
  • 限流与防护:配置请求限流(nginx.ingress.kubernetes.io/limit-rps)、跨域(CORS)、IP 黑白名单;
  • 实操:为 Nginx Ingress 配置 HTTPS 自动续期 + 基于权重的灰度发布。
10. Cluster Autoscaler —— 集群节点自动扩缩容
核心定位

当集群资源不足时自动扩容节点(如云厂商 ECS/EKS),资源充足时自动缩容节点,结合 HPA 实现「Pod 扩容 → 节点扩容」的全自动化,适配大规模弹性场景。

学习重点
  • 适配环境:云厂商集群(AWS EKS、阿里云 ACK、腾讯云 TKE);
  • 核心配置:关联云厂商节点池,配置扩缩容阈值(如节点资源使用率 80% 触发扩容);
  • 实操:在阿里云 ACK 中部署 Cluster Autoscaler,验证 Pod 扩容时自动创建新节点。
11. 监控与日志 —— 集群可观测性
核心定位

生产集群必备的可观测性能力,包括「监控(Metrics)、日志(Logs)、链路追踪(Tracing)」,及时发现并定位问题。

学习重点
  • 监控:Prometheus + Grafana 监控集群 / 应用指标(CPU / 内存 / QPS),配置告警(Alertmanager);
  • 日志:EFK/ELK 栈(Elasticsearch + Fluentd/Fluent Bit + Kibana)收集 Pod 日志,实现日志检索;
  • 链路追踪:Jaeger/Zipkin 追踪微服务调用链路;
  • 实操:部署 Prometheus + Grafana 监控 K8s 集群,部署 Fluent Bit 收集 Pod 日志到 Elasticsearch。
总结

按「从易到难、从基础到生产」的学习顺序,推荐路径:

  1. 第一梯队(必学):Namespace → RBAC → HPA → ResourceQuota/LimitRange;
  2. 第二梯队(生产必备):PDB → Taints&Tolerations → Node Affinity;
  3. 第三梯队(大规模集群):Operator → Ingress 高级配置 → Cluster Autoscaler → 监控日志。

每学习一个知识点,建议结合你已掌握的 Nginx/Redis 示例实操(如为 Redis StatefulSet 配置 PDB、为 Nginx Ingress 配置 HTTPS 自动续期),将知识点落地到实际场景中,加深理解


4)云原生架构开箱:4 层体系,一次性串完

你只要记住这个架构图:

  1. 应用层:微服务 / AI 模型服务(TensorFlow、TorchServe、vLLM)
  2. 调度层:K8s 核心(Deployment、StatefulSet、Job)
  3. 流量层:Service + Ingress / Gateway API
  4. 运维层:监控、日志、存储、CI/CD

学习法:每层只学 1 个工具,跑通链路就算会。

云原生应用层:微服务 + AI 模型服务

一、云原生应用层:微服务(Microservices)
1. 基础认知
微服务是什么
  • 把一个大应用拆成多个独立、小、自治的服务
  • 每个服务:独立开发、独立部署、独立扩缩容
  • 服务之间通过 HTTP/gRPC 通信

云原生微服务的核心目标

  • 高可用、弹性、可观测、可自动恢复
  • 完全跑在 K8s 上

微服务 ≠ 分布式微服务强调:业务边界 + 独立部署 + 独立团队


2. 核心配置(在 K8s 里必须有的一套)
(1)服务基础部署
  • Deployment / StatefulSet
  • Service(ClusterIP)
  • Ingress / API Gateway
  • ConfigMap + Secret
(2)微服务治理标配
  • 服务发现
  • 负载均衡
  • 限流、熔断、降级
  • 链路追踪
  • 监控告警
  • 日志统一收集
(3)常用技术栈(云原生事实标准)
  • 通信:HTTP /gRPC
  • 网关:Ingress-NGINX、APISIX、Kong
  • 服务治理:Spring Cloud / Istio / Dapr
  • 可观测:Prometheus + Grafana + Jaeger + ELK

3. 实操场景(你能立刻练的)
场景 1:最简单微服务部署
  • 服务 A:用户服务(Deployment + Service)
  • 服务 B:订单服务(Deployment + Service)
  • 服务 A 调用 服务 B:http://order-service.{namespace}.svc.cluster.local
场景 2:统一入口(网关)
  • 外部访问:api.xxx.com/user → 用户服务api.xxx.com/order → 订单服务
场景 3:服务治理
  • 超时控制
  • 重试
  • 熔断(防止级联故障)
  • 限流(保护后端)
场景 4:可观测
  • 看每个服务的 QPS、延迟、错误率
  • 看一次请求跨多少服务(链路追踪)
  • 日志统一检索

4. 进阶扩展
  • Service Mesh(服务网格):Istio / Linkerd无侵入式治理,不用改代码
  • gRPC 云原生部署:HTTP/2、长连接、流式、强类型
  • Serverless 微服务:Knative缩到 0、按调用收费、自动弹性
  • 多环境、多集群微服务
  • 灰度 / 金丝雀发布
  • 混沌测试:主动杀服务、杀节点,验证健壮性

二、云原生应用层:AI 模型服务(AI Model Serving)
1. 基础认知

AI 模型服务 = 把训练好的模型变成 API

  • 输入:文本 / 图片 / 特征
  • 输出: embedding / 分类结果 / 生成文本 / 检测框

云原生 AI 服务特点

  • GPU 资源调度
  • 高并发、低延迟
  • 自动扩缩容(HPA 非常关键)
  • 多模型、多版本管理

和微服务的区别

  • 更依赖硬件(GPU)
  • 推理性能敏感
  • 框架更专用(TensorRT、TorchServe、Triton、vLLM)

2. 核心配置
(1)部署底座
  • Deployment / StatefulSet(推理服务)
  • GPU 资源声明(nvidia.com/gpu: 1)
  • Service + Ingress(提供 API)
(2)资源与调度
  • 节点亲和性(只调度到 GPU 节点)
  • 污点与容忍(Taint/Toleration)
  • 资源限制:CPU / 内存 / 显存
(3)推理引擎(必须掌握)
  • Triton Inference Server(多框架、生产级)
  • vLLM(大模型 LLM 推理超快)
  • TorchServe
  • TensorFlow Serving
(4)弹性与高可用
  • HPA(基于 GPU/CPU/QPS 自动扩缩)
  • 多副本
  • 健康检查

3. 实操场景
场景 1:基础模型服务部署
  • 模型:ResNet / BERT / 小 LLaMA
  • 容器化 → 部署到 K8s → 暴露 API
场景 2:GPU 调度

yaml

resources:
  limits:
    nvidia.com/gpu: 1
场景 3:大模型(LLM)API 服务
  • vLLM + OpenAI 兼容接口
  • 支持流式输出(streaming)
  • 并发、批量处理
场景 4:多模型统一管理
  • Triton 同时跑:PyTorch、TensorRT、ONNX
  • 支持版本控制、A/B 测试
场景 5:弹性 AI 服务
  • 低峰:1 副本
  • 高峰:自动扩到 6 副本
  • 用 HPA + GPU 节点自动扩缩(Cluster Autoscaler)

4. 进阶扩展
  • 模型热更新:不重启容器更新模型
  • 模型缓存:热点模型加速
  • 多 GPU / 分布式推理
  • 量化、TensorRT 加速
  • 模型监控:延迟、吞吐量、准确率漂移
  • AI Workflow:推理 + 预处理 + 后处理 流水线
  • 多集群统一模型分发

三、微服务 & AI 模型服务 对比速览

表格

维度 微服务 AI 模型服务
核心依赖 CPU、网络 CPU/GPU、显存、模型文件
扩缩容依据 CPU、QPS、延迟 GPU 利用率、并发、排队长度
通信方式 HTTP/gRPC HTTP/gRPC(流式更常见)
关键组件 网关、注册中心、治理、链路追踪 推理引擎、GPU 调度、模型管理
典型中间件 Spring Cloud、Istio、APISIX Triton、vLLM、TorchServe

调度层:K8s 核心

一、基础认知:什么是 K8s 调度层?

一句话:调度层 = 决定 “这个 Pod 应该跑在哪个 Node 节点上” 的整套系统。

核心作用
  • 自动为 Pod 选择最优节点
  • 保证集群资源合理利用
  • 满足业务约束(GPU、地域、高可用、亲和性等)
  • 保证服务稳定性、高可用、性能
调度层的核心组件
  1. kube-schedulerK8s 官方默认调度器,负责 “选节点”。
  2. Node工作节点,提供 CPU、内存、GPU、存储。
  3. Pod调度的最小单元。
  4. 调度策略 / 规则亲和性、污点、容忍、资源限制等。

二、核心认知:调度层到底做什么?
1. 过滤(Predicate)

先去掉不能运行这个 Pod 的节点:

  • 资源不够(CPU / 内存不足)
  • 端口冲突
  • 节点有污点(Taint)
  • 不满足亲和性
  • 节点宕机 / 被封锁
2. 打分(Priority)

在剩下的节点里选最优

  • 资源利用率最均衡
  • 就近(拓扑分布)
  • 负载最低
  • 亲和性最高
3. 绑定(Bind)

最终决定:Pod → Node


三、K8s 调度层核心能力(必须掌握)

我按使用频率从高到低给你列全:

1. 资源调度(最基础)

作用:保证 Pod 不被 “饿死”,不占满节点。

2. 节点选择(NodeSelector)

最简单的调度:

yaml

nodeSelector:
  disk: ssd
  env: prod
3. 节点亲和性(Node Affinity)
  • 硬亲和:必须调度到某类节点
  • 软亲和:尽量调度到某类节点

更灵活,支持多条件、与或非。

4. 污点与容忍(Taints & Tolerations)
  • Taint(污点):节点拒绝 Pod
  • Toleration(容忍):Pod 我能接受这个污点

典型场景:

  • GPU 节点
  • 专属节点(数据库、大数据)
  • 主节点隔离
5. Pod 亲和性 / 反亲和性
  • 亲和:两个 Pod 尽量放一起(性能好)
  • 反亲和:两个 Pod 尽量分开(高可用)

典型场景:

  • 服务主副本不允许在同一节点
  • 缓存和应用就近部署
6. 拓扑调度(Topology Spread Constraints)

按:

  • 节点
  • 机架
  • 可用区(AZ)
  • 地域均匀打散 Pod,保证高可用。
7. 优先级与抢占(Priority & Preemption)
  • 重要业务 Pod 可以 “挤掉” 低优先级 Pod
  • 保证核心服务先运行

四、标准调度流程(面试 / 架构都用得到)
  1. Pod 创建 → 进入 Pending
  2. API Server 通知 kube-scheduler
  3. 过滤:去掉不符合条件的节点
  4. 打分:对剩下节点排序
  5. 绑定:将 Pod 分配到得分最高节点
  6. kubelet 在节点上启动 Pod

五、调度层 核心配置模板(你直接能复制用)
1. 节点亲和性(硬限制 + 软限制)

yaml

affinity:
  nodeAffinity:
    requiredDuringSchedulingIgnoredDuringExecution:
      nodeSelectorTerms:
      - matchExpressions:
        - key: gpu
          operator: In
          values: ["true"]
    preferredDuringSchedulingIgnoredDuringExecution:
    - weight: 1
      preference:
        matchExpressions:
        - key: env
          operator: In
          values: ["prod"]
2. 污点容忍(调度到 GPU 节点)

yaml

tolerations:
- key: nvidia.com/gpu
  operator: Exists
  effect: NoSchedule
3. Pod 反亲和性(高可用)

yaml

podAntiAffinity:
  requiredDuringSchedulingIgnoredDuringExecution:
  - labelSelector:
      matchExpressions:
      - key: app
        operator: In
        values: ["my-service"]
    topologyKey: kubernetes.io/hostname
4. 拓扑分布约束(跨节点打散)

yaml

topologySpreadConstraints:
- maxSkew: 1
  topologyKey: kubernetes.io/hostname
  whenUnsatisfiable: DoNotSchedule
  labelSelector:
    matchLabels:
      app: my-app

六、调度层 典型实操场景
1. CPU 密集型服务
  • 节点亲和:高 CPU 机型
  • 资源 request/limit 严格
2. GPU 任务(AI 训练 / AI 推理)
  • 污点 + 容忍
  • GPU 资源声明
  • 节点亲和:只调度到 GPU 节点
3. 微服务高可用
  • Pod 反亲和
  • 拓扑跨节点、跨可用区
4. 有状态服务(StatefulSet)
  • 固定节点调度
  • 本地存储 + 亲和性
5. 批处理任务(Job/CronJob)
  • 低优先级
  • 抢占式调度
  • 空闲节点运行

七、调度层 进阶扩展(云原生架构师必备)
1. 自定义调度器

替换默认 kube-scheduler,适合超大规模集群。

2. 调度器插件(Scheduler Framework)
  • 自定义过滤
  • 自定义打分
  • 公司级调度策略
3. 集群自动扩缩容(Cluster Autoscaler)
  • Pod 调度不了 → 自动买新节点
  • 节点空闲 → 自动释放
4. 调度性能优化
  • 调度并发
  • 缓存优化
  • 批量调度
5. 多集群调度(Karmada / KubeFed)
  • 跨区域、跨云、多集群统一调度
  • 全球分布式架构
6. 弹性调度 + 混部
  • 在线服务(微服务 / AI 推理)
  • 离线任务(大数据 / 训练)
  • 同一集群混跑,提高利用率

八、一句话总结调度层

K8s 调度层 = 集群的 “指挥中心”,负责把所有 Pod 放到最合适的节点,保证资源最优、高可用、业务稳定。

它是:

  • 微服务部署的基础
  • AI 模型服务(GPU)的核心
  • 有状态服务的依赖
  • 云原生架构的 “底盘”

流量层:Service + Ingress / Gateway API

一、基础认知:流量层到底干什么?

一句话:流量层 = 负责 “请求怎么进到容器里、怎么在服务之间转发” 的整套机制。

它解决 3 个问题:

  1. 外部用户 → 集群内服务怎么访问?
  2. 服务 A → 服务 B 怎么稳定调用?
  3. 流量怎么路由、灰度、限流、安全?
两层流量结构(最经典、最标准)
  • 内部流量:Service集群内部服务互相访问
  • 外部流量:Ingress / Gateway API外部域名 + 路由进入集群

二、核心 1:Service(内部流量核心)
1. 基础认知

Service 是 K8s 官方稳定的服务发现 + 负载均衡

  • Pod IP 会变,但 Service IP 不变
  • 自动代理到后端 Pod
  • 服务间调用用域名:service-name.namespace.svc.cluster.local
2. 四种类型(必须掌握)
① ClusterIP(默认)
  • 仅集群内部可访问
  • 微服务之间调用
  • 最常用
② NodePort
  • 在每个节点开端口
  • 外部可访问,但不生产级
③ LoadBalancer
  • 云厂商自动创建 LB
  • 外部直接访问
  • 成本高,不适合大量服务
④ ExternalName
  • 映射到外部域名
  • 集群访问外部服务用
3. 工作原理
  • kube-proxy 维护 iptables/ipvs 规则
  • 访问 Service → 转发到任意健康 Pod
  • 四层负载均衡(TCP/UDP)
4. 核心配置(极简模板)

yaml

apiVersion: v1
kind: Service
metadata:
  name: user-service
spec:
  type: ClusterIP
  selector:
    app: user-service
  ports:
  - port: 80        # Service 端口
    targetPort: 8080 # 容器端口

三、核心 2:Ingress(七层外部流量入口)
1. 基础认知
  • 七层 HTTP/HTTPS 流量入口
  • 基于域名 + 路径路由到不同 Service
  • 统一入口:SSL、限流、重写、跨域
2. 核心能力
  • 域名路由
  • 多域名、多服务
  • HTTPS 证书(Secret)
  • path 路由 / 重写
  • 黑白名单、限流
3. 组成
  • Ingress 资源:你写的路由规则
  • Ingress Controller:真正执行转发(如 nginx-ingress)
4. 标准模板

yaml

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: app-ingress
  annotations:
    nginx.ingress.kubernetes.io/ssl-redirect: "true"
spec:
  tls:
  - hosts:
    - api.example.com
    secretName: ssl-tls
  rules:
  - host: api.example.com
    http:
      paths:
      - path: /user
        pathType: Prefix
        backend:
          service:
            name: user-service
            port:
              number: 80
      - path: /ai
        backend:
          service:
            name: ai-service
            port:
              number: 80

四、核心 3:Gateway API(下一代标准)
1. 基础认知

Gateway API = Ingress 的升级版

  • 更灵活
  • 更安全
  • 更云原生
  • 支持流量灰度、权重、HTTP/gRPC/TCP 统一管理
2. 三个核心对象
① Gateway

网关本身:监听端口、TLS

② HTTPRoute

路由规则:域名、path、header、权重

③ ReferenceGrant

权限控制(哪个命名空间能用网关)

3. 优势(为什么要学)
  • 支持流量切分(金丝雀)
  • 支持请求头改写
  • 支持权重路由
  • 支持gRPC、TCP
  • 角色分离:运维管网关,开发管路由
4. 核心定位

未来云原生流量标准,正在逐步替代 Ingress


五、三者关系(最清晰总结)

plaintext

外部用户
   ↓
LB(云厂商)
   ↓
Ingress / Gateway API (七层路由)
   ↓
Service(四层负载均衡 + 服务发现)
   ↓
Pod
  • Service:内部流量枢纽
  • Ingress:外部 HTTP 入口
  • Gateway API:下一代统一流量网关

六、典型实操场景(你能直接用)
1. 微服务统一入口

plaintext

api.example.com/user → user-service
api.example.com/order → order-service
api.example.com/ai → ai-service
2. HTTPS 统一证书

所有服务共用一个证书,通过 Ingress 配置。

3. AI 模型服务流式输出
  • vLLM / Triton
  • 流式响应
  • 长连接保持
  • 由 Ingress 或 Gateway 提供
4. 灰度发布(Gateway API 最强)
  • 90% 流量 → v1
  • 10% 流量 → v2

七、进阶扩展(架构师级别)
  • TCP /gRPC 暴露
  • 限流、熔断、重试
  • 灰度 / 金丝雀 / A/B 测试
  • WAF 防护
  • 多集群网关
  • API 管理:认证、授权、限流、计费
  • Service Mesh + Gateway 集成(Istio)

八、最简单记忆口诀
  • Service 管内部
  • Ingress 管外部 HTTP
  • Gateway API 是未来统一入口

运维层:监控、日志、存储、CI/CD

(云原生稳定运行的 “底盘”)


一、整体定位

运维层 = 让微服务 + AI 模型服务在 K8s 上稳定、自动化、可追溯地运行。

它负责 4 件事:

  1. 看得见(监控)
  2. 查得清(日志)
  3. 存得住(存储)
  4. 自动发(CI/CD)

二、1. 监控(Monitoring)
基础认知
  • 实时看系统运行状态
  • 出问题能告警、定位、复盘
核心组件(云原生事实标准)
  • Prometheus:采集、存储指标
  • Grafana:大盘展示
  • AlertManager:告警(钉钉 / 企业微信 / 邮件)
  • Metrics Server:给 HPA 提供数据
监控看什么
  • 集群:节点 CPU、内存、磁盘、网络
  • 容器:Pod CPU、内存、重启次数
  • 业务:QPS、延迟、错误率
  • AI:GPU 使用率、推理耗时、并发
核心价值
  • 自动发现问题
  • 自动弹性扩缩容(HPA)
  • 容量规划
  • 稳定性保障

三、2. 日志(Logging)
基础认知
  • 记录程序运行轨迹
  • 出问题追溯、排查、审计
标准架构:EFK / PLG
  • EFK
    • Elasticsearch:存日志
    • Fluentd / Fluent Bit:收集日志
    • Kibana:查询、展示
  • PLG(轻量)
    • Promtail + Loki + Grafana
日志收集方式
  • 容器 stdout
  • 宿主机文件
  • 容器内挂载日志文件
核心价值
  • 问题快速定位
  • 行为审计
  • 安全分析
  • 业务统计

四、3. 存储(Storage)
基础认知
  • 给容器提供持久化数据
  • Pod 删了数据不丢
K8s 存储三件套
  • PV:集群存储空间
  • PVC:容器申请空间
  • StorageClass:自动创建云盘 / 存储
存储使用场景
  • 数据库:MySQL、PostgreSQL、Redis
  • AI 模型:模型文件、权重、缓存
  • 业务:上传文件、导出报表、日志归档
核心价值
  • 有状态服务底座
  • 数据不丢
  • 动态扩容

五、4. CI/CD(持续集成 / 持续部署)
基础认知
  • 代码提交 → 自动构建 → 自动部署
  • 全流程自动化,不手工操作服务器
主流工具
  • GitLab CI
  • Jenkins
  • GitHub Actions
  • ArgoCD(GitOps 云原生主流)
标准流程
  1. 代码 push → Git
  2. 自动构建镜像
  3. 自动扫描安全漏洞
  4. 自动更新 K8s YAML
  5. 自动发布到测试 / 预发 / 生产
核心价值
  • 发布效率提升 10~100 倍
  • 降低人为失误
  • 可回滚、可追溯
  • 支持灰度、蓝绿

六、运维层整体架构图(极简可直接用)

plaintext

┌─────────────────────────────────────────────────────┐
│                    业务应用层                       │
│              微服务 / AI 模型服务                   │
└───────────────────────┬─────────────────────────────┘
                        │
┌───────────────────────┼─────────────────────────────┐
│                       ▼                             │
│                运维层(四大件)                       │
│                                                    │
│  ┌─────────────┬────────────┬────────┬─────────┐  │
│  │   监控      │    日志     │  存储  │  CI/CD  │  │
│  │ Prometheus  │  EFK/Loki   │ PV/PVC │ GitLab  │  │
│  │ Grafana     │ Fluent Bit │ SC     │ ArgoCD  │  │
│  └─────────────┴────────────┴────────┴─────────┘  │
│                                                    │
└───────────────────────┬─────────────────────────────┘
                        │
                        ▼
┌─────────────────────────────────────────────────────┐
│                     K8s 集群                         │
└─────────────────────────────────────────────────────┘

七、一句话总结运维层

监控让你 “看得见”,日志让你 “查得清”,存储让你 “存得稳”,CI/CD 让你 “发得快”。

它们共同保证:微服务 + AI 模型服务在 K8s 上稳定、高效、自动化运行。


5)AI + K8S 开箱:直接学「AI 云原生落地三件套」

现在企业最缺的就是这个:

  1. 模型推理部署

    • K8s + TorchServe / Triton / vLLM

K8s + TorchServe / Triton /vLLM 到底是什么?

一句话总结:就是把训练好的 AI 模型,变成一个可以在线调用的 API 服务,并且跑在 K8s 上,实现自动扩缩容、高可用、GPU 调度。


1. 先拆成 2 部分看
① K8s 是什么角色?

AI 模型的 “运行平台 + 管理员”

  • 负责把模型服务启动、重启、扩缩容
  • 负责GPU 分配、节点调度、高可用
  • 负责流量分发、负载均衡
  • 负责监控、日志、自动恢复

你可以理解:K8s = 模型服务的云原生底座


② TorchServe / Triton /vLLM 是什么角色?

它们是 3 种不同的 “模型推理引擎”= 专门把模型变成 API 的工具。

就像:

  • Web 服务用 Tomcat、Nginx
  • AI 模型服务用 TorchServe、Triton、vLLM

2. 三个工具分别干什么?(超级清晰)
🔥 TorchServe

专门给 PyTorch 模型用的推理服务器

  • 官方出品,简单、轻量
  • 适合:小模型、常规模型、个人 / 小团队
  • 提供 HTTP API:/predict/health

优点:

  • 开箱即用
  • PyTorch 生态完美支持
  • 适合快速上线

缺点:

  • 性能一般
  • 不适合超大模型(LLM)

🔥 Triton Inference Server(英伟达出品)

企业级、多框架、高性能统一推理引擎

  • 支持 PyTorch、TensorFlow、ONNX、TensorRT
  • 支持 CPU/GPU
  • 支持并发、批处理、动态调度
  • 生产级工业标准

优点:

  • 性能极强
  • 多模型、多版本管理
  • 支持流水线、模型编排
  • 大厂标配:腾讯、阿里、字节、百度都用

适合:

  • 公司级 AI 平台
  • 多模型统一管理
  • 高并发、低延迟场景

🔥 vLLM(最火的大模型推理引擎)

专门给 LLM 大模型(如 Llama、Qwen、GLM)做高速推理

  • 主打一个:快、快、超快
  • 用 PagedAttention 技术,比传统方式快 10~20 倍
  • 支持流式输出(streaming)
  • 兼容 OpenAI 接口

优点:

  • LLM 大模型部署神器
  • 显存利用率极高
  • 支持高并发聊天、生成

适合:

  • 对话机器人
  • 文生文
  • 私有化大模型 API

3. 放在一起:K8s + TorchServe / Triton /vLLM 是什么?

就是:

把 AI 模型→ 装进容器→ 用 TorchServe / Triton /vLLM 提供 API→ 跑在 K8s 上→ 实现:高可用、自动扩缩容、GPU 调度、灰度发布、监控告警


用生活类比(秒懂)
  • K8s = 商场 / 机房
  • TorchServe / Triton / vLLM = 售货机 / 服务台
  • AI 模型 = 商品
  • 用户请求 = 顾客

顾客 → 商场 → 售货机 → 拿到商品用户 → K8s → 推理引擎 → 拿到模型结果


4. 最实用的选型口诀(直接背)
  • 小模型、PyTorch、简单部署 → TorchServe
  • 企业多模型、高性能、统一管理 → Triton
  • 大模型 LLM、对话、高并发 → vLLM
  • 全都跑在 K8s 上 → 云原生 AI 服务

5. 架构长这样(极简图)

plaintext

用户请求
   ↓
Ingress / API 网关
   ↓
K8s Service(负载均衡)
   ↓
Pod 里跑着:
   TorchServe 或 Triton 或 vLLM
   ↓
加载 AI 模型,返回结果
开箱即用的 K8s YAML 部署模板

两套开箱即用的 K8s YAML 部署模板—— 分别是 K8s + vLLM(大模型推理)、K8s + Triton(多模型统一推理),你只需要替换模型地址 / 参数,就能直接部署出生产级的 AI 模型服务。

说明
  • 所有配置已做生产级优化(资源限制、健康检查、GPU 调度、弹性扩缩容);
  • 基于 NVIDIA GPU 环境(需集群已安装 NVIDIA 设备插件);
  • 部署前确保集群有 GPU 节点(标注 gpu: "true")。

一、K8s + vLLM 部署模板(大模型推理)
核心场景:LLM 大模型(如 Llama3、Qwen、GLM)提供 OpenAI 兼容 API,支持流式输出

yaml

# 1. Service(负载均衡 + 服务发现)
apiVersion: v1
kind: Service
metadata:
  name: vllm-service
  labels:
    app: vllm
spec:
  type: ClusterIP
  selector:
    app: vllm
  ports:
  - port: 8000
    targetPort: 8000
    name: http
---
# 2. Deployment(vLLM 推理服务)
apiVersion: apps/v1
kind: Deployment
metadata:
  name: vllm-deployment
  labels:
    app: vllm
spec:
  replicas: 1
  selector:
    matchLabels:
      app: vllm
  template:
    metadata:
      labels:
        app: vllm
    spec:
      # 仅调度到 GPU 节点
      affinity:
        nodeAffinity:
          requiredDuringSchedulingIgnoredDuringExecution:
            nodeSelectorTerms:
            - matchExpressions:
              - key: gpu
                operator: In
                values: ["true"]
      # 容忍 GPU 节点污点
      tolerations:
      - key: nvidia.com/gpu
        operator: Exists
        effect: NoSchedule
      containers:
      - name: vllm
        # 官方 vLLM 镜像(已包含 CUDA)
        image: vllm/vllm-openai:latest
        ports:
        - containerPort: 8000
        # 启动命令:加载模型 + 开启 OpenAI 兼容 API
        command:
        - python
        - -m
        - vllm.entrypoints.openai.api_server
        args:
        - --model=Qwen/Qwen2-7B-Instruct  # 替换为你的模型(本地/ HuggingFace)
        - --port=8000
        - --host=0.0.0.0
        - --gpu-memory-utilization=0.9  # GPU 显存利用率(按需调整)
        - --max-num-batched-tokens=4096  # 批处理最大 Token 数
        - --enable-streaming  # 开启流式输出
        # 资源限制(按需调整)
        resources:
          limits:
            nvidia.com/gpu: 1  # 1 张 GPU
            cpu: "8"
            memory: "32Gi"
          requests:
            cpu: "4"
            memory: "16Gi"
        # 健康检查(生产必备)
        livenessProbe:
          httpGet:
            path: /health
            port: 8000
          initialDelaySeconds: 60  # 模型加载慢,延长初始化时间
          periodSeconds: 10
        readinessProbe:
          httpGet:
            path: /health
            port: 8000
          initialDelaySeconds: 60
          periodSeconds: 10
        # 模型缓存(可选:挂载 PVC 存储模型,避免每次重启重新下载)
        volumeMounts:
        - name: model-cache
          mountPath: /root/.cache/huggingface
      # 持久化模型缓存
      volumes:
      - name: model-cache
        persistentVolumeClaim:
          claimName: vllm-model-pvc  # 需提前创建 PVC
---
# 3. HPA(自动扩缩容,基于 GPU 利用率)
apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
  name: vllm-hpa
spec:
  scaleTargetRef:
    apiVersion: apps/v1
    kind: Deployment
    name: vllm-deployment
  minReplicas: 1
  maxReplicas: 4  # 最大 4 个副本
  metrics:
  - type: Pods
    pods:
      metric:
        name: nvidia_gpu_utilization  # GPU 利用率指标(需 Prometheus + NVIDIA 监控)
      target:
        type: AverageValue
        averageValue: 80  # GPU 利用率超 80% 扩容
  behavior:
    scaleUp:
      stabilizationWindowSeconds: 60  # 扩容冷却 60s
    scaleDown:
      stabilizationWindowSeconds: 300  # 缩容冷却 5 分钟
---
# 4. Ingress(外部访问入口)
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: vllm-ingress
  annotations:
    nginx.ingress.kubernetes.io/ssl-redirect: "true"
    nginx.ingress.kubernetes.io/proxy-body-size: "100m"
    nginx.ingress.kubernetes.io/connection-proxy-header: "keep-alive"  # 长连接(流式输出)
spec:
  tls:
  - hosts:
    - ai.example.com
    secretName: ai-tls-secret  # 需提前创建 SSL 证书 Secret
  rules:
  - host: ai.example.com
    http:
      paths:
      - path: /v1
        pathType: Prefix
        backend:
          service:
            name: vllm-service
            port:
              number: 8000
关键配置说明
  1. 模型替换:把 --model=Qwen/Qwen2-7B-Instruct 换成你的模型(支持本地路径 / HuggingFace 地址);
  2. GPU 资源:根据模型大小调整 nvidia.com/gpu 数量(如 70B 模型需 4 张 GPU);
  3. 流式输出--enable-streaming 开启后,支持 ChatGPT 风格的流式返回;
  4. 模型缓存:挂载 PVC 后,模型只需下载一次,重启 Pod 无需重新下载。
测试访问

bash

运行

# 集群内访问
curl http://vllm-service:8000/v1/models

# 外部访问(通过 Ingress)
curl https://ai.example.com/v1/chat/completions \
  -H "Content-Type: application/json" \
  -d '{
    "model": "Qwen/Qwen2-7B-Instruct",
    "messages": [{"role": "user", "content": "介绍下 K8s + vLLM"}],
    "stream": true
  }'

二、K8s + Triton Inference Server 部署模板(多模型统一推理)
核心场景:同时部署 PyTorch/ONNX/TensorRT 模型,提供统一推理 API

yaml

# 1. ConfigMap(Triton 模型配置)
apiVersion: v1
kind: ConfigMap
metadata:
  name: triton-model-config
data:
  # 模型仓库配置(示例:同时部署 ResNet(图像分类) + BERT(文本分类))
  model_repository: |
    model_repository/
    ├── resnet50/
    │   ├── 1/
    │   │   └── model.onnx  # 模型文件
    │   └── config.pbtxt   # 模型配置
    └── bert/
        ├── 1/
        │   └── model.pt
        └── config.pbtxt
  # ResNet 模型配置示例
  resnet50_config.pbtxt: |
    name: "resnet50"
    platform: "onnxruntime_onnx"
    max_batch_size: 32
    input [
      {
        name: "input_0"
        data_type: TYPE_FP32
        dims: [3, 224, 224]
      }
    ]
    output [
      {
        name: "output_0"
        data_type: TYPE_FP32
        dims: [1000]
      }
    ]
---
# 2. Service
apiVersion: v1
kind: Service
metadata:
  name: triton-service
  labels:
    app: triton
spec:
  type: ClusterIP
  selector:
    app: triton
  ports:
  - port: 8000
    targetPort: 8000
    name: http
  - port: 8001
    targetPort: 8001
    name: grpc
  - port: 8002
    targetPort: 8002
    name: metrics
---
# 3. Deployment
apiVersion: apps/v1
kind: Deployment
metadata:
  name: triton-deployment
  labels:
    app: triton
spec:
  replicas: 1
  selector:
    matchLabels:
      app: triton
  template:
    metadata:
      labels:
        app: triton
    spec:
      affinity:
        nodeAffinity:
          requiredDuringSchedulingIgnoredDuringExecution:
            nodeSelectorTerms:
            - matchExpressions:
              - key: gpu
                operator: In
                values: ["true"]
      tolerations:
      - key: nvidia.com/gpu
        operator: Exists
        effect: NoSchedule
      containers:
      - name: triton
        # NVIDIA 官方 Triton 镜像(带 CUDA)
        image: nvcr.io/nvidia/tritonserver:24.01-py3
        ports:
        - containerPort: 8000  # HTTP
        - containerPort: 8001  # gRPC
        - containerPort: 8002  # Metrics
        # 启动 Triton 服务器
        command:
        - tritonserver
        args:
        - --model-repository=/models  # 模型仓库路径
        - --http-port=8000
        - --grpc-port=8001
        - --metrics-port=8002
        - --model-control-mode=poll  # 自动加载模型
        - --load-model=all  # 加载所有模型
        # 资源限制
        resources:
          limits:
            nvidia.com/gpu: 1
            cpu: "8"
            memory: "32Gi"
          requests:
            cpu: "4"
            memory: "16Gi"
        # 健康检查
        livenessProbe:
          httpGet:
            path: /v2/health/live
            port: 8000
          initialDelaySeconds: 30
          periodSeconds: 10
        readinessProbe:
          httpGet:
            path: /v2/health/ready
            port: 8000
          initialDelaySeconds: 30
          periodSeconds: 10
        # 挂载模型文件(PVC 存储模型)
        volumeMounts:
        - name: triton-models
          mountPath: /models
      # 模型存储 PVC
      volumes:
      - name: triton-models
        persistentVolumeClaim:
          claimName: triton-model-pvc  # 需提前创建 PVC,放入模型文件
---
# 4. Ingress
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: triton-ingress
  annotations:
    nginx.ingress.kubernetes.io/ssl-redirect: "true"
spec:
  tls:
  - hosts:
    - triton.example.com
    secretName: triton-tls-secret
  rules:
  - host: triton.example.com
    http:
      paths:
      - path: /v2
        pathType: Prefix
        backend:
          service:
            name: triton-service
            port:
              number: 8000
关键配置说明
  1. 模型部署:把模型文件(ONNX/PyTorch/TensorRT)放到 triton-model-pvc 对应的 PV 路径下,按 Triton 目录结构组织;
  2. 多模型管理:支持同时部署多个模型,通过 config.pbtxt 定义输入输出格式、批处理大小;
  3. 协议支持:同时提供 HTTP/gRPC 接口,gRPC 适合低延迟、高并发场景;
  4. 监控指标:8002 端口暴露 Prometheus 指标,可监控推理延迟、吞吐量、GPU 使用率。
测试访问

bash

运行

# 查看已加载的模型
curl https://triton.example.com/v2/models

# 调用 ResNet 模型推理
curl -X POST https://triton.example.com/v2/models/resnet50/infer \
  -H "Content-Type: application/json" \
  -d '{
    "inputs": [
      {
        "name": "input_0",
        "shape": [1, 3, 224, 224],
        "datatype": "FP32",
        "data": [/* 图像数据 */]
      }
    ]
  }'

三、部署前置条件
  1. GPU 环境:K8s 集群已安装 NVIDIA 设备插件(nvidia-device-plugin);
  2. PVC 创建:提前创建用于存储模型的 PVC(参考之前 PV/PVC 教程);
  3. 监控配置:如需 HPA 基于 GPU 扩缩容,需部署 Prometheus + NVIDIA DCGM 监控;
  4. 镜像拉取:确保集群能拉取 vllm/vllm-openainvcr.io/nvidia/tritonserver 镜像(私有仓库需配置 Secret)。

四、核心总结
  1. vLLM 模板:专为 LLM 大模型优化,支持流式输出、OpenAI 兼容 API,开箱即用;
  2. Triton 模板:企业级多模型统一推理,支持多框架、批处理、高并发,适合规模化部署;
  3. 生产优化:包含健康检查、资源限制、GPU 调度、自动扩缩容,直接用于生产环境;
  4. 灵活调整:只需替换模型地址 / 配置,即可适配不同模型(小模型 / 大模型、CV/NLP)。

你可以先部署单副本测试,验证模型推理正常后,再开启 HPA 实现自动扩缩容,逐步扩到生产规模。

  1. AI 任务调度

    • K8s Job + Volcano 批量调度
K8s Job + Volcano 批量调度到底是什么?
一句话总结
  • K8s Job:跑一次性任务(数据处理、模型训练、数据清洗、离线计算)。
  • Volcano:专门给 AI / 大数据 / 批量任务 做的增强版 K8s 调度器
  • 合起来K8s + Volcano + Job = 云原生批量计算平台(AI 训练标配)

1. 先搞懂:原生 K8s Job 不够用在哪?

原生 Job 只能做简单任务,但AI 训练 / 分布式训练需要:

  • GPU 排队、抢占
  • 任务优先级(重要训练先跑)
  • 分布式训练调度(TensorFlow/PyTorch PS/Worker 模式)
  • 任务排队、批队列、资源池管理
  • binpack 优化(尽量塞满 GPU,不浪费)

原生 kube-scheduler 搞不定 → 所以要用 Volcano。


2. Volcano 是什么?

Volcano = 云原生批量计算调度引擎(CNCF 毕业项目)专门为这些场景设计:

  • AI 模型训练(PyTorch/TensorFlow/MindSpore)
  • 大数据(Spark、Flink)
  • 批量计算、离线任务
  • 渲染、仿真、基因测序

完全兼容 K8s Job,但强得多。


3. Volcano 核心能力(你必须知道的)

1)批量任务调度(Queue 队列)

任务太多排着等,有资源再跑。

2)GPU / 算力调度

  • 按 GPU 数量分配
  • 支持多卡、分布式训练

3)任务优先级 & 抢占

  • 高优先级任务可以 “抢” 低优先级任务的资源
  • 保证核心训练不排队

4)分布式训练调度(PS / Worker / Chief)

PyTorchDistributed、TensorFlow PS 架构直接支持。

5)Binpack 调度(塞满机器,省钱)

尽量把任务塞进同个节点,提高利用率。

6)多租户排队(团队隔离)

不同团队、不同项目有自己的队列和资源配额。

7)兼容原生 K8s Job

你原来的 Job YAML 几乎不用改。


4. K8s Job + Volcano 长什么样?

架构超级简单

plaintext

用户提交 Job
   ↓
Volcano 调度器(队列、优先级、GPU、资源池)
   ↓
分配到最合适的节点
   ↓
启动 Pod 执行任务(训练/数据处理)

5. 最直观对比:原生 Job vs Volcano

表格

特性 原生 K8s Job Volcano + Job
任务排队 ❌ 不支持 ✅ 支持
优先级 / 抢占 ❌ 弱 ✅ 强
分布式训练 ❌ 难 ✅ 原生支持
GPU 调度 ✅ 基础 ✅ 企业级
多租户队列 ❌ 无 ✅ 有
批处理能力 简单 专业级
场景 简单一次性任务 AI 训练、大数据、离线计算

6. 一句话定位(面试 / 架构都能背)
  • K8s Job:定义跑什么任务
  • Volcano:决定任务怎么排、谁先跑、跑在哪、用多少 GPU

Volcano 是 AI 训练平台的标配调度器。


7. 给你一段最经典的 Volcano Job YAML(可直接用)

yaml

apiVersion: batch.volcano.sh/v1alpha1
kind: Job
metadata:
  name: pytorch-train-job
spec:
  # 调度队列(Volcano 核心)
  schedulerName: volcano
  queue: default
  # 任务优先级
  priorityClassName: high-priority
  # 最大重试次数
  maxRetry: 3
  # 分布式训练:PyTorch Worker
  tasks:
  - name: worker
    replicas: 4  # 4 个 Worker 分布式训练
    template:
      spec:
        containers:
        - name: train
          image: pytorch/pytorch:2.0-cuda11.7-cudnn8-runtime
          command: ["python", "train.py"]
          resources:
            limits:
              nvidia.com/gpu: 1  # 每个Worker 1张GPU
          volumeMounts:
          - name: data
            mountPath: /data
        volumes:
        - name: data
          persistentVolumeClaim:
            claimName: training-data

8. 最常见使用场景(你一定会遇到)

1)AI 模型训练(最主流)

PyTorch / TensorFlow 分布式训练

2)数据预处理 / 清洗

大量离线 Job,排队跑

3)大数据 Spark / Flink 任务

Volcano 比原生调度稳定很多

4)批量推理

跑一批图片、视频、语音推理任务

5)渲染、仿真、基因测序

高算力、批量、排队任务


9. 超级好记的总结
  • K8s Job = 一次性任务
  • Volcano = 批量任务调度增强器
  • K8s Job + Volcano = 云原生 AI / 大数据 计算平台
开箱即用的 Volcano + PyTorch 分布式训练完整部署方案

开箱即用的 Volcano + PyTorch 分布式训练完整部署方案,包含「Volcano 安装 → 分布式训练 Job YAML → 任务提交 / 监控 → 结果验证」全流程,你只需替换训练脚本和数据地址,就能直接跑起分布式训练。

核心说明
  • 基于 PyTorch Distributed Data Parallel (DDP) 分布式训练(最主流的多卡 / 多机训练方式);
  • 适配 GPU 集群,支持 多 Worker + 多 GPU;
  • 包含 Volcano 队列、优先级、资源配额等生产级配置。

一、前置准备:安装 Volcano

1. 快速安装(推荐)

bash

运行

# 安装最新版 Volcano(兼容 K8s 1.20+)
kubectl apply -f https://raw.githubusercontent.com/volcano-sh/volcano/master/installer/volcano-development.yaml

# 验证安装(看到以下组件 Running 即成功)
kubectl get pods -n volcano-system
# 预期输出:
# NAME                                       READY   STATUS    RESTARTS   AGE
# volcano-admission-7f987d9c7f-xxxx         1/1     Running   0          5m
# volcano-controllers-7896d876c6-xxxx       1/1     Running   0          5m
# volcano-scheduler-5f97867894-xxxx        1/1     Running   0          5m

2. 创建 Volcano 队列(任务排队 / 资源隔离)

yaml

# volcano-queue.yaml
apiVersion: scheduling.volcano.sh/v1beta1
kind: Queue
metadata:
  name: ai-training-queue
spec:
  # 队列资源配额(限制该队列最多用 8 张 GPU、16核 CPU)
  resourceQuota:
    hard:
      nvidia.com/gpu: 8
      cpu: 16
      memory: 64Gi
  # 队列优先级(高优先级队列先调度)
  priority: 100

bash

运行

kubectl apply -f volcano-queue.yaml

# 验证队列
kubectl get queue
# 预期输出:
# NAME                CLUSTER   PRIORITY   STATE     AGE
# ai-training-queue   default   100        Open      10s

二、Volcano + PyTorch 分布式训练完整 YAML

1. 训练数据 PVC(持久化训练数据 / 模型)

yaml

# training-data-pvc.yaml
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: pytorch-training-pvc
spec:
  accessModes:
    - ReadWriteMany  # 多 Worker 共享读写
  resources:
    requests:
      storage: 100Gi
  storageClassName: nfs-storage  # 替换为你的共享存储类(如 NFS/CEPH)

bash

运行

kubectl apply -f training-data-pvc.yaml

2. 分布式训练 Job(核心配置)

yaml

# pytorch-ddp-training-job.yaml
apiVersion: batch.volcano.sh/v1alpha1
kind: Job
metadata:
  name: pytorch-ddp-training
  labels:
    app: pytorch-training
spec:
  # 指定 Volcano 调度器(核心)
  schedulerName: volcano
  # 绑定训练队列
  queue: ai-training-queue
  # 任务优先级(队列内优先级)
  priorityClassName: high-priority
  # 最大重试次数(训练失败自动重试)
  maxRetry: 3
  # 任务完成策略:所有 Worker 完成才算结束
  completionPolicy:
    type: AllCompletions
  # 分布式训练任务定义(Worker 节点)
  tasks:
  - name: ddp-worker
    # 4 个 Worker 节点(每个节点 1 张 GPU,共 4 卡训练)
    replicas: 4
    # 任务模板
    template:
      spec:
        # 仅调度到 GPU 节点
        affinity:
          nodeAffinity:
            requiredDuringSchedulingIgnoredDuringExecution:
              nodeSelectorTerms:
              - matchExpressions:
                - key: gpu
                  operator: In
                  values: ["true"]
        # 容忍 GPU 节点污点
        tolerations:
        - key: nvidia.com/gpu
          operator: Exists
          effect: NoSchedule
        # 容器配置
        containers:
        - name: pytorch-trainer
          # PyTorch 官方镜像(带 CUDA/分布式训练依赖)
          image: pytorch/pytorch:2.2.0-cuda12.1-cudnn8-runtime
          # 启动分布式训练脚本
          command:
          - /bin/bash
          - -c
          - |
            # 设置分布式训练环境变量
            export MASTER_ADDR=$(hostname -i)
            export MASTER_PORT=29500
            export WORLD_SIZE=4  # 总 Worker 数
            # 获取当前 Worker 序号(Volcano 自动注入 VOLCANO_TASK_INDEX)
            export RANK=${VOLCANO_TASK_INDEX}
            export LOCAL_RANK=0

            # 进入数据目录
            cd /data
            # 下载示例训练脚本(替换为你的脚本)
            wget -O train_ddp.py https://raw.githubusercontent.com/pytorch/examples/main/distributed/ddp/train_ddp.py
            # 启动分布式训练
            python -m torch.distributed.launch \
              --nproc_per_node=1 \
              --nnodes=${WORLD_SIZE} \
              --node_rank=${RANK} \
              --master_addr=$(kubectl get pod pytorch-ddp-training-ddp-worker-0 -o jsonpath='{.status.podIP}') \
              --master_port=29500 \
              train_ddp.py \
              --epochs=10 \
              --batch-size=64
          # 资源限制(每个 Worker 1 张 GPU、4 核 CPU、16Gi 内存)
          resources:
            limits:
              nvidia.com/gpu: 1
              cpu: 4
              memory: 16Gi
            requests:
              cpu: 2
              memory: 8Gi
          # 挂载训练数据/模型目录
          volumeMounts:
          - name: training-data
            mountPath: /data
          # 健康检查(训练任务长时间运行,关闭存活检查,仅做就绪检查)
          readinessProbe:
            exec:
              command: ["pgrep", "python"]
            initialDelaySeconds: 60
            periodSeconds: 30
        # 重启策略:训练失败不重启(由 Volcano 重试整个 Job)
        restartPolicy: Never
        # 挂载 PVC
        volumes:
        - name: training-data
          persistentVolumeClaim:
            claimName: pytorch-training-pvc

关键配置说明

  1. 分布式核心
    • WORLD_SIZE=4:总 Worker 数(对应 replicas: 4);
    • VOLCANO_TASK_INDEX:Volcano 自动为每个 Worker 注入的序号(0~3),作为分布式训练的 RANK
    • torch.distributed.launch:PyTorch 分布式训练启动器,自动搭建通信集群。
  2. 资源调度
    • 绑定 ai-training-queue 队列,受队列资源配额限制;
    • 仅调度到带 gpu: "true" 标签的节点,保证 GPU 资源。
  3. 数据持久化
    • 挂载 ReadWriteMany 类型的 PVC,所有 Worker 可共享训练数据,训练结果(模型文件)也会保存到 PVC 中。

三、提交并监控训练任务

1. 提交 Job

bash

运行

kubectl apply -f pytorch-ddp-training-job.yaml

# 查看 Job 状态
kubectl get vcjob pytorch-ddp-training
# 预期输出(PENDING → RUNNING → COMPLETED):
# NAME                    STATE      MINIMUM   PENDING   RUNNING   SUCCEEDED   FAILED   AGE
# pytorch-ddp-training    RUNNING    4         0         4         0           0        2m

2. 查看训练 Pod

bash

运行

# 查看所有 Worker Pod
kubectl get pods -l app=pytorch-training
# 预期输出:
# NAME                                      READY   STATUS    RESTARTS   AGE
# pytorch-ddp-training-ddp-worker-0         1/1     Running   0          3m
# pytorch-ddp-training-ddp-worker-1         1/1     Running   0          3m
# pytorch-ddp-training-ddp-worker-2         1/1     Running   0          3m
# pytorch-ddp-training-ddp-worker-3         1/1     Running   0          3m

3. 查看训练日志(验证分布式训练)

bash

运行

# 查看任意 Worker 日志
kubectl logs -f pytorch-ddp-training-ddp-worker-0

# 关键日志(看到以下内容说明分布式训练成功):
# > Initializing distributed: GLOBAL_RANK: 0, MEMBER: 1/4
# > Initializing distributed: GLOBAL_RANK: 1, MEMBER: 2/4
# > Initializing distributed: GLOBAL_RANK: 2, MEMBER: 3/4
# > Initializing distributed: GLOBAL_RANK: 3, MEMBER: 4/4
# > Epoch 1/10, Loss: 2.302, Accuracy: 10.0%
# > Epoch 10/10, Loss: 0.123, Accuracy: 98.5%
# > Training completed! Model saved to /data/model.pth

4. 查看队列资源使用

bash

运行

kubectl describe queue ai-training-queue
# 查看 "Allocated Resources" 部分,确认 GPU/CPU 资源已分配:
# Allocated Resources:
#   nvidia.com/gpu: 4
#   cpu: 16
#   memory: 64Gi

四、任务完成后验证结果

1. 检查 Job 状态

bash

运行

kubectl get vcjob pytorch-ddp-training
# 预期输出:
# NAME                    STATE        MINIMUM   PENDING   RUNNING   SUCCEEDED   FAILED   AGE
# pytorch-ddp-training    Completed    4         0         0         4           0        30m

2. 查看训练结果(模型文件)

bash

运行

# 进入任意 Pod 查看模型文件
kubectl exec -it pytorch-ddp-training-ddp-worker-0 -- ls /data
# 预期输出:
# train_ddp.py  model.pth  training.log

3. 清理任务(可选)

bash

运行

# 删除训练 Job
kubectl delete vcjob pytorch-ddp-training

# 保留 PVC(模型文件),如需清理则执行:
# kubectl delete pvc pytorch-training-pvc

五、生产级优化建议

  1. 训练脚本定制

    • 替换示例 train_ddp.py 为你的实际训练脚本(如图像分类、LLM 预训练);

    • 增加 checkpoint 保存逻辑,训练中断后可续跑。

  2. 资源调度优化

    • 为不同训练任务创建不同队列(如 llm-training-queuecv-training-queue),实现团队 / 任务隔离;

    • 配置 priorityClassName,核心任务(如正式训练)设为高优先级,测试任务设为低优先级。

  3. 监控告警

    • 部署 Prometheus + Volcano 监控插件,监控队列资源使用率、任务运行时长、失败率;

    • 配置 AlertManager 告警,当训练任务失败 / 资源不足时触发通知。

  4. 多机多卡扩展

    • 增加 replicas 数量(如 8),并调整 WORLD_SIZE 为对应值,实现 8 卡分布式训练;

    • 如需多机训练,确保节点间网络互通(Calico/Flannel 网络插件支持)。


核心总结

  1. Volcano 核心价值:为 PyTorch 分布式训练提供队列调度、优先级、资源隔离、GPU 精准调度,解决原生 K8s Job 无法满足的批量 / 分布式训练需求;
  2. 部署流程:安装 Volcano → 创建队列 → 编写分布式训练 Job → 提交监控 → 验证结果;
  3. 关键配置schedulerName: volcano 绑定 Volcano 调度器,VOLCANO_TASK_INDEX 实现分布式训练节点序号分配,PVC 保证数据 / 模型持久化。

这套方案可直接用于生产环境,适配 CV/NLP/LLM 等各类 PyTorch 分布式训练场景。

  1. GPU 虚拟化 / 共享

    • nvidia-device-plugin、MIG、vGPU

nvidia-device-plugin + MIG + vGPU 到底是什么?

一句话总结

这三个都是 K8s 集群中 NVIDIA GPU 资源的管理 / 切分工具,核心解决:

  • nvidia-device-plugin:让 K8s 能 “看见” GPU,是基础;
  • MIG:物理 GPU 硬切分(适合算力密集型任务);
  • vGPU:物理 GPU 软切分(适合多轻量任务共享)。

1. 先搞懂:为什么需要这些工具?

原生 K8s 不认识 GPU → 无法调度 / 分配 GPU 资源;一张物理 GPU 很贵(几万 / 张)→ 直接给一个任务用太浪费 → 需要切分成更小的单元共享。


2. 逐个拆解(从基础到进阶)
🔥 1)nvidia-device-plugin(GPU 管理基础)

核心定位

K8s 与 NVIDIA GPU 之间的 “翻译官”

  • 让 K8s 知道:集群有多少张 GPU、每张 GPU 用了多少;
  • 让 K8s 能:给 Pod 分配 GPU(nvidia.com/gpu: 1);
  • 是所有 NVIDIA GPU 调度的前提,必须先装。

核心作用

表格

功能 说明
资源发现 自动识别节点上的 NVIDIA GPU 型号 / 数量
资源分配 K8s 调度时,为 Pod 分配指定数量的 GPU
资源隔离 保证 Pod 只能用分配的 GPU,不抢占其他 Pod 的 GPU
状态上报 向 K8s API Server 上报 GPU 使用率 / 健康状态

安装(极简命令)

bash

运行

# 部署 nvidia-device-plugin(DaemonSet,每个 GPU 节点跑一个)
kubectl apply -f https://raw.githubusercontent.com/NVIDIA/k8s-device-plugin/v0.15.0/nvidia-device-plugin.yml

# 验证安装(节点标注出现 nvidia.com/gpu 数量)
kubectl describe node <gpu-node-name> | grep nvidia.com/gpu
# 预期输出:nvidia.com/gpu:  2(节点有 2 张 GPU)

使用示例(Pod 申请 GPU)

yaml

resources:
  limits:
    nvidia.com/gpu: 1  # 申请 1 张物理 GPU

🔥 2)MIG(Multi-Instance GPU)—— GPU 硬切分

核心定位

NVIDIA 高端 GPU 自带的 “硬件级切分功能”

  • 一张物理 GPU 切分成 多个独立的 MIG 实例(比如 A100 可切成 7 个实例);

  • 每个 MIG 实例有独立的显存、算力、缓存,互相完全隔离;

  • 只有 NVIDIA A100/A30/H100/H200 等高端 GPU 支持。

核心特点

表格

特性

说明

硬件隔离

切分后实例间无性能干扰,比软切分稳定

固定规格

每张 GPU 有固定的切分规格(如 A100 可切:1g.5gb / 2g.10gb / 3g.20gb)

独立调度

K8s 可把每个 MIG 实例当作独立 GPU 分配(nvidia.com/mig-1g.5gb: 1

适合场景

AI 训练、高性能推理(需要稳定算力 / 显存)

核心用法(K8s 中使用 MIG)

1)开启 MIG(节点上操作)

bash

运行

# 登录 GPU 节点,开启 MIG 模式
nvidia-smi -mig 1

# 创建 MIG 实例(A100 切 4 个 2g.10gb 实例)
nvidia-mig-manager create -f a100_4x2g10gb

2)K8s 中申请 MIG 实例

yaml

resources:
  limits:
    # 申请 1 个 2g.10gb 的 MIG 实例(不是整张 GPU)
    nvidia.com/mig-2g.10gb: 1

优势 vs 劣势

表格

优势

劣势

性能无干扰

仅高端 GPU 支持

显存 / 算力隔离

切分规格固定,不够灵活

稳定性高

配置复杂


🔥 3)vGPU(Virtual GPU)—— GPU 软切分

核心定位

NVIDIA 虚拟化技术,软件级切分 GPU

  • 把一张物理 GPU 切分成 多个 vGPU 虚拟机 / 容器

  • 基于软件层隔离,实例间共享 GPU 核心,可灵活分配显存 / 算力;

  • 支持大部分 NVIDIA GPU(Tesla/P4/T4/A10/A16/A30 等)。

核心特点

表格

特性

说明

软件隔离

基于驱动层切分,实例间可能有轻微性能干扰

灵活规格

可自定义每个 vGPU 的显存(如 2GB/4GB/8GB)、算力占比

广泛兼容

支持中低端 GPU,成本更低

适合场景

轻量推理、多用户共享 GPU、开发测试

K8s 中使用 vGPU(基于 NVIDIA vGPU 驱动)

1)前置条件

  • 节点安装 NVIDIA vGPU 驱动 + 许可证;

  • 部署 vGPU 设备插件(替代原生 nvidia-device-plugin)。

2)申请 vGPU 资源

yaml

resources:
  limits:
    # 申请 1 个 vGPU,显存 4GB,算力 20%
    nvidia.com/vgpu: 4GB-20%

优势 vs 劣势

表格

优势

劣势

成本低、兼容广

性能有轻微损耗

规格灵活

隔离性不如 MIG

易配置

需要许可证(付费)


3. 三者核心关系(一张表看懂)

表格

维度 nvidia-device-plugin MIG vGPU
定位 GPU 基础管理插件 GPU 硬件切分 GPU 软件切分
隔离级别 物理 GPU 级 硬件实例级 软件虚拟级
灵活性 低(只能分配整张 GPU) 中(固定规格) 高(自定义规格)
性能 无损耗 无损耗 轻微损耗
成本 免费 高(仅高端 GPU) 中(需许可证)
适合场景 所有 GPU 集群基础配置 AI 训练 / 高性能推理 轻量推理 / 共享 GPU

4. 典型使用场景(直接对号入座)
场景 1:AI 训练(A100/H100)
  • 基础:安装 nvidia-device-plugin
  • 切分:用 MIG 把 1 张 A100 切成 4 个实例,同时跑 4 个训练任务;
  • 优势:硬件隔离,训练互不干扰。
场景 2:LLM 轻量推理(T4/A10)
  • 基础:安装 nvidia-device-plugin
  • 切分:用 vGPU 把 1 张 T4 切成 8 个 vGPU(每个 2GB 显存),同时提供 8 路推理;
  • 优势:成本低,利用率高。
场景 3:开发测试环境
  • 基础:安装 nvidia-device-plugin
  • 切分:用 vGPU 给每个开发者分配 1 个 4GB vGPU;
  • 优势:灵活共享,降低硬件成本。

5. 超级好记的总结
  1. nvidia-device-plugin:K8s 用 GPU 的 “基础门票”,必须装;
  2. MIG:高端 GPU 硬切分,稳但贵,适合训练;
  3. vGPU:中低端 GPU 软切分,灵但略损性能,适合推理 / 共享。

三者的核心目标都是:让 K8s 能精细化管理 GPU,提高 GPU 利用率,降低成本

学习法:不啃论文,直接跑通「模型打包 → 上 K8s → 对外提供 API」。


6)架构师思维开箱:用 3 个问题代替死记硬背

任何技术,你只问三句:

  1. 它解决什么业务问题?
  2. 在 K8s 里放在哪一层?
  3. 出问题怎么排查?

能回答,你就是架构师思维,不是运维背命令。

7)实战开箱:做 1 个完整云原生 AI 项目(最提效)

建议你直接做这个:「基于 K8s 的 AI 模型推理服务平台」流程:

  1. 写一个简单模型(torch)

基于 PyTorch 框架的简单深度学习模型,我会为你提供一个结构清晰、注释完整的基础模型示例,适合新手理解和上手。

我将以图像分类这个最经典的任务为例,构建一个简单的全连接神经网络(MLP),这个模型结构简单,能帮你快速理解 PyTorch 构建模型的核心逻辑。

完整代码示例

python

运行

import torch
import torch.nn as nn
import torch.optim as optim
from torch.utils.data import DataLoader, TensorDataset

# ====================== 1. 定义简单的神经网络模型 ======================
class SimpleMLP(nn.Module):
    """
    简单的多层感知机(MLP)模型,用于图像分类(以MNIST手写数字为例)
    输入:28x28的灰度图(展平后为784维向量)
    输出:10类数字的概率分布
    """
    def __init__(self, input_size=784, hidden_size=128, output_size=10):
        super(SimpleMLP, self).__init__()
        # 定义网络层
        self.fc1 = nn.Linear(input_size, hidden_size)  # 第一层全连接:输入层→隐藏层
        self.relu = nn.ReLU()                          # 激活函数(引入非线性)
        self.fc2 = nn.Linear(hidden_size, output_size) # 第二层全连接:隐藏层→输出层

    def forward(self, x):
        """
        前向传播(必须实现的核心方法)
        :param x: 输入张量,形状为 [batch_size, input_size]
        :return: 输出张量,形状为 [batch_size, output_size]
        """
        # 展平输入(如果输入是[batch_size, 1, 28, 28],先转为[batch_size, 784])
        x = x.view(x.size(0), -1)
        # 逐层计算
        out = self.fc1(x)
        out = self.relu(out)
        out = self.fc2(out)
        return out

# ====================== 2. 初始化模型、损失函数、优化器 ======================
# 设置设备(优先使用GPU,没有则用CPU)
device = torch.device("cuda" if torch.cuda.is_available() else "cpu")

# 初始化模型并移到指定设备
model = SimpleMLP(input_size=784, hidden_size=128, output_size=10).to(device)

# 损失函数:分类任务用交叉熵损失(自动包含Softmax)
criterion = nn.CrossEntropyLoss()

# 优化器:随机梯度下降(SGD),也可以用Adam(更常用)
optimizer = optim.Adam(model.parameters(), lr=0.001)

# ====================== 3. 模拟训练过程(用随机数据) ======================
# 生成模拟数据:100个样本,每个样本是1通道28x28的图像,标签是0-9的数字
batch_size = 10
x_train = torch.randn(100, 1, 28, 28).to(device)  # 输入数据
y_train = torch.randint(0, 10, (100,)).to(device) # 标签

# 构建数据加载器(批量加载数据)
train_dataset = TensorDataset(x_train, y_train)
train_loader = DataLoader(train_dataset, batch_size=batch_size, shuffle=True)

# 训练5个epoch
num_epochs = 5
model.train()  # 切换到训练模式
for epoch in range(num_epochs):
    running_loss = 0.0
    for batch_idx, (data, targets) in enumerate(train_loader):
        # 1. 前向传播
        outputs = model(data)
        loss = criterion(outputs, targets)

        # 2. 反向传播+优化
        optimizer.zero_grad()  # 清空梯度(必须!)
        loss.backward()        # 反向传播计算梯度
        optimizer.step()       # 更新参数

        # 统计损失
        running_loss += loss.item()

    # 打印每个epoch的平均损失
    epoch_loss = running_loss / len(train_loader)
    print(f'Epoch [{epoch+1}/{num_epochs}], Loss: {epoch_loss:.4f}')

print("训练完成!")

# ====================== 4. 模拟推理过程 ======================
model.eval()  # 切换到评估模式(禁用Dropout/BatchNorm等)
with torch.no_grad():  # 禁用梯度计算(节省内存、加快速度)
    # 取一个测试样本
    test_sample = torch.randn(1, 1, 28, 28).to(device)
    output = model(test_sample)
    # 取概率最大的类别作为预测结果
    pred_label = torch.argmax(output, dim=1).item()
    print(f"\n测试样本的预测标签:{pred_label}")

# 保存模型
torch.save(model.state_dict(), "simple_mlp_model.pth")
print("模型已保存为 simple_mlp_model.pth")

代码关键部分解释

  1. 模型定义(SimpleMLP 类)

    • 必须继承 nn.Module,这是 PyTorch 所有模型的基类。

    • __init__ 方法:定义网络层(如全连接层nn.Linear、激活函数nn.ReLU)。

    • forward 方法:定义前向传播逻辑(数据如何通过各层),不能手动调用 forward,直接用model(x)即可

  2. 训练核心三步

    • 前向传播:输入数据→计算输出→计算损失。

    • 清空梯度:optimizer.zero_grad()(否则梯度会累加,导致错误)。

    • 反向传播 + 更新参数:loss.backward() + optimizer.step()

  3. 模式切换

    • model.train():训练模式(启用 Dropout、BatchNorm 的训练行为)。

    • model.eval():评估模式(禁用 Dropout、固定 BatchNorm 参数)。

    • torch.no_grad():推理时禁用梯度计算,避免不必要的内存消耗。

总结

  1. PyTorch 构建模型的核心是继承nn.Module,实现__init__(定义层)和forward(定义前向传播)。

  2. 训练流程固定为:前向传播算损失 → 清空梯度 → 反向传播算梯度 → 优化器更新参数。

  3. 推理时需切换到eval()模式,并使用torch.no_grad()禁用梯度计算,提升效率。

这个模型是最基础的版本,你可以在此基础上扩展(比如增加隐藏层、添加 Dropout 防止过拟合、换成卷积层处理图像等),核心逻辑完全通用。

  1. 打包 Docker

你想要把上一个基于 PyTorch 的简单模型打包成 Docker 镜像,这样可以在任何支持 Docker 的环境中运行,避免环境配置的麻烦。我会为你提供完整的 Dockerfile 编写、镜像构建和容器运行的步骤,全程保持简洁易懂。

前置条件

  1. 你的电脑已安装 Docker(Windows/Mac 需安装 Docker Desktop,Linux 需安装 Docker Engine)
  2. 已准备好上一步的模型代码文件(命名为simple_model.py
步骤 1:编写 Dockerfile

Dockerfile 是构建 Docker 镜像的 "配方",我们基于官方的 PyTorch 镜像来构建,避免手动安装复杂依赖。

在代码同目录下创建名为Dockerfile的文件(无后缀),内容如下:

dockerfile

# 基础镜像:使用官方的PyTorch镜像(包含Python、PyTorch、CUDA等)
# 选择轻量的CPU版本(如果需要GPU,替换为 pytorch/pytorch:2.2.0-cuda12.1-cudnn8-runtime)
FROM pytorch/pytorch:2.2.0-cpu

# 设置工作目录(容器内的目录)
WORKDIR /app

# 复制本地的模型代码到容器的工作目录
COPY simple_model.py /app/

# 可选:安装额外依赖(如果代码需要)
# RUN pip install --no-cache-dir numpy pandas

# 设置容器启动时默认执行的命令
CMD ["python", "simple_model.py"]
步骤 2:编写.dockerignore(可选但推荐)

创建.dockerignore文件,排除不需要复制到镜像的文件,减小镜像体积:

plaintext

# 排除Python缓存文件
__pycache__/
*.pyc
*.pyo
*.pyd

# 排除Docker相关文件
Dockerfile
.dockerignore

# 排除模型权重文件(如果后续保存了,可按需排除)
*.pth

# 排除其他无关文件
.git
.gitignore
venv/
.env
步骤 3:构建 Docker 镜像

打开终端 / 命令行,进入代码和 Dockerfile 所在目录,执行以下命令:

bash

运行

# 构建镜像,-t 指定镜像名称(如simple-torch-model),. 表示Dockerfile在当前目录
docker build -t simple-torch-model .

命令解释

  • -t simple-torch-model:给镜像打标签,方便后续引用

  • .:指定构建上下文为当前目录(即 Dockerfile 中 COPY 的文件从当前目录读取)

构建完成后,执行docker images可看到刚构建的镜像。

步骤 4:运行 Docker 容器

镜像构建完成后,执行以下命令启动容器运行模型:

bash

运行

# 运行容器,--rm 表示容器运行结束后自动删除(节省空间)
docker run --rm simple-torch-model

如果需要 GPU 支持(需主机有 NVIDIA 显卡且安装了 NVIDIA Container Toolkit):

bash

运行

# 启用GPU的运行命令
docker run --rm --gpus all simple-torch-model
步骤 5:验证运行结果

容器启动后,会自动执行python simple_model.py,终端会输出模型训练的日志(如 Epoch 损失、预测结果),和本地运行效果一致,说明打包和运行成功。

额外实用操作

  1. 进入容器调试(如果运行出错,可进入容器排查):

bash

运行

# 以交互模式启动容器,/bin/bash 进入命令行
docker run -it --rm simple-torch-model /bin/bash
  1. 保存 / 加载镜像(用于迁移到其他机器):

bash

运行

# 保存镜像为tar文件
docker save -o simple-torch-model.tar simple-torch-model

# 加载tar文件为镜像
docker load -i simple-torch-model.tar
  1. 后台运行容器

bash

运行

# -d 表示后台运行,-name 指定容器名称
docker run -d --name torch-model-container simple-torch-model

# 查看容器日志
docker logs torch-model-container
总结
  1. 打包 PyTorch 模型的核心是基于官方 PyTorch 镜像编写 Dockerfile,避免手动配置环境;
  2. 构建镜像用docker build -t 名称 .,运行容器用docker run --rm 镜像名
  3. 如需 GPU 支持,需替换基础镜像为 CUDA 版本,并添加--gpus all参数运行容器。

这个流程是通用的,你后续无论修改模型代码还是添加依赖,只需更新 Dockerfile 中的COPYRUN pip install部分,重新构建镜像即可。

  1. 写 K8s YAML

Kubernetes (K8s) 集群中部署上述 PyTorch 模型的 YAML 配置文件,我会为你提供基础的 Deployment 配置(适合运行无状态的模型任务),并附带详细注释和使用说明,确保新手能快速理解和上手。

前置条件

  1. K8s 集群已部署并可访问(如 minikube、k3s、云厂商 K8s 等)

  2. kubectl 工具已配置并能连接集群

  3. 你的 PyTorch 镜像已推送到集群可访问的镜像仓库(如 Docker Hub、Harbor 等)

完整 YAML 配置文件

创建名为 torch-model-deployment.yaml 的文件,内容如下(所有关键配置都有注释):

yaml

# 配置类型:Deployment(无状态应用部署)
apiVersion: apps/v1
kind: Deployment
metadata:
  # Deployment 名称(自定义)
  name: simple-torch-model
  # 命名空间(可自定义,默认default)
  namespace: default
  # 标签(用于关联Service、Pod等)
  labels:
    app: torch-model
spec:
  # 副本数(运行多少个Pod实例)
  replicas: 1
  # 标签选择器:匹配Pod的标签
  selector:
    matchLabels:
      app: torch-model
  # Pod 模板(定义Pod的具体配置)
  template:
    metadata:
      labels:
        app: torch-model
    spec:
      # 容器配置(核心)
      containers:
      - name: torch-model-container
        # 镜像地址(替换为你自己的镜像仓库地址,如 docker.io/你的用户名/simple-torch-model:latest)
        image: simple-torch-model:latest
        # 镜像拉取策略:Always(总是拉取最新)、IfNotPresent(本地没有才拉取)、Never(只用本地)
        imagePullPolicy: IfNotPresent
        # 资源限制(可选,推荐配置,避免占用过多集群资源)
        resources:
          requests:
            # 最小资源需求
            cpu: "100m"       # 100毫核(0.1核)
            memory: "256Mi"   # 256MB内存
          limits:
            # 最大资源限制
            cpu: "500m"       # 0.5核
            memory: "512Mi"   # 512MB内存
        # 重启策略:Pod异常时的处理(Always/OnFailure/Never)
        restartPolicy: OnFailure
        # 可选:容器启动命令(覆盖镜像的CMD)
        # command: ["python", "simple_model.py"]
        # 可选:环境变量(如需传递参数)
        # env:
        # - name: LEARNING_RATE
        #   value: "0.001"
---
# 可选:Service配置(如果模型需要对外提供服务,如API)
# 这里仅演示ClusterIP类型(集群内访问),如需外部访问可改用NodePort/LoadBalancer
apiVersion: v1
kind: Service
metadata:
  name: torch-model-service
  namespace: default
spec:
  # 选择器:匹配Deployment的Pod标签
  selector:
    app: torch-model
  # Service类型
  type: ClusterIP
  # 端口映射(容器端口→Service端口)
  ports:
  - port: 80          # Service对外暴露的端口
    targetPort: 8080  # 容器内应用监听的端口(需模型代码启动Web服务才需要)
    protocol: TCP

关键配置解释

  1. Deployment 核心字段

    • replicas: 运行的 Pod 数量,新手先设为 1,避免资源浪费;

    • image: 必须替换为你推送到镜像仓库的实际镜像地址(如 docker.io/yourname/simple-torch-model:v1);

    • resources: 限制 Pod 的 CPU / 内存使用,防止单个 Pod 占用集群全部资源;

    • restartPolicy: OnFailure: 仅当模型运行失败时重启 Pod(适合一次性训练任务),如果是常驻服务可改为 Always

  2. 镜像仓库说明:本地构建的镜像(simple-torch-model:latest)仅在本机可见,K8s 集群(尤其是多节点集群)无法直接访问,需推送到公共 / 私有镜像仓库:

    bash

    运行

    # 1. 给镜像打标签(替换为你的仓库地址)
    docker tag simple-torch-model:latest docker.io/你的用户名/simple-torch-model:latest
    # 2. 登录Docker Hub
    docker login
    # 3. 推送镜像
    docker push docker.io/你的用户名/simple-torch-model:latest
    

    推送完成后,将 YAML 中的image字段替换为上述标签。

部署和验证命令

bash

运行

# 1. 部署到K8s集群
kubectl apply -f torch-model-deployment.yaml

# 2. 查看Deployment状态
kubectl get deployments

# 3. 查看Pod状态(确认Running/Completed)
kubectl get pods

# 4. 查看Pod日志(验证模型是否正常运行)
kubectl logs <Pod名称>  # 替换为实际Pod名,如 simple-torch-model-7f987d6b89-xxxx

# 5. 如需删除部署
kubectl delete -f torch-model-deployment.yaml

针对 GPU 集群的额外配置(可选)

如果你的 K8s 集群有 GPU 节点,需在 Pod 模板中添加 GPU 资源请求,修改resources部分:

yaml

resources:
  requests:
    cpu: "100m"
    memory: "512Mi"
    nvidia.com/gpu: 1  # 请求1块GPU
  limits:
    cpu: "1000m"
    memory: "1Gi"
    nvidia.com/gpu: 1  # 限制最多使用1块GPU

总结

  1. K8s 部署 PyTorch 模型的核心是Deployment配置,通过template定义 Pod 的容器、资源、镜像等;

  2. 必须确保镜像推送到集群可访问的仓库,否则 Pod 会因拉取镜像失败而报错;

  3. 关键配置项:image(镜像地址)、replicas(副本数)、resources(资源限制)、restartPolicy(重启策略);

  4. 部署后通过kubectl get podskubectl logs验证运行状态。

这份配置是基础版,适合一次性的模型训练任务;如果是需要对外提供推理服务的模型,还可以结合Service(NodePort/LoadBalancer)和Ingress实现外部访问,核心配置逻辑一致。

  1. 部署 Service + Ingress

在 K8s 中为 PyTorch 模型部署Service(服务暴露)和Ingress(外部访问入口),让模型能通过域名 / IP 对外提供推理服务。我会基于之前的 Deployment 配置,补充完整的 Service+Ingress YAML,并说明关键配置和验证步骤,同时适配新手的理解难度。

前置说明

  1. 本次示例会先改造模型代码,让它以Web 服务(Flask)形式运行(否则 Ingress/Service 无意义);
  2. 需确保 K8s 集群已安装 Ingress 控制器(如 NGINX Ingress Controller,后面会给出安装命令);
  3. 核心逻辑:Ingress → Service → Pod(运行模型 Web 服务)。

步骤 1:改造模型代码为 Web 服务

将之前的simple_model.py修改为带 Flask 接口的推理服务,这样才能通过 HTTP 访问:

python

运行

import torch
import torch.nn as nn
from flask import Flask, request, jsonify

# ====================== 1. 定义模型(复用之前的SimpleMLP) ======================
class SimpleMLP(nn.Module):
    def __init__(self, input_size=784, hidden_size=128, output_size=10):
        super(SimpleMLP, self).__init__()
        self.fc1 = nn.Linear(input_size, hidden_size)
        self.relu = nn.ReLU()
        self.fc2 = nn.Linear(hidden_size, output_size)

    def forward(self, x):
        x = x.view(x.size(0), -1)
        out = self.fc1(x)
        out = self.relu(out)
        out = self.fc2(out)
        return out

# ====================== 2. 初始化模型(模拟加载训练好的权重) ======================
device = torch.device("cpu")
model = SimpleMLP().to(device)
model.eval()  # 推理模式

# ====================== 3. 启动Flask Web服务 ======================
app = Flask(__name__)

@app.route('/predict', methods=['POST'])
def predict():
    """
    推理接口:接收JSON格式的图像数据,返回预测结果
    请求示例:{"data": [0.1, 0.2, ..., 0.784]}(784维向量)
    """
    try:
        # 解析请求数据
        data = request.get_json()['data']
        # 转换为Tensor并推理
        input_tensor = torch.tensor(data, dtype=torch.float32).unsqueeze(0).to(device)
        with torch.no_grad():
            output = model(input_tensor)
            pred_label = torch.argmax(output, dim=1).item()
        
        # 返回结果
        return jsonify({
            "code": 200,
            "pred_label": pred_label,
            "msg": "推理成功"
        })
    except Exception as e:
        return jsonify({
            "code": 500,
            "msg": f"推理失败:{str(e)}"
        })

if __name__ == '__main__':
    # 监听0.0.0.0(容器内必须监听所有地址),端口8080
    app.run(host='0.0.0.0', port=8080, debug=False)
步骤 2:更新 Dockerfile(安装 Flask 依赖)

dockerfile

FROM pytorch/pytorch:2.2.0-cpu
WORKDIR /app
COPY simple_model.py /app/
# 新增:安装Flask
RUN pip install --no-cache-dir flask
CMD ["python", "simple_model.py"]
步骤 3:重新构建并推送镜像

bash

运行

# 重新构建镜像
docker build -t your-username/simple-torch-model:v2 .
# 推送镜像(替换为你的仓库地址)
docker push your-username/simple-torch-model:v2

步骤 4:完整的 Service + Ingress YAML 配置

创建torch-model-full.yaml,包含 Deployment、Service、Ingress:

yaml

# 1. Deployment(运行模型Web服务的Pod)
apiVersion: apps/v1
kind: Deployment
metadata:
  name: simple-torch-model
  namespace: default
spec:
  replicas: 1
  selector:
    matchLabels:
      app: torch-model
  template:
    metadata:
      labels:
        app: torch-model
    spec:
      containers:
      - name: torch-model-container
        # 替换为你推送的镜像地址
        image: your-username/simple-torch-model:v2
        imagePullPolicy: IfNotPresent
        # 资源限制
        resources:
          requests:
            cpu: "100m"
            memory: "256Mi"
          limits:
            cpu: "500m"
            memory: "512Mi"
        # 端口映射:容器内Flask运行在8080端口
        ports:
        - containerPort: 8080
        restartPolicy: Always

---
# 2. Service(ClusterIP类型,暴露Pod的8080端口)
apiVersion: v1
kind: Service
metadata:
  name: torch-model-service
  namespace: default
spec:
  selector:
    app: torch-model  # 匹配Deployment的Pod标签
  type: ClusterIP     # 仅集群内访问,由Ingress转发请求
  ports:
  - port: 80          # Service的端口(Ingress会指向这个端口)
    targetPort: 8080  # 容器内的端口(Flask监听的8080)
    protocol: TCP

---
# 3. Ingress(外部访问入口,通过域名/IP转发到Service)
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: torch-model-ingress
  namespace: default
  # 注解:指定Ingress控制器(NGINX)的配置
  annotations:
    # 核心注解:指定使用NGINX Ingress控制器
    kubernetes.io/ingress.class: "nginx"
    # 可选:设置请求超时
    nginx.ingress.kubernetes.io/proxy-connect-timeout: "30"
    nginx.ingress.kubernetes.io/proxy-read-timeout: "120"
spec:
  # 规则:域名/路径映射到Service
  rules:
  - host: torch-model.local  # 自定义域名(需本地hosts解析)
    http:
      paths:
      - path: /
        pathType: Prefix
        backend:
          service:
            name: torch-model-service  # 关联上面的Service
            port:
              number: 80  # Service的端口
  # 可选:如果需要HTTPS,添加tls配置(需证书)
  # tls:
  # - hosts:
  #   - torch-model.local
  #   secretName: torch-model-tls-secret
步骤 5:安装 Ingress 控制器(关键!)

如果集群中没有 Ingress 控制器,Ingress 规则不会生效,先安装 NGINX Ingress:

bash

运行

# 适用于K8s 1.24+的NGINX Ingress安装命令(官方推荐)
kubectl apply -f https://raw.githubusercontent.com/kubernetes/ingress-nginx/controller-v1.10.0/deploy/static/provider/cloud/deploy.yaml

# 验证Ingress控制器是否运行
kubectl get pods -n ingress-nginx
# 看到 "ingress-nginx-controller-xxxx" 状态为Running即可
步骤 6:配置本地域名解析(可选)

为了用torch-model.local访问,需修改本地hosts文件:

  • WindowsC:\Windows\System32\drivers\etc\hosts
  • Linux/Mac/etc/hosts

添加一行:

plaintext

# 替换为你的K8s节点IP(如minikube的IP用minikube ip查看)
192.168.49.2  torch-model.local

步骤 7:部署并验证
1. 部署所有资源

bash

运行

kubectl apply -f torch-model-full.yaml
2. 检查资源状态

bash

运行

# 检查Deployment
kubectl get deployments simple-torch-model
# 检查Service
kubectl get svc torch-model-service
# 检查Ingress
kubectl get ingress torch-model-ingress
# 检查Pod
kubectl get pods -l app=torch-model
3. 测试访问
方式 1:本地 curl 测试

bash

运行

# 发送POST请求到推理接口
curl -X POST http://torch-model.local/predict \
  -H "Content-Type: application/json" \
  -d '{"data": [0.1]*784}'  # 模拟784维的图像数据
方式 2:浏览器 / Postman 测试

访问 http://torch-model.local/predict(POST 方法),请求体:

json

{"data": [0.1, 0.2, 0.3, ..., 0.784]}  // 784个数值,可重复填充
预期返回结果:

json

{"code":200,"pred_label":5,"msg":"推理成功"}

关键配置说明

  1. Service 的核心作用

    • ClusterIP类型:仅集群内可见,避免直接暴露 Pod;

    • selector:通过标签app: torch-model关联 Pod;

    • targetPort:必须和容器内 Flask 监听的端口(8080)一致。

  2. Ingress 的核心作用

    • rules:将外部请求(域名 + 路径)转发到指定 Service;

    • annotations:指定使用 NGINX 控制器,是 Ingress 生效的关键;

    • host:自定义域名,也可留空用 IP 直接访问(如http://<节点IP>/predict)。

  3. 常见问题排查

    • Ingress 状态为Pending:未安装 Ingress 控制器;
    • 访问域名超时:检查 hosts 解析、Ingress 规则、Pod 是否正常运行;
    • Pod 日志报错:用kubectl logs <Pod名>查看,大概率是镜像拉取失败或依赖缺失。

总结
  1. 对外提供推理服务需先将模型封装为 Web 服务(如 Flask),监听0.0.0.0:8080
  2. Service 通过ClusterIP暴露 Pod 的端口,Ingress 作为外部入口转发请求到 Service;
  3. 核心配置要点:
    • Service 的selector匹配 Pod 标签,targetPort匹配容器端口;
    • Ingress 的rules关联 Service,需提前安装 Ingress 控制器;
    • 镜像必须推送到集群可访问的仓库,否则 Pod 启动失败。

如果需要对外暴露公网访问,可将 Ingress 的host改为公网域名,或使用LoadBalancer类型的 Service(云厂商 K8s 支持)。

  1. 加监控(Prometheus/Grafana)

为 K8s 中运行的 PyTorch 模型服务添加Prometheus + Grafana 监控,实现对 Pod 资源(CPU / 内存)、模型推理接口指标(QPS / 延迟 / 错误率)的可视化监控。我会分步骤完成配置:先添加指标暴露、再部署 Prometheus/Grafana、最后配置监控面板,全程保持新手友好。

核心思路

  1. 暴露指标:修改模型代码,用prometheus_client暴露自定义指标(推理 QPS / 延迟)+ K8s 自带的 Node/Pod 资源指标;
  2. 部署监控组件:用 Prometheus 采集指标,Grafana 可视化;
  3. 配置监控面板:导入预制面板,实现一键查看所有指标。

步骤 1:改造模型代码,暴露监控指标

更新simple_model.py,添加 Prometheus 指标暴露(Flask 接口指标 + 系统指标):

python

运行

import time
import torch
import torch.nn as nn
from flask import Flask, request, jsonify
# 新增:Prometheus监控依赖
from prometheus_client import Counter, Histogram, Gauge, generate_latest, REGISTRY
from prometheus_client.exposition import make_wsgi_app
from werkzeug.middleware.dispatcher import DispatcherMiddleware

# ====================== 1. 定义Prometheus指标 ======================
# 自定义指标:推理请求总数
PREDICTION_REQUESTS = Counter(
    'torch_model_prediction_requests_total',
    'Total number of prediction requests',
    ['method', 'endpoint']
)
# 自定义指标:推理请求延迟(秒)
PREDICTION_LATENCY = Histogram(
    'torch_model_prediction_latency_seconds',
    'Latency of prediction requests in seconds',
    ['endpoint']
)
# 自定义指标:推理错误数
PREDICTION_ERRORS = Counter(
    'torch_model_prediction_errors_total',
    'Total number of prediction errors',
    ['endpoint', 'error_type']
)
# 系统指标:模型加载状态(1=加载完成,0=未加载)
MODEL_STATUS = Gauge(
    'torch_model_loaded_status',
    'Status of model loading (1=loaded, 0=not loaded)'
)

# ====================== 2. 定义模型(复用之前的SimpleMLP) ======================
class SimpleMLP(nn.Module):
    def __init__(self, input_size=784, hidden_size=128, output_size=10):
        super(SimpleMLP, self).__init__()
        self.fc1 = nn.Linear(input_size, hidden_size)
        self.relu = nn.ReLU()
        self.fc2 = nn.Linear(hidden_size, output_size)

    def forward(self, x):
        x = x.view(x.size(0), -1)
        out = self.fc1(x)
        out = self.relu(out)
        out = self.fc2(out)
        return out

# ====================== 3. 初始化模型 ======================
device = torch.device("cpu")
model = SimpleMLP().to(device)
model.eval()
MODEL_STATUS.set(1)  # 标记模型加载完成

# ====================== 4. 启动Flask Web服务 ======================
app = Flask(__name__)

# 新增:将Prometheus的/metrics端点集成到Flask应用
app.wsgi_app = DispatcherMiddleware(app.wsgi_app, {
    '/metrics': make_wsgi_app(REGISTRY)
})

@app.route('/predict', methods=['POST'])
def predict():
    """推理接口:带Prometheus指标监控"""
    # 记录请求总数
    PREDICTION_REQUESTS.labels(method='POST', endpoint='/predict').inc()
    # 记录请求延迟
    start_time = time.time()
    try:
        data = request.get_json()['data']
        input_tensor = torch.tensor(data, dtype=torch.float32).unsqueeze(0).to(device)
        with torch.no_grad():
            output = model(input_tensor)
            pred_label = torch.argmax(output, dim=1).item()
        
        # 记录延迟
        PREDICTION_LATENCY.labels(endpoint='/predict').observe(time.time() - start_time)
        return jsonify({
            "code": 200,
            "pred_label": pred_label,
            "msg": "推理成功"
        })
    except Exception as e:
        # 记录错误数
        PREDICTION_ERRORS.labels(endpoint='/predict', error_type=type(e).__name__).inc()
        # 记录延迟(即使出错)
        PREDICTION_LATENCY.labels(endpoint='/predict').observe(time.time() - start_time)
        return jsonify({
            "code": 500,
            "msg": f"推理失败:{str(e)}"
        })

if __name__ == '__main__':
    # 监听0.0.0.0,端口8080
    app.run(host='0.0.0.0', port=8080, debug=False)
步骤 2:更新 Dockerfile(安装 Prometheus 依赖)

dockerfile

FROM pytorch/pytorch:2.2.0-cpu
WORKDIR /app
COPY simple_model.py /app/
# 安装Flask + Prometheus客户端
RUN pip install --no-cache-dir flask prometheus-client
CMD ["python", "simple_model.py"]
步骤 3:重新构建并推送镜像

bash

运行

docker build -t your-username/simple-torch-model:v3 .
docker push your-username/simple-torch-model:v3
步骤 4:更新 Deployment,添加监控端口注解

修改torch-model-full.yaml中的 Deployment 部分,添加Prometheus 采集注解(让 Prometheus 自动发现并采集指标):

yaml

apiVersion: apps/v1
kind: Deployment
metadata:
  name: simple-torch-model
  namespace: default
  # 新增:Prometheus注解(关键!)
  annotations:
    prometheus.io/scrape: "true"        # 开启采集
    prometheus.io/path: "/metrics"      # 指标路径
    prometheus.io/port: "8080"          # 指标端口
spec:
  replicas: 1
  selector:
    matchLabels:
      app: torch-model
  template:
    metadata:
      labels:
        app: torch-model
      # 可选:Pod级别注解(和上面二选一即可)
      # annotations:
      #   prometheus.io/scrape: "true"
      #   prometheus.io/path: "/metrics"
      #   prometheus.io/port: "8080"
    spec:
      containers:
      - name: torch-model-container
        image: your-username/simple-torch-model:v3  # 改为v3镜像
        imagePullPolicy: IfNotPresent
        resources:
          requests:
            cpu: "100m"
            memory: "256Mi"
          limits:
            cpu: "500m"
            memory: "512Mi"
        ports:
        - containerPort: 8080
        restartPolicy: Always
---
# Service和Ingress部分保持不变(略)

步骤 5:部署 Prometheus + Grafana(用 Helm 快速部署)

前置:安装 Helm(K8s 包管理工具)

bash

运行

# Linux/Mac
curl https://raw.githubusercontent.com/helm/helm/main/scripts/get-helm-3 | bash

# Windows(需PowerShell)
choco install kubernetes-helm
1. 添加 Prometheus 社区仓库

bash

运行

helm repo add prometheus-community https://prometheus-community.github.io/helm-charts
helm repo update
2. 部署 Prometheus(包含 Node Exporter、kube-state-metrics)

bash

运行

# 创建监控命名空间
kubectl create namespace monitoring

# 部署Prometheus
helm install prometheus prometheus-community/prometheus \
  --namespace monitoring \
  --set server.service.type=NodePort  # 暴露NodePort方便访问(新手友好)
3. 部署 Grafana

bash

运行

# 部署Grafana
helm install grafana prometheus-community/grafana \
  --namespace monitoring \
  --set service.type=NodePort  # 暴露NodePort
4. 查看部署状态

bash

运行

# 查看监控组件Pod
kubectl get pods -n monitoring

# 查看Prometheus和Grafana的NodePort端口
kubectl get svc -n monitoring
# 找到:
# prometheus-server   NodePort    <IP>   80:30090/TCP  → Prometheus端口是30090
# grafana             NodePort    <IP>   80:32000/TCP  → Grafana端口是32000
步骤 6:配置 Prometheus 采集模型指标
1. 访问 Prometheus UI

plaintext

http://<K8s节点IP>:<Prometheus NodePort>  # 如 http://192.168.49.2:30090
  • 点击「Status」→「Targets」,能看到default/simple-torch-model的采集目标(状态 UP),说明指标采集成功。
  • 可在「Graph」中查询指标,如torch_model_prediction_requests_total,验证指标是否正常。
2. 配置 Grafana 数据源
  1. 访问 Grafana UI:http://<K8s节点IP>:<Grafana NodePort>(如http://192.168.49.2:32000);
  2. 获取 Grafana 初始密码:

    bash

    运行

    kubectl get secret -n monitoring grafana -o jsonpath="{.data.admin-password}" | base64 --decode
    
  3. 登录(用户名admin,密码为上述结果);
  4. 点击「Configuration」→「Data sources」→「Add data source」→选择「Prometheus」;
  5. 填写 Prometheus 地址:http://prometheus-server.monitoring.svc.cluster.local:80(K8s 内部 Service 地址);
  6. 点击「Save & test」,提示「Data source is working」即配置成功。
步骤 7:导入 Grafana 监控面板
1. 导入预制面板(推荐)
  • 模型接口监控:导入面板 ID 15778(通用 HTTP 服务监控,适配自定义指标);
  • K8s Pod 资源监控:导入面板 ID 8588(Pod CPU / 内存 / 网络监控)。

导入步骤:

  1. Grafana 左侧点击「Dashboards」→「+ Import」;
  2. 输入面板 ID(如 15778)→「Load」;
  3. 选择已配置的 Prometheus 数据源→「Import」。
2. 自定义模型监控面板(可选)

可手动添加以下指标到面板:

  • 推理请求总数:sum(torch_model_prediction_requests_total)
  • 推理 QPS:rate(torch_model_prediction_requests_total[1m])
  • 推理平均延迟:avg(torch_model_prediction_latency_seconds_avg)
  • 推理错误率:sum(torch_model_prediction_errors_total) / sum(torch_model_prediction_requests_total)
  • 模型加载状态:torch_model_loaded_status
  • Pod CPU 使用率:sum(rate(container_cpu_usage_seconds_total{pod=~"simple-torch-model.*"}[1m])) / sum(kube_pod_container_resource_limits_cpu_cores{pod=~"simple-torch-model.*"}) * 100
  • Pod 内存使用率:sum(container_memory_usage_bytes{pod=~"simple-torch-model.*"}) / sum(kube_pod_container_resource_limits_memory_bytes{pod=~"simple-torch-model.*"}) * 100
步骤 8:验证监控效果
  1. 发送测试请求,触发指标变化:

    bash

    运行

    for i in {1..10}; do
      curl -X POST http://torch-model.local/predict \
        -H "Content-Type: application/json" \
        -d '{"data": [0.1]*784}'
      sleep 1
    done
    
  2. 在 Grafana 面板中,能看到请求数、QPS、延迟等指标实时变化,Pod CPU / 内存也会显示对应波动。

关键配置说明
  1. 自定义指标设计
    • Counter:累计型指标(请求数、错误数),适合统计总数;
    • Histogram:分布型指标(延迟),可计算平均值、分位数;
    • Gauge:瞬时值指标(模型状态),适合监控开关 / 状态。
  2. Prometheus 采集注解
    • prometheus.io/scrape: "true":开启自动采集;
    • prometheus.io/path:指标暴露路径(默认/metrics);
    • prometheus.io/port:指标端口(需和容器端口一致)。
  3. Grafana 数据源:使用 K8s 内部 Service 地址(prometheus-server.monitoring.svc.cluster.local),避免依赖 NodePort,更稳定。
总结
  1. 监控核心是暴露指标(代码中添加prometheus_client)+ 采集指标(Prometheus)+ 可视化指标(Grafana);
  2. 关键步骤:
    • 模型代码添加自定义指标,暴露/metrics端点;
    • Deployment 添加 Prometheus 注解,实现自动采集;
    • 用 Helm 快速部署 Prometheus/Grafana,配置数据源和面板;
  3. 核心监控维度:接口指标(QPS / 延迟 / 错误率)+ 资源指标(CPU / 内存)+ 业务指标(模型状态)。

如果需要告警(如延迟过高、错误率超标),可在 Prometheus 中配置 AlertManager,Grafana 中添加告警规则,核心逻辑和上述配置兼容。

  1. 做自动扩缩容 HPA

为 K8s 中的 PyTorch 模型服务配置Horizontal Pod Autoscaler (HPA) 实现自动扩缩容,根据 CPU / 内存使用率或自定义的 Prometheus 指标(如推理 QPS)动态调整 Pod 副本数。我会提供完整的 HPA 配置(基础 CPU / 内存扩缩容 + 自定义指标扩缩容),并说明关键配置和验证步骤。

核心思路

  1. 基础 HPA:基于 CPU / 内存使用率自动扩缩容(K8s 原生支持);
  2. 高级 HPA:基于 Prometheus 自定义指标(推理 QPS)扩缩容(需安装 Prometheus Adapter);
  3. 核心逻辑:HPA 监控指标→达到阈值→自动调整 Deployment 的replicas数。

前置条件

  1. 已完成前序步骤(Deployment/Service/Ingress/ 监控部署);
  2. K8s 集群版本≥1.23(HPA v2 稳定版);
  3. 已部署 Metrics Server(HPA 依赖,用于采集 Pod 资源指标)。

先安装 Metrics Server(如未安装)

bash

运行

# 安装Metrics Server(适配国内环境,跳过TLS验证)
kubectl apply -f https://raw.githubusercontent.com/kubernetes-sigs/metrics-server/v0.7.0/deploy/components.yaml

# 修改Metrics Server部署,添加--kubelet-insecure-tls(避免证书错误)
kubectl edit deployment metrics-server -n kube-system
# 在spec.template.spec.containers.args中添加:
# - --kubelet-insecure-tls

# 验证Metrics Server运行
kubectl get pods -n kube-system | grep metrics-server
kubectl top pods  # 能看到Pod CPU/内存使用,说明安装成功

步骤 1:基础 HPA(基于 CPU / 内存)

创建torch-model-hpa.yaml,配置基于 CPU 使用率的自动扩缩容:

yaml

apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
  name: simple-torch-model-hpa
  namespace: default
spec:
  # 关联要扩缩容的Deployment
  scaleTargetRef:
    apiVersion: apps/v1
    kind: Deployment
    name: simple-torch-model
  # 副本数范围:最小1个,最大5个
  minReplicas: 1
  maxReplicas: 5
  # 扩缩容策略(可选,控制扩缩速度)
  behavior:
    scaleUp:
      stabilizationWindowSeconds: 30  # 扩容前稳定观察30秒(避免抖动)
      policies:
      - type: Percent
        value: 100  # 每次扩容100%(即翻倍)
        periodSeconds: 60  # 60秒内最多扩容1次
    scaleDown:
      stabilizationWindowSeconds: 60  # 缩容前稳定观察60秒
      policies:
      - type: Percent
        value: 50  # 每次缩容50%
        periodSeconds: 120  # 120秒内最多缩容1次
  # 指标配置(CPU使用率阈值)
  metrics:
  - type: Resource
    resource:
      name: cpu
      target:
        type: Utilization  # 基于使用率(而非绝对数值)
        averageUtilization: 50  # 平均CPU使用率超过50%触发扩容
  # 可选:添加内存指标
  # - type: Resource
  #   resource:
  #     name: memory
  #     target:
  #       type: Utilization
  #       averageUtilization: 80

部署基础 HPA

bash

运行

kubectl apply -f torch-model-hpa.yaml

# 查看HPA状态
kubectl get hpa simple-torch-model-hpa
# 输出示例:
# NAME                        REFERENCE                              TARGETS   MINPODS   MAXPODS   REPLICAS   AGE
# simple-torch-model-hpa      Deployment/simple-torch-model         0%/50%    1         5         1          10s

步骤 2:高级 HPA(基于 Prometheus 自定义指标)

如果想基于推理 QPS(而非 CPU)扩缩容,需安装Prometheus Adapter(将 Prometheus 指标转换为 K8s 自定义指标)。

1. 安装 Prometheus Adapter

bash

运行

# 添加仓库并更新
helm repo add prometheus-community https://prometheus-community.github.io/helm-charts
helm repo update

# 部署Prometheus Adapter到monitoring命名空间
helm install prometheus-adapter prometheus-community/prometheus-adapter \
  --namespace monitoring \
  --set prometheus.url=http://prometheus-server.monitoring.svc.cluster.local \
  --set prometheus.port=80
2. 配置 Prometheus Adapter 识别自定义指标

创建adapter-config.yaml,定义 QPS 指标转换规则:

yaml

apiVersion: v1
kind: ConfigMap
metadata:
  name: prometheus-adapter-config
  namespace: monitoring
data:
  config.yaml: |
    rules:
    - seriesQuery: 'torch_model_prediction_requests_total{endpoint=~"/predict",namespace!=""}'
      resources:
        overrides:
          namespace: {resource: "namespace"}
          pod: {resource: "pod"}
      name:
        matches: "^(.*)_total"
        as: "${1}_qps"
      metricsQuery: 'sum(rate(<<.Series>>{<<.LabelMatchers>>}[2m])) by (<<.GroupBy>>)'
---
# 更新Prometheus Adapter使用自定义配置
apiVersion: apps/v1
kind: Deployment
metadata:
  name: prometheus-adapter
  namespace: monitoring
spec:
  template:
    spec:
      containers:
      - name: prometheus-adapter
        args:
        - --metrics-relist-interval=1m
        - --config=/etc/adapter/config.yaml
        - --kubelet-insecure-tls
        - --kubelet-preferred-address-types=InternalIP,ExternalIP,Hostname
        volumeMounts:
        - name: config-volume
          mountPath: /etc/adapter
      volumes:
      - name: config-volume
        configMap:
          name: prometheus-adapter-config
3. 应用配置并验证

bash

运行

# 应用配置
kubectl apply -f adapter-config.yaml

# 重启Prometheus Adapter使配置生效
kubectl rollout restart deployment prometheus-adapter -n monitoring

# 验证自定义指标是否被识别
kubectl get --raw "/apis/custom.metrics.k8s.io/v1beta1/namespaces/default/pods/*/torch_model_prediction_requests_qps" | jq .
# 能看到指标数值,说明配置成功
4. 创建基于 QPS 的 HPA

更新torch-model-hpa.yaml,替换为自定义指标配置:

yaml

apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
  name: simple-torch-model-hpa
  namespace: default
spec:
  scaleTargetRef:
    apiVersion: apps/v1
    kind: Deployment
    name: simple-torch-model
  minReplicas: 1
  maxReplicas: 5
  behavior:
    scaleUp:
      stabilizationWindowSeconds: 30
      policies:
      - type: Percent
        value: 100
        periodSeconds: 60
    scaleDown:
      stabilizationWindowSeconds: 60
      policies:
      - type: Percent
        value: 50
        periodSeconds: 120
  # 基于Prometheus自定义指标(QPS)
  metrics:
  - type: Pods
    pods:
      metric:
        name: torch_model_prediction_requests_qps  # 自定义QPS指标
      target:
        type: AverageValue
        averageValue: 10  # 平均每个Pod QPS超过10触发扩容
  # 可选:保留CPU作为兜底指标
  # - type: Resource
  #   resource:
  #     name: cpu
  #     target:
  #       type: Utilization
  #       averageUtilization: 80
5. 部署并验证自定义指标 HPA

bash

运行

kubectl apply -f torch-model-hpa.yaml

# 查看HPA状态(TARGETS列会显示QPS数值)
kubectl get hpa simple-torch-model-hpa
# 输出示例:
# NAME                        REFERENCE                              TARGETS   MINPODS   MAXPODS   REPLICAS   AGE
# simple-torch-model-hpa      Deployment/simple-torch-model         0/10      1         5         1          20s

步骤 3:测试自动扩缩容
1. 模拟高 QPS 压力(触发扩容)

bash

运行

# 循环发送请求,模拟QPS>10
while true; do
  curl -X POST http://torch-model.local/predict \
    -H "Content-Type: application/json" \
    -d '{"data": [0.1]*784}' > /dev/null 2>&1
  sleep 0.05  # 每秒20个请求,超过阈值10
done
2. 观察 HPA 和 Pod 变化

bash

运行

# 实时查看HPA状态
watch kubectl get hpa simple-torch-model-hpa

# 实时查看Pod数量
watch kubectl get pods -l app=torch-model
  • 约 30 秒后,HPA 的 TARGETS 会显示 QPS 超过 10,REPLICAS 会从 1→2→4(按 100% 扩容策略);
  • 停止压力测试后,约 60 秒 HPA 会触发缩容,Pod 数逐步减少到 1。

关键配置说明
  1. HPA 核心参数

    • minReplicas/maxReplicas:控制 Pod 数量范围,避免无限扩容 / 缩容;
    • behaviorstabilizationWindowSeconds 避免短时间指标波动导致的 “抖动扩缩容”;
    • metrics
      • Resource:基于 CPU / 内存(原生支持,简单易配);
      • Pods:基于自定义 Pod 指标(需 Prometheus Adapter)。
  2. Prometheus Adapter 关键

    • seriesQuery:匹配 Prometheus 中的原始指标(torch_model_prediction_requests_total);
    • metricsQuery:计算 QPS(rate(指标[2m])),按 Pod / 命名空间分组;
    • 需确保指标标签包含namespace/pod,否则无法关联到 K8s 资源。
  3. 扩缩容策略调优

    • 扩容策略:scaleUpperiodSeconds不宜过小(避免频繁扩容);
    • 缩容策略:scaleDownstabilizationWindowSeconds建议比扩容大(避免缩容过快导致服务不可用)。

总结
  1. 基础 HPA 基于 CPU / 内存使用率,配置简单(仅需 Metrics Server),适合通用场景;
  2. 高级 HPA 基于 Prometheus 自定义指标(如 QPS),需安装 Prometheus Adapter,更贴合业务场景;
  3. 核心配置要点:
    • 基础 HPA:scaleTargetRef关联 Deployment,metrics设置 CPU / 内存阈值;
    • 自定义指标 HPA:通过 Prometheus Adapter 将 Prometheus 指标转换为 K8s 自定义指标,HPA 引用该指标;
    • behavior配置可避免扩缩容抖动,提升稳定性。

如果需要更精细的控制(如基于延迟扩缩容),只需修改 Prometheus Adapter 的指标规则,将 QPS 替换为延迟指标(torch_model_prediction_latency_seconds)即可,核心配置逻辑一致。

做完这个,你就能面:云原生 / 云原生 AI/K8s 架构师。

Logo

有“AI”的1024 = 2048,欢迎大家加入2048 AI社区

更多推荐