使用 Vault 支持的 KES 的 MinIO 运算符

MinIO Operator with KES backed by Vault

为了提供有关安全锁定和擦除的监管合规性功能, MinIO 对对象进行加密 在存储层使用服务器端加密 (SSE) 在写入操作期间保护对象。MinIO 以极高的效率执行此操作 - 基准测试表明 MinIO 能够以接近线速的速度进行加密/解密。

MinIO 使用的秘诀是 单指令多数据 (SIMD)。通常,您只能一次发送一条 CPU 指令,并在收到响应后才能发送下一条指令。这效率极低,尤其是在每秒执行数千甚至数百万次加密和解密指令时。MinIO 利用 SIMD,因此它可以将多条指令在一个请求中发送到 CPU 进行处理。我们已在 GoLang 中使用汇编语言编写了此代码,以便尽可能靠近硬件层,充分利用通常未充分利用的 CPU 能力来大规模执行加密操作。

之前的文章中 我们向您展示了如何在裸机环境中使用 KES 启动 MinIO 和 Vault。在这篇文章中,我们将向您展示如何在 Kubernetes 中以云原生方式使用 KES(密钥加密系统)和 Vault 配置 MinIO 运算符。这将使您能够在扩展时自动化流程,并使用 Kubernetes 资源来配置它们。

先决条件

在我们开始之前,请确保您已具备以下先决条件

  • 一个 Kubernetes 集群(在本教程中,我们将使用 kind 创建一个本地集群)
  • 在您的本地计算机上安装 kubectl 命令行工具
  • 用于克隆必要存储库的 git

步骤 1:使用 kind 部署 Kubernetes 集群

首先,我们将使用 kind 创建一个 Kubernetes 集群。这将为我们提供一个本地环境来部署和测试 MinIO 设置。

首先,使用以下命令创建一个名为 kind-config.yaml 的 kind 配置文件: 

$ cat > kind-config.yaml <<EOF

kind: Cluster

apiVersion: kind.x-k8s.io/v1alpha4

nodes

  - role: control-plane

  - role: worker

  - role: worker

  - role: worker

  - role: worker

EOF


$ kind create cluster --config kind-config.yml

步骤 2:部署 MinIO 运算符

Kubernetes 集群启动并运行后,我们现在可以使用 kustomization 插件部署 MinIO 运算符。MinIO 运算符简化了 Kubernetes 环境中 MinIO 实例的部署和管理。

执行以下命令在 kind 集群中部署 MinIO 运算符

$ kubectl apply -k github.com/minio/operator

在继续执行下一步之前,请等待所有 pod 在 minio-operator 命名空间中上线。

步骤 3:设置 HashiCorp Vault

HashiCorp Vault 是一个功能强大的秘密管理工具,我们将使用它来安全地存储和管理我们的加密密钥。为了在 Kubernetes 集群中设置 Vault,我们将使用 kubernetes-vault 存储库。

通过运行以下命令克隆存储库

$ git clone https://github.com/scriptcamp/kubernetes-vault.git

$ cd kubernetes-vault/vault-manifests

接下来,设置必要的 RBAC(基于角色的访问控制)规则,创建 Vault 配置映射,部署 Vault 服务,并设置有状态集

$ kubectl apply -f rbac.yml

创建 Vault 配置映射

$ kubectl apply -f configmap.yaml

部署 Vault 服务

$ kubectl apply -f services.yaml

由于 Vault 是有状态服务,因此我们需要为其设置有状态集。执行以下命令以完成此操作

$ kubectl apply -f statefulset.yaml

Vault 设置完成后,请取消密封并初始化 Vault。 

$ kubectl exec vault-0 -- vault operator init -key-shares=1 -key-threshold=1 -format=json > keys.json


$ VAULT_UNSEAL_KEY=$(cat keys.json | jq -r ".unseal_keys_b64[]")

$ echo $VAULT_UNSEAL_KEY


$ VAULT_ROOT_KEY=$(cat keys.json | jq -r ".root_token")

$ echo $VAULT_ROOT_KEY


$ kubectl exec vault-0 -- vault operator unseal $VAULT_UNSEAL_KEY

现在,输入 vault-0 POS 以执行其他配置

$ kubectl exec -it vault-0 -- /bin/sh

