引言
在容器编排系统中,保护和管理敏感信息,如密码、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,并使用 valueFrom
和 secretKeyRef
从 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,并使用 valueFrom
和 secretKeyRef
从 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,确保应用程序和系统的安全性和稳定性。