Kubernetes 配置管理与安全部署实践
1. 配置文件清理
在处理 Kubernetes 的 YAML 配置文件时,有些内容可以删除以简化配置。如果计划在多个命名空间使用配置,建议删除
metadata -> namespace
字段,这样能在当前命名空间部署配置,避免意外更新指定命名空间的对象。另外,
metadata
部分的
uid
、
resourceVersion
、
selfLink
、
creationTimestamp
以及整个
status
部分也可移除,这些字段在部署上下文之外意义不大,移除可避免版本控制中的混淆。
2. 以代码方式管理 Kubernetes 配置
将配置视为代码,提交到版本控制系统,就可以像处理代码一样对生产系统配置进行版本管理,例如查看版本历史、回滚提交。对于提交的配置,也应进行同行评审,因为配置对运行系统的影响与代码同样重要。
大的互联网公司常采用这种模式,如 Google 的多数服务在单个代码仓库中开发和部署,服务配置与代码相邻,代码和服务遵循相同的代码审查实践,但批准合并的工程师列表可能不同。不过,并非必须将配置和代码存于同一仓库,可根据自身工程实践调整。
这里介绍一种将 Kubernetes 配置存储在 Git 中的示例:使用单个 Git 仓库表示单个集群中部署的所有 Kubernetes 对象,仓库中为每个 Kubernetes 命名空间创建一个文件夹,文件夹中存放该命名空间对象的 YAML 文件。另一种选择是为每个命名空间使用单独的分支,能方便从测试环境到生产环境合并更改,但可能会导致混乱。
以下是示例目录布局:
/_debug # 存储所有开发者使用的调试脚本的目录
/_cluster # 集群配置,如命名空间配置文件,仅在集群创建时使用
/staging # 测试环境配置文件夹
/production # 生产环境配置文件夹
每个目录与一个 Kubernetes 命名空间映射,这种 1:1 的映射允许使用
kubectl apply -f .
命令将目录中的所有更改部署到活动命名空间,克隆环境只需复制整个文件夹并部署到新的命名空间。
工作流程如下:
1. 对部署环境的配置进行更改。
2. 提交这些更改。
3. 使用
kubectl
设置当前命名空间。
4. 在匹配的目录中运行
kubectl apply -f .
更新实时状态。
3. 安全部署配置
简单地检出仓库并运行
kubectl apply -f .
可能会导致将错误的配置部署到错误的命名空间,为避免这种情况,可以采取以下措施:
3.1 添加检查脚本
编写脚本检查当前命名空间是否与目录名匹配,以下是示例脚本:
# gitops_check.sh
#!/bin/bash
CURRENT_DIR=`echo "${PWD##*/}"`
CURRENT_NAMESPACE=`kubectl config view --minify -o=jsonpath='{.contexts[0].context.namespace}'`
if [ "$CURRENT_DIR" != "$CURRENT_NAMESPACE" ]; then
>&2 echo "Wrong namespace (currently $CURRENT_NAMESPACE but $CURRENT_DIR expected)"
exit 1
fi
exit 0
然后在其他脚本中使用该检查脚本,例如:
# rollout.sh
#!/bin/sh
if [ $(../gitops_check.sh; echo $?) != 0 ]; then exit 1; fi
kubectl apply -f .
要使这些脚本正常工作,确保配置文件中不直接指定
metadata -> namespace
字段。
3.2 使用部署管道
部署管道是基于代码仓库触发运行的一组函数,例如“当代码推送到配置仓库时,将配置部署到 Kubernetes 集群”。使用管道可确保部署的配置与提交的一致,如果操作员需要在部署后进行额外更改,在配置代码仓库中修改并推送代码,再次触发管道部署。
对于 GKE 用户,可使用 Cloud Build 实现部署管道,设置步骤如下:
1. 为 Cloud Build 服务账户配置 IAM 权限,使其能在 GKE 集群上操作。
2. 创建新的触发器,设置为在配置仓库推送时触发。
3. 在仓库中添加 Cloud Build 配置文件,并在触发器中引用。
以下是 Cloud Build 配置文件示例:
# cloudbuild-deploy.yaml
steps:
- name: 'gcr.io/cloud-builders/kubectl'
id: Deploy
args:
- 'apply'
- '-f'
- '$FOLDER'
env:
- 'CLOUDSDK_COMPUTE_ZONE=us-west1-a'
- 'CLOUDSDK_CONTAINER_CLUSTER=my-cluster'
3.3 使用 GitOps 操作员
使用 GitOps 操作员可进一步改进部署方法,如 Flux。它是运行在集群中的代码循环,持续使集群中运行的配置与配置仓库中的配置一致,相比部署管道,能在出现差异时进行额外的协调。
4. 管理 Kubernetes 中的秘密数据
在 Kubernetes 中,有些敏感数据如数据库密码和 API 密钥等不适合直接存储在代码仓库中,Kubernetes 提供了
Secrets
对象来安全地存储这些秘密数据。
4.1 字符串类型的秘密数据
如果你之前在部署配置中使用明文环境变量来存储密码等秘密数据,现在可以将其迁移到
Secrets
对象中。例如,有一个值为
secret_value
的秘密数据,可将其封装到一个 Kubernetes
Secret
对象中:
# StringSecrets/secret.yaml
apiVersion: v1
kind: Secret
metadata:
name: secrets-production
type: Opaque
stringData:
SECRET_KEY: secret_value
ANOTHER_KEY: another_secret_value
Secrets
可以通过两种方式提供给 Pod:作为文件或作为环境变量。对于简单的字符串类型的秘密数据,通常使用环境变量的方式。以下示例展示了如何在 Deployment 中使用
Secrets
作为环境变量:
# StringSecrets/deploy.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: timeserver
spec:
replicas: 1
selector:
matchLabels:
pod: timeserver-pod
template:
metadata:
labels:
pod: timeserver-pod
spec:
containers:
- name: timeserver-container
image: docker.io/wdenniss/timeserver:4
env:
- name: AVATAR_ENDPOINT # 普通的非秘密环境变量
value: http://robohash-internal
- name: SECRET_KEY # 从 Secret 中获取值的环境变量
valueFrom:
secretKeyRef:
name: secrets-production
key: SECRET_KEY
要验证配置是否生效,可以创建 Deployment 和 Secret,然后通过以下命令查看 Pod 中的环境变量:
$ kubectl get pods
$ kubectl exec <POD_NAME> -- env
你应该能在输出中看到
SECRET_KEY=secret_value
。
4.2 Base64 编码的秘密数据
在编写本文时,Kubernetes 文档和其他资料中经常展示使用 Base64 编码的秘密数据(使用
data
键而非
stringData
)。这并非为了安全(Base64 是编码而非加密),而是为了表示在 YAML 中不兼容的数据。
以下是之前示例的 Base64 编码表示:
# Base64Secrets/secret-base64.yaml
apiVersion: v1
kind: Secret
metadata:
name: secrets-production
type: Opaque
data:
SECRET_KEY: c2VjcmV0X3ZhbHVlCg==
在任何 *nix 系统上,可以使用以下命令进行 Base64 编码和解码:
$ echo "secret_value" | base64
c2VjcmV0X3ZhbHVlCg==
$ echo "c2VjcmV0X3ZhbHVlCg==" | base64 -D
secret_value
可以在同一个配置文件中同时包含
data
和
stringData
,也可以在每个 Kubernetes
Secret
对象中存储多个秘密数据。以下是一个包含多个秘密数据的示例:
# Base64Secrets/secrets-multiple.yaml
apiVersion: v1
kind: Secret
metadata:
name: secrets-production
type: Opaque
stringData:
SECRET_KEY: secret_value
ANOTHER_KEY: another_value
data:
ENCODED_KEY: VGhpcyBzdHJpbmcKbWlnaHQgYmUgaGFyZCB0byByZXByZXNlbnQgaW4gWUFNTCDwn5iFCg==
从服务器检索的秘密数据是以 Base64 编码存储的,需要进行解码才能获取明文值。
4.3 文件类型的秘密数据
有时候,你可能需要将秘密数据以文件的形式提供给应用程序。Kubernetes 同样支持这种场景。
例如,有一个私钥文件,可将其存储在
Secrets
中。以下是使用 YAML 表示私钥文件的示例:
# FileSecrets/secret_file.yaml
apiVersion: v1
kind: Secret
metadata:
name: secret-files
type: Opaque
stringData:
example.key: |
-----BEGIN RSA PRIVATE KEY-----
MIGsAgEAAiEA4TneQFg/UMsVGrAvsm1wkonC/5jX+ykJAMeNffnlPQkCAwEAAQIh
ANgcs+MgClkXFQAP0SSvmJRmnRze3+zgUbN+u+rrYNRlAhEA+K0ghKRgKlzVnOxw
qltgTwIRAOfb8LCVNf6FAdD+bJGwHycCED6YzfO1sONZBQiAWAf6Am8CEQDIEXI8
fVSNHmp108UNZcNLAhEA3hHFV5jZppEHHHLy4F9Dnw==
-----END RSA PRIVATE KEY-----
如果你觉得处理 YAML 语法比较繁琐,也可以使用 Base64 编码文件数据:
# FileSecrets/secret_file_base64.yaml
apiVersion: v1
kind: Secret
metadata:
name: secret-files
type: Opaque
data:
example.key: LS0tLS1CRUdJTiBSU0EgU...SBLRVktLS0tLQo=
使用
kubectl
可以更自动化地创建
Secrets
文件:
$ kubectl create secret generic secret-files --from-file=example.key=./example.key --dry-run=client -o yaml
--dry-run=client -o yaml
表示不会实际在服务器上创建
Secret
,而是将其输出为 YAML 格式,方便你将其保存到配置文件中,后续使用
kubectl apply -f filename.yaml
应用到服务器。
创建
Secrets
后,可以将其挂载到指定的文件夹中。以下示例将
secret-files
挂载到
/etc/config
文件夹:
# 挂载 Secret 到指定文件夹的示例配置
# 这里省略了 Deployment 等其他部分,仅展示挂载 Secret 的关键部分
spec:
containers:
- name: my-container
volumeMounts:
- name: secret-volume
mountPath: /etc/config
volumes:
- name: secret-volume
secret:
secretName: secret-files
总结
通过以上方法,你可以更安全、高效地管理 Kubernetes 中的配置和秘密数据。在配置管理方面,采用配置即代码的方式,结合部署管道和 GitOps 操作员,确保部署的配置与代码仓库中的一致。在秘密数据管理方面,利用 Kubernetes 的
Secrets
对象,将敏感数据与配置分离,避免数据泄露风险。同时,根据不同类型的秘密数据(字符串、Base64 编码、文件),选择合适的存储和使用方式。
流程图
graph LR
classDef process fill:#E5F6FF,stroke:#73A6FF,stroke-width:2px;
A(对部署环境配置更改):::process --> B(提交更改):::process
B --> C(使用 kubectl 设置当前命名空间):::process
C --> D(运行 kubectl apply -f . 更新实时状态):::process
D --> E{是否有额外更改}:::process
E -->|是| F(在配置代码仓库修改并推送):::process
F --> D
E -->|否| G(部署完成):::process
表格
| 管理方面 | 方法 | 描述 |
|---|---|---|
| 配置管理 | 配置即代码 | 将配置提交到版本控制系统,进行版本管理和同行评审 |
| 配置管理 | 部署管道 | 基于代码仓库触发,确保部署配置与提交一致 |
| 配置管理 | GitOps 操作员 | 持续协调集群与仓库配置,处理差异 |
| 秘密数据管理 | 字符串类型 | 将明文秘密数据封装到 Secret 对象,通过环境变量使用 |
| 秘密数据管理 | Base64 编码 | 处理在 YAML 中不兼容的数据,需解码获取明文 |
| 秘密数据管理 | 文件类型 | 将秘密文件存储在 Secret 中,挂载到指定文件夹 |
超级会员免费看
1200

被折叠的 条评论
为什么被折叠?



