Linkerd 2.10(Step by Step)—3. 自动轮换控制平面 TLS 与 Webhook TLS 凭证

简介: Linkerd 2.10(Step by Step)—3. 自动轮换控制平面 TLS 与 Webhook TLS 凭证

自动轮换控制平面 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 中,它已被弃用,并且是上面指定的第一个参数。

相关实践学习
容器服务Serverless版ACK Serverless 快速入门:在线魔方应用部署和监控
通过本实验,您将了解到容器服务Serverless版ACK Serverless 的基本产品能力,即可以实现快速部署一个在线魔方应用,并借助阿里云容器服务成熟的产品生态,实现在线应用的企业级监控,提升应用稳定性。
云原生实践公开课
课程大纲 开篇:如何学习并实践云原生技术 基础篇: 5 步上手 Kubernetes 进阶篇:生产环境下的 K8s 实践 相关的阿里云产品:容器服务&nbsp;ACK 容器服务&nbsp;Kubernetes&nbsp;版(简称&nbsp;ACK)提供高性能可伸缩的容器应用管理能力,支持企业级容器化应用的全生命周期管理。整合阿里云虚拟化、存储、网络和安全能力,打造云端最佳容器化应用运行环境。 了解产品详情:&nbsp;https://www.aliyun.com/product/kubernetes
相关文章
|
8月前
|
Python
requests--超时设置,代理设置,身份认证
requests--超时设置,代理设置,身份认证
|
Prometheus Cloud Native 数据可视化
Linkerd 2.10(Step by Step)—4. 如何配置外部 Prometheus 实例
Linkerd 2.10(Step by Step)—4. 如何配置外部 Prometheus 实例
124 0
|
数据安全/隐私保护
etcd集群开启用户身份认证
etcd集群开启用户身份认证,发现单机etcd和集群的授权不会同步,单机启动的是单机实例,集群启动的是集群实例
1020 1
|
Prometheus Kubernetes 监控
(三)Prometheus获取指标的tls认证机制
阿里云ACK专有集群的master组件基本都是https监听,那么prometheus server是如何鉴权获取到htts监听的metrics指标呢?Tls认证环节无关operator, 主要是prometheus server的认证处理 ,属于prometheus 监控体系通用的理论。先从prometheus最常见场景- pod (apiserver/scheduler/kcm)的tls认证场景开始介绍,然后单独介绍etcd和kubelet的tls认证 。本文通过curl模拟prometheus server获取https metrics 指标,便于对认证机制的理解。
1445 0
(三)Prometheus获取指标的tls认证机制
|
Kubernetes JavaScript 开发工具
开发 k8s 管理平台 - k8sailor 12. 设置 deployment 副本数量 与 参数的有效性验证
开发 k8s 管理平台 - k8sailor 12. 设置 deployment 副本数量 与 参数的有效性验证
200 0
开发 k8s 管理平台 - k8sailor 12. 设置 deployment 副本数量 与 参数的有效性验证
|
存储 Kubernetes 安全
Linkerd 2.10(Step by Step)—手动轮换控制平面 TLS 凭证
Linkerd 2.10(Step by Step)—手动轮换控制平面 TLS 凭证
105 0
|
Java Go Perl
Linkerd 2.10(Step by Step)—控制平面调试端点
Linkerd 2.10(Step by Step)—控制平面调试端点
|
安全 Linux Perl
Linkerd 2.10(Step by Step)—Linkerd 和 Pod 安全策略 (PSP)
Linkerd 2.10(Step by Step)—Linkerd 和 Pod 安全策略 (PSP)
121 0
|
Kubernetes API 容器
Linkerd 2.10(Step by Step)—使用请求跟踪调试 gRPC 应用程序
Linkerd 2.10(Step by Step)—使用请求跟踪调试 gRPC 应用程序
118 0
Linkerd 2.10(Step by Step)—使用请求跟踪调试 gRPC 应用程序
|
JSON Kubernetes 安全
Linkerd 2.10(Step by Step)—多集群通信
Linkerd 2.10(Step by Step)—多集群通信
196 0
Linkerd 2.10(Step by Step)—多集群通信