我们最近有不少Bank-Vaults的发布,其中新的功能到达了webhook和运营商。这并不是巧合,相反,这些功能是在过去两年中围绕项目成长起来的社区的帮助下开发和实现的。在这篇博文中,我们想强调和讨论其中的一些改进.
Docker镜像注册表的变化 🔗︎
ghcr.io 🔗︎
从1.4.2开始,我们已经开始将所有Bank-Vaults的镜像推送到最近推出的GitHub容器注册处。这样做的原因之一是,我们想提供一个备份注册表源已经很久了。而且,鉴于最近的Docker速率限制公告,我们认为这可能是把类似的东西放在那里的正确时机。
ghcr.io将是这个项目的默认仓库,一旦我们完成测试。目前,你必须特别明确地要求从那里提取图像,而不是DockerHub,就像下面的例子中安装webhook时那样。
helm repo add banzaicloud-stable https://kubernetes-charts.banzaicloud.com
helm upgrade --install vault-secrets-webhook banzaicloud-stable/vault-secrets-webhook --set image.repository=ghcr.io/banzaicloud/vault-secrets-webhook --set vaultEnv.repository=ghcr.io/banzaicloud/vault-env --set configMapMutation=true
GCR在webhook中的自动认证 🔗︎
我们是Viktor Radnai为GCR Docker镜像提供的出色便利功能的受益者;为了让webhook通过向容器注入vault-env来改变容器,它必须知道预置vault-env二进制文件所需的确切命令和参数。如果这些没有明确定义,webhook将在给定的容器注册表中寻找图像元数据。这在公共注册表的情况下很有效,但是,如果你使用的是私人注册表,webhook需要先进行认证。当ECR在EC2实例上运行时,这种认证已经是自动的,但现在GCR也是自动的--如果你的工作负载是在GCP节点上运行的话。
ARM图像 🔗︎
在1.5.0中,我们增加了对各种ARM平台(32和64位)的支持。这个伟大的想法/要求来自Pato Arvizu,他在他的Raspberry PI集群上运行Bank-Vaults!现在推送到ghcr.io的镜像是多架构的。DockerHub上的还不是,但我们很快会更新DockerHub镜像的构建,使其也成为多架构的。

