集群服务 Kubernetes 部署 - 阿里云 ACK 方案
适用场景:企业级生产环境、高可用、自动扩缩容、微服务架构
本文档:使用阿里云 ACK(托管 Kubernetes)部署完整应用
目录
一、核心概念
1.1 什么是 Kubernetes(K8s)?
┌─────────────────────────────────────────────────────────────────────────────────┐
│ K8s 是什么? │
├─────────────────────────────────────────────────────────────────────────────────┤
│ │
│ K8s = Kubernetes(K + 8个字母 + s)= 容器编排平台 │
│ │
│ 解决什么问题? │
│ ───────────────────────────────────────────────────────────────── │
│ │
│ 传统部署: K8s 部署: │
│ • 应用挂了 → 人工发现 → 人工重启 • 应用挂了 → 自动发现 → 自动重启 │
│ • 流量暴增 → 人工扩容 → 1小时 • 流量暴增 → 自动扩容 → 30秒 │
│ • 版本更新 → 停服维护 → 用户抱怨 • 版本更新 → 滚动更新 → 零停机 │
│ • 服务器宕机 → 用户无法访问 • 服务器宕机 → 自动迁移 → 用户无感知 │
│ │
│ 核心能力: │
│ ───────────────────────────────────────────────────────────────── │
│ • 自动调度:决定容器运行在哪台服务器 │
│ • 自动扩缩:根据负载自动增减容器数量 │
│ • 自动恢复:容器挂了自动重启 │
│ • 滚动更新:不停服更新版本 │
│ • 服务发现:自动找到服务地址 │
│ • 负载均衡:流量均匀分配 │
│ │
└─────────────────────────────────────────────────────────────────────────────────┘
1.2 什么是 ACK?
┌─────────────────────────────────────────────────────────────────────────────────┐
│ ACK 是什么? │
├─────────────────────────────────────────────────────────────────────────────────┤
│ │
│ ACK = Alibaba Cloud Kubernetes = 阿里云托管的 K8s 服务 │
│ │
│ 自建 K8s vs ACK 托管: │
│ ───────────────────────────────────────────────────────────────── │
│ │
│ ┌─────────────────────┬────────────────────┬────────────────────┐ │
│ │ 对比项 │ 自建 K8s │ ACK 托管 │ │
│ ├─────────────────────┼────────────────────┼────────────────────┤ │
│ │ Master 节点 │ 你搭建、你维护 │ 阿里云管理(免费) │ │
│ │ 高可用 │ 你配置 3 个 Master │ 阿里云保证 │ │
│ │ 版本升级 │ 你手动升级 │ 控制台一键升级 │ │
│ │ 安全补丁 │ 你自己打 │ 阿里云自动打 │ │
│ │ 故障处理 │ 你 7×24 值班 │ 阿里云 SLA 保障 │ │
│ │ 学习成本 │ ⭐⭐⭐⭐⭐ │ ⭐⭐ │ │
│ │ 运维成本 │ 高 │ 低 │ │
│ │ 费用 │ Master 服务器费 │ Master 免费 │ │
│ └─────────────────────┴────────────────────┴────────────────────┘ │
│ │
│ 结论:90% 场景用 ACK 托管版,省心省力! │
│ │
└─────────────────────────────────────────────────────────────────────────────────┘
1.3 K8s 核心组件
┌─────────────────────────────────────────────────────────────────────────────────┐
│ K8s 架构图 │
├─────────────────────────────────────────────────────────────────────────────────┤
│ │
│ ┌───────────────────────────────────────────────────────────────────────┐ │
│ │ 控制面 Control Plane(ACK 托管) │ │
│ │ │ │
│ │ ┌─────────────┐ ┌─────────────┐ ┌───────────────┐ ┌───────────┐ │ │
│ │ │ API Server │ │ Scheduler │ │ Controller │ │ etcd │ │ │
│ │ │ │ │ │ │ Manager │ │ │ │ │
│ │ │ 所有请求入口 │ │ 调度Pod到 │ │ 管理各种 │ │ 存储所有 │ │ │
│ │ │ kubectl命令 │ │ 哪个节点 │ │ 控制器 │ │ 集群状态 │ │ │
│ │ └─────────────┘ └─────────────┘ └───────────────┘ └───────────┘ │ │
│ │ │ │
│ └───────────────────────────────────────────────────────────────────────┘ │
│ │ │
│ ▼ │
│ ┌───────────────────────────────────────────────────────────────────────┐ │
│ │ 工作节点 Worker Node(你管理) │ │
│ │ │ │
│ │ ┌─────────────┐ ┌─────────────┐ ┌─────────────────────────────┐ │ │
│ │ │ kubelet │ │ kube-proxy │ │ Container Runtime │ │ │
│ │ │ │ │ │ │ │ │ │
│ │ │ 管理本节点 │ │ 管理网络 │ │ 运行容器(containerd) │ │ │
│ │ │ 的Pod │ │ 规则 │ │ │ │ │
│ │ └─────────────┘ └─────────────┘ └─────────────────────────────┘ │ │
│ │ │ │
│ │ ┌─────────────────────────────────────────────────────────────────┐ │ │
│ │ │ Pods │ │ │
│ │ │ ┌─────────┐ ┌─────────┐ ┌─────────┐ ┌─────────┐ │ │ │
│ │ │ │ Pod 1 │ │ Pod 2 │ │ Pod 3 │ │ Pod 4 │ │ │ │
│ │ │ │ 后端 │ │ 后端 │ │ 前端 │ │ 前端 │ │ │ │
│ │ │ └─────────┘ └─────────┘ └─────────┘ └─────────┘ │ │ │
│ │ └─────────────────────────────────────────────────────────────────┘ │ │
│ └───────────────────────────────────────────────────────────────────────┘ │
│ │
└─────────────────────────────────────────────────────────────────────────────────┘
1.4 K8s 资源对象
┌─────────────────────────────────────────────────────────────────────────────────┐
│ K8s 核心资源对象 │
├─────────────────────────────────────────────────────────────────────────────────┤
│ │
│ ┌──────────────┬────────────────────────────────┬──────────────────────────┐ │
│ │ 资源 │ 是什么 │ 什么时候用 │ │
│ ├──────────────┼────────────────────────────────┼──────────────────────────┤ │
│ │ Namespace │ 命名空间,隔离资源 │ 区分环境(dev/test/prod)│ │
│ │ Pod │ 最小部署单元,包含容器 │ 一般不直接创建 │ │
│ │ Deployment │ 无状态应用部署 │ Web服务、API(最常用) │ │
│ │ StatefulSet │ 有状态应用部署 │ 数据库(建议用云服务) │ │
│ │ Service │ 服务发现,负载均衡 │ 暴露Pod访问入口 │ │
│ │ Ingress │ HTTP/HTTPS入口网关 │ 对外暴露服务 │ │
│ │ ConfigMap │ 配置信息 │ 非敏感配置 │ │
│ │ Secret │ 敏感信息 │ 密码、密钥 │ │
│ │ PVC │ 持久化存储声明 │ 数据持久化 │ │
│ │ HPA │ 自动扩缩容 │ 根据CPU/内存自动扩缩 │ │
│ └──────────────┴────────────────────────────────┴──────────────────────────┘ │
│ │
│ 资源关系图: │
│ ───────────────────────────────────────────────────────────────── │
│ │
│ 用户请求 │
│ │ │
│ ▼ │
│ Ingress(入口网关,处理HTTPS) │
│ │ │
│ ▼ │
│ Service(服务发现,负载均衡) │
│ │ │
│ ▼ │
│ Deployment(管理Pod副本数、更新策略) │
│ │ │
│ ▼ │
│ Pod(运行容器) │
│ │
└─────────────────────────────────────────────────────────────────────────────────┘
二、整体架构
┌─────────────────────────────────────────────────────────────────────────────────┐
│ 企业级 ACK 部署架构 │
├─────────────────────────────────────────────────────────────────────────────────┤
│ │
│ 互联网用户 │
│ │ │
│ │ HTTPS │
│ ▼ │
│ ┌─────────────────────────────────────────────────────────────────────────┐ │
│ │ 阿里云 SLB(负载均衡) │ │
│ │ 公网IP + HTTPS证书 │ │
│ └─────────────────────────────────────────────────────────────────────────┘ │
│ │ │
│ ▼ │
│ ┌─────────────────────────────────────────────────────────────────────────┐ │
│ │ Nginx Ingress Controller │ │
│ │ 路由分发、限流、熔断 │ │
│ └─────────────────────────────────────────────────────────────────────────┘ │
│ │ │
│ ├────────────────────────┬────────────────────────┐ │
│ ▼ ▼ ▼ │
│ ┌─────────────┐ ┌─────────────┐ ┌─────────────┐ │
│ │ 前端 Pod │ │ 后端 Pod │ │ 后端 Pod │ │
│ │ ×2 副本 │ │ ×3 副本 │ │ (自动扩缩) │ │
│ └─────────────┘ └─────────────┘ └─────────────┘ │
│ │ │
│ ▼ │
│ ┌─────────────────────────────────────────────────────────────────────────┐ │
│ │ 阿里云云服务 │ │
│ │ ┌───────────────┐ ┌───────────────┐ ┌───────────────┐ │ │
│ │ │ RDS MySQL │ │ Redis │ │ OSS 存储 │ │ │
│ │ │ 主从高可用 │ │ 集群版 │ │ 静态文件 │ │ │
│ │ └───────────────┘ └───────────────┘ └───────────────┘ │ │
│ └─────────────────────────────────────────────────────────────────────────┘ │
│ │
└─────────────────────────────────────────────────────────────────────────────────┘
三、准备工作
3.1 注册阿里云账号
步骤:
1. 访问 https://www.aliyun.com
2. 点击「免费注册」
3. 完成实名认证(企业/个人)
4. 充值(建议 500 元起)
3.2 开通必要服务
| 服务 | 入口 | 用途 |
|---|---|---|
| ACK | https://cs.console.aliyun.com | K8s 集群 |
| ACR | https://cr.console.aliyun.com | 镜像仓库 |
| RDS | https://rdsnext.console.aliyun.com | MySQL 数据库 |
| Redis | https://kvstore.console.aliyun.com | 缓存 |
| SLB | https://slb.console.aliyun.com | 负载均衡 |
| 域名 | https://dc.console.aliyun.com | 域名管理 |
四、创建ACK集群
4.1 进入创建页面
路径:https://cs.console.aliyun.com → 集群列表 → 创建集群
4.2 选择集群类型
┌─────────────────────────────────────────────────────────────────────────────────┐
│ 选择集群类型 │
├─────────────────────────────────────────────────────────────────────────────────┤
│ │
│ ● ACK 托管版(推荐) │
│ └─ Master 免费托管,只需管理 Worker 节点 │
│ │
│ ○ ACK 专有版 │
│ └─ 自建 Master,需要更多服务器 │
│ │
│ ○ ACK Serverless │
│ └─ 无需管理节点,按 Pod 收费 │
│ │
│ 【选择】ACK 托管版 │
│ │
└─────────────────────────────────────────────────────────────────────────────────┘
4.3 集群配置
┌─────────────────────────────────────────────────────────────────────────────────┐
│ 集群基础配置 │
├─────────────────────────────────────────────────────────────────────────────────┤
│ │
│ 集群名称: │
│ ┌─────────────────────────────────────────────────────────────────────────┐ │
│ │ prod-cluster │ │
│ └─────────────────────────────────────────────────────────────────────────┘ │
│ 【说明】命名规范:环境-cluster,如 dev-cluster、test-cluster、prod-cluster │
│ │
│ 地域和可用区: │
│ ┌─────────────────────────────────────────────────────────────────────────┐ │
│ │ 中国(香港) ← 【选择】免备案 │ │
│ │ 华东1(杭州) ← 备案后可选,访问快 │ │
│ │ 华北2(北京) ← 备案后可选 │ │
│ └─────────────────────────────────────────────────────────────────────────┘ │
│ │
│ Kubernetes 版本: │
│ ┌─────────────────────────────────────────────────────────────────────────┐ │
│ │ 1.28.x(最新稳定版) ← 【选择】 │ │
│ └─────────────────────────────────────────────────────────────────────────┘ │
│ │
│ 专有网络: │
│ ┌─────────────────────────────────────────────────────────────────────────┐ │
│ │ ● 新建专有网络 ← 【选择】首次使用 │ │
│ │ ○ 使用已有专有网络 ← 有现成 VPC 可选 │ │
│ └─────────────────────────────────────────────────────────────────────────┘ │
│ │
│ Pod 网络 CIDR: │
│ ┌─────────────────────────────────────────────────────────────────────────┐ │
│ │ 172.16.0.0/16 ← 【默认】Pod 使用的 IP 段 │ │
│ └─────────────────────────────────────────────────────────────────────────┘ │
│ │
│ Service CIDR: │
│ ┌─────────────────────────────────────────────────────────────────────────┐ │
│ │ 10.96.0.0/16 ← 【默认】Service 使用的 IP 段 │ │
│ └─────────────────────────────────────────────────────────────────────────┘ │
│ │
└─────────────────────────────────────────────────────────────────────────────────┘
4.4 Worker 节点配置
┌─────────────────────────────────────────────────────────────────────────────────┐
│ Worker 节点配置 │
├─────────────────────────────────────────────────────────────────────────────────┤
│ │
│ 节点数量: │
│ ┌─────────────────────────────────────────────────────────────────────────┐ │
│ │ 3 ← 【推荐】生产环境最少 3 个 │ │
│ └─────────────────────────────────────────────────────────────────────────┘ │
│ 【说明】 │
│ • 1 个节点:不推荐,无高可用 │
│ • 2 个节点:可用,但扩展性差 │
│ • 3 个节点:推荐,高可用 │
│ • 5+ 节点:大型项目 │
│ │
│ 实例规格: │
│ ┌─────────────────────────────────────────────────────────────────────────┐ │
│ │ ecs.c6.xlarge(4核8G) ← 【推荐】生产环境起步配置 │ │
│ │ ecs.c6.2xlarge(8核16G) ← 中大型项目 │ │
│ │ ecs.g6.2xlarge(8核32G) ← 内存密集型 │ │
│ └─────────────────────────────────────────────────────────────────────────┘ │
│ 【说明】c6 = 计算型,g6 = 通用型,r6 = 内存型 │
│ │
│ 系统盘: │
│ ┌─────────────────────────────────────────────────────────────────────────┐ │
│ │ ESSD 云盘 120GB ← 【推荐】SSD 性能好 │ │
│ └─────────────────────────────────────────────────────────────────────────┘ │
│ │
│ 登录方式: │
│ ┌─────────────────────────────────────────────────────────────────────────┐ │
│ │ ● 密钥对 ← 【推荐】更安全 │ │
│ │ ○ 自定义密码 ← 简单场景 │ │
│ └─────────────────────────────────────────────────────────────────────────┘ │
│ │
└─────────────────────────────────────────────────────────────────────────────────┘
4.5 组件配置
┌─────────────────────────────────────────────────────────────────────────────────┐
│ 组件配置 │
├─────────────────────────────────────────────────────────────────────────────────┤
│ │
│ Ingress: │
│ ┌─────────────────────────────────────────────────────────────────────────┐ │
│ │ ☑ 安装 Nginx Ingress Controller ← 【必选】处理 HTTP/HTTPS 入口 │ │
│ │ ☐ 安装 ALB Ingress Controller ← 可选,使用 ALB 负载均衡 │ │
│ └─────────────────────────────────────────────────────────────────────────┘ │
│ │
│ 监控: │
│ ┌─────────────────────────────────────────────────────────────────────────┐ │
│ │ ☑ 安装 Prometheus 监控 ← 【必选】监控指标 │ │
│ │ ☑ 安装 metrics-server ← 【必选】HPA 自动扩缩需要 │ │
│ └─────────────────────────────────────────────────────────────────────────┘ │
│ │
│ 日志: │
│ ┌─────────────────────────────────────────────────────────────────────────┐ │
│ │ ☑ 安装日志服务组件 ← 【推荐】统一日志收集 │ │
│ └─────────────────────────────────────────────────────────────────────────┘ │
│ │
└─────────────────────────────────────────────────────────────────────────────────┘
4.6 确认创建
点击「创建集群」→ 等待 10-15 分钟 → 集群状态变为「运行中」
五、配置kubectl
5.1 安装 kubectl
Windows:
# 下载 kubectl
curl -LO "https://dl.k8s.io/release/v1.28.0/bin/windows/amd64/kubectl.exe"
# 移动到 PATH 目录(如 C:\Windows\System32)
move kubectl.exe C:\Windows\System32\
# 验证
kubectl version --client
Mac:
brew install kubectl
kubectl version --client
Linux:
curl -LO "https://dl.k8s.io/release/v1.28.0/bin/linux/amd64/kubectl"
chmod +x kubectl
mv kubectl /usr/local/bin/
kubectl version --client
5.2 获取 kubeconfig
路径:ACK 控制台 → 集群列表 → 点击集群名 → 连接信息 → 公网访问
5.3 保存配置
# 创建目录
mkdir -p ~/.kube
# 将复制的内容保存到 config 文件
# Windows: C:\Users\你的用户名\.kube\config
# Mac/Linux: ~/.kube/config
config 文件内容示例:
apiVersion: v1
kind: Config
clusters:
- cluster:
server: https://xxx.xxx.xxx.xxx:6443 # API Server 地址
certificate-authority-data: LS0tLS1C... # CA 证书
name: kubernetes
contexts:
- context:
cluster: kubernetes
user: kubernetes-admin
name: kubernetes-admin@kubernetes
current-context: kubernetes-admin@kubernetes
users:
- name: kubernetes-admin
user:
client-certificate-data: LS0tLS1C... # 客户端证书
client-key-data: LS0tLS1C... # 客户端密钥
5.4 验证连接
# 查看节点
kubectl get nodes
# 预期输出:
# NAME STATUS ROLES AGE VERSION
# cn-hongkong.10.0.1.100 Ready <none> 10m v1.28.0
# cn-hongkong.10.0.1.101 Ready <none> 10m v1.28.0
# cn-hongkong.10.0.1.102 Ready <none> 10m v1.28.0
六、创建镜像仓库
6.1 进入 ACR 控制台
路径:https://cr.console.aliyun.com
6.2 创建个人版实例(免费)
路径:实例列表 → 创建个人版实例
6.3 创建命名空间
路径:仓库管理 → 命名空间 → 创建命名空间
命名空间名称:myproject
# 【说明】一般用项目名或公司名
6.4 创建镜像仓库
路径:仓库管理 → 镜像仓库 → 创建镜像仓库
仓库名称:backend
命名空间:myproject
仓库类型:私有
代码源:本地仓库
# 创建完成后,完整镜像地址为:
# registry.cn-hongkong.aliyuncs.com/myproject/backend
6.5 配置访问凭证
路径:访问凭证 → 设置固定密码
用户名:阿里云账号全名
密码:【设置一个】
6.6 Docker 登录
# 登录镜像仓库
docker login registry.cn-hongkong.aliyuncs.com
# 输入用户名和密码
# 构建并推送镜像
docker build -t registry.cn-hongkong.aliyuncs.com/myproject/backend:v1.0.0 .
docker push registry.cn-hongkong.aliyuncs.com/myproject/backend:v1.0.0
七、部署中间件
7.1 推荐使用云服务
┌─────────────────────────────────────────────────────────────────────────────────┐
│ 中间件选择建议 │
├─────────────────────────────────────────────────────────────────────────────────┤
│ │
│ ┌──────────────┬────────────────────┬────────────────────┬──────────────────┐ │
│ │ 中间件 │ K8s 部署 │ 云服务 │ 推荐 │ │
│ ├──────────────┼────────────────────┼────────────────────┼──────────────────┤ │
│ │ MySQL │ 需维护、易丢数据 │ RDS 高可用、自动备份│ ⭐ 云服务 │ │
│ │ Redis │ 单节点风险 │ 集群版、自动扩容 │ ⭐ 云服务 │ │
│ │ RabbitMQ │ 可以 │ 云消息队列 │ 看需求 │ │
│ │ ElasticSearch│ 资源消耗大 │ 云搜索服务 │ ⭐ 云服务 │ │
│ └──────────────┴────────────────────┴────────────────────┴──────────────────┘ │
│ │
│ 【结论】数据库类用云服务!省心、安全、有保障 │
│ │
└─────────────────────────────────────────────────────────────────────────────────┘
7.2 购买 RDS MySQL
路径:https://rdsnext.console.aliyun.com → 创建实例
配置推荐:
┌─────────────────────────────────────────────────────────────────────────────────┐
│ 地域: 中国(香港) ← 与 ACK 同地域 │
│ 数据库类型: MySQL 8.0 │
│ 系列: 高可用版 ← 生产环境必选 │
│ 存储类型: ESSD 云盘 │
│ 规格: 2核4G ← 根据需求调整 │
│ 存储空间: 50GB ← 根据需求调整 │
└─────────────────────────────────────────────────────────────────────────────────┘
创建后:
1. 设置数据库账号密码
2. 创建数据库
3. 配置白名单(添加 ACK 的 VPC 网段)
4. 记录连接地址:rm-xxx.mysql.rds.aliyuncs.com
7.3 购买 Redis
路径:https://kvstore.console.aliyun.com → 创建实例
配置推荐:
┌─────────────────────────────────────────────────────────────────────────────────┐
│ 地域: 中国(香港) ← 与 ACK 同地域 │
│ 版本: Redis 7.0 │
│ 架构: 集群版 ← 生产环境推荐 │
│ 规格: 1GB ← 根据需求调整 │
└─────────────────────────────────────────────────────────────────────────────────┘
创建后:
1. 设置密码
2. 配置白名单
3. 记录连接地址:r-xxx.redis.rds.aliyuncs.com
八、部署应用
8.1 创建命名空间
文件位置:本地任意目录,如 ~/k8s/namespace.yaml
# ═══════════════════════════════════════════════════════════════════════════════
# 文件名:namespace.yaml
# 作用:创建命名空间,隔离不同环境/项目的资源
# 执行:kubectl apply -f namespace.yaml
# ═══════════════════════════════════════════════════════════════════════════════
apiVersion: v1
# ┌─────────────────────────────────────────────────────────────────────────────┐
# │ apiVersion: API 版本 │
# │ │
# │ 常用版本: │
# │ • v1 → 核心资源(Pod、Service、ConfigMap、Secret、Namespace) │
# │ • apps/v1 → 应用资源(Deployment、StatefulSet、DaemonSet) │
# │ • networking.k8s.io/v1 → 网络资源(Ingress、NetworkPolicy) │
# │ • batch/v1 → 批处理资源(Job、CronJob) │
# │ │
# │ 如何知道用哪个版本? │
# │ kubectl api-resources | grep Deployment │
# │ # 输出:deployments apps/v1 true Deployment │
# └─────────────────────────────────────────────────────────────────────────────┘
kind: Namespace
# ┌─────────────────────────────────────────────────────────────────────────────┐
# │ kind: 资源类型,首字母大写 │
# └─────────────────────────────────────────────────────────────────────────────┘
metadata:
name: prod
# ┌─────────────────────────────────────────────────────────────────────────┐
# │ name: 命名空间名称 │
# │ │
# │ 命名规范: │
# │ • 只能用小写字母、数字、连字符(-) │
# │ • 不能用下划线、空格 │
# │ │
# │ 【改】根据环境修改: │
# │ • dev → 开发环境 │
# │ • test → 测试环境 │
# │ • staging → 预发布环境 │
# │ • prod → 生产环境 │
# │ • myproject-prod → 项目名-环境 │
# └─────────────────────────────────────────────────────────────────────────┘
labels:
env: production
# ┌─────────────────────────────────────────────────────────────────────┐
# │ labels: 标签,用于分类和选择资源 │
# │ │
# │ 常用标签: │
# │ • env: production/staging/test/dev │
# │ • team: backend/frontend/devops │
# │ • app: myapp │
# └─────────────────────────────────────────────────────────────────────┘
执行:
kubectl apply -f namespace.yaml
# 输出:namespace/prod created
# 验证
kubectl get ns
8.2 创建 Secret
文件位置:~/k8s/secret.yaml
# ═══════════════════════════════════════════════════════════════════════════════
# 文件名:secret.yaml
# 作用:存储敏感信息(数据库密码、API密钥等)
# 执行:kubectl apply -f secret.yaml
# ═══════════════════════════════════════════════════════════════════════════════
apiVersion: v1
kind: Secret
metadata:
name: app-secrets
# ┌─────────────────────────────────────────────────────────────────────────┐
# │ name: Secret 名称 │
# │ 【改】可以改成:mysql-secret、redis-secret、app-secret 等 │
# └─────────────────────────────────────────────────────────────────────────┘
namespace: prod
# ┌─────────────────────────────────────────────────────────────────────────┐
# │ namespace: 所属命名空间 │
# │ 【改】与你的 Deployment 在同一个命名空间 │
# └─────────────────────────────────────────────────────────────────────────┘
type: Opaque
# ┌─────────────────────────────────────────────────────────────────────────────┐
# │ type: Secret 类型 │
# │ │
# │ 类型说明: │
# │ • Opaque → 通用类型,存储任意数据(最常用) │
# │ • kubernetes.io/tls → TLS 证书(包含 tls.crt 和 tls.key) │
# │ • kubernetes.io/dockerconfigjson → Docker 镜像仓库凭证 │
# │ • kubernetes.io/basic-auth → 用户名密码 │
# │ • kubernetes.io/ssh-auth → SSH 密钥 │
# └─────────────────────────────────────────────────────────────────────────────┘
stringData:
# ┌─────────────────────────────────────────────────────────────────────────┐
# │ stringData: 明文数据(会自动 Base64 编码存储) │
# │ │
# │ 也可以用 data 字段存储已编码的数据: │
# │ data: │
# │ MYSQL_PASSWORD: TXlQYXNzd29yZDEyMyE= # base64 编码 │
# │ │
# │ 编码命令:echo -n "MyPassword123!" | base64 │
# │ 解码命令:echo "TXlQYXNzd29yZDEyMyE=" | base64 -d │
# └─────────────────────────────────────────────────────────────────────────┘
MYSQL_HOST: "rm-xxx.mysql.rds.aliyuncs.com"
# 【改】你的 RDS 连接地址
MYSQL_PORT: "3306"
# 【改】一般不用改,MySQL 默认 3306
MYSQL_DATABASE: "mydb"
# 【改】你的数据库名
MYSQL_USERNAME: "root"
# 【改】数据库用户名
MYSQL_PASSWORD: "MyPassword123!"
# 【改】数据库密码,使用强密码!
REDIS_HOST: "r-xxx.redis.rds.aliyuncs.com"
# 【改】你的 Redis 连接地址
REDIS_PORT: "6379"
# 【改】一般不用改,Redis 默认 6379
REDIS_PASSWORD: "RedisPassword123!"
# 【改】Redis 密码
执行:
kubectl apply -f secret.yaml
# 输出:secret/app-secrets created
# 验证(不会显示明文)
kubectl get secret app-secrets -n prod
kubectl describe secret app-secrets -n prod
8.3 创建 ConfigMap
文件位置:~/k8s/configmap.yaml
# ═══════════════════════════════════════════════════════════════════════════════
# 文件名:configmap.yaml
# 作用:存储非敏感配置(日志级别、功能开关等)
# 执行:kubectl apply -f configmap.yaml
# ═══════════════════════════════════════════════════════════════════════════════
apiVersion: v1
kind: ConfigMap
metadata:
name: app-config
namespace: prod
data:
# ┌─────────────────────────────────────────────────────────────────────────┐
# │ data: 配置数据,键值对形式 │
# └─────────────────────────────────────────────────────────────────────────┘
# 简单键值对
LOG_LEVEL: "INFO"
# 【改】日志级别:DEBUG、INFO、WARN、ERROR
SPRING_PROFILES_ACTIVE: "prod"
# 【改】Spring 环境:dev、test、prod
SERVER_PORT: "8080"
# 一般不改,应用端口
# 配置文件内容
application-prod.yml: |
# ┌─────────────────────────────────────────────────────────────────────┐
# │ 用 | 符号可以存储多行文本(整个配置文件) │
# └─────────────────────────────────────────────────────────────────────┘
server:
port: 8080
logging:
level:
root: INFO
com.yourcompany: DEBUG
执行:
kubectl apply -f configmap.yaml
8.4 创建 Deployment
文件位置:~/k8s/backend-deployment.yaml
# ═══════════════════════════════════════════════════════════════════════════════
# 文件名:backend-deployment.yaml
# 作用:部署后端应用,管理 Pod 副本、更新策略、资源限制
# 执行:kubectl apply -f backend-deployment.yaml
# ═══════════════════════════════════════════════════════════════════════════════
apiVersion: apps/v1
kind: Deployment
metadata:
name: backend
# ┌─────────────────────────────────────────────────────────────────────────┐
# │ name: 资源名称(唯一标识) │
# │ │
# │ 作用: │
# │ • 给资源一个唯一标识,用于 kubectl 命令操作 │
# │ • kubectl get deployment backend │
# │ │
# │ 命名规则: │
# │ • 只能用:小写字母、数字、连字符(-) │
# │ • 不能用:下划线、空格、大写字母 │
# │ • 最长 63 个字符 │
# │ • 必须以字母或数字开头和结尾 │
# │ │
# │ 举例: │
# │ ✅ backend、user-service、order-api-v2 │
# │ ❌ Backend(大写)、user_service(下划线) │
# │ │
# │ 【改】根据服务改:backend、frontend、user-service、order-service │
# └─────────────────────────────────────────────────────────────────────────┘
namespace: prod
# ┌─────────────────────────────────────────────────────────────────────────┐
# │ namespace: 命名空间(逻辑隔离) │
# │ │
# │ 作用: │
# │ • 逻辑隔离:把不同项目/环境的资源分开 │
# │ • 权限控制:给不同团队分配不同命名空间的权限 │
# │ • 资源配额:限制每个命名空间使用的资源 │
# │ │
# │ 类比:命名空间 = 文件夹,资源 = 文件 │
# │ • 不同文件夹可以有同名文件 │
# │ • prod/backend 和 dev/backend 互不冲突 │
# │ │
# │ 常用命名空间: │
# │ • default → 默认(不指定时用这个) │
# │ • kube-system → K8s 系统组件 │
# │ • prod → 生产环境 │
# │ • dev → 开发环境 │
# │ • test → 测试环境 │
# │ │
# │ 【改】根据环境改:dev、test、staging、prod │
# └─────────────────────────────────────────────────────────────────────────┘
labels:
app: backend
version: v1
# ┌─────────────────────────────────────────────────────────────────────────┐
# │ labels: 标签(分类和选择) │
# │ │
# │ 作用: │
# │ • 分类资源:给资源打标签,方便筛选 │
# │ • 关联资源:Service 通过 labels 找到对应的 Pod │
# │ • 批量操作:按标签批量删除/查询 │
# │ │
# │ 格式:键值对(key: value) │
# │ │
# │ 常用标签: │
# │ • app: backend → 应用名 │
# │ • version: v1 → 版本 │
# │ • env: prod → 环境 │
# │ • team: backend-team → 团队 │
# │ │
# │ ════════════════════════════════════════════════════════════════════════│
# │ 标签匹配规则(重要!) │
# │ ════════════════════════════════════════════════════════════════════════│
# │ │
# │ Q: key 和 value 必须同时相等才算匹配吗? │
# │ A: 取决于匹配方式,有三种: │
# │ │
# │ 1️⃣ 精确匹配(Equality-based):key 和 value 必须完全相等 │
# │ ────────────────────────────────────────────────────────────────── │
# │ selector: │
# │ matchLabels: │
# │ app: backend # app 必须等于 backend │
# │ version: v1 # 且 version 必须等于 v1 │
# │ │
# │ Pod 标签必须同时满足所有条件才匹配: │
# │ ✅ {app: backend, version: v1} → 匹配 │
# │ ❌ {app: backend, version: v2} → 不匹配(version不对) │
# │ ❌ {app: frontend, version: v1} → 不匹配(app不对) │
# │ ❌ {app: backend} → 不匹配(缺少version) │
# │ │
# │ 2️⃣ 集合匹配(Set-based):更灵活的匹配方式 │
# │ ────────────────────────────────────────────────────────────────── │
# │ selector: │
# │ matchExpressions: │
# │ - key: app │
# │ operator: In │
# │ values: [backend, api] # app 是 backend 或 api │
# │ - key: version │
# │ operator: NotIn │
# │ values: [v0] # version 不是 v0 │
# │ - key: env │
# │ operator: Exists # 只要有 env 标签就行 │
# │ │
# │ operator 可选值: │
# │ • In → 值在列表中 │
# │ • NotIn → 值不在列表中 │
# │ • Exists → 只要有这个 key(不管 value) │
# │ • DoesNotExist → 没有这个 key │
# │ │
# │ 3️⃣ kubectl 命令行匹配 │
# │ ────────────────────────────────────────────────────────────────── │
# │ kubectl get pods -l app=backend # 精确匹配 │
# │ kubectl get pods -l app=backend,version=v1 # 多条件AND │
# │ kubectl get pods -l 'app in (backend,api)' # 集合匹配 │
# │ kubectl get pods -l 'env' # 存在性匹配 │
# │ kubectl get pods -l '!env' # 不存在匹配 │
# │ │
# │ 总结: │
# │ • matchLabels:key 和 value 必须完全相等,多个标签是 AND 关系 │
# │ • matchExpressions:更灵活,支持 In/NotIn/Exists 等操作 │
# └─────────────────────────────────────────────────────────────────────────┘
spec:
# ════════════════════════════════════════════════════════════════════════════
# spec: Deployment 的规格定义
# ════════════════════════════════════════════════════════════════════════════
replicas: 3
# ┌─────────────────────────────────────────────────────────────────────────┐
# │ replicas: Pod 副本数 │
# │ │
# │ 作用:指定运行多少个相同的 Pod 实例 │
# │ │
# │ 类型:整数 │
# │ │
# │ 取值范围:0 ~ 无上限(受节点资源限制) │
# │ │
# │ 常用配置: │
# │ ┌────────────┬──────────┬──────────────────────────────────────────────┐│
# │ │ 环境 │ 副本数 │ 说明 ││
# │ ├────────────┼──────────┼──────────────────────────────────────────────┤│
# │ │ 开发环境 │ 1 │ 节省资源 ││
# │ │ 测试环境 │ 2 │ 基本高可用 ││
# │ │ 预发布环境 │ 2-3 │ 接近生产配置 ││
# │ │ 生产环境 │ 3+ │ 保证高可用,至少 3 个 ││
# │ │ 高流量场景 │ 10+ │ 根据压测结果设定 ││
# │ └────────────┴──────────┴──────────────────────────────────────────────┘│
# │ │
# │ 计算方法: │
# │ • 副本数 = 预估 QPS / 单 Pod 承载 QPS │
# │ • 例:预估 1000 QPS,单 Pod 能承载 300 QPS │
# │ → 1000 / 300 = 3.33 → 向上取整 = 4 个副本 │
# │ • 再加 1-2 个冗余,最终设置 5-6 个 │
# │ │
# │ 举例: │
# │ replicas: 1 # 开发环境,单副本 │
# │ replicas: 3 # 生产环境,基本高可用 │
# │ replicas: 10 # 高流量,10 个副本 │
# │ replicas: 0 # 暂停服务(所有 Pod 会被删除) │
# │ │
# │ 【改】根据你的环境和流量调整 │
# └─────────────────────────────────────────────────────────────────────────┘
selector:
matchLabels:
app: backend
# ┌─────────────────────────────────────────────────────────────────────────┐
# │ selector: 选择器 │
# │ │
# │ 作用:告诉 Deployment 管理哪些 Pod │
# │ │
# │ ⚠️ 重要规则: │
# │ • selector.matchLabels 必须与 template.metadata.labels 一致 │
# │ • 否则 Deployment 无法找到并管理 Pod │
# │ │
# │ 两种写法: │
# │ │
# │ 写法1:matchLabels(精确匹配,最常用) │
# │ ────────────────────────────────────────────────────────────────────── │
# │ selector: │
# │ matchLabels: │
# │ app: backend # key=app,value=backend │
# │ version: v1 # 多个标签是 AND 关系 │
# │ │
# │ 写法2:matchExpressions(灵活匹配) │
# │ ────────────────────────────────────────────────────────────────────── │
# │ selector: │
# │ matchExpressions: │
# │ - key: app │
# │ operator: In # 操作符 │
# │ values: │
# │ - backend │
# │ - api # app 是 backend 或 api │
# │ - key: version │
# │ operator: NotIn │
# │ values: │
# │ - v0 # version 不是 v0 │
# │ │
# │ operator 枚举值: │
# │ ┌──────────────┬─────────────────────────────────────────────────────┐ │
# │ │ 操作符 │ 含义 │ │
# │ ├──────────────┼─────────────────────────────────────────────────────┤ │
# │ │ In │ 值在列表中(values 必填) │ │
# │ │ NotIn │ 值不在列表中(values 必填) │ │
# │ │ Exists │ 只要有这个 key(values 必须为空) │ │
# │ │ DoesNotExist │ 没有这个 key(values 必须为空) │ │
# │ └──────────────┴─────────────────────────────────────────────────────┘ │
# │ │
# │ 举例: │
# │ # 匹配 app=backend 或 app=api 的 Pod │
# │ selector: │
# │ matchExpressions: │
# │ - key: app │
# │ operator: In │
# │ values: [backend, api] │
# │ │
# │ # 匹配有 env 标签的 Pod(不管值是什么) │
# │ selector: │
# │ matchExpressions: │
# │ - key: env │
# │ operator: Exists │
# └─────────────────────────────────────────────────────────────────────────┘
strategy:
type: RollingUpdate
# ┌─────────────────────────────────────────────────────────────────────┐
# │ strategy.type: 更新策略类型 │
# │ │
# │ 作用:定义如何更新 Pod │
# │ │
# │ 枚举值(只有2个): │
# │ ┌───────────────┬────────────────────────────────────────────────┐ │
# │ │ 类型 │ 说明 │ │
# │ ├───────────────┼────────────────────────────────────────────────┤ │
# │ │ RollingUpdate │ 滚动更新(默认) │ │
# │ │ │ • 逐步替换旧 Pod │ │
# │ │ │ • 零停机 │ │
# │ │ │ • 【生产环境必须用这个】 │ │
# │ ├───────────────┼────────────────────────────────────────────────┤ │
# │ │ Recreate │ 重建 │ │
# │ │ │ • 先删除全部旧 Pod │ │
# │ │ │ • 再创建全部新 Pod │ │
# │ │ │ • ⚠️ 会停服!有一段时间无 Pod 可用 │ │
# │ │ │ • 用于:单副本、不能多版本共存的应用 │ │
# │ └───────────────┴────────────────────────────────────────────────┘ │
# │ │
# │ 举例: │
# │ # 滚动更新(推荐) │
# │ strategy: │
# │ type: RollingUpdate │
# │ rollingUpdate: │
# │ maxSurge: 1 │
# │ maxUnavailable: 0 │
# │ │
# │ # 重建(特殊场景) │
# │ strategy: │
# │ type: Recreate │
# │ # 不需要 rollingUpdate 配置 │
# └─────────────────────────────────────────────────────────────────────┘
rollingUpdate:
maxSurge: 1
# ┌─────────────────────────────────────────────────────────────────┐
# │ maxSurge: 最大浪涌数 │
# │ │
# │ 作用:更新时最多可以多创建几个 Pod │
# │ │
# │ 类型:整数 或 百分比字符串 │
# │ │
# │ 取值方式: │
# │ ┌─────────────┬──────────────────────────────────────────────┐ │
# │ │ 写法 │ 说明 │ │
# │ ├─────────────┼──────────────────────────────────────────────┤ │
# │ │ 1 │ 最多多 1 个 Pod │ │
# │ │ 2 │ 最多多 2 个 Pod │ │
# │ │ "25%" │ 最多多 25%(向上取整) │ │
# │ │ "50%" │ 最多多 50% │ │
# │ │ "100%" │ 最多多 100%(翻倍) │ │
# │ └─────────────┴──────────────────────────────────────────────┘ │
# │ │
# │ 计算举例(replicas=4,maxSurge=1): │
# │ • 更新时最多有 4 + 1 = 5 个 Pod 同时运行 │
# │ • 先创建 1 个新 Pod │
# │ • 新 Pod 就绪后,删除 1 个旧 Pod │
# │ • 重复直到全部更新完成 │
# │ │
# │ 计算举例(replicas=10,maxSurge="25%"): │
# │ • 25% × 10 = 2.5 → 向上取整 = 3 │
# │ • 更新时最多有 10 + 3 = 13 个 Pod │
# │ │
# │ 推荐配置: │
# │ • 小规模(1-5副本):maxSurge: 1 │
# │ • 中规模(5-20副本):maxSurge: "25%" │
# │ • 大规模(20+副本):maxSurge: "25%" 或 "10%" │
# │ │
# │ 举例: │
# │ maxSurge: 1 # 推荐,稳妥 │
# │ maxSurge: 2 # 更快更新 │
# │ maxSurge: "25%" # 按比例 │
# │ maxSurge: "100%" # 蓝绿部署效果 │
# └─────────────────────────────────────────────────────────────────┘
maxUnavailable: 0
# ┌─────────────────────────────────────────────────────────────────┐
# │ maxUnavailable: 最大不可用数 │
# │ │
# │ 作用:更新时最多允许几个 Pod 不可用 │
# │ │
# │ 类型:整数 或 百分比字符串 │
# │ │
# │ 取值方式: │
# │ ┌─────────────┬──────────────────────────────────────────────┐ │
# │ │ 写法 │ 说明 │ │
# │ ├─────────────┼──────────────────────────────────────────────┤ │
# │ │ 0 │ 不允许有 Pod 不可用【推荐】 │ │
# │ │ 1 │ 最多 1 个 Pod 不可用 │ │
# │ │ "25%" │ 最多 25% 不可用(向下取整) │ │
# │ │ "50%" │ 最多 50% 不可用 │ │
# │ └─────────────┴──────────────────────────────────────────────┘ │
# │ │
# │ ⚠️ 重要约束: │
# │ • maxSurge 和 maxUnavailable 不能同时为 0 │
# │ • 否则无法更新(既不能多创建,又不能删除) │
# │ │
# │ 计算举例(replicas=4,maxUnavailable=1): │
# │ • 更新时最少有 4 - 1 = 3 个 Pod 可用 │
# │ • 先删除 1 个旧 Pod │
# │ • 创建 1 个新 Pod │
# │ • 等新 Pod 就绪后,再删除下一个旧 Pod │
# │ │
# │ 推荐配置: │
# │ • 生产环境:maxUnavailable: 0(零停机) │
# │ • 允许短暂降级:maxUnavailable: 1 或 "25%" │
# │ │
# │ 常见组合: │
# │ ┌─────────────────────────────┬─────────────────────────────┐ │
# │ │ 配置 │ 效果 │ │
# │ ├─────────────────────────────┼─────────────────────────────┤ │
# │ │ maxSurge: 1 │ 最稳妥,零停机 │ │
# │ │ maxUnavailable: 0 │ 但更新较慢 │ │
# │ ├─────────────────────────────┼─────────────────────────────┤ │
# │ │ maxSurge: "25%" │ 平衡速度和稳定 │ │
# │ │ maxUnavailable: "25%" │ │ │
# │ ├─────────────────────────────┼─────────────────────────────┤ │
# │ │ maxSurge: "100%" │ 类似蓝绿部署 │ │
# │ │ maxUnavailable: 0 │ 最快,资源消耗大 │ │
# │ └─────────────────────────────┴─────────────────────────────┘ │
# │ │
# │ 【推荐】生产环境用 maxSurge: 1, maxUnavailable: 0 │
# └─────────────────────────────────────────────────────────────────┘
template:
# ┌─────────────────────────────────────────────────────────────────────┐
# │ template: Pod 模板 │
# │ │
# │ 作用:定义 Pod 的具体内容(元数据 + 规格) │
# │ │
# │ 结构: │
# │ template: │
# │ metadata: → Pod 的元数据(标签等) │
# │ spec: → Pod 的规格(容器、卷等) │
# └─────────────────────────────────────────────────────────────────────┘
metadata:
labels:
app: backend
version: v1
# ┌─────────────────────────────────────────────────────────────────┐
# │ template.metadata.labels: Pod 的标签 │
# │ │
# │ ⚠️ 重要:必须与上面 selector.matchLabels 一致 │
# │ │
# │ 常用标签: │
# │ • app: backend → 应用名(必须) │
# │ • version: v1 → 版本(推荐) │
# │ • env: prod → 环境 │
# │ • team: backend-team → 团队 │
# │ • release: stable → 发布状态 │
# │ │
# │ 可选:添加 annotations(注解) │
# │ annotations: │
# │ prometheus.io/scrape: "true" # Prometheus 抓取 │
# │ prometheus.io/port: "8080" # 抓取端口 │
# └─────────────────────────────────────────────────────────────────┘
spec:
# ════════════════════════════════════════════════════════════════════
# Pod 规格定义
# ════════════════════════════════════════════════════════════════════
containers:
# ┌─────────────────────────────────────────────────────────────────────┐
# │ containers: 容器列表 │
# │ │
# │ 作用:定义 Pod 中运行的容器(可以多个) │
# │ │
# │ 一个 Pod 多个容器的场景: │
# │ • Sidecar 模式:主容器 + 日志收集容器 │
# │ • Ambassador 模式:主容器 + 代理容器 │
# │ • Adapter 模式:主容器 + 格式转换容器 │
# │ │
# │ 举例(单容器,最常见): │
# │ containers: │
# │ - name: backend │
# │ image: xxx │
# │ │
# │ 举例(多容器,Sidecar): │
# │ containers: │
# │ - name: backend # 主容器 │
# │ image: backend:v1 │
# │ - name: log-collector # Sidecar 容器 │
# │ image: fluentd:latest │
# └─────────────────────────────────────────────────────────────────────┘
- name: backend
# ┌─────────────────────────────────────────────────────────────────┐
# │ name: 容器名称 │
# │ │
# │ 作用:容器的唯一标识 │
# │ │
# │ 命名规则: │
# │ • 只能用小写字母、数字、连字符 │
# │ • 同一 Pod 内必须唯一 │
# │ │
# │ 用途: │
# │ • kubectl logs <pod> -c backend # 指定查看哪个容器的日志 │
# │ • kubectl exec -c backend # 指定进入哪个容器 │
# │ │
# │ 【改】根据服务命名:backend、frontend、api、worker 等 │
# └─────────────────────────────────────────────────────────────────┘
image: registry.cn-hongkong.aliyuncs.com/myproject/backend:v1.0.0
# ┌─────────────────────────────────────────────────────────────────┐
# │ image: 容器镜像地址 │
# │ │
# │ 格式:[仓库地址/][命名空间/]镜像名[:标签] │
# │ │
# │ 完整格式举例: │
# │ ┌─────────────────────────────────────────────────────────────┐ │
# │ │ registry.cn-hongkong.aliyuncs.com/myproject/backend:v1.0.0 │ │
# │ │ ├─────────────────────────────┤ ├───────┤ ├─────┤ ├─────┤ │ │
# │ │ │ 仓库地址 │ │命名空间│ │镜像名│ │标签 │ │ │
# │ └─────────────────────────────────────────────────────────────┘ │
# │ │
# │ 仓库地址举例: │
# │ ┌─────────────────────────────────────┬───────────────────────┐ │
# │ │ 仓库地址 │ 说明 │ │
# │ ├─────────────────────────────────────┼───────────────────────┤ │
# │ │ (省略) │ Docker Hub 官方 │ │
# │ │ registry.cn-hongkong.aliyuncs.com │ 阿里云香港 │ │
# │ │ registry.cn-hangzhou.aliyuncs.com │ 阿里云杭州 │ │
# │ │ ccr.ccs.tencentyun.com │ 腾讯云 │ │
# │ │ ghcr.io │ GitHub │ │
# │ │ gcr.io │ Google │ │
# │ │ your-registry.com │ 私有仓库 │ │
# │ └─────────────────────────────────────┴───────────────────────┘ │
# │ │
# │ 标签规范(推荐语义化版本): │
# │ ┌─────────────────┬──────────────────────────────────────────┐ │
# │ │ 标签 │ 说明 │ │
# │ ├─────────────────┼──────────────────────────────────────────┤ │
# │ │ v1.0.0 │ 语义化版本(推荐!) │ │
# │ │ v1.0.0-alpha │ 预发布版本 │ │
# │ │ v1.0.0-rc.1 │ 候选版本 │ │
# │ │ latest │ 最新版(❌不推荐,不可控) │ │
# │ │ abc123def │ Git commit SHA(CI/CD 常用) │ │
# │ │ 20240101-1 │ 日期+序号 │ │
# │ │ main-abc123 │ 分支名+commit │ │
# │ └─────────────────┴──────────────────────────────────────────┘ │
# │ │
# │ 【改】替换为你的镜像地址 │
# └─────────────────────────────────────────────────────────────────┘
imagePullPolicy: IfNotPresent
# ┌─────────────────────────────────────────────────────────────────┐
# │ imagePullPolicy: 镜像拉取策略 │
# │ │
# │ 作用:决定何时从仓库拉取镜像 │
# │ │
# │ 枚举值(只有3个): │
# │ ┌────────────────┬─────────────────────────────────────────────┐│
# │ │ 值 │ 说明 ││
# │ ├────────────────┼─────────────────────────────────────────────┤│
# │ │ Always │ 每次启动 Pod 都拉取镜像 ││
# │ │ │ • latest 标签默认使用此策略 ││
# │ │ │ • 保证使用最新镜像 ││
# │ │ │ • 但启动较慢,依赖网络 ││
# │ ├────────────────┼─────────────────────────────────────────────┤│
# │ │ IfNotPresent │ 本地没有才拉取【推荐】 ││
# │ │ │ • 指定版本标签默认使用此策略 ││
# │ │ │ • 启动快 ││
# │ │ │ • 生产环境推荐 ││
# │ ├────────────────┼─────────────────────────────────────────────┤│
# │ │ Never │ 从不拉取,只用本地镜像 ││
# │ │ │ • 本地没有会报错 ││
# │ │ │ • 用于离线环境 ││
# │ └────────────────┴─────────────────────────────────────────────┘│
# │ │
# │ 默认行为: │
# │ • 标签是 latest 或省略 → Always │
# │ • 标签是其他(如 v1.0.0)→ IfNotPresent │
# │ │
# │ 【推荐】使用具体版本标签 + IfNotPresent │
# └─────────────────────────────────────────────────────────────────┘
ports:
- name: http
containerPort: 8080
protocol: TCP
# ┌─────────────────────────────────────────────────────────────────┐
# │ ports: 容器端口配置 │
# │ │
# │ 作用:声明容器暴露的端口(仅声明,不会自动暴露到外部) │
# │ │
# │ 字段说明: │
# │ ┌─────────────────┬────────────────────────────────────────────┐│
# │ │ 字段 │ 说明 ││
# │ ├─────────────────┼────────────────────────────────────────────┤│
# │ │ name │ 端口名称(可选) ││
# │ │ │ • Service 可通过名称引用 ││
# │ │ │ • 只能用小写字母、数字、连字符 ││
# │ ├─────────────────┼────────────────────────────────────────────┤│
# │ │ containerPort │ 容器内端口号(必填) ││
# │ │ │ • 范围:1-65535 ││
# │ ├─────────────────┼────────────────────────────────────────────┤│
# │ │ protocol │ 协议(可选,默认 TCP) ││
# │ │ │ • 枚举值:TCP、UDP、SCTP ││
# │ ├─────────────────┼────────────────────────────────────────────┤│
# │ │ hostPort │ 宿主机端口(可选,不推荐) ││
# │ │ │ • 直接映射到节点端口 ││
# │ │ │ • 会限制 Pod 调度 ││
# │ └─────────────────┴────────────────────────────────────────────┘│
# │ │
# │ 常用端口举例: │
# │ ┌──────────────────────┬─────────────────────────────────────┐ │
# │ │ 应用 │ 端口 │ │
# │ ├──────────────────────┼─────────────────────────────────────┤ │
# │ │ Spring Boot │ 8080 │ │
# │ │ Node.js │ 3000 │ │
# │ │ Go │ 8080 │ │
# │ │ Python Flask │ 5000 │ │
# │ │ Nginx │ 80、443 │ │
# │ │ MySQL │ 3306 │ │
# │ │ Redis │ 6379 │ │
# │ │ PostgreSQL │ 5432 │ │
# │ └──────────────────────┴─────────────────────────────────────┘ │
# │ │
# │ 多端口举例: │
# │ ports: │
# │ - name: http │
# │ containerPort: 8080 │
# │ protocol: TCP │
# │ - name: metrics # Prometheus 指标端口 │
# │ containerPort: 9090 │
# │ protocol: TCP │
# │ - name: grpc # gRPC 端口 │
# │ containerPort: 9000 │
# │ protocol: TCP │
# │ │
# │ 【改】根据应用实际端口修改 │
# └─────────────────────────────────────────────────────────────────┘
env:
# ┌─────────────────────────────────────────────────────────────────┐
# │ env: 环境变量配置 │
# │ │
# │ 作用:设置容器内的环境变量 │
# │ │
# │ 四种来源: │
# │ ┌───────────────────────────────────────────────────────────┐ │
# │ │ 1. 直接写值 │ │
# │ │ ─────────────────────────────────────────────────────────│ │
# │ │ - name: LOG_LEVEL │ │
# │ │ value: "INFO" │ │
# │ └───────────────────────────────────────────────────────────┘ │
# │ │
# │ ┌───────────────────────────────────────────────────────────┐ │
# │ │ 2. 从 Secret 获取(敏感信息) │ │
# │ │ ─────────────────────────────────────────────────────────│ │
# │ │ - name: DB_PASSWORD │ │
# │ │ valueFrom: │ │
# │ │ secretKeyRef: │ │
# │ │ name: mysql-secret # Secret 名称 │ │
# │ │ key: password # Secret 中的 key │ │
# │ │ optional: false # 是否可选,默认 false │ │
# │ └───────────────────────────────────────────────────────────┘ │
# │ │
# │ ┌───────────────────────────────────────────────────────────┐ │
# │ │ 3. 从 ConfigMap 获取(配置信息) │ │
# │ │ ─────────────────────────────────────────────────────────│ │
# │ │ - name: LOG_LEVEL │ │
# │ │ valueFrom: │ │
# │ │ configMapKeyRef: │ │
# │ │ name: app-config # ConfigMap 名称 │ │
# │ │ key: log_level # ConfigMap 中的 key │ │
# │ └───────────────────────────────────────────────────────────┘ │
# │ │
# │ ┌───────────────────────────────────────────────────────────┐ │
# │ │ 4. 从 Pod 信息获取(fieldRef) │ │
# │ │ ─────────────────────────────────────────────────────────│ │
# │ │ - name: POD_NAME │ │
# │ │ valueFrom: │ │
# │ │ fieldRef: │ │
# │ │ fieldPath: metadata.name # Pod 名称 │ │
# │ │ - name: POD_IP │ │
# │ │ valueFrom: │ │
# │ │ fieldRef: │ │
# │ │ fieldPath: status.podIP # Pod IP │ │
# │ │ - name: NODE_NAME │ │
# │ │ valueFrom: │ │
# │ │ fieldRef: │ │
# │ │ fieldPath: spec.nodeName # 节点名称 │ │
# │ │ - name: NAMESPACE │ │
# │ │ valueFrom: │ │
# │ │ fieldRef: │ │
# │ │ fieldPath: metadata.namespace # 命名空间 │ │
# │ └───────────────────────────────────────────────────────────┘ │
# │ │
# │ fieldRef 可用字段: │
# │ • metadata.name → Pod 名称 │
# │ • metadata.namespace → 命名空间 │
# │ • metadata.uid → Pod UID │
# │ • metadata.labels['x'] → 获取标签值 │
# │ • spec.nodeName → 节点名称 │
# │ • spec.serviceAccountName → ServiceAccount 名称 │
# │ • status.podIP → Pod IP │
# │ • status.hostIP → 节点 IP │
# │ │
# │ 变量引用(在 value 中引用其他变量): │
# │ - name: FULL_URL │
# │ value: "http://$(HOST):$(PORT)/api" # $(变量名) │
# └─────────────────────────────────────────────────────────────────┘
- name: TZ
value: "Asia/Shanghai"
# ┌─────────────────────────────────────────────────────────────────┐
# │ TZ: 时区设置 │
# │ │
# │ 作用:设置容器时区,保证日志时间正确 │
# │ │
# │ 常用时区: │
# │ • Asia/Shanghai → 中国标准时间(北京时间) │
# │ • Asia/Hong_Kong → 香港时间 │
# │ • UTC → 世界协调时间 │
# │ • America/New_York → 美国东部时间 │
# └─────────────────────────────────────────────────────────────────┘
- name: SPRING_PROFILES_ACTIVE
valueFrom:
configMapKeyRef:
name: app-config
key: SPRING_PROFILES_ACTIVE
# 从 ConfigMap 获取
- name: SPRING_DATASOURCE_URL
value: "jdbc:mysql://$(MYSQL_HOST):$(MYSQL_PORT)/$(MYSQL_DATABASE)?useSSL=false&serverTimezone=Asia/Shanghai"
# ┌─────────────────────────────────────────────────────────────┐
# │ $(VAR_NAME) 可以引用其他环境变量 │
# └─────────────────────────────────────────────────────────────┘
- name: MYSQL_HOST
valueFrom:
secretKeyRef:
name: app-secrets
key: MYSQL_HOST
- name: MYSQL_PORT
valueFrom:
secretKeyRef:
name: app-secrets
key: MYSQL_PORT
- name: MYSQL_DATABASE
valueFrom:
secretKeyRef:
name: app-secrets
key: MYSQL_DATABASE
- name: SPRING_DATASOURCE_USERNAME
valueFrom:
secretKeyRef:
name: app-secrets
key: MYSQL_USERNAME
- name: SPRING_DATASOURCE_PASSWORD
valueFrom:
secretKeyRef:
name: app-secrets
key: MYSQL_PASSWORD
- name: SPRING_REDIS_HOST
valueFrom:
secretKeyRef:
name: app-secrets
key: REDIS_HOST
- name: SPRING_REDIS_PORT
valueFrom:
secretKeyRef:
name: app-secrets
key: REDIS_PORT
- name: SPRING_REDIS_PASSWORD
valueFrom:
secretKeyRef:
name: app-secrets
key: REDIS_PASSWORD
resources:
requests:
memory: "512Mi"
cpu: "250m"
limits:
memory: "1Gi"
cpu: "500m"
# ┌─────────────────────────────────────────────────────────────────┐
# │ resources: 资源配置 │
# │ │
# │ 作用:限制容器使用的 CPU 和内存资源 │
# │ │
# │ ════════════════════════════════════════════════════════════════│
# │ requests(请求) │
# │ ════════════════════════════════════════════════════════════════│
# │ • 调度时保证的最小资源 │
# │ • 节点剩余资源 >= requests 才能调度到该节点 │
# │ • 影响 Pod 调度位置 │
# │ │
# │ ════════════════════════════════════════════════════════════════│
# │ limits(限制) │
# │ ════════════════════════════════════════════════════════════════│
# │ • 容器最多能用的资源 │
# │ • CPU 超过 limits:被限流(throttled),变慢但不会被杀 │
# │ • Memory 超过 limits:被 OOM Kill,容器重启 │
# │ │
# │ ════════════════════════════════════════════════════════════════│
# │ CPU 单位 │
# │ ════════════════════════════════════════════════════════════════│
# │ ┌────────────┬────────────┬───────────────────────────────────┐ │
# │ │ 写法 │ 含义 │ 举例 │ │
# │ ├────────────┼────────────┼───────────────────────────────────┤ │
# │ │ 1 │ 1 个 CPU核 │ 1 核 │ │
# │ │ 0.5 │ 0.5 个核 │ 半个核 │ │
# │ │ 1000m │ 1000毫核=1核│ m = milli(千分之一) │ │
# │ │ 500m │ 0.5 核 │ 500毫核 │ │
# │ │ 250m │ 0.25 核 │ 250毫核 │ │
# │ │ 100m │ 0.1 核 │ 100毫核 │ │
# │ └────────────┴────────────┴───────────────────────────────────┘ │
# │ │
# │ ════════════════════════════════════════════════════════════════│
# │ Memory 单位 │
# │ ════════════════════════════════════════════════════════════════│
# │ ┌────────────┬────────────┬───────────────────────────────────┐ │
# │ │ 写法 │ 含义 │ 举例 │ │
# │ ├────────────┼────────────┼───────────────────────────────────┤ │
# │ │ Ki │ Kibibyte │ 1Ki = 1024 bytes │ │
# │ │ Mi │ Mebibyte │ 1Mi = 1024 Ki ≈ 1MB │ │
# │ │ Gi │ Gibibyte │ 1Gi = 1024 Mi ≈ 1GB │ │
# │ │ Ti │ Tebibyte │ 1Ti = 1024 Gi ≈ 1TB │ │
# │ ├────────────┼────────────┼───────────────────────────────────┤ │
# │ │ K │ Kilobyte │ 1K = 1000 bytes(不推荐) │ │
# │ │ M │ Megabyte │ 1M = 1000 K │ │
# │ │ G │ Gigabyte │ 1G = 1000 M │ │
# │ └────────────┴────────────┴───────────────────────────────────┘ │
# │ │
# │ ⚠️ 推荐用 Mi、Gi(二进制单位),避免用 M、G │
# │ │
# │ ════════════════════════════════════════════════════════════════│
# │ 各类应用推荐配置 │
# │ ════════════════════════════════════════════════════════════════│
# │ ┌─────────────────┬─────────────────┬─────────────────────────┐ │
# │ │ 应用类型 │ requests │ limits │ │
# │ ├─────────────────┼─────────────────┼─────────────────────────┤ │
# │ │ Spring Boot │ cpu: 250m │ cpu: 500m-1 │ │
# │ │ │ memory: 512Mi │ memory: 1Gi-2Gi │ │
# │ ├─────────────────┼─────────────────┼─────────────────────────┤ │
# │ │ Node.js │ cpu: 100m │ cpu: 500m │ │
# │ │ │ memory: 128Mi │ memory: 512Mi │ │
# │ ├─────────────────┼─────────────────┼─────────────────────────┤ │
# │ │ Go │ cpu: 100m │ cpu: 500m │ │
# │ │ │ memory: 64Mi │ memory: 256Mi │ │
# │ ├─────────────────┼─────────────────┼─────────────────────────┤ │
# │ │ Python │ cpu: 100m │ cpu: 500m │ │
# │ │ │ memory: 256Mi │ memory: 512Mi │ │
# │ ├─────────────────┼─────────────────┼─────────────────────────┤ │
# │ │ Nginx │ cpu: 50m │ cpu: 200m │ │
# │ │ │ memory: 64Mi │ memory: 256Mi │ │
# │ └─────────────────┴─────────────────┴─────────────────────────┘ │
# │ │
# │ ════════════════════════════════════════════════════════════════│
# │ 最佳实践 │
# │ ════════════════════════════════════════════════════════════════│
# │ 1. requests 设为实际平均使用量(通过监控获取) │
# │ 2. limits 设为 requests 的 1.5-2 倍 │
# │ 3. 不要设置过大的 limits(浪费资源) │
# │ 4. 不要设置过小的 limits(频繁 OOM) │
# │ 5. 建议设置 requests = limits(QoS 为 Guaranteed) │
# │ │
# │ QoS 等级: │
# │ • Guaranteed:requests = limits(最高优先级) │
# │ • Burstable:requests < limits │
# │ • BestEffort:不设置 resources(最低优先级) │
# │ │
# │ 【改】根据实际监控数据调整 │
# └─────────────────────────────────────────────────────────────────┘
readinessProbe:
httpGet:
path: /actuator/health/readiness
port: 8080
initialDelaySeconds: 30
periodSeconds: 10
timeoutSeconds: 5
successThreshold: 1
failureThreshold: 3
# ┌─────────────────────────────────────────────────────────────────┐
# │ readinessProbe: 就绪探针 │
# │ │
# │ 作用:判断 Pod 是否准备好接收流量 │
# │ • 检查成功:加入 Service 负载均衡,开始接收请求 │
# │ • 检查失败:从 Service 移除,不接收请求(但不重启) │
# │ │
# │ ════════════════════════════════════════════════════════════════│
# │ 三种检查方式 │
# │ ════════════════════════════════════════════════════════════════│
# │ │
# │ 方式1:HTTP GET(最常用) │
# │ ────────────────────────────────────────────────────────────── │
# │ readinessProbe: │
# │ httpGet: │
# │ path: /health # 检查路径 │
# │ port: 8080 # 检查端口 │
# │ scheme: HTTP # 协议,HTTP 或 HTTPS │
# │ httpHeaders: # 可选,自定义请求头 │
# │ - name: Custom-Header │
# │ value: value │
# │ │
# │ 返回状态码 200-399 为成功,其他为失败 │
# │ │
# │ 方式2:TCP Socket │
# │ ────────────────────────────────────────────────────────────── │
# │ readinessProbe: │
# │ tcpSocket: │
# │ port: 8080 # 检查端口是否能连接 │
# │ │
# │ 端口能连接为成功 │
# │ │
# │ 方式3:执行命令 │
# │ ────────────────────────────────────────────────────────────── │
# │ readinessProbe: │
# │ exec: │
# │ command: │
# │ - cat │
# │ - /tmp/healthy │
# │ │
# │ 命令返回 0 为成功,非 0 为失败 │
# │ │
# │ ════════════════════════════════════════════════════════════════│
# │ 参数详解 │
# │ ════════════════════════════════════════════════════════════════│
# │ ┌──────────────────────┬──────┬─────────────────────────────┐ │
# │ │ 参数 │默认值│ 说明 │ │
# │ ├──────────────────────┼──────┼─────────────────────────────┤ │
# │ │ initialDelaySeconds │ 0 │ 容器启动后等待多少秒开始检查 │ │
# │ │ │ │ 【改】Spring Boot 设 30-60 │ │
# │ ├──────────────────────┼──────┼─────────────────────────────┤ │
# │ │ periodSeconds │ 10 │ 检查间隔秒数 │ │
# │ ├──────────────────────┼──────┼─────────────────────────────┤ │
# │ │ timeoutSeconds │ 1 │ 检查超时秒数 │ │
# │ ├──────────────────────┼──────┼─────────────────────────────┤ │
# │ │ successThreshold │ 1 │ 连续成功几次算成功 │ │
# │ │ │ │ readiness 可设 1-3 │ │
# │ ├──────────────────────┼──────┼─────────────────────────────┤ │
# │ │ failureThreshold │ 3 │ 连续失败几次算失败 │ │
# │ └──────────────────────┴──────┴─────────────────────────────┘ │
# │ │
# │ 常用健康检查路径: │
# │ • Spring Boot: /actuator/health/readiness │
# │ • Node.js: /health, /ready │
# │ • Go: /healthz, /ready │
# │ • 自定义: /ping, /status │
# └─────────────────────────────────────────────────────────────────┘
livenessProbe:
httpGet:
path: /actuator/health/liveness
port: 8080
initialDelaySeconds: 60
periodSeconds: 10
timeoutSeconds: 5
failureThreshold: 3
# ┌─────────────────────────────────────────────────────────────────┐
# │ livenessProbe: 存活探针 │
# │ │
# │ 作用:判断容器是否还活着,需不需要重启 │
# │ • 检查成功:正常 │
# │ • 检查失败:kubelet 会杀死容器并重启 │
# │ │
# │ ════════════════════════════════════════════════════════════════│
# │ readinessProbe vs livenessProbe 对比 │
# │ ════════════════════════════════════════════════════════════════│
# │ ┌─────────────────┬───────────────────┬───────────────────────┐ │
# │ │ 探针 │ 检查失败时 │ 用途 │ │
# │ ├─────────────────┼───────────────────┼───────────────────────┤ │
# │ │ readinessProbe │ 从 Service 移除 │ 是否可以接收流量 │ │
# │ │ │ 不再接收请求 │ 启动中、过载时不接收 │ │
# │ │ │ 不会重启 │ │ │
# │ ├─────────────────┼───────────────────┼───────────────────────┤ │
# │ │ livenessProbe │ 重启容器 │ 是否需要重启 │ │
# │ │ │ │ 死锁、假死时重启 │ │
# │ └─────────────────┴───────────────────┴───────────────────────┘ │
# │ │
# │ ⚠️ 重要注意事项: │
# │ 1. liveness 的 initialDelaySeconds 要 > readiness 的 │
# │ • 避免应用还在启动就被 liveness 判定失败重启 │
# │ • 造成无限重启循环 │
# │ │
# │ 2. liveness 不要检查外部依赖(如数据库) │
# │ • 数据库挂了,重启应用也没用 │
# │ • 只检查应用自身状态 │
# │ │
# │ 3. readiness 可以检查外部依赖 │
# │ • 数据库挂了,暂时不接收请求 │
# │ • 等数据库恢复后再接收 │
# │ │
# │ 推荐配置: │
# │ ┌─────────────────┬───────────────────┬───────────────────────┐ │
# │ │ 应用 │ initialDelay │ periodSeconds │ │
# │ ├─────────────────┼───────────────────┼───────────────────────┤ │
# │ │ Spring Boot │ readiness: 30 │ 10 │ │
# │ │ │ liveness: 60 │ 10 │ │
# │ ├─────────────────┼───────────────────┼───────────────────────┤ │
# │ │ Node.js │ readiness: 5 │ 5 │ │
# │ │ │ liveness: 15 │ 10 │ │
# │ ├─────────────────┼───────────────────┼───────────────────────┤ │
# │ │ Go │ readiness: 3 │ 5 │ │
# │ │ │ liveness: 10 │ 10 │ │
# │ └─────────────────┴───────────────────┴───────────────────────┘ │
# └─────────────────────────────────────────────────────────────────┘
# 还有一个可选探针:startupProbe(启动探针)
# startupProbe:
# httpGet:
# path: /actuator/health
# port: 8080
# initialDelaySeconds: 0
# periodSeconds: 10
# timeoutSeconds: 5
# failureThreshold: 30 # 30 × 10 = 300秒 = 5分钟
# ┌─────────────────────────────────────────────────────────────────┐
# │ startupProbe: 启动探针(K8s 1.18+) │
# │ │
# │ 作用:专门用于启动慢的应用 │
# │ • 启动探针成功前,liveness 和 readiness 不会执行 │
# │ • 启动探针成功后,才开始 liveness 和 readiness 检查 │
# │ │
# │ 适用场景: │
# │ • 启动时间超过 1 分钟的应用 │
# │ • 旧版应用,启动时间不确定 │
# │ │
# │ 例:failureThreshold: 30, periodSeconds: 10 │
# │ → 最多等待 30 × 10 = 300 秒(5分钟) │
# └─────────────────────────────────────────────────────────────────┘
lifecycle:
preStop:
exec:
command: ["/bin/sh", "-c", "sleep 15"]
# ┌─────────────────────────────────────────────────────────────────┐
# │ lifecycle: 生命周期钩子 │
# │ │
# │ 作用:在容器生命周期的特定时刻执行操作 │
# │ │
# │ ════════════════════════════════════════════════════════════════│
# │ preStop: 容器停止前执行 │
# │ ════════════════════════════════════════════════════════════════│
# │ • 在收到 SIGTERM 之前执行 │
# │ • 用于优雅关闭 │
# │ │
# │ 常用方式: │
# │ ┌─────────────────────────────────────────────────────────────┐ │
# │ │ # 方式1:执行命令(最常用) │ │
# │ │ preStop: │ │
# │ │ exec: │ │
# │ │ command: ["/bin/sh", "-c", "sleep 15"] │ │
# │ │ │ │
# │ │ # 方式2:HTTP 请求 │ │
# │ │ preStop: │ │
# │ │ httpGet: │ │
# │ │ path: /shutdown │ │
# │ │ port: 8080 │ │
# │ └─────────────────────────────────────────────────────────────┘ │
# │ │
# │ 为什么要 sleep? │
# │ • K8s 从 Service 移除 Pod 需要时间(Endpoint 更新延迟) │
# │ • sleep 期间不再接收新请求 │
# │ • 等待已有请求处理完成 │
# │ • 推荐 sleep 15-30 秒 │
# │ │
# │ ════════════════════════════════════════════════════════════════│
# │ postStart: 容器启动后执行 │
# │ ════════════════════════════════════════════════════════════════│
# │ postStart: │
# │ exec: │
# │ command: ["/bin/sh", "-c", "echo started >> /var/log/app"] │
# │ │
# │ 用途:初始化操作、注册到服务发现等 │
# │ ⚠️ 注意:postStart 与容器 ENTRYPOINT 并行执行 │
# └─────────────────────────────────────────────────────────────────┘
terminationGracePeriodSeconds: 30
# ┌─────────────────────────────────────────────────────────────────────┐
# │ terminationGracePeriodSeconds: 优雅终止等待时间 │
# │ │
# │ 作用:定义 Pod 停止时的最大等待时间 │
# │ │
# │ 类型:整数(秒) │
# │ 默认值:30 │
# │ 范围:0 - 无上限(但一般不超过 300 秒) │
# │ │
# │ ════════════════════════════════════════════════════════════════════│
# │ Pod 停止完整流程 │
# │ ════════════════════════════════════════════════════════════════════│
# │ │
# │ ┌────────────────────────────────────────────────────────────────┐ │
# │ │ 1. kubectl delete pod xxx 或 Deployment 更新 │ │
# │ │ │ │ │
# │ │ ▼ │ │
# │ │ 2. Pod 状态变为 Terminating │ │
# │ │ │ │ │
# │ │ ▼ │ │
# │ │ 3. 从所有 Service 的 Endpoint 中移除(不再接收新请求) │ │
# │ │ │ │ │
# │ │ ▼(并行执行) │ │
# │ │ 4. 执行 preStop 钩子(如 sleep 15) │ │
# │ │ │ │ │
# │ │ ▼(preStop 完成后) │ │
# │ │ 5. 发送 SIGTERM 信号给容器主进程 │ │
# │ │ │ │ │
# │ │ ▼(等待进程退出) │ │
# │ │ 6. 等待最多 terminationGracePeriodSeconds 秒 │ │
# │ │ │ │ │
# │ │ ▼(超时或进程退出) │ │
# │ │ 7. 发送 SIGKILL 强制终止 │ │
# │ │ │ │ │
# │ │ ▼ │ │
# │ │ 8. Pod 被删除 │ │
# │ └────────────────────────────────────────────────────────────────┘ │
# │ │
# │ 设置建议: │
# │ • terminationGracePeriodSeconds >= preStop 时间 + 应用关闭时间 │
# │ • 例:preStop sleep 15 秒,应用关闭需要 10 秒 │
# │ → terminationGracePeriodSeconds 至少设 30 │
# │ │
# │ 【改】根据应用实际关闭时间调整 │
# └─────────────────────────────────────────────────────────────────────┘
affinity:
podAntiAffinity:
preferredDuringSchedulingIgnoredDuringExecution:
- weight: 100
podAffinityTerm:
labelSelector:
matchLabels:
app: backend
topologyKey: kubernetes.io/hostname
# ┌─────────────────────────────────────────────────────────────────────┐
# │ affinity: 亲和性配置 │
# │ │
# │ 作用:控制 Pod 调度到哪些节点 │
# │ │
# │ ════════════════════════════════════════════════════════════════════│
# │ 三种亲和性 │
# │ ════════════════════════════════════════════════════════════════════│
# │ │
# │ 1. nodeAffinity(节点亲和性) │
# │ ────────────────────────────────────────────────────────────────── │
# │ 作用:Pod 调度到特定节点 │
# │ │
# │ affinity: │
# │ nodeAffinity: │
# │ # 硬性要求:必须调度到有 GPU 的节点 │
# │ requiredDuringSchedulingIgnoredDuringExecution: │
# │ nodeSelectorTerms: │
# │ - matchExpressions: │
# │ - key: gpu │
# │ operator: Exists │
# │ │
# │ # 软性偏好:尽量调度到 SSD 节点 │
# │ preferredDuringSchedulingIgnoredDuringExecution: │
# │ - weight: 100 │
# │ preference: │
# │ matchExpressions: │
# │ - key: disk-type │
# │ operator: In │
# │ values: [ssd] │
# │ │
# │ 2. podAffinity(Pod 亲和性) │
# │ ────────────────────────────────────────────────────────────────── │
# │ 作用:Pod 和其他 Pod 调度到一起(同节点/同可用区) │
# │ 场景:减少网络延迟(如前端和后端在同一节点) │
# │ │
# │ affinity: │
# │ podAffinity: │
# │ requiredDuringSchedulingIgnoredDuringExecution: │
# │ - labelSelector: │
# │ matchLabels: │
# │ app: cache # 和 cache Pod 在一起 │
# │ topologyKey: kubernetes.io/hostname │
# │ │
# │ 3. podAntiAffinity(Pod 反亲和性)【最常用】 │
# │ ────────────────────────────────────────────────────────────────── │
# │ 作用:Pod 和其他 Pod 不在一起(分散到不同节点) │
# │ 场景:高可用,避免单点故障 │
# │ │
# │ affinity: │
# │ podAntiAffinity: │
# │ # 软性偏好:尽量分散到不同节点 │
# │ preferredDuringSchedulingIgnoredDuringExecution: │
# │ - weight: 100 │
# │ podAffinityTerm: │
# │ labelSelector: │
# │ matchLabels: │
# │ app: backend │
# │ topologyKey: kubernetes.io/hostname │
# │ │
# │ ════════════════════════════════════════════════════════════════════│
# │ 调度类型 │
# │ ════════════════════════════════════════════════════════════════════│
# │ ┌──────────────────────────────────────────┬────────────────────┐ │
# │ │ 类型 │ 说明 │ │
# │ ├──────────────────────────────────────────┼────────────────────┤ │
# │ │ requiredDuringSchedulingIgnored... │ 硬性要求 │ │
# │ │ │ 不满足不调度 │ │
# │ ├──────────────────────────────────────────┼────────────────────┤ │
# │ │ preferredDuringSchedulingIgnored... │ 软性偏好 │ │
# │ │ │ 尽量满足 │ │
# │ │ │ weight: 1-100 │ │
# │ └──────────────────────────────────────────┴────────────────────┘ │
# │ │
# │ ════════════════════════════════════════════════════════════════════│
# │ topologyKey 常用值 │
# │ ════════════════════════════════════════════════════════════════════│
# │ ┌────────────────────────────────┬───────────────────────────────┐ │
# │ │ topologyKey │ 含义 │ │
# │ ├────────────────────────────────┼───────────────────────────────┤ │
# │ │ kubernetes.io/hostname │ 节点级别(同一节点) │ │
# │ │ topology.kubernetes.io/zone │ 可用区级别(同一可用区) │ │
# │ │ topology.kubernetes.io/region │ 地域级别(同一地域) │ │
# │ └────────────────────────────────┴───────────────────────────────┘ │
# │ │
# │ 【推荐】生产环境使用 podAntiAffinity,让 Pod 分散到不同节点 │
# │ • podAffinity: 让某些 Pod 在一起(减少网络延迟) │
# └─────────────────────────────────────────────────────────────────┘
执行:
kubectl apply -f backend-deployment.yaml
# 查看部署状态
kubectl get deployment -n prod
kubectl get pods -n prod
# 查看 Pod 详情(排查问题用)
kubectl describe pod <pod-name> -n prod
# 查看日志
kubectl logs -f <pod-name> -n prod
8.5 创建 Service
文件位置:~/k8s/backend-service.yaml
# ═══════════════════════════════════════════════════════════════════════════════
# 文件名:backend-service.yaml
# 作用:为 Pod 提供固定访问入口和负载均衡
# 执行:kubectl apply -f backend-service.yaml
# ═══════════════════════════════════════════════════════════════════════════════
apiVersion: v1
kind: Service
metadata:
name: backend-service
# ┌─────────────────────────────────────────────────────────────────────────┐
# │ name: Service 名称 │
# │ 【改】与 Deployment 名称对应:backend-service、frontend-service │
# │ │
# │ 集群内访问方式: │
# │ http://backend-service.prod.svc.cluster.local:8080 │
# │ 或简写:http://backend-service:8080(同命名空间内) │
# └─────────────────────────────────────────────────────────────────────────┘
namespace: prod
spec:
selector:
app: backend
# ┌─────────────────────────────────────────────────────────────────────┐
# │ selector: 选择哪些 Pod │
# │ 必须与 Deployment 的 template.metadata.labels 匹配 │
# └─────────────────────────────────────────────────────────────────────┘
ports:
- name: http
port: 8080
targetPort: 8080
protocol: TCP
# ┌─────────────────────────────────────────────────────────────────────┐
# │ ports: 端口配置 │
# │ │
# │ • port: Service 端口(访问 Service 用这个端口) │
# │ • targetPort: Pod 端口(转发到 Pod 的这个端口) │
# │ • protocol: TCP 或 UDP │
# │ │
# │ 例子: │
# │ 访问 backend-service:8080 → 转发到 Pod:8080 │
# │ │
# │ port 和 targetPort 可以不同: │
# │ port: 80 │
# │ targetPort: 8080 │
# │ → 访问 Service:80,转发到 Pod:8080 │
# └─────────────────────────────────────────────────────────────────────┘
type: ClusterIP
# ┌─────────────────────────────────────────────────────────────────────┐
# │ type: Service 类型 │
# │ │
# │ ClusterIP(默认): │
# │ • 只能集群内部访问 │
# │ • 分配一个虚拟 IP(ClusterIP) │
# │ • 【推荐】后端服务用这个,通过 Ingress 暴露 │
# │ │
# │ NodePort: │
# │ type: NodePort │
# │ ports: │
# │ - port: 8080 │
# │ targetPort: 8080 │
# │ nodePort: 30080 # 30000-32767 范围 │
# │ • 在每个节点开放一个端口 │
# │ • 可通过 节点IP:30080 访问 │
# │ • 适合测试,生产环境不推荐 │
# │ │
# │ LoadBalancer: │
# │ type: LoadBalancer │
# │ • 云厂商自动创建负载均衡器 │
# │ • 有公网 IP │
# │ • 费用较高,每个 Service 一个 SLB │
# │ • 单个服务暴露时可用 │
# │ │
# │ ExternalName: │
# │ type: ExternalName │
# │ externalName: rm-xxx.mysql.rds.aliyuncs.com │
# │ • 映射到外部 DNS 名称 │
# │ • 用于访问外部服务 │
# └─────────────────────────────────────────────────────────────────────┘
执行:
kubectl apply -f backend-service.yaml
# 验证
kubectl get svc -n prod
九、配置Ingress和HTTPS
9.1 创建 Ingress
文件位置:~/k8s/ingress.yaml
# ═══════════════════════════════════════════════════════════════════════════════
# 文件名:ingress.yaml
# 作用:对外暴露服务,处理 HTTPS,路由分发
# 执行:kubectl apply -f ingress.yaml
# ═══════════════════════════════════════════════════════════════════════════════
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: app-ingress
namespace: prod
annotations:
# ┌─────────────────────────────────────────────────────────────────────┐
# │ annotations: 注解,用于配置 Ingress Controller 的行为 │
# └─────────────────────────────────────────────────────────────────────┘
kubernetes.io/ingress.class: nginx
# 指定使用 Nginx Ingress Controller
nginx.ingress.kubernetes.io/ssl-redirect: "true"
# HTTP 自动重定向到 HTTPS
nginx.ingress.kubernetes.io/proxy-body-size: "100m"
# 【改】最大请求体大小,上传大文件需要调大
nginx.ingress.kubernetes.io/proxy-connect-timeout: "60"
nginx.ingress.kubernetes.io/proxy-send-timeout: "60"
nginx.ingress.kubernetes.io/proxy-read-timeout: "60"
# 【改】超时时间,长连接或大文件需要调大
# 以下是可选配置
# nginx.ingress.kubernetes.io/rewrite-target: /$1
# URL 重写,去掉路径前缀
spec:
tls:
- hosts:
- example.com
- www.example.com
secretName: tls-secret
# ┌─────────────────────────────────────────────────────────────────────┐
# │ tls: HTTPS 配置 │
# │ │
# │ • hosts: 需要 HTTPS 的域名 │
# │ 【改】替换为你的域名 │
# │ • secretName: 存储证书的 Secret 名称 │
# │ 需要先创建包含证书的 Secret(见下一节) │
# └─────────────────────────────────────────────────────────────────────┘
rules:
- host: example.com
# ┌─────────────────────────────────────────────────────────────────────┐
# │ host: 域名 │
# │ 【改】替换为你的域名 │
# │ │
# │ 可以配置多个域名: │
# │ - host: api.example.com # API 服务 │
# │ - host: admin.example.com # 管理后台 │
# └─────────────────────────────────────────────────────────────────────┘
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: frontend-service
port:
number: 80
# ┌─────────────────────────────────────────────────────────────────┐
# │ / 路径 → frontend-service │
# │ │
# │ pathType 可选值: │
# │ • Prefix: 前缀匹配(推荐) │
# │ /user 匹配 /user、/user/123、/user/list │
# │ • Exact: 精确匹配 │
# │ /user 只匹配 /user,不匹配 /user/123 │
# │ • ImplementationSpecific: 由 Ingress Controller 决定 │
# └─────────────────────────────────────────────────────────────────┘
- path: /api
pathType: Prefix
backend:
service:
name: backend-service
port:
number: 8080
# ┌─────────────────────────────────────────────────────────────────┐
# │ /api 路径 → backend-service │
# │ │
# │ 注意:路径匹配顺序 │
# │ • 更长的路径优先匹配 │
# │ • /api/v1 比 /api 优先 │
# └─────────────────────────────────────────────────────────────────┘
- host: www.example.com
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: frontend-service
port:
number: 80
9.2 创建 TLS Secret
方式1:使用已有证书
# 如果你已经有证书文件(fullchain.pem 和 privkey.pem)
kubectl create secret tls tls-secret \
--cert=fullchain.pem \
--key=privkey.pem \
-n prod
方式2:使用 Cert-Manager 自动申请(推荐)
# 安装 Cert-Manager
kubectl apply -f https://github.com/cert-manager/cert-manager/releases/download/v1.13.0/cert-manager.yaml
# 等待安装完成
kubectl get pods -n cert-manager
创建证书颁发者:~/k8s/cluster-issuer.yaml
# ═══════════════════════════════════════════════════════════════════════════════
# 文件名:cluster-issuer.yaml
# 作用:配置 Let's Encrypt 证书颁发者
# 执行:kubectl apply -f cluster-issuer.yaml
# ═══════════════════════════════════════════════════════════════════════════════
apiVersion: cert-manager.io/v1
kind: ClusterIssuer
metadata:
name: letsencrypt-prod
spec:
acme:
server: https://acme-v02.api.letsencrypt.org/directory
# Let's Encrypt 生产环境服务器
email: your-email@example.com
# 【改】你的邮箱,用于证书到期提醒
privateKeySecretRef:
name: letsencrypt-prod-key
solvers:
- http01:
ingress:
class: nginx
# 使用 HTTP-01 验证方式
修改 Ingress 使用自动证书:
# 在 ingress.yaml 的 annotations 中添加:
annotations:
cert-manager.io/cluster-issuer: letsencrypt-prod
# 指定使用 letsencrypt-prod 颁发者自动申请证书
执行:
kubectl apply -f cluster-issuer.yaml
kubectl apply -f ingress.yaml
# 查看证书状态
kubectl get certificate -n prod
十、CI/CD自动化部署
10.1 使用阿里云云效
入口:https://devops.aliyun.com
步骤1:创建代码库
路径:云效 → Codeup → 新建代码库 / 导入仓库
步骤2:创建流水线
路径:云效 → Flow → 新建流水线 → 选择「Java + Docker + K8s部署」模板
步骤3:配置流水线阶段
| 阶段 | 类型 | 配置 |
|---|---|---|
| 1 | 代码检出 | 选择 Codeup 仓库,分支 main |
| 2 | Java构建 | 命令:mvn clean package -DskipTests |
| 3 | 镜像构建 | 推送到 ACR |
| 4 | K8s部署 | 选择 ACK 集群、命名空间、Deployment |
步骤4:配置触发
流水线设置 → 触发设置 → ☑ 代码提交触发 → 分支 main
10.2 部署 YAML
文件位置:项目根目录 k8s/deployment.yaml
# 云效会自动替换 ${IMAGE} 变量
image: ${IMAGE}
十一、监控告警
11.1 使用阿里云 ARMS(推荐)
路径:ACK 控制台 → 集群详情 → 运维管理 → Prometheus监控
优点:
• 与 ACK 深度集成
• 自动发现服务
• 内置大量 Dashboard
• 支持告警
11.2 查看监控
路径:ARMS → Prometheus监控 → Grafana → 选择 Dashboard
十二、金丝雀发布
12.1 什么是金丝雀发布
传统发布:一次性全部更新,有问题影响所有用户
金丝雀发布:
1. 先发布 10% 的 Pod 运行新版本
2. 观察监控、日志,确认没问题
3. 逐步增加新版本比例
4. 最终全部更新
12.2 使用 Ingress 实现
# ═══════════════════════════════════════════════════════════════════════════════
# 金丝雀发布配置
# ═══════════════════════════════════════════════════════════════════════════════
# 主版本 Ingress
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: app-ingress-stable
namespace: prod
spec:
rules:
- host: example.com
http:
paths:
- path: /api
pathType: Prefix
backend:
service:
name: backend-stable
port:
number: 8080
---
# 金丝雀版本 Ingress
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: app-ingress-canary
namespace: prod
annotations:
nginx.ingress.kubernetes.io/canary: "true"
nginx.ingress.kubernetes.io/canary-weight: "10"
# 10% 流量到金丝雀版本
spec:
rules:
- host: example.com
http:
paths:
- path: /api
pathType: Prefix
backend:
service:
name: backend-canary
port:
number: 8080
十三、常见问题
13.1 Pod 启动失败
# 查看 Pod 状态
kubectl get pods -n prod
# 查看详情
kubectl describe pod <pod-name> -n prod
# 常见原因:
# ImagePullBackOff → 镜像拉取失败,检查镜像地址和凭证
# CrashLoopBackOff → 应用启动失败,查看日志
# Pending → 资源不足或调度失败
# 查看日志
kubectl logs <pod-name> -n prod
13.2 Service 无法访问
# 检查 Service
kubectl get svc -n prod
kubectl describe svc backend-service -n prod
# 检查 Endpoints(是否有 Pod 关联)
kubectl get endpoints backend-service -n prod
# 如果 Endpoints 为空,检查 selector 是否匹配
13.3 Ingress 无法访问
# 检查 Ingress
kubectl get ingress -n prod
kubectl describe ingress app-ingress -n prod
# 检查 Ingress Controller
kubectl get pods -n kube-system | grep ingress
# 检查 SLB
# ACK 控制台 → 负载均衡 → 查看监听状态
完整清单
阶段一:基础设施
☐ 1. 注册阿里云账号,实名认证
☐ 2. 开通 ACK、ACR、RDS、Redis 服务
☐ 3. 创建 ACK 集群(托管版)
☐ 4. 配置 kubectl
☐ 5. 创建 ACR 镜像仓库
☐ 6. 购买 RDS MySQL
☐ 7. 购买 Redis
☐ 8. 购买域名
阶段二:部署应用
☐ 9. 构建并推送镜像
☐ 10. 创建 Namespace
☐ 11. 创建 Secret
☐ 12. 创建 ConfigMap
☐ 13. 部署 Deployment
☐ 14. 创建 Service
☐ 15. 配置 Ingress
☐ 16. 配置 HTTPS 证书
阶段三:运维
☐ 17. 配置 CI/CD(云效)
☐ 18. 配置监控告警
☐ 19. 配置 HPA 自动扩缩
✅ 完成!访问 https://你的域名
1282

被折叠的 条评论
为什么被折叠?



