
专栏系列Docker程序员零基础吃透K8s生产实战前面五篇我们已经完整打通了 K8s 集群环境、YAML 规范、Docker 镜像优化、Java / Python / Go 三大主流业务服务生产部署以及 HPA 自动扩缩容。到这里无状态业务服务已经可以直接上线生产。但企业项目绝对离不开中间件数据库、缓存、网关。很多同学学 K8s 卡在最后一步明明服务部署成功了重启 Pod 数据全丢、密码明文泄露、配置重启还原、节点漂移业务炸掉。原因非常简单业务服务是无状态中间件是有状态无状态服务随便重建、随便漂移没问题有状态服务MySQL/Redis一旦没有持久化重建即清零。本篇一次性彻底解决✅ PV/PVC 持久化存储彻底吃透✅ Secret 加密密码杜绝明文漏洞✅ MySQL 生产级部署重启不丢数据✅ Redis 带密码持久化部署✅ Nginx 配置文件持久化支持热更新✅ 全套生产避坑、资源限制、健康探针、稳定运行方案读完本篇你的 K8s 集群真正具备完整上线能力不再是玩具集群一、前置核心认知为什么中间件部署和业务服务不一样1. 容器默认 100% 丢数据Docker / K8s 容器默认所有数据都存在容器临时读写层。只要 Pod 重启、删除、重建、调度漂移所有数据、配置、缓存全部清空。这就是新手 MySQL 重启归零、Redis 重启清空的本质。2. K8s 标准解决方案PV PVC为了适配集群调度K8s 不允许直接裸挂载宿主机目录会导致集群错乱。官方标准PV 集群硬盘池 PVC 业务领用PVPersistentVolume集群级磁盘提前建好永久存在PVCPersistentVolumeClaim服务申请使用磁盘挂载逻辑Pod 不直接挂目录只挂 PVC彻底解耦3. Secret 加密作用YAML 写明文密码属于生产严重漏洞。K8s 使用 Secret 存储密码、密钥加密存储、不落地明文、可统一管理。二、环境准备沿用之前集群继续使用业务命名空间统一环境隔离kubectl create ns business三、第一步创建全局 PV 持久化磁盘集群存储底座我们先创建三个 PV分别给 MySQL、Redis、Nginx 使用。新建pv.yamlapiVersion: v1 kind: PersistentVolume metadata: name: pv-mysql spec: capacity: storage: 10Gi accessModes: - ReadWriteOnce hostPath: path: /data/k8s/mysql --- apiVersion: v1 kind: PersistentVolume metadata: name: pv-redis spec: capacity: storage: 5Gi accessModes: - ReadWriteOnce hostPath: path: /data/k8s/redis --- apiVersion: v1 kind: PersistentVolume metadata: name: pv-nginx spec: capacity: storage: 5Gi accessModes: - ReadWriteOnce hostPath: path: /data/k8s/nginx执行创建kubectl apply -f pv.yaml kubectl get pv此时集群拥有三块永久磁盘无论 Pod 怎么销毁数据都在宿主机/data/k8s/xxx。四、第二步创建 Secret 加密密码无明文我们统一设置数据库、Redis 密码通过 Secret 加密管理。新建secret.yamlapiVersion: v1 kind: Secret metadata: name: middleware-secret namespace: business type: Opaque data: # 密码123456base64加密 mysql-root-pwd: MTIzNDU2 redis-pwd: MTIzNDU2执行生效kubectl apply -f secret.yaml生产优势全程无明文密码配置文件看不到密码安全合规。五、MySQL 生产级部署持久化加密探针资源限制解决重启丢数据、明文密码、服务假死、资源打满等问题。新建mysql.yamlapiVersion: v1 kind: PersistentVolumeClaim metadata: name: mysql-pvc namespace: business spec: accessModes: - ReadWriteOnce resources: requests: storage: 10Gi --- apiVersion: apps/v1 kind: Deployment metadata: name: mysql namespace: business spec: replicas: 1 selector: matchLabels: app: mysql template: metadata: labels: app: mysql spec: containers: - name: mysql image: mysql:8.0 ports: - containerPort: 3306 env: - name: MYSQL_ROOT_PASSWORD valueFrom: secretKeyRef: name: middleware-secret key: mysql-root-pwd # 资源限制防雪崩 resources: requests: cpu: 200m memory: 256Mi limits: cpu: 1000m memory: 1Gi # 健康探针防止假死 livenessProbe: tcpSocket: port: 3306 initialDelaySeconds: 15 periodSeconds: 10 readinessProbe: tcpSocket: port: 3306 initialDelaySeconds: 10 periodSeconds: 5 # 数据持久化挂载 volumeMounts: - name: mysql-data mountPath: /var/lib/mysql volumes: - name: mysql-data persistentVolumeClaim: claimName: mysql-pvc --- apiVersion: v1 kind: Service metadata: name: mysql-svc namespace: business spec: selector: app: mysql ports: - port: 3306 targetPort: 3306 type: ClusterIP部署命令kubectl apply -f mysql.yaml kubectl get pods -n business生产特性数据永久落地删 Pod 不丢数据密码加密存储无明文泄露TCP 探针检测数据库存活杜绝假死资源限制防止 MySQL 打满集群六、Redis 生产级部署持久化密码加密新建redis.yamlapiVersion: v1 kind: PersistentVolumeClaim metadata: name: redis-pvc namespace: business spec: accessModes: - ReadWriteOnce resources: requests: storage: 5Gi --- apiVersion: apps/v1 kind: Deployment metadata: name: redis namespace: business spec: replicas: 1 selector: matchLabels: app: redis template: metadata: labels: app: redis spec: containers: - name: redis image: redis:6-alpine ports: - containerPort: 6379 command: [redis-server] args: - --requirepass - $(REDIS_PWD) env: - name: REDIS_PWD valueFrom: secretKeyRef: name: middleware-secret key: redis-pwd resources: requests: cpu: 100m memory: 128Mi limits: cpu: 500m memory: 256Mi livenessProbe: tcpSocket: port: 6379 initialDelaySeconds: 10 periodSeconds: 10 readinessProbe: tcpSocket: port: 6379 initialDelaySeconds: 5 periodSeconds: 5 volumeMounts: - name: redis-data mountPath: /data volumes: - name: redis-data persistentVolumeClaim: claimName: redis-pvc --- apiVersion: v1 kind: Service metadata: name: redis-svc namespace: business spec: selector: app: redis ports: - port: 6379 targetPort: 6379 type: ClusterIP部署kubectl apply -f redis.yaml七、Nginx 持久化部署配置不丢失Nginx 最大问题修改配置重启 Pod 全部还原。我们通过 PVC 挂载配置目录实现配置永久留存。新建nginx.yamlapiVersion: v1 kind: PersistentVolumeClaim metadata: name: nginx-pvc namespace: business spec: accessModes: - ReadWriteOnce resources: requests: storage: 5Gi --- apiVersion: apps/v1 kind: Deployment metadata: name: nginx namespace: business spec: replicas: 1 selector: matchLabels: app: nginx template: metadata: labels: app: nginx spec: containers: - name: nginx image: nginx:alpine ports: - containerPort: 80 resources: requests: cpu: 50m memory: 64Mi limits: cpu: 300m memory: 128Mi readinessProbe: httpGet: path: / port: 80 initialDelaySeconds: 3 periodSeconds: 3 livenessProbe: httpGet: path: / port: 80 initialDelaySeconds: 5 periodSeconds: 5 volumeMounts: - name: nginx-data mountPath: /etc/nginx volumes: - name: nginx-data persistentVolumeClaim: claimName: nginx-pvc --- apiVersion: v1 kind: Service metadata: name: nginx-svc namespace: business spec: selector: app: nginx ports: - port: 80 targetPort: 80 type: ClusterIP部署kubectl apply -f nginx.yaml八、全套验证命令确保生产正常# 查看存储 kubectl get pv kubectl get pvc -n business # 查看所有中间件 kubectl get all -n business # 查看日志排错 kubectl logs -f deployment/mysql -n business kubectl logs -f deployment/redis -n business九、生产高频避坑总结禁止裸挂载宿主机目录集群调度会导致数据错乱禁止 YAML 明文密码必须使用 Secret有状态服务必须 PV/PVC否则重启必丢数据中间件必须配置资源限制防止集群雪崩必须配置探针避免数据库假死、流量异常十、本篇总结本篇完整落地了K8s 生产级中间件基础设施✅ 吃透 PV/PVC 持久化存储核心原理✅ 掌握 Secret 加密敏感数据方案✅ MySQL 8.0 零数据丢失生产部署✅ Redis 带密码持久化高可用部署✅ Nginx 配置永久留存、不还原至此你的 K8s 集群业务服务 基础中间件 全部生产闭环完全具备企业上线能力下期预告第七篇K8s 完整项目上线实战微服务整套串联、流水线发布、域名统一管理、生产最终上线架构欢迎订阅专栏零基础全套吃透 K8s 生产实战