Kopsでcalico-nodeがCrashLoopBackOffになる事象
ちょくちょくとKubernetes関連の記事を上げていっています。今回もちょっとしたトラブルの覚書です。
事象
Kopsでcalicoを使っていると、Node立ち上げ時にcalico-nodeがCrashLoopBackOffになることがある。エラーが出たcalico-nodeと同じnodeのpodから外部への接続が一切できなくなってしまいました。(ping, 名前解決ともにできなくなる。)
2018-MM-DD HH:MM:SS.207 [INFO][9] startup.go 467: Using autodetected IPv4 address on interface eth0: XX.XX.XX.XX/24 2018-MM-DD HH:MM:SS.207 [INFO][9] startup.go 338: Node IPv4 changed, will check for conflicts 2018-MM-DD HH:MM:SS.626[WARNING][9] startup.go 718: Calico node '<ホスト名>' is already using the IPv4 address XX.XX.XX.XX. 2018-MM-DD HH:MM:SS.626 [WARNING][9] startup.go 915: Terminating Calico node failed to start
ログをみてみると、Calico node '[ホスト名]' is already using the IPv4 address <IP Addresess>.
というエラーが出力されていました。
原因
前提としてKubernetesのMasterにはETCDというKVSがバックエンドとして存在していて、そこにノードの情報などが格納されています。
$ kubectl exec -it etcd-server-ip-XX-XX-XX-XX.XX.compute.internal -n kube-system -- /bin/sh / # etcdctl ls /calico/v1/host /calico/v1/host/<ホスト名> ...
こんな感じで。どうやらNodeが削除されてもここのKVが残り続け、新規で立ち上げたNodeとIPアドレスが被ってしまった場合、上記のエラーが出力されるようです。
解決方法
Nodeが削除される時に同時にETCDからも削除されれば解決しそうです。調べてみると、calico-nodeを管理するcalico-kube-controllersにNode controllerという機能がありました。Node controllreNode削除時にetcdのホスト情報を一緒に削除してくれるというもので、これを使えば解決しそうですね。この機能はデフォルトでは無効化されているので、有効化する手順をまとめます。
$ kops version Version 1.8.1 (git-94ef202)
まず、deploymentのcalico-kube-controllersにENABLED_CONTROLLERS
という環境変数を設定します。
$ kubectl get deployment -n kube-system NAME DESIRED CURRENT UP-TO-DATE AVAILABLE AGE calico-kube-controllers 1 1 1 1 20d
$ kubectl edit deployment calico-kube-controllers -n kube-system .... spec: containers: - env: + - name: ENABLED_CONTROLLERS + value: policy,profile,workloadendpoint,node - name: ETCD_ENDPOINTS valueFrom: configMapKeyRef: key: etcd_endpoints name: calico-config image: quay.io/calico/kube-controllers:v1.0.3 imagePullPolicy: IfNotPresent name: calico-kube-controllers resources: requests: cpu: 10m terminationMessagePath: /dev/termination-log terminationMessagePolicy: File .....
続いてcalico-nodeのdaemonsetにCALICO_K8S_NODE_REF
という環境変数を設定します。
$ kubectl get daemonset -n kube-system NAME DESIRED CURRENT READY UP-TO-DATE AVAILABLE NODE SELECTOR AGE calico-node 2 2 2 1 2 <none> 20d $ kubectl edit daemonset calico-node -n kube-system .... spec: containers: - env: - name: ETCD_ENDPOINTS valueFrom: configMapKeyRef: key: etcd_endpoints name: calico-config - name: CALICO_NETWORKING_BACKEND valueFrom: configMapKeyRef: key: calico_backend name: calico-config - name: CALICO_IPV4POOL_CIDR value: XX.XX.XX.XX/11 - name: CALICO_IPV4POOL_IPIP value: cross-subnet - name: CLUSTER_TYPE value: kops,bgp - name: CALICO_DISABLE_FILE_LOGGING value: "true" - name: IP - name: FELIX_IPV6SUPPORT value: "false" - name: FELIX_LOGSEVERITYSCREEN value: info - name: FELIX_HEALTHENABLED value: "true" + - name: CALICO_K8S_NODE_REF + valueFrom: + fieldRef: + apiVersion: v1 + fieldPath: spec.nodeName image: quay.io/calico/node:v2.6.6 ....
これでNode controllerが有効化されました。
確認
実際に確認してみます。Masterのetcd serverに入ってetcdctlコマンドで確認します。
nodesを増やす前
# etcdctl ls /calico/v1/host | wc -l 2
nodesを増やしてみる。その後
# etcdctl ls /calico/v1/host | wc -l 5
nodesを消した後
# etcdctl ls /calico/v1/host | wc -l 2
とノードの数と合わせてcalicoのホストも増減していることがわかります。
既存のホストはどうするか
これでノードの増減とcalicoのホストも合わせて増減することができましたが、calico-node-controllerを有効化する前にできた余分なホストは削除してくれないので、これは自分で削除する必要があります。手動でちまちまと消していくのはとてもダルイのでRubyでスクリプトを書きましたが、そこまで数が多いのなら作り直してしまった方が早いかもしれません。
ということで、こんな感じの簡単な備忘録でした。