去年11月に社内でk8sの勉強会をしていただいたけど、その時は今よりもk8s何もわからん状態だった。その後k8sクラスタ再作成等をやったのでこれをもう1度やってみた。
トラブルシューティングから学ぶk8s
基本コマンド
※ kubectl
= k
Pod内のコンテナに対してコマンド実行
$ k exec -it <Pod名> -- /bin/bash
# コンテナの中
root@<Pod名>
:/#
複数コンテナがあるPodで -c オプションでコンテナを指定してコマンド実行
$ k exec <Pod名> -c <コンテナ名> -- cat /var/log/nginx/access.log
新しいPodをコンテナイメージを指定して作成(デバッグ用Podとして使える)
※ --rm は シェルを終了すると、自動的にPodは削除される。
$ k run -it --rm <コンテナイメージ> --image=<Pod名>
PodやNodeのCPUやメモリのリソース量を確認
$ k top po <Pod名>
$ k top no
クラスタ内のPodやServiceにクラスタ外からアクセス(http://localhost:8080)
別ターミナルでアクセスログの確認ができる
$ k port-forward <Pod名> 8080:80
Forwarding from 127.0.0.1:8080 -> 80
Forwarding from [::1]:8080 -> 80
主にメンテナンスやログ収集、その他にもトラブルシューティング等でクラスタのNodeへアクセスしたいときに使用する
# Node上に特権コンテナがデプロイされ、シェルに接続される
$ k debug no/<Node名> -it --image=<コンテナイメージ>
Creating debugging pod node-debugger-<Node名>-69tns with container debugger on node <Node名>.
If you don't see a command prompt, try pressing enter.
[root@<Node名> /]#
# chroot /host を実行すると、Node上の全ファイルシステムにアクセス可能
[root@<Node名> /]# chroot /host
アプリケーションPodのトラブルシューティング
正常なPodはRunningステータスで動作し続けることが想定される
- Pending : PodがNodeにスケジューリングされていない状態
- Terminating : Podが終了中の状態
- Unknown : 何らかの理由でPodのステータスが確認できない状態
- CrashLoopBackOff : コンテナが起動と終了を繰り返している状態
- ContainerCreating : コンテナが作成中の状態
- CreateContainerConfigError : コンテナを作成するための設定に問題がある状態
- ErrImagePull/ImagePullBackOff : コンテナイメージのPullに失敗している状態
Podはひとつ以上のコンテナの集合体で構成される(Containers.<コンテナ名>.State)
Stateフィールドの情報からPod内に存在する各コンテナの状態が確認できる。
- Waiting : コンテナの作成が未完了
- Running : コンテナが実行中
- Terminated: コンテナが実行され、完了もしくは失敗した状態
トラブル1 (CrashLoopBackOffステータス)
# Eventフィールドを確認すると、Liveness Probeに失敗している
$ k describe po
--- snip ---
Events:
Type Reason Age From Message
---- ------ ---- ---- -------
Warning Unhealthy 15m (x9 over 17m) kubelet Liveness probe failed: cat: can't open '/tmp/health': No such file or directory
Normal Killing 15m (x3 over 17m) kubelet Container liveness failed liveness probe, will be restarted
--- snip ---
Containers.<コンテナ名>.Last State: を見ると、Terminatedで終了している
Containers:
liveness:
--- snip ---
State: Waiting
Reason: CrashLoopBackOff
Last State: Terminated
Reason: Error
Exit Code: 137
--- snip ---
Liveness probeに設定しているコマンドでチェックしているファイルのパスが間違っていることが原因だった。
トラブル2 (ContainerCreatingステータス)
# Eventフィールドを確認すると、ReasonがFailedMountと記録されている
$ k describe po mypod
--- snip ---
Events:
Type Reason Age From Message
---- ------ ---- ---- -------
Normal Scheduled 46s default-scheduler Successfully assigned default/mypod to colima
Warning FailedMount 14s (x7 over 46s) kubelet MountVolume.SetUp failed for volume "foo" : configmap "mycnofigmap" not found
--- snip ---
Messageを見ると、コンテナにマウントするはずのvolumeがマウントできていないので、起動する前に待ち状態になってしまっている。また、fooボリュームとしてmycnofigmapというConfigMapリソースを指定しているが、見つかっていない。
# ConfigMapを確認
$ k get cm
NAME DATA AGE
myconfigmap 1 5m2s
ConfigMapはmyconfigmapなのでtypoしていることが原因だった。
トラブル3 (CreatingContainerConfigError)
# Eventフィールドを確認すると、ReasonがFailedと記録されている
$ k describe po mypod-2
--- snip ---
Events:
Type Reason Age From Message
---- ------ ---- ---- -------
Warning Failed 15s (x4 over 49s) kubelet Error: couldn't find key USERNAME in Secret default/mysecret
--- snip ---
Messageを見ると、default/mysecretのUSERNAMEキーを参照しようとしているが、そのようなキーが見つからずにエラーとなっている。
# Secretを確認
$ k get secret
NAME TYPE DATA AGE
mysecret Opaque 1 4m22s
# 存在するキーはuserなのでPodの定義かSecretのキー名を修正する
$ k describe secret mysecret
Name: mysecret
Namespace: default
Labels: <none>
Annotations: <none>
Type: Opaque
Data
====
user: 6 bytes
※ 今回はVolume Mount周りには問題がなく、ContainerCreatingフェーズは正常に終了した。その後に実行されるSecretからの値の参照処理に間違いがあって CreateContainerConfigError になっていた。
トラブル4 (ErrorImage/ImagePullBackOff)
# Eventフィールドを確認すると、ReasonがFailedと記録されている
$ k describe po my-busybox
--- snip ---
Events:
Type Reason Age From Message
---- ------ ---- ---- -------
Warning Failed 27s (x3 over 73s) kubelet Failed to pull image "rancher/bosybux": rpc error: code = Unknown desc = failed to pull and unpack image "docker.io/rancher/bosybux:latest": failed to resolve reference "docker.io/rancher/bosybux:latest": pull access denied, repository does not exist or may require authorization: server message: insufficient_scope: authorization failed
--- snip ---
Messageを見ると、docker.io/rancher/bosybux:latestイメージをpullしようとしているが、アクセスが拒否されたかリポジトリにそのようなイメージが存在してないため、イメージの取得に失敗している。
トラブル5 (ErrorImage/ImagePullBackOff その2)
# Podのステータスが ErrImagePull or ImagePullBackOff
$ k get po mysql
NAME READY STATUS RESTARTS AGE
mysql 0/1 ErrImagePull 0 77s
$ k get po mysql
NAME READY STATUS RESTARTS AGE
mysql 0/1 ImagePullBackOff 0 84s
# image pullに問題がある
$ k describe po mysql
--- snip ---
Events:
Type Reason Age From Message
---- ------ ---- ---- -------
Normal Pulling 31s (x4 over 116s) kubelet Pulling image "<コンテナイメージ名>mysql:8"
Warning Failed 31s (x4 over 116s) kubelet Failed to pull image "<コンテナイメージ名>/mysql:8": rpc error: code = Unknown desc = failed to pull and unpack image "<コンテナイメージ名>/mysql:8": failed to resolve reference "<コンテナイメージ名>/mysql:8": pulling from host <ホスト名> failed with status code [manifests 8]: 401 Unauthorized
Warning Failed 31s (x4 over 116s) kubelet Error: ErrImagePull
Warning Failed 18s (x6 over 116s) kubelet Error: ImagePullBackOff
Normal BackOff 7s (x7 over 116s) kubelet Back-off pulling image "<コンテナイメージ名>/mysql:8"
--- snip ---
Messageを見ると、レジストリの<コンテナイメージ名>から401が返って、認証に失敗している。理由は認証情報を持っている人だけがアクセスできるプライベートレジストリであり、クラスタやPodには認証情報を設定していないのでコンテナイメージの取得に失敗している。
(Part2 に続く...)
その他
過去、基本的なやつはQiitaに残していた。