---
# System prepended metadata

title: K8s NetworkPolicy 深入研討實戰
tags: [K8S]

---

# K8s NetworkPolicy 深入研討實戰

在 NetworkPolicy 規則裡針對一個 pod 如果有 deny 的規則，這時在新增一個 allow 的 NetworkPolicy 規則，則 allow 是會覆蓋掉 deny 的規則。

## 題目一
Context
You need to allow a pod to connect to each other over the network only with two other pods, but not with pods other than these two.

Task
Update Pod `ckad00018-newpod` in namespace ckad00018 to use a Networkpolicy that only allows this pod to send and receive traffic to and from pod `front` and `db`.

* All necessary NetworkPolicy have been established.
* Do not create, modify, or delete any NetworkPolicy while completing this project; you can only use existing NetworkPolicy.

> 在 `ckad00018` namespace 下有 `ckad00018-newpod`、`front`、`db` 這三個 pod，允許 `ckad00018-newpod` pod 可以訪問 `front`、`db` 這兩個 pod，但 `front`、`db` 這兩個 pod 之間不允許互相訪問。


### 環境準備
* 建立 pod
```
$ kubectl create ns ckad00018
namespace/ckad00018 created

$ kubectl -n ckad00018 run front \
  --image=quay.io/cloudwalker/nginx \
  -l "app=front"
pod/front created

$ kubectl -n ckad00018 run db \
  --image=quay.io/cloudwalker/nginx \
  -l "app=db"
pod/db created

$ kubectl -n ckad00018 run ckad00018-newpod \
  --image=quay.io/cloudwalker/nginx \
  -l "app=ckad00018-newpod"
pod/ckad00018-newpod created
```
* 建立 NetworkPolicy 規則
```
$ cat <<EOF | kubectl apply -f -
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: default-deny
  namespace: ckad00018
spec:
  podSelector: {}
  policyTypes:
  - Ingress
EOF

$ cat <<EOF | kubectl apply -f -
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: all-access
  namespace: ckad00018
spec:
  podSelector:
    matchLabels:
      all-access: "true"
  ingress:
  - {}
  egress:
  - {}
EOF

$ cat <<EOF | kubectl apply -f -
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: access-db
  namespace: ckad00018
spec:
  podSelector: 
    matchLabels:
      app: db
  ingress:
  - from:
    - podSelector:
        matchLabels:
          db-access: "true"
  egress:
  - to:
    - podSelector:
        matchLabels:
          db-access: "true"
EOF

$ cat <<EOF | kubectl apply -f -
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: access-front
  namespace: ckad00018
spec:
  podSelector: 
    matchLabels:
      app: front
  ingress:
  - from:
    - podSelector:
        matchLabels:
          front-access: "true"
  egress:
  - to:
    - podSelector:
        matchLabels:
          front-access: "true"
EOF
```
```
$ kubectl -n ckad00018 get po -owide
NAME               READY   STATUS    RESTARTS   AGE     IP             NODE            NOMINATED NODE   READINESS GATES
ckad00018-newpod   1/1     Running   0          5m42s   10.244.41.12   tkdev-worker1   <none>           <none>
db                 1/1     Running   0          5m46s   10.244.42.8    tkdev-worker2   <none>           <none>
front              1/1     Running   0          5m52s   10.244.41.11   tkdev-worker1   <none>           <none>

$ kubectl -n ckad00018 get netpol
NAME           POD-SELECTOR      AGE
access-db      app=db            31s
access-front   app=front         11s
all-access     all-access=true   3m31s
default-deny   <none>            3m36s
```
### 解答

* 在目前情況因為 `default-deny` NetworkPolicy 對每個 pod 都禁止 Ingress(進入) 的流量，因此目前這三個 pod 是互相都連不到的。 

