4. 自动轮换 Webhook TLS 凭证

Linkerd 控制平面包含几个组件,称为 webhooks, 由 Kubernetes 本身直接调用。 从 KubernetesLinkerd webhooks 的流量使用 TLS 进行保护, 因此每个 webhooks 都需要一个包含 TLS 凭据secret。 这些证书与 Linkerd 代理用于保护 podpod 通信并 使用完全独立的信任链的证书不同。 有关轮换 Linkerd 代理使用的 TLS 凭据的更多信息, 请参阅自动轮换控制平面 TLS 凭据

默认情况下,当 LinkerdLinkerd CLILinkerd 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

将签名密钥对保存为 Secret

接下来,我们将使用 step 工具创建一个签名密钥对,用于对每个 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

创建引用 Secret 的 Issuer

有了 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

颁发证书并将其写入 Secret

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

cat <<EOF | kubectl apply -f -
apiVersion: cert-manager.io/v1
kind: Certificate
metadata:
  name: linkerd-policy-validator
  namespace: linkerd
spec:
  secretName: linkerd-policy-validator-k8s-tls
  duration: 24h
  renewBefore: 1h
  issuerRef:
    name: webhook-issuer
    kind: Issuer
  commonName: linkerd-policy-validator.linkerd.svc
  dnsNames:
  - linkerd-policy-validator.linkerd.svc
  isCA: false
  privateKey:
    algorithm: ECDSA
    encoding: PKCS8
  usages:
  - server auth
---
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 这些 secret 中。

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

在 CLI 安装中使用这些凭据

Linkerd 配置为使用来自 cert-manager 的凭据而不是生成自己的凭据:

linkerd install \
  --set policyValidator.externalSecret=true \
  --set-file policyValidator.caBundle=ca.crt \
  --set proxyInjector.externalSecret=true \
  --set-file proxyInjector.caBundle=ca.crt \
  --set profileValidator.externalSecret=true \
  --set-file profileValidator.caBundle=ca.crt \
  | kubectl apply -f -

# ignore if not using the viz extension
linkerd viz install \
  --set tap.externalSecret=true \
  --set-file tap.caBundle=ca.crt \
  --set tapInjector.externalSecret=true \
  --set-file tapInjector.caBundle=ca.crt \
  | kubectl apply -f -

# ignore if not using the jaeger extension
linkerd jaeger install
  --set webhook.externalSecret=true \
  --set-file webhook.caBundle=ca.crt \
  | kubectl apply -f -

使用 Helm 安装

Helm 可以使用类似的模式:

helm install linkerd2 \
  --set installNamespace=false \
  --set policyValidator.externalSecret=true \
  --set-file policyValidator.caBundle=ca.crt \
  --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

有关如何对控制平面凭据执行类似操作的详细信息, 请参阅自动轮换控制平面 TLS 凭据