阿里云服務網格ASM支持使用CNI插件,將Iptables規則配置移出Pod。CNI插件不要求Istio用戶啟用Priviledge權限,從而降低了對操作者的權限要求,提升了服務網格ASM的安全性。本文介紹如何啟用CNI插件。
前提條件
已創建ASM實例,且版本為1.14.3.86及以上。
已使用kubectl連接到ASM實例。具體操作,請參見通過控制面kubectl訪問Istio資源。
背景信息
為了確保服務網格ASM正常工作,Istio需要在網格中的每個Pod中配置一個Envoy代理,通過Iptables規則控制Pod的流量,以便通過注入的Envoy代理將流量重定向到應用程序。因為每個Pod的Iptables規則都是網絡命名,所以更改不會影響節點上的其他Pod。
默認情況下,Istio在Pod中注入istio-init容器,并在Pod中的其他容器啟動之前設置必要的Iptables規則。這就要求操作者部署容器時具有足夠的特權,包括部署具有NET_ADMIN功能的其他容器、重新配置網絡等。
服務網格ASM支持使用CNI插件,將Iptables規則配置移出Pod。CNI插件不要求Istio用戶啟用Priviledge權限,在Pod的網絡設置階段執行流量重定向,從而消除了對NET_ADMIN能力的依賴要求。CNI插件啟用后,其配置將被插入到容器CNI插件鏈中,從而在容器啟動時被調用執行。
CNI插件根據以下條件進行查找需要重定向流量的Pod:
Pod的命名空間不在配置的excludeNamespaces列表中。
Pod中包含一個名為istio-proxy的容器。
Pod中有多個容器。
Pod中存在
sidecar.istio.io/status
注解。Pod中
sidecar.istio.io/inject
的值不為false
。
啟用CNI插件
您可以通過ASM控制臺為ASM實例啟用CNI插件,具體操作步驟如下:
登錄ASM控制臺。
在網格管理頁面,單擊目標實例名稱,然后在左側導航欄,選擇 。
在網格CNI插件頁面,打開是否啟用網格CNI插件開關,選中需要排除的命名空間,然后單擊更新設置。
被排除的命名空間的Pod啟動時將通過istio-init進行網絡配置,不通過CNI進行網絡配置。當目標實例的狀態由更新中變為運行中,表示CNI插件啟用成功。
驗證Iptables規則
本文以在集群中部署bookinfo應用為例,驗證攔截規則是否生效。
使用以下內容,創建bookinfo.yaml。
################################################################################################## # Details service ################################################################################################## apiVersion: v1 kind: Service metadata: name: details labels: app: details service: details spec: ports: - port: 9080 name: http selector: app: details --- apiVersion: v1 kind: ServiceAccount metadata: name: bookinfo-details labels: account: details --- apiVersion: apps/v1 kind: Deployment metadata: name: details-v1 labels: app: details version: v1 spec: replicas: 1 selector: matchLabels: app: details version: v1 template: metadata: labels: app: details version: v1 spec: serviceAccountName: bookinfo-details containers: - name: details image: docker.io/istio/examples-bookinfo-details-v1:1.16.2 imagePullPolicy: IfNotPresent ports: - containerPort: 9080 securityContext: runAsUser: 1000 --- ################################################################################################## # Ratings service ################################################################################################## apiVersion: v1 kind: Service metadata: name: ratings labels: app: ratings service: ratings spec: ports: - port: 9080 name: http selector: app: ratings --- apiVersion: v1 kind: ServiceAccount metadata: name: bookinfo-ratings labels: account: ratings --- apiVersion: apps/v1 kind: Deployment metadata: name: ratings-v1 labels: app: ratings version: v1 spec: replicas: 1 selector: matchLabels: app: ratings version: v1 template: metadata: labels: app: ratings version: v1 spec: serviceAccountName: bookinfo-ratings containers: - name: ratings image: docker.io/istio/examples-bookinfo-ratings-v1:1.16.2 imagePullPolicy: IfNotPresent ports: - containerPort: 9080 securityContext: runAsUser: 1000 --- ################################################################################################## # Reviews service ################################################################################################## apiVersion: v1 kind: Service metadata: name: reviews labels: app: reviews service: reviews spec: ports: - port: 9080 name: http selector: app: reviews --- apiVersion: v1 kind: ServiceAccount metadata: name: bookinfo-reviews labels: account: reviews --- apiVersion: apps/v1 kind: Deployment metadata: name: reviews-v1 labels: app: reviews version: v1 spec: replicas: 1 selector: matchLabels: app: reviews version: v1 template: metadata: labels: app: reviews version: v1 spec: serviceAccountName: bookinfo-reviews containers: - name: reviews image: docker.io/istio/examples-bookinfo-reviews-v1:1.16.2 imagePullPolicy: IfNotPresent env: - name: LOG_DIR value: "/tmp/logs" ports: - containerPort: 9080 volumeMounts: - name: tmp mountPath: /tmp - name: wlp-output mountPath: /opt/ibm/wlp/output securityContext: runAsUser: 1000 volumes: - name: wlp-output emptyDir: {} - name: tmp emptyDir: {} --- apiVersion: apps/v1 kind: Deployment metadata: name: reviews-v2 labels: app: reviews version: v2 spec: replicas: 1 selector: matchLabels: app: reviews version: v2 template: metadata: labels: app: reviews version: v2 spec: serviceAccountName: bookinfo-reviews containers: - name: reviews image: docker.io/istio/examples-bookinfo-reviews-v2:1.16.2 imagePullPolicy: IfNotPresent env: - name: LOG_DIR value: "/tmp/logs" ports: - containerPort: 9080 volumeMounts: - name: tmp mountPath: /tmp - name: wlp-output mountPath: /opt/ibm/wlp/output securityContext: runAsUser: 1000 volumes: - name: wlp-output emptyDir: {} - name: tmp emptyDir: {} --- apiVersion: apps/v1 kind: Deployment metadata: name: reviews-v3 labels: app: reviews version: v3 spec: replicas: 1 selector: matchLabels: app: reviews version: v3 template: metadata: labels: app: reviews version: v3 spec: serviceAccountName: bookinfo-reviews containers: - name: reviews image: docker.io/istio/examples-bookinfo-reviews-v3:1.16.2 imagePullPolicy: IfNotPresent env: - name: LOG_DIR value: "/tmp/logs" ports: - containerPort: 9080 volumeMounts: - name: tmp mountPath: /tmp - name: wlp-output mountPath: /opt/ibm/wlp/output securityContext: runAsUser: 1000 volumes: - name: wlp-output emptyDir: {} - name: tmp emptyDir: {} --- ################################################################################################## # Productpage services ################################################################################################## apiVersion: v1 kind: Service metadata: name: productpage labels: app: productpage service: productpage spec: ports: - port: 9080 name: http selector: app: productpage --- apiVersion: v1 kind: ServiceAccount metadata: name: bookinfo-productpage labels: account: productpage --- apiVersion: apps/v1 kind: Deployment metadata: name: productpage-v1 labels: app: productpage version: v1 spec: replicas: 1 selector: matchLabels: app: productpage version: v1 template: metadata: labels: app: productpage version: v1 spec: serviceAccountName: bookinfo-productpage containers: - name: productpage image: docker.io/istio/examples-bookinfo-productpage-v1:1.16.2 imagePullPolicy: IfNotPresent ports: - containerPort: 9080 volumeMounts: - name: tmp mountPath: /tmp securityContext: runAsUser: 1000 volumes: - name: tmp emptyDir: {} ---
執行以下命令,部署bookinfo。
kubectl apply -f bookinfo.yaml
執行以下命令,獲取Productpage Pod的容器ID、節點名稱。
ns=default podname=kubectl get pod |grep productpage #容器運行時為Docker時,使用下面命令。 container_id=$(kubectl get pod -n ${ns} ${podname} -o jsonpath="{.status.containerStatuses[?(@.name=='istio-proxy')].containerID}" | sed -n 's/docker:\/\/\(.*\)/\1/p') #容器運行時為Containerd時,使用下面命令。 container_id=$(kubectl get pod -n ${ns} ${podname} -o jsonpath="{.status.containerStatuses[?(@.name=='istio-proxy')].containerID}" | sed -n 's/containerd:\/\/\(.*\)/\1/p') echo $container_id #獲取節點名稱。 kubectl get pod ${podname} -o jsonpath="{.spec.nodeName}"
登錄Productpage Pod的節點(例如使用SSH),執行以下命令,獲取映射到Conatiner ID的對應進程。
#容器運行時為Docker時,使用下面命令。 docker inspect --format '{{ .State.Pid }}' $container_id #容器運行時為Containerd時,使用下面命令。 crictl inspect $container_id|jq ".info.pid"
執行以下命令,進入Productpage容器的網絡命名空間,獲取當前配置。
nsenter -t $ -n iptables -L -t nat -n -v --line-numbers -x
Chain PREROUTING (policy ACCEPT 0 packets, 0 bytes) num pkts bytes target prot opt in out source destination 1 34938 2096280 ISTIO_INBOUND tcp -- * * 0.0.0.0/0 0.0.0.0/0 Chain INPUT (policy ACCEPT 0 packets, 0 bytes) num pkts bytes target prot opt in out source destination Chain POSTROUTING (policy ACCEPT 0 packets, 0 bytes) num pkts bytes target prot opt in out source destination Chain OUTPUT (policy ACCEPT 0 packets, 0 bytes) num pkts bytes target prot opt in out source destination 1 17 1020 ISTIO_OUTPUT tcp -- * * 0.0.0.0/0 0.0.0.0/0 Chain ISTIO_INBOUND (1 references) num pkts bytes target prot opt in out source destination 1 0 0 RETURN tcp -- * * 0.0.0.0/0 0.0.0.0/0 tcp dpt:15008 2 0 0 RETURN tcp -- * * 0.0.0.0/0 0.0.0.0/0 tcp dpt:22 3 0 0 RETURN tcp -- * * 0.0.0.0/0 0.0.0.0/0 tcp dpt:15020 4 34938 2096280 RETURN tcp -- * * 0.0.0.0/0 0.0.0.0/0 tcp dpt:15021 5 0 0 RETURN tcp -- * * 0.0.0.0/0 0.0.0.0/0 tcp dpt:15090 6 0 0 ISTIO_IN_REDIRECT tcp -- * * 0.0.0.0/0 0.0.0.0/0 Chain ISTIO_REDIRECT (1 references) num pkts bytes target prot opt in out source destination 1 0 0 REDIRECT tcp -- * * 0.0.0.0/0 0.0.0.0/0 redir ports 15001 Chain ISTIO_IN_REDIRECT (3 references) num pkts bytes target prot opt in out source destination 1 1 60 REDIRECT tcp -- * * 0.0.0.0/0 0.0.0.0/0 redir ports 15006 Chain ISTIO_OUTPUT (1 references) num pkts bytes target prot opt in out source destination 1 2 120 RETURN tcp -- * * 0.0.0.0/0 0.0.0.0/0 tcp dpt:15020 2 0 0 RETURN all -- * lo 127.0.X.X 0.0.0.0/0 3 1 60 ISTIO_IN_REDIRECT all -- * lo 0.0.0.0/0 !127.0.X.X owner UID match 1337 4 0 0 RETURN all -- * lo 0.0.0.0/0 0.0.0.0/0 ! owner UID match 1337 5 14 840 RETURN all -- * * 0.0.0.0/0 0.0.0.0/0 owner UID match 1337 6 0 0 ISTIO_IN_REDIRECT all -- * lo 0.0.0.0/0 !127.0.X.X owner GID match 1337 7 0 0 RETURN all -- * lo 0.0.0.0/0 0.0.0.0/0 ! owner GID match 1337 8 0 0 RETURN all -- * * 0.0.0.0/0 0.0.0.0/0 owner GID match 1337 9 0 0 RETURN all -- * * 0.0.0.0/0 127.0.X.X 10 0 0 RETURN all -- * * 0.0.0.0/0 192.168.0.1 11 0 0 ISTIO_REDIRECT all -- * * 0.0.0.0/0 0.0.0.0/0
由預期輸出得到,存在
ISTIO_INBOUND
、ISTIO_REDIRECT
、ISTIO_IN_REDIRECT
、ISTIO_OUTPUT
等規則,表明攔截規則已經生效。