如何在 Istio 中整合 SPRIRE?
安裝 Istio
到 GitHub
上下載 Istio 安裝包,解壓後,建議使用 istioctl
安裝 Istio。
istioctl install --set profile=demo
如果你安裝了低於 1.14 版本的 Istio,請先升級 Istio。
安裝 SPIRE
我們使用 Istio 提供的快速安裝方式:
kubectl apply -f samples/security/spire/spire-quickstart.yaml
這將安裝以下元件:
namespace/spire created csidriver.storage.k8s.io/csi.spiffe.io created customresourcedefinition.apiextensions.k8s.io/spiffeids.spiffeid.spiffe.io created clusterrolebinding.rbac.authorization.k8s.io/k8s-workload-registrar-role-binding created clusterrole.rbac.authorization.k8s.io/k8s-workload-registrar-role created configmap/k8s-workload-registrar created serviceaccount/spire-server created configmap/trust-bundle created clusterrole.rbac.authorization.k8s.io/spire-server-trust-role created clusterrolebinding.rbac.authorization.k8s.io/spire-server-trust-role-binding created configmap/spire-server created statefulset.apps/spire-server created service/spire-server created serviceaccount/spire-agent created clusterrole.rbac.authorization.k8s.io/spire-agent-cluster-role created clusterrolebinding.rbac.authorization.k8s.io/spire-agent-cluster-role-binding created configmap/spire-agent created daemonset.apps/spire-agent created
需要給打 patch,這是為了讓所有 sidecar 和 Ingress 都可以共享 SPIRE agent 的 UNIX Domain Socket。
istioctl install --skip-confirmation -f - <<EOF apiVersion: install.istio.io/v1alpha1 kind: IstioOperator metadata: namespace: istio-system spec: profile: default meshConfig: trustDomain: example.org values: global: # This is used to customize the sidecar template sidecarInjectorWebhook: templates: spire: | spec: containers: - name: istio-proxy volumeMounts: - name: workload-socket mountPath: /run/secrets/workload-spiffe-uds readOnly: true volumes: - name: workload-socket csi: driver: "csi.spiffe.io" components: ingressGateways: - name: istio-ingressgateway enabled: true label: istio: ingressgateway k8s: overlays: - apiVersion: apps/v1 kind: Deployment name: istio-ingressgateway patches: - path: spec.template.spec.volumes.[name:workload-socket] value: name: workload-socket csi: driver: "csi.spiffe.io" - path: spec.template.spec.containers.[name:istio-proxy].volumeMounts.[name:workload-socket] value: name: workload-socket mountPath: "/run/secrets/workload-spiffe-uds" readOnly: true EOF
安裝好 Istio 和 SPIRE 後,我們就可以註冊負載了。
自動註冊 Kubernetes 負載
在快速安裝 SPIRE 的時候,我們已經安裝了 SPRIE Kubernetes Workload Registrar ,也就是說我們已經開啟自動負載註冊。現在檢查一下 SPIRE 是否給負載頒發了身份證明。
kubectl exec -i -t spire-server-0 -n spire -c spire-server -- /bin/sh -c "bin/spire-server entry show -socketPath /run/spire/sockets/server.sock"
你將看到例如下面這樣的結果:
# Node Entry ID : 3f17c8be-1379-4b7c-9a01-90805165d59f SPIFFE ID : spiffe://example.org/k8s-workload-registrar/demo-cluster/node/gke-jimmy-cluster-default-pool-d5041909-3atb Parent ID : spiffe://example.org/spire/server Revision : 0 TTL : default Selector : k8s_psat:agent_node_uid:cbab5123-b32f-49d0-89f2-0a7e4d2b0edd Selector : k8s_psat:cluster:demo-cluster # Ingress gateway Entry ID : ffc76b2e-e602-4ad3-8069-993ffbf4440e SPIFFE ID : spiffe://example.org/ns/istio-system/sa/istio-ingressgateway-service-account Parent ID : spiffe://example.org/k8s-workload-registrar/demo-cluster/node/gke-jimmy-cluster-default-pool-d5041909-0ucb Revision : 1 TTL : default Selector : k8s:node-name:gke-jimmy-cluster-default-pool-d5041909-0ucb Selector : k8s:ns:istio-system Selector : k8s:pod-uid:be32b10a-b5a4-4716-adaf-eab778f58c13 DNS name : istio-ingressgateway-6989cbc776-87qb6 DNS name : istio-ingressgateway.istio-system.svc # SPIRE Server Entry ID : 54444848-95ec-4b4d-a7c5-902a4049c96a SPIFFE ID : spiffe://example.org/ns/spire/sa/spire-server Parent ID : spiffe://example.org/k8s-workload-registrar/demo-cluster/node/gke-jimmy-cluster-default-pool-d5041909-0ucb Revision : 1 TTL : default Selector : k8s:node-name:gke-jimmy-cluster-default-pool-d5041909-0ucb Selector : k8s:ns:spire Selector : k8s:pod-uid:4917defc-9b5a-42d8-9b98-c0e0a48c0313 DNS name : spire-server-0 DNS name : spire-server.spire.svc
每個 node 的 parent ID 是 spiffe://example.org/ns/spire/sa/spire-server
,而 spiffe://example.org/ns/spire/sa/spire-server
的 parent 是 spiffe://example.org/k8s-workload-registrar/demo-cluster/node/gke-jimmy-cluster-default-pool-d5041909-0ucb
。
也就是說工作負載的層級是這樣的:
spiffe://example.org/spire/server spiffe://example.org/k8s-workload-registrar/demo-cluster/node/ spiffe://example.org/{namespace}/spire/sa/{service_acount}
SPIRE 通過標籤選擇器選擇工作負載,為它們建立 SPIFFE ID。
工作負載的 SPIFEE ID 格式為 spiffe://<trust.domain>/ns/<namespace>/sa/<service-account>
。
部署應用
下面我們部署一個應用,然後檢查下 SPIRE 為該應提供的身份。
使用下面的命令部署 Istio 提供的示例應用 sleep
:
istioctl kube-inject --filename samples/security/spire/sleep-spire.yaml | kubectl apply -f -
因為我們在安裝 Istio 的時候打了補丁,做了 SPIRE 自動注入,然後所有 pod 都會共享 SPIRE Agent 中的 UNIX Domain Socket: /run/secrets/workload-spiffe-uds/socket
。獲取正在執行的 sleep
pod 的 YAML,我們可以看到其中有 volume 配置如下:
volumes: - name: workload-socket csi: driver: csi.spiffe.io
以及 volumeMounts
如下:
volumeMounts: - name: workload-socket readOnly: true mountPath: /run/secrets/workload-spiffe-uds - name: workload-socket mountPath: /var/run/secrets/workload-spiffe-uds - name: workload-certs mountPath: /var/run/secrets/workload-spiffe-credentials - name: istiod-ca-cert
這都證實了 SPRIE Agent 與工作負載 pod 共享 UNIX Domain Socket。
我們再查詢下 Kubernetes 叢集中的 SPIRE 條目,你將可以看到 sleep 的條目已註冊。
Entry ID : bd4457af-c55c-4d8c-aee2-4d477a79b465 SPIFFE ID : spiffe://example.org/ns/default/sa/sleep Parent ID : spiffe://example.org/k8s-workload-registrar/demo-cluster/node/gke-jimmy-cluster-default-pool-d5041909-3atb Revision : 1 TTL : default Selector : k8s:node-name:gke-jimmy-cluster-default-pool-d5041909-3atb Selector : k8s:ns:default Selector : k8s:pod-uid:81f116ce-6538-4492-a78a-98b163b58310 DNS name : sleep-9df96d88-tvl49 DNS name : sleep.default.svc
再檢查下 sleep 的 SVID。
istioctl proxy-config secret $SLEEP_POD -o json | jq -r \ '.dynamicActiveSecrets[0].secret.tlsCertificate.certificateChain.inlineBytes' | base64 --decode > chain.pem
上面這條命令獲取 sleep pod 中 Envoy 的 secret 並解析其中的 TLS 證書,將其 base64 解碼後儲存到 chain.pem
檔案中。
openssl x509 -in chain.pem -text | grep SPIRE
使用 OpenSSL 解析其中的發行商,將得到如下的結果。
Subject: C=US, O=SPIRE, CN=sleep-9df96d88-tvl49
SPIFFE 還支援聯邦,你可以為 SPIRE Agent SDS 配置 bundle,還需要為 pod 增加註解 spiffe.io/federatesWith: "<trust.domain>"
,然後 Envoy 就會向 SPRIE Server 獲取 bundle 了,詳細步驟請參考 Istio 官方文件
。
以上就是在 Istio 中整合 SPIRE 的全過程。
參考
- 自 2020 年以來全球的開源商業化軟體融資情況
- IstioCon 2022 回顧及錄影、PPT 分享
- Beyond Istio OSS —— Istio 服務網格的現狀及未來
- 如何在 Istio 中整合 SPRIRE?
- 什麼是零信任?
- 為什麼 Istio 要使用 SPIRE 做身份認證?
- 再見 KataCoda!
- 如何編譯 Istio?
- Istio 資料平面 Pod 啟動過程詳解
- Istio 中的各元件埠及功能詳解
- Istio sidecar 中的流量型別及 iptables 規則詳解
- Tetrate 公司開源專案介紹
- 跨越鴻溝:理解鴻溝理論
- 網易開源 Istio 擴充套件專案 Slime 簡介——基於 Istio 的智慧服務網格管理器
- 服務網格現狀之我見
- 如何理解 Istio Ingress, 它與 API Gateway 有什麼區別?
- 如何除錯 Kubernetes 中的微服務 ——proxy、sidecar 還是 service mesh?
- Jimmy Song:為什麼山寨幣持有者不關心比特幣 Taproot 升級?
- Zoom OBS B 站直播配置手冊
- Istio 開源四週年回顧與展望