在 pod 内部,启用 K/V 后端,创建策略,启用 AppRole 身份验证,创建 KES 角色,并生成 AppRole ID 和密钥

$ vault secrets enable -version=1 kv

创建策略

$ cat > kes-policy.hcl <<EOF

path "kv/*" {

   capabilities = [ "create", "read", "delete" ]

}


$ vault policy write kes-policy kes-policy.hcl

启用 AppRole 身份验证

$ vault auth enable approle

创建 KES 角色并将策略附加到它

$ vault write auth/approle/role/kes-server token_num_uses=0  secret_id_num_uses=0  period=5m

$ vault write auth/approle/role/kes-server policies=kes-policy

生成 AppRole ID 和密钥,并记下这些值

$ vault read auth/approle/role/kes-server/role-id

Key    Value

---    -----

role_id b484633b-8965-08dd-0e24-d6973e6be2d2


$ vault write -f auth/approle/role/kes-server/secret-id

Key               Value

---               -----

secret_id         7fd44d44-a3f1-a013-1f40-e1952496c416

secret_id_accessor b5ee0c97-5ffc-b9a7-fe0b-763757fe1033

secret_id_ttl     0s

记下生成的 AppRole ID 和密钥,因为我们将在下一步中需要它们。

步骤 4:使用 kustomization 插件部署 KES

为了使用 kustomization 插件部署 KES(密钥加密服务),我们首先需要克隆 MinIO 存储库

$ git clone https://github.com/minio/operator.git

$ cd operator

使用适当的 KES 值更新 examples/kustomization/tenant-kes-encryption/kes-configuration-secret.yaml 文件,包括 Vault 端点、命名空间、前缀以及生成的 AppRole ID 和密钥。

keystore:

   ## 在 Kubernetes 环境中配置使用 fs(文件系统模式)的 KES 不起作用,也不推荐使用

   ## 使用真正的 KMS

   # fs:

   #   path: "./keys" # 密钥将存储为文件。不建议在生产环境中使用。

   vault:

     endpoint: "http://vault.default.svc.cluster.local:8200" # Vault 端点

     namespace: "default" # 可选的 Vault 命名空间。查看:https://www.vaultproject.io/docs/enterprise/namespaces/index.html

     prefix: "my-minio" # 可选的 K/V 前缀。服务器将在此前缀下存储密钥。

     approle: # AppRole 凭据。查看:https://www.vaultproject.io/docs/auth/approle.html

       id: "b484633b-8965-08dd-0e24-d6973e6be2d2"  # 您的 AppRole 角色 ID

       secret: "7fd44d44-a3f1-a013-1f40-e1952496c416"  # 您的 AppRole 密钥 ID

       retry: 15s  # 连接丢失后服务器尝试重新身份验证的持续时间。

     tls:    # Vault 客户端 TLS 配置,用于 mTLS 身份验证和证书验证

       key: "" # TLS 客户端私钥路径,用于 mTLS 身份验证到 Vault

       cert: "" # TLS 客户端证书路径,用于 mTLS 身份验证到 Vault

       ca: ""  # 一个或多个 PEM 根 CA 证书路径

     status: # Vault 状态配置。服务器将定期访问 Vault 以检查其状态。

       ping: 10s   # 服务器再次检查 Vault 状态的时间间隔。

现在,将 KES 服务与 MinIO 租户一起部署

$ kubectl apply -k operator/examples/kustomization/tenant-kes-encryption

这将部署如下所示的 KES 和 MinIO Pod

$ kubectl get pods -n tenant-kms-encrypted

NAME           READY   STATUS RESTARTS   AGE

myminio-kes-0  1/1 Running   0          104m

myminio-kes-1  1/1 Running   0          104m

myminio-pool-0-0   2/2 Running   0          101m

myminio-pool-0-1   2/2 Running   0          102m

myminio-pool-0-2   2/2 Running   3 (102m ago)   103m

myminio-pool-0-3   2/2 Running   4 (102m ago)   104m

您现在已启动并运行带有 KES 的 MinIO 部署。

步骤 5:验证部署

为了确保我们的部署顺利运行,让我们检查 MinIO 租户 Pod、KES Pod 和操作员 Pod 的状态

$ kubectl get pods -n minio-operator                                                                                                                    NAME                          READY   STATUS RESTARTS   AGE

