告别硬编码:手把手教你用Secrets保护CronJob的阿里云AK/SK

前言

Kubernetes CronJob 详解:配置、原理与实践指南这篇文章中,我 将监控服务费用以及 ssl 证书的脚本部署在 k8s 中,但有一个问题,脚本中需要使用到阿里云的 AK/SK,目前是硬编码到脚本中的, 为了安全起见,我计划将 AK/SK 配置在 k8s 的 secret 中。

Secret 基础概念

为什么需要 Secret

将敏感数据直接写在容器镜像或配置文件中存在严重的安全风险。 Kubernetes 提供的 Secret 资源就是为解决这个问题而设计的。

Secret 是什么?

Secret 是 Kubernetes 中专门用于存储敏感数据的资源对象,特点包括:

  • 数据以 Base64 编码存储(注意:这不是加密!)
  • 支持多种数据类型(Opaque、docker-registry、TLS 等)
  • 可以通过卷挂载或环境变量注入到 Pod 中

Secret 与 ConfigMap 的区别

特性 Secret ConfigMap
数据类型 敏感信息 普通配置
存储方式 Base64 编码 明文
典型用途 密码、密钥 应用配置

创建 Secret 的多种方式

方法一: 通过 kubectl 命令行创建

从字面值创建:

ini 复制代码
kubectl create secret generic my-secret \
  --from-literal=username=my-user \
  --from-literal=password=my-password

这将创建一个名为 my-secret 的 Secret,其中包含两个键值对:username 和 password。

从文件创建:

ini 复制代码
kubectl create secret generic tls-cert \
  --from-file=tls.crt=./server.crt \
  --from-file=tls.key=./server.key

这将使用文件中的内容创建一个名为 tls-cert 的 Secret。

方法二:通过 YAML 文件定义

通过创建一个 YAML 文件来定义 Secret,然后使用 kubectl apply 或 kubectl create 命令来创建

yaml 复制代码
apiVersion: v1
kind: Secret
metadata:
  name: my-secret
type: Opaque
data:
  username: bXktdXNlcg==  # Base64 编码的 username
  password: bXktcGFzc3dvcmQ=  # Base64 编码的 password

username 和 password 值是通过 base64 编码的。

你可以使用 echo -n "bXktdXNlcg==" | base64 来获取 base64 编码的值。

恢复成原始值:

bash 复制代码
echo -n "bXktdXNlcg==" | base64 --decode

Secret 的使用方式

方式一:作为环境变量注入

将这些 Secret 值注入到容器的环境变量中

yaml 复制代码
containers:
- name: myapp
  image: myapp:latest
  env:
    - name: USERNAME
      valueFrom:
        secretKeyRef:
          name: my-secret
          key: username
    - name: PASSWORD
      valueFrom:
        secretKeyRef:
          name: my-secret
          key: password

这样,Pod 中的容器将会通过 Secret 中的 username 和 password 创建环境变量 USERNAME 和 PASSWORD。

方式二: 作为文件挂载

可以将 Secret 挂载到容器中的某个目录,容器可以通过文件访问 Secret 的内容。

yaml 复制代码
apiVersion: v1
kind: Pod
metadata:
  name: mypod
spec:
  containers:
    - name: mycontainer
      image: myimage
      volumeMounts:
        - name: secret-volume
          mountPath: /etc/secrets
          readOnly: true
  volumes:
    - name: secret-volume
      secret:
        secretName: my-secret

my-secret 被挂载到容器的 /etc/secrets 目录下。 容器内将可以通过文件访问这些 Secret 的值(例如 /etc/secrets/username 和 /etc/secrets/password)。

方式三:拉取私有镜像的 Secret

存储 Docker registry 的凭据,可以使用 Secret 来存储 Docker 配置文件。

ini 复制代码
kubectl create secret docker-registry my-registry-secret \
  --docker-server=my-docker-server.com \
  --docker-username=my-username \
  --docker-password=my-password \
  --docker-email=my-email@example.com

可以在 Kubernetes 配置中使用该 Secret 来拉取镜像:

yaml 复制代码
apiVersion: v1
kind: Pod
metadata:
  name: mypod
spec:
  imagePullSecrets:
    - name: my-registry-secret
  containers:
    - name: mycontainer
      image: my-docker-server.com/myimage

这个配置中,Pod 使用 my-registry-secret 来从私有 Docker registry 拉取镜像。

方式四:使用 Secret 存储 TLS 证书

可以将 TLS 证书和密钥存储在 Secret 中,并在 Pod 中使用它们。

创建 TLS 证书 Secret:

css 复制代码
kubectl create secret tls my-tls-secret \
  --cert=/path/to/cert.crt \
  --key=/path/to/cert.key

挂载到 Pod 中:

yaml 复制代码
apiVersion: v1
kind: Pod
metadata:
  name: mypod
spec:
  containers:
    - name: mycontainer
      image: myimage
      volumeMounts:
        - name: tls-volume
          mountPath: /etc/tls
          readOnly: true
  volumes:
    - name: tls-volume
      secret:
        secretName: my-tls-secret

这个配置中,Pod 将 my-tls-secret 挂载到 /etc/tls 目录下,容器可以使用证书和密钥文件。

