k8s中的服务通过secret访问数据库的实际案例

文章目录

  • 概述
  • [一、完整实现步骤(含 Python Demo)](#一、完整实现步骤(含 Python Demo))
    • [Step 1️⃣:创建 Kubernetes Secret](#Step 1️⃣:创建 Kubernetes Secret)
    • [Step 2️⃣:编写 Python 应用(Flask 示例)](#Step 2️⃣:编写 Python 应用(Flask 示例))
    • [Step 3️⃣:构建 Docker 镜像(Dockerfile)](#Step 3️⃣:构建 Docker 镜像(Dockerfile))
    • [Step 4️⃣:部署到 Kubernetes(Deployment + Service)](#Step 4️⃣:部署到 Kubernetes(Deployment + Service))
    • [Step 5:测试](#Step 5:测试)
    • 二、如何"随时变更"数据库密码?

概述

在 Kubernetes 中,将数据库账号密码等敏感配置与代码解耦,并支持动态更新,是标准的安全和运维实践。我将通过(Python 应用 + 阿里云 RDS + 账号 jialh / 密码 Cfeur123)来设计一个完整可运行的 Python Demo。

✅ 推荐方案:使用 Kubernetes Secret + 环境变量注入

这是最简单、安全、且满足"随时变更配置"的方式:

  • 敏感信息存入 Secret
  • Pod 通过环境变量读取
  • 更新 Secret 后,滚动重启 Pod 即可生效(或配合 ConfigMap Reloader 实现热更新,但对 DB 密码通常不需要)

💡 注意:Kubernetes 的 Secret 不会自动热更新到已运行的 Pod 环境变量中(这是设计行为)。但你可以通过 滚动更新

Deployment 实现"配置变更生效",这在生产中是标准做法。

一、完整实现步骤(含 Python Demo)

Step 1️⃣:创建 Kubernetes Secret

yaml 复制代码
# rds-secret.yaml
apiVersion: v1
kind: Secret
metadata:
  name: rds-secret
type: Opaque
data:
  # 注意:必须是 base64 编码
  username: amlhbGg=        # echo -n "jialh" | base64
  password: Q2ZldXIxMjM=    # echo -n "Cfeur123" | base64
bash 复制代码
kubectl apply -f rds-secret.yaml

Step 2️⃣:编写 Python 应用(Flask 示例)

python 复制代码
# app.py
import os
import pymysql
from flask import Flask, jsonify

app = Flask(__name__)

def get_db_connection():
    host = os.getenv("DB_HOST", "localhost")
    port = int(os.getenv("DB_PORT", "3306"))
    user = os.getenv("DB_USER")
    password = os.getenv("DB_PASSWORD")
    database = os.getenv("DB_NAME", "test")

    if not user or not password:
        raise ValueError("DB_USER or DB_PASSWORD not set!")

    return pymysql.connect(
        host=host,
        port=port,
        user=user,
        password=password,
        database=database,
        charset='utf8mb4'
    )

@app.route('/health')
def health():
    try:
        conn = get_db_connection()
        conn.close()
        return jsonify({"status": "ok", "db": "connected"})
    except Exception as e:
        return jsonify({"status": "error", "message": str(e)}), 500

if __name__ == '__main__':
    app.run(host='0.0.0.0', port=8080)

Step 3️⃣:构建 Docker 镜像(Dockerfile)

bash 复制代码
# Dockerfile
FROM python:3.9-slim

WORKDIR /app
COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt

COPY app.py .

CMD ["python", "app.py"]
bash 复制代码
# requirements.txt
Flask==2.3.3
PyMySQL==1.1.0

构建并推送(假设镜像名为 my-registry/my-app:v1):

bash 复制代码
docker build -t my-registry/my-app:v1 .
docker push my-registry/my-app:v1

Step 4️⃣:部署到 Kubernetes(Deployment + Service)

yaml 复制代码
# app-deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: my-app
spec:
  replicas: 2
  selector:
    matchLabels:
      app: my-app
  template:
    metadata:
      labels:
        app: my-app
    spec:
      containers:
      - name: app
        image: my-registry/my-app:v1
        ports:
        - containerPort: 8080
        env:
        - name: DB_HOST
          value: "rm-xxxx.mysql.rds.aliyuncs.com"   # 替换为你的 RDS 内网地址
        - name: DB_PORT
          value: "3306"
        - name: DB_NAME
          value: "mydb"
        - name: DB_USER
          valueFrom:
            secretKeyRef:
              name: rds-secret
              key: username
        - name: DB_PASSWORD
          valueFrom:
            secretKeyRef:
              name: rds-secret
              key: password
---
apiVersion: v1
kind: Service
metadata:
  name: my-app-svc
spec:
  selector:
    app: my-app
  ports:
    - protocol: TCP
      port: 80
      targetPort: 8080
bash 复制代码
kubectl apply -f app-deployment.yaml

Step 5:测试

将 Service 端口映射到本地,直接调用 /health 接口:

bash 复制代码
kubectl port-forward svc/my-app-svc 8080:80

然后在另一个终端执行:

bash 复制代码
curl http://localhost:8080/health

✅ 成功响应示例:

bash 复制代码
{"status": "ok", "db": "connected"}

❌ 失败可能返回:

bash 复制代码
{"status": "error", "message": "(1045, \"Access denied for user 'jialh'@'192.168.x.x' (using password: YES)\")"}

二、如何"随时变更"数据库密码?

场景:RDS 密码从 Cfeur123 改为 NewPass456!
步骤:

  • 更新 Secret
bash 复制代码
kubectl create secret generic rds-secret \
  --from-literal=username=jialh \
  --from-literal=password=NewPass456! \
  --dry-run=client -o yaml | kubectl apply -f -
  • 触发 Pod 重启(使新环境变量生效)
bash 复制代码
# 方法1:滚动重启(推荐)
kubectl rollout restart deployment/my-app

# 方法2:修改 Deployment 注解(也会触发滚动更新)
kubectl patch deployment my-app -p "{\"spec\":{\"template\":{\"metadata\":{\"annotations\":{\"restartedAt\":\"$(date +%Y-%m-%dT%H:%M:%S%z)\"}}}}}"
相关推荐
honortech2 小时前
外部连接 redis-server 相关配置
数据库·redis·缓存
不会写程序的未来程序员2 小时前
Redis 的内存回收机制详解
数据库·redis·缓存
一过菜只因2 小时前
使用Junit测试
服务器·数据库·junit
啊巴矲2 小时前
小白从零开始勇闯人工智能Linux初级篇(MySQL库)
数据库·mysql
StarRocks_labs2 小时前
从小文件困局到“花小钱办大事”:StarRocks 存算分离批量导入优化实践
数据库·starrocks·compaction·memtable·本地磁盘 spill
帝吃藕和2 小时前
MySQL 知识点复习- 6.MySQL语法顺序
数据库·mysql
不会写程序的未来程序员2 小时前
Redis 主从同步原理详解
数据库·redis·缓存
李慕婉学姐2 小时前
Springboot猪肉销售网站的设计与实现mk77pcvj(程序+源码+数据库+调试部署+开发环境)带论文文档1万字以上,文末可获取,系统界面在最后面。
数据库·spring boot·后端
小满、2 小时前
Redis:缓存击穿、穿透、雪崩问题
数据库·redis·缓存穿透·缓存击穿·缓存雪崩