EKSでCalicoを使ってみた[2. ネットワークポリシーを使ってみた編]


『IT自動化の力でビジネス加速を全ての企業に』

”IT自動化の専門会社”、リアルグローブ・オートメーティッド(RGA)の技術ブログ編集部の馬塚です。本日もRGAの技師がまとめた技術情報を読者の皆様にお届けしていきます!

以前配信した「EKSでCalicoを使ってみた[1.インストール編]」で、Amazon EKSのCNIをデフォルトのamazon-vpc-cni-k8sからCalicoネットワークプラグインに変更することのメリットとして、Pod数の上限を解除できることを紹介しました。多数のPodを稼働させる必要があるプロジェクトにおいては、まさに救世主的なプラグインなのですが、実はCalicoを使うことのメリットは、これ以外にもあります。

今回はそのもう1つの大きなメリットについて知っていただければと思い、記事にまとめました。ネットワークポリシーに関するややディープな話となりますが、是非お付き合いいただければと思います。

――――――――――――――――――――――――――――――――――

前回の記事では、EKSデフォルトの amazon-vpc-cni-k8s ネットワーキングプラグインの代わりに Calico ネットワーキングプラグインを使用し、ノードあたりのPod数制限を回避する方法をご紹介しました。

しかし、Calicoネットワークプラグインを導入することで得られるメリットはそれだけではありません。Calicoのネットワークポリシー機能(マイクロサービスにおけるネットワークセキュリティー機能)も使えるようになります。

実はCalicoといえばこちらのネットワークセキュリティー機能の方が有名で、"calico"と検索してヒットする記事のほとんどがこちらの機能について言及されたものでした。(EKSのノード当たりのPod数制限を回避する目的で導入するという話はおそらくかなりのレアケースです)

今回はこのCalicoのネットワークポリシー機能の概要と動作検証の結果をご紹介します。

補足: 前回の記事でも少し触れましたが、amazon-vpc-cni-k8s を使用しながら、Calicoのネットワークポリシー機能を使用することもできます。ノード当たりのPod数制限が重大な問題とはならない場合は、こちらの方法でCalicoを導入した方が手軽で良さそうです。 

