新:在推特Mastodon 获取项目更新。

使用信任管理器在 Kubernetes 中管理公共信任

上次验证:2023 年 6 月 19 日

在本教程中,我们将逐步介绍如何使用 trust-manager 在 Kubernetes 集群中分发公认的证书颁发机构 (CA) 证书。分发完成后,我们还会演示

  • 如何在你信任捆绑包更改时自动重新加载应用程序
  • 如何强制应用程序使用你分发的 CA 捆绑包

然后,我们将使用一个简单的 curl pod 来展示如何自动挂载受信任的 CA Bundle,以便在无需手动配置 curl 的情况下使用它。这模拟了应用程序如何无需任何额外配置即可使用你受信任的 CA 证书捆绑包。

在本教程中,我们将限制更改范围,使其仅影响 team-a 命名空间。要充分利用这些功能,你需要移除此限制。

注意: 提供的所有资源仅用于演示,在生产环境中使用前应进行适当的审查。

先决条件

💻 软件

  1. kubectl:Kubernetes 命令行工具,允许你配置 Kubernetes 集群。
  2. helm:Kubernetes 的包管理器。
  3. yq:用于解析 YAML 的命令行工具,具有方便的彩色显示。

分发公认 CA 信任

首先,让我们设置 trust-manager 并将我们的公认 CA 分发到我们的演示命名空间:team-a

设置应用程序和捆绑包

  1. 按照 此处说明 安装 trust-manager。

  2. 创建第一个 Bundle 资源,其中仅包含公认 CA 证书

    apiVersion: trust.cert-manager.io/v1alpha1
    kind: Bundle
    metadata:
    name: public-bundle
    spec:
    sources:
    - useDefaultCAs: true
    target:
    configMap:
    key: "ca-certificates.crt"
    namespaceSelector:
    matchLabels:
    trust: enabled
    kubectl apply -f - <<EOF
    apiVersion: trust.cert-manager.io/v1alpha1
    kind: Bundle
    metadata:
    name: public-bundle
    spec:
    sources:
    - useDefaultCAs: true
    target:
    configMap:
    key: "ca-certificates.crt"
    namespaceSelector:
    matchLabels:
    trust: enabled
    EOF
  3. 让我们创建一个命名空间,我们的应用程序将在其中运行

    kubectl apply -f - <<EOF
    apiVersion: v1
    kind: Namespace
    metadata:
    labels:
    trust: enabled
    name: team-a
    EOF

    请注意,此命名空间使用 trust: enabled 标记,它与 Bundle 资源中的 namespaceSelector 条件相匹配

    namespaceSelector:
    matchLabels:
    trust: enabled

    注意:这是为了将我们的信任捆绑包范围限制在前面提到的 team-a 命名空间。

  4. 验证 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 检查构建的容器映像。

  1. 应用应用程序部署

    apiVersion: apps/v1
    kind: Deployment
    metadata:
    labels:
    app: sleep-auto
    name: sleep-auto
    namespace: team-a
    spec:
    replicas: 1
    revisionHistoryLimit: 3
    selector:
    matchLabels:
    app: sleep-auto
    strategy: {}
    template:
    metadata:
    labels:
    app: sleep-auto
    spec:
    containers:
    - command:
    - /bin/sh
    - -c
    - sleep 1d
    image: quay.io/zenlab/curl:latest
    name: curl
    resources: {}
    volumeMounts:
    - mountPath: /etc/ssl/certs/
    name: ca-certificate-only
    readOnly: true
    volumes:
    - name: ca-certificate-only
    configMap:
    name: public-bundle
    defaultMode: 0644
    optional: false
    items:
    - key: ca-certificates.crt
    path: ca-certificates.crt
    kubectl apply -f - <<EOF
    apiVersion: apps/v1
    kind: Deployment
    metadata:
    labels:
    app: sleep-auto
    name: sleep-auto
    namespace: team-a
    spec:
    replicas: 1
    revisionHistoryLimit: 3
    selector:
    matchLabels:
    app: sleep-auto
    template:
    metadata:
    labels:
    app: sleep-auto
    spec:
    containers:
    - command:
    - /bin/sh
    - -c
    - sleep 1d
    image: quay.io/zenlab/curl:latest
    name: curl
    volumeMounts:
    - mountPath: /etc/ssl/certs/
    name: ca-certificate-only
    readOnly: true
    volumes:
    - name: ca-certificate-only
    configMap:
    name: public-bundle
    defaultMode: 0644
    optional: false
    items:
    - key: ca-certificates.crt
    path: ca-certificates.crt
    EOF
  2. 在运行的 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
  3. 列出 /etc/ssl/certs/ 的内容,以验证只有你的受信任 ca-certificates.crt 文件存在。

    ls -ltr /etc/ssl/certs/

    输出应该类似于

    ~ $ ls -ltr /etc/ssl/certs/
    total 0
    lrwxrwxrwx 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.crt
    lrwxrwxrwx 1 root root 52 Apr 14 01:11 ca-cert-vTrus_Root_CA.pem -> /usr/share/ca-certificates/mozilla/vTrus_Root_CA.crt
    lrwxrwxrwx 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.pem
    lrwxrwxrwx 1 root root 31 Apr 14 01:11 002c0b4f.0 -> ca-cert-GlobalSign_Root_R46.pem
  4. 向知名站点发出 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.
  1. 退出容器:exit

