Linkerd 2.10 系列
- 快速上手 Linkerd v2 Service Mesh(服务网格)
- 腾讯云 K8S 集群实战 Service Mesh—Linkerd2 & Traefik2 部署 emojivoto 应用
- 详细了解 Linkerd 2.10 基础功能,一起步入 Service Mesh 微服务架构时代
- Linkerd 2.10(Step by Step)—1. 将您的服务添加到 Linkerd
- Linkerd 2.10(Step by Step)—2. 自动化的金丝雀发布
Linkerd 2.10 中文手册持续修正更新中:
自动轮换控制平面 TLS 凭证
Linkerd
的自动 mTLS
功能使用一组 TLS
凭据(TLS credentials
)为代理生成 TLS
证书(TLS certificates
):
信任锚(trust anchor
)、颁发者证书(issuer certificate
)和私钥(private key
)。
虽然 Linkerd
每 24
小时自动轮换数据平面代理的 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-tls
、linkerd-sp-validator-k8s-tls
、tap- k8s-tls
、tap-injector-k8s-tls
和 jaeger-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
公众号:黑客下午茶
加我微信(互相学习交流),关注公众号(获取更多学习资料~)