ちなみにCalicoは、ネットワーキング、IPAM、ポリシー機能などの機能がモジュール化して設計されているため、それぞれ独立して利用することが可能になっているようです。(Exploring the Networking Foundation for EKS: amazon-vpc-cni-k8s + Calico
そのため、下表のようにネットワークポリシー機能のみを利用する構成を取ることができます。

画像1

(参考: https://docs.projectcalico.org/getting-started/kubernetes/managed-public-cloud/eks#install-eks-with-calico-networking

KubernetesのネットワークポリシーとCalicoのネットワークポリシーについて

実は今回の記事内では、KubernetesのネットワークポリシーとCalicoのネットワークポリシーという2種類のネットワークポリシーが登場します。
まずは、それぞれの違いをご紹介します。

Kubernetesのネットワークポリシー

Kubernetesにおけるネットワークポリシーとは、Pod間通信のルールを規定するものです。KubernetesはデフォルトではPod間の通信に制限はなく、クラスタ上のすべてのPodと自由に通信することができます。ネットワークポリシーを使うことでPod間通信に制限を与えることができます。

このネットワークポリシー機能は全てのKubernetes環境で利用できるわけではありません。ネットワークポリシーに対応したネットワークプラグインを使用しているときのみ利用することができます。

KubernetesはNetwork Policy API を用意することで、ユーザーがネットワークポリシーを定義するための "方法" を提供しています。そのためユーザーはネットワークプラグインの違いを意識せずにネットワークポリシー機能を使用することができます。
(参考: Get started with Kubernetes network policy

Calicoのネットワークポリシー

Calicoのネットワークポリシーは、Kubernetesのネットワークポリシーのスーパーセットです。KubernetesのNetwork Policy APIに定義されている機能だけでなく、Calicoの独自機能も使うことができます。
例えば、

・ポリシーの優先順位付け
・より柔軟な一致ルール
・Pod、VM、ホストインターフェースを含む複数のタイプのエンドポイントにルールを適用(KubernetesのネットワークポリシーはPodにのみ適用)

などの機能が追加されています。
他にも色々あるようなので以下の参考リンクを参照して下さい。
(参考: Get started with Calico network policy

動作検証

calicoctl のインストール

Calicoのネットワークポリシーを操作するためには calicoctl というコマンドラインツールが必要なのでインストールします。
インストール方法はこちらです。
本検証ではmacにbrewでインストールしました。

$ brew install calicoctl

calicoctl から Kubernetes API datastore への接続設定も必要です。
これも何種類かの設定方法があり、こちらで紹介されています。
今回の検証では次のように設定しました。

$ export DATASTORE_TYPE=kubernetes
$ export KUBECONFIG=~/.kube/config

正常に設定できていれば、次のように calicoctl コマンドが使えるようになります。

$ calicoctl get nodes
NAME
ip-192-168-36-230.ap-northeast-1.compute.internal
ip-192-168-81-67.ap-northeast-1.compute.internal

ちなみに、接続設定が正しくできていないと次のようなエラーがでます。

$ calicoctl get node
Failed to create Calico API client: no etcd endpoints specified

検証環境の用意

まずは、次のような検証環境を用意します。

画像2

$ kubectl create ns test-ns1
$ kubectl label ns test-ns1 ns=test-ns1
$ kubectl create ns test-ns2
$ kubectl label ns test-ns2 ns=test-ns2
$ kubectl run -n test-ns1 debug --image=nginx:latest --labels="app=debug"
$ kubectl run -n test-ns1 nginx --image=nginx:latest --labels="app=nginx"
$ kubectl run -n test-ns2 nginx --image=nginx:latest --labels="app=nginx"

Namespace "test-ns1" に作成した Pod "debug" から各 Namespace の Pod  "nginx" に疎通確認を行い。NetworkPolicy の動作確認をしていきます。
そのために、各 "nginx" Pod のIPを確認しておきます。

$ kubectl get -n test-ns1 pod -o wide
NAME    READY   STATUS    RESTARTS   AGE   IP               NODE                                                NOMINATED NODE   READINESS GATES
debug   1/1     Running   0          67s   172.16.173.133   ip-192-168-36-230.ap-northeast-1.compute.internal   <none>           <none>
nginx   1/1     Running   0          49s   172.16.26.4      ip-192-168-81-67.ap-northeast-1.compute.internal    <none>           <none>

$ kubectl get -n test-ns2 pod -o wide
NAME    READY   STATUS    RESTARTS   AGE   IP            NODE                                               NOMINATED NODE   READINESS GATES
nginx   1/1     Running   0          48s   172.16.26.5   ip-192-168-81-67.ap-northeast-1.compute.internal   <none>           <none>
test-ns1nginx: 172.16.26.4
test-ns2nginx: 172.16.26.5

デフォルト状態ではどのPodとも疎通可能であることを確認します。
1. test-ns1 の "debug" Podから test-ns1 の "nginx" Podに接続できるか確認

$ kubectl exec -n test-ns1 -it debug -- curl -m 3 -I 172.16.26.4
HTTP/1.1 200 OK
Server: nginx/1.19.1
Date: Sun, 26 Jul 2020 11:45:45 GMT
Content-Type: text/html
Content-Length: 612
Last-Modified: Tue, 07 Jul 2020 15:52:25 GMT
Connection: keep-alive
ETag: "5f049a39-264"
Accept-Ranges: bytes

2. test-ns1 の "debug" Podから test-ns2 の "nginx" Podに接続できるか確認

$ kubectl exec -n test-ns1 -it debug -- curl -m 3 -I 172.16.26.5
HTTP/1.1 200 OK
Server: nginx/1.19.1
Date: Sun, 26 Jul 2020 11:59:53 GMT
Content-Type: text/html
Content-Length: 612
Last-Modified: Tue, 07 Jul 2020 15:52:25 GMT
Connection: keep-alive
ETag: "5f049a39-264"
Accept-Ranges: bytes

画像3

calico の GlobalNetworkPolicy の作成

まずは、全インバウンドを拒否する Calico の GlobalNetworkPolicy を作成してみます。

GlobalNetworkPolicy はクラスタ全体に適用されるポリシーです。次の設定をすることで、全Namespaceの全Podが他のPodからのインバウンドを拒否するようになります。

$ calicoctl apply -f - <<EOF
apiVersion: projectcalico.org/v3
kind: GlobalNetworkPolicy
metadata:
 name: default-deny
spec:
 selector: all()
 types:
 - Ingress
EOF

作成したオブジェクトを確認してみます。

$ calicoctl get globalNetworkPolicy
NAME
default-deny

では、実際にどのPodとも疎通できなくなっているか確認します。
1. test-ns1 の "debug" Podから test-ns1 の "nginx" Podに接続できるか確認

$ kubectl exec -n test-ns1 -it debug -- curl -m 3 -I 172.16.26.4
curl: (28) Connection timed out after 3000 milliseconds
command terminated with exit code 28

2. test-ns1 の "debug" Podから test-ns2 の "nginx" Podに接続できるか確認

$ kubectl exec -n test-ns1 -it debug -- curl -m 3 -I 172.16.26.5
curl: (28) Connection timed out after 3000 milliseconds
command terminated with exit code 28

想定どおり、どのPodとも疎通できなくなっています。

画像4

Kubernetes の NetworkPolicy を作成する

次は、test-ns1 に Kubernetes の NetworkPolicy を作成してみます。

NetworkPolicy オブジェクトは Namespace に拘束されるオブジェクトです。作成したNamespace内のPodにのみ効力が発生します。

ここでは、"app: nginx" というラベルのついたPodは "app: debug" というラベルがついたPodからのトラフィックを許可する設定をしています。

$ kubectl -n test-ns1 apply -f - <<EOF
kind: NetworkPolicy
apiVersion: networking.k8s.io/v1
metadata:
 name: allow-debug-to-nginx
spec:
 podSelector:
   matchLabels:
     app: nginx
 policyTypes:
 - Ingress
 ingress:
 - from:
   - podSelector:
       matchLabels:
         app: debug     
EOF

1. test-ns1 の "debug" Podから test-ns1 の "nginx" Podに接続できるか確認

$ kubectl exec -n test-ns1 -it debug -- curl -m 3 -I 172.16.26.4
HTTP/1.1 200 OK
Server: nginx/1.19.1
Date: Sun, 26 Jul 2020 11:45:45 GMT
Content-Type: text/html
Content-Length: 612
Last-Modified: Tue, 07 Jul 2020 15:52:25 GMT
Connection: keep-alive
ETag: "5f049a39-264"
Accept-Ranges: bytes

2. test-ns1 の "debug" Podから test-ns2 の "nginx" Podに接続できるか確認

$ kubectl exec -n test-ns1 -it debug -- curl -m 3 -I 172.16.26.5
curl: (28) Connection timed out after 3000 milliseconds
command terminated with exit code 28

新たに、NetworkPolicy オブジェクトを作成したことで、test-ns1 の "nginx" Podとは通信ができるようになりました。

画像5

ちなみに、Kubernetes の NetworkPolicy は、kubectl でも calicoctl でも確認することができます。

$ kubectl get networkpolicy -n test-ns1
NAME                        POD-SELECTOR   AGE
allow-debug-to-nginx   app=nginx      4m34s
$ calicoctl get networkpolicy -n test-ns1
NAMESPACE   NAME
test-ns1    knp.default.allow-debug-to-nginx

Calico の NetworkPolicy の作成

次は、Calicoの NetworkPolicy を作成してみます。

内容は test-ns2 の "nginx" Podが test-ns1 の "debug" Podからのインバウンドを許可する設定にします。

Kubernetes と Calico では apiVersion が違うだけではなく、ポリシーの書き方も少し違います。

$ calicoctl apply -f - <<EOF
apiVersion: projectcalico.org/v3
kind: NetworkPolicy
metadata:
 name: allow-debug-to-nginx
 namespace: test-ns2
spec:
 selector: app == 'nginx'
 ingress:
 - action: Allow
   protocol: TCP
   source:
     selector: app == 'debug'
     namespaceSelector: ns == 'test-ns1'
   destination:
     ports:
     - 80
EOF

test-ns1 の "debug" podから test-ns2 の "nginx" podに接続できるようになったか確認してみます。

$ kubectl exec -n test-ns1 -it debug -- curl -m 3 -I 172.16.26.5
HTTP/1.1 200 OK
Server: nginx/1.19.1
Date: Sun, 26 Jul 2020 12:09:21 GMT
Content-Type: text/html
Content-Length: 612
Last-Modified: Tue, 07 Jul 2020 15:52:25 GMT
Connection: keep-alive
ETag: "5f049a39-264"
Accept-Ranges: bytes

接続できるようになりました。

画像6

なお、Calico の API で作成した NetworkPolicy は、calicoctl からは確認できますが、kubectl からは確認できませんでした。

$ calicoctl get networkpolicy -n test-ns2
NAMESPACE   NAME
test-ns2    allow-debug-to-nginx
$ kubectl get networkpolicy -n test-ns2
No resources found in test-ns2 namespace.

まとめ

以上の結果から、Kubernetes と Calico どちらの ネットワークポリシーも作成可能であることが確認できました。

先にご紹介したように、Calicoのネットワークポリシーは Kubernetes のそれのスーパーセットなので、Kubernetes には存在しない機能もたくさんあります。

しかし、Calicoの独自機能を使ってしまうとCalicoにロックインされるというデメリットもあるため、環境に合わせてCalico独自機能を使うか使わないか決める必要があります。

ちなみに今回はCalicoの検証が目的だったため、シンプルなネットワークポリシーしか作成しませんでしたが、Calico公式では本番環境でのベストプラクティスなども紹介しています。

より実践的な使い方を知りたい場合はこちらもご参照ください。

参考

Project Calico 公式サイト … calicoのインストールや設定方法など。
Kubernetes 公式サイト … ネットワークポリシーに対応するネットワークプラグインの一覧情報。
クラウドネイティブ時代のネットワークOSS Project Calicoを理解する … Calicoについて詳しく記述されている貴重な日本語記事。

執筆者:株式会社リアルグローブ・オートメーティッド技師 青島――――――――――――――――――――――――――――――――――

執筆者プロフィール:青島 秀治
株式会社リアルグローブ・オートメーティッド 技師
九州大学大学院理学府博士課程中退。
大学院では理論天文学が専門。数値計算プログラム開発の傍ら、研究用の計算機郡や学内システムの開発・運用を経験。
2019年よりAnsibleを用いた運用作業自動化や自社サービスのKubernetes移行、OpenShiftのインフラCI実装などの業務に従事。

【ご案内】
ITシステム開発やITインフラ運用の効率化、高速化、品質向上、その他、情シス部門の働き方改革など、IT自動化導入がもたらすメリットは様々ございます。
IT業務の自動化にご興味・ご関心ございましたら、まずは一度、IT自動化の専門家リアルグローブ・オートメーティッド(RGA)にご相談ください!

お問合せは以下の窓口までお願いいたします。

【お問い合わせ窓口】
株式会社リアルグローブ・オートメーティッド
代表窓口:info@rg-automated.jp
URL: https://rg-automated.jp

画像1

(編集:馬塚勇介/校正:水谷裕一)