如何在 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 开源四周年回顾与展望