在 Hashicorp Vault 中存储 Cassandra Secret
此功能可让您在外部密钥管理器 Hashicorp Vault 中存储 Apigee Hybrid 的 Cassandra 数据库凭据。外部密钥管理器可让您管理 Secret 在 Kubernetes 中的存储方式,包括管理数据驻留和精细的访问权限控制。
在 Apigee Hybrid 1.10 版之前,为 Cassandra 用户提供密码的唯一方法是在 override.yaml 中指定密码。这些密码存储在 Kubernetes Secret 中。例如:
cassandra: auth: default: password: "********" admin: password: "********" ddl: password: "********" dml: password: "********" jmx: username: "jmxuser" password: "********" jolokia: username: "apigee" password: "********"
使用 Hashicorp Vault,您可以通过 Kubernetes Secrets Store CSI 驱动程序 API (SecretProviderClass
) 提供这些密码。这允许 Kubernetes 装载存储在外部 Vault 中的多个 Secret、密钥和证书。
Cassandra 用户和密码
您需要为以下 Cassandra 用户创建 Secret。更改默认值以满足组织的安全政策。
Cassandra 用户 | 默认用户名 | 默认密码 |
---|---|---|
管理员 | admin_user |
"********" |
DDL | ddl_user |
"********" |
默认 | cassandra 注意:默认用户名必须始终为“cassandra” |
"********" |
DML | dml_user |
"********" |
JMX | "jmxuser" |
"********" |
Jolokia | "apigee" |
"********" |
如需了解详情,请参阅 cassandra 配置属性。
配置外部 Secret 集成
为 Apigee Hybrid 设置 Vault 集成包括以下步骤。
- 在前两个步骤中,您直接与 Vault 交互。
- 在第三步和第四步中,您将配置应用于 Kubernetes 集群。
按照以下步骤在 Vault 中创建 Secret,并使 Hybrid 安装可以访问它们。
创建 Vault Secret、政策和角色
-
验证当前 Kubernetes 上下文是否设置为您的集群:
kubectl config current-context
-
使用 Vault API、CLI 或界面创建 Cassandra Secret。您创建的 Secret 值必须与集群中当前使用的 Cassandra 用户名和密码相匹配。
-
密钥:可以使用任何密钥(或多个密钥的组合),例如:
secret/data/apigee/cassandra
-
Secret 数据:Apigee Hybrid 要求以下 Cassandra 用户的用户名和密码:
Cassandra 用户 管理员 DDL 默认 DML JMX Jolokia -
Vault CLI:以下命令展示了如何创建一个包含所有必需用户名和密码的 Secret:
vault kv put secret/apigee/cassandra \ adminUsername="ADMIN_USERNAME" \ adminPassword="ADMIN_PASSWORD" \ ddlUsername="DDL_USERNAME" \ ddlPassword="DDL_PASSWORD" \ defaultUsername="cassandra" \ defaultPassword="DEFAULT_PASSWORD" \ dmlUsername="DML_USERNAME" \ dmlPassword="DML_PASSWORD" \ jmxUsername="JMX_USERNAME" \ jmxPassword="JMX_PASSWORD" \ jolokiaUsername="JOLOKIA_USERNAME" \ jolokiaPassword="JOLOKIA_PASSWORD"
每个用户的默认用户名如下所示:Cassandra 用户 默认值 管理员 admin_user
DDL ddl_user
默认 cassandra
DML dml_user
JMX jmxuser
Jolokia apigee
-
密钥:可以使用任何密钥(或多个密钥的组合),例如:
-
在 Vault 中,创建政策以授予对您刚刚创建的 Secret 的访问权限。
-
创建一个包含以下内容的政策文件(建议的名称:
apigee-cassandra-auth.txt
):path "secret/data/apigee/cassandra" { capabilities = ["read"] }
如果您创建了多个 Secret,则每个 Secret 都必须添加到该政策文件中:path "secret/data/apigee/cassandra/admin" { capabilities = ["read"] } path "secret/data/apigee/cassandra/ddl" { capabilities = ["read"] }
-
将该政策应用于 Vault:
vault policy write apigee-cassandra-auth apigee-cassandra-auth.txt
可使用标准输入取代从文件读取来创建政策:
echo 'path "secret/data/apigee/cassandra" { capabilities = ["read"] }' | vault policy write apigee-cassandra-auth -
-
创建一个包含以下内容的政策文件(建议的名称:
-
将该政策绑定到 Apigee Cassandra Kubernetes 服务账号。
- 定义以下环境变量:
export ORG_NAME=APIGEE_ORG_NAME
export ENVS_LIST=LIST_OF_APIGEE-ENVS
export APIGEE_NAMESPACE=YOUR_APIGEE_NAMESPACE
export NAMESPACES=apigee-system,${APIGEE_NAMESPACE}
其中:
- ORG_NAME 是您的 Apigee 组织的名称。
- ENVS_LIST 是您的 Apigee 环境的逗号分隔列表,例如
dev,prod
。 - APIGEE_NAMESPACE 是您的 Apigee 命名空间。默认值为
apigee
。 - NAMESPACES 是 Apigee、
apigee-system
和您的 Apigee 命名空间的命名空间逗号分隔列表。
- 创建一个包含以下内容的脚本:脚本可以采用任何名称。在以下示例中,脚本的名称为
create-vault-cassandra-role.sh
:# create-vault-cassandra-role.sh ORG=ORG_NAME # ORG name ENVS=ENVS_LIST # comma separated env names, for example: dev,prod org_short_name=$(echo $ORG | head -c 15) encode=$(echo -n $ORG | shasum -a 256 | head -c 7) org_encode=$(echo "$org_short_name-$encode") names=apigee-manager,apigee-cassandra-default,apigee-cassandra-backup-sa,apigee-cassandra-restore-sa,apigee-cassandra-schema-setup-${org_encode},apigee-cassandra-schema-val-${org_encode},apigee-cassandra-user-setup-${org_encode},apigee-mart-${org_encode},apigee-mint-task-scheduler-${org_encode} for env in ${ENVS//,/ } do env_short_name=$(echo $env | head -c 15) encode=$(echo -n $ORG:$env | shasum -a 256 | head -c 7) env_encode=$(echo "$org_short_name-$env_short_name-$encode") names+=,apigee-synchronizer-${env_encode},apigee-runtime-${env_encode} done echo $names
- 运行脚本并将输出分配给 SERVICE_ACCOUNT_NAMES 变量。这将创建 Kubernetes 服务账号名称的逗号分隔列表。
export SERVICE_ACCOUNT_NAMES=$(./create-vault-cassandra-role)
检查该变量是否已填充列表:
echo $SERVICE_ACCOUNT_NAMES
-
使用 Vault CLI 创建一个将政策绑定到 Kubernetes 服务账号的角色:
vault write auth/kubernetes/role/cassandra \ bound_service_account_names=${SERVICE_ACCOUNT_NAMES} \ bound_service_account_namespaces=${NAMESPACES} \ policies=apigee-cassandra-auth \ ttl=1m
- 定义以下环境变量:
安装 CSI 驱动程序和 Vault 提供程序
Apigee Hybrid v1.12.1 支持以下 Helm 图表版本:
软件 | 版本 |
---|---|
Secret Store CSI 驱动程序 | v1.3.4 |
保险柜 | v0.25.0 |
- 按照 Secrets Store CSI 驱动程序安装说明在您的集群上安装 CSI 驱动程序。CSI 驱动程序具有用于安装的 Helm 图表。
- 如果您尚未安装 Vault CSI 提供程序,请按照安装 Vault CSI 提供程序中的说明操作。
创建 SecretProviderClass 对象
SecretProviderClass
资源告知 CSI 驱动程序在请求 Secret 时要通信的提供程序。Cassandra 用户的凭据必须通过此对象进行配置。下表显示了 Apigee Cassandra 预期的文件名 (objectName
):
Cassandra 用户 | 预期的 Secret 文件名 |
---|---|
管理员 | adminUsername ,adminPassword |
DDL | ddlUsername ,ddlPassword |
默认 | cassandra ,defaultPassword |
DML | dmlUsername ,dmlPassword |
JMX | jmxUsername ,jmxPassword |
Jolokia | jolokiaUsername ,jolokiaPassword |
- 为您的
SecretProviderClass
创建一个 YAML 文件。文件可以采用任何名称,例如spc.yaml
。使用以下SecretProviderClass
模板配置此资源:apiVersion: secrets-store.csi.x-k8s.io/v1 kind: SecretProviderClass metadata: name: apigee-cassandra-auth-spc spec: provider: vault parameters: roleName: apigee-cassandra-auth # the roleName should match the vault role you created earlier in this procedure # vaultAddress is the endpoint your Vault server is running at. # If Vault is running in the same cluster as Apigee, the format will generally be: # http://vault.<namespace>.svc.cluster.local:<vaultServicePort> vaultAddress: VAULT_ADDRESS # "objectName" is an alias used within the SecretProviderClass to reference # that specific secret. This will also be the filename containing the secret. # Apigee Cassandra expects these exact values so they must not be changed. # "secretPath" is the path in Vault where the secret should be retrieved. # "secretKey" is the key within the Vault secret response to extract a value from. # For example, if the Vault secret is located at `secret/data/apigee/cassandra` # and you want to specify the admin password, you would use the following: # - objectName: "adminPassword" # secretPath: "secret/data/apigee/cassandra" # secretKey: "key within Vault secret specifying the admin password" objects: | - objectName: "adminUsername" secretPath: "" secretKey: "" - objectName: "adminPassword" secretPath: "" secretKey: "" - objectName: "defaultUsername" secretPath: "" secretKey: "" - objectName: "defaultPassword" secretPath: "" secretKey: "" - objectName: "ddlUsername" secretPath: "" secretKey: "" - objectName: "ddlPassword" secretPath: "" secretKey: "" - objectName: "dmlUsername" secretPath: "" secretKey: "" - objectName: "dmlPassword" secretPath: "" secretKey: "" - objectName: "jolokiaUsername" secretPath: "" secretKey: "" - objectName: "jolokiaPassword" secretPath: "" secretKey: "" - objectName: "jmxUsername" secretPath: "" secretKey: "" - objectName: "jmxPassword" secretPath: "" secretKey: ""
- 将
SecretProviderClass
应用于您的apigee
和apigee-system
命名空间。在以下命令中,命名空间为apigee
和apigee-system
。如果您要使用不同的命名空间,请替换这些值:kubectl -n apigee apply -f spc.yaml
kubectl -n apigee-system apply -f spc.yaml
为 Cassandra 启用外部 Secret
- 在
overrides.yaml
中添加以下配置,以便为 Cassandra 启用外部 Secret:cassandra: auth: secretProviderClass: apigee-cassandra-auth-spc # The name of the SecretProviderClass created in spc.yaml.
- 使用
helm upgrade
将更改应用于apigee-operator
和apigee-datastore
组件:apigee-operator
中的数据存储区控制器参与区域扩展期间的 Cassandra 停用和数据复制。这些任务需要 JMX 和 Jolokia 凭据。helm upgrade operator apigee-operator/ \ --namespace apigee-system \ --atomic \ -f overrides.yaml
apigee-datastore
提供在连接到 Cassandra 时,apigee-runtime
、Synchronizer 和 MART 等下游组件使用的凭据。helm upgrade datastore apigee-datastore/ \ --namespace apigee \ --atomic \ -f overrides.yaml
-
验证是否使用了外部 Secret。启用外部 Secret 后,系统会添加引用这些 Secret 的新
Volume
、Volume Mount
和Environment Variable
。- 验证
apigee-controller-manager
Deployment。检查是否存在名为
apigee-external-secrets
且引用上面创建的SecretProviderClass
的Volume
:kubectl -n apigee-system get deployment apigee-controller-manager -o jsonpath='{.spec.template.spec.volumes[?(@.name=="apigee-external-secrets")]}' { "csi": { "driver": "secrets-store.csi.k8s.io", "readOnly": true, "volumeAttributes": { "secretProviderClass": "apigee-cassandra-auth-spc" } }, "name": "apigee-external-secrets" }
检查名为
apigee-external-secrets
的VolumeMount
是否存在:kubectl -n apigee-system get deployment apigee-controller-manager -o jsonpath='{.spec.template.spec.containers[?(@.name=="manager")].volumeMounts[?(@.name=="apigee-external-secrets")]}' { "mountPath": "/opt/apigee/externalsecrets", "name": "apigee-external-secrets", "readOnly": true }
检查是否存在引用外部 Secret 的
Environment Variable
:kubectl -n apigee-system get deployment apigee-controller-manager -o jsonpath='{.spec.template.spec.containers[?(@.name=="manager")].env}' [ ... { "name": "CASSANDRA_JOLOKIA_USERNAME_PATH", "value": "/opt/apigee/externalsecrets/jolokiaUsername" }, { "name": "CASSANDRA_JOLOKIA_PASSWORD_PATH", "value": "/opt/apigee/externalsecrets/jolokiaPassword" } ]
- 验证
回滚到 K8s Secret
- 如需还原为非外部 Secret,请移除
overrides.yaml
中的secretProviderClass
配置并使用先前的配置:cassandra: auth: secretProviderClass: apigee-cassandra-auth-spc # remove this line
- 使用
helm upgrade
将更改应用于apigee-operator
和apigee-datastore
组件:helm upgrade operator apigee-operator/ \ --namespace apigee-system \ --atomic \ -f overrides.yaml
helm upgrade datastore apigee-datastore/ \ --namespace apigee \ --atomic \ -f overrides.yaml
问题排查:创建用于调试的客户端容器
如果您使用的是 Vault,则本部分将取代问题排查部分创建用于调试的客户端容器中的说明。
本部分介绍如何创建客户端容器,您可从中访问 Cassandra 调试实用程序(如 cqlsh
)。这些实用程序可让您查询 Cassandra 表,并且可用于调试。
创建客户端容器
如需创建客户端容器,请按以下步骤操作:
- 容器使用
apigee-cassandra-user-setup
Pod 中的 TLS 证书。第一步是提取此证书的名称:kubectl get secrets -n apigee --field-selector type=kubernetes.io/tls | grep apigee-cassandra-user-setup | awk '{print $1}'
此命令返回证书名称。例如:
apigee-cassandra-user-setup-rg-hybrid-b7d3b9c-tls
。 - 打开一个新文件,并将以下 pod 规范粘贴到其中:
apiVersion: v1 kind: Pod metadata: labels: name: CASSANDRA_CLIENT_NAME # For example: my-cassandra-client namespace: apigee spec: containers: - name: CASSANDRA_CLIENT_NAME image: "gcr.io/apigee-release/hybrid/apigee-hybrid-cassandra-client:1.12.1" imagePullPolicy: Always command: - sleep - "3600" env: - name: CASSANDRA_SEEDS value: apigee-cassandra-default.apigee.svc.cluster.local - name: APIGEE_DML_USERNAME_PATH value: /opt/apigee/externalsecrets/dmlUsername - name: APIGEE_DML_PASSWORD_PATH value: /opt/apigee/externalsecrets/dmlPassword volumeMounts: - mountPath: /opt/apigee/ssl name: tls-volume readOnly: true - name: apigee-external-secrets mountPath: /opt/apigee/externalsecrets readOnly: true volumes: - name: tls-volume secret: defaultMode: 420 secretName: apigee-cassandra-user-setup-vaibhavhybridor-8b3e61d-tls - name: apigee-external-secrets csi: driver: secrets-store.csi.k8s.io readOnly: true volumeAttributes: secretProviderClass: apigee-cass-password serviceAccount: apigee-cassandra-default serviceAccountName: apigee-cassandra-default restartPolicy: Never
- 使用
.yaml
扩展名保存文件。例如:my-spec.yaml
。 - 将此规范应用于您的集群:
kubectl apply -f my-spec.yaml -n apigee
- 登录容器:
kubectl exec -n CASSANDRA_CLIENT_NAME -it -- bash
- 使用以下命令连接到 Cassandra
cqlsh
接口。输入与以下内容完全一致的命令:APIGEE_DML_USER=$(cat "$APIGEE_DML_USERNAME_PATH")
export APIGEE_DML_USER
APIGEE_DML_PASSWORD=$(cat "$APIGEE_DML_PASSNAME_PATH")
export APIGEE_DML_PASSWORD
cqlsh ${CASSANDRA_SEEDS} -u ${APIGEE_DML_USER} -p ${APIGEE_DML_PASSWORD} --ssl
删除客户端 pod
使用以下命令删除 Cassandra 客户端 pod:
kubectl delete pods -n apigee cassandra-client