当ウェブサイトは安全と利便性向上のためにクッキー(Cookies)を使用しています。詳細はこちら

法人向けクラウド・ネットワークサービスのUnitas Global

Kubernetes Cluster HA構成 後編「クラスターの作成と検証」

2021年03月16日

事業開発担当マネージャー兼
ネットワークオペレーションセンター長
間庭 一宏

前編に続き後編ではKubernetes HA clusterの構築を進める。

 

Kubernetes Nodeの構築
Kubernetes control-plane nodeとworker nodeを構築する。Cluster構築ツールはkubeadmで、Pod network add-onはflannel、CRIはDockerである。基本的なフローは本家kubernetes.ioと本家Dockerの以下に倣った。

https://kubernetes.io/docs/setup/production-environment/
https://docs.docker.com/engine/install/ubuntu/

 

Control-Plane Nodeの構築
Dockerのインストール
3台のcontrol planeにDockerをインストールする。詳細な手順は本家Dockerのドキュメントに記載されているので、ここで徒に下手な翻訳を繰り返すようなことはしない。一次情報源を当たって欲しい。
Dockerのインストールが終わったら、Dockerデーモンの設定ファイルの/etc/docker/daemon.jsonを忘れずに作成すること。これはKubernetesのドキュメントにある。

 

/etc/docker/daemon.json

{
  "exec-opts": ["native.cgroupdriver=systemd"],
  "log-driver": "json-file",
  "log-opts": {
    "max-size": "100m"
  },
  "storage-driver": "overlay2"
}

 

このファイルの作成を怠ると、後述するkubeadm init時に以下の警告が出る。

I0304 00:32:10.042809    2629 checks.go:102] validating the container runtime
I0304 00:32:10.175750    2629 checks.go:128] validating if the "docker" service is enabled and active
        [WARNING IsDockerSystemdCheck]: detected "cgroupfs" as the Docker cgroup driver. The recommended driver is "systemd". Please follow the guide at https://kubernetes.io/docs/setup/cri/

daemon.jsonには多数のオプションを指定できるが、検証目的ゆえKubernetesのドキュメントの通りとする。

 

補足
「周章狼狽する勿れ」と前置きした上で、2021年後半リリース予定の1.22において、DockerはKubernetesのcontainer runtimeから外される旨が以下に掲載されている。Dockerイメージは引き続きpullもでき健在なのであるが、container runtimeとしてはサポートされないとのことである。

https://kubernetes.io/blog/2020/12/02/dont-panic-kubernetes-and-docker/

尚、本ブログでインストールしたDockerのバージョンは20.10.4である。

# docker version
Client: Docker Engine - Community
 Version:           20.10.4
 …

Server: Docker Engine - Community
 Engine:
  Version:          20.10.4
  …

 

kubeadm、kubelet、kubectlのインストール
クラスター作成ツールのkubeadm、kubeletデーモン及びkubectlのインストール手順も、本家Kubernetesのドキュメント に親切丁寧を極めたものがあるのでここでは繰り返さない。インストールの前に、前提条件であるスワップファイルを無効化とファイアウォールの設定を完了しておくこと。

master1:~# cat /etc/fstab
…
#/swapfile     none     swap     sw     0     0

master1:~# firewall-cmd --zone=public --add-port={6443,2379-2380,10250-10252}/tcp --permanent
master1:~# firewall-cmd --reload
master1:~# firewall-cmd --zone=public --list-ports
6443/tcp 2379-2380/tcp 10250-10252/tcp

flannel向けのファイウォール設定は後述する。

 

Kubernetesクラスターの作成
ここまでの手順でロードバランサーを構築し、Kubernetes control-plane node 3台にDocker、kubeadm、kubelet、kubectlをインストールしたら、Kubernetesクラスターを作成する。

 

Kubernetesクラスター作成の流れは、以下のとおりである。

  • kubeadm initでクラスター1台目のcontrol planeを作成
  • flannelをインストール
  • kubeadm joinで2台のcontrol planeをクラスターに追加

 

1台目のcontrol-plane nodeの構築
kubeadmツールで1台目のcontrol-planeを初期化する。コマンドは「kubeadm init [flags]」で、initは複数のフェーズに分かれている。詳細はこちら を参照されたい。

