k8s部署简单测试环境
k8s 部署测试环境
前一阵子为开发的项目部署了一套简单的测试环境,在此记录一下部署流程及遇到的坑点。
项目主要组成部分有:Traefik (包含自研的中间件插件)、PostgreSQL、write 应用 (StatefulSet) 和 read 应用 (Deployment),均部署在腾讯云k8s集群上。
PostgreSQL
问题描述
在 Kubernetes 集群中,CloudNativePG 的 Pod cluster-example-3 无法删除,持续处于 Terminating 状态,且被控制器反复重建。
1. Pod 状态异常
1 | kubectl get pods -n default | grep cluster-example-3 |
Pod 一直处于 Init:0/1 状态,无法成功启动。
2. 网络错误日志
1 | Failed to create pod sandbox: rpc error: code = Unknown desc = failed to setup network for sandbox |
3. 控制器行为
执行 kubectl delete pod cluster-example-3 --force --grace-period=0 后,Pod 会被立即删除,但控制器随即又会重新创建。
根本原因分析
-
IP 地址冲突
旧容器207f...虽然已被删除,但其占用的 ENI IP 地址192.168.0.22仍然被 TKE ENI IP 管理器记录在缓存中。 -
PVC 元数据持久化
检查 PVC 发现包含以下注解:1
2
3
4annotations:
cnpg.io/nodeSerial: "3"
cnpg.io/operatorVersion: 1.27.1
cnpg.io/pvcStatus: readyPVC 中的
nodeSerial: "3"导致 CloudNativePG 控制器持续尝试创建cluster-example-3Pod。 -
控制器重建逻辑
CloudNativePG 的 Cluster 控制器检测到:- 配置文件中
instances: 2 - 但由于 PVC
cluster-example-3存在 - 控制器判断需要维持这个实例
- 配置文件中
解决方案 (删除 Pod 和 PVC)
1. 强制删除 Pod
1 | kubectl delete pod cluster-example-3 -n default --force --grace-period=0 |
2. 删除相关 PVC
1 | kubectl delete pvc cluster-example-3 cluster-example-3-wal -n default |
注意: 删除 PVC 会导致数据丢失,请确保已备份重要数据!
3. 等待控制器重建
CloudNativePG 控制器会根据配置文件中的 instances: 2 自动创建新的 Pod。
1 | # 监控 pod 状态 |
总结
本次问题的根本原因是:
- 网络层: TKE ENI IP 管理器缓存了已删除容器的 IP 分配记录。
- 存储层: PVC 中的元数据 (
nodeSerial: "3") 导致控制器持续重建 Pod。 - 控制层: CloudNativePG 控制器根据 PVC 存在性判断需要维护的实例。
最佳实践:
- 缩容时应同时删除 Pod 和对应的 PVC。
- 使用 Operator 提供的缩容功能而不是手动删除 (当时直接在 k9s 上删了导致的问题😂)。
Traefik
Traefik 本身的部署并不复杂,但加上安装中间件插件和配置 TLS,复杂度就随之上升了。
配置 TLS
使用 cert-manager 配合 Let’s Encrypt 免费证书来实现 TLS 证书的自动管理与颁发。
1. 安装 cert-manager
1 | helm install \ |
验证安装:
1 | # 查看 cert-manager pods 状态 |
2. 配置 ClusterIssuer
ClusterIssuer 是 cert-manager 中用于签发证书的资源,它指定了证书颁发机构。
创建文件 lets-encrypt.yaml:
1 | apiVersion: cert-manager.io/v1 |
应用配置:
1 | kubectl apply -f lets-encrypt.yaml |
3. 配置 Certificate
Certificate 资源定义了需要申请的证书信息。
创建文件 certificate.yaml:
1 | apiVersion: cert-manager.io/v1 |
应用配置:
1 | kubectl apply -f certificate.yaml |
4. 配置 DNS 解析
必须先配置 DNS,Let’s Encrypt 才能完成域名验证,否则流程会卡住。
5. 配置 IngressRoute
修改 IngressRoute 配置以启用 HTTPS。
关键修改点:
1 | spec: |
应用配置:
1 | kubectl apply -f ingress.yaml |
安装中间件插件
这个插件的主要作用是请求校验与转发,即校验特定请求并将其转发到后端的 write Pod (StatefulSet 部署)。
安装时最重要的是目录结构,必须严格遵循以下方式:
1 | ./plugins-local/ |
踩坑记录:
我打包了一个辅助镜像作为 initContainers 来帮助下载和解压插件。一开始为了图方便,用 7zip 打包成了 .tar.gz 格式,结果解压后多了一层 src 目录,导致插件安装失败。后来老老实实换回命令行打包,问题解决
最后
其实整个部署过程中还遇到了不少问题,但其余多是些琐碎细节,例如如何备份、路由匹配规则怎么写、如何平滑迁移 Pod、应该使用什么类型的存储等等。虽然我对部署还不是特别精通,但至少靠自己跑通了完整流程,收获颇丰🥰。