kubernetes 核心技术-Secret

139 阅读5分钟

在现代分布式系统中,安全地管理和使用敏感信息(如密码、API 密钥、证书等)至关重要。Kubernetes 提供了 Secret 资源来帮助我们实现这一点。Secret 允许将这些敏感数据以加密形式存储,并仅在需要时解密和传递给容器使用。本文将深入探讨 Kubernetes 中 Secret 的概念、创建方式及其应用场景,帮助您更好地理解和利用这一关键技术。

什么是 Secret?

定义与背景

Secret 是 Kubernetes 中用于保存敏感信息的一种资源对象。它旨在解决应用程序配置中敏感数据的安全性问题,确保这些数据不会被明文暴露在代码库或环境中。通过 Secret,我们可以将敏感信息与应用程序代码分离,减少泄露风险,并且可以更方便地进行版本控制和管理。

关键特性

  • 加密存储:所有存储在 Secret 中的数据都会经过 base64 编码处理,默认情况下并不会进一步加密。不过,在某些 Kubernetes 集群中,可以通过启用静态数据加密来增强安全性。
  • 生命周期管理Secret 的生命周期独立于 Pod 或其他资源。这意味着即使 Pod 被删除或重新调度,相关联的 Secret 仍然存在,直到显式删除为止。
  • 权限控制:可以为不同的命名空间和服务账户设置访问权限,限制哪些组件能够读取特定的 Secret
  • 灵活挂载:支持将 Secret 作为环境变量或卷挂载到容器中,方便应用程序直接使用。

创建和使用 Secret

接下来我们将详细介绍如何创建和使用 Secret,并给出几个实际的例子。

创建 Secret

方法一:通过命令行工具创建

最简单的方式是使用 kubectl create secret 命令直接从文件或字面值创建 Secret。例如:

# 从文件创建 Secret
kubectl create secret generic db-secret --from-file=./db-password.txt

# 从字面值创建 Secret
kubectl create secret generic api-key --from-literal=key=myapikey123

方法二:通过 YAML 文件定义

对于更复杂的场景,建议编写一个 YAML 文件来描述 Secret 的结构。以下是一个简单的例子:

apiVersion: v1
kind: Secret
metadata:
  name: mysecret
type: Opaque
data:
  username: dXNlcm5hbWU=  # "username" 的 base64 编码
  password: cGFzc3dvcmQ=  # "password" 的 base64 编码

然后应用此配置:

kubectl apply -f secret.yaml

使用 Secret

一旦创建了 Secret,就可以将其作为环境变量或卷挂载到容器中使用。

作为环境变量使用

编辑 Pod 或 Deployment 的 YAML 文件,添加对 Secret 的引用:

apiVersion: apps/v1
kind: Deployment
metadata:
  name: myapp-deployment
spec:
  replicas: 2
  selector:
    matchLabels:
      app: myapp
  template:
    metadata:
      labels:
        app: myapp
    spec:
      containers:
      - name: myapp-container
        image: myapp-image
        env:
        - name: DB_USERNAME
          valueFrom:
            secretKeyRef:
              name: mysecret
              key: username
        - name: DB_PASSWORD
          valueFrom:
            secretKeyRef:
              name: mysecret
              key: password

这段代码会将 mysecret 中的 usernamepassword 字段分别赋值给环境变量 DB_USERNAMEDB_PASSWORD,供容器内的应用程序使用。

作为卷挂载使用

另一种常见的用法是将 Secret 挂载为文件系统中的文件。这适用于那些期望从文件读取配置的应用程序。以下是修改后的 Pod 配置示例:

apiVersion: v1
kind: Pod
metadata:
  name: secret-pod
spec:
  containers:
  - name: myapp-container
    image: myapp-image
    volumeMounts:
    - name: secret-volume
      mountPath: /etc/secret-volume
      readOnly: true
  volumes:
  - name: secret-volume
    secret:
      secretName: mysecret

在这个例子中,mysecret 中的所有键值对都将被挂载到容器内的 /etc/secret-volume 目录下,每个键对应一个文件名,其内容即为该键对应的值。

更新 Secret

更新 Secret 的内容后,已存在的 Pod 不会自动重新加载新的值。如果希望应用程序获取最新的敏感信息,通常需要重启 Pod 或者设计应用程序定期检查并刷新配置。

Secret 类型

除了默认的 Opaque 类型外,Kubernetes 还支持几种特殊类型的 Secret,用于满足特定用途:

  • kubernetes.io/service-account-token:自动生成的服务账号令牌,用于 API 认证。
  • kubernetes.io/dockerconfigjson:包含 Docker 注册表认证信息的 JSON 文件,用于拉取私有镜像。
  • tls:用于 HTTPS/TLS 通信的证书和私钥。

注意事项

尽管 Secret 提供了很多便利的功能,但在实际应用中也需要注意一些潜在的问题:

  • 数据加密:虽然 Secret 内的数据会被 base64 编码,但这并不意味着它们是安全的。为了防止未授权访问,应该考虑启用静态数据加密功能。
  • 权限控制:严格限制哪些服务账户能够访问特定的 Secret,避免不必要的泄露风险。
  • 定期轮换:敏感信息应当定期更新,尤其是在发现可能的安全漏洞时。
  • 监控和审计:记录 Secret 的创建、修改和删除操作,以便后续审查和追踪。

实战演练

接下来我们将通过几个实际的例子来展示如何使用 Secret 管理 Kubernetes 中的敏感信息。

创建并使用 TLS Secret

假设我们要部署一个 Nginx Ingress Controller,并为其提供 SSL/TLS 证书。首先,生成证书文件:

openssl req -x509 -nodes -days 365 -newkey rsa:2048 \
  -keyout tls.key -out tls.crt -subj "/CN=example.com"

接着,创建一个名为 nginx-tls 的 TLS Secret:

kubectl create secret tls nginx-tls --cert=tls.crt --key=tls.key

最后,在 Ingress 资源中引用这个 Secret:

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: example-ingress
spec:
  tls:
  - hosts:
    - example.com
    secretName: nginx-tls
  rules:
  - host: example.com
    http:
      paths:
      - path: /
        pathType: Prefix
        backend:
          service:
            name: myapp-service
            port:
              number: 80

现在,当用户访问 https://example.com 时,Nginx Ingress Controller 将使用 nginx-tls 中的证书来建立安全连接。

使用 Docker Config Secret

为了让 Pod 能够从私有 Docker 注册表拉取镜像,我们需要创建一个包含认证信息的 Docker Config Secret。假设我们有一个名为 docker-config.json 的文件,其中包含了必要的认证凭证:

{
  "auths": {
    "myregistrydomain.com": {
      "auth": "base64-encoded-auth-string",
      "email": "user@example.com"
    }
  }
}

创建 Secret:

kubectl create secret docker-registry regcred \
  --docker-server=myregistrydomain.com \
  --docker-username=<your-name> \
  --docker-password=<your-pword> \
  --docker-email=<your-email>

然后在 Pod 或 Deployment 的 YAML 文件中添加对这个 Secret 的引用:

apiVersion: v1
kind: Pod
metadata:
  name: private-reg-pod
spec:
  containers:
  - name: uses-private-reg
    image: myregistrydomain.com/myimage
  imagePullSecrets:
  - name: regcred

这样,Kubernetes 在拉取镜像时就会使用 regcred 中提供的认证信息。

总结

感谢您的阅读!如果您对 Secret 或 Kubernetes 有任何疑问或见解,欢迎继续探讨。