【Kubernetes】kubectl execができなかった件
自分で勉強目的に作ったk8s環境について、kubectl exec
がなぜか失敗して、なんでだろ、と思って調べた記録。
ググれば出てくるが自身への備忘録としてまとめる
事象
kubectl exec
を実行すると以下のエラーがかえってきた
$ kubectl exec hogehoge -- ls / error: unable to upgrade connection: pod does not exist
kubectl exec --help
を実行すると以下のような内容
# Get output from running 'date' command from the first pod of the deployment mydeployment, using the first container by default kubectl exec deploy/mydeployment -- date
も確認できたのと、実際の環境が実際DeploymentでつくったPodだったのもあって、kubectl exec deploy/hogehoge -- ls /
とか書かないとだめなのかなと思ったが、これもだめ。
エラーメッセージがそもそも「Podが見つからない」なので、違うだろうなとは思ったが…。
Kubernetes.ioのexecコマンドの説明を見てもPodを指定するという点には間違っていないし。
う~ん??
まあPod動いてるし後で調べればいいかと思ってちょっと放置してしまっていた。
原因
内容的にはこれが一番近かった。(これはVagrantの例だけど)
確かに見てみたらマスター、ワーカー、各ノードの「INTERNAL-IP」が同じ値になっていた。
$ kubectl get no -o wide NAME STATUS ROLES AGE VERSION INTERNAL-IP EXTERNAL-IP OS-IMAGE KERNEL-VERSION CONTAINER-RUNTIME ubuntu00 Ready control-plane,master 2d13h v1.20.1 10.0.2.15 <none> Ubuntu 20.04.1 LTS 5.4.0-58-generic docker://20.10.1 ubuntu01 Ready <none> 47h v1.20.1 10.0.2.15 <none> Ubuntu 20.04.1 LTS 5.4.0-58-generic docker://20.10.1 ubuntu02 Ready <none> 21h v1.20.1 10.0.2.15 <none> Ubuntu 20.04.1 LTS 5.4.0-58-generic docker://20.10.1
解決法として、稼働する各ノードに一意のIPを指定してあげる必要がある。
具体的にはkubeletの起動オプションに
Environment="KUBELET_EXTRA_ARGS=--node-ip=[ノードIP]"
を追加するということのようだ。
今回の例では
Node | IP Address |
---|---|
Master Node | 192.168.56.100 |
Worker Node | 192.168.56.101 |
Worker Node | 192.168.56.102 |
だったので、それぞれのノードの/etc/systemd/system/kubelet.service.d/10-kubeadm.conf
を修正して↑の一行(IPアドレスは各ノードで変える)を追加し、sudo systemctl daemon-reload
及びsudo systemctl restart kubelet
でkubeletを再起動する。
これで各ノードのIPが変わる。
$ kubectl get no -o wide NAME STATUS ROLES AGE VERSION INTERNAL-IP EXTERNAL-IP OS-IMAGE KERNEL-VERSION CONTAINER-RUNTIME ubuntu00 Ready control-plane,master 2d13h v1.20.1 192.168.56.100 <none> Ubuntu 20.04.1 LTS 5.4.0-58-generic docker://20.10.1 ubuntu01 Ready <none> 47h v1.20.1 192.168.56.101 <none> Ubuntu 20.04.1 LTS 5.4.0-58-generic docker://20.10.1 ubuntu01 Ready <none> 21h v1.20.1 192.168.56.102 <none> Ubuntu 20.04.1 LTS 5.4.0-58-generic docker://20.10.1
これで無事にkubectl exec
が実行できた。
このあと滅茶苦茶execした。
$ kubectl exec test-nginx -- ls / bin boot dev docker-entrypoint.d docker-entrypoint.sh etc home lib lib64 media mnt opt proc root run sbin srv sys tmp usr var
ちなみに中に入る(?)ときは
$ kubectl exec test-nginx --tty --stdin -- bash root@test-nginx:/# ls bin boot dev docker-entrypoint.d docker-entrypoint.sh etc home lib lib64 media mnt opt proc root run sbin srv sys tmp usr var
こんなかんじ。
要するに--tty
と--stdin
のオプションが必要だ。
(このオプション付けないとbashだけ実行されて速攻コマンドが終わる)
余談
昔(1~2年前?よく覚えていない)同じことをやったときに、ユーザーの環境変数に指定しておけばいいと思って、/home/xxx/.profile
にexport KUBELET_EXTRA_ARGS=...
を指定してkubelet起動させて、これはこれでexecが実行できていた記憶があり、自分の手元でKubernetesの環境作ったときも、最初はこれでやっていた。
まあ今回はrootの環境変数をいじってなかった(自ユーザーの変数いじってたから効くわけない。kubeletのサービスはrootで起動するので、環境変数設定するにしてもrootのほうに設定する必要があった)ので結局駄目だったんだけどね。。。
ただ/etc/environment
とかにいれても反応してくれず、どうしたもんかとずっと思っていたら、kubeadmでkubeletを入れた場合は、上述した設定ファイル/etc/systemd/system/kubelet.service.d/10-kubeadm.conf
がもう出来上がっていて、そっちの設定が優先されるようになってるらしい。
そんなこと言ってるのをちょっと見かけた。
だから一度この設定ファイルができてしまうと後でいくら環境変数をいじくっても無駄のようだ。
逆にいうとkubeadmを入れる前にきちんと適切に環境変数いれておけばこの設定ファイルにもそれが反映された…のかもしれない。
試していない。
まあ、そのうちやってみるか。