master1:~# kubeadm init --control-plane-endpoint 192.0.2.100:6443 --upload-certs --pod-network-cidr=10.244.0.0/16 --v=5

 

–control-plane-endpoint 192.0.2.100:6443
API-Serverへの宛先IPアドレスとポートに、ロードバランサーの仮想IPとポートを指定する。worker nodeやkubectlコマンド等、各種API-Serverへの通信は本IPアドレス:ポートに対して行うように、との指定である。

–upload-certs
これによりクラスター間通信で使う証明書が本control-plane nodeに作成される。これは「kubeadm-certs」という名のSecretオブジェクトで、追加のcontrol planeはこの証明書をダウンロードしてクラスターに参加する。説明が前後するが以下がSecretオブジェクトである。

master1:~# kubectl describe secret kubeadm-certs -n kube-system
Name:         kubeadm-certs
Namespace:    kube-system
Labels:       
Annotations:  

Type:  Opaque

Data
====
front-proxy-ca.crt:  1106 bytes
front-proxy-ca.key:  1707 bytes
sa.key:              1703 bytes
sa.pub:              479 bytes
ca.crt:              1094 bytes
ca.key:              1707 bytes
etcd-ca.crt:         1086 bytes
etcd-ca.key:         1707 bytes

–pod-network-cidr=10.244.0.0/16
本検証ではflannelを使うので、flannelのデフォルトネットワークを指定する。以下は後述するflanne.ymlの該当箇所の抜粋である。

kind: ConfigMap
…
net-conf.json: |
    {
      "Network": "10.244.0.0/16",
      "Backend": {
        "Type": "vxlan"
      }
    }
    …

–v=5
デバッグレベルに5を指定する。

Linuxでbashで動かす前提ならちゃんとそう書いてほしい

コマンドを実行すると使用するインターフェイスが決定せられ、各種事前確認(pre-flight checks)が行われる。問題がなければ/etc/kubernetes/pkiフォルダが掘られ各種証明書が用意され、API-Serverを構成する各種静的Podのmanifestファイルが作られ、イメージがpullされ起動する。
無事Pod達が起動し(メッセージ:[apiclient] All control plane components are healthy after 66.502566 seconds)、即ち6443ポートが活きになると、HAProxyの監視でもapi-server1がUPする。

Mar 04 00:34:21 loadbalancer1 haproxy[192558]: [WARNING] 062/003421 (192558) : Server apiserver/api-server1 is UP, reason: Layer6 check passed, check duration: 1ms. 1 active and 0 backup servers online. 0 sessions requeued, 0 total in queue.

 

KeepalivedもHAProxyが活きになったのを受けて、正常なMASTER/BACKUP状態に遷移する。

Mar 04 00:33:49 loadbalancer1 Keepalived_vrrp[45385]: Script `check_haproxy` now returning 0
Mar 04 00:33:55 loadbalancer1 Keepalived_vrrp[45385]: (VI_1) Entering MASTER STATE

 

そしてkubeadm initコマンドの最後にcontrol-plane node及びworker nodeを追加するためのコマンドが提示される。

 

Control-plane node追加用

kubeadm join 192.0.2.100:6443 \
 --token l6ev91.zw6c88y6nd37ctxx \
 --discovery-token-ca-cert-hash sha256:6720510784653492fee8d9c4d7c7fd1d4560d5f5b7f4246cad7133de3abb6e82 \
 --control-plane \
 --certificate-key b7c8581d6d8ea88570ba15ca5a200ed6dd34951f97ba7075b540e63e416fd8a9

 

Worker node追加用

kubeadm join 192.0.2.100:6443 --token l6ev91.zw6c88y6nd37ctxx \
 --discovery-token-ca-cert-hash sha256:6720510784653492fee8d9c4d7c7fd1d4560d5f5b7f4246cad7133de3abb6e82

 

状態確認
kubeadm initコマンドの出力にあるように環境変数KUBECONFIGを設定し、nodeの状態を確認する。

master1:~# export KUBECONFIG=/etc/kubernetes/admin.conf
master1:~# kubectl get nodes
NAME      STATUS     ROLES                  AGE   VERSION
master1   NotReady   control-plane,master   35m   v1.20.4

 

