zoukankan      html  css  js  c++  java
  • Linkerd 2.10(Step by Step)—3. 自动轮换控制平面 TLS &Webhook TLS 凭证

    Linkerd 2.10 系列

    Linkerd 2.10 中文手册持续修正更新中:

    自动轮换控制平面 TLS 凭证

    Linkerd 的自动 mTLS 功能使用一组 TLS 凭据(TLS credentials)为代理生成 TLS 证书(TLS certificates):
    信任锚(trust anchor)、颁发者证书(issuer certificate)和私钥(private key)。
    虽然 Linkerd24 小时自动轮换数据平面代理的 TLS 证书,
    但它不会轮换用于颁发这些证书的 TLS 凭据。
    在本文档中,我们将描述如何使用外部解决方案
    自动轮换颁发者证书和私钥。

    (请注意,Linkerd 的信任锚仍然必须在 long-lived 集群上手动轮换)

    Cert manager

    Cert-manager
    是一个流行的项目,用于使来自外部来源的 TLS 凭证(TLS credentials)可用于 Kubernetes 集群。

    第一步,在您的集群上安装
    cert-manager

    如果您要安装 cert-manager >= 1.0
    则需要 kubernetes >= 1.16
    cert-manager 中用于 kubernetes <= 1.15
    的传统自定义资源定义没有 keyAlgorithm 选项,
    因此证书将使用 RSA 生成并且与 linkerd 不兼容。

    有关版本要求的更多详细信息,请参阅 v0.16 到 v1.0 升
    级说明

    Cert manager 作为集群上的证书颁发机构(CA)

    在这种情况下,我们不会从外部来源(external source)获取凭据,
    而是将其配置为集群上的
    CA
    并让它定期重新颁发 Linkerd 的颁发者证书(issuer certificate)和私钥(private key)。

    首先,创建 cert-manager 将用来存储其 Linkerd 相关资源的命名空间。
    为简单起见,我们建议使用默认的 Linkerd 控制平面命名空间:

    kubectl create namespace linkerd
    

    将签名密钥对(signing key pair)保存为 Secret

    接下来,使用 step 工具,
    创建一个签名密钥对(signing key pair)并将其存储在上面创建的
    命名空间中的 Kubernetes Secret 中:

    step certificate create root.linkerd.cluster.local ca.crt ca.key 
      --profile root-ca --no-password --insecure &&
      kubectl create secret tls 
        linkerd-trust-anchor 
        --cert=ca.crt 
        --key=ca.key 
        --namespace=linkerd
    

    对于寿命更长(longer-lived)的信任锚证书,将 --not-after 参数传递
    给具有所需值(desired value)的 step 命令(例如 --not-after=87600h)。

    创建引用密钥(referencing the secret)的颁发者(Issuer)

    有了 Secret,我们可以创建一个引用它的 cert-manager "Issuer" 资源:

    cat <<EOF | kubectl apply -f -
    apiVersion: cert-manager.io/v1
    kind: Issuer
    metadata:
      name: linkerd-trust-anchor
      namespace: linkerd
    spec:
      ca:
        secretName: linkerd-trust-anchor
    EOF
    

    颁发证书(Issuing certificates)并将它们写入一个 secret

    最后,我们可以创建一个 cert-manager "Certificate" 资源,
    它使用这个 Issuer 来生成所需的证书:

    cat <<EOF | kubectl apply -f -
    apiVersion: cert-manager.io/v1
    kind: Certificate
    metadata:
      name: linkerd-identity-issuer
      namespace: linkerd
    spec:
      secretName: linkerd-identity-issuer
      duration: 48h
      renewBefore: 25h
      issuerRef:
        name: linkerd-trust-anchor
        kind: Issuer
      commonName: identity.linkerd.cluster.local
      dnsNames:
      - identity.linkerd.cluster.local
      isCA: true
      privateKey:
        algorithm: ECDSA
      usages:
      - cert sign
      - crl sign
      - server auth
      - client auth
    EOF
    

    (在上面的 YAML 清单中,duration key 指示 cert-manager 将
    证书视为有效 48 小时,而 renewBefore key 指示
    cert-manager 将尝试在当前证书到期前 25 小时颁发新证书。
    这些值可以根据您的喜好定制。)

    此时,cert-manager 现在可以使用此证书资源(Certificate resource)
    获取 TLS 凭据(TLS credentials),
    该凭据将存储在名为 linkerd-identity-issuer 的 secret 中。
    要验证您新颁发的证书,您可以运行:

    kubectl get secret linkerd-identity-issuer -o yaml -n linkerd
    

    现在我们只需要通知 Linkerd 使用这些凭据。

    由于 cert-manager 中的
    bug
    如果您将 cert-manager 版本 0.15 与实验控制器(experimental controllers)一起使用,
    则它颁发的证书与 Linkerd 版本 <= stable-2.8.1 不兼容。

    您的 linkerd-identity pod 可能会因以下日志输出而崩溃:

    "Failed to initialize identity service: failed to read CA from disk:
    unsupported block type: 'PRIVATE KEY'"
    

    解决此问题的一些可能方法是:

    • 将 Linkerd 升级到包含修复程序的边缘版本 >= edge-20.6.4
    • 将 cert-manager 升级到版本 >= 0.16。(如何升级
    • 关闭 cert-manager 实验控制器(experimental controllers)。(docs)

    替代 CA 提供商

    您可以将 Cert Manager 配置为依赖于许多其他解决方案,
    例如 Vault
    而不是使用 Cert Manager 作为 CA。
    可以在此处找到
    有关如何设置现有证书管理器
    以使用不同类型的颁发者的更多详细信息。

    第三方证书管理解决方案

    需要注意的是,Linkerd 提供的机制也可以在 cert-manager 之外使用。
    Linkerd 将读取 linkerd-identity-issuer Secret,
    如果它是 kubernetes.io/tls 类型,将使用内容作为其 TLS 凭证(TLS credentials)。
    这意味着任何能够通过将 TLS 证书(certificates)写入此密钥
    来轮换它们的解决方案都可用于提供动态 TLS 证书管理。

    在 CLI 安装中使用这些凭据

    对于 CLI 安装,Linkerd 控制平面应该
    --identity-external-issuer 标志一起安装,
    该标志指示 Linkerd 从 linkerd-identity-issuer secret 读取证书。
    每当更新存储在 secret 中的 certificate 和 key 时,
    identity 服务将自动检测此更改并重新加载新凭据。

    瞧!我们已经设置了 Linkerd 控制平面 TLS 凭据的自动轮换。
    如果你想监控更新过程,你可以检查服务发出的 IssuerUpdated 事件:

    kubectl get events --field-selector reason=IssuerUpdated -n linkerd
    

    使用 Helm 安装

    对于 Helm 安装,而不是运行 linkerd install
    identityTrustAnchorsPEM 设置为
    linkerd-identity-issuer Secret 中 ca.crt 的值:

    helm install linkerd2 
      --set-file identityTrustAnchorsPEM=ca.crt 
      --set identity.issuer.scheme=kubernetes.io/tls 
      --set installNamespace=false 
      linkerd/linkerd2 
      -n linkerd
    

    对于低于 v3 的 Helm 版本,必须专门传递 --name 标志。
    在 Helm v3 中,它已被弃用,并且是上面指定的第一个参数。

    自动轮换 Webhook TLS 凭证

    Linkerd 控制平面包含几个组件,称为 webhooks,
    由 Kubernetes 本身直接调用。
    从 Kubernetes 到 Linkerd webhooks 的流量使用 TLS 进行保护,
    因此每个 webhooks 都需要一个包含 TLS 凭据的 secret。
    这些证书与 Linkerd 代理用于保护 pod 到 pod 通信并
    使用完全独立的信任链的证书不同。

    默认情况下,当 Linkerd 与 Linkerd CLI 或 Linkerd Helm chart 一起安装时,
    会自动为所有 webhook 生成 TLS 凭据。
    如果这些证书过期或因任何原因需要重新生成,
    执行 Linkerd upgrade(使用 Linkerd CLI 或使用 Helm)将重新生成它们。

    此工作流程适用于大多数用户。
    但是,如果您需要定期自动轮换这些 webhook 证书,
    则可以使用 cert-manager 来自动管理它们。

    安装 Cert manager

    第一步,在
    您的集群上安装 cert-manager
    并创建 cert-manager 将用于存储其 webhook 相关资源的命名空间。
    为简单起见,我们建议使用默认命名空间 linkerd 使用:

    # control plane core
    kubectl create namespace linkerd
    
    # viz (ignore if not using the viz extension)
    kubectl create namespace linkerd-viz
    
    # viz (ignore if not using the jaeger extension)
    kubectl create namespace linkerd-jaeger
    

    将签名密钥对(signing key pair)保存为 Secret

    接下来,我们将使用 step
    工具创建一个签名密钥对(signing key pair),用于对每个 webhook 证书进行签名:

    step certificate create webhook.linkerd.cluster.local ca.crt ca.key 
      --profile root-ca --no-password --insecure --san webhook.linkerd.cluster.local
    
    kubectl create secret tls webhook-issuer-tls --cert=ca.crt --key=ca.key --namespace=linkerd
    
    # ignore if not using the viz extension
    kubectl create secret tls webhook-issuer-tls --cert=ca.crt --key=ca.key --namespace=linkerd-viz
    
    # ignore if not using the jaeger extension
    kubectl create secret tls webhook-issuer-tls --cert=ca.crt --key=ca.key --namespace=linkerd-jaeger
    

    创建引用 secrets 的发行者(Issuers)

    有了 Secrets,我们就可以创建引用它们的 cert-manager "Issuer" 资源:

    cat <<EOF | kubectl apply -f -
    apiVersion: cert-manager.io/v1
    kind: Issuer
    metadata:
      name: webhook-issuer
      namespace: linkerd
    spec:
      ca:
        secretName: webhook-issuer-tls
    ---
    # ignore if not using the viz extension
    apiVersion: cert-manager.io/v1
    kind: Issuer
    metadata:
      name: webhook-issuer
      namespace: linkerd-viz
    spec:
      ca:
        secretName: webhook-issuer-tls
    ---
    # ignore if not using the jaeger extension
    apiVersion: cert-manager.io/v1
    kind: Issuer
    metadata:
      name: webhook-issuer
      namespace: linkerd-jaeger
    spec:
      ca:
        secretName: webhook-issuer-tls
    EOF
    

    颁发证书并将其写入 secrets

    最后,我们可以创建 cert-manager "Certificate" 资源,
    它使用颁发者(Issuers)来生成所需的证书:

    cat <<EOF | kubectl apply -f -
    apiVersion: cert-manager.io/v1
    kind: Certificate
    metadata:
      name: linkerd-proxy-injector
      namespace: linkerd
    spec:
      secretName: linkerd-proxy-injector-k8s-tls
      duration: 24h
      renewBefore: 1h
      issuerRef:
        name: webhook-issuer
        kind: Issuer
      commonName: linkerd-proxy-injector.linkerd.svc
      dnsNames:
      - linkerd-proxy-injector.linkerd.svc
      isCA: false
      privateKey:
        algorithm: ECDSA
      usages:
      - server auth
    ---
    apiVersion: cert-manager.io/v1
    kind: Certificate
    metadata:
      name: linkerd-sp-validator
      namespace: linkerd
    spec:
      secretName: linkerd-sp-validator-k8s-tls
      duration: 24h
      renewBefore: 1h
      issuerRef:
        name: webhook-issuer
        kind: Issuer
      commonName: linkerd-sp-validator.linkerd.svc
      dnsNames:
      - linkerd-sp-validator.linkerd.svc
      isCA: false
      privateKey:
        algorithm: ECDSA
      usages:
      - server auth
    ---
    # ignore if not using the viz extension
    apiVersion: cert-manager.io/v1
    kind: Certificate
    metadata:
      name: tap
      namespace: linkerd-viz
    spec:
      secretName: tap-k8s-tls
      duration: 24h
      renewBefore: 1h
      issuerRef:
        name: webhook-issuer
        kind: Issuer
      commonName: tap.linkerd-viz.svc
      dnsNames:
      - tap.linkerd-viz.svc
      isCA: false
      privateKey:
        algorithm: ECDSA
      usages:
      - server auth
    ---
    # ignore if not using the viz extension
    apiVersion: cert-manager.io/v1
    kind: Certificate
    metadata:
      name: linkerd-tap-injector
      namespace: linkerd-viz
    spec:
      secretName: tap-injector-k8s-tls
      duration: 24h
      renewBefore: 1h
      issuerRef:
        name: webhook-issuer
        kind: Issuer
      commonName: tap-injector.linkerd-viz.svc
      dnsNames:
      - tap-injector.linkerd-viz.svc
      isCA: false
      privateKey:
        algorithm: ECDSA
      usages:
      - server auth
    ---
    # ignore if not using the jaeger extension
    apiVersion: cert-manager.io/v1
    kind: Certificate
    metadata:
      name: jaeger-injector
      namespace: linkerd-jaeger
    spec:
      secretName: jaeger-injector-k8s-tls
      duration: 24h
      renewBefore: 1h
      issuerRef:
        name: webhook-issuer
        kind: Issuer
      commonName: jaeger-injector.linkerd.svc
      dnsNames:
      - jaeger-injector.linkerd.svc
      isCA: false
      privateKey:
        algorithm: ECDSA
      usages:
      - server auth
    EOF
    

    此时 cert-manager 现在可以使用这些 Certificate resources 来获取 TLS 凭证,
    这些凭证分别存储在 linkerd-proxy-injector-k8s-tlslinkerd-sp-validator-k8s-tlstap- k8s-tlstap-injector-k8s-tlsjaeger-injector-k8s-tls 这些 secrets 中。

    现在我们只需要通知 Linkerd 使用这些凭据。

    在 CLI 安装中使用这些凭据

    要将 Linkerd 配置为使用来自 cert-manager 的凭据而不是生成自己的凭据,
    我们生成了一个补充配置文件:

    CA=$(awk '{ print "    " $0 }' ca.crt)
    
    cat > config.yml <<EOF
    proxyInjector:
      externalSecret: true
      caBundle: |
    $CA
    profileValidator:
      externalSecret: true
      caBundle: |
    $CA
    EOF
    
    # ignore if not using the viz extension
    cat > config-viz.yml <<EOF
    tap:
      externalSecret: true
      caBundle: |
    $CA
    tapInjector:
      externalSecret: true
      caBundle: |
    $CA
    EOF
    
    # ignore if not using the jaeger extension
    cat > config-jaeger.yml <<EOF
    webhook:
      externalSecret: true
      caBundle: |
    $CA
    EOF
    

    现在我们可以使用这些配置文件安装 Linkerd

    linkerd install --values=config.yml | kubectl apply -f -
    
    # ignore if not using the viz extension
    linkerd viz install --values=config-viz.yml | kubectl apply -f -
    
    # ignore if not using the jaeger extension
    linkerd jaeger install --values=config-jaeger.yml | kubectl apply -f -
    

    使用 Helm 安装

    对于 Helm 安装,我们可以直接配置 Helm 值:

    helm install linkerd2 
      --set installNamespace=false 
      --set proxyInjector.externalSecret=true 
      --set-file proxyInjector.caBundle=ca.crt 
      --set profileValidator.externalSecret=true 
      --set-file profileValidator.caBundle=ca.crt 
      linkerd/linkerd2 
      -n linkerd
    
    # ignore if not using the viz extension
    helm install linkerd-viz 
      --set installNamespace=false 
      --set tap.externalSecret=true 
      --set-file tap.caBundle=ca.crt 
      --set tapInjector.externalSecret=true 
      --set-file tapInjector.caBundle=ca.crt 
      linkerd/linkerd-viz 
      -n linkerd-viz
    
    # ignore if not using the jaeger extension
    helm install linkerd-jaeger 
      --set installNamespace=false 
      --set webhook.externalSecret=true 
      --set-file webhook.caBundle=ca.crt 
      linkerd/linkerd-jaeger 
      -n linkerd-jaeger
    

    使用 Helm 安装 Linkerd 时,
    您还必须提供颁发者信任根(issuer trust root)和颁发者凭据(issuer credentials),
    使用 Helm 安装 Linkerd 中所述。

    对于低于 v3 的 Helm 版本,必须专门传递 --name 标志。
    在 Helm v3 中,它已被弃用,并且是上面指定的第一个参数。

    我是为少
    微信:uuhells123
    公众号:黑客下午茶
    加我微信(互相学习交流),关注公众号(获取更多学习资料~)
    
  • 相关阅读:
    Swift学习 --- 2.1基础部分
    【oracle案例】ORA-01722
    一种适合于大数据的并行坐标下降法
    【机器学习算法-python实现】svm支持向量机(3)—核函数
    让Editplus支持sql语法高亮显示
    CF986F Oppa Funcan Style Remastered
    HashMap和Hashtable的区别
    ArrayList和Vector的区别
    基本概念
    java编程规范
  • 原文地址:https://www.cnblogs.com/hacker-linner/p/14884010.html
Copyright © 2011-2022 走看看