```
$ kubectl -n ckad00018 exec ckad00018-newpod -- curl 10.244.42.8
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
  0     0    0     0    0     0      0      0 --:--:--  0:00:02 --:--:--     0
  
$ kubectl -n ckad00018 exec db -- curl 10.244.41.11
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
  0     0    0     0    0     0      0      0 --:--:--  0:00:02 --:--:--     0
```
* 檢視 `access-db` networkpolicy，允需帶有 `app=db` label 的 pod ，可以接受帶有 `db-access=true` label 進入與出去的流量。
```
$ kubectl -n ckad00018 describe networkpolicy access-db
Name:         access-db
Namespace:    ckad00018
Created on:   2024-11-16 23:24:37 +0800 CST
Labels:       <none>
Annotations:  <none>
Spec:
  PodSelector:     app=db
  Allowing ingress traffic:
    To Port: <any> (traffic allowed to all ports)
    From:
      PodSelector: db-access=true
  Allowing egress traffic:
    To Port: <any> (traffic allowed to all ports)
    To:
      PodSelector: db-access=true
  Policy Types: Ingress, Egress
```
* 檢視 `access-front` networkpolicy，允需帶有 `app=front` label 的 pod ，可以接受帶有 `front-access=true` label 進入與出去的流量。
```
$ kubectl -n ckad00018 describe networkpolicy access-front
Name:         access-front
Namespace:    ckad00018
Created on:   2024-11-16 23:24:57 +0800 CST
Labels:       <none>
Annotations:  <none>
Spec:
  PodSelector:     app=front
  Allowing ingress traffic:
    To Port: <any> (traffic allowed to all ports)
    From:
      PodSelector: front-access=true
  Allowing egress traffic:
    To Port: <any> (traffic allowed to all ports)
    To:
      PodSelector: front-access=true
  Policy Types: Ingress, Egress
```
* 因此這題的作答，就是將 `ckad00018-newpod` pod 貼上 `front-access=true` 與 `db-access=true` label
```
$ tl -n ckad00018 get pods -o wide --show-labels
NAME               READY   STATUS    RESTARTS   AGE   IP             NODE            NOMINATED NODE   READINESS GATES   LABELS
ckad00018-newpod   1/1     Running   0          54m   10.244.41.12   tkdev-worker1   <none>           <none>            app=ckad00018-newpod
db                 1/1     Running   0          54m   10.244.42.8    tkdev-worker2   <none>           <none>            app=db
front              1/1     Running   0          54m   10.244.41.11   tkdev-worker1   <none>           <none>            app=front

$ kubectl -n ckad00018 label pod ckad00018-newpod front-access=true

$ kubectl -n ckad00018 label pod ckad00018-newpod db-access=true
```
* 驗證 `ckad00018-newpod` 可以訪問 `db`、`front` 這兩個 pod，且 `db`、`front` 這兩個 pod 互相是不能溝通的。
```
$ kubectl -n ckad00018 exec ckad00018-newpod -- curl 10.244.42.8
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
100   615  100   615    0     0   393k      0 --:--:-- --:--:-- --:--:--  600k
<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>

$ kubectl -n ckad00018 exec ckad00018-newpod -- curl 10.244.41.11
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
100   615  100   615    0     0   337k      0 --:--:-- --:--:-- --:--:--  600k
<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>

$ kubectl -n ckad00018 exec db -- curl 10.244.41.11
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
  0     0    0     0    0     0      0      0 --:--:--  0:00:02 --:--:--     0
```
### 題外
* 在這個情況下雖然 `ckad00018-newpod` 可以訪問 `db`、`front` 這兩個 pod，但 `db`、`front` 是不能訪問 `ckad00018-newpod` 的，原因是因為 `ckad00018-newpod` 的 Ingress(進入) 的流量被阻擋了。 

```
# 新增這個 NetworkPolicy 後，`front` 就可以訪問 `ckad00018-newpod` 了，`db` 以此類推。
$ cat <<EOF | kubectl apply -f -
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: test
  namespace: ckad00018
spec:
  podSelector: 
    matchLabels:
      app: ckad00018-newpod
  ingress:
  - from:
    - podSelector:
        matchLabels:
          app: front
EOF
```


## 題目二

有兩個 namespace `demo1`、`demo2`，設計 NetworkPolicy 拒絕這兩個 namespace 之間所有網路流量，但只允 `demo1` namespace 下帶有 `app=demo1` 與 `demo2` namespace 下帶有 `app=demo2` 這兩個 label 的 pod 網路可以互通。


