calicoの設定はサボるな

TL;DR

  • NetworkManagerとの競合を防ぐためNetworkManagerで一部インターフェイスはマネジメントしないように設定する。

  • calico daemonsetsのIP_AUTODETECTION_METHODをfirst-foundからcidrsに切り替えることでちゃんと通信先のNICを指定する。


タイトルの通り。

kubernetesクラスタを構築する際にcalicoの設定をサボった結果あとから痛い目に遭遇したのでそれの共有でもしていきます。

我が家のkubernetesはCNIにcalicoを使っており、特別な設定をせずにQuick Startそのまんまでデプロイしていた。

しばらくはそれでPodにちゃんとIPアドレスが割り当てられていたし、Ingressを設定しても問題なく疎通があった。

さて、しばらくはそんな感じでいくつかのPodを上げては壊しを繰り返しいろいろ実験していました。

そうするとやはりというかなんというか、リソース不足に陥るわけです。

特にメモリが不足しており、OOM Killが走り他のノードに割り当て直されそこでもOOM Killが走り・・・ということが起きていました。

というわけで普段踏み台としてしか使っていないそれなりにスペックのあるミニPCと普段はゲームくらいでしか酷使されないメインマシンをKubernetesクラスタに突っ込んでしまうことにしました。

普段踏み台とかメインとして使っているホストをKubernetesのノードとして動かす試みというのはあまりないわけですので、まあいろいろ面倒は出てきます。

その最たる例はcalicoでした。

calicoはCNI Container Network Interface Pluginと呼ばれるものでコンテナ間のネットワークを司るKubernetesのネットワークプラグインです。

このcalicoが例の新しく追加しようとしたノード上ではうまく動きませんでした。

その原因は以下2つです。

  • NetworkManagerとの競合

  • Interfaceの疎通不可能NICを自動選択したことによる疎通不可能状態

NetworkManagerとの競合

これはかなり有名なお話のようでcalicoの公式ドキュメントのTrouble Shootingのところに記載あるのでこちらを参照してもらえればなと思います。

https://docs.tigera.io/calico/latest/operations/troubleshoot/troubleshooting

NetworkManagerがcalicoのルーティングテーブルと競合した結果、calicoのルーティングの方を優先させようとしたと思われますがデフォルトゲートウェイのmetricがものすごい大きい数が割り当てられており、あらゆる通信がcalicoの方に流れるという問題が生じました。

その結果ホスト自体の通信が落ちてしまいSSHもつながらないとひどい状態に陥りました。

というわけで、そうならないようにNetworkManager側にはそれを是正するような設定を記載しました。

[keyfile]
unmanaged-devices=interface-name:cali*;interface-name:tunl*;interface-name:vxlan.calico;interface-name:vxlan-v6.calico;interface-name:wireguard.cali;interface-name:wg-v6.cali

ひとまずNetworkManager関連の競合問題はこれで解決しました。

Interfaceの疎通不可能NICを自動選択したことによる疎通不可能状態

こちらは仕事の忙しさも相まってかなり長い期間悩まされてきましたが、昨日ようやく解決に至ったのでご報告いたします。

この問題はまず最初稀にIngressの疎通ができないな〜という問題から始まりました。

そのときは稀に通信ができない程度だったのでDNSが原因だろうかとcorednsの設定を見たりなんやらしていた記憶があります。

Pod自体の問題かとか、Serviceリソースの設定がなにかおかしいのかとかかなり的外れなことを調べていましたが、

なんだかんだいろいろ試していくうちに新しく追加したミニPCとメインマシンへのPodのみ通信ができなくなるということが分かりました。

その頃は、まあいろいろあって一部システムを止めていたこともあったので一旦ノードをcordonしてどう解決していこうか検討していこうということでお茶を濁しました。

その結果、いろいろ仕事が忙しかったり、なんか6月病みたいなものになって休日も何もできない日々がずーっと続いていたので放置していました。

k8s自体も放置していましたし、まだモニタリングシステムもなんの整備もしていないのでアラートが鳴るということもなかったわけです。

そうこう過ごしてるうちに、またおうちk8sをいじりたいという気持ちが昂ぶり、さあいじるか〜 -> あれリソース足らねえ -> あ、cordonしてたわ〜と長い間放置していた前の記憶を掘り起こし、重い腰上げて根本原因調査するか〜とはじめました。

お仕事でもKubernetesクラスタのメンテナンスや障害対応をしていたため、だいぶ見るべきところが見えてきて数ヶ月前になんとな〜く公式ドキュメント通りにデプロイしたcalicoが怪しいな〜とたどりつきました。

