附029.Kubernetes安全之網路策略
阿新 • • 發佈:2020-12-23
[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 也不會被允許入站或出站