让我们来看一个例子,如何在混合架构的EKS集群上用操作员设置一个Vault实例。EKS支持价格适中的A1 ARM EC2实例,它将完美地作为本篇文章的廉价示范基础设施。首先,我们通过我们的Try Pipeline环境和Banzai CLI部署一个有两个节点池的新集群,一个是ARM实例,一个是X86实例。
# login to try
banzai login -e <your-pipeline-url>/pipeline
# create an AWS secret based on your local credentials
banzai secret create -n aws -t amazon --magic
banzai cluster create <<EOF
{
"name": "eks-arm-bank-vaults",
"location": "us-east-2",
"cloud": "amazon",
"secretName": "aws-trash",
"properties": {
"eks": {
"version": "1.17.9",
"nodePools": {
"pool1": {
"spotPrice": "0.1",
"count": 2,
"minCount": 2,
"maxCount": 3,
"autoscaling": true,
"instanceType": "a1.xlarge",
"image": "ami-05835ec0d56045247"
},
"pool2": {
"spotPrice": "0.101",
"count": 1,
"minCount": 1,
"maxCount": 2,
"autoscaling": true,
"instanceType": "c5.large"
}
}
}
}
}
EOF
一旦集群准备好了,我们就安装运营商,使用ghcr.io的图像(很快就会成为默认的)。
banzai cluster shell --cluster-name eks-arm-bank-vaults -- \
helm upgrade --install vault-operator banzaicloud-stable/vault-operator --set image.repository=ghcr.io/banzaicloud/vault-operator --set image.bankVaultsRepository=ghcr.io/banzaicloud/bank-vaults
现在,用操作员创建Vault实例。
kubectl apply -f https://raw.githubusercontent.com/banzaicloud/bank-vaults/master/operator/deploy/rbac.yaml
kubectl apply -f https://raw.githubusercontent.com/banzaicloud/bank-vaults/master/operator/deploy/cr.yaml
为了确保你的Vault实例落在一个arm64 节点上,编辑vault CR,并添加以下几行。
nodeSelector:
kubernetes.io/arch: arm64
正如你在下面的输出中看到的,vault-0 Pod运行在ip-192-168-68-7.us-east-2.compute.internal ,这是一个aarch64 (ARM 64bit)节点。
kubectl get nodes -o wide
NAME STATUS ROLES AGE VERSION INTERNAL-IP EXTERNAL-IP OS-IMAGE KERNEL-VERSION CONTAINER-RUNTIME
ip-192-168-68-7.us-east-2.compute.internal Ready <none> 4h56m v1.17.11-eks-cfdc40 192.168.68.7 3.15.218.216 Amazon Linux 2 4.14.198-152.320.amzn2.aarch64 docker://19.3.6
ip-192-168-68-84.us-east-2.compute.internal Ready <none> 4h47m v1.17.11-eks-cfdc40 192.168.68.84 3.16.47.242 Amazon Linux 2 4.14.198-152.320.amzn2.aarch64 docker://19.3.6
ip-192-168-76-34.us-east-2.compute.internal Ready <none> 4h56m v1.17.11-eks-cfdc40 192.168.76.34 18.216.230.201 Amazon Linux 2 4.14.198-152.320.amzn2.x86_64 docker://19.3.6
有些Pod运行在x86_64 ,有些运行在aarch64 - 对于Bank-Vaults来说不是问题。
kubectl get pods -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
vault-0 3/3 Running 0 3h9m 192.168.68.157 ip-192-168-68-7.us-east-2.compute.internal <none> <none>
vault-configurer-5b7cd464cb-2fn5p 1/1 Running 0 3h10m 192.168.78.204 ip-192-168-68-84.us-east-2.compute.internal <none> <none>
vault-operator-966949459-kf6pp 1/1 Running 0 84s 192.168.73.136 ip-192-168-68-84.us-east-2.compute.internal <none> <none>
vault-secrets-webhook-58db77d747-6plv7 1/1 Running 0 168m 192.168.71.128 ip-192-168-68-84.us-east-2.compute.internal <none> <none>
vault-secrets-webhook-58db77d747-wttqg 1/1 Running 0 168m 192.168.72.95 ip-192-168-68-7.us-east-2.compute.internal <none> <none>
之前提到的nodeSelector 并不是必需的,我们只是用它来确保Bank-Vaults容器落在ARM节点上。在实际节点上运行的Docker/ContainerD守护程序知道它在哪个架构上运行,并自动调出正确的镜像。
Webhook 🔗︎
多种认证类型 🔗︎
以前,Webhook在Vault中只提供基于KubernetesServiceAccount的认证。这种机制是不可配置的--这是我们的一个老毛病--我们一直想在webhook中加强认证支持。另外,用户早就要求基于AWS/GCP/JWT的认证。在新的vault.security.banzaicloud.io/vault-auth-method 注释的帮助下,用户现在可以要求不同的认证类型。
apiVersion: apps/v1
kind: Deployment
metadata:
name: vault-env-gcp-auth
spec:
selector:
matchLabels:
app.kubernetes.io/name: vault-env-gcp-auth
template:
metadata:
labels:
app.kubernetes.io/name: vault-env-gcp-auth
annotations:
# These annotations enable Vault GCP GCE auth, see:
# https://www.vaultproject.io/docs/auth/gcp#gce-login
vault.security.banzaicloud.io/vault-addr: "https://vault:8200"
vault.security.banzaicloud.io/vault-tls-secret: vault-tls
vault.security.banzaicloud.io/vault-role: "my-role"
vault.security.banzaicloud.io/vault-path: "gcp"
vault.security.banzaicloud.io/vault-auth-method: "gcp-gce"
spec:
containers:
- name: alpine
image: alpine
command:
- "sh"
- "-c"
- "echo $MYSQL_PASSWORD && echo going to sleep... && sleep 10000"
env:
- name: MYSQL_PASSWORD
value: vault:secret/data/mysql#MYSQL_PASSWORD
该部署--如果在GCP实例上运行--将自动从云提供商的元数据服务器接收一个经过签名的JWT令牌,它将使用该令牌对Vault进行认证。vault-auth-method: "aws-ec2" ,当运行在具有正确实例角色的EC2节点上时也是如此。
将Vault秘密中的所有密钥挂到env 🔗︎
从Rakesh Patel那里,webhook得到了一个与Kubernetes的标准envFrom: 结构非常相似的功能,但不是Kubernetes Secret/ConfigMap,而是在webhook和vault-env的帮助下,从Vault secret挂载它的所有密钥。让我们看看vault.security.banzaicloud.io/vault-env-from-path 注释的作用。
apiVersion: apps/v1
kind: Deployment
metadata:
name: hello-secrets
spec:
selector:
matchLabels:
app.kubernetes.io/name: hello-secrets
template:
metadata:
labels:
app.kubernetes.io/name: hello-secrets
annotations:
vault.security.banzaicloud.io/vault-addr: "https://vault:8200"
vault.security.banzaicloud.io/vault-tls-secret: vault-tls
vault.security.banzaicloud.io/vault-env-from-path: "secret/data/accounts/aws"
spec:
initContainers:
- name: init-ubuntu
image: ubuntu
command: ["sh", "-c", "echo AWS_ACCESS_KEY_ID: $AWS_ACCESS_KEY_ID && echo initContainers ready"]
containers:
- name: alpine
image: alpine
command: ["sh", "-c", "echo AWS_SECRET_ACCESS_KEY: $AWS_SECRET_ACCESS_KEY && echo going to sleep... && sleep 10000"]
与Podenv 结构中的原始环境变量定义相比,这里唯一的区别是,你不会在定义中看到实际的环境变量,因为它是动态的--是基于Vault secret的内容--就像envFrom: 。
在资源中定义多个 inline-secrets 🔗︎
感谢AOE GmbH的热心人,我们收到了期待已久的webhook的附加功能,即允许我们在一个Secret/ConfigMap/Object中的同一密钥下注入多个secret。最初,我们提供一个单一的Vault路径,定义为Secret/ConfigMap/PodEnv中的一个值。后来,我们通过模板化对其进行了扩展,因此你可以对收到的值进行转换。现在,我们提供了对一个值内的多个Vault路径的完整支持,在这里,在下面的例子中找到这些。
apiVersion: v1
kind: ConfigMap
metadata:
name: sample-configmap
annotations:
vault.security.banzaicloud.io/vault-addr: "https://vault.default:8200"
vault.security.banzaicloud.io/vault-role: "default"
vault.security.banzaicloud.io/vault-tls-secret: vault-tls
vault.security.banzaicloud.io/vault-path: "kubernetes"
vault.security.banzaicloud.io/inline-mutation: "true"
data:
aws-access-key-id: "vault:secret/data/accounts/aws#AWS_ACCESS_KEY_ID"
aws-access-template: "vault:secret/data/accounts/aws#AWS key in base64: ${.AWS_ACCESS_KEY_ID | b64enc}"
aws-access-inline: "AWS_ACCESS_KEY_ID: ${vault:secret/data/accounts/aws#AWS_ACCESS_KEY_ID} AWS_SECRET_ACCESS_KEY: ${vault:secret/data/accounts/aws#AWS_SECRET_ACCESS_KEY}"
这个例子还展示了在非Pod资源的情况下如何使用CA证书(由操作员创建)来验证TLS连接(与vault.security.banzaicloud.io/vault-tls-secret: vault-tls ),这是在#1148中添加的。
操作员 🔗︎
运营商在最近的版本中得到了大量的修复和稳定。有两个特点值得一提。
删除了对Helm2的支持 🔗︎
这是对一个功能的删除。从Helm 2到Helm 3的转变并不像在Helm社区中那样流畅,我们也纳入了一些 "不太理想 "的解决方案来度过这个过渡。由于Helm 2在未来的日子里将达到终结,我们决定完全放弃对Helm 2的支持,这使得我们的图表更加简洁,并且可以适当地进行联接。
有适当验证的CRD 🔗︎
在最终为我们的Vault自定义资源实施适当的CRD验证之前,我们已经走到了终点线,但我们有一个阻止者的问题,kubernetes-sigs/controller-tools ,需要首先修复。一旦合并,你将能够完全验证Vault的CRD,甚至在级别上也是如此 。