docs: 归档基于旧版 k8s 的 jwt 加密部署文档
This commit is contained in:
@@ -0,0 +1,424 @@
|
||||
# JWT Secret + ETCD Encryption Deployment Guide
|
||||
|
||||
完整的 JWT 认证系统部署指南,包括密钥管理、RBAC 权限控制和 ETCD 加密。
|
||||
|
||||
## 部署顺序
|
||||
|
||||
### 第1步:创建 Secret 和 RBAC(必需)
|
||||
|
||||
创建 JWT 秘钥和服务账户权限:
|
||||
|
||||
```bash
|
||||
kubectl apply -f deploy/k8s/secrets/jwt-secret.yaml
|
||||
```
|
||||
|
||||
验证创建成功:
|
||||
|
||||
```bash
|
||||
# 检查 Secret
|
||||
kubectl get secret jwt-secret -n juwan
|
||||
kubectl get secret jwt-secret -n juwan -o yaml
|
||||
|
||||
# 检查 ServiceAccounts
|
||||
kubectl get sa user-rpc -n juwan
|
||||
kubectl get sa envoy-gateway -n juwan
|
||||
|
||||
# 检查 RBAC 权限
|
||||
kubectl get role jwt-secret-reader -n juwan
|
||||
kubectl get rolebinding -n juwan -l app=jwt-secret-reader
|
||||
```
|
||||
|
||||
### 第2步:更新 user-rpc 部署(依赖第1步)
|
||||
|
||||
已自动更新 `deploy/k8s/service/user/user-rpc.yaml`:
|
||||
|
||||
- ✅ 更新 `serviceAccountName` 从 `find-endpoints` → `user-rpc`
|
||||
- ✅ 添加环境变量 `JWT_SECRET_KEY` 从 Secret `jwt-secret` 读取
|
||||
|
||||
应用更新:
|
||||
|
||||
```bash
|
||||
kubectl apply -f deploy/k8s/service/user/user-rpc.yaml
|
||||
```
|
||||
|
||||
验证部署:
|
||||
|
||||
```bash
|
||||
# 检查 ServiceAccount 已正确绑定
|
||||
kubectl get deployment user-rpc -n juwan -o yaml | grep -A 5 serviceAccountName
|
||||
|
||||
# 查看 Pod 是否以 user-rpc ServiceAccount 身份运行
|
||||
kubectl get pod -n juwan -l app=user-rpc -o yaml | grep serviceAccount
|
||||
|
||||
# 验证环境变量已注入
|
||||
kubectl exec -it POD_NAME -n juwan -- env | grep JWT_SECRET_KEY
|
||||
```
|
||||
|
||||
### 第3步:更新 Envoy 网关部署(依赖第1步)
|
||||
|
||||
已自动更新 `deploy/k8s/envoy/envoy.yaml`:
|
||||
|
||||
- ✅ 添加 `serviceAccountName: envoy-gateway` 到 Deployment spec
|
||||
|
||||
应用更新:
|
||||
|
||||
```bash
|
||||
kubectl apply -f deploy/k8s/envoy/envoy.yaml
|
||||
```
|
||||
|
||||
验证部署:
|
||||
|
||||
```bash
|
||||
# 检查 ServiceAccount 已正确绑定
|
||||
kubectl get deployment envoy-gateway -n juwan -o yaml | grep -A 2 serviceAccountName
|
||||
|
||||
# 检查 Pod 状态
|
||||
kubectl get pod -n juwan -l app=envoy-gateway
|
||||
```
|
||||
|
||||
### 第4步:启用 ETCD 加密(强烈推荐用于生产环境)
|
||||
|
||||
这是一个集群级别的配置,需要在 Kubernetes 控制平面节点上执行。
|
||||
|
||||
**前提条件:**
|
||||
- 具有 Kubernetes 集群管理员权限
|
||||
- 可以访问控制平面节点
|
||||
- 备份 ETCD 数据库
|
||||
|
||||
**步骤:**
|
||||
|
||||
1. **生成加密密钥**
|
||||
```bash
|
||||
head -c 32 /dev/urandom | base64
|
||||
```
|
||||
记录输出的 Base64 密钥。
|
||||
|
||||
2. **创建加密配置文件**
|
||||
|
||||
在控制平面节点上,创建 `/etc/kubernetes/encryption-config.yaml`:
|
||||
|
||||
```yaml
|
||||
apiVersion: apiserver.config.k8s.io/v1
|
||||
kind: EncryptionConfiguration
|
||||
resources:
|
||||
- resources:
|
||||
- secrets
|
||||
providers:
|
||||
- aescbc:
|
||||
keys:
|
||||
- name: key1
|
||||
secret: <BASE64_ENCODED_32_BYTE_KEY>
|
||||
- identity: {}
|
||||
```
|
||||
|
||||
替换 `<BASE64_ENCODED_32_BYTE_KEY>` 为第1步生成的密钥。
|
||||
|
||||
3. **修改 kube-apiserver 配置**
|
||||
|
||||
在控制平面节点上,编辑 `/etc/kubernetes/manifests/kube-apiserver.yaml`:
|
||||
|
||||
**添加参数:**
|
||||
```yaml
|
||||
spec:
|
||||
containers:
|
||||
- name: kube-apiserver
|
||||
command:
|
||||
- kube-apiserver
|
||||
- --encryption-provider-config=/etc/kubernetes/encryption-config.yaml
|
||||
```
|
||||
|
||||
**添加卷挂载:**
|
||||
```yaml
|
||||
spec:
|
||||
containers:
|
||||
- name: kube-apiserver
|
||||
volumeMounts:
|
||||
- name: encryption-config
|
||||
mountPath: /etc/kubernetes
|
||||
readOnly: true
|
||||
|
||||
volumes:
|
||||
- name: encryption-config
|
||||
hostPath:
|
||||
path: /etc/kubernetes
|
||||
type: DirectoryOrCreate
|
||||
```
|
||||
|
||||
4. **重启 kube-apiserver**
|
||||
|
||||
修改清单后,kubelet 会自动重启 kube-apiserver。检查状态:
|
||||
|
||||
```bash
|
||||
# 在控制平面节点
|
||||
kubectl get pods -n kube-system | grep kube-apiserver
|
||||
|
||||
# 监控重启过程
|
||||
kubectl logs -n kube-system -l component=kube-apiserver -f
|
||||
```
|
||||
|
||||
5. **验证加密是否启用**
|
||||
|
||||
创建一个新 Secret 并检查它在 ETCD 中是否加密:
|
||||
|
||||
```bash
|
||||
# 创建测试 Secret
|
||||
kubectl create secret generic test-secret -n juwan --from-literal=key=value
|
||||
|
||||
# 从 control plane 节点检查 ETCD 数据
|
||||
# 如果数据不可读并包含加密标记,说明加密已启用
|
||||
```
|
||||
|
||||
6. **保存加密密钥**
|
||||
|
||||
⚠️ **关键:将加密密钥安全地保存在离线存储中**
|
||||
- 密钥丢失后,无法解密 ETCD 中的数据
|
||||
- 无法恢复任何 Secrets
|
||||
- 建议用密码管理工具(如 HashiCorp Vault)或 HSM 存储密钥
|
||||
|
||||
### 第5步:验证整个系统
|
||||
|
||||
完整的验证清单:
|
||||
|
||||
```bash
|
||||
# 检查所有 Secrets 已创建
|
||||
kubectl get secret -n juwan
|
||||
kubectl get secret jwt-secret -n juwan -o jsonpath='{.data.secret-key}' | base64 -d
|
||||
|
||||
# 检查 ServiceAccounts 已创建
|
||||
kubectl get sa -n juwan
|
||||
kubectl describe sa user-rpc -n juwan
|
||||
kubectl describe sa envoy-gateway -n juwan
|
||||
|
||||
# 检查 RBAC 权限
|
||||
kubectl get role -n juwan
|
||||
kubectl get rolebinding -n juwan
|
||||
kubectl describe role jwt-secret-reader -n juwan
|
||||
|
||||
# 测试权限:user-rpc 可以读 jwt-secret
|
||||
kubectl auth can-i get secrets --as=system:serviceaccount:juwan:user-rpc --resource-name=jwt-secret -n juwan
|
||||
|
||||
# 测试权限:envoy-gateway 可以读 jwt-secret
|
||||
kubectl auth can-i get secrets --as=system:serviceaccount:juwan:envoy-gateway --resource-name=jwt-secret -n juwan
|
||||
|
||||
# 测试权限:其他 ServiceAccount 无法读取
|
||||
kubectl auth can-i get secrets --as=system:serviceaccount:juwan:other-service -n juwan
|
||||
|
||||
# 检查 Deployments 已正确配置
|
||||
kubectl get deployment user-rpc -n juwan -o yaml | grep -A 2 serviceAccountName
|
||||
kubectl get deployment envoy-gateway -n juwan -o yaml | grep -A 2 serviceAccountName
|
||||
|
||||
# 检查 Pods 是否已启动并运行
|
||||
kubectl get pods -n juwan -l app=user-rpc
|
||||
kubectl get pods -n juwan -l app=envoy-gateway
|
||||
|
||||
# 查看 JWT Secret 是否已挂载到 Pod
|
||||
kubectl exec -it $(kubectl get pod -n juwan -l app=user-rpc -o name | head -1) -n juwan -- env | grep JWT_SECRET_KEY
|
||||
```
|
||||
|
||||
## 监控和日志
|
||||
|
||||
### 查看 Pod 日志
|
||||
|
||||
```bash
|
||||
# user-rpc 日志
|
||||
kubectl logs -n juwan -l app=user-rpc -f --all-containers=true
|
||||
|
||||
# Envoy 日志
|
||||
kubectl logs -n juwan -l app=envoy-gateway -f
|
||||
```
|
||||
|
||||
### 检查 Pod 事件
|
||||
|
||||
```bash
|
||||
# 查看 Pod 创建和启动事件
|
||||
kubectl describe pod -n juwan -l app=user-rpc
|
||||
kubectl describe pod -n juwan -l app=envoy-gateway
|
||||
```
|
||||
|
||||
### 权限问题排查
|
||||
|
||||
如果 Pod 无法读取 Secret:
|
||||
|
||||
```bash
|
||||
# 检查 Pod 使用的 ServiceAccount
|
||||
kubectl get pod POD_NAME -n juwan -o yaml | grep serviceAccountName
|
||||
|
||||
# 检查 RBAC 绑定
|
||||
kubectl get rolebinding -n juwan -o wide
|
||||
|
||||
# 检查 Role 权限定义
|
||||
kubectl get role jwt-secret-reader -n juwan -o yaml
|
||||
|
||||
# 尝试用 Pod 的身份读取 Secret(需要 kubectl-user-impersonate 或类似工具)
|
||||
kubectl get secret jwt-secret --as=system:serviceaccount:juwan:user-rpc -n juwan
|
||||
```
|
||||
|
||||
## 安全最佳实践
|
||||
|
||||
### 1. 密钥轮换
|
||||
|
||||
周期性更换 JWT 秘钥(建议每季度):
|
||||
|
||||
```bash
|
||||
# 1. 生成新密钥
|
||||
NEW_KEY=$(head -c 32 /dev/urandom | base64)
|
||||
|
||||
# 2. 更新 Secret
|
||||
kubectl create secret generic jwt-secret \
|
||||
--from-literal=secret-key=$NEW_KEY \
|
||||
--dry-run=client -o yaml | kubectl apply -f -
|
||||
|
||||
# 3. 重启 Pods 以加载新密钥(滚动更新)
|
||||
kubectl rollout restart deployment/user-rpc -n juwan
|
||||
kubectl rollout restart deployment/envoy-gateway -n juwan
|
||||
|
||||
# 4. 验证新 Pods 已启动并运行
|
||||
kubectl rollout status deployment/user-rpc -n juwan
|
||||
kubectl rollout status deployment/envoy-gateway -n juwan
|
||||
|
||||
# 5. 已颁发的旧令牌将变为无效
|
||||
# 需要用户重新登录获取新令牌
|
||||
```
|
||||
|
||||
### 2. 审计和监控
|
||||
|
||||
在生产环境中启用 Kubernetes 审计日志来跟踪 Secret 访问:
|
||||
|
||||
```yaml
|
||||
# kube-apiserver 审计策略示例
|
||||
apiVersion: audit.k8s.io/v1
|
||||
kind: Policy
|
||||
rules:
|
||||
# 记录 secret 资源的访问
|
||||
- level: RequestResponse
|
||||
verbs: ["get", "list", "watch"]
|
||||
resources: ["secrets"]
|
||||
# 记录所有认证失败
|
||||
- level: RequestResponse
|
||||
omitStages:
|
||||
- RequestReceived
|
||||
userGroups: ["system:unauthenticated"]
|
||||
- level: Metadata
|
||||
omitStages:
|
||||
- RequestReceived
|
||||
```
|
||||
|
||||
### 3. 网络策略
|
||||
|
||||
使用 NetworkPolicy 限制 Pods 之间的通信:
|
||||
|
||||
```yaml
|
||||
apiVersion: networking.k8s.io/v1
|
||||
kind: NetworkPolicy
|
||||
metadata:
|
||||
name: jwt-secret-access
|
||||
namespace: juwan
|
||||
spec:
|
||||
podSelector:
|
||||
matchLabels:
|
||||
app: jwt-secret-reader
|
||||
policyTypes:
|
||||
- Ingress
|
||||
ingress:
|
||||
- from:
|
||||
- podSelector:
|
||||
matchLabels:
|
||||
app: user-rpc
|
||||
- podSelector:
|
||||
matchLabels:
|
||||
app: envoy-gateway
|
||||
ports:
|
||||
- protocol: TCP
|
||||
port: 443 # API Server
|
||||
```
|
||||
|
||||
## 灾难恢复
|
||||
|
||||
### 备份 Secret 和 RBAC 配置
|
||||
|
||||
```bash
|
||||
# 备份 JWT Secret
|
||||
kubectl get secret jwt-secret -n juwan -o yaml > jwt-secret-backup.yaml
|
||||
|
||||
# 备份 RBAC 配置
|
||||
kubectl get role jwt-secret-reader -n juwan -o yaml > jwt-role-backup.yaml
|
||||
kubectl get rolebinding -n juwan -l app=jwt-secret-reader -o yaml > jwt-rolebinding-backup.yaml
|
||||
|
||||
# 加密备份文件
|
||||
gpg --symmetric jwt-secret-backup.yaml
|
||||
```
|
||||
|
||||
### 恢复步骤
|
||||
|
||||
如果 Secret 被意外删除:
|
||||
|
||||
```bash
|
||||
# 从备份恢复
|
||||
kubectl apply -f jwt-secret-backup.yaml
|
||||
|
||||
# 重启 Pods 以重新加载 Secret
|
||||
kubectl rollout restart deployment/user-rpc -n juwan
|
||||
kubectl rollout restart deployment/envoy-gateway -n juwan
|
||||
```
|
||||
|
||||
## 常见问题
|
||||
|
||||
### Q: Pod 无法启动,显示 "failed to pull secret"
|
||||
|
||||
A: 检查:
|
||||
1. Secret 是否存在:`kubectl get secret jwt-secret -n juwan`
|
||||
2. ServiceAccount 是否绑定了 RBAC:`kubectl describe rolebinding -n juwan`
|
||||
3. Secret 名称和命名空间是否正确
|
||||
|
||||
### Q: 加密后如何验证 ETCD 中的数据已加密?
|
||||
|
||||
A: 从 control plane 节点:
|
||||
```bash
|
||||
# 直接读取 ETCD(如果配置了加密,数据应该不可读)
|
||||
sudo strings /var/lib/etcd/member/snap/db | grep -i secret
|
||||
```
|
||||
|
||||
### Q: 能否更改加密密钥而不重新创建 ETCD?
|
||||
|
||||
A: 可以,但流程复杂:
|
||||
1. 更新 encryption-config.yaml 中的新密钥
|
||||
2. 将新密钥添加到提供程序列表(保持旧密钥)
|
||||
3. 重启 kube-apiserver
|
||||
4. 触发重新加密:`kubectl get all --all-namespaces -o json | kubectl apply -f -`
|
||||
|
||||
### Q: 如何在 Minikube 中启用 ETCD 加密?
|
||||
|
||||
A: 参考 `ENCRYPTION.md` 中的 Minikube 特定说明部分。
|
||||
|
||||
## 相关文件
|
||||
|
||||
- `jwt-secret.yaml` - Secret 和 RBAC 配置
|
||||
- `ENCRYPTION.md` - ETCD 加密详细文档
|
||||
- `README.md` - 快速参考指南
|
||||
- `/deploy/k8s/service/user/user-rpc.yaml` - user-rpc Deployment 配置
|
||||
- `/deploy/k8s/envoy/envoy.yaml` - Envoy 网关 Deployment 配置
|
||||
|
||||
## 下一步
|
||||
|
||||
部署完成后:
|
||||
|
||||
1. **集成 JWT 验证到 RPC Handlers**
|
||||
- 实现 gRPC unary interceptor
|
||||
- 验证令牌有效性
|
||||
- 处理令牌刷新逻辑
|
||||
|
||||
2. **集成 JWT 验证到 Envoy**
|
||||
- 扩展 Lua filter 进行令牌验证
|
||||
- 返回 401(无效令牌)或 200(有效令牌)
|
||||
|
||||
3. **端到端测试**
|
||||
- 创建用户和登录
|
||||
- 生成和验证 JWT
|
||||
- 测试令牌刷新和撤销
|
||||
- 验证 ETCD 加密
|
||||
|
||||
4. **生产部署**
|
||||
- 启用审计日志
|
||||
- 配置密钥轮换计划
|
||||
- 建立备份和恢复流程
|
||||
- 监控 Secret 访问
|
||||
Reference in New Issue
Block a user