「STATUS」が「NotReady」であるのは、CoreDNS Podが動いていないからである。

master1:~# kubectl get pods -n kube-system
NAME                              READY   STATUS    RESTARTS   AGE
coredns-74ff55c5b-f92vl           0/1     Pending   0          46m
coredns-74ff55c5b-mwjk6           0/1     Pending   0          46m
etcd-master1                      1/1     Running   0          46m
kube-apiserver-master1            1/1     Running   0          46m
kube-controller-manager-master1   1/1     Running   0          46m
kube-proxy-m9t8z                  1/1     Running   0          46m
kube-scheduler-master1            1/1     Running   0          46m

CoreDNSが動かないのは、まだPod network add-onをインストールしていないからである。ここではPod network add-on としてflannelをインストールする。

 

flannelのインストール
flannelをインストールするにあたり、flannelが使うポートをfirewalldで許可する。ポートは採用するバックエンドがUDPかVXLANかで異なる。今回はデフォルトのVXLANを使うので、UDP 8472を許可する。

flannel.yml抜粋

kind: ConfigMap
…
net-conf.json: |
    {
      "Network": "10.244.0.0/16",
      "Backend": {
        "Type": "vxlan"
      }
    }
    …

firewall-cmdの設定

master1:~# firewall-cmd --zone=public --add-port=8472/udp --permanent
master1:~# firewall-cmd --reload
master1:~# firewall-cmd --zone=public --list-ports
6443/tcp 2379-2380/tcp 10250-10252/tcp 8472/udp

flannelをインストールする。

master1:~# kubectl apply -f https://raw.githubusercontent.com/coreos/flannel/master/Documentation/kube-flannel.yml
podsecuritypolicy.policy/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.apps/kube-flannel-ds created

flannelが起動するとpod networkが作成され、pod間通信ができるようになる。これにともないCoreDNSが起動する。

master1:~# kubectl get pods -n kube-system
NAME                              READY   STATUS    RESTARTS   AGE
coredns-74ff55c5b-f92vl           1/1     Running   0          3h29m
coredns-74ff55c5b-mwjk6           1/1     Running   0          3h29m
etcd-master1                      1/1     Running   0          3h29m
kube-apiserver-master1            1/1     Running   0          3h29m
kube-controller-manager-master1   1/1     Running   0          3h29m
kube-flannel-ds-6rcn6             1/1     Running   0          72s
kube-proxy-m9t8z                  1/1     Running   0          3h29m
kube-scheduler-master1            1/1     Running   0          3h29m

以上で1台目のcontrol-plane nodeは完成である。以降、2台目、3台目のcontrol-plane nodeをクラスターに追加する。

 

2台目以降のcontrol-plane nodeのクラスターへの追加
firewalldでflannelのUDPポート8472を許可し、1台目のkubeadm initの最後に表示された「Control-plane node追加用」のコマンドを実行する。ただし、証明書kubeadm-certsは2時間で消えてしまうので、kubeadm init後2時間経過してしまったら再作成する。かくいう私も、仕事をしている振りを装いながら本ブログを執筆していると容赦なく別業務にしょっぴかれてしまった。自席に戻る頃には優に2時間を経過しており、kubeadm-certsは虚しく消えていた。証明書再作成コマンドを発射せねばならない。

kubeadm initは複数のphaseに分かれているので、証明書の作成phaseだけ切り出して実行すればよい。以下のコマンドで証明書のキーが生成され、出力される。

master1:~# kubeadm init phase upload-certs --upload-certs
[upload-certs] Storing the certificates in Secret "kubeadm-certs" in the "kube-system" Namespace
[upload-certs] Using certificate key:
7b89adf0ae835f1b8d572035263047b07380ff7d849b836de140cc2d169cf364

 

2台目以降のcontrol-plane nodeで実行するkubeadm joinコマンドを表示させるには、以下が手っ取り早い。新規でdiscovery tokenを作成すると同時にkubeadm joinコマンドを表示してもらうというものだ。ただし表示されるkubeadm joinコマンドはworker node追加用なので、control-plane nodeを追加するには、先ほどupload-certsで1台目のcontrol-plane nodeに生成した証明書を指定する。

