前言
在使用Kubernetes的时候,我们常常会通过configmap、secret等原生资源来配置一些环境变量等,以便同代码一起用于git版本管理。如果是用于存储一般信息还行,但是某些时候我们可能需要用这些资源来配置一些账号密码等敏感信息,虽然secrets具备加密性质,但是因为其本身的加密方式是基于base64的,所以对于稍微有点相关知识的人来说,等同于明文。
在很多公司研发部门的管理中,生产环境的很多账户密码是不允许被除管理员之外的人员获知的(比如数据库密码),如果不对相关信息进行加密存储,直接在git中进行版本管理,对相关人员来说,无异于裸奔。所以此处介绍一款K8S的开源资源类型sealed-secrets
sealed-secrets是什么
Problem: “I can manage all my K8s config in git, except Secrets.”
Solution: Encrypt your Secret into a SealedSecret, which is safe to store - even inside a public repository. The SealedSecret can be decrypted only by the controller running in the target cluster and nobody else (not even the original author) is able to obtain the original Secret from the SealedSecret.
官方文档中的这一问一答,清晰明了的表达了sealed-secrets的作用,他就是为了让我们可以放心的把secret共享存储和使用,而避免加密信息被破解。
安装部署
Sealed Secrets由两部分组成:
- 服务器端的控制器
- 客户端工具:kubeseal
kubeseal使用非对称加密来加密数据,只有服务端的控制器才能解密数据,这些加密数据被编码在SealedSecret资源中。
安装kubeseal
1.登录Releases · bitnami-labs/sealed-secrets (github.com),找到最新版本,选择适合你系统的版本下载
2.将压缩包解压后将工具放到/usr/local/bin/目录下
tar -zxvf kubeseal-0.19.3-linux-amd64.tar.gz
install -m 755 kubeseal /usr/local/bin/kubeseal
##验证一下
[root@master sealed-secrets]# kubeseal --version
kubeseal version: 0.19.3
安装控制器
1.下载
登录github,下载相应资源文件Releases · bitnami-labs/sealed-secrets (github.com)
2.部署
kubectl apply -f controller.yaml
3.查看pod
[root@master sealed-secrets]# kubectl get pods -n kube-system -l name=sealed-secrets-controller
NAME READY STATUS RESTARTS AGE
sealed-secrets-controller-8645675c65-jtrc2 1/1 Running 0 10d
[root@master sealed-secrets]# kubectl logs sealed-secrets-controller-8645675c65-jtrc2 -n kube-system
controller version: 0.19.3
2022/12/23 09:15:22 Starting sealed-secrets controller version: 0.19.3
2022/12/23 09:15:22 Searching for existing private keys
2022/12/23 09:15:24 New key written to kube-system/sealed-secrets-keymrkx6
2022/12/23 09:15:24 Certificate is
-----BEGIN CERTIFICATE-----
MIIEzTCCArWgAwIBAgIRAONV9p03jyrJuRrGUwyJJ2AwDQYJKoZIhvcNAQELBQAw
ADAeFw0yMjEyMjMwOTE1MjRaFw0zMjEyMjAwOTE1MjRaMAAwggIiMA0GCSqGSIb3
DQEBAQUAA4ICDwAwggIKAoICAQDMkPndKm9g0XpgdNMuHvZ2qWsSGlET3pGyiSSs
APWDPT8FJEOcO1d4SrevrBCfWLxsd+CMyl4SE6Os1zqGXNMPAWJuag0JJBqcONgi
k3yWpma3h3g0fY21T7MUoAO16a+uMBJEPZAfzjfb3Oz8q26mWi8Ct96DKsvZkdZs
Xt1PL6nCKvj8DuAqH9+VzDiW/z66TeOCd8RsvJkMjGpyBZR+puIiDdDZ0dY/bS5l
0p3Ri72cTKnTBToLr3tM91einiJ0vhaMMVEdCED84rautJtbyBk/Km15g+D9ojW+
LcL5z8qKtDn13Hxo/2RRuUt4gsucuqrBWYUwKj8qoQZ/+iHAs6Ym+Y3A94qNFxNQ
udAbu/7HVIEOIU5G64HY5dqiQN5LJRqM7zlUjip65Rrr/Ysk/t0kNULKDX1060/k
EaVC8pPYa5hQLcWmyRBWstQTSNYGHO2ANevBIOT+O4wjrmEyC9dMuVRomdkqSkBi
NJsIYc3JATiGWcDax6H1G2V+QYmjg0PlH008e/n2wbJmAfHIxxBgMHGL0FPUFthX
rNhMHAirDrB7I1yW/OaoIm/YRJM+PMmJOk4IkJ66a6pVHDuRfY8lwDiH8vJaYk6y
oDS6T9qJ1bKTFDZtPg4rna+C36/px57BW/bTADHNckefuPFtAGbflEabeGr0TcoC
sU/ATQIDAQABo0IwQDAOBgNVHQ8BAf8EBAMCAAEwDwYDVR0TAQH/BAUwAwEB/zAd
BgNVHQ4EFgQULw16NueVc/9IABCb1k6GGESJVJkwDQYJKoZIhvcNAQELBQADggIB
ACXaJ318/8KLv8MOzqtA0dhzQsqZkdrC+jm+Sf+nAmGFP1K/MsSQa8Ggyw/o8t/E
c+q2UYBF8CeP5hDRWlTavvkJISjQTyGJlhuhwA9EefFgcX4hIJhXrLqOGL7tJplr
oVyCoqDbeWuR4M3Nr2z44AQqbo0L9QFkEW4fHHOtIjjt9535yGgB5ApuryM/Crad
7Y3dC1Uohn7oW/4xO0EIjn1blOh9XFc4a862frTiQP54gZ3yU9/JhieSLlNFkReT
ZHcIIGKvNp52mw1hVJATClWKF3JljK4YLG+lHd1NGiuBLDvI6s/9x/3Fih8S37Tv
V3AFz1F0yb5xbFALmhzhgi744vK2lXt2/Gp6SzLq4cIQFi10wYNrW7I2dlpJczs3
p0PmCEJa1r2WEBLvlS+85FkJy7CXrCc9te4vHGIqY2kBG5u2VUUm/gl21HHrTYDt
P5HalOefSq+ve02Tiyyye8STz1sr0bN0db47DOhylnkzJPgHWMCuOq0KNZBry2N9
euPDbGlhga3USPWOyKV6eingIFFT7ug9Fc5vLBh+mD8FQjDOAJ4Cl0MbkIDuQy+x
wYf9W21fxfKQnBgjYvjcNb5no7wKp2KsWshXWDkoih/05icJMfTSkwQ/Qzu4dbDw
6IifuAQn4SzIUd6y+0sVNjZK9XQ3ve+NYYBvM01OhfUA
-----END CERTIFICATE-----
4.查看公钥/私钥信息
kubectl get secret -n kube-system -l sealedsecrets.bitnami.com/sealed-secrets-key -o yaml
测试
1.创建一个secret文件
kubectl create secret generic mysecret --from-literal=username=admin --from-literal=password=123456 --dry-run -o yaml > mysecret.yaml
# 查看生成的文件
[root@master sealed-secrets]# cat mysecret.yaml
apiVersion: v1
data:
password: MTIzNDU2
username: YWRtaW4=
kind: Secret
metadata:
creationTimestamp: null
name: mysecret
2.使用kubeseal对mysercret.yaml进行加密转换
kubeseal --format=yaml < mysecret.yaml > mysecret-sealed.yaml
### kubeseal输出的默认格式是json,此处使用--format将格式转为yaml,这一步是kubeseal从Kubernetes集群获取公钥并使用该公钥加密数据
##查看转换后的SealedSecret
[root@master sealed-secrets]# cat mysecret-sealed.yaml
apiVersion: bitnami.com/v1alpha1
kind: SealedSecret
metadata:
creationTimestamp: null
name: mysecret
namespace: default
spec:
encryptedData:
password: AgBPYXyfWoN6YH/Dls8+L8uIQbHEfVmd6T4bOe3Y0W7d4wL9YPCLDS4fNpjJMPGx7nnR2nJkL2nWcr8xqepkLuIgn5cIZxQ5+EV624nzDIrm/PWE/3GNgb6oCQmpbcW2fIYVbicG6xpz3KHsPKHgxXQCGUJD9wB6bb1wWw5UZOGmihjHanzqbWZhdicDyfKdkyGHPiVi83xgdRmCaScgz9f1EQOfNsD5IkjD3gyLp3ZoMJUBprx0vvKDfZcoIL7vBJLHke9SrvDFtPdfmIneL2yJ7Gew4DJazlUct/U9FnMczl7Wr1Y6YAOFNNV9ysCRVC+C1bmrwr5r21G17KeES+GWLyXIy/epKoCpmtWcHJ22YNhSEtR0RGHWHCwSPeXbr2SdQegZ0Pk64X9QAYrEBO7IhF2gA1JA045DwFMXJjrKzDW+4ogslDXT2a5cIcVKVdrCGk8ajSsXQeOFq5GIcWLPeXs/LRu5SYyj7nr+xjyrPUtV7vxbNUmBCoFJ5TvWnO5yKE6wGQuTUxCOiIRf44KZqy03XZD2nsxe5UW/tyLJHXp1VL8hYHcoSfVSMHsTVPCNpDDUxCnZRnncfRHAXUyPnI2Cpx7uKsg8zu7M6TKklm8g1Ow+P8XBjzTY5vAr441oTad86REHQ6FVdBw8IKtZHYy2kxaTrThnWB3L+3ckk7ZhM3kbIDUdbXkFTkEx82A76ucXSLc=
username: AgCwYrUhSKTgBZ5rf8DTToyB6yztH1+4P5tCv3mSCXt0dJ4L5sCso38JwBQJW6IRgw9nHqXdNwdZKpZW7Yjjr/LpsKUrs/9XkO+rgyf68uXi5tqNSHpsCza3e9Jx9qUI7k3WjHFHtRt5IsaO4OH7tUEmVlnCeuegXZ51HJfnmsZIgzGqDhnHWt6Z9FUOMvyd8jpro58p8tjjZIEBgrIRlMJdGSuUuSP0o3x30/4oPO7+yqbeV9B7OOp7i+sk4LBNfclmjLgySbCww6bc6wHr45NIt/bhIYkiKwk/IWh5e5LBqmZh+klkWA+GcltDTXi7+wv2UMAJXBmPhg4x41/unZUDhsljMvkPC92xWjivp4SMcMrRnjzKYI5UiTi5czS3uqRjH23q6U5/QM0o9IqVRojbSsnF9RmAAsfvZSoToHMgxOyS5ApF+4K/p9LI5t+vz3h7SQ+QhwYyyCcA3JRoK8a0ZFa3fz6bSMFMR+ANC7JtNez7Kiem9WjFhP+FB99UJCGdPmVHWL44uThtRZf/B3hO2hb/oXNHfZiUdjvXdB6Ee56yCUZrurkfjGd0ElnTy7a2CpEHjk2KIETv47qXnL4R6hRbd7nwdprjEg/0hawa0xhwat2PA4Vt+ZG2VbWYIgqc8TgDHJObb6IPn0HEoPvaZCGK1GzXspsbslNMdWrHu5bmbimVDrl7VUAKMWQe7uOy1PHy9A==
template:
metadata:
creationTimestamp: null
name: mysecret
namespace: default
3.部署mysecret-sealed.yaml
kubectl apply -f mysecret-sealed.yaml
##查看部署后的文件
[root@master sealed-secrets]# kubectl get secrets mysecret -o yaml
apiVersion: v1
data:
password: MTIzNDU2
username: YWRtaW4=
kind: Secret
metadata:
creationTimestamp: "2022-12-23T09:24:38Z"
name: mysecret
namespace: default
ownerReferences:
- apiVersion: bitnami.com/v1alpha1
controller: true
kind: SealedSecret
name: mysecret
uid: af66d9ea-3ce3-4894-a1b5-0c3396ffb8d3
resourceVersion: "2935007"
uid: ed797abd-4390-4fc3-bda0-56c36c531d37
type: Opaque
可以看到,mysecret-sealed.yaml被还原为secret并进行部署
我们可以通过日志看到转换过程:控制器拦截了请求,并解密来自SealedSecret的加密数据,然后创建Secret对象
kubectl logs sealed-secrets-controller-8645675c65-jtrc2 -n kube-system
....
2022/12/23 09:24:38 WARNING: Empty API version & kind, filling it...
2022/12/23 09:24:38 Updating default/mysecret
2022/12/23 09:24:38 Event(v1.ObjectReference{Kind:"SealedSecret", Namespace:"default", Name:"mysecret", UID:"af66d9ea-3ce3-4894-a1b5-0c3396ffb8d3", APIVersion:"bitnami.com/v1alpha1", ResourceVersion:"2935006", FieldPath:""}): type: 'Normal' reason: 'Unsealed' SealedSecret unsealed successfully
....
安装web-ui
在很多情况下(比如全流程devops),集群管理员与业务运维等并非同一权限,因此这种命令行操作的方式并不能适用所有情况,这时就会需要一个WEB-UI界面来完成这个加密过程,很幸运github上开源了secret-sealed对应的web界面
web-ui官网地址
bakito/sealed-secrets-web: A web interface for Sealed Secrets by Bitnami. (github.com)
使用helm直接安装
helm repo add bakito https://charts.bakito.net
helm repo update
helm upgrade --install sealed-secrets-web bakito/sealed-secrets-web
当然,我们可能需要一些自定义的配置
helm upgrade --install sealed-secrets-web bakito/sealed-secrets-web \
--set sealedSecrets.namespace=sealed-secrets-web \
--set sealedSecrets.serviceName=sealed-secrets
其他使用方式请参照官方文档
查看部署
[root@master sealed-secrets]# kubectl get all -n sealed-secrets-web
NAME READY STATUS RESTARTS AGE
pod/sealed-secrets-web-6874bbdfb5-9p5wq 1/1 Running 0 8d
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
service/sealed-secrets-web ClusterIP 10.1.3.215 <none> 80:/TCP 8d
NAME READY UP-TO-DATE AVAILABLE AGE
deployment.apps/sealed-secrets-web 1/1 1 1 8d
NAME DESIRED CURRENT READY AGE
replicaset.apps/sealed-secrets-web-6874bbdfb5 1 1 1 8d
我们将service/sealed-secrets-web以nodeport的方式暴露端口(当然也可以使用ingressgateway的方式):
kubectl edit svc sealed-secrets-web -n sealed-secrets-web ##编辑svc
...
spec:
clusterIP: 10.1.3.215
clusterIPs:
- 10.1.3.215
externalTrafficPolicy: Cluster
internalTrafficPolicy: Cluster
ipFamilies:
- IPv4
ipFamilyPolicy: SingleStack
ports:
- name: http
nodePort: 30088 #------------------新增
port: 80
protocol: TCP
targetPort: http
selector:
app.kubernetes.io/instance: sealed-secrets-web
app.kubernetes.io/name: sealed-secrets-web
sessionAffinity: None
type: NodePort #--------------将ClusterIP修改为NodePort
status:
loadBalancer: {
}
...
[root@master sealed-secrets]# kubectl get svc -n sealed-secrets-web
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
sealed-secrets-web NodePort 10.1.3.215 <none> 80:30088/TCP 8d
web访问
-
Encode:Base64 对 stringData 字段中的每个密钥进行秘密编码。
-
Decode:Base64 对数据字段中的每个密钥进行秘密解码。
-
Secrets:返回所有命名空间中所有 Sealed Secrets 的列表。单击 Sealed Secret 即可加载解密的 Kubernetes 机密。
-
Seal:加密 Kubernetes 秘密并创建 Sealed Secret。
缺点
web没有登录认证体系,因此需要自行想办法解决权限问题,比如集成到其他web权限管理下,官方提供了API,可以进行参照改造