配置真实应用程序

根据上面的示例,Kubernetes 能够挂载到默认 CA 证书捆绑包的顶部。你可以将它与应用程序一起使用,假设你知道它们检索 CA 证书的默认位置。

例如,对于 Go,你的应用程序可以使用 SSL_CERT_FILESSL_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 可以重新加载或推出部署,无论何时 ConfigMapSecret 发生更改。因此,每当 Bundle 的目标同步时,Reloader 组件就可以获取此更改并推出将这些资源作为卷或环境变量挂载的应用程序。

请注意,你可以将许多其他软件捆绑在一起,或者将其写入应用程序容器中。它们只需监视文件系统的更改并触发应用程序进程的重新加载。这种方法需要容器映像或代码更改,在许多租户的情况下可能难以实现。使用 reloader 的优势在于它是一个通用的解决方案,适用于集群中运行的所有应用程序。

  1. 继续使用 reloader,可以使用 helm 安装它

    helm repo add stakater https://stakater.github.io/stakater-charts
    helm repo update
    helm install reloader stakater/reloader -n stakater-reloader --create-namespace --set fullnameOverride=reloader
  2. 我们可以重复使用上一节中的部署 sleep-auto,并将其配置为启用重新加载功能

    kubectl annotate deployment -n team-a sleep-auto reloader.stakater.com/auto="true"

    请注意,有几种配置选项可以配置 reloader 工具,而这只是一个最基本的示例。有关更详细的示例,请参阅 文档

  3. 在另一个终端中监视应用程序推出

    kubectl get po -n team-a -w
  4. 为了测试此更改,我们可以编辑我们的 Bundle 资源,以删除所有默认公认 CA 证书,而只提供一个 CA 证书

    apiVersion: trust.cert-manager.io/v1alpha1
    kind: Bundle
    metadata:
    name: public-bundle
    spec:
    sources:
    - inLine: |
    -----BEGIN CERTIFICATE-----
    MIIETjCCAzagAwIBAgINAe5fFp3/lzUrZGXWajANBgkqhkiG9w0BAQsFADBXMQsw
    CQYDVQQGEwJCRTEZMBcGA1UEChMQR2xvYmFsU2lnbiBudi1zYTEQMA4GA1UECxMH
    Um9vdCBDQTEbMBkGA1UEAxMSR2xvYmFsU2lnbiBSb290IENBMB4XDTE4MDkxOTAw
    MDAwMFoXDTI4MDEyODEyMDAwMFowTDEgMB4GA1UECxMXR2xvYmFsU2lnbiBSb290
    IENBIC0gUjMxEzARBgNVBAoTCkdsb2JhbFNpZ24xEzARBgNVBAMTCkdsb2JhbFNp
    Z24wggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDMJXaQeQZ4Ihb1wIO2
    hMoonv0FdhHFrYhy/EYCQ8eyip0EXyTLLkvhYIJG4VKrDIFHcGzdZNHr9SyjD4I9
    DCuul9e2FIYQebs7E4B3jAjhSdJqYi8fXvqWaN+JJ5U4nwbXPsnLJlkNc96wyOkm
    DoMVxu9bi9IEYMpJpij2aTv2y8gokeWdimFXN6x0FNx04Druci8unPvQu7/1PQDh
    BjPogiuuU6Y6FnOM3UEOIDrAtKeh6bJPkC4yYOlXy7kEkmho5TgmYHWyn3f/kRTv
    riBJ/K1AFUjRAjFhGV64l++td7dkmnq/X8ET75ti+w1s4FRpFqkD2m7pg5NxdsZp
    hYIXAgMBAAGjggEiMIIBHjAOBgNVHQ8BAf8EBAMCAQYwDwYDVR0TAQH/BAUwAwEB
    /zAdBgNVHQ4EFgQUj/BLf6guRSSuTVD6Y5qL3uLdG7wwHwYDVR0jBBgwFoAUYHtm
    GkUNl8qJUC99BM00qP/8/UswPQYIKwYBBQUHAQEEMTAvMC0GCCsGAQUFBzABhiFo
    dHRwOi8vb2NzcC5nbG9iYWxzaWduLmNvbS9yb290cjEwMwYDVR0fBCwwKjAooCag
    JIYiaHR0cDovL2NybC5nbG9iYWxzaWduLmNvbS9yb290LmNybDBHBgNVHSAEQDA+
    MDwGBFUdIAAwNDAyBggrBgEFBQcCARYmaHR0cHM6Ly93d3cuZ2xvYmFsc2lnbi5j
    b20vcmVwb3NpdG9yeS8wDQYJKoZIhvcNAQELBQADggEBACNw6c/ivvVZrpRCb8RD
    M6rNPzq5ZBfyYgZLSPFAiAYXof6r0V88xjPy847dHx0+zBpgmYILrMf8fpqHKqV9
    D6ZX7qw7aoXW3r1AY/itpsiIsBL89kHfDwmXHjjqU5++BfQ+6tOfUBJ2vgmLwgtI
    fR4uUfaNU9OrH0Abio7tfftPeVZwXwzTjhuzp3ANNyuXlava4BJrHEDOxcd+7cJi
    WOx37XMiwor1hkOIreoTbv3Y/kIvuX1erRjvlJDKPSerJpSZdcfL03v3ykzTr1Eh
    kluEfSufFT90y1HonoMOFm8b50bOI7355KKL0jlrqnkckSziYSQtjipIcJDEHsXo
    4HA=
    -----END CERTIFICATE-----
    target:
    configMap:
    key: "ca-certificates.crt"
    namespaceSelector:
    matchLabels:
    trust: enabled
    kubectl apply -f - <<EOF
    apiVersion: trust.cert-manager.io/v1alpha1
    kind: Bundle
    metadata:
    name: public-bundle
    spec:
    sources:
    - inLine: |
    -----BEGIN CERTIFICATE-----
    MIIETjCCAzagAwIBAgINAe5fFp3/lzUrZGXWajANBgkqhkiG9w0BAQsFADBXMQsw
    CQYDVQQGEwJCRTEZMBcGA1UEChMQR2xvYmFsU2lnbiBudi1zYTEQMA4GA1UECxMH
    Um9vdCBDQTEbMBkGA1UEAxMSR2xvYmFsU2lnbiBSb290IENBMB4XDTE4MDkxOTAw
    MDAwMFoXDTI4MDEyODEyMDAwMFowTDEgMB4GA1UECxMXR2xvYmFsU2lnbiBSb290
    IENBIC0gUjMxEzARBgNVBAoTCkdsb2JhbFNpZ24xEzARBgNVBAMTCkdsb2JhbFNp
    Z24wggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDMJXaQeQZ4Ihb1wIO2
    hMoonv0FdhHFrYhy/EYCQ8eyip0EXyTLLkvhYIJG4VKrDIFHcGzdZNHr9SyjD4I9
    DCuul9e2FIYQebs7E4B3jAjhSdJqYi8fXvqWaN+JJ5U4nwbXPsnLJlkNc96wyOkm
    DoMVxu9bi9IEYMpJpij2aTv2y8gokeWdimFXN6x0FNx04Druci8unPvQu7/1PQDh
    BjPogiuuU6Y6FnOM3UEOIDrAtKeh6bJPkC4yYOlXy7kEkmho5TgmYHWyn3f/kRTv
    riBJ/K1AFUjRAjFhGV64l++td7dkmnq/X8ET75ti+w1s4FRpFqkD2m7pg5NxdsZp
    hYIXAgMBAAGjggEiMIIBHjAOBgNVHQ8BAf8EBAMCAQYwDwYDVR0TAQH/BAUwAwEB
    /zAdBgNVHQ4EFgQUj/BLf6guRSSuTVD6Y5qL3uLdG7wwHwYDVR0jBBgwFoAUYHtm
    GkUNl8qJUC99BM00qP/8/UswPQYIKwYBBQUHAQEEMTAvMC0GCCsGAQUFBzABhiFo
    dHRwOi8vb2NzcC5nbG9iYWxzaWduLmNvbS9yb290cjEwMwYDVR0fBCwwKjAooCag
    JIYiaHR0cDovL2NybC5nbG9iYWxzaWduLmNvbS9yb290LmNybDBHBgNVHSAEQDA+
    MDwGBFUdIAAwNDAyBggrBgEFBQcCARYmaHR0cHM6Ly93d3cuZ2xvYmFsc2lnbi5j
    b20vcmVwb3NpdG9yeS8wDQYJKoZIhvcNAQELBQADggEBACNw6c/ivvVZrpRCb8RD
    M6rNPzq5ZBfyYgZLSPFAiAYXof6r0V88xjPy847dHx0+zBpgmYILrMf8fpqHKqV9
    D6ZX7qw7aoXW3r1AY/itpsiIsBL89kHfDwmXHjjqU5++BfQ+6tOfUBJ2vgmLwgtI
    fR4uUfaNU9OrH0Abio7tfftPeVZwXwzTjhuzp3ANNyuXlava4BJrHEDOxcd+7cJi
    WOx37XMiwor1hkOIreoTbv3Y/kIvuX1erRjvlJDKPSerJpSZdcfL03v3ykzTr1Eh
    kluEfSufFT90y1HonoMOFm8b50bOI7355KKL0jlrqnkckSziYSQtjipIcJDEHsXo
    4HA=
    -----END CERTIFICATE-----
    target:
    configMap:
    key: "ca-certificates.crt"
    namespaceSelector:
    matchLabels:
    trust: enabled
    EOF

    你应该立即看到应用程序部署在另一个终端中推出。

  5. 新 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/lzUrZGXWajANBgkqhkiG9w0BAQsFADBXMQsw
    CQYDVQQGEwJCRTEZMBcGA1UEChMQR2xvYmFsU2lnbiBudi1zYTEQMA4GA1UECxMH
    Um9vdCBDQTEbMBkGA1UEAxMSR2xvYmFsU2lnbiBSb290IENBMB4XDTE4MDkxOTAw
    MDAwMFoXDTI4MDEyODEyMDAwMFowTDEgMB4GA1UECxMXR2xvYmFsU2lnbiBSb290
    IENBIC0gUjMxEzARBgNVBAoTCkdsb2JhbFNpZ24xEzARBgNVBAMTCkdsb2JhbFNp
    Z24wggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDMJXaQeQZ4Ihb1wIO2
    hMoonv0FdhHFrYhy/EYCQ8eyip0EXyTLLkvhYIJG4VKrDIFHcGzdZNHr9SyjD4I9
    DCuul9e2FIYQebs7E4B3jAjhSdJqYi8fXvqWaN+JJ5U4nwbXPsnLJlkNc96wyOkm
    DoMVxu9bi9IEYMpJpij2aTv2y8gokeWdimFXN6x0FNx04Druci8unPvQu7/1PQDh
    BjPogiuuU6Y6FnOM3UEOIDrAtKeh6bJPkC4yYOlXy7kEkmho5TgmYHWyn3f/kRTv
    riBJ/K1AFUjRAjFhGV64l++td7dkmnq/X8ET75ti+w1s4FRpFqkD2m7pg5NxdsZp
    hYIXAgMBAAGjggEiMIIBHjAOBgNVHQ8BAf8EBAMCAQYwDwYDVR0TAQH/BAUwAwEB
    /zAdBgNVHQ4EFgQUj/BLf6guRSSuTVD6Y5qL3uLdG7wwHwYDVR0jBBgwFoAUYHtm
    GkUNl8qJUC99BM00qP/8/UswPQYIKwYBBQUHAQEEMTAvMC0GCCsGAQUFBzABhiFo
    dHRwOi8vb2NzcC5nbG9iYWxzaWduLmNvbS9yb290cjEwMwYDVR0fBCwwKjAooCag
    JIYiaHR0cDovL2NybC5nbG9iYWxzaWduLmNvbS9yb290LmNybDBHBgNVHSAEQDA+
    MDwGBFUdIAAwNDAyBggrBgEFBQcCARYmaHR0cHM6Ly93d3cuZ2xvYmFsc2lnbi5j
    b20vcmVwb3NpdG9yeS8wDQYJKoZIhvcNAQELBQADggEBACNw6c/ivvVZrpRCb8RD
    M6rNPzq5ZBfyYgZLSPFAiAYXof6r0V88xjPy847dHx0+zBpgmYILrMf8fpqHKqV9
    D6ZX7qw7aoXW3r1AY/itpsiIsBL89kHfDwmXHjjqU5++BfQ+6tOfUBJ2vgmLwgtI
    fR4uUfaNU9OrH0Abio7tfftPeVZwXwzTjhuzp3ANNyuXlava4BJrHEDOxcd+7cJi
    WOx37XMiwor1hkOIreoTbv3Y/kIvuX1erRjvlJDKPSerJpSZdcfL03v3ykzTr1Eh
    kluEfSufFT90y1HonoMOFm8b50bOI7355KKL0jlrqnkckSziYSQtjipIcJDEHsXo
    4HA=
    -----END CERTIFICATE-----
  6. 此 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.com

    TLS 失败示例

    * 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 0
    curl: (60) SSL certificate problem: unable to get local issuer certificate
    More details here: https://curl.se/docs/sslcerts.html
    curl failed to verify the legitimacy of the server and therefore could not
    establish a secure connection to it. To learn more about this situation and
    how to fix it, please visit the web page mentioned above.
    command terminated with exit code 60

