1. 程式人生 > >附029.Kubernetes安全之網路策略

附029.Kubernetes安全之網路策略

[toc] ### 環境構建 #### 基礎環境構建 ``` [root@master01 cksstudy]# vi studyns01.yaml apiVersion: v1 kind: Namespace metadata: name: studyns01 labels: role: studyns01 [root@master01 cksstudy]# vi studyns02.yaml apiVersion: v1 kind: Namespace metadata: name: studyns02 labels: role: studyns02 [root@master01 cksstudy]# vi studyns03.yaml apiVersion: v1 kind: Namespace metadata: name: studyns03 labels: role: studyns03 [root@master01 cksstudy]# vi studyns04.yaml apiVersion: v1 kind: Namespace metadata: name: studyns04 labels: role: studyns04 [root@master01 cksstudy]# vi studypod01.yaml apiVersion: v1 kind: Pod metadata: name: studypod01 namespace: studyns01 labels: role: studypod01 spec: containers: - name: studypod01 image: training/webapp command: - python - app.py imagePullPolicy: IfNotPresent restartPolicy: Always [root@master01 cksstudy]# vi studypod02.yaml apiVersion: v1 kind: Pod metadata: name: studypod02 namespace: studyns01 labels: role: studypod02 spec: containers: - name: studypod02 image: training/webapp command: - python - app.py imagePullPolicy: IfNotPresent restartPolicy: Always [root@master01 cksstudy]# vi studypod03.yaml apiVersion: v1 kind: Pod metadata: name: studypod03 namespace: studyns01 labels: role: studypod03 spec: containers: - name: studypod03 image: training/webapp command: - python - app.py imagePullPolicy: IfNotPresent restartPolicy: Always [root@master01 cksstudy]# vi studypod04.yaml apiVersion: v1 kind: Pod metadata: name: studypod04 namespace: studyns02 labels: role: studypod04 spec: containers: - name: studypod04 image: training/webapp command: - python - app.py imagePullPolicy: IfNotPresent restartPolicy: Always [root@master01 cksstudy]# vi studypod05.yaml apiVersion: v1 kind: Pod metadata: name: studypod05 namespace: studyns03 labels: role: studypod05 spec: containers: - name: studypod05 image: training/webapp command: - python - app.py imagePullPolicy: IfNotPresent restartPolicy: Always [root@master01 cksstudy]# vi studypod06.yaml apiVersion: v1 kind: Pod metadata: name: studypod06 namespace: studyns04 labels: role: studypod06 spec: containers: - name: studypod06 image: training/webapp command: - python - app.py imagePullPolicy: IfNotPresent restartPolicy: Always [root@master01 cksstudy]# kubectl apply -f . [root@master01 cksstudy]# kubectl -n studyns01 get pods -o wide NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES studypod01 1/1 Running 0 14s 10.10.30.108 worker02 studypod02 1/1 Running 0 14s 10.10.5.46 worker01 studypod03 1/1 Running 0 14s 10.10.5.47 worker01 [root@master01 cksstudy]# kubectl -n studyns02 get pods -o wide NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES studypod04 1/1 Running 0 16s 10.10.30.109 worker02 [root@master01 cksstudy]# kubectl -n studyns03 get pods -o wide NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES studypod05 1/1 Running 0 19s 10.10.5.48 worker01 [root@master01 cksstudy]# kubectl -n studyns04 get pods -o wide NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES studypod06 1/1 Running 0 21s 10.10.30.110 worker02 ``` #### 網路測試 ``` [root@master01 cksstudy]# kubectl -n studyns01 exec -ti studypod01 -- /bin/sh # ping -c 1 10.10.5.46 PING 10.10.5.46 (10.10.5.46) 56(84) bytes of data. 64 bytes from 10.10.5.46: icmp_seq=1 ttl=62 time=0.374 ms --- 10.10.5.46 ping statistics --- 1 packets transmitted, 1 received, 0% packet loss, time 0ms rtt min/avg/max/mdev = 0.374/0.374/0.374/0.000 ms # ping -c 1 10.10.5.47 PING 10.10.5.47 (10.10.5.47) 56(84) bytes of data. 64 bytes from 10.10.5.47: icmp_seq=1 ttl=62 time=0.522 ms --- 10.10.5.47 ping statistics --- 1 packets transmitted, 1 received, 0% packet loss, time 0ms rtt min/avg/max/mdev = 0.522/0.522/0.522/0.000 ms # ping -c 1 10.10.30.109 PING 10.10.30.109 (10.10.30.109) 56(84) bytes of data. 64 bytes from 10.10.30.109: icmp_seq=1 ttl=63 time=0.109 ms --- 10.10.30.109 ping statistics --- 1 packets transmitted, 1 received, 0% packet loss, time 0ms rtt min/avg/max/mdev = 0.109/0.109/0.109/0.000 ms # ping -c 1 10.10.5.48 PING 10.10.5.48 (10.10.5.48) 56(84) bytes of data. 64 bytes from 10.10.5.48: icmp_seq=1 ttl=62 time=0.408 ms --- 10.10.5.48 ping statistics --- 1 packets transmitted, 1 received, 0% packet loss, time 0ms rtt min/avg/max/mdev = 0.408/0.408/0.408/0.000 ms # ping -c 1 10.10.30.110 PING 10.10.30.110 (10.10.30.110) 56(84) bytes of data. 64 bytes from 10.10.30.110: icmp_seq=1 ttl=63 time=0.073 ms --- 10.10.30.110 ping statistics --- 1 packets transmitted, 1 received, 0% packet loss, time 0ms rtt min/avg/max/mdev = 0.073/0.073/0.073/0.000 ms ``` ### 安全策略 #### 策略配置 ``` [root@master01 cksstudy]# vi studynp01.yaml apiVersion: networking.k8s.io/v1 kind: NetworkPolicy metadata: name: studynp01 namespace: studyns01 spec: podSelector: matchLabels: role: studypod01 policyTypes: - Ingress - Egress ingress: - from: - ipBlock: cidr: 10.10.0.0/16 except: - 10.10.30.0/24 - namespaceSelector: matchLabels: role: studyns03 - podSelector: matchLabels: role: studypod02 ports: - protocol: TCP port: 5000 egress: - to: - ipBlock: cidr: 10.10.30.0/24 ports: - protocol: TCP port: 5000 [root@master01 cksstudy]# kubectl apply -f studynp01.yaml ``` ***釋義說明:*** + 必須欄位:類似於Kubernetes其他安全策略,NetworkPolicy 資源需要 apiVersion、 kind 和 metadata 欄位。 + pec:NetworkPolicy spec中包含了在一個名稱空間中定義特定網路策略所需的所有資訊。 + podSelector:每個 NetworkPolicy 都包括一個 podSelector,它對該策略所適用的一組 Pod 進行選擇。空的 podSelector 表示匹配名稱空間下的所有 Pod。 + policyTypes: 每個 NetworkPolicy 都包含一個 policyTypes 列表,其中包含 Ingress 或 Egress 或兩者兼具。policyTypes 欄位表示該策略是應用於 進入所選 Pod 的入站流量還是來自所選 Pod 的出站流量,或兩者都進行了配置。 如果 NetworkPolicy 未指定 policyTypes 則預設情況下始終設定 Ingress; 如果 NetworkPolicy 有需要配置任何出口規則的話則必須配置 Egress。 + ingress: 每個 NetworkPolicy 可包含一個 ingress 規則的白名單列表。 每個規則都允許同時匹配 from 和 ports 部分的流量。 + egress: 每個 NetworkPolicy 可包含一個 egress 規則的白名單列表。 每個規則都允許匹配 to 和 port 部分的流量。 如上網路策略示例表示: + 隔離 "studyns01" 名稱空間下 "role:=studypod01" 的 Pod ,即隔離studypod01; + Ingress 規則允許以下 Pod 連線到 "studyns01" 名稱空間下的帶有 "role:=studypod01" 標籤的所有 Pod 的 5000 TCP 埠: + 允許"studyns01" 名稱空間下帶有 "role:=studypod01" 標籤的所有 Pod入; + 允許帶有 "role=studyns03" 標籤的名稱空間中的所有 Pod入; + 允許IP 地址範圍為除了 10.10.30.0/24 之外的所有 10.10.0.0/16入。 + Egress 規則允許從"studyns01" 名稱空間中帶有 "role:=studypod01" 標籤的任何 Pod 到 CIDR 10.0.0.0/16 下 5000 TCP 埠的連線。 #### 策略測試 ##### ingress方向測試 + 擁有10.10.30.0/24 ip的Pod(如studypod04)訪問studypod01(10.10.5.46): ``` [root@master01 ~]# kubectl -n studyns02 exec -ti studypod04 -- /bin/bash root@studypod04:/opt/webapp# nc -v 10.10.30.108 5000 #根據策略應該不通 ``` + 擁有10.10.0.0/16 ip的Pod(如studypod03)訪問studypod01(10.10.5.46): ``` [root@master01 ~]# kubectl -n studyns01 exec -ti studypod03 -- /bin/bash root@studypod03:/opt/webapp# nc -v 10.10.30.108 5000 #根據策略應該能通 Connection to 10.10.30.108 5000 port [tcp/*] succeeded! ``` + 所有studyns03名稱空間下的Pod(如studypod05)訪問studypod01(10.10.5.46): ``` [root@master01 ~]# kubectl -n studyns03 exec -ti studypod05 -- /bin/bash root@studypod05:/opt/webapp# nc -v 10.10.30.108 5000 #根據策略應該能通 Connection to 10.10.30.108 5000 port [tcp/*] succeeded! ``` + 所有帶role=studypod02標籤的Pod(如studypod02)訪問studypod01(10.10.5.46): ``` [root@master01 ~]# kubectl -n studyns01 exec -ti studypod02 -- /bin/bash root@studypod02:/opt/webapp# nc -v 10.10.30.108 5000 #根據策略應該能通 Connection to 10.10.30.108 5000 port [tcp/*] succeeded! ``` ##### egress方向測試 + studypod01訪問擁有10.10.30.0/24 ip的Pod(如studypod06): ``` [root@master01 ~]# kubectl -n studyns01 exec -ti studypod01 -- /bin/bash root@studypod01:/opt/webapp# nc -v 10.10.30.109 5000 #根據策略應該能通 Connection to 10.10.30.109 5000 port [tcp/*] succeeded! ^C root@studypod01:/opt/webapp# nc -v 10.10.30.110 5000 #根據策略應該能通 Connection to 10.10.30.110 5000 port [tcp/*] succeeded! ^C root@studypod01:/opt/webapp# nc -v 10.10.5.46 5000 #根據策略應該不通 ^C ``` #### to和from行為 在 ingress 的 from 部分或 egress 的 to 部分中指定四種選擇器: + podSelector: 此選擇器將在與 NetworkPolicy 相同的名稱空間中選擇特定的 Pod,ingress 的 from 則表示允許該選擇器選定的Pod作為入站流量來源,egress 的 to則表示允許去往該選擇器選定的Pod的出站流量(即該podSelector選定的Pod為目的地)。 + namespaceSelector:此選擇器將選擇特定的名稱空間,應將所有 Pod 用作其入站流量來源或出站流量目的地。 + namespaceSelector 和 podSelector: 一個指定 namespaceSelector 和 podSelector 的 to/from 條目選擇特定名稱空間中的特定 Pod。 示例001:只允許來自帶有user=xhyns標籤的名稱空間下,且帶有role=xhyuser的特定Pod的入請求連線。 ``` ... ingress: - from: - namespaceSelector: matchLabels: user: alice podSelector: matchLabels: role: client ... ``` 示例002:允許來自帶有user=xhyns標籤的名稱空間下的任何Pod,或來自該策略所在名稱空間的帶有role=xhyuser的Pod的入請求連線。 ``` ... ingress: - from: - namespaceSelector: matchLabels: user: xhyns - podSelector: matchLabels: role: xhyuser ... ``` + ipBlock: 此選擇器將選擇特定的 IP CIDR 範圍以用作入站流量來源或出站流量目的地。通常為叢集外部IP,Pod IP通常為隨機產生,使用Pod IP段無實際意義。 #### 預設策略 預設情況下,如果名稱空間中不存在任何策略,則所有進出該名稱空間中 Pod 的流量都被允許。 可通過如下方式修改名稱空間中的預設行為。 + 預設拒絕所有入站流量 禁止進入studyns01名稱空間下的所有Pod的入流量,即預設拒絕所有進入studyns01名稱空間任何Pod的流量。 ``` apiVersion: networking.k8s.io/v1 kind: NetworkPolicy metadata: name: default-deny-ingress namespace: studyns01 spec: podSelector: {} policyTypes: - Ingress ``` > 如上可以當做最後匹配策略,確保即使容器沒有匹配到其他任何 NetworkPolicy,也仍然可以被隔離。 此策略不會更改預設的出口隔離行為。 + 預設允許所有入站流量 允許進入studyns01名稱空間下的所有Pod的入流量,即預設允許所有進入studyns01名稱空間任何Pod的流量。 ``` apiVersion: networking.k8s.io/v1 kind: NetworkPolicy metadata: name: allow-all-ingress namespace: studyns01 spec: podSelector: {} policyTypes: - Ingress ingress: - {} ``` + 預設拒絕所有出站流量 禁止studyns01名稱空間下的所有Pod的出流量,即預設禁止studyns01名稱空間任何Pod的出流量。 ``` apiVersion: networking.k8s.io/v1 kind: NetworkPolicy metadata: name: default-deny-egress namespace: studyns01 spec: podSelector: {} policyTypes: - Egress ``` + 預設允許所有出站流量 允許studyns01名稱空間下的所有Pod的出流量,即預設允許studyns01名稱空間任何Pod的出流量。 ``` apiVersion: networking.k8s.io/v1 kind: NetworkPolicy metadata: name: allow-all-egress namespace: studyns01 spec: podSelector: {} egress: - {} policyTypes: - Egress ``` > 匹配此策略後,能保證即使添加了導致某些 Pod 被視為“隔離”的策略也能顯式的允許該名稱空間中的所有出站流量。 + 預設拒絕所有入口和所有出站流量 禁止studyns01名稱空間下的所有出入流量。 ``` apiVersion: networking.k8s.io/v1 kind: NetworkPolicy metadata: name: default-deny-all spec: podSelector: {} policyTypes: - Ingress - Egress ``` > 如上可以當做最後匹配策略,確保即使沒有被其他任何 NetworkPolicy 選擇的 Pod 也不會被允許入站或出站