使用 SealedSecret 对 secret 进行加密并配合 reloader 并对相应的 pod 进行 重启 ¶
本项目展示了如何在 GitOps 工作流程中使用 SealedSecret 安全管理 Kubernetes 集群中的敏感信息。通过非对称加密技术,实现敏感数据在 Git 仓库中密文存储,仅在集群内部解密,确保数据安全。并配合 reloader 自动化监控对相应的 pod 进行 重启。
1. SealedSecret 介绍和场景 ¶
官方文档 ¶
https://github.com/bitnami-labs/sealed-secrets/blob/main/README.md
安装 ¶
1. 部署 SealedSecret 控制器 ¶
kubectl apply -f https://github.com/bitnami-labs/sealed-secrets/releases/download/v0.29.0/controller.yaml
2. 安装 kubeseal 客户端 ¶
用于本地加密 Secret:
Linux x86_64:
curl -OL "https://github.com/bitnami-labs/sealed-secrets/releases/download/v0.29.0/kubeseal-0.29.0-linux-amd64.tar.gz"
tar -xvzf kubeseal-0.29.0-linux-amd64.tar.gz kubeseal
sudo install -m 755 kubeseal /usr/local/bin/kubeseal
3. 初始化 git 仓库 ¶
1. 创建 git 仓库 ¶
mkdir -p my-gitops-repo/{k8s-manifests/{deployments,services,sealed-secrets},secrets,certs,.github/workflows}
my-gitops-repo/
├── k8s-manifests/ # Kubernetes 资源定义
│ ├── deployments/ # Deployment 配置
│ │ └── app-deployment.yaml
│ ├── services/ # Service 配置
│ │ └── app-service.yaml
│ └── sealed-secrets/ # 加密后的 SealedSecret(提交到 Git)
│ └── db-credentials.yaml
├── secrets/ # 明文 Secret(本地开发,不提交)
│ └── db-credentials.yaml
├── certs/ # 集群公钥证书(预导出,提交到 Git)
│ ├── prod-sealed.pub # 生产环境证书
│ └── dev-sealed.pub # 开发环境证书
└── .github/workflows/ # GitHub Actions 配置
└── encrypt-secrets.yml
2. 预导出集群公钥证书 ¶
导出公钥证书(可在集群内或有访问权限的机器上执行)提交到 git
# 从生产环境集群导出证书
kubectl get secret -n kube-system -l sealedsecrets.bitnami.com/sealed-secrets-key -o jsonpath='{.items[0].data.tls\.crt}' | base64 -d > certs/prod-sealed.pub
提交证书到 Git
git add certs/
git commit -m "Add cluster certificates"
git push
2. 加密敏感信息流程 ¶
graph LR
A[明文 Secret] --> B[使用公钥加密]
B --> C[生成 SealedSecret]
C --> D[提交到 Git]
D --> E[部署到集群]
E --> F[控制器使用私钥解密]
F --> G[生成实际 Secret]
1. 创建明文 Secret(本地操作,不提交) ¶
创建数据库凭证 Secret(本地操作,不提交到 Git)
1. 编码敏感数据(Base64) ¶
在终端中执行以下命令,将明文密码和用户名转换为 Base64 编码:
# 编码 "test" 为 Base64
echo -n "test" | base64 # 输出: dGVzdA==
2. 创建 YAML 文件 ¶
使用 cat
命令写入配置(注意替换编码后的值):
cat > secrets/db-credentials.yaml << 'EOF'
apiVersion: v1
kind: Secret
metadata:
name: db-credentials
namespace: default # 可选,指定命名空间
type: Opaque
data:
password: dGVzdA== # 明文 "test" 的 Base64 编码
username: dGVzdA== # 明文 "test" 的 Base64 编码
EOF
3. 加密为 SealedSecret ¶
# 获取集群公钥并加密 < 输入文件 > 输出文件,即加密后的 SealedSecret YAML
kubeseal --cert=certs/prod-sealed.pub --format=yaml < secrets/db-credentials.yaml > k8s-manifests/sealed-secrets/db-credentials.yaml
加密后的 db-credentials.yaml
内容如下(提交到 Git):
apiVersion: bitnami.com/v1alpha1
kind: SealedSecret
metadata:
name: db-credentials
namespace: default
spec:
encryptedData:
password: AgBmfy5dwYD8ZJe5... # 长密文
username: AgBz... # 长密文
template:
metadata:
name: db-credentials
namespace: default
4. Deployment 配置 ¶
apiVersion: apps/v1
kind: Deployment
metadata:
name: my-app
annotations:
secret.reloader.stakater.com/reload: "db-credentials" # 配置 Secret 变更时自动重启
spec:
replicas: 3
selector:
matchLabels:
app: my-app
template:
metadata:
labels:
app: my-app
spec:
containers:
- name: my-app
image: docker.io/library/nginx:1.15-alpine
ports:
- containerPort: 80
env:
- name: DB_USER
valueFrom:
secretKeyRef:
name: db-credentials
key: username
- name: DB_PASSWORD
valueFrom:
secretKeyRef:
name: db-credentials
key: password
---
apiVersion: v1
kind: Service
metadata:
name: my-app-service
spec:
selector:
app: my-app
ports:
- protocol: TCP
port: 80
targetPort: 80
type: ClusterIP
---
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: k8slinuxcdn1
spec:
ingressClassName: nginx
tls:
- hosts:
- test.k8s.linuxcdn.com
secretName: k8s-linuxcdn-crt-secret
rules:
- host: test.k8s.linuxcdn.com
http:
paths:
- path: /
pathType: ImplementationSpecific
backend:
service:
name: my-app-service
port:
number: 80
应用1:SealedSecret + Gitea + Argo CD + Reloader 完整实践方案 ¶
graph TD
subgraph "开发者工作站"
A[明文 Secret] --> B{操作类型}
B -->|新建/修改| C[使用公钥加密]
C --> D[生成 SealedSecret]
D --> E[提交到 Git]
B -->|直接编辑| F[修改 SealedSecret YAML]
F --> E
end
subgraph "GitOps 流程"
E --> G[Git 版本控制]
G --> H[Argo CD/Flux 监控变更]
H --> I[同步到集群]
end
subgraph "Kubernetes 集群"
I --> J[部署 SealedSecret]
J --> K[sealed-secrets 控制器]
K --> L{是否需要解密?}
L -->|是| M[使用私钥解密]
L -->|否| N[保持 SealedSecret 状态]
M --> O[创建/更新实际 Secret]
O --> P[Reloader 检测 Secret 变更]
P --> Q[触发 Deployment 滚动更新]
Q --> R[新 Pod 加载最新配置]
end
subgraph "安全防护"
S[公钥证书存储在 Git]:::safe
T[私钥仅存在于集群]:::safe
U[明文 Secret 不提交]:::safe
V[所有变更可审计]:::safe
end
classDef safe fill:#E5F6FF,stroke:#73A6FF,stroke-width:2px
以下是一个完整的 GitOps 工作流示例,展示如何使用 Gitea(代码托管)、Argo CD(部署工具)、SealedSecret(敏感信息管理)和 Reloader(自动重启应用)构建安全、自动化的 Kubernetes 部署流程。
1. 环境准备 ¶
1. 部署 Gitea ¶
2. 部署 Argo CD ¶
3. 部署 SealedSecret 控制器 ¶
4. 部署 Reloader ¶
Gitea 仓库结构 ¶
创建一个名为 my-gitops-repo
的仓库,结构如下:
1. Argo CD 配置 ¶
1. 添加 Gitea 仓库 ¶
argocd repo add http://gitea.gitea.svc.cluster.local:3000/admin/my-gitops-repo.git \
--username admin \
--password admin123
2. 创建 Argo CD 应用 ¶
# argocd-app.yaml
apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
name: my-app
namespace: argocd
spec:
destination:
namespace: default
server: https://kubernetes.default.svc
project: default
source:
path: k8s-manifests/base
repoURL: http://gitea.gitea.svc.cluster.local:3000/admin/my-gitops-repo.git
targetRevision: HEAD
syncPolicy:
automated:
prune: true
selfHeal: true
syncOptions:
- CreateNamespace=true
3. 应用配置到 Argo CD ¶
kubectl apply -f argocd-app.yaml -n argocd
2. 完整工作流程 ¶
-
开发者工作流程
-
在本地修改明文 Secret (
secrets/
) - 使用
kubeseal
加密为 SealedSecret -
提交 SealedSecret 到 Gitea 仓库
-
自动化流程
-
Argo CD 检测到仓库变更
- 自动同步 SealedSecret 到集群
- SealedSecret 控制器解密并创建实际 Secret
-
Reloader 检测到 Secret 变更,触发 Deployment 滚动更新
-
安全检查
-
查看 Gitea 仓库:只包含加密后的 SealedSecret
-
尝试从集群获取 Secret:
kubectl get secret db-credentials -o jsonpath='{.data.password}' | base64 -d # 输出应为正确的密码(supersecret)
3. 验证流程 ¶
1. 修改数据库密码 ¶
# 更新明文 Secret
echo -n "newpassword" | base64 # 生成新密码的 Base64 值
# 更新 secrets/db-credentials.yaml
data:
password: bmV3cGFzc3dvcmQ= # 新密码的 Base64 值
# 重新加密
kubeseal --cert=sealed-secrets.pem --format=yaml < secrets/db-credentials.yaml > k8s-manifests/base/sealed-secrets/db-credentials.yaml
# 提交到 Gitea
git add k8s-manifests/base/sealed-secrets/db-credentials.yaml
git commit -m "Update DB password"
git push
2. 观察自动化流程 ¶
- 在 Argo CD UI 中查看同步状态
- 观察 Deployment 的滚动更新
- 验证应用是否使用新密码连接数据库
通过这种方式,你可以实现一个完全自动化、安全的 GitOps 工作流,确保敏感信息在整个生命周期中都得到加密保护。