强制使用您的 CA 捆绑包

使用诸如 GatekeeperKyverno 之类的工具,我们可以要求在将应用程序部署到 Kubernetes 时强制执行特定的 volumevolumeMount 配置。通过这种方法,集群管理员可以设置规则以自动将相关配置插入到每个 Pod 中。这可能有助于强制执行配置,但对于集群的应用程序团队或租户来说可能更加不透明。

在本教程中,我们将演示如何使用 Gatekeeper。

Gatekeeper

请参阅 Gatekeeper 目录,其中包含两个旨在强制执行在所有 Pod 上安装 CA 捆绑包的示例 Assign 策略,这些 Pod 来自 trust-manager 在每个命名空间中生成的 configMap

  1. 将 Gatekeeper 安装到您的集群中

    helm repo add gatekeeper https://open-policy-agent.github.io/gatekeeper/charts
    helm repo update
    helm install gatekeeper/gatekeeper --name-template=gatekeeper --namespace gatekeeper-system --create-namespace --version v3.11.0
  2. 创建一个适用于 team-a 命名空间中所有 pod 资源的策略,该策略在应用具有必需的 volumes 配置时,会对 Pod 资源进行变异。

    apiVersion: mutations.gatekeeper.sh/v1
    kind: Assign
    metadata:
    name: demo-trust-ca-volume
    spec:
    applyTo:
    - groups: [""]
    kinds: ["Pod"]
    versions: ["v1"]
    match:
    scope: Namespaced
    kinds:
    - apiGroups: ["*"]
    kinds: ["Pod"]
    namespaces: ["team-a"]
    excludedNamespaces: ["kube-system", "public", "kyverno", "gatekeeper-system"]
    # Mounting the volume named "ca-certificates" from ConfigMap
    location: "spec.volumes[name:ca-certificates]"
    parameters:
    assign:
    value:
    name: ca-certificates
    configMap:
    name: public-bundle
    defaultMode: 0644
    optional: false
    items:
    - key: ca-certificates.crt
    path: ca-certificates.crt
    kubectl apply -f gatekeeper/gatekeeper-trust-pod-ca-volume.yaml
  3. 创建一个适用于 team-a 命名空间中所有 pod 资源的策略,该策略会对它们进行变异,使其具有必需的 volumeMounts 配置。

    apiVersion: mutations.gatekeeper.sh/v1
    kind: Assign
    metadata:
    name: demo-trust-ca-volumemount
    spec:
    applyTo:
    - groups: [""]
    kinds: ["Pod"]
    versions: ["v1"]
    match:
    scope: Namespaced
    kinds:
    - 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-certificates
    readOnly: true
    kubectl apply -f gatekeeper/gatekeeper-trust-pod-ca-volumemount.yaml
  4. 切换到 team-a 命名空间,并创建一个没有事先 volumevolumeMount 配置的部署,以查看 Pod 运行后变异生效的情况。

    apiVersion: apps/v1
    kind: Deployment
    metadata:
    labels:
    app: test-assign
    name: test-assign
    namespace: team-a
    spec:
    replicas: 1
    revisionHistoryLimit: 3
    selector:
    matchLabels:
    app: test-assign
    strategy: {}
    template:
    metadata:
    labels:
    app: test-assign
    spec:
    containers:
    - command:
    - /bin/sh
    - -c
    - sleep 1d
    image: quay.io/zenlab/curl:latest
    name: curl
    resources: {}
    volumeMounts: []
    volumes: []
    kubectl apply -f gatekeeper/deploy-novol.yaml
  5. 应用后,验证 volumevolumeMount 是否已应用。

    kubectl get po -n team-a -l app=test-assign -o yaml | yq '.items[0].spec' -
  6. 执行一个 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

  7. 最后,我们可以应用一个类似的 Pod,只是这次 CA 证书已显式安装。这将展示,如果相关配置已经存在,Gatekeeper 策略将不采取任何行动。

    apiVersion: apps/v1
    kind: Deployment
    metadata:
    labels:
    app: test-assign-noop
    name: test-assign-noop
    namespace: team-a
    spec:
    replicas: 1
    revisionHistoryLimit: 3
    selector:
    matchLabels:
    app: test-assign-noop
    template:
    metadata:
    labels:
    app: test-assign-noop
    spec:
    containers:
    - command:
    - /bin/sh
    - -c
    - sleep 1d
    image: quay.io/zenlab/curl:latest
    name: curl
    volumeMounts:
    - mountPath: /etc/ssl/certs/
    name: ca-certificates
    readOnly: true
    volumes:
    - name: ca-certificates
    configMap:
    name: example
    defaultMode: 0644
    optional: false
    items:
    - key: ca-certificates.crt
    path: ca-certificates.crt
    kubectl apply -f gatekeeper/deploy-withvol.yaml
    kubectl 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-noop
kubectl delete bundle public-bundle
kubectl delete assign demo-trust-ca-volume demo-trust-ca-volumemount
helm uninstall -n gatekeeper-system gatekeeper
helm uninstall -n stakater-reloader reloader
helm uninstall -n cert-manager trust-manager
helm uninstall -n cert-manager cert-manager
kubectl delete namespace cert-manager team-a stakater-reloader gatekeeper-system
kubectl delete crd -l gatekeeper.sh/system=yes