見てみると、なんと一部ホストでcalico-node-***というPodがちゃんと動いていないと

 $ k get pods -n calico-system
 NAME                                       READY   STATUS    RESTARTS        AGE
 calico-kube-controllers-558b7d9cf4-rslz8   1/1     Running   313 (22h ago)   227d
 calico-node-28xr4                          1/1     Running   23 (7h2m ago)   227d
 calico-node-45xkr                          1/1     Running   0               10d
 calico-node-5qrz5                          1/1     Running   16 (10d ago)    226d
 calico-node-6xjgq                          1/1     Running   0               10d
 calico-node-fkf9d                          1/1     Running   16 (10d ago)    227d
 calico-node-k62hq                          1/1     Running   22 (8d ago)     76d
 calico-node-nnjkr                          1/1     Running   25 (44d ago)    227d
 calico-node-smxkd                          0/1     Running   0               38m
 calico-node-snq2d                          1/1     Running   25              227d
 calico-typha-996fb9cc7-fgtms               1/1     Running   21 (44d ago)    227d
 calico-typha-996fb9cc7-m8ftm               1/1     Running   27 (10d ago)    227d
 calico-typha-996fb9cc7-tdg8k               1/1     Running   20 (44d ago)    227d
 csi-node-driver-4c62z                      2/2     Running   42 (8d ago)     81d
 csi-node-driver-6blck                      2/2     Running   26 (44d ago)    227d
 csi-node-driver-7rqxd                      2/2     Running   0               10d
 csi-node-driver-cnzcp                      2/2     Running   32 (10d ago)    226d
 csi-node-driver-d5mss                      2/2     Running   27 (44d ago)    227d
 csi-node-driver-fldqr                      2/2     Running   0               38d
 csi-node-driver-s2jpt                      2/2     Running   32 (10d ago)    227d
 csi-node-driver-t6f4z                      2/2     Running   0               10d
 csi-node-driver-xd8vc                      2/2     Running   26 (44d ago)    227d

で、そのPodをdescribeしてみるとなーんかBIRDのconnectionがうまくいってないことが分かります。

Events:
   Type     Reason     Age   From               Message
   ----     ------     ----  ----               -------
   Normal   Scheduled  41m   default-scheduler  Successfully assigned calico-system/calico-node-smxkd to einsteinium
   Normal   Pulled     41m   kubelet            Container image "docker.io/calico/pod2daemon-flexvol:v3.26.1" already present on machine
   Normal   Created    41m   kubelet            Created container flexvol-driver
   Normal   Started    41m   kubelet            Started container flexvol-driver
   Normal   Pulled     41m   kubelet            Container image "docker.io/calico/cni:v3.26.1" already present on machine
   Normal   Created    41m   kubelet            Created container install-cni
   Normal   Started    41m   kubelet            Started container install-cni
   Normal   Pulled     41m   kubelet            Container image "docker.io/calico/node:v3.26.1" already present on machine
   Normal   Created    41m   kubelet            Created container calico-node
   Normal   Started    41m   kubelet            Started container calico-node
   Warning  Unhealthy  41m   kubelet            Readiness probe failed: calico/node is not ready: BIRD is not ready: Error querying BIRD: unable to connect to BIRDv4 socket: dial unix /var/run/calico/bird.ctl: connect: connection refused
 W0626 11:17:59.370689      24 feature_gate.go:241] Setting GA feature gate ServiceInternalTrafficPolicy=true. It will be removed in a future release.
   Warning  Unhealthy  41m  kubelet  Readiness probe failed: calico/node is not ready: BIRD is not ready: Error querying BIRD: unable to connect to BIRDv4 socket: dial unix /var/run/calico/bird.ctl: connect: connection refused
 W0626 11:18:00.347606      62 feature_gate.go:241] Setting GA feature gate ServiceInternalTrafficPolicy=true. It will be removed in a future release.
   Warning  Unhealthy  41m  kubelet  Readiness probe failed: 2024-06-26 11:18:07.119 [INFO][365] confd/health.go 180: Number of node(s) with BGP peering established = 0

さて、ここでまずはこのBIRDが使うであろうポート179が空いてるかなぁと見ていきますが案の定繋がりはするわけです。

https://docs.tigera.io/calico/latest/getting-started/kubernetes/requirements

$ curl *****:179
つながりはするけどホストのサービス側(calico)から落とされる
$ telnet *****:179
上と同様

となると179ポート自体は閉じていない。

もちろんufw自体も停止しているので阻むものは何もありませんでした。

そうこうして調べていくうちに以下のstackoverflowにたどり着き、どうやらIP_AUTODETECTION_METHODを設定する必要があるということが分かりました。

jenkins - Kubernetes - Calico-Nodes 0/1 Ready - Stack Overflow

で、calicoインストール時にデプロイしたオペレータのコードを見ていくとnodeAddressAutoDetectionV4には他にもいくつか設定できる項目があり、その中にCIDRを設定できるということが分かりました。

https://raw.githubusercontent.com/projectcalico/calico/v3.28.0/manifests/tigera-operator.yaml

お、これは勝利の予感。

というわけでcalicoのDaemonSetのnodeAddressAutoDetectionV4をホスト間通信用のNICが使っているCIDRにしてデプロイし直してようやく解決しました。