CalicoのNetworkPolicyについて確認したのでメモ(前編)
目次
環境
CalicoをNetworkPolicyとして使用する環境下でテスト。
Calicoのバージョンは3.1.3
。
$ kubectl get node -o wide
NAME STATUS ROLES AGE VERSION INTERNAL-IP EXTERNAL-IP OS-IMAGE KERNEL-VERSION CONTAINER-RUNTIME
k8s-master1 Ready master 5d v1.11.3 192.168.110.246 <none> Ubuntu 16.04.5 LTS 4.4.0-72-generic docker://17.3.2
k8s-master2 Ready master 5d v1.11.3 192.168.110.248 <none> Ubuntu 16.04.5 LTS 4.4.0-72-generic docker://17.3.2
k8s-master3 Ready master 5d v1.11.3 192.168.110.244 <none> Ubuntu 16.04.5 LTS 4.4.0-72-generic docker://17.3.2
k8s-node1 Ready <none> 5d v1.11.3 192.168.110.243 <none> Ubuntu 16.04.5 LTS 4.4.0-72-generic docker://17.3.2
k8s-node2 Ready <none> 5d v1.11.3 192.168.110.241 <none> Ubuntu 16.04.5 LTS 4.4.0-72-generic docker://17.3.2
k8s-node3 Ready <none> 5d v1.11.3 192.168.110.247 <none> Ubuntu 16.04.5 LTS 4.4.0-72-generic docker://17.3.2
NetworkPolicyについて
Networkポリシーとは、デフォルトでPodへのアクセスは全て許可されている所へ、Podへのファイアウォールの定義を行うものである。
公式にあるとおり、定義できるものは以下の通り。
- どのPodに適用するのか(podSelectorで指定)
- Policyのタイプ(以下のどちらかまたは指定を指定可能)
- Pod宛の通信
- Podからの通信
- Policyの内容(タイプで指定した通信の詳細を記載。以下のタイプが指定可能)
- ipBlock
- namespaceSelector
- podSelector
NetworkPolicyの作り方
Policyのタイプ
Policyのタイプには、Ingress
とEgress
があり出または入の通信を指定可能。
ipBlock
ipBlockはcidr
とexcept
からなり、ネットワークアドレスを指定することが可能。明示的にネットワークのアドレスが決まっている場合には、便利な設定。
namespaceSelector, podSelector
どのPodに適用するのかやPolicyの内容にて、podSelectorが使用可能。
両方指定されている場合には、namespaceSelectorにてマッチしたネームスペース内のpodSelectorにマッチしたPodが対象となる。
Specを確認すると、LabelSelctor
として定義されていて、指定されるPodはmatchExpressions
とmatchLabels
のAND条件で引っかかったものとなる。
また、空のラベルセレクター({}
)は全てのオブジェクトとマッチする。
matchExpressions
SpecによるとmatchExpressions
はkey
、 operator
、values
からなる。
使い方の例としては、ここの最後に掲載されている通りで、以下のような感じ。
selector:
matchExpressions:
- {key: tier, operator: In, values: [cache]}
- {key: environment, operator: NotIn, values: [dev]}
加えて、operatorにはExists
とDoesNotExist
があり、valueに関係なくlabelのkeyが存在するかどうかで指定可能。
Calicoを使ったNetworkPolicy
準備
NetworkPolicyのためのPodを作成する
Namespace dev
に以下のPodを作成
- pod
red
はラベルapp: red
とenvironment: dev
- pod
blue
はラベルapp: blue
とenvironment: dev
- pod
green
はラベルapp: green
とenvironment: dev
Namespace prod
に以下のPodを作成
- pod
red
はラベルapp: red
とenvironment: prod
- pod
blue
はラベルapp: blue
とenvironment: prod
- pod
green
はラベルapp: green
とenvironment: prod
以下作成に使用したコマンド
本nginxイメージには追加でpingとcurlが使えるようパッケージをインストールしている。
$ kubectl create ns dev
$ kubectl -n dev run red --image=nginx --labels="app=red,environment=dev"
$ kubectl -n dev run blue --image=nginx --labels="app=blue,environment=dev"
$ kubectl -n dev run green --image=nginx --labels="app=green,environment=dev"
$ kubectl create ns prod
$ kubectl -n prod run red --image=nginx --labels="app=red,environment=prod"
$ kubectl -n prod run blue --image=nginx --labels="app=blue,environment=prod"
$ kubectl -n prod run green --image=nginx --labels="app=green,environment=prod"
作成が完了すると以下のようにPodが作成される
$ kubectl get pod -o wide --all-namespaces --show-labels
NAMESPACE NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE LABELS
dev blue-786db8bbc8-pvz95 1/1 Running 0 11s 10.244.3.6 k8s-node1 <none> app=blue,environment=dev,pod-template-hash=3428646674
dev green-98c6b676d-45ktr 1/1 Running 0 11s 10.244.5.43 k8s-node3 <none> app=green,environment=dev,pod-template-hash=547262328
dev red-778f756b64-g69gz 1/1 Running 0 12s 10.244.4.6 k8s-node2 <none> app=red,environment=dev,pod-template-hash=3349312620
prod blue-5ffb74bd54-b7bb8 1/1 Running 0 10s 10.244.3.7 k8s-node1 <none> app=blue,environment=prod,pod-template-hash=1996306810
prod green-74f9c459f8-4b7gz 1/1 Running 0 9s 10.244.5.44 k8s-node3 <none> app=green,environment=prod,pod-template-hash=3095701594
prod red-57799c64cd-xmckh 1/1 Running 0 10s 10.244.4.7 k8s-node2 <none> app=red,environment=prod,pod-template-hash=1335572078
全てのアクセスを禁止する
全ての入と出の通信を禁止するNetworkPolicyをprodのredに設定する。
まずは、他のPodとノードのIPからredに対してICMPが通っていることをNetworkPolicy設定前に確認する。
ノードから。
localadmin@k8s-node1:~$ ping -c 3 10.244.4.7
PING 10.244.4.7 (10.244.4.7) 56(84) bytes of data.
64 bytes from 10.244.4.7: icmp_seq=1 ttl=63 time=1.56 ms
64 bytes from 10.244.4.7: icmp_seq=2 ttl=63 time=0.643 ms
64 bytes from 10.244.4.7: icmp_seq=3 ttl=63 time=0.793 ms
--- 10.244.4.7 ping statistics ---
3 packets transmitted, 3 received, 0% packet loss, time 2000ms
rtt min/avg/max/mdev = 0.643/1.001/1.569/0.407 ms
devのblue podから。
$ kubectl -n dev exec -it blue-786db8bbc8-pvz95 /bin/bash
root@blue-786db8bbc8-pvz95:/# ping -c 3 10.244.4.7
PING 10.244.4.7 (10.244.4.7) 56(84) bytes of data.
64 bytes from 10.244.4.7: icmp_seq=1 ttl=62 time=1.02 ms
64 bytes from 10.244.4.7: icmp_seq=2 ttl=62 time=0.783 ms
64 bytes from 10.244.4.7: icmp_seq=3 ttl=62 time=0.848 ms
--- 10.244.4.7 ping statistics ---
3 packets transmitted, 3 received, 0% packet loss, time 2000ms
rtt min/avg/max/mdev = 0.783/0.886/1.028/0.106 ms
通信が通るので期待通り。
次に、以下のyamlファイルを作成して、設定。
# deny-all.yml
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: all-deny
namespace: prod
spec:
podSelector:
matchLabels:
app: red
environment: prod
policyTypes:
- Ingress
- Egress
$ kubectl apply -f ./deny-all.yaml
networkpolicy.networking.k8s.io/all-deny created
期待動作はすべての通信が通らなくなるはず。
ノードから
localadmin@k8s-node1:~$ ping -c 3 10.244.4.7
PING 10.244.4.7 (10.244.4.7) 56(84) bytes of data.
--- 10.244.4.7 ping statistics ---
3 packets transmitted, 0 received, 100% packet loss, time 2016ms
localadmin@k8s-node1:~$ curl -m 3 http://10.244.4.7
curl: (28) Connection timed out after 3001 milliseconds
同じノードのPodから
$ kubectl -n dev exec -it red-778f756b64-g69gz /bin/bash
root@red-778f756b64-g69gz:/# ping -c 3 10.244.4.7
PING 10.244.4.7 (10.244.4.7) 56(84) bytes of data.
--- 10.244.4.7 ping statistics ---
3 packets transmitted, 0 received, 100% packet loss, time 2000ms
root@red-778f756b64-g69gz:/# curl -m 3 http://10.244.4.7
curl: (28) Connection timed out after 3000 milliseconds
TCP80番ポート以外の入通信を禁止する
TCP80番めがけて入ってくる入りの通信と出の通信は全て許可するNetworkPolicyをprodのにblueに設定する。
まずは、他のPodとノードのIPからblueに対してICMPが通っていることをNetworkPolicy設定前に確認する。
ノードから。
localadmin@k8s-node1:~$ ping -c 3 10.244.3.7
PING 10.244.3.7 (10.244.3.7) 56(84) bytes of data.
64 bytes from 10.244.3.7: icmp_seq=1 ttl=64 time=0.737 ms
64 bytes from 10.244.3.7: icmp_seq=2 ttl=64 time=0.112 ms
64 bytes from 10.244.3.7: icmp_seq=3 ttl=64 time=0.109 ms
--- 10.244.3.7 ping statistics ---
3 packets transmitted, 3 received, 0% packet loss, time 1998ms
rtt min/avg/max/mdev = 0.109/0.319/0.737/0.295 ms
localadmin@k8s-node1:~$
localadmin@k8s-node1:~$ curl http://10.244.3.7
<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
<style>
body {
width: 35em;
margin: 0 auto;
font-family: Tahoma, Verdana, Arial, sans-serif;
}
</style>
</head>
<body>
<h1>Welcome to nginx!</h1>
<p>If you see this page, the nginx web server is successfully installed and
working. Further configuration is required.</p>
<p>For online documentation and support please refer to
<a href="http://nginx.org/">nginx.org</a>.<br/>
Commercial support is available at
<a href="http://nginx.com/">nginx.com</a>.</p>
<p><em>Thank you for using nginx.</em></p>
</body>
</html>
devのblue podから。
$ kubectl -n dev exec -it blue-786db8bbc8-pvz95 /bin/bash
root@blue-786db8bbc8-pvz95:/# ping -c 3 10.244.3.7
PING 10.244.3.7 (10.244.3.7) 56(84) bytes of data.
64 bytes from 10.244.3.7: icmp_seq=1 ttl=63 time=0.670 ms
64 bytes from 10.244.3.7: icmp_seq=2 ttl=63 time=0.098 ms
64 bytes from 10.244.3.7: icmp_seq=3 ttl=63 time=0.134 ms
--- 10.244.3.7 ping statistics ---
3 packets transmitted, 3 received, 0% packet loss, time 2000ms
rtt min/avg/max/mdev = 0.098/0.300/0.670/0.262 ms
root@blue-786db8bbc8-pvz95:/# curl http://10.244.3.7
<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
<style>
body {
width: 35em;
margin: 0 auto;
font-family: Tahoma, Verdana, Arial, sans-serif;
}
</style>
</head>
<body>
<h1>Welcome to nginx!</h1>
<p>If you see this page, the nginx web server is successfully installed and
working. Further configuration is required.</p>
<p>For online documentation and support please refer to
<a href="http://nginx.org/">nginx.org</a>.<br/>
Commercial support is available at
<a href="http://nginx.com/">nginx.com</a>.</p>
<p><em>Thank you for using nginx.</em></p>
</body>
</html>
通信が通るので期待通り。
次に、以下のyamlファイルを作成して、設定。
# allow-ingress-tcp-80.yml
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: allow-ingress-tcp-80
namespace: prod
spec:
podSelector:
matchLabels:
app: blue
environment: prod
policyTypes:
- Ingress
ingress:
- ports:
- protocol: TCP
port: 80
$ kubectl apply -f allow-ingress-tcp-80.yml
networkpolicy.networking.k8s.io/all-deny configured
期待動作はTCP80番ポートへの通信のみが通ること。
また、Podからの通信は通るべき。
ノードから
localadmin@k8s-node1:~$ ping -c 3 10.244.3.7
PING 10.244.3.7 (10.244.3.7) 56(84) bytes of data.
64 bytes from 10.244.3.7: icmp_seq=1 ttl=64 time=0.513 ms
64 bytes from 10.244.3.7: icmp_seq=2 ttl=64 time=0.100 ms
64 bytes from 10.244.3.7: icmp_seq=3 ttl=64 time=0.108 ms
--- 10.244.3.7 ping statistics ---
3 packets transmitted, 3 received, 0% packet loss, time 1998ms
rtt min/avg/max/mdev = 0.100/0.240/0.513/0.193 ms
localadmin@k8s-node1:~$ curl http://10.244.3.7
<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
<style>
body {
width: 35em;
margin: 0 auto;
font-family: Tahoma, Verdana, Arial, sans-serif;
}
</style>
</head>
<body>
<h1>Welcome to nginx!</h1>
<p>If you see this page, the nginx web server is successfully installed and
working. Further configuration is required.</p>
<p>For online documentation and support please refer to
<a href="http://nginx.org/">nginx.org</a>.<br/>
Commercial support is available at
<a href="http://nginx.com/">nginx.com</a>.</p>
<p><em>Thank you for using nginx.</em></p>
</body>
</html>
期待だと、Pingは通らず、TCP80に対するcurlは動作の予定だったが、Pingが届いてしまった。
同じノードからのPodへの通信のため、iptablesが動作していない?っぽい。
後編でここらへんは確認。
ちなみに、違うネームスペースの同じノードのPodからの確認
$ kubectl -n dev exec -it blue-786db8bbc8-pvz95 /bin/bash
root@blue-786db8bbc8-pvz95:/# ping -c 3 10.244.3.7
PING 10.244.3.7 (10.244.3.7) 56(84) bytes of data.
--- 10.244.3.7 ping statistics ---
3 packets transmitted, 0 received, 100% packet loss, time 1999ms
root@blue-786db8bbc8-pvz95:/# curl http://10.244.3.7
<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
<style>
body {
width: 35em;
margin: 0 auto;
font-family: Tahoma, Verdana, Arial, sans-serif;
}
</style>
</head>
<body>
<h1>Welcome to nginx!</h1>
<p>If you see this page, the nginx web server is successfully installed and
working. Further configuration is required.</p>
<p>For online documentation and support please refer to
<a href="http://nginx.org/">nginx.org</a>.<br/>
Commercial support is available at
<a href="http://nginx.com/">nginx.com</a>.</p>
<p><em>Thank you for using nginx.</em></p>
</body>
</html>
期待通り、Pingは通らず、TCP80に対するcurlは動作した。
おわりに
NetworkPolicyの仕様と簡単なNetworkPolicyについてCalicoを使って確認した。
次回ももう少しNetworkPolicyについては。