如何在 Kubernetes 中使用 Vault HA 执行滚动更新?

Dat*_*atz 5 kubernetes hashicorp-vault

我正在 K8s 中运行 HashiCorp Vault 无状态集,在三个节点上有 3 个 pod。

部署后,我手动解封 Vault。然后 Vault 始终保持未密封状态。

问题是当其中一个节点重新启动时,Vault pod 会以非密封模式重新启动。 有什么办法可以通过与已经解封的 pod 之一进行服务器-服务器通信来自动解封 Vault 节点吗?

当我的 Kubernetes 环境更新并且所有节点都重新启动(滚动更新 - 一个接一个)时,我不想手动解封 Vault pod。

我也不想将解封密钥存储在 K8s 秘密甚至文件中,因为这会使我的秘密加密无用。

这是我的 yaml:

apiVersion: v1
kind: Service
metadata:
  name: vault
spec:
  clusterIP: None
  ports:
    - name: http
      port: 8200
    - name: server
      port: 8201
  selector:
    xyz.service: vault
---
apiVersion: apps/v1
kind: StatefulSet
metadata:
  name: vault
  labels:
    xyz.service: vault
spec:
  serviceName: "vault"
  selector:
    matchLabels:
      xyz.service: vault
  replicas: 3
  template:
    metadata:
      labels:
        xyz.service: vault
    spec:
      imagePullSecrets:
      - name: reg-dhc-xyzoms-pull-secret
      securityContext:
        runAsUser: 100
        fsGroup: 1000
      affinity:
        podAntiAffinity:
          requiredDuringSchedulingIgnoredDuringExecution:
            - labelSelector:
                matchExpressions:
                  - key: xyz.service
                    operator: In
                    values:
                      - vault
              topologyKey: kubernetes.io/hostname
      containers:
        - name: vault
          image: vault:0.11.0
          resources:
            requests:
              memory: "100Mi"
          env:
          - name: SKIP_SETCAP
            value: dontcare
          - name: POD_IP
            valueFrom:
              fieldRef:
                fieldPath: "status.podIP"
          - name: "VAULT_CLUSTER_ADDR"
            value: "https://$(POD_IP):8201"
          ports:
            - name: http
              containerPort: 8200
              protocol: "TCP"
            - name: server
              containerPort: 8201
              protocol: "TCP"
Run Code Online (Sandbox Code Playgroud)

Dat*_*atz 2

经过更多的挖掘,我了解到,我想要的东西是不可能的。每当 Vault 实例重新启动时,它都会首先被解封,并且无法使用 Vault 自己的技术自动解封它。

您可以在 GitHub 和Docker 商店中找到许多“vault-unsealer”实现,它们试图通过定期检查 Vault Pod 状态并在必要时将其解封来填补这一空白。

建议使用 K8s readinessprobe 以避免服务访问密封的 Vault Pod。

由于没有官方的“vault-unsealer”图像,因此必须谨慎使用公共实现。我最终编写了自己的“vault-unsealer”以避免安全缺陷和许可问题。

我的解决方案是每个 Vault pod 都有一个 sidecar 容器。首先必须使用kubectl exec ...一个边车手动输入一次开封密钥。Sidecar 会定期检查所有 Vault Pod,并将开封密钥传送给另一个 Sidecar(如果已密封)。如果 sidecar 收到解封密钥,它们将存储在内存中并用于解封其自己的 Vault 实例。

  1. kubect aply -f vault.yaml-> Vault-0 开始
  2. kubectl exec vault-0 -c sidecar ...输入解封密钥 ->Vault-0 sidecar 解封Vault-0并准备就绪
  3. Vault-1 启动
  4. Vault-0 sidecar 检测到Vault-1 已解封,并调用vault-1 sidecar 来传输解封密钥。->Vault-1 Sidecar 解封Vault-0 并准备就绪
  5. 等等...