### 環境準備
* 建立 pod
```
$ kubectl create ns demo1

$ kubectl create ns demo2

$ kubectl -n demo1 run demo1-front \
  --image=quay.io/cloudwalker/nginx \
  -l "app=demo1"

$ kubectl -n demo2 run demo2-front \
  --image=quay.io/cloudwalker/nginx \
  -l "app=demo2"
```
* 還沒有 NetworkPolicy，所有流量都是互通的
```
$ kubectl -n demo1 get pod -o wide --show-labels
NAME          READY   STATUS    RESTARTS   AGE    IP            NODE            NOMINATED NODE   READINESS GATES   LABELS
demo1-front   1/1     Running   0          118m   10.244.41.4   tkdev-worker1   <none>           <none>            app=demo1

$ kubectl -n demo2 get pod -o wide --show-labels
NAME          READY   STATUS    RESTARTS   AGE   IP            NODE            NOMINATED NODE   READINESS GATES   LABELS
demo2-front   1/1     Running   0          19s   10.244.41.3   tkdev-worker1   <none>           <none>            app=demo2

$ kubectl -n demo1 exec demo1-front -- curl http://10.244.41.3:80
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
  0     0    0     0    0     0      0      0 --:--:-- --:--:-- --:--:--     0<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
```


### 解答

* 設定拒絕 `demo1` namespace 下所有的 pod 出去與進來的流量
```
$ cat <<EOF | kubectl apply -f -
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: deny-all
  namespace: demo1
spec:
  podSelector: {}
  policyTypes:
  - Ingress
  - Egress
EOF
```

* 設定拒絕 `demo2` namespace 下所有的 pod 出去與進來的流量
```
$ cat <<EOF | kubectl apply -f -
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: deny-all
  namespace: demo2
spec:
  podSelector: {}
  policyTypes:
  - Ingress
  - Egress
EOF
```

```
$ kubectl -n demo1 get netpol
NAME       POD-SELECTOR   AGE
deny-all   <none>         58s

$ kubectl -n demo2 get netpol
NAME       POD-SELECTOR   AGE
deny-all   <none>         61s
```

* 在 `demo1` namespace 針對帶有 `app=demo1` label 的 pod 允許接受來自 `demo2` namespace 下帶有 `app=demo2` label 的 pod 過來與過去的流量。
```
$ cat <<EOF | kubectl apply -f -
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: access-front
  namespace: demo1
spec:
  podSelector: 
    matchLabels:
      app: demo1
  ingress:
  - from:
    - namespaceSelector:
        matchLabels: 
          kubernetes.io/metadata.name: demo2
      podSelector:
        matchLabels:
          app: demo2
  egress:
  - to:
    - namespaceSelector:
        matchLabels:
          kubernetes.io/metadata.name: demo2
      podSelector:
        matchLabels:
          app: demo2
EOF
```
* 在 `demo2` namespace 允許帶有 `app=demo2` label 的 pod 接受來自 demo1 namespace 下帶有 `app=demo1` label 的 pod 過來與過去的流量。
```
$ cat <<EOF | kubectl apply -f -
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: access-front
  namespace: demo2
spec:
  podSelector: 
    matchLabels:
      app: demo2
  ingress:
  - from:
    - namespaceSelector:
        matchLabels: 
          kubernetes.io/metadata.name: demo1
      podSelector:
        matchLabels:
          app: demo1
  egress:
  - to:
    - namespaceSelector:
        matchLabels:
          kubernetes.io/metadata.name: demo1
      podSelector:
        matchLabels:
          app: demo1
EOF
```
* 驗證兩個 namespace 之間只允許帶有 `app=demo1` 與 `app=demo2` 這兩個 label 的 pod 網路互通。
```
$ kubectl -n demo1 exec demo1-front -- curl http://10.244.41.3:80
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
  0     0    0     0    0     0      0      0 --:--:-- --:--:-- --:--:--     0<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>

$ kubectl -n demo2 exec demo2-front -- curl http://10.244.41.4:80
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
  0     0    0     0    0     0      0      0 --:--:-- --:--:-- --:--:--     0<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
```