Secret 的类型

实际案例:安全使用阿里云 AK/SK

场景

前言中有提到,需要在一个监控 Pod 中使用阿里云访问凭证,但不希望将 AK/SK 硬编码。

解决方案

  1. 在K8s集群中创建存储密钥的Secret:
ini 复制代码
kubectl create secret generic aliyun-credentials --namespace=kube-ops \
  --from-literal=access_key_id='AK123456' \
  --from-literal=access_key_secret='SK789012'
  1. 修改CronJob配置,配置CronJob引用Secret:
yaml 复制代码
apiVersion: batch/v1
kind: CronJob
metadata:
   namespace: kube-ops
   name: serverguard-job
spec:
   schedule: "0 10 * * *"
   concurrencyPolicy: Forbid
   startingDeadlineSeconds: 60
   successfulJobsHistoryLimit: 1
   failedJobsHistoryLimit: 1
   jobTemplate:
      spec:
         template:
            spec:
               containers:
                  - name: serverguard
                    image: /server-guard:latest
                    imagePullPolicy: Always
                    env:
                       - name: ALIYUN_ACCESS_KEY_ID
                         valueFrom:
                            secretKeyRef:
                               name: aliyun-credentials
                               key: access_key_id
                       - name: ALIYUN_ACCESS_KEY_SECRET
                         valueFrom:
                            secretKeyRef:
                               name: aliyun-credentials
                               key: access_key_secret
               restartPolicy: OnFailure
         ttlSecondsAfterFinished: 100
  1. 修改代码读取环境变量
ini 复制代码
import os  # 添加os模块导入
# ... 其他现有导入保持不变 ...


class Secret(NamedTuple):
    access_key_id: str
    access_key_secret: str


# 从环境变量读取密钥,移除硬编码
secret = Secret(
    access_key_id=os.environ.get('ALIYUN_ACCESS_KEY_ID'),
    access_key_secret=os.environ.get('ALIYUN_ACCESS_KEY_SECRET')
)


# ... 后续代码保持不变 ...
  1. 检查CronJob是否正常运行 手动创建job测试:
ini 复制代码
kubectl create job test-job --from=cronjob/serverguard-job -n kube-ops

这个命令是用来基于一个已经存在的 CronJob 创建一个 Job,用是从名为 serverguard-job 的 CronJob 中提取任务配置, 并在 kube-ops 命名空间中创建一个新的 Job,任务将立即执行一次,而不是定期运行。方便测试。

最后

到这里就告别了硬编码,使用 Kubernetes Secret 存储敏感数据,那现在有一个疑问,Secret 真的安全吗?

我们知道,Secret 的内容通常是以 Base64 编码存储的,因此它不能有效地防止恶意用户获取敏感数据。 如果攻击者有权限访问 Kubernetes 集群中的资源,他们可以轻松解码 Base64 编码的数据。

为了增加 Secret 的安全性,建议采取以下措施:

  • 启用 etcd 加密:确保 etcd 集群中的数据以加密形式存储,防止未经授权的访问。
  • 启用 RBAC 控制:通过 Role-Based Access Control(RBAC)机制,限制对 Secret 的访问权限,仅授权必要的用户或服务账号。
  • 实施严格的访问控制:确保只有授权的用户或服务账号才能访问 Secret,避免泄露敏感信息。 下一篇文章,就来探索如何使用 RBAC 控制 Secret 的访问权限。
相关推荐
自律懒人11 小时前
AI应用从原型到上线的最后一公里——灵光闪应用一键部署深度实测,30+免费API + Serverless零配置发布
人工智能·云原生·开源·serverless
风曦Kisaki12 小时前
Kubernetes(K8s)笔记Day03: Pod命名空间,标签,Pod 的调度,污点与容忍度,Pod 常见状态和重启策略,Pod 生命周期
linux·运维·笔记·docker·云原生·容器·kubernetes
张忠琳12 小时前
【NVIDIA】NVIDIA k8s-device-plugin v0.19.3 资源管理器模块深度分析之三
云原生·容器·架构·kubernetes·nvidia
Chengbei1114 小时前
云安全漏洞挖掘SKILL、一站式云漏洞挖掘工具,支持S3爆破、IMDS探测、K8s检测与AK/SK权限利用
前端·人工智能·网络安全·云原生·容器·kubernetes·系统安全
宋均浩16 小时前
# 测试工程师学 K8s:一份"最小必要知识"清单,附学习路线
测试
瞬间&永恒~16 小时前
【MySQL】练习5-1:配置慢查询日志
linux·运维·云原生
张忠琳16 小时前
【NVIDIA】k8s-device-plugin v0.19.3 — CDI / MIG / vGPU 模块超深度代码分析之五
云原生·容器·架构·kubernetes·nvidia
snow@li17 小时前
命名规范:企业级微服务模块前缀命名规范全景梳理
微服务·云原生·架构
逻极17 小时前
C# 从入门到精通:现代云原生与AI应用开发实战
ai·云原生·c#·.net
AINative软件工程17 小时前
LLM 应用的 Eval 数据工程实践:Golden Set 构建、版本管理与生产 Trace 回放
llm·测试·前端工程化