告别硬编码:手把手教你用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 的访问权限。
相关推荐
岚天start40 分钟前
K8S中,kubectl cordon、uncordon、drain、taint的区别
云原生·容器·kubernetes·cordon·uncordon·taint·drain
程序员二黑3 小时前
(Python) vs (Java) vs(javaScript) 谁才是自动化测试的最佳拍档
单元测试·测试·ab测试
得物技术3 小时前
AI质量专项报告自动分析生成|得物技术
openai·测试
昌sit!5 小时前
k8s基本概念
云原生·容器·kubernetes
斯普信专业组6 小时前
Kubernetes部署apisix的理论与最佳实践(四)
云原生·容器·kubernetes
阿波罗尼亚14 小时前
容器 K8S Docker Kata 学习(一)
docker·容器·kubernetes
代码老y1 天前
从裸机到云原生:Linux 操作系统实战进阶的“四维跃迁”
linux·运维·云原生
TG_yunshuguoji1 天前
华为云数据仓库服务核心优势指南
数据仓库·云原生·华为云·数据库服务
池以遇1 天前
云原生高级——nginx
运维·nginx·云原生