master1:~# kubeadm token create --print-join-command
kubeadm join 192.0.2.100:6443 --token kbcaen.d2cnbu6ntca5259j --discovery-token-ca-cert-hash sha256:6720510784653492fee8d9c4d7c7fd1d4560d5f5b7f4246cad7133de3abb6e82

 

以下のように、–control-planeを指定し、証明書キーを追加したものを、2台目以降のcontrol-planeで実行する。

master2:~# kubeadm join 192.0.2.100:6443 --token kbcaen.d2cnbu6ntca5259j --discovery-token-ca-cert-hash sha256:6720510784653492fee8d9c4d7c7fd1d4560d5f5b7f4246cad7133de3abb6e82 --control-plane --certificate-key 7b89adf0ae835f1b8d572035263047b07380ff7d849b836de140cc2d169cf364

 

HAProxyで2台目のcontrol-planeが活きになる。

Mar 04 23:43:35 loadbalancer1 haproxy[192558]: Server apiserver/api-server2 is UP, reason: Layer6 check passed, check duration: 1ms. 2 active and 0 backup servers online. 0 sessions requeued, 0 total in queue.

 

2台目のcontrol-plane nodeがcontrol planeとして追加された。

master1:~# kubectl get nodes -o wide
NAME      STATUS   ROLES                  AGE    VERSION   INTERNAL-IP      EXTERNAL-IP   OS-IMAGE             KERNEL-VERSION     CONTAINER-RUNTIME
master1   Ready    control-plane,master   22h    v1.20.4   192.0.2.1           Ubuntu 20.04.2 LTS   5.4.0-66-generic   docker://20.10.5
master2   Ready    control-plane,master   3m6s   v1.20.4   192.0.2.2           Ubuntu 20.04.2 LTS   5.4.0-66-generic   docker://20.10.5

 

Control planeを構成する各静的podが2台のcontrol-plane nodeに分散されているのが分かる。尚、CoreDNSに関しては挙動が他のpodと異なる。

master1:~# kubectl get pods -n kube-system -o wide
NAME                              READY   STATUS    RESTARTS   AGE    IP               NODE      NOMINATED NODE   READINESS GATES
coredns-74ff55c5b-f92vl           1/1     Running   2          22h    10.244.0.7       master1              
coredns-74ff55c5b-mwjk6           1/1     Running   2          22h    10.244.0.6       master1              
etcd-master1                      1/1     Running   2          22h    192.0.2.1   master1              
etcd-master2                      1/1     Running   0          5m4s   192.0.2.2   master2              
kube-apiserver-master1            1/1     Running   2          22h    192.0.2.1   master1              
kube-apiserver-master2            1/1     Running   0          5m4s   192.0.2.2   master2              
kube-controller-manager-master1   1/1     Running   3          22h    192.0.2.1   master1              
kube-controller-manager-master2   1/1     Running   0          5m5s   192.0.2.2   master2              
kube-flannel-ds-6rcn6             1/1     Running   2          19h    192.0.2.1   master1              
kube-flannel-ds-w8rc2             1/1     Running   1          5m6s   192.0.2.2   master2              
kube-proxy-m9t8z                  1/1     Running   2          22h    192.0.2.1   master1              
kube-proxy-t5rrs                  1/1     Running   0          5m6s   192.0.2.2   master2              
kube-scheduler-master1            1/1     Running   3          22h    192.0.2.1   master1              
kube-scheduler-master2            1/1     Running   0          5m4s   192.0.2.2   master2              

 

3台目のcontrol-plane nodeをクラスターに追加する。

master3:~# kubeadm join 192.0.2.100:6443 --token kbcaen.d2cnbu6ntca5259j --discovery-token-ca-cert-hash sha256:6720510784653492fee8d9c4d7c7fd1d4560d5f5b7f4246cad7133de3abb6e82 --control-plane --certificate-key 7b89adf0ae835f1b8d572035263047b07380ff7d849b836de140cc2d169cf364

 

3台目のcontrol-plane nodeがcontrol planeとして追加された。

