1.5. 为 pod 提供敏感数据
有些应用程序需要密码和用户名等敏感信息,但您不希望开发人员持有这些信息。
作为管理员,您可以使用 Secret 对象在不以明文方式公开的前提下提供此类信息。
1.5.1. 了解 secret
Secret
对象类型提供了一种机制来保存敏感信息,如密码、OpenShift Container Platform 客户端配置文件和私有源存储库凭证等。Secret 将敏感内容与 pod 分离。您可以使用卷插件将 secret 挂载到容器中,系统也可以使用 secret 代表 pod 执行操作。
主要属性包括:
- Secret 数据可以独立于其定义来引用。
- Secret 数据卷由临时文件工具 (tmpfs) 支持,永远不会停留在节点上。
- Secret 数据可以在命名空间内共享。
YAML Secret 对象定义
apiVersion: v1 kind: Secret metadata: name: test-secret namespace: my-namespace type: Opaque 1 data: 2 username: dmFsdWUtMQ0K 3 password: dmFsdWUtMg0KDQo= stringData: 4 hostname: myapp.mydomain.com 5
您必须先创建 secret,然后创建依赖于此 secret 的 pod。
在创建 secret 时:
- 使用 secret 数据创建 secret 对象。
- 更新 pod 的服务帐户以允许引用该 secret。
-
创建以环境变量或文件(使用
secret
卷)形式消耗 secret 的 pod。
1.5.1.1. secret 的类型
type
字段中的值指明 secret 的键名称和值的结构。此类型可用于强制使 secret 对象中存在用户名和密钥。如果您不想进行验证,请使用 opaque 类型,这也是默认类型。
指定以下一种类型来触发最小服务器端验证,确保 secret 数据中存在特定的键名称:
-
kubernetes.io/service-account-token
。使用服务帐户令牌。 -
kubernetes.io/basic-auth
。搭配基本身份验证使用。 -
kubernetes.io/ssh-auth
。搭配 SSH 密钥身份验证使用。 -
kubernetes.io/tls
。搭配 TLS 证书颁发机构使用。
如果您不想要验证,请指定 type: Opaque
,即 secret 没有声明键名称或值需要符合任何约定。opaque secret 允许使用无结构 key:value
对,可以包含任意值。
您可以指定其他任意类型,如 example.com/my-secret-type
。这些类型不是在服务器端强制执行,而是表明 secret 的创建者意在符合该类型的键/值要求。
如需不同 secret 类型的示例,请参阅使用 secret 中的代码示例。
1.5.1.2. secret 配置示例
以下是几个 secret 配置文件示例。
创建四个文件的 Secret YAML
apiVersion: v1 kind: Secret metadata: name: test-secret data: username: dmFsdWUtMQ0K 1 password: dmFsdWUtMQ0KDQo= 2 stringData: hostname: myapp.mydomain.com 3 secret.properties: |- 4 property1=valueA property2=valueB
一个 Pod 的 YAML 定义,使用卷中的 secret 数据。
apiVersion: v1 kind: Pod metadata: name: secret-example-pod spec: containers: - name: secret-test-container image: busybox command: [ "/bin/sh", "-c", "cat /etc/secret-volume/*" ] volumeMounts: # name must match the volume name below - name: secret-volume mountPath: /etc/secret-volume readOnly: true volumes: - name: secret-volume secret: secretName: test-secret restartPolicy: Never
一个 Pod 的 YAML 定义,在环境变量中使用 secret 数据
apiVersion: v1 kind: Pod metadata: name: secret-example-pod spec: containers: - name: secret-test-container image: busybox command: [ "/bin/sh", "-c", "export" ] env: - name: TEST_SECRET_USERNAME_ENV_VAR valueFrom: secretKeyRef: name: test-secret key: username restartPolicy: Never
一个 Build Config 的 YAML 定义,在环境变量中使用 secret 数据。
apiVersion: v1 kind: BuildConfig metadata: name: secret-example-bc spec: strategy: sourceStrategy: env: - name: TEST_SECRET_USERNAME_ENV_VAR valueFrom: secretKeyRef: name: test-secret key: username
1.5.1.3. Secret 数据密钥
Secret 密钥必须在 DNS 子域中。
1.5.2. 了解如何创建 secret
作为管理员,您必须先创建 secret,然后开发人员才能创建依赖于该 secret 的 pod。
在创建 secret 时:
- 使用 secret 数据创建 secret 对象。
- 更新 pod 的服务帐户以允许引用该 secret。
-
创建以环境变量或文件(使用
secret
卷)形式消耗 secret 的 pod。
1.5.2.1. Secret 创建限制
若要使用 secret,pod 需要引用该 secret。可以通过三种方式将 secret 用于 pod:
- 容器的环境变量。
- 作为挂载到一个或多个容器上的卷中的文件。
- 在拉取 pod 的镜像时由 kubelet 使用。
卷类型 secret 使用卷机制将数据作为文件写入到容器中。镜像拉取 secret 使用服务帐户,将 secret 自动注入到命名空间中的所有 pod。
当模板包含 secret 定义时,模板使用提供的 secret 的唯一方法是确保 secret 卷源通过验证,并且指定的对象引用实际指向 Secret
类型的对象。因此,secret 需要在依赖它的任何 pod 之前创建。确保这一点的最有效方法是通过使用服务帐户自动注入。
Secret API 对象驻留在命名空间中。它们只能由同一命名空间中的 pod 引用。
每个 secret 的大小限制为 1MB。这是为了防止创建可能会耗尽 apiserver 和 kubelet 内存的大型 secret。不过,创建许多较小的 secret 也可能会耗尽内存。
1.5.2.2. 创建不透明 secret
作为管理员,您可以创建不透明 secret,从而能使用包含任意值的无结构 key:value
对。
流程
在主控机上的 YAML 文件中创建 secret 对象。
例如:
apiVersion: v1 kind: Secret metadata: name: mysecret type: Opaque 1 data: username: dXNlci1uYW1l password: cGFzc3dvcmQ=
- 1
- 指定不透明 secret。
使用以下命令来创建 secret 对象:
$ oc create -f <filename>
然后:
- 为您要使用 secret 来允许引用该 secret 的 pod 更新服务帐户。
-
创建以环境变量或文件(使用
secret
卷)形式消耗 secret 的 pod。
1.5.3. 了解如何更新 secret
修改 secret 值时,值(由已在运行的 pod 使用)不会动态更改。若要更改 secret,您必须删除原始 pod 并创建一个新 pod(可能具有相同的 PodSpec)。
更新 secret 遵循与部署新容器镜像相同的工作流程。您可以使用 kubectl rolling-update
命令。
secret 中的 resourceVersion
值不在引用时指定。因此,如果在 pod 启动的同时更新 secret,则将不能定义用于 pod 的 secret 版本。
目前,无法检查 pod 创建时使用的 secret 对象的资源版本。按照计划 pod 将报告此信息,以便控制器可以重启使用旧 resourceVersion
的 pod。在此期间,请勿更新现有 secret 的数据,而应创建具有不同名称的新数据。
1.5.4. 关于将签名证书与 secret 搭配使用
若要与服务进行安全通信,您可以配置 OpenShift Container Platform,以生成一个签名的服务用证书/密钥对,再添加到项目中的 secret 里。
服务用证书 secret 旨在支持需要开箱即用证书的复杂中间件应用程序。它的设置与管理员工具为节点和主控机生成的服务器证书相同。
为服务用证书 secret 配置的服务 pod 规格。
apiVersion: v1
kind: Service
metadata:
name: registry
annotations:
service.alpha.openshift.io/serving-cert-secret-name: registry-cert1
....
- 1
- 指定证书的名称
其他 pod 可以信任集群创建的证书(仅对内部 DNS 名称进行签名),方法是使用 pod 中自动挂载的 /var/run/secrets/kubernetes.io/serviceaccount/service-ca.crt 文件中的 CA 捆绑。
此功能的签名算法是 x509.SHA256WithRSA
。要手动轮转,请删除生成的 secret。这会创建新的证书。
1.5.4.1. 生成签名证书以便与 secret 搭配使用
要将签名的服务用证书/密钥对用于 pod,请创建或编辑服务以添加到 service.alpha.openshift.io/serving-cert-secret-name
注解,然后将 secret 添加到该 pod。
流程
创建服务用证书 secret:
- 编辑服务的 pod 规格。
使用您要用于 secret 的名称,添加
service.alpha.openshift.io/serving-cert-secret-name
注解。kind: Service apiVersion: v1 metadata: name: my-service annotations: service.alpha.openshift.io/serving-cert-secret-name: my-cert 1 spec: selector: app: MyApp ports: - protocol: TCP port: 80 targetPort: 9376
证书和密钥采用 PEM 格式,分别存储在
tls.crt
和tls.key
中。创建服务:
$ oc create -f <file-name>.yaml
查看 secret 以确保已成功创建:
$ oc get secrets NAME TYPE DATA AGE my-cert kubernetes.io/tls 2 9m $ oc describe secret my-service-pod Name: my-service-pod Namespace: openshift-console Labels: <none> Annotations: kubernetes.io/service-account.name: builder kubernetes.io/service-account.uid: ab-11e9-988a-0eb4e1b4a396 Type: kubernetes.io/service-account-token Data ca.crt: 5802 bytes namespace: 17 bytes token: eyJhbGciOiJSUzI1NiIsImtpZCI6IiJ9.eyJpc3MiOiJrdWJlcm5ldGVzL3NlcnZpY2VhY2NvdW50Ii wia3ViZXJuZXRlcy5pby9zZXJ2aWNlYWNjb3VudC9uYW1lc3BhY2UiOiJvcGVuc2hpZnQtY29uc29sZSIsImt1YmVyb cnZpY2VhY2NvdW50L3NlcnZpY2UtYWNjb3VudC51aWQiOiJhYmE4Y2UyZC00MzVlLTExZTktOTg4YS0wZWI0ZTFiNGEz OTYiLCJzdWIiOiJzeXN0ZW06c2VydmljZWFjY291bnQ6b3BlbnNoaWZ
编辑与该 secret 搭配的 pod 规格。
apiVersion: v1 kind: Pod metadata: name: my-service-pod spec: containers: - name: mypod image: redis volumeMounts: - name: foo mountPath: "/etc/foo" volumes: - name: foo secret: secretName: my-cert items: - key: username path: my-group/my-username mode: 511
当它可用时,您的 pod 将会运行。该证书对内部服务 DNS 名称
<service.name>.<service.namespace>.svc
有效。证书/密钥对在接近到期时自动替换。在 secret 的
service.alpha.openshift.io/expiry
注解中查看到期日期,其采用 RFC3339 格式。注意在大多数情形中,服务 DNS 名称
<service.name>.<service.namespace>.svc
不可从外部路由。<service.name>.<service.namespace>.svc
的主要用途是集群内或服务内通信,也用于重新加密路由。
1.5.5. secret 故障排除
如果服务证书生成失败并显示以下信息(服务的 service.alpha.openshift.io/serving-cert-generation-error
注解包含以下信息):
secret/ssl-key references serviceUID 62ad25ca-d703-11e6-9d6f-0e9c0057b608, which does not match 77b6dd80-d716-11e6-9d6f-0e9c0057b60
生成证书的服务不再存在,或者具有不同的 serviceUID
。您必须移除旧 secret 并清除服务注解 service.alpha.openshift.io/serving-cert-generation-error
和 service.alpha.openshift.io/serving-cert-generation-error-num
,以强制重新生成证书:
$ oc delete secret <secret_name> $ oc annotate service <service_name> service.alpha.openshift.io/serving-cert-generation-error- $ oc annotate service <service_name> service.alpha.openshift.io/serving-cert-generation-error-num-
在用于移除注解的命令中,要移除的注解名称后面有一个 -
。