使用信任管理器在 Kubernetes 中管理公共信任
上次验证:2023 年 6 月 19 日
在本教程中,我们将逐步介绍如何使用 trust-manager 在 Kubernetes 集群中分发公认的证书颁发机构 (CA) 证书。分发完成后,我们还会演示
- 如何在你信任捆绑包更改时自动重新加载应用程序
- 如何强制应用程序使用你分发的 CA 捆绑包
然后,我们将使用一个简单的 curl
pod 来展示如何自动挂载受信任的 CA Bundle
,以便在无需手动配置 curl 的情况下使用它。这模拟了应用程序如何无需任何额外配置即可使用你受信任的 CA 证书捆绑包。
在本教程中,我们将限制更改范围,使其仅影响 team-a
命名空间。要充分利用这些功能,你需要移除此限制。
注意: 提供的所有资源仅用于演示,在生产环境中使用前应进行适当的审查。
先决条件
💻 软件
分发公认 CA 信任
首先,让我们设置 trust-manager 并将我们的公认 CA 分发到我们的演示命名空间:team-a
。
设置应用程序和捆绑包
-
按照 此处说明 安装 trust-manager。
-
创建第一个
Bundle
资源,其中仅包含公认 CA 证书apiVersion: trust.cert-manager.io/v1alpha1kind: Bundlemetadata:name: public-bundlespec:sources:- useDefaultCAs: truetarget:configMap:key: "ca-certificates.crt"namespaceSelector:matchLabels:trust: enabledkubectl apply -f - <<EOFapiVersion: trust.cert-manager.io/v1alpha1kind: Bundlemetadata:name: public-bundlespec:sources:- useDefaultCAs: truetarget:configMap:key: "ca-certificates.crt"namespaceSelector:matchLabels:trust: enabledEOF -
让我们创建一个命名空间,我们的应用程序将在其中运行
kubectl apply -f - <<EOFapiVersion: v1kind: Namespacemetadata:labels:trust: enabledname: team-aEOF请注意,此命名空间使用
trust: enabled
标记,它与Bundle
资源中的namespaceSelector
条件相匹配namespaceSelector:matchLabels:trust: enabled注意:这是为了将我们的信任捆绑包范围限制在前面提到的
team-a
命名空间。 -
验证 trust-manager 控制器是否已将 CA 捆绑包正确传播到命名空间
kubectl get configmap -n team-a public-bundle -o yaml请注意,此输出应该很长。这是因为我们使用的默认公共捆绑包包含许多公认的 CA。
将信任捆绑包挂载到具有自动使用的应用程序
为了使用我们受信任的 CA,我们将它们挂载到应用程序的默认位置,大多数应用程序期望在该位置找到一个 ca-certificates.crt
文件。这种方法的好处是,容器中的大多数应用程序代码默认情况下将使用此文件,无需任何额外的配置。此外,你将挂载到 /etc/ssl/certs
的顶部,这将删除现有的 CA 证书,这些证书通常来自容器基础映像或在 CI 构建期间被拉取。
警告: 在此示例中,我们选择了一个众所周知的位置,该位置被 alpine 和
curl
用于获取受信任的 CA。这不是唯一可以使用的位置,因此容器可能具有其他默认位置。如果你想查看默认 CA 所在的位置,可以使用 paranoia 检查构建的容器映像。
-
应用应用程序部署
apiVersion: apps/v1kind: Deploymentmetadata:labels:app: sleep-autoname: sleep-autonamespace: team-aspec:replicas: 1revisionHistoryLimit: 3selector:matchLabels:app: sleep-autostrategy: {}template:metadata:labels:app: sleep-autospec:containers:- command:- /bin/sh- -c- sleep 1dimage: quay.io/zenlab/curl:latestname: curlresources: {}volumeMounts:- mountPath: /etc/ssl/certs/name: ca-certificate-onlyreadOnly: truevolumes:- name: ca-certificate-onlyconfigMap:name: public-bundledefaultMode: 0644optional: falseitems:- key: ca-certificates.crtpath: ca-certificates.crtkubectl apply -f - <<EOFapiVersion: apps/v1kind: Deploymentmetadata:labels:app: sleep-autoname: sleep-autonamespace: team-aspec:replicas: 1revisionHistoryLimit: 3selector:matchLabels:app: sleep-autotemplate:metadata:labels:app: sleep-autospec:containers:- command:- /bin/sh- -c- sleep 1dimage: quay.io/zenlab/curl:latestname: curlvolumeMounts:- mountPath: /etc/ssl/certs/name: ca-certificate-onlyreadOnly: truevolumes:- name: ca-certificate-onlyconfigMap:name: public-bundledefaultMode: 0644optional: falseitems:- key: ca-certificates.crtpath: ca-certificates.crtEOF -
在运行的 pod 内创建 shell
kubectl exec -n team-a -ti $(kubectl get po -n team-a -l app=sleep-auto -o jsonpath='{.items[0].metadata.name}') -- /bin/sh -
列出
/etc/ssl/certs/
的内容,以验证只有你的受信任ca-certificates.crt
文件存在。ls -ltr /etc/ssl/certs/输出应该类似于
~ $ ls -ltr /etc/ssl/certs/total 0lrwxrwxrwx 1 root root 26 Apr 14 15:12 ca-certificates.crt -> ..data/ca-certificates.crt请注意,在没有卷覆盖此目录的情况下,通常此容器映像的输出将类似于以下内容
~ $ ls -ltr /etc/ssl/certs/total 608-rw-r--r-- 1 root root 214222 Apr 14 01:11 ca-certificates.crtlrwxrwxrwx 1 root root 52 Apr 14 01:11 ca-cert-vTrus_Root_CA.pem -> /usr/share/ca-certificates/mozilla/vTrus_Root_CA.crtlrwxrwxrwx 1 root root 56 Apr 14 01:11 ca-cert-vTrus_ECC_Root_CA.pem -> /usr/share/ca-certificates/mozilla/vTrus_ECC_Root_CA.crt...lrwxrwxrwx 1 root root 53 Apr 14 01:11 02265526.0 -> ca-cert-Entrust_Root_Certification_Authority_-_G2.pemlrwxrwxrwx 1 root root 31 Apr 14 01:11 002c0b4f.0 -> ca-cert-GlobalSign_Root_R46.pem -
向知名站点发出 HTTPS 请求以验证
curl
是否无需传递额外的--cacert
标志即可工作curl -v https://bbc.co.uk/news成功将导致有效的 TLS 连接,例如
* Trying 151.101.0.81:443...* Connected to bbc.co.uk (151.101.0.81) port 443 (#0)* ALPN: offers h2,http/1.1* TLSv1.3 (OUT), TLS handshake, Client hello (1):* CAfile: /etc/ssl/certs/ca-certificates.crt* CApath: none* TLSv1.3 (IN), TLS handshake, Server hello (2):* TLSv1.3 (IN), TLS handshake, Encrypted Extensions (8):* TLSv1.3 (IN), TLS handshake, Certificate (11):* TLSv1.3 (IN), TLS handshake, CERT verify (15):* TLSv1.3 (IN), TLS handshake, Finished (20):* TLSv1.3 (OUT), TLS change cipher, Change cipher spec (1):* TLSv1.3 (OUT), TLS handshake, Finished (20):* SSL connection using TLSv1.3 / TLS_AES_128_GCM_SHA256* ALPN: server accepted h2* Server certificate:* subject: C=GB; ST=London; L=London; O=BRITISH BROADCASTING CORPORATION; CN=www.bbc.com* start date: Mar 14 06:16:13 2023 GMT* expire date: Apr 14 06:16:12 2024 GMT* subjectAltName: host "bbc.co.uk" matched cert's "bbc.co.uk"* issuer: C=BE; O=GlobalSign nv-sa; CN=GlobalSign RSA OV SSL CA 2018* SSL certificate verify ok.
- 退出容器:
exit
配置真实应用程序
根据上面的示例,Kubernetes 能够挂载到默认 CA 证书捆绑包的顶部。你可以将它与应用程序一起使用,假设你知道它们检索 CA 证书的默认位置。
例如,对于 Go
,你的应用程序可以使用 SSL_CERT_FILE
或 SSL_CERT_DIR
来指定默认 CA 证书文件位置。
查看更多详细信息 此处,并查看各种 OS 基础的默认位置 此处
// Possible certificate files; stop after finding one.var certFiles = []string{"/etc/ssl/certs/ca-certificates.crt", // Debian/Ubuntu/Gentoo etc."/etc/pki/tls/certs/ca-bundle.crt", // Fedora/RHEL 6"/etc/ssl/ca-bundle.pem", // OpenSUSE"/etc/pki/tls/cacert.pem", // OpenELEC"/etc/pki/ca-trust/extracted/pem/tls-ca-bundle.pem", // CentOS/RHEL 7"/etc/ssl/cert.pem", // Alpine Linux}// Possible directories with certificate files; all will be read.var certDirectories = []string{"/etc/ssl/certs", // SLES10/SLES11, https://golang.ac.cn/issue/12139"/etc/pki/tls/certs", // Fedora/RHEL"/
检查过 Python 后,发现 ssl
库使用相同的两个环境变量来查找受信任的 CA:SSL_CERT_DIR
和/或 SSL_CERT_FILE
。你可以在 文档 中以及 python3
运行时中验证这一点
>>> import ssl>>> ssl.get_default_verify_paths()DefaultVerifyPaths(cafile=None, capath='/usr/lib/ssl/certs', openssl_cafile_env='SSL_CERT_FILE', openssl_cafile='/usr/lib/ssl/cert.pem', openssl_capath_env='SSL_CERT_DIR', openssl_capath='/usr/lib/ssl/certs')
这意味着任何以文件形式挂载的 CA 以及以下任何文件都将被任何 python 应用程序运行时信任,与 Go
相似
- '/usr/lib/ssl/cert.pem'
- '/usr/lib/ssl/certs/*'
其他语言也可以实现类似的功能。
自动化和强制执行
现在我们已经手动挂载了 trust-manager 的捆绑包,你可能会想
- 如果 CA 捆绑包更改了,如何将更改传达给我的应用程序?
- 如何确保我的 CA 捆绑包被挂载到集群中的所有应用程序,而不必向我的租户请求更改?
让我们使用其他开源工具来解决这两种情况。
推出 CA 捆绑包更改
如果你的 CA 捆绑包发生更改,这些更改将很快同步到命名空间。此更改将反映在挂载到容器的卷中,但大多数应用程序不会检测到文件系统更改。常见的方法是重新启动客户端应用程序部署,方法是使用 kubectl rollout restart deployment <DEPLOY_NAME>
。可以使用第三方开源软件来自动执行此过程。
使用 Stakater Reloader 可以重新加载或推出部署,无论何时 ConfigMap
或 Secret
发生更改。因此,每当 Bundle
的目标同步时,Reloader 组件就可以获取此更改并推出将这些资源作为卷或环境变量挂载的应用程序。
请注意,你可以将许多其他软件捆绑在一起,或者将其写入应用程序容器中。它们只需监视文件系统的更改并触发应用程序进程的重新加载。这种方法需要容器映像或代码更改,在许多租户的情况下可能难以实现。使用 reloader 的优势在于它是一个通用的解决方案,适用于集群中运行的所有应用程序。
-
继续使用 reloader,可以使用 helm 安装它
helm repo add stakater https://stakater.github.io/stakater-chartshelm repo updatehelm install reloader stakater/reloader -n stakater-reloader --create-namespace --set fullnameOverride=reloader -
我们可以重复使用上一节中的部署
sleep-auto
,并将其配置为启用重新加载功能kubectl annotate deployment -n team-a sleep-auto reloader.stakater.com/auto="true"请注意,有几种配置选项可以配置 reloader 工具,而这只是一个最基本的示例。有关更详细的示例,请参阅 文档。
-
在另一个终端中监视应用程序推出
kubectl get po -n team-a -w -
为了测试此更改,我们可以编辑我们的
Bundle
资源,以删除所有默认公认 CA 证书,而只提供一个 CA 证书apiVersion: trust.cert-manager.io/v1alpha1kind: Bundlemetadata:name: public-bundlespec:sources:- inLine: |-----BEGIN CERTIFICATE-----MIIETjCCAzagAwIBAgINAe5fFp3/lzUrZGXWajANBgkqhkiG9w0BAQsFADBXMQswCQYDVQQGEwJCRTEZMBcGA1UEChMQR2xvYmFsU2lnbiBudi1zYTEQMA4GA1UECxMHUm9vdCBDQTEbMBkGA1UEAxMSR2xvYmFsU2lnbiBSb290IENBMB4XDTE4MDkxOTAwMDAwMFoXDTI4MDEyODEyMDAwMFowTDEgMB4GA1UECxMXR2xvYmFsU2lnbiBSb290IENBIC0gUjMxEzARBgNVBAoTCkdsb2JhbFNpZ24xEzARBgNVBAMTCkdsb2JhbFNpZ24wggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDMJXaQeQZ4Ihb1wIO2hMoonv0FdhHFrYhy/EYCQ8eyip0EXyTLLkvhYIJG4VKrDIFHcGzdZNHr9SyjD4I9DCuul9e2FIYQebs7E4B3jAjhSdJqYi8fXvqWaN+JJ5U4nwbXPsnLJlkNc96wyOkmDoMVxu9bi9IEYMpJpij2aTv2y8gokeWdimFXN6x0FNx04Druci8unPvQu7/1PQDhBjPogiuuU6Y6FnOM3UEOIDrAtKeh6bJPkC4yYOlXy7kEkmho5TgmYHWyn3f/kRTvriBJ/K1AFUjRAjFhGV64l++td7dkmnq/X8ET75ti+w1s4FRpFqkD2m7pg5NxdsZphYIXAgMBAAGjggEiMIIBHjAOBgNVHQ8BAf8EBAMCAQYwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQUj/BLf6guRSSuTVD6Y5qL3uLdG7wwHwYDVR0jBBgwFoAUYHtmGkUNl8qJUC99BM00qP/8/UswPQYIKwYBBQUHAQEEMTAvMC0GCCsGAQUFBzABhiFodHRwOi8vb2NzcC5nbG9iYWxzaWduLmNvbS9yb290cjEwMwYDVR0fBCwwKjAooCagJIYiaHR0cDovL2NybC5nbG9iYWxzaWduLmNvbS9yb290LmNybDBHBgNVHSAEQDA+MDwGBFUdIAAwNDAyBggrBgEFBQcCARYmaHR0cHM6Ly93d3cuZ2xvYmFsc2lnbi5jb20vcmVwb3NpdG9yeS8wDQYJKoZIhvcNAQELBQADggEBACNw6c/ivvVZrpRCb8RDM6rNPzq5ZBfyYgZLSPFAiAYXof6r0V88xjPy847dHx0+zBpgmYILrMf8fpqHKqV9D6ZX7qw7aoXW3r1AY/itpsiIsBL89kHfDwmXHjjqU5++BfQ+6tOfUBJ2vgmLwgtIfR4uUfaNU9OrH0Abio7tfftPeVZwXwzTjhuzp3ANNyuXlava4BJrHEDOxcd+7cJiWOx37XMiwor1hkOIreoTbv3Y/kIvuX1erRjvlJDKPSerJpSZdcfL03v3ykzTr1EhkluEfSufFT90y1HonoMOFm8b50bOI7355KKL0jlrqnkckSziYSQtjipIcJDEHsXo4HA=-----END CERTIFICATE-----target:configMap:key: "ca-certificates.crt"namespaceSelector:matchLabels:trust: enabledkubectl apply -f - <<EOFapiVersion: trust.cert-manager.io/v1alpha1kind: Bundlemetadata:name: public-bundlespec:sources:- inLine: |-----BEGIN CERTIFICATE-----MIIETjCCAzagAwIBAgINAe5fFp3/lzUrZGXWajANBgkqhkiG9w0BAQsFADBXMQswCQYDVQQGEwJCRTEZMBcGA1UEChMQR2xvYmFsU2lnbiBudi1zYTEQMA4GA1UECxMHUm9vdCBDQTEbMBkGA1UEAxMSR2xvYmFsU2lnbiBSb290IENBMB4XDTE4MDkxOTAwMDAwMFoXDTI4MDEyODEyMDAwMFowTDEgMB4GA1UECxMXR2xvYmFsU2lnbiBSb290IENBIC0gUjMxEzARBgNVBAoTCkdsb2JhbFNpZ24xEzARBgNVBAMTCkdsb2JhbFNpZ24wggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDMJXaQeQZ4Ihb1wIO2hMoonv0FdhHFrYhy/EYCQ8eyip0EXyTLLkvhYIJG4VKrDIFHcGzdZNHr9SyjD4I9DCuul9e2FIYQebs7E4B3jAjhSdJqYi8fXvqWaN+JJ5U4nwbXPsnLJlkNc96wyOkmDoMVxu9bi9IEYMpJpij2aTv2y8gokeWdimFXN6x0FNx04Druci8unPvQu7/1PQDhBjPogiuuU6Y6FnOM3UEOIDrAtKeh6bJPkC4yYOlXy7kEkmho5TgmYHWyn3f/kRTvriBJ/K1AFUjRAjFhGV64l++td7dkmnq/X8ET75ti+w1s4FRpFqkD2m7pg5NxdsZphYIXAgMBAAGjggEiMIIBHjAOBgNVHQ8BAf8EBAMCAQYwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQUj/BLf6guRSSuTVD6Y5qL3uLdG7wwHwYDVR0jBBgwFoAUYHtmGkUNl8qJUC99BM00qP/8/UswPQYIKwYBBQUHAQEEMTAvMC0GCCsGAQUFBzABhiFodHRwOi8vb2NzcC5nbG9iYWxzaWduLmNvbS9yb290cjEwMwYDVR0fBCwwKjAooCagJIYiaHR0cDovL2NybC5nbG9iYWxzaWduLmNvbS9yb290LmNybDBHBgNVHSAEQDA+MDwGBFUdIAAwNDAyBggrBgEFBQcCARYmaHR0cHM6Ly93d3cuZ2xvYmFsc2lnbi5jb20vcmVwb3NpdG9yeS8wDQYJKoZIhvcNAQELBQADggEBACNw6c/ivvVZrpRCb8RDM6rNPzq5ZBfyYgZLSPFAiAYXof6r0V88xjPy847dHx0+zBpgmYILrMf8fpqHKqV9D6ZX7qw7aoXW3r1AY/itpsiIsBL89kHfDwmXHjjqU5++BfQ+6tOfUBJ2vgmLwgtIfR4uUfaNU9OrH0Abio7tfftPeVZwXwzTjhuzp3ANNyuXlava4BJrHEDOxcd+7cJiWOx37XMiwor1hkOIreoTbv3Y/kIvuX1erRjvlJDKPSerJpSZdcfL03v3ykzTr1EhkluEfSufFT90y1HonoMOFm8b50bOI7355KKL0jlrqnkckSziYSQtjipIcJDEHsXo4HA=-----END CERTIFICATE-----target:configMap:key: "ca-certificates.crt"namespaceSelector:matchLabels:trust: enabledEOF你应该立即看到应用程序部署在另一个终端中推出。
-
新 pod 运行后,使用以下命令确认你只有一个 CA 证书
ca-certificates.crt
文件,即我们刚刚应用的文件kubectl exec -ti -n team-a $(kubectl get po -n team-a -l app=sleep-auto -o jsonpath='{.items[0].metadata.name}') -- cat /etc/ssl/certs/ca-certificates.crt你应该得到完全相同的输出
-----BEGIN CERTIFICATE-----MIIETjCCAzagAwIBAgINAe5fFp3/lzUrZGXWajANBgkqhkiG9w0BAQsFADBXMQswCQYDVQQGEwJCRTEZMBcGA1UEChMQR2xvYmFsU2lnbiBudi1zYTEQMA4GA1UECxMHUm9vdCBDQTEbMBkGA1UEAxMSR2xvYmFsU2lnbiBSb290IENBMB4XDTE4MDkxOTAwMDAwMFoXDTI4MDEyODEyMDAwMFowTDEgMB4GA1UECxMXR2xvYmFsU2lnbiBSb290IENBIC0gUjMxEzARBgNVBAoTCkdsb2JhbFNpZ24xEzARBgNVBAMTCkdsb2JhbFNpZ24wggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDMJXaQeQZ4Ihb1wIO2hMoonv0FdhHFrYhy/EYCQ8eyip0EXyTLLkvhYIJG4VKrDIFHcGzdZNHr9SyjD4I9DCuul9e2FIYQebs7E4B3jAjhSdJqYi8fXvqWaN+JJ5U4nwbXPsnLJlkNc96wyOkmDoMVxu9bi9IEYMpJpij2aTv2y8gokeWdimFXN6x0FNx04Druci8unPvQu7/1PQDhBjPogiuuU6Y6FnOM3UEOIDrAtKeh6bJPkC4yYOlXy7kEkmho5TgmYHWyn3f/kRTvriBJ/K1AFUjRAjFhGV64l++td7dkmnq/X8ET75ti+w1s4FRpFqkD2m7pg5NxdsZphYIXAgMBAAGjggEiMIIBHjAOBgNVHQ8BAf8EBAMCAQYwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQUj/BLf6guRSSuTVD6Y5qL3uLdG7wwHwYDVR0jBBgwFoAUYHtmGkUNl8qJUC99BM00qP/8/UswPQYIKwYBBQUHAQEEMTAvMC0GCCsGAQUFBzABhiFodHRwOi8vb2NzcC5nbG9iYWxzaWduLmNvbS9yb290cjEwMwYDVR0fBCwwKjAooCagJIYiaHR0cDovL2NybC5nbG9iYWxzaWduLmNvbS9yb290LmNybDBHBgNVHSAEQDA+MDwGBFUdIAAwNDAyBggrBgEFBQcCARYmaHR0cHM6Ly93d3cuZ2xvYmFsc2lnbi5jb20vcmVwb3NpdG9yeS8wDQYJKoZIhvcNAQELBQADggEBACNw6c/ivvVZrpRCb8RDM6rNPzq5ZBfyYgZLSPFAiAYXof6r0V88xjPy847dHx0+zBpgmYILrMf8fpqHKqV9D6ZX7qw7aoXW3r1AY/itpsiIsBL89kHfDwmXHjjqU5++BfQ+6tOfUBJ2vgmLwgtIfR4uUfaNU9OrH0Abio7tfftPeVZwXwzTjhuzp3ANNyuXlava4BJrHEDOxcd+7cJiWOx37XMiwor1hkOIreoTbv3Y/kIvuX1erRjvlJDKPSerJpSZdcfL03v3ykzTr1EhkluEfSufFT90y1HonoMOFm8b50bOI7355KKL0jlrqnkckSziYSQtjipIcJDEHsXo4HA=-----END CERTIFICATE----- -
此 CA 证书可用于验证网站
https://bbc.co.uk
的真实性。我们可以使用该容器中的curl
来验证。kubectl exec -ti -n team-a $(kubectl get po -n team-a -l app=sleep-auto -o jsonpath='{.items[0].metadata.name}') -- curl -v https://bbc.co.uk我们还可以验证从这个 Pod 开始,我们无法再与 google.com 通信。
kubectl exec -ti -n team-a $(kubectl get po -n team-a -l app=sleep-auto -o jsonpath='{.items[0].metadata.name}') -- curl -v https://google.comTLS 失败示例
* Trying 142.250.200.46:443...* Connected to google.com (142.250.200.46) port 443 (#0)* ALPN: offers h2,http/1.1* TLSv1.3 (OUT), TLS handshake, Client hello (1):* CAfile: /etc/ssl/certs/ca-certificates.crt* CApath: none* TLSv1.3 (IN), TLS handshake, Server hello (2):* TLSv1.3 (IN), TLS handshake, Encrypted Extensions (8):* TLSv1.3 (IN), TLS handshake, Certificate (11):* TLSv1.3 (OUT), TLS alert, unknown CA (560):* SSL certificate problem: unable to get local issuer certificate* Closing connection 0curl: (60) SSL certificate problem: unable to get local issuer certificateMore details here: https://curl.se/docs/sslcerts.htmlcurl failed to verify the legitimacy of the server and therefore could notestablish a secure connection to it. To learn more about this situation andhow to fix it, please visit the web page mentioned above.command terminated with exit code 60
强制使用您的 CA 捆绑包
使用诸如 Gatekeeper 和 Kyverno 之类的工具,我们可以要求在将应用程序部署到 Kubernetes 时强制执行特定的 volume
和 volumeMount
配置。通过这种方法,集群管理员可以设置规则以自动将相关配置插入到每个 Pod 中。这可能有助于强制执行配置,但对于集群的应用程序团队或租户来说可能更加不透明。
在本教程中,我们将演示如何使用 Gatekeeper。
Gatekeeper
请参阅 Gatekeeper 目录,其中包含两个旨在强制执行在所有 Pod 上安装 CA 捆绑包的示例 Assign
策略,这些 Pod 来自 trust-manager 在每个命名空间中生成的 configMap
。
-
将 Gatekeeper 安装到您的集群中
helm repo add gatekeeper https://open-policy-agent.github.io/gatekeeper/chartshelm repo updatehelm install gatekeeper/gatekeeper --name-template=gatekeeper --namespace gatekeeper-system --create-namespace --version v3.11.0 -
创建一个适用于
team-a
命名空间中所有pod
资源的策略,该策略在应用具有必需的volumes
配置时,会对Pod
资源进行变异。apiVersion: mutations.gatekeeper.sh/v1kind: Assignmetadata:name: demo-trust-ca-volumespec:applyTo:- groups: [""]kinds: ["Pod"]versions: ["v1"]match:scope: Namespacedkinds:- apiGroups: ["*"]kinds: ["Pod"]namespaces: ["team-a"]excludedNamespaces: ["kube-system", "public", "kyverno", "gatekeeper-system"]# Mounting the volume named "ca-certificates" from ConfigMaplocation: "spec.volumes[name:ca-certificates]"parameters:assign:value:name: ca-certificatesconfigMap:name: public-bundledefaultMode: 0644optional: falseitems:- key: ca-certificates.crtpath: ca-certificates.crtkubectl apply -f gatekeeper/gatekeeper-trust-pod-ca-volume.yaml -
创建一个适用于
team-a
命名空间中所有pod
资源的策略,该策略会对它们进行变异,使其具有必需的volumeMounts
配置。apiVersion: mutations.gatekeeper.sh/v1kind: Assignmetadata:name: demo-trust-ca-volumemountspec:applyTo:- groups: [""]kinds: ["Pod"]versions: ["v1"]match:scope: Namespacedkinds:- apiGroups: ["*"]kinds: ["Pod"]namespaces: ["team-a"]excludedNamespaces: ["kube-system", "public", "kyverno", "gatekeeper-system"]# All containers in a pod mounting to volumeMount named "ca-certificates"location: "spec.containers[name:*].volumeMounts[name:ca-certificates]"parameters:assign:value:mountPath: /etc/ssl/certs/name: ca-certificatesreadOnly: truekubectl apply -f gatekeeper/gatekeeper-trust-pod-ca-volumemount.yaml -
切换到
team-a
命名空间,并创建一个没有事先volume
或volumeMount
配置的部署,以查看 Pod 运行后变异生效的情况。apiVersion: apps/v1kind: Deploymentmetadata:labels:app: test-assignname: test-assignnamespace: team-aspec:replicas: 1revisionHistoryLimit: 3selector:matchLabels:app: test-assignstrategy: {}template:metadata:labels:app: test-assignspec:containers:- command:- /bin/sh- -c- sleep 1dimage: quay.io/zenlab/curl:latestname: curlresources: {}volumeMounts: []volumes: []kubectl apply -f gatekeeper/deploy-novol.yaml -
应用后,验证
volume
和volumeMount
是否已应用。kubectl get po -n team-a -l app=test-assign -o yaml | yq '.items[0].spec' - -
执行一个 shell 到 Pod 中,并尝试建立与任何公共信任网站的 HTTPS 连接,例如:
https://bbc.co.uk
。kubectl exec -n team-a -ti $(kubectl get pod -n team-a -l app=test-assign -o jsonpath='{.items[0].metadata.name}') -- curl -v https://bbc.co.uk成功将显示来自网页的有效 200 响应。
请注意,现在这应该无需任何额外的配置即可工作。如果您在此时遇到 SSL 错误,请检查
volumes
部分中是否引用了正确的configMap
。 -
最后,我们可以应用一个类似的 Pod,只是这次 CA 证书已显式安装。这将展示,如果相关配置已经存在,Gatekeeper 策略将不采取任何行动。
apiVersion: apps/v1kind: Deploymentmetadata:labels:app: test-assign-noopname: test-assign-noopnamespace: team-aspec:replicas: 1revisionHistoryLimit: 3selector:matchLabels:app: test-assign-nooptemplate:metadata:labels:app: test-assign-noopspec:containers:- command:- /bin/sh- -c- sleep 1dimage: quay.io/zenlab/curl:latestname: curlvolumeMounts:- mountPath: /etc/ssl/certs/name: ca-certificatesreadOnly: truevolumes:- name: ca-certificatesconfigMap:name: exampledefaultMode: 0644optional: falseitems:- key: ca-certificates.crtpath: ca-certificates.crtkubectl apply -f gatekeeper/deploy-withvol.yamlkubectl exec -n team-a -ti $(kubectl get pod -n team-a -l app=test-assign-noop -o jsonpath='{.items[0].metadata.name}') -- curl -v https://bbc.co.uk
注意:如果您在 Assign
策略资源方面遇到问题,请尝试检查 Kubernetes 事件(kubectl get events
)以查找问题。
使用 trust-manager 进行公共信任
在本教程中,我们演示了如何使用 trust-manager 在集群级别管理证书颁发机构证书,以及如何手动或通过 Gatekeeper 强制执行来使用此受信任的 Bundle
。我们了解了如何设置应用程序,以便在您受信任的 CA 发生更改时自动部署。
虽然这对于当前在您的环境中“正常运行”的东西来说似乎是更多工作,但请考虑此解决方案如何在您不再信任特定证书颁发机构的情况下为您提供帮助。
下次我们将探讨如何将私有证书颁发机构轻松地集成到此信任管理流程中。
清理
要删除在本教程中部署的所有资源,请执行以下操作:
kubectl delete deployment -n team-a sleep-auto test-assign test-assign-noopkubectl delete bundle public-bundlekubectl delete assign demo-trust-ca-volume demo-trust-ca-volumemounthelm uninstall -n gatekeeper-system gatekeeperhelm uninstall -n stakater-reloader reloaderhelm uninstall -n cert-manager trust-managerhelm uninstall -n cert-manager cert-managerkubectl delete namespace cert-manager team-a stakater-reloader gatekeeper-systemkubectl delete crd -l gatekeeper.sh/system=yes