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
公眾號:黑客下午茶
加我微信(互相學習交流),關注公眾號(獲取更多學習資料~)