Calicoを使ったNetworkPolicyについての動作確認(前編)

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のタイプには、IngressEgressがあり出または入の通信を指定可能。

ipBlock

ipBlockはcidrexceptからなり、ネットワークアドレスを指定することが可能。明示的にネットワークのアドレスが決まっている場合には、便利な設定。

namespaceSelector, podSelector

どのPodに適用するのかやPolicyの内容にて、podSelectorが使用可能。
両方指定されている場合には、namespaceSelectorにてマッチしたネームスペース内のpodSelectorにマッチしたPodが対象となる。
Specを確認すると、LabelSelctorとして定義されていて、指定されるPodはmatchExpressionsmatchLabelsのAND条件で引っかかったものとなる。
また、空のラベルセレクター({})は全てのオブジェクトとマッチする。

matchExpressions

SpecによるとmatchExpressionskeyoperatorvaluesからなる。
使い方の例としては、ここの最後に掲載されている通りで、以下のような感じ。

selector:
  matchExpressions:
    - {key: tier, operator: In, values: [cache]}
    - {key: environment, operator: NotIn, values: [dev]}

加えて、operatorにはExistsDoesNotExistがあり、valueに関係なくlabelのkeyが存在するかどうかで指定可能。

Calicoを使ったNetworkPolicy

準備

NetworkPolicyのためのPodを作成する

Namespace devに以下のPodを作成

  • pod red はラベルapp: redenvironment: dev
  • pod blue はラベルapp: blueenvironment: dev
  • pod green はラベルapp: greenenvironment: dev

Namespace prodに以下のPodを作成

  • pod red はラベルapp: redenvironment: prod
  • pod blue はラベルapp: blueenvironment: prod
  • pod green はラベルapp: greenenvironment: 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については。

コメントを残す

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です

このサイトはスパムを低減するために Akismet を使っています。コメントデータの処理方法の詳細はこちらをご覧ください