K3s 如何配置 etcd S3 快照的凭据 Secret,避免把凭据写在命令行与 systemd 中
【免费下载链接】k3sLightweight Kubernetes项目地址: https://gitcode.com/GitHub_Trending/k3/k3s
当 k3s server 使用内置 etcd 并把快照备份到 S3 兼容存储时,S3 的 access key、secret key、endpoint 等信息按默认方式只能写在k3s server的命令行参数、配置文件或 systemd unit 的环境变量里(--etcd-s3-access-key等参数支持AWS_ACCESS_KEY_ID、AWS_SECRET_ACCESS_KEY、AWS_SESSION_TOKEN环境变量回退)。这些位置对登录用户和备份工具都可见,凭据轮换也不方便——K3s 只在启动时重新加载配置。K3s 提供了--etcd-s3-config-secret参数:把整套 S3 快照配置放进kube-system命名空间下的一个 Secret,服务端在每次执行快照操作时按需读取。本文基于 K3s 仓库中的设计文档 docs/adrs/etcd-s3-secret.md、实现代码 pkg/etcd/s3/config_secret.go、pkg/etcd/s3/s3.go 以及 e2e 测试 tests/e2e/s3/s3_test.go、tests/e2e/s3/Vagrantfile,给出完整的配置与验证步骤。
适用前提:一个已经以 etcd 角色启动的 k3s server(--cluster-init),需要把 etcd 快照备份到 S3 兼容服务端点。Secret 方法只覆盖快照的保存操作(on-demand 与定时),不覆盖恢复,这一点后文会展开。
先弄清两条规则,避免配完不生效
在动手之前,设计文档明确了两条最容易踩坑的规则:
--etcd-s3-config-secret不等于开启 S3 备份。必须同时用--etcd-s3启用 S3,否则 Secret 不会被读取。- Secret 与 CLI/配置文件中的 S3 参数不合并。只要有任何其他 etcd-s3 参数来自命令行或配置文件,Secret 中设置的全部字段都会被忽略,服务端日志会输出告警:
Ignoring s3 configuration from etcd-s3-config-secret %q due to existing configuration from CLI or config file所以正确的做法是:服务端配置里只出现etcd-s3: true和etcd-s3-config-secret: <Secret 名>两项,其余 S3 字段全部放进 Secret。这两个参数本身不含凭据,可以放心写在 systemd unit、/etc/rancher/k3s/k3s.yaml或 config file 里。
另外一条好消息:Secret不需要在 K3s 启动时存在,它是在每次执行快照操作时才被检查的。这意味着更换凭据时只需更新 Secret,不必重启 server。
步骤一:在 kube-system 命名空间创建配置 Secret
Secret 的字段名与k3s server的 CLI flag / 配置文件键名一致(见 pkg/cli/cmds/server.go 中各etcd-s3-*flag 定义)。设计文档给出的示例如下:
apiVersion: v1 kind: Secret metadata: name: k3s-etcd-snapshot-s3-config namespace: kube-system stringData: etcd-s3-endpoint: "" etcd-s3-endpoint-ca: "" etcd-s3-endpoint-ca-name: "" etcd-s3-skip-ssl-verify: "false" etcd-s3-access-key: "AWS_ACCESS_KEY_ID" etcd-s3-secret-key: "AWS_SECRET_ACCESS_KEY" etcd-s3-bucket: "bucket" etcd-s3-folder: "folder" etcd-s3-region: "us-east-1" etcd-s3-insecure: "false" etcd-s3-timeout: "5m" etcd-s3-proxy: ""(以上为设计文档中的示例,etcd-s3-access-key/etcd-s3-secret-key等值需要替换为你的真实凭据。)
实际创建时可以直接用kubectl。下面是 e2e 测试中真实执行的命令(值为测试环境的 mock S3 值,endpoint、bucket、access key 请替换为你自己的 S3 配置):
k3s kubectl create secret generic k3s-etcd-s3-config --namespace=kube-system \ --from-literal=etcd-s3-insecure=true \ --from-literal=etcd-s3-bucket=test-bucket \ --from-literal=etcd-s3-folder=test-folder \ --from-literal=etcd-s3-endpoint=localhost:9090 \ --from-literal=etcd-s3-skip-ssl-verify=true \ --from-literal=etcd-s3-access-key=test \ --from-literal=etcd-s3-retention=1成功时输出(e2e 测试断言内容):
secret/k3s-etcd-s3-config created各字段含义以 flag 的 Usage 描述为准,例如etcd-s3-endpoint是 "S3 endpoint url",etcd-s3-bucket是 "S3 bucket name",etcd-s3-proxy是 "Proxy server to use when connecting to S3, overriding any proxy-releated environment variables"。除文档示例列出的字段外,实现代码 pkg/etcd/s3/config_secret.go 还会读取etcd-s3-secret-key、etcd-s3-session-token、etcd-s3-region、etcd-s3-retention、etcd-s3-bucket-lookup-type。
关于 CA 证书有两个可选写法(来自设计文档):
etcd-s3-endpoint-ca:填入内联的 PEM 编码 CA bundle,而不是文件路径;etcd-s3-endpoint-ca-name:填入kube-system命名空间下一个 ConfigMap 的名字,该 ConfigMap 的data/binaryData中可包含一个或多个 CA bundle。两个来源找到的所有有效 CA bundle 都会被加载。
Secret 创建完成后,用下面命令确认它落在正确的命名空间:
k3s kubectl get secret k3s-etcd-s3-config -n kube-system步骤二:在 server 端只配置两个参数
在 k3s server 的启动参数或配置文件中加上etcd-s3和etcd-s3-config-secret。e2e 测试的 tests/e2e/s3/Vagrantfile 中,server 的配置文件(即 systemd 安装时对应的/etc/rancher/k3s/k3s.yaml)是这样写的:
etcd-s3: true etcd-s3-config-secret: k3s-etcd-s3-config etcd-snapshot-schedule-cron: '*/1 * * * *' etcd-snapshot-retention: 2要点:
etcd-s3: true启用 S3 备份;etcd-s3-config-secret只带 Secret 的名字,不含任何凭据,可以安全地留在 systemd unit 或配置文件中。- 示例里的
etcd-snapshot-schedule-cron让定时快照也走这条路径——设计文档明确 Secret 会用于 on-demand 和 scheduled 两类快照保存操作。 - 除了这两项外,不要再在命令行或配置文件里写任何
etcd-s3-*凭据类参数,否则整个 Secret 会被忽略(见前面的第二条规则)。
步骤三:触发快照并验证
在 server 节点上手动触发一次快照。k3s etcd-snapshot save默认会读取 server 的配置文件,因此不需要在命令行重复传入 S3 参数:
k3s etcd-snapshot savee2e 测试断言成功输出包含Snapshot on-demand-server-0(其中server-0是该测试集群的节点名,你的节点名会不同)。
再用 list 确认快照同时存在于本地目录和 S3:
k3s etcd-snapshot liste2e 测试对输出的断言(示例值):
file:///var/lib/rancher/k3s/server/db/snapshots/on-demand-server-0 s3://test-bucket/test-folder/on-demand-server-0file://行是本地快照,s3://bucket/folder/快照名行说明 S3 端也上传成功了。
还可以在 server 日志中确认配置确实来自 Secret,pkg/etcd/s3/s3.go 中GetClient命中 Secret 路径时会记录:
Using etcd s3 configuration from etcd-s3-config-secret "k3s-etcd-s3-config"排查:Secret 未生效时的日志判读
| 现象 | 日志/错误 | 说明 |
|---|---|---|
| Secret 不存在或读不到 | failed to get config from etcd-s3-config-secret "<名字>"(内含failed to get etcd S3 config secret: ...) | 检查 Secret 是否在kube-system命名空间、名字是否拼写正确;Secret 不存在会导致当次快照操作失败 |
| Secret 被整体忽略 | Ignoring s3 configuration from etcd-s3-config-secret "<名字>" due to existing configuration from CLI or config file | 命令行或配置文件里还残留了其他etcd-s3-*参数,全部清掉,只保留etcd-s3与etcd-s3-config-secret |
| 某个字段值非法 | Failed to parse etcd-s3-timeout value from S3 config secret <名字>: ...(etcd-s3-skip-ssl-verify、etcd-s3-insecure、etcd-s3-retention同理) | 该字段解析失败时只打 warning 并沿用默认值,快照仍会继续,需要回 Secret 里修正该字段的格式(如5m这样的 duration) |
边界与限制
- 恢复(restore)不使用 Secret。设计文档明确:Secret 只用于 on-demand 和定时快照保存;恢复流程发生在 Secret 不可用的阶段,需要从 S3 取快照时必须通过环境变量或 CLI flag 传入相应配置。如果你的流程包含"从 S3 恢复 etcd",这部分凭据仍需按传统方式临时提供,不要指望 Secret 覆盖。
- Secret 按操作时点检查。启动时 Secret 不存在不会阻止 server 启动,快照操作执行时才读取;这也意味着删除或改坏 Secret 只影响下一次快照操作,而不影响正在运行的集群。
- 进程参数隐藏是另一层保护。pkg/cli/etcdsnapshot/etcd_snapshot.go 中
commandSetup会把etcd-snapshot命令的进程标题改写,注释说明原因是"进程参数可能包含数据库凭据或其他机密"。即使你在 CLI 上临时传了凭据类参数,ps输出中也不会暴露完整参数列表。
完成以上配置后,判定标准是:systemd unit 与配置文件中只剩etcd-s3与etcd-s3-config-secret两个无凭据参数,k3s etcd-snapshot save成功且k3s etcd-snapshot list出现s3://条目,server 日志出现Using etcd s3 configuration from etcd-s3-config-secret。之后轮换凭据只需更新kube-system下的 Secret,无需重启 server。
【免费下载链接】k3sLightweight Kubernetes项目地址: https://gitcode.com/GitHub_Trending/k3/k3s
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考