console-6459d44b76-fgwbt      1/1 Running   0      5h29m

minio-operator-5668d46f98-9p2wm   1/1 Running   0      5h29m

minio-operator-5668d46f98-pm98s   1/1 正在运行   0      5h29m


$ kubectl get pods -n tenant-kms-encrypted

NAME           READY   STATUS RESTARTS   AGE

myminio-kes-0  1/1 正在运行   0          116m

myminio-kes-1  1/1 正在运行   0          116m

myminio-pool-0-0   2/2 正在运行   0          113m

myminio-pool-0-1   2/2 正在运行   0          114m

myminio-pool-0-2   2/2 正在运行   3 (114m 前)   115m

myminio-pool-0-3   2/2 正在运行   4 (114m 前)   116m


$ k get pods -n default

名称     就绪   状态 重启次数   年龄

vault-0  1/1 正在运行   0      4h39m

验证 KES pod 日志以确保没有错误,并且 pod 按预期运行,如下所示

$ kubectl logs myminio-kes-0 -n tenant-kms-encrypted                                                                                                        版权所有   MinIO, Inc.       https://min-io.cn

许可证 GNU AGPLv3        https://gnu.ac.cn/licenses/agpl-3.0.html

版本 2023-04-18T19-36-09Z  linux/amd64


KMS     Hashicorp Vault: http://vault.default.svc.cluster.local:8200

端点   https://127.0.0.1:7373

         https://10.244.3.55:7373


管理员   _                 [ 已禁用 ]

内存锁定 关闭               无法锁定内存页面。请考虑授予 CAP_IPC_LOCK 权限。


{"time":"2024-03-08T07:51:31.333681336Z","request":{"ip":"10.244.1.47","path":"/v1/key/create/my-minio-key","identity":"f9daf353b4bb9bba772a369b621a258c9464322c85d1ac9d2aafd29afdb96ea6"},"response":{"code":400,"time":2871000}}

{"time":"2024-03-08T07:51:32.191375099Z","request":{"ip":"10.244.3.54","path":"/v1/identity/self/describe","identity":"f9daf353b4bb9bba772a369b621a258c9464322c85d1ac9d2aafd29afdb96ea6"},"response":{"code":200,"time":18000}}

{"time":"2024-03-08T07:51:32.191784146Z","request":{"ip":"10.244.3.54","path":"/v1/key/create/my-minio-key","identity":"f9daf353b4bb9bba772a369b621a258c9464322c85d1ac9d2aafd29afdb96ea6"},"response":{"code":400,"time":1739000}}

{"time":"2024-03-08T07:52:01.890935905Z","request":{"ip":"10.244.3.54","path":"/v1/key/generate/my-minio-key","identity":"f9daf353b4bb9bba772a369b621a258c9464322c85d1ac9d2aafd29afdb96ea6"},"response":{"code":200,"time":1888000}}

{"time":"2024-03-08T07:52:02.145905494Z","request":{"ip":"10.244.1.47","path":"/v1/key/generate/my-minio-key","identity":"f9daf353b4bb9bba772a369b621a258c9464322c85d1ac9d2aafd29afdb96ea6"},"response":{"code":200,"time":62000}}

{"time":"2024-03-08T07:52:02.162627602Z","request":{"ip":"10.244.1.47","path":"/v1/key/generate/my-minio-key","identity":"f9daf353b4bb9bba772a369b621a258c9464322c85d1ac9d2aafd29afdb96ea6"},"response":{"code":200,"time":62000}}

{"time":"2024-03-08T07:52:04.850766874Z","request":{"ip":"10.244.3.54","path":"/v1/key/decrypt/my-minio-key","identity":"f9daf353b4bb9bba772a369b621a258c9464322c85d1ac9d2aafd29afdb96ea6"},"response":{"code":200,"time":68000}}

{"time":"2024-03-08T07:52:04.857285115Z","request":{"ip":"10.244.3.54","path":"/v1/key/decrypt/my-minio-key","identity":"f9daf353b4bb9bba772a369b621a258c9464322c85d1ac9d2aafd29afdb96ea6"},"response":{"code":200,"time":53000}}

