📶

複数NICを持つノードで、特定NICを使ってk8sクラスタを構成する

2020/11/03に公開

この記事は何?

下図のように、各マシンで2つのNIC(eth0eth1)が使用されているケースを考えます。

(node0の3つめのNICeth2には実験用機器がありますが、この記事には関係ない…はずでした)

普段インターネットへの接続等に使用しているのはeth0の先の赤色のネットワーク。でもkubernetesのノード間通信には、eth1の先の紫色のネットワークを使ってほしく、各ノードのIPもeth1のものであってほしいとします。
(状況としては、紫のネットワークが赤より高速な場合など)

この要件を満たしたkubernetesクラスタを構築しようとしたものの、意外とハマったので備忘録を残します。

前提条件

  • 各ノード、各NICのIPは固定済、10.0.0.0/24のIPレンジで紫色のネットワークに到達するよう、ルーティングも行っていること。
  • 全てのノードでkubeadmのインストールに従い
    • kubeadmkubeletkubectl がインストールされていること (バージョンは1.16.15-00を使用)
    • ファイアウォール(UFW)が適切に設定済みであること
  • (決め事) node0をマスターノード、node1をワーカーノードとする、シングルコントロールプレーンクラスタを構築する
  • (決め事) CNIプラグインにはcalicoを使用する

普通にクラスタ構築し、問題発生するまで

公式ドキュメントを参考に、クラスタ構築を進めます。

# 初期化
# (心の声) --apiserver-advertise-addressをnode0のeth1のIPにしたから、あとはいい感じに紫色ネットワーク使ってくれるよね
# kubectl join用の認証情報はメモっておく
sudo kubeadm init --control-plane-endpoint=10.0.0.100:6443 \
   --apiserver-advertise-address=10.0.0.100 \
   --pod-network-cidr=10.1.0.0/16

# kubectl で操作できるように
mkdir -p $HOME/.kube
sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config
sudo chown $(id -u):$(id -g) $HOME/.kube/config

# calico インストール
kubectl apply -f https://docs.projectcalico.org/manifests/calico.yaml

# masterノードでもpodを動かせるように
kubectl taint nodes --all node-role.kubernetes.io/master-

# node1をクラスタに追加
# **node1で下記を実行**
node1> sudo kubeadm join 10.0.0.100:6443 --token <token> \
   --discovery-token-ca-cert-hash sha256:<hash>

これでクラスタ構築はおしまい。kubectl init時に--apiserver-advertise-addressをnode0のeth1のIPにしたから、あとはいい感じに紫色ネットワーク使ってくれるよね、と思っていました。

あとはkubernetes-dashboard入れて、他にもアプリケーションデプロイ…と色々設定進めていたところ、問題に気づきました

問題の発覚

kubernetes-dashboardアクセス時にネットワークエラー発生(失念しましたが、503 Bad Gatewayだったかな...?)。
更に調査をすすめると、ノード間の通信が成立していなさそうな雰囲気。

もしやと思って、ノードIPを下記で取得

# -o wide オプションを付けないと、ノードIPは表示されない
> kubectl get node  -o wide
NAME    STATUS   ROLES    AGE   VERSION    INTERNAL-IP   ()
node0   Ready    master   12m   v1.16.15   172.16.0.4    ()
node1   Ready    <none>   5m    v1.16.15   192.168.1.21  ()

INTERNAL-IPが想定と違う。

node0は、全然関係ないはずの実験用機器向けのIPを、node1は赤色ネットワークのIPを使っていた。

対処

色々試したところ、下記2つの施策により、

  • ノード(のINTERNAL-IP)をeth1のアドレスにする
  • eth1の紫色ネットワークでpod間通信を行う

を実現出来ました

1.ノードINTERNAL-IPの変更

こちらの記事を参考に、kubecel起動時の引数を変更してINTERNAL-IPを変更(明示的に指定)します

# kubeletのservice設定ファイルを編集
sudo vim /etc/systemd/system/kubelet.service.d/10-kubeadm.conf

設定ファイル内のEnvironment変数(の中のKUBELET_CONFIG_ARGS)を下記のように変更します

# 変更前
Environment="KUBELET_CONFIG_ARGS=--config=/var/lib/kubelet/config.yaml"
# 変更後
Environment="KUBELET_CONFIG_ARGS=--config=/var/lib/kubelet/config.yaml --node-ip=10.0.0.100"
## node1の場合、10.0.0.101

変更後は下記でサービスを再起動します

sudo systemctl daemon-reload
sudo systemctl restart kubelet

INTERNAL-IPが適切に変更されていることを確認します

> kubectl get node  -o wide
NAME    STATUS   ROLES    AGE   VERSION    INTERNAL-IP   ()
node0   Ready    master   17m   v1.16.15   10.0.0.100    ()
node1   Ready    <none>   12m    v1.16.15   10.0.0.101  ()

2.calicoのBGP Networking設定変更

こちらのドキュメントを参考に、calicoのルーティング設定を変更します。

kubectl set env daemonset/calico-node -n kube-system IP_AUTODETECTION_METHOD=interface=eth1

これで、紫色ネットワークを使用してルーティングを行ってくれます。

所感

(自前でのクラスタ運用、やっぱ面倒…マネージド使いたい)

Discussion