master1:~# kubectl get nodes -o wide
NAME      STATUS   ROLES                  AGE     VERSION   INTERNAL-IP      EXTERNAL-IP   OS-IMAGE             KERNEL-VERSION     CONTAINER-RUNTIME
master1   Ready    control-plane,master   22h     v1.20.4   192.0.2.1           Ubuntu 20.04.2 LTS   5.4.0-66-generic   docker://20.10.5
master2   Ready    control-plane,master   9m44s   v1.20.4   192.0.2.2           Ubuntu 20.04.2 LTS   5.4.0-66-generic   docker://20.10.5
master3   Ready    control-plane,master   110s    v1.20.4   192.0.2.3           Ubuntu 20.04.2 LTS   5.4.0-66-generic   docker://20.10.5

 

以上でcontrol-plane nodeのクラスター構築は完了である。Worker nodeの追加に進む。

 

Worker nodeの構築
Worker nodeとcontrol-plane nodeの構築手順の違いは、クラスターへの参加時にkubeadm joinのオプションに–control-planeを指定するか否かであるため、control-plane nodeと同じ手順でDocker、kubeadm、kubelet、kubectlをインストールする。ファイアウォールで許可するポートだけ異なるため以下に記す。

worker1:~# firewall-cmd --zone=public --add-port={10250,30000-32767}/tcp --permanent
worker1:~# firewall-cmd --zone=public --add-port=8472/udp --permanent
worker1:~# firewall-cmd --reload
worker1:~# firewall-cmd --zone=public --list-ports
10250/tcp 30000-32767/tcp 8472/udp

 

Worker nodeをクラスターに参加させる。

worker1:~# kubeadm join 192.0.2.100:6443 --token kbcaen.d2cnbu6ntca5259j --discovery-token-ca-cert-hash sha256:6720510784653492fee8d9c4d7c7fd1d4560d5f5b7f4246cad7133de3abb6e82

 

Worker nodeがクラスターに追加された。

master1:~# kubectl get nodes
NAME      STATUS   ROLES                  AGE     VERSION
master1   Ready    control-plane,master   27h     v1.20.4
master2   Ready    control-plane,master   4h21m   v1.20.4
master3   Ready    control-plane,master   4h13m   v1.20.4
worker1   Ready                     71s     v1.20.4

 

以上でKubernetes HA clusterは完成である。

 

検証
3台のcontrol-plane nodeのうち一台をシャットダウンし、kubectlが実行できることを以って動作検証完了としてもよいのであるが、せっかく64GBメモリーもあるworker nodeを稼働させているので一つpodを走らせることにした。その上でmaster1をシャットダウンし、該当podの機能が動作し続けることを以って動作検証合格とする。

検証に使うpodは、Kubernetesの名前解決に関するトラブルシュート のページで紹介されているdnsutilsとする。このpodのイメージには名前解決に便利なツールがインストールされており、本ブログ執筆以外でもリアルにお世話になったpodである。Kubernetes cluster内部の名前解決も検証できるため、任意のstateless applicationを走らせるよりもkubernetes clusterの内部構造を窺い知ることができてよいと判断したためである。

ところで検証の前に、3台のcontrol-plane nodeで以下のコマンドを実行する。

master1:~# iptables -t filter -I FORWARD 16 -p udp -m conntrack --ctstate NEW -j ACCEPT

これは検証段階で出くわした不具合に対する苦し紛れの回避策であり、HAの検証にとって重要度は低いため詳細は後回しにする。コマンドの内容は、「filterテーブル内のFORWARDチェインの16行目に、connection tracking(conntrack)で状態がNEWのUDPは許可する」というルールを挿入せよというものである。ちなみに挿入行は必ずしも16行目とは限らない。実行前にiptablesの該当テーブルとチェイン行を確認したところ、該当不具合の箇所が16行目だったのである。

 

Dnsutils podを作成する。

master1:~# kubectl apply -f https://k8s.io/examples/admin/dns/dnsutils.yaml
master1:~# kubectl get pods
NAME       READY   STATUS    RESTARTS   AGE
dnsutils   1/1     Running   0          5s

まずはdnsutilsで名前解決ができることを確認する。

master1:~# kubectl exec -it dnsutils -- nslookup kubernetes.default.svc.cluster.local.
Server:         10.96.0.10
Address:        10.96.0.10#53

Name:   kubernetes.default.svc.cluster.local
Address: 10.96.0.1