{"time":"2024-03-08T07:52:07.753077729Z","request":{"ip":"10.244.2.35","path":"/v1/identity/self/describe","identity":"f9daf353b4bb9bba772a369b621a258c9464322c85d1ac9d2aafd29afdb96ea6"},"response":{"code":200,"time":7000}}

步骤 6:测试部署

为了测试我们的部署,我们将创建一个示例桶并从安装了 mc(MinIO 客户端)的调试 pod 加载/检索对象。

首先,启动一个新的终端并运行以下命令以进入调试 pod

kubectl exec -it pod/ubuntu-pod -n default -- bash

在调试 pod 内,运行以下命令来创建桶、创建加密密钥、上传文件并验证加密,如下所示

mc alias ls myminio
mc ls myminio
mc mb myminio/encryptedbucket
mc admin kms key create myminio encrypted-bucket-key

echo "Hello" >> file1.txt
mc cp file1.txt myminio/encryptedbucket
mc ls myminio/encryptedbucket
mc cat myminio/encryptedbucket/file1.txt
mc admin kms key status myminio encrypted-bucket-key
mc stat myminio/encryptedbucket/file1.txt

如果一切设置正确,您应该看到上传的文件已加密,并且加密密钥状态有效。

以下是此过程的预期展示

$ kubectl exec -it pod/ubuntu-pod -n default -- bash                                                                                               


root@ubuntu-pod:/# mc alias ls myminio

myminio

  URL   : https://myminio-pool-0-0.myminio-hl.tenant-kms-encrypted.svc.cluster.local:9000

  AccessKey : minio

  SecretKey : minio123

  API   : s3v4

  Path  : auto


root@ubuntu-pod:/# mc ls myminio


root@ubuntu-pod:/# mc mb myminio/encryptedbucket

桶 `myminio/encryptedbucket` 创建成功。


root@ubuntu-pod:/# mc admin kms key create myminio encrypted-bucket-key

主密钥 `encrypted-bucket-key` 创建成功


root@ubuntu-pod:/# echo "Hello" >> file1.txt


root@ubuntu-pod:/# mc cp file1.txt myminio/encryptedbucket

/file1.txt:                        6 B / 6 B ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 344 B/s 0sroot@ubuntu-pod:/# mc ls myminio/encryptedbucket

[2024-03-08 10:25:01 UTC] 6B STANDARD file1.txt


root@ubuntu-pod:/# mc cat myminio/encryptedbucket/file1.txt

Hello


root@ubuntu-pod:/# mc admin kms key status myminio encrypted-bucket-key

Key: encrypted-bucket-key

   - 加密 ✔

   - 解密 ✔


root@ubuntu-pod:/# mc stat myminio/encryptedbucket/file1.txt

名称  : file1.txt

日期  : 2024-03-08 10:25:01 UTC

大小  : 6 B    

ETag  : 27e775e1a5d22463e4cd39f12ce14ea0

类型  : 文件

元数据 

  Content-Type: text/plain

已加密

  X-Amz-Server-Side-Encryption           : aws:kms

  X-Amz-Server-Side-Encryption-Aws-Kms-Key-Id: arn:aws:kms:encrypted-bucket-key


如果一切设置正确,您应该看到上传的文件已加密,并且加密密钥状态有效,从而确认对象已加密。

最后的想法

在这篇博文中,我们探讨了如何在 Kubernetes 环境中使用 KES 支持的 Vault 部署 MinIO 运算符,重点关注服务器端加密 (SSE)。通过利用 Kubernetes 和 kustomization 插件的强大功能,我们可以自动化部署流程并根据需要轻松扩展 MinIO 设置。

采用“左移”方法,我们强调了从开发和规划的早期阶段嵌入安全和数据保护实践的重要性。意图明确:将安全性从仅仅是一种考虑因素提升为基础设施的基础元素。通过突出 SSE 的简单性和可访问性,我们的目标是鼓励将其作为所有 MinIO 部署的标准进行采用。实现稳固安全性的路径既简单又切实可行,为更安全、更安全的数字环境铺平了道路。

如果您有任何疑问、遇到任何问题,或者只是想谈论您使用 MinIO 的经验,我们的社区随时准备为您提供帮助。加入我们的 Slack,结识其他用户,从专家那里获得建议,并了解对象存储的最新消息。 

祝您加密愉快!