K8s 部署学习笔记
一、环境准备
1.1 安装 minikube
powershell
# 下载 minikube(Windows)
# 访问 https://github.com/kubernetes/minikube/releases
# 下载 minikube-windows-amd64.exe,重命名为 minikube.exe,放到 C:\minikube\
# 验证安装
C:\minikube\minikube.exe version
1.2 启动 minikube 集群
powershell
# 基本启动
C:\minikube\minikube.exe start --driver=docker --memory=4096 --cpus=2
# 国内镜像加速(如果网络慢)
C:\minikube\minikube.exe start --driver=docker --memory=4096 --cpus=2 --image-mirror-country=cn
常见问题:网络问题导致镜像拉取失败
表格
| 错误 | 解决 |
|---|---|
cannot pull kicbase image |
配置 Docker 镜像加速器,或手动拉取镜像 |
registry.cn-hangzhou.aliyuncs.com/... not found |
阿里云镜像源缺少某些镜像,改用默认源 |
二、部署过程中的问题与解决
问题 1:ImagePullBackOff(镜像拉取失败)
现象:
powershell
kubectl get pods -n camp
# NAME READY STATUS RESTARTS AGE
# camp-auth-xxx 0/1 ImagePullBackOff 0 5m
原因分析:
-
镜像仓库需要认证(私有镜像)
-
镜像不存在或拼写错误
-
网络问题(国内访问 ghcr.io 慢/被墙)
错误日志:
plain
Failed to pull image "ghcr.io/...": unauthorized
解决方案:
方案 A:本地构建并加载镜像(推荐用于学习)
powershell
# 1. 确认本地有镜像
docker images | findstr camp
# 2. 给镜像打上 YAML 中期望的标签
docker tag kubernetes-microservices-camp-auth:latest ghcr.io/elishatheodore/kubernetes-microservices/camp-auth:latest
docker tag kubernetes-microservices-camp-web:latest ghcr.io/elishatheodore/kubernetes-microservices/camp-web:latest
docker tag kubernetes-microservices-camp-backend:latest ghcr.io/elishatheodore/kubernetes-microservices/camp-backend:latest
# 3. 加载到 minikube
minikube image load ghcr.io/elishatheodore/kubernetes-microservices/camp-auth:latest
minikube image load ghcr.io/elishatheodore/kubernetes-microservices/camp-web:latest
minikube image load ghcr.io/elishatheodore/kubernetes-microservices/camp-backend:latest
# 4. 验证
minikube ssh -- docker images | findstr camp
方案 B:配置镜像拉取密钥(用于私有仓库)
powershell
# 创建 docker-registry 密钥
kubectl create secret docker-registry ghcr-secret `
--docker-server=ghcr.io `
--docker-username=你的GitHub用户名 `
--docker-password=你的GitHubToken `
-n camp
# 在 Deployment 中添加 imagePullSecrets
# spec.template.spec.imagePullSecrets:
# - name: ghcr-secret
问题 2:imagePullPolicy 导致重复拉取镜像
现象: 即使镜像已加载到 minikube,Pod 仍然尝试从远程拉取。
原因: 当镜像标签是 latest 时,K8s 默认 imagePullPolicy: Always,每次都从远程拉取。
解决: 修改 Deployment,添加 imagePullPolicy: Never
yaml
spec:
containers:
- name: camp-auth
image: ghcr.io/elishatheodore/kubernetes-microservices/camp-auth:latest
imagePullPolicy: Never # ← 添加这一行
批量修改命令:
powershell
(Get-Content auth-frontend-deployment.yaml) -replace 'imagePullPolicy: Always', 'imagePullPolicy: Never' | Set-Content auth-frontend-deployment.yaml
问题 3:PVC Pending(持久化存储未绑定)
现象:
powershell
kubectl get pvc -n camp
# NAME STATUS VOLUME CAPACITY ACCESS MODES STORAGECLASS
# camp-database-pvc Pending default
原因分析:
-
StorageClass
default不存在 -
minikube 的 storage-provisioner 未启用
错误日志:
plain
storageclass.storage.k8s.io "default" not found
解决方案:
方案 A:创建 StorageClass
powershell
# 查看现有 StorageClass
kubectl get storageclass
# 创建 default StorageClass
@"
apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
name: default
annotations:
storageclass.kubernetes.io/is-default-class: "true"
provisioner: k8s.io/minikube-hostpath
"@ | kubectl apply -f -
方案 B:使用 minikube 自带的 standard StorageClass
修改 PVC YAML,将 storageClassName: default 改为 storageClassName: standard
方案 C:手动创建 PV(绕过动态供给)
yaml
apiVersion: v1
kind: PersistentVolume
metadata:
name: camp-database-pv
spec:
capacity:
storage: 1Gi
accessModes:
- ReadWriteOnce
storageClassName: default
hostPath:
path: /tmp/camp-database
问题 4:subPath 挂载目录到文件
现象:
powershell
kubectl describe pod camp-backend-xxx -n camp
# Error: failed to start container "camp-backend"
# not a directory: Are you trying to mount a directory onto a file (or vice-versa)?
原因: YAML 中配置了 subPath: camp.db,但 PVC 挂载的是一个目录,不是文件。
原始配置(错误):
yaml
volumeMounts:
- name: database-storage
mountPath: /app/camp.db # ← 期望挂载为文件
subPath: camp.db # ← 但 PVC 是目录
解决方案:
去掉 subPath,改为挂载目录:
yaml
volumeMounts:
- name: database-storage
mountPath: /app/data # ← 改为挂载目录
注意: 这样修改后,应用的数据库路径也需要相应调整(如从 /app/camp.db 改为 /app/data/camp.db)。
问题 5:CrashLoopBackOff(容器启动后崩溃)
现象:
powershell
kubectl get pods -n camp
# NAME READY STATUS RESTARTS AGE
# camp-backend-xxx 0/1 CrashLoopBackOff 5 10m
排查步骤:
powershell
# 1. 查看日志
kubectl logs camp-backend-xxx -n camp
# 2. 查看详细事件
kubectl describe pod camp-backend-xxx -n camp
常见原因:
表格
| 原因 | 日志特征 | 解决 |
|---|---|---|
| 应用启动失败 | 应用错误日志 | 修复应用代码或配置 |
| 健康检查失败 | Liveness probe failed |
修改探针路径或延迟时间 |
| 资源不足 | OOMKilled |
增加内存限制 |
| 权限问题 | Permission denied |
修改文件权限或 SecurityContext |
问题 6:Kustomize 补丁找不到目标
现象:
powershell
kubectl apply -k .
# error: no matches for Id Deployment.v1.apps/camp-backend.[noNs]
# failed to find unique target for patch
原因: patchesStrategicMerge 中的 patch 没有指定 namespace,但资源在 camp 命名空间中。
解决: 给 patch 添加 namespace: camp
yaml
patchesStrategicMerge:
- |-
apiVersion: apps/v1
kind: Deployment
metadata:
name: camp-backend
namespace: camp # ← 添加这一行
三、K8s 核心概念详解
3.1 Pod vs Container
表格
| Pod | Container | |
|---|---|---|
| 定义 | K8s 最小调度单位 | Docker 运行实例 |
| 包含 | 1 个或多个 Container | 单个应用进程 |
| 关系 | Pod 是 Container 的"外壳" | Container 运行在 Pod 内 |
| 生命周期 | 由控制器管理(Deployment 等) | 随 Pod 创建和销毁 |
类比: Pod 是一间公寓,Container 是公寓里的住户。
3.2 Deployment vs ReplicaSet vs Pod
plain
Deployment(管理)
↓ 创建/管理
ReplicaSet(副本控制)
↓ 创建/管理
Pod(实际运行)
表格
| 资源 | 职责 |
|---|---|
| Deployment | 声明式管理应用,支持滚动更新、回滚 |
| ReplicaSet | 确保指定数量的 Pod 副本在运行 |
| Pod | 实际承载容器的运行实例 |
为什么需要三层?
-
Deployment 负责版本管理(更新策略)
-
ReplicaSet 负责数量控制(故障自愈)
-
Pod 负责实际运行
3.3 Service 类型对比
表格
| 类型 | 访问方式 | 适用场景 |
|---|---|---|
| ClusterIP | 集群内部访问(默认) | 微服务之间通信 |
| NodePort | 节点 IP + 端口 | 外部临时访问 |
| LoadBalancer | 云厂商负载均衡器 | 生产环境外部访问 |
| ExternalName | DNS 别名 | 映射外部服务 |
本项目使用 ClusterIP + Ingress 的原因:
-
ClusterIP 只暴露集群内部
-
Ingress 作为统一入口,路由到不同 Service
-
节省云厂商负载均衡器费用
3.4 ConfigMap vs Secret
表格
| ConfigMap | Secret | |
|---|---|---|
| 存储内容 | 非敏感配置(URL、日志级别) | 敏感数据(密码、Token) |
| 编码方式 | 明文 | Base64(不是加密!) |
| 挂载方式 | 环境变量或文件 | 环境变量或文件 |
| 安全性 | 低 | 中(Base64 易解码) |
重要: Secret 的 Base64 只是编码,不是加密。生产环境应使用:
-
Sealed Secret
-
HashiCorp Vault
-
云厂商 Secret Manager
3.5 PersistentVolume vs PersistentVolumeClaim vs StorageClass
plain
StorageClass(存储模板)
↓ 动态创建
PersistentVolume(实际存储卷)
↓ 绑定
PersistentVolumeClaim(存储申请)
↓ 挂载
Pod(使用存储)
表格
| 资源 | 类比 | 职责 |
|---|---|---|
| StorageClass | 存储"套餐" | 定义存储类型(SSD/HDD/本地) |
| PersistentVolume | 实际硬盘 | 集群中的存储资源 |
| PersistentVolumeClaim | 购买申请 | 用户申请使用存储 |
emptyDir vs PVC:
表格
| emptyDir | PVC | |
|---|---|---|
| 生命周期 | 随 Pod 销毁 | 独立于 Pod |
| 数据持久化 | ❌ Pod 重启丢失 | ✅ 数据保留 |
| 适用场景 | 临时缓存 | 数据库、文件存储 |
3.6 HPA(Horizontal Pod Autoscaler)
工作原理:
plain
Metrics Server 采集 CPU/内存
↓
HPA Controller 计算需要的副本数
↓
Deployment 调整 ReplicaSet
↓
Pod 数量变化
关键参数:
表格
| 参数 | 说明 |
|---|---|
minReplicas |
最小副本数(防止缩容到 0) |
maxReplicas |
最大副本数(防止无限扩容) |
targetCPUUtilizationPercentage |
CPU 使用率阈值 |
scaleDownDelaySeconds |
缩容冷却时间(默认 5 分钟) |
注意: HPA 需要 Metrics Server 才能获取指标。如果显示 <unknown>,说明 Metrics Server 未安装或未就绪。
3.7 ResourceQuota vs LimitRange
表格
| ResourceQuota | LimitRange | |
|---|---|---|
| 作用范围 | 整个命名空间 | 单个 Pod/容器 |
| 限制对象 | 总资源使用量 | 单个容器的资源默认值 |
| 示例 | 命名空间最多 20 个 Pod | 单个容器默认内存限制 512Mi |
关系:
-
ResourceQuota = 小区总用水量限制
-
LimitRange = 每户的用水配额
四、常用命令速查
4.1 资源管理
bash
# 查看资源
kubectl get pods -n camp # 查看 Pod
kubectl get deployment -n camp # 查看 Deployment
kubectl get svc -n camp # 查看 Service
kubectl get pvc -n camp # 查看 PVC
kubectl get hpa -n camp # 查看 HPA
kubectl get all -n camp # 查看所有资源
# 查看详情
kubectl describe pod <pod-name> -n camp # 查看 Pod 详情(排错)
kubectl logs <pod-name> -n camp # 查看日志
kubectl logs -f deployment/camp-backend -n camp # 持续查看日志
# 进入容器
kubectl exec -it <pod-name> -n camp -- sh # 进入容器调试
4.2 资源操作
bash
# 扩缩容
kubectl scale deployment camp-backend --replicas=5 -n camp
# 删除资源
kubectl delete pod <pod-name> -n camp # 删除单个 Pod
kubectl delete deployment camp-backend -n camp # 删除 Deployment
kubectl delete namespace camp # 删除整个命名空间
# 端口转发
kubectl port-forward svc/camp-backend-service 8000:8000 -n camp
4.3 minikube 管理
bash
# 启动/停止/删除
minikube start --driver=docker --memory=4096 --cpus=2
minikube stop
minikube delete
# 镜像管理
minikube image load <image-name> # 加载本地镜像
minikube ssh -- docker images # 查看 minikube 中的镜像
# 插件
minikube addons enable ingress # 启用 Ingress
minikube addons enable metrics-server # 启用 Metrics Server
minikube addons list # 查看插件列表
五、部署最佳实践
5.1 部署顺序
plain
1. Namespace(命名空间)
2. ConfigMap / Secret(配置)
3. PersistentVolumeClaim(存储)
4. Deployment(应用)
5. Service(网络暴露)
6. Ingress(入口)
7. HPA / ResourceQuota(高级功能)
5.2 排错流程
plain
Pod 异常
↓
kubectl describe pod <name> ← 看 Events
↓
├─ ImagePullBackOff → 检查镜像名、权限、imagePullPolicy
├─ Pending → 检查资源、节点、PVC
├─ CrashLoopBackOff → 查看日志、检查探针
└─ ...
5.3 学习建议
表格
| 阶段 | 内容 |
|---|---|
| 第一阶段 | 理解 Pod、Deployment、Service 基本概念 |
| 第二阶段 | 掌握 ConfigMap、Secret、PVC 的使用 |
| 第三阶段 | 学习 Ingress、HPA、ResourceQuota |
| 第四阶段 | 尝试 Helm、Kustomize 等部署工具 |
| 第五阶段 | 部署到云厂商 K8s(AKS/EKS/ACK) |