【Kubernetes】 flannel を使ったコンテナ間通信をキャプチャしてみた
Kubernetes (k8s) をデプロイして動作確認をしてみました。Container Networking Interface (CNI) として flannel と Calico の両方を試してみたので、今回は flannel を 利用した場合にノード上のコンテナ間でどのように通信が行われているのか検証した結果をまとめました。
構成
以下のような k8s 環境を構築しました。シングル master とし、Pod 間通信用に NIC を分けています。
仮想マシンのスペックは以下の通りです。
- 2 vCPU
- 3 GB Memory
- CentOS Linux release 7.6.1810
- NIC は 2枚
- NIC1: enp0s3 (Node アクセス、インターネット接続用)
- NIC2: enp0s8 (Pod 間通信用)
ハイパーバイザーは VirtualBox を使用しています。
k8s の構築
公式ドキュメントを参考に構築を行いました。詳しいインストール方法については解説しません。自分がハマったところだけかいつまんで書いていきます。
k8s インストールの準備として、予め以下の設定を行っておきます。
- hostname の設定
- master 1台 : master.lab.com
- worker 3台 : worker1.lab.com, worker2.lab.com, worker3.lab.com
- /etc/hosts の編集
[root@master ~]# cat /etc/hosts | grep \.lab\.com 10.0.0.1 master.lab.com 10.0.0.2 worker1.lab.com 10.0.0.3 worker2.lab.com 10.0.0.4 worker3.lab.com
- SELinux を Permissive に設定
- swap を無効
上記の設定が終わったら、Docker、k8s のインストールに移ります。
- Docker のインストール
- kubelet, kubeadm, kubectl のインストール
これで master / worker ノードの両方に必要なソフトウェアのインストールが完了しました。
引き続き、master ノードで k8s のクラスタ設定を行っていきます。
[root@master ~]# kubeadm init --apiserver-advertise-address 10.0.0.1 --pod-network-cidr=10.244.0.0/16 ..... (snip) You can now join any number of machines by running the following on each node as root: kubeadm join 10.0.0.1:6443 --token **** --discovery-token-ca-cert-hash ****** [root@master ~]#
--apiserver-advertise-address
では、NIC2 が接続している 10.0.0.0/24 のネットワークを利用して k8s ノードの管理用の通信を行うよう指定しています。
--pod-network-cidr
は Pod に払い出す CIDR アドレスを指定しています。10.244.0.0/16 としている理由は、この後に行う flannel デプロイのデフォルト設定と一致させるためです。
flannel の設定ファイルをダウンロードし、Pod 間通信用の NIC を指定します。デフォルトでは、 default route を持つ NIC が選択されます。
[root@master ~]# curl -O https://raw.githubusercontent.com/coreos/flannel/master/Documentation/kube-flannel.yml [root@master ~]# vim kube-flannel.yml [root@master ~]# cat kube-flannel.yml ---snip--- command: - /opt/bin/flanneld args: - --iface=enp0s8 #iface オプションを指定 - --ip-masq - --kube-subnet-mgr resources: ---snip--- [root@master ~]#
編集した設定を使用して flannel をデプロイします。
[root@master ~]# kubectl apply -f kube-flannel.yml podsecuritypolicy.extensions/psp.flannel.unprivileged created clusterrole.rbac.authorization.k8s.io/flannel created clusterrolebinding.rbac.authorization.k8s.io/flannel created serviceaccount/flannel created configmap/kube-flannel-cfg created daemonset.extensions/kube-flannel-ds-amd64 created daemonset.extensions/kube-flannel-ds-arm64 created daemonset.extensions/kube-flannel-ds-arm created daemonset.extensions/kube-flannel-ds-ppc64le created daemonset.extensions/kube-flannel-ds-s390x created [root@master ~]#
[root@worker1 ~]# kubeadm join 10.0.0.1:6443 --token ***--discovery-token-ca-cert-hash ***** # worker2, worker3 でも実行する。
worker ノードの状態が Ready になっていることが確認できます。
[root@master ~]# kubectl get nodes NAME STATUS ROLES AGE VERSION master.lab.com Ready master 31m v1.13.4 worker1.lab.com Ready <none> 102s v1.13.4 worker2.lab.com Ready <none> 98s v1.13.4 worker3.lab.com Ready <none> 95s v1.13.4 [root@master ~]#
system 用の Pod が全て Running となっていれば、K8s + flannel の環境構築は完了です。
[root@master ~]# kubectl get pods -n kube-system NAME READY STATUS RESTARTS AGE coredns-86c58d9df4-2rzz6 1/1 Running 1 31m coredns-86c58d9df4-vs4ph 1/1 Running 1 31m etcd-master.lab.com 1/1 Running 0 30m kube-apiserver-master.lab.com 1/1 Running 0 30m kube-controller-manager-master.lab.com 1/1 Running 0 30m kube-flannel-ds-amd64-l94cx 1/1 Running 0 116s kube-flannel-ds-amd64-vwstv 1/1 Running 0 5m49s kube-flannel-ds-amd64-xdmnv 1/1 Running 0 113s kube-flannel-ds-amd64-zcmnw 1/1 Running 0 2m kube-proxy-5lgpt 1/1 Running 0 31m kube-proxy-dzfhm 1/1 Running 0 116s kube-proxy-f6tzt 1/1 Running 0 2m kube-proxy-mttv2 1/1 Running 0 113s kube-scheduler-master.lab.com 1/1 Running 0 30m [root@master ~]#
flannel を利用した Pod 間の通信確認
以下に示す kube-test.yml を利用して centos のコンテナを3台デプロイし、Pod 間の通信を確認します。
[root@master ~]# cat kube-test.yml apiVersion: extensions/v1beta1 kind: Deployment metadata: name: centos-deployment spec: replicas: 3 selector: matchLabels: app: centos template: metadata: labels: app: centos spec: containers: - name: centos image: centos command: ["/bin/sh","-c","while true; do sleep 3600; done"] [root@master ~]# [root@master ~]# kubectl apply -f kube-test.yml deployment.extensions/centos-deployment created
Pod の状態を確認すると、それぞれ別の worker ノードに Pod がデプロイされ、各 Pod に10.244.0.0/16 から Pod ネットワークが払い出されていることが確認できます。
[root@master ~]# kubectl get pods -o wide NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES centos-deployment-75f6cbcb5d-d7vcb 1/1 Running 0 78s 10.244.3.5 worker3.lab.com <none> <none> centos-deployment-75f6cbcb5d-h22tj 1/1 Running 0 78s 10.244.1.9 worker1.lab.com <none> <none> centos-deployment-75f6cbcb5d-qt7qm 1/1 Running 0 78s 10.244.2.7 worker2.lab.com <none> <none> [root@master ~]#
worker1 にデプロイされている centos のコンテナから、worker2 のコンテナに ping を実行し各 worker ノードの NIC でコンテナ間のパケットをキャプチャしてみます。キャプチャポイントは以下の4点です。
キャプチャした結果より、コンテナから送信されたパケットは worker ノードで VXLAN でカプセル化され、宛先コンテナが動いている worker ノードまで転送されていることがわかります。最終的には worker ノードによってカプセル化が解除され、宛先のコンテナに転送されていることが確認できました。
まとめ
CNI に flannel を使用して、K8s クラスタのデプロイを行い、Pod 間の通信がどのような経路で行われているか確認しました。実際には flannel より Calico の方が k8s の CNI として利用されていることが多いようです。Calico に関しても同じような動作確認を行ったので、次は2つの違いも含めてまとめてみようと思います。