引言

在容器编排系统中,保护和管理敏感信息,如密码、API 密钥等,至关重要。Kubernetes 提供了 Secrets 这一强大工具,以安全、集中和可控的方式处理敏感信息。本文将深入探讨 Kubernetes Secrets 的原理、优点、不足、创建、更新、使用,以及一些实战建议。

Secrets 原理

  • Secrets 以 base64 编码的形式存储敏感信息,如密码、API 密钥等。
  • 存储在 etcd 中,但会经过一层 base64 编码,提高了信息的安全性。

优点

  • 安全性提升:通过 base64 编码和集中管理,提高了对敏感信息的保护。
  • 集中管理:敏感信息集中存储,方便管理和更新。
  • 版本控制:可以与 Pod 特定版本关联,实现精确控制和追踪访问权限。

不足

  • 有限的安全性:base64 编码提供的是一种简单的混淆,而不是真正的加密。
  • 权限管理简单:相对较简单的权限管理可能不足以满足某些场景的需求。

创建和更新 Secrets

从文字创建 Secrets

kubectl create secret generic db-credentials \
  --from-literal=username=myuser \
  --from-literal=password=mypassword

从文件创建 Secrets

假设 secrets.txt 文件包含如下内容:

username=myuser
password=mypassword
kubectl create secret generic db-credentials --from-file=secrets.txt

直接更新 Secrets(例子仅为演示,不建议在生产环境中直接更新)

kubectl create secret generic db-credentials \
  --from-literal=username=newuser \
  --from-literal=password=newpassword \
  --dry-run=client -o yaml | kubectl apply -f -

通过文件更新 Secrets

假设 secrets_updated.txt 文件包含如下内容:

username=newuser
password=newpassword
kubectl create secret generic db-credentials --from-file=secrets_updated.txt --dry-run=client -o yaml | kubectl apply -f -

使用 Secrets

在 Pod 中使用 Secrets

深入讨论了在 Pod 配置文件中如何引用 Secrets,并使用 valueFromsecretKeyRef 从 Secrets 中获取敏感信息。例如,在 Pod 中使用上述的数据库凭据 Secret:

apiVersion: v1
kind: Pod
metadata:
  name: mypod
spec:
  containers:
  - name: mycontainer
    image: myimage
    env:
    - name: DB_USERNAME
      valueFrom:
        secretKeyRef:
          name: db-credentials
          key: username
    - name: DB_PASSWORD
      valueFrom:
        secretKeyRef:
          name: db-credentials
          key: password

深入讨论了在 Pod 配置文件中如何引用 Secrets,并使用 valueFromsecretKeyRef 从 Secrets 中获取敏感信息。以下是在 Java、Python 和 Node.js 应用程序中读取配置的例子:

Java 应用程序

import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.Base64;

public class MyApp {
    public static void main(String[] args) throws Exception {
        // 从 Secrets 中读取数据库凭据
        String usernameSecret = System.getenv("DB_USERNAME");
        String passwordSecret = System.getenv("DB_PASSWORD");

        // 解码 base64 编码的凭据
        String decodedUsername = new String(Base64.getDecoder().decode(usernameSecret));
        String decodedPassword = new String(Base64.getDecoder().decode(passwordSecret));

        // 使用凭据连接到数据库或执行其他敏感操作
        // ...
    }
}

Python 应用程序

import os
import base64

# 从 Secrets 中读取数据库凭据
username_secret = os.environ.get("DB_USERNAME")
password_secret = os.environ.get("DB_PASSWORD")

# 解码 base64 编码的凭据
decoded_username = base64.b64decode(username_secret).decode('utf-8')
decoded_password = base64.b64decode(password_secret).decode('utf-8')

# 使用凭据连接到数据库或执行其他敏感操作
# ...

Node.js 应用程序

const { DB_USERNAME, DB_PASSWORD } = process.env;

// 从 Secrets 中读取数据库凭据
const usernameSecret = DB_USERNAME;
const passwordSecret = DB_PASSWORD;

// 解码 base64 编码的凭据
const decodedUsername = Buffer.from(usernameSecret, 'base64').toString('utf-8');
const decodedPassword = Buffer.from(passwordSecret, 'base64').toString('utf-8');

// 使用凭据连接到数据库或执行其他敏感操作
// ...

这些例子展示了如何在不同语言的应用程序中读取 Kubernetes Secrets,并在应用程序中解码和使用这些敏感信息。通过这种方式,您可以确保敏感信息安全地传递到应用程序中。


实战建议

为读者提供一些建议,包括避免硬编码敏感信息、定期轮转敏感信息等最佳实践,以帮助他们更好地应用 Secrets 到实际生产环境。

清理和最佳实践

介绍如何安全地清理不再需要的 Secrets 和一些使用 Secrets 的最佳实践,以确保系统的稳健性和安全性。

  • 清理不再需要的 Secrets:
kubectl delete secret db-credentials
  • 定期轮转敏感信息:

定义一个自动化任务,例如 CronJob,定期创建新的 Secrets 并更新相关的应用程序,确保旧的凭据不再有效。例如,每月轮转一次数据库凭据:

apiVersion: batch/v1beta1
kind: CronJob
metadata:
  name: rotate-db-credentials
spec:
  schedule: "0 0 1 * *"
  jobTemplate:
    spec:
      template:
        spec:
          containers:
          - name: rotate
            image: rotate-image
            command: ["rotate-script.sh"]

结论

总结了 Kubernetes Secrets 的关键概念和实践,强调了在容器化环境中安全地管理敏感信息的重要性。通过本文,读者将更全面地了解如何有效地使用 Kubernetes Secrets,确保应用程序和系统的安全性和稳定性。