ここではお尻にドット「.」付きでkubernetes.default.svc.cluster.local.とFQDN指定しているが、kubernetesやkubernetes.defaultだけでもよろしく名前解決してくれる。CoreDNSが後ろに「default.svc.cluster.local.」を付け足して、解決できるまでトライしてくれるからである。以下は参考までに、”nslookup kubernetes.default”を実行した時のパケットキャプチャである。

03:44:09.300787 IP 10.244.3.3.55212 > 10.244.0.7.domain: 62854+ A? kubernetes.default.default.svc.cluster.local. (62)
03:44:09.302349 IP 10.244.0.7.domain > 10.244.3.3.55212: 62854 NXDomain*- 0/1/0 (155) ←失敗
03:44:09.303306 IP 10.244.3.3.43908 > 10.244.0.7.domain: 38359+ A? kubernetes.default.svc.cluster.local. (54)
03:44:09.303726 IP 10.244.0.7.domain > 10.244.3.3.43908: 38359*- 1/0/0 A 10.96.0.1 (106) ←成功

 

master1をシャットダウンする。

master1:~# shutdown -h now

master2でkubectlコマンドを実行するための環境変数を設定する。

master2:~# export KUBECONFIG=/etc/kubernetes/admin.conf

しばらくすると、CoreDNS pod始めcontrol planeを構成するpodが他のcontrol-plane nodeで稼働し始める。

master2:~# kubectl get pods -n kube-system -o wide
NAME                              READY   STATUS        RESTARTS   AGE     IP               NODE      NOMINATED NODE   READINESS GATES
coredns-74ff55c5b-4tmmz           1/1     Terminating   0          57m     10.244.0.2       master1              
coredns-74ff55c5b-z4pdk           1/1     Terminating   0          57m     10.244.0.3       master1              
coredns-74ff55c5b-c5sgh           1/1     Running       0          3m46s   10.244.3.4       master2              
coredns-74ff55c5b-ggtrq           1/1     Running       0          3m46s   10.244.3.3       master2              
etcd-master1                      1/1     Running       0          57m     192.0.2.1   master1              
etcd-master2                      1/1     Running       0          57m     192.0.2.2   master2              
etcd-master3                      1/1     Running       0          56m     192.0.2.3   master3              
kube-apiserver-master1            1/1     Running       0          57m     192.0.2.1   master1              
kube-apiserver-master2            1/1     Running       0          57m     192.0.2.2   master2              
kube-apiserver-master3            1/1     Running       0          54m     192.0.2.3   master3              
…

以下はetcdの新leader選定が行われている際のログである。

master2:~# kubectl logs etcd-master2 -n kube-system
…
2021-03-08 10:07:44.129986 I | etcdserver/api/etcdhttp: /health OK (status code 200)
2021-03-08 10:07:54.124452 I | etcdserver/api/etcdhttp: /health OK (status code 200)
2021-03-08 10:08:04.124697 I | etcdserver/api/etcdhttp: /health OK (status code 200)
(ここでmaster1をシャットダウン)
raft2021/03/08 10:08:05 INFO: 2dcb5bfc2532f1aa [term 4] received MsgTimeoutNow from 29ecb8f9253d2802 and starts an election to get leadership.
raft2021/03/08 10:08:05 INFO: 2dcb5bfc2532f1aa became candidate at term 5
…
raft2021/03/08 10:08:05 INFO: 2dcb5bfc2532f1aa became leader at term 5

dnsutilsによる名前解決も成功した。

master2:~# kubectl exec -it dnsutils -- nslookup kubernetes.default
Server:         10.96.0.10
Address:        10.96.0.10#53

Name:   kubernetes.default.svc.cluster.local
Address: 10.96.0.1

 

以上でkubernetes HA clusterの動作検証を完了とする。

 

参考
以下は、dnsutilsによる名前解決で遭遇した不具合である。参考までに一部始終を共有しよう。dnsutilsでnslookupを実行したところ、admin prohibitedで名前解決が失敗するというものである。以下はインターフェースens3をtcpdumpした結果である。

10:01:17.683365 IP worker1.44084 > 192.0.2.1.8472: OTV, flags [I] (0x08), overlay 0, instance 1
IP 10.244.3.2.44228 > 10.244.0.2.domain: 38797+ A? kubernetes.default.svc.cluster.local. (54)
10:01:17.683868 IP 192.0.2.1.60753 > worker1.8472: OTV, flags [I] (0x08), overlay 0, instance 1
IP 10.244.0.0 > 10.244.3.2: ICMP host 10.244.0.2 unreachable - admin prohibited, length 90

Worker1のdnsutils podからmaster1のCoreDNS podへ、flannelによりVXLANでカプセル化されpod networkの10.244.0.0/16のアドレスで宛先に届いている。その後、ICMP admin prohibitedが返っている。

明らかにファイアウォールで拒否されているのであるが、firewalldではそのような設定はしておらず、メッセージから推測しても、どうやらバックエンドのiptablesが拒否している可能性が高い。iptablesのルールは、私がfirewalldで設定したルール以外にも、kubernetesやDockerが入れ込んだものでてんこ盛りなのである。
そこでiptablesのトレースをすることにした。既にNetfilterのlogging用モジュールのnf_log_ipv4が有効なので、すぐにiptablesのトレースができる。以下の通りUDP 53をトレース対象とした。

master1:~# iptables -t raw -j TRACE -p udp --dport 53 -I PREROUTING 1

Netfilterで最初に入ってくるrawテーブルのPREROUTINGチェイン1行目にTRACEを仕込んだ。

再度nslookupをさせると/var/log/sysloに以下のログが吐き出された。最後の行がこれである。

Mar  8 02:07:08 master1 kernel: [271253.540926] TRACE: filter:FORWARD:rule:16 IN=flannel.1 OUT=cni0 MAC=62:6d:28:95:48:fe:3e:d3:39:f5:46:2c:08:00 SRC=10.244.3.2 DST=10.244.0.7 LEN=82 TOS=0x00 PREC=0x00 TTL=62 ID=26190 PROTO=UDP SPT=45338 DPT=53 LEN=62

filterテーブルのFORWARDチェインの16行目で止まっているようである。該当テーブルのチェインを調べてみた。

master1:~# iptables -t filter -L FORWARD --line-number
Chain FORWARD (policy DROP)
num  target     prot opt source               destination
…
16   REJECT     all  --  anywhere             anywhere             reject-with icmp-host-prohibited

確かに16行目にICMP admin prohibitedで拒否せよとある。本来であればきちんと該当パケットを拾い上げてFORWARDしてもらいたい。そこで苦肉の策として、以下を仕込んだ次第であった。

master1:~# iptables -t filter -I FORWARD 16 -p udp -m conntrack --ctstate NEW -j ACCEPT

 

終わり

 

最後までお付き合いいただきありがとうございました。

お陰様でINAP Japanは創立20周年を迎えました。設立20周年を記念してINAP Japanオリジナル曲(Rockです)を作り、ボーカリストを公募し、楽器隊は社員とインターンで構成。動画制作会社に依頼して本格的なミュージックビデオを制作中です。そこで私は10年ぶりにドラムを叩くこととなりました。人生何が起こるか分かりませんね。ミュージックビデオでは私が一番目立つよう、目下ドラムを練習しています。

今回のブログ執筆のために、検証中のインスタンスをsnap shotで一時退避してクオータに空きを作って協力してくれたINAP Japan NOCの皆さんに感謝します。株主総会の登記や米国INAP本社の監査対応で忙しい中、明らかに業務と関係のないTera Termの黒い画面を並べている私を優しく見守ってくれた事業戦略部のチームメンバーにも感謝します。

 


執筆者紹介

事業開発担当マネージャー兼
ネットワークオペレーションセンター長
間庭 一宏

事業開発担当マネージャー兼 ネットワークオペレーションセンター長 間庭 一宏

IT業界で長年の就労経験を積み、国内外企業のIT課題を数多く解決してきたベテランエンジニア。鋭い眼力でテクノロジーの事業化に取り組む。INAP Japanの個性あふれるメンバーの中でも、常にポジティブな課題解決力は群を抜き、顧客からの信頼も厚い。衰えを知らぬ成長意欲で若手を引っ張るリーダーである。

各種お問合せ、お見積もり、資料請求に関するご質問を承っております。まずはお気軽にご連絡ください。

ページトップ戻る