5 つくって、壊して、直して学ぶ Kubernetes入門 Chapter5 トラブルシューティングガイドと kubectl コマンドの使い方
#k8s #docker #つくって壊して直して学ぶk8s入門
https://www.shoeisha.co.jp/book/detail/9784798183961
https://github.com/aoi1/bbf-kubernetes
自分でやってみているリポジトリ
https://github.com/nobu09/bbf-k8s-learn/tree/main/01
Kubectl Cheat Sheet
https://kubernetes.io/ja/docs/reference/kubectl/cheatsheet/
Chapter5 トラブルシューティングガイドと kubectl コマンドの使い方
5.1 トラブルシューティングガイド
5.1.1 PodのSTATUSカラム
kubectl get pod で得られる STATUS カラムには、トラブルシューティングで役出す情報が出力される
code:sh
% kubectl get pod -n default
NAME READY STATUS RESTARTS AGE
myapp 1/1 Running 0 2d
Pending
Running
Completed
Unknown
ErrImagePull
Error
OOMKilled
Terminating
5.2 現状を把握するためにkubectlコマンドを使ってみよう
5.2.1 リソースを取得する: kubectl get
code:sh
# kubectl get <リソース名> でリソースの情報を取得
nobu@shinodanobukonoMacBook-Air 04 % kubectl get pods --namespace default
NAME READY STATUS RESTARTS AGE
myapp 1/1 Running 0 24h
# リソース名指定
nobu@shinodanobukonoMacBook-Air 04 % kubectl get pod myapp --namespace default
NAME READY STATUS RESTARTS AGE
myapp 1/1 Running 0 24h
# --output(-o)オプション IPアドレスやNode情報が取得できるwide
nobu@shinodanobukonoMacBook-Air 04 % kubectl get pod --output wide -n default
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
myapp 1/1 Running 0 24h 10.244.0.5 kind-control-plane <none> <none>
# --output(-o)オプション YAMLファイル形式でリソース情報を取得するyaml
nobu@shinodanobukonoMacBook-Air 04 % kubectl get pod --output yaml -n default
apiVersion: v1
items:
- apiVersion: v1
kind: Pod
metadata:
annotations:
kubectl.kubernetes.io/last-applied-configuration: |
{"apiVersion":"v1","kind":"Pod","metadata":{"annotations":{},"labels":{"app":"myapp"},"name":"myapp","namespace":"default"},"spec":{"containers":[{"image":"blux2/hello-server:1.0","name":"hello-server","ports":{"containerPort":8080}}]}}
creationTimestamp: "2024-05-13T23:47:35Z"
labels:
app: myapp
name: myapp
namespace: default
resourceVersion: "11407"
uid: 6b93f14e-6790-4be9-ac4d-7538cccf797f
spec:
containers:
- image: blux2/hello-server:1.0
(略)
YAMLでoutputしたリソースの情報と、マニフェストファイルの差分を見るとたくさん出る
kubectl get pod myapp --output yaml --namespace default
k8sではリソースを運用するにあたって、kubectl apply で使用したマニフェストに書いてあることより多くの情報が必要
マニフェストには、リソースに必須な内容、人間が宣言的に指定したい内容のみ記載
k8s の仕組みとして、自動的にさまざまな情報(Status や 内部用IDなど)をリソースに付与する
code:sh
# YAMLでoutputしたリソースの情報と、マニフェストファイルの差分を見るとたくさん出る
% kubectl get pod myapp --output yaml --namespace default > pod.yaml
% diff myapp.yaml pod.yaml
4c4,7
< name: myapp
---
annotations:
kubectl.kubernetes.io/last-applied-configuration: |
{"apiVersion":"v1","kind":"Pod","metadata":{"annotations":{},"labels":{"app":"myapp"},"name":"myapp","namespace":"default"},"spec":{"containers":[{"image":"blux2/hello-server:1.0","name":"hello-server","ports":{"containerPort":8080}}]}}
creationTimestamp: "2024-05-13T23:47:35Z"
6a10,13
name: myapp
namespace: default
resourceVersion: "11407"
uid: 6b93f14e-6790-4be9-ac4d-7538cccf797f
9,10c16,18
< - name: hello-server
<
--output(-o)で jsonpath でフィールドを指定して get する
code:sh
% kubectl get pod myapp --output jsonpath='{.spec.containers[].image}'
blux2/hello-server:1.0%
jq を使い慣れていれば、--output json と jq を組み合わせても同じことできる
code:sh
% kubectl get pod myapp -o json | jq '.spec.containers[].image'
"blux2/hello-server:1.0"
--v で kubectl の出力結果のログレベルを変更する
ログレベルを変更するコマンド(あまり使わないけど)
「kubectl と kube-apiserver がクライアントと API Server である」ということがわかるログレベル --v=7 を指定した例 ↓
REST のリクエストやヘッダーが参照できるレベル
v7: HTTPリクエストのヘッダを表示
ドキュメント: Kubectlのログレベルとデバッグ
code:sh
% kubectl get pod myapp --v=7 -n default
I0518 16:10:31.229893 52727 loader.go:395] Config loaded from file: /Users/nobu/.kube/config
I0518 16:10:31.230791 52727 round_trippers.go:463] GET https://127.0.0.1:60372/api?timeout=32s
I0518 16:10:31.230796 52727 round_trippers.go:469] Request Headers:
I0518 16:10:31.230801 52727 round_trippers.go:473] Accept: application/json;g=apidiscovery.k8s.io;v=v2;as=APIGroupDiscoveryList,application/json;g=apidiscovery.k8s.io;v=v2beta1;as=APIGroupDiscoveryList,application/json
I0518 16:10:31.230803 52727 round_trippers.go:473] User-Agent: kubectl/v1.30.0 (darwin/arm64) kubernetes/7c48c2b
I0518 16:10:31.237054 52727 round_trippers.go:574] Response Status: 200 OK in 6 milliseconds
I0518 16:10:31.238075 52727 round_trippers.go:463] GET https://127.0.0.1:60372/apis?timeout=32s
I0518 16:10:31.238080 52727 round_trippers.go:469] Request Headers:
I0518 16:10:31.238084 52727 round_trippers.go:473] Accept: application/json;g=apidiscovery.k8s.io;v=v2;as=APIGroupDiscoveryList,application/json;g=apidiscovery.k8s.io;v=v2beta1;as=APIGroupDiscoveryList,application/json
I0518 16:10:31.238086 52727 round_trippers.go:473] User-Agent: kubectl/v1.30.0 (darwin/arm64) kubernetes/7c48c2b
I0518 16:10:31.239032 52727 round_trippers.go:574] Response Status: 200 OK in 0 milliseconds
I0518 16:10:31.244789 52727 round_trippers.go:463] GET https://127.0.0.1:60372/api/v1/namespaces/default/pods/myapp
I0518 16:10:31.244796 52727 round_trippers.go:469] Request Headers:
I0518 16:10:31.244800 52727 round_trippers.go:473] Accept: application/json;as=Table;v=v1;g=meta.k8s.io,application/json;as=Table;v=v1beta1;g=meta.k8s.io,application/json
I0518 16:10:31.244802 52727 round_trippers.go:473] User-Agent: kubectl/v1.30.0 (darwin/arm64) kubernetes/7c48c2b
I0518 16:10:31.246453 52727 round_trippers.go:574] Response Status: 200 OK in 1 milliseconds
NAME READY STATUS RESTARTS AGE
myapp 1/1 Running 0 4d7h
5.2.2 リソースの詳細を取得する: kubectl describe
kubectl describe pod <Pod名>
kubectl get より詳しい情報が得られる
特に Events の内容はトラブルシューティングに役立つ
ただし、Events は一定時間で消えてしまう!!
code:sh
% kubectl describe pod myapp -n default
Name: myapp
Namespace: default
Priority: 0
Service Account: default
Node: kind-control-plane/172.18.0.2
Start Time: Tue, 14 May 2024 08:47:35 +0900
(略)
QoS Class: BestEffort
Node-Selectors: <none>
Tolerations: node.kubernetes.io/not-ready:NoExecute op=Exists for 300s
node.kubernetes.io/unreachable:NoExecute op=Exists for 300s
Events: <none>
%
Kubernetes のデフォルト設定では、イベントの保持期間は以下のようになっています:
1時間ごとにガベージコレクションのプロセスが実行されます。
デフォルトの保持期間は1時間です。
つまり、イベントは発生してから約1時間後に自動的に削除されます。この期間はKubernetesの設定で変更可能ですが、通常はデフォルトのまま使用されます。
具体的な保持期間やガベージコレクションの設定は、クラスターの設定ファイル(APIサーバーのパラメータ)で変更できます。例えば、--event-ttl フラグを使用して設定します。このフラグはAPIサーバーの起動パラメータとして設定され、イベントの有効期限を指定できます。
code:yml
--event-ttl=1h
これはAPIサーバーの起動時に指定されるため、クラスター全体の設定が必要です。
保持期間を確認または変更するには、クラスター管理者がAPIサーバーの設定を変更する必要がありますが、デフォルト設定ではイベントは約1時間で削除されると覚えておくとよいでしょう。
5.2.3 コンテナのログを取得する: kubectl logs
コンテナのログの取得は、kubectl logs で行う
ログはリソースでなくサブコマンドなので、kubectl get logs ではない
ここで出力されるのは、標準出力のログ
特定の Pod のログを取得する
kubectl logs <Pod名>
複数コンテナがPod内に存在する場合、--container(-c)オプションを利用してコンテナも指定する
code:sh
# podのログを参照する
% kubectl logs myapp -n default
# --container でコンテナを指定
% kubectl logs myapp --container hello-server -n default
2024/05/25 02:06:04 Starting server on port 8080
# -cでOK
% kubectl logs myapp -c hello-server -n default
2024/05/25 02:06:04 Starting server on port 8080
特定の Deployment にひもづく Pod のログを取得する
kubectl logs deploy/<Deployment名>
Deployment というリソースを利用して Pod を複製できるが、Pod 名がランダムで生成される
ランダムな Pod名を取得するために毎回 kubectl get pod するの大変!
そういう時に、このコマンドで Deployment にひもづく全ての Pod のログを見る
複数 Pod を運用しているアプリケーションに関して、「ユーザーからのアクセスがどの Pod に対して行われるかがわからない」というケースで活用可能
ログは、kubectl を利用する以外に、stern というツールを利用するのも便利
sternの公式ページ、https://github.com/stern/stern ぽい
検索しても404のページが出てきたりしてた
code:sh
kubectl logs deploy/hello-server
寄り道: stern
https://github.com/stern/stern
Sternでは、Kubernetes上の複数のポッドと、ポッド内の複数のコンテナをtailすることができる。各結果は色分けされており、デバッグを迅速に行うことができる。
code:sh
# インストール
brew install stern
ラベルを指定して参照する Pod を絞り込む
code:sh
kubectl get pod --selector(-l) <labelのキー名>=<labelの値>
# ラベルで絞り込み
% kubectl get pod --selector app=myapp
NAME READY STATUS RESTARTS AGE
myapp 1/1 Running 1 (2d11h ago) 13d
myapp3 1/1 Running 0 90s
% kubectl get pod -l app=myapp
NAME READY STATUS RESTARTS AGE
myapp 1/1 Running 1 (2d11h ago) 13d
myapp3 1/1 Running 0 57s
ログも、ラベルを指定して複数のPodを参照できる
同じ役割のPodに同じラベルを振っておくことでまとめて見れそう
code:sh
% kubectl logs -l app=myapp
2024/05/25 02:06:04 Starting server on port 8080 #myappのログ
2024/05/27 13:48:25 Starting server on port 8080 #myapp3のログ
5.3 詳細な情報を取得する kubectl コマンドを使ってみよう
参照系のコマンドで情報が足りない場合に使うコマンド
参照系よりも権限が必要な場合があるので注意📝
5.3.1 デバッグ用のサイドカーコンテナを立ち上げる: kubectl debug
code:sh
kubectl debug --stdin -tty <デバッグ対象Pod名> --image=<デバッグ用コンテナのimage> --target=<デバッグ対象のコンテナ名>
Kubernetes 1.25からStableになった機能
コンテナは起動を早くしたり、セキュリティリスクを低減するために、動作に必要最低限なツールしか同梱していないことも多いので、デバッグしたくても必要なツールが入ってないことも(シェルさえ入っていないとか)
そこで、デバッグ用のコンテナを起動することで多様なデバッグツールを利用できるようになる
code:sh
% kubectl debug --stdin --tty myapp --image=curlimages/curl:8.4.0 --target=hello-server -n default -- sh
Targeting container "hello-server". If you don't see processes from this container it may be because the container runtime doesn't support this feature.
Defaulting debug container name to debugger-hw95l.
If you don't see a command prompt, try pressing enter.
~ $ curl localhost:8080
Hello, world!~ $ exit
Session ended, the ephemeral container will not be restarted but may be reattached using 'kubectl attach myapp -c debugger-hw95l -i -t' if it is still running
デバッグ対象のPodと同じネットワーク、同じボリュームをそれぞれローカルネットワーク、ローカルボリュームとして参照できて非常に便利🙌
特にネットワークの問題は障害の分岐点が多いため、まずはローカルで接続可能か確認するという使い方ができる
5.3.2 コンテナを即座に実行する: kubectl run
code:sh
kubectl run <Pod名> --image=<イメージ名>
kubectl debug の登場以前、クラスタ内からアクセスするにはデバッグ用Podを起動する必要があった
busyboxというPodを起動し、nslookupコマンドを実行したら終了する ↓
code:sh
kubectl -n default run busybox --image=busybox:1.36.1 --rm --stdin --tty --restart=Never --command -- nslookup google.com
% kubectl -n default run busybox --image=busybox:1.36.1 --rm --stdin --tty --restart=Never --command -- nslookup google.com
Server: 10.96.0.10
Address: 10.96.0.10:53
Non-authoritative answer:
Name: google.com
Address: 172.217.161.206
Non-authoritative answer:
Name: google.com
Address: 2404:6800:400a:80b::200e
pod "busybox" deleted
%
--rm: 実行が完了したらPodを削除する
--stdiin(-i): オプションで標準出力に渡す
--tty(-t): オプションで擬似端末を割り当てる
--restart=Never: Podの再起動ポリシーをNeverに設定する。コンテナが終了しても再起動を行わない(デフォルトだと常に再起動するというポリシーのため)
--command --: " --"の後に渡される拡張引数の1つ目が引数でなくコマンドとして渡される
--stdinと--ttyは2つを同時に省略して、-itと書く場合も多い
5.3.3 コンテナにログインする: kubectl exec
code:sh
kubectl exec -it <Pod名> -- <コマンド名>
kubectl exec を利用して、コンテナ上でコマンドを実行することができる
https://kubernetes.io/docs/reference/kubectl/generated/kubectl_exec/
コマンドには、/bin/sh を利用すると、コンテナにシェルが入っていれば、直接対象のコンテナにログインできる
シェルが入っていないことも多い
kubectl runで立ち上げたdebug用Podにログインして使うという用途もある
code:sh
#ログイン用のpodを作成
% kubectl -n default run curlpod --image=curlimages/curl:8.4.0 --command -- /bin/sh -c "while true; do sleep initify; done;"
pod/curlpod created
# できてる
% kubectl get pod -n default
NAME READY STATUS RESTARTS AGE
curlpod 1/1 Running 0 16s
myapp 1/1 Running 1 (5d22h ago) 17d
myapp3 1/1 Running 0 3d10h
# myappのIPアドレスを取得
% kubectl get pod myapp -n default -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
myapp 1/1 Running 1 (5d22h ago) 17d 10.244.0.4 kind-control-plane <none> <none>
# ログイン用Podにログイン、curlを叩いて疎通確認する
% kubectl -n default exec -it curlpod -- /bin/sh
~ $ curl 10.244.0.4
curl: (7) Failed to connect to 10.244.0.4 port 80 after 0 ms: Couldn't connect to server
~ $ curl 10.244.0.4:8080
Hello, world!~ $
アプリケーションがインターネット上からアクセスできなくなった時に、クラスタ内から上記のようにIPアドレスでアクセスできるか確認することで問題を切り分ける
5.3.4 port-forward でアプリケーションにアクセス: kubectl port-forward
code:sh
kubectl port-forward <Pod名> <転送先ポート番号>:<転送元ポート番号>
Podには、k8sクラスタ内のIPアドレスが割り当てられるので、何もしないとクラスが外からアクセスできない
後述のServiceというリソースを利用することで、クラスが外からアクセス可能にすることはできるが、kubectlを使ってポートフォワーディングの設定をすることでお手軽にアクセスできる
Podが終わるまでport-forwardをし続ける
転送元と転送先は同じポート番号でもOK、転送先ポート番号は、ローカルで使用していないポート番号を指定すること
code:sh
% kubectl port-forward myapp 5555:8080 -n default
Forwarding from 127.0.0.1:5555 -> 8080
Forwarding from ::1:5555 -> 8080
Handling connection for 5555 # curlしたタイミングで出力
^C% # Ctrl + Cで終了させた(そうしないとPodが終了するまでport-forwardをし続ける)
nobu@shinodanobukonoMacBook-Air bbf-k8s-learn %
code:sh
# 別ターミナルで
% curl localhost:5555
Hello, world!%
nobu@shinodanobukonoMacBook-Air ~ %
転送先ポートの指定は省略できる、その場合、ローカルのランダムポートが選択される
code:sh
# 2回やってみて、違うポートが指定されるさま
nobu@shinodanobukonoMacBook-Air bbf-k8s-learn % kubectl port-forward myapp :8080 -n default
Forwarding from 127.0.0.1:54638 -> 8080
Forwarding from ::1:54638 -> 8080
^C%
nobu@shinodanobukonoMacBook-Air bbf-k8s-learn % kubectl port-forward myapp :8080 -n default
Forwarding from 127.0.0.1:54643 -> 8080
Forwarding from ::1:54643 -> 8080
^
5.4 障害を直すための kubectl コマンドを使ってみよう
5.4.1 マニフェストをその場で編集する: kubectl edit
kubectl edit <リソース名> でリソースマニフェストを修正できる
修正履歴を残しにくいため、この方法は推奨されていない
できるだけ修正前のマニフェストを保存しておき、修正後のマニフェストを kubectl apply する形が望ましい
OSのデフォルトエディタが起動し、マニフェストを修正できるようになる
起動するエディタを変更したい場合は、KUBE_EDITOR、EDITOR のいずれかの環境変数を指定する
code:sh
% kubectl edit pod myapp -n default
pod/myapp edited
# ↑ 修正が完了してファイルを保存するとこう出る(自分の場合、エディタはviだった)
# 修正を確認、labels: env: prodが設定されている
nobu@shinodanobukonoMacBook-Air quick-start % kubectl get pod myapp -o yaml -n default
apiVersion: v1
kind: Pod
metadata:
annotations:
kubectl.kubernetes.io/last-applied-configuration: |
{"apiVersion":"v1","kind":"Pod","metadata":{"annotations":{},"labels":{"app":"myapp"},"name":"myapp","namespace":"default"},"spec":{"containers":[{"image":"blux2/hello-server:1.0","name":"hello-server","ports":{"containerPort":8080}}]}}
creationTimestamp: "2024-05-13T23:47:35Z"
labels:
app: myapp
env: prod
5.4.2 リソースを削除する: kubectl delete
kubectl delete <リソース名>
kubectlには、podを再起動するコマンドがないので、kubectl deleteコマンドで代替する
本番でのアプリケーションは、Deploymentというリソースを使ってPodを冗長化している
ある特定のPodだけハングしてしまった時、Podを削除して、Deploymentで自動的に削除したPodが再度作成されるようになるので、Podを削除しても問題ないケースが多い
code:sh
nobu@shinodanobukonoMacBook-Air ~ % kubectl get pod -n default
NAME READY STATUS RESTARTS AGE
myapp 1/1 Running 1 (15d ago) 26d
myapp3 1/1 Running 0 12d
nobu@shinodanobukonoMacBook-Air ~ % kubectl delete pod myapp -n default
pod "myapp" deleted
nobu@shinodanobukonoMacBook-Air ~ % kubectl get pod -n default
NAME READY STATUS RESTARTS AGE
myapp3 1/1 Running 0 12d
Deployment を利用した Pod を全て順番に再起動したい場合、kubectl deleteよりも、kubectl rollout restartを利用する方が良い
Kubernetes Feature Stateについて
k8sには、各機能にFeature State(機能のステータス)がついている
機能のステータスには、それぞれRelease Stageが存在する
Release Stageには3種類
Alpha: デフォルトでオフになっている、バグが含まれている可能性があり、機能としてまだ不安定な状態
Beta: 多くの場合デフォルトでオンになっているが、互換性のない変更が入る可能性があるため、ビジネス上深刻なユースケースでは使用しないように
GA(General Abailability, または Stable): 安定している機能である
k8sにはバージョンが新しくなるたびに、さまざまな機能のRelase Stageが変更になったり新機能が追加になったりする
5.5 ターミナル操作を便利にする細かなTips
5.5.1 自動補完を設定する
シェルの自動補完を設定しておくと、kubectl実行時に自動補完してくれるので便利
https://kubernetes.io/docs/reference/kubectl/generated/kubectl_completion/
macOSのインストール方法: https://kubernetes.io/docs/tasks/tools/install-kubectl-macos/#enable-shell-autocompletion
手順に沿って、zshで以下のコマンドを打ったが、エラーになってしまった
あとでよく見たら、macOSのインストール方法に、command not found: compdefになった時の対処もちゃんと書いてあった・・・😇
code:sh
% source <(kubectl completion zsh)
/dev/fd/11:2: command not found: compdef
/dev/fd/11:18: command not found: compdef
compinitは、zshの補完機能を初期化するためのコマンド
zsh補完機能に必要なcompinit関数が実行されていないためエラーになっていた
compinitを呼び出してzshの補完機能を有効にする必要があった
compinitを実行すると、zshが補完機能のために必要な設定を読み込む
以下の内容を、.zshrcに書き込んで、source ~/.zshrcで読み込んだ
code:sh
autoload -Uz compinit
compinit
source <(kubectl completion zsh)
kubectl <TAB> や kubectl get p<TAB> などで補完が表示されるようになる
code:sh
% kubectl get p
persistentvolumeclaims pods prioritylevelconfigurations.flowcontrol.apiserver.k8s.io
persistentvolumes podtemplates
poddisruptionbudgets.policy priorityclasses.scheduling.k8s.io
5.5.2 kubectl の別名を設定する
alias k=kubectl を設定しておくと便利、公式でも推奨されているらしい
5.5.3 リソース指定の省略
リソース名は省略できる
code:sh
# 以下3つは全部同じ意味
kubectl get pods
kubectl get pod
kubectl get po
kubectl api-resources の SHORTNAMES カラムに略称が書かれている
po、deploy、svc、rsあたり便利そう
code:sh
% k api-resources
NAME SHORTNAMES APIVERSION NAMESPACED KIND
bindings v1 true Binding
componentstatuses cs v1 false ComponentStatus
configmaps cm v1 true ConfigMap
endpoints ep v1 true Endpoints
events ev v1 true Event
limitranges limits v1 true LimitRange
namespaces ns v1 false Namespace
nodes no v1 false Node
persistentvolumeclaims pvc v1 true PersistentVolumeClaim
persistentvolumes pv v1 false PersistentVolume
pods po v1 true Pod
podtemplates v1 true PodTemplate
replicationcontrollers rc v1 true ReplicationController
resourcequotas quota v1 true ResourceQuota
secrets v1 true Secret
serviceaccounts sa v1 true ServiceAccount
services svc v1 true Service
mutatingwebhookconfigurations admissionregistration.k8s.io/v1 false MutatingWebhookConfiguration
validatingwebhookconfigurations admissionregistration.k8s.io/v1 false ValidatingWebhookConfiguration
customresourcedefinitions crd,crds apiextensions.k8s.io/v1 false CustomResourceDefinition
apiservices apiregistration.k8s.io/v1 false APIService
controllerrevisions apps/v1 true ControllerRevision
daemonsets ds apps/v1 true DaemonSet
deployments deploy apps/v1 true Deployment
replicasets rs apps/v1 true ReplicaSet
statefulsets sts apps/v1 true StatefulSet
selfsubjectreviews authentication.k8s.io/v1 false SelfSubjectReview
tokenreviews authentication.k8s.io/v1 false TokenReview
localsubjectaccessreviews authorization.k8s.io/v1 true LocalSubjectAccessReview
selfsubjectaccessreviews authorization.k8s.io/v1 false SelfSubjectAccessReview
selfsubjectrulesreviews authorization.k8s.io/v1 false SelfSubjectRulesReview
subjectaccessreviews authorization.k8s.io/v1 false SubjectAccessReview
horizontalpodautoscalers hpa autoscaling/v2 true HorizontalPodAutoscaler
cronjobs cj batch/v1 true CronJob
jobs batch/v1 true Job
certificatesigningrequests csr certificates.k8s.io/v1 false CertificateSigningRequest
leases coordination.k8s.io/v1 true Lease
endpointslices discovery.k8s.io/v1 true EndpointSlice
events ev events.k8s.io/v1 true Event
flowschemas flowcontrol.apiserver.k8s.io/v1 false FlowSchema
prioritylevelconfigurations flowcontrol.apiserver.k8s.io/v1 false PriorityLevelConfiguration
ingressclasses networking.k8s.io/v1 false IngressClass
ingresses ing networking.k8s.io/v1 true Ingress
networkpolicies netpol networking.k8s.io/v1 true NetworkPolicy
runtimeclasses node.k8s.io/v1 false RuntimeClass
poddisruptionbudgets pdb policy/v1 true PodDisruptionBudget
clusterrolebindings rbac.authorization.k8s.io/v1 false ClusterRoleBinding
clusterroles rbac.authorization.k8s.io/v1 false ClusterRole
rolebindings rbac.authorization.k8s.io/v1 true RoleBinding
roles rbac.authorization.k8s.io/v1 true Role
priorityclasses pc scheduling.k8s.io/v1 false PriorityClass
csidrivers storage.k8s.io/v1 false CSIDriver
csinodes storage.k8s.io/v1 false CSINode
csistoragecapacities storage.k8s.io/v1 true CSIStorageCapacity
storageclasses sc storage.k8s.io/v1 false StorageClass
volumeattachments storage.k8s.io/v1 false VolumeAttachment
5.5.4 kubectl の操作に役立つツールの紹介
stern
https://github.com/stern/stern
Pod のログを出力するツール
Deployment を利用して Pod を複製した場合、Podには、Deployment名-xxx という名前がつく
stern を使うことで、Deploymentの文字列だけで、これらのPodのログを参照できる
stern 実行中に Pod が消されたとしても、新規に作成された Pod のログを自動で出力してくれる
code:sh
# brewでインストールできた
brew install stern
k9s
https://k9scli.io/
k9sはコマンドを使わずに、ターミナル上でわかりやすいUIを提供するツール
starship
https://starship.rs/
k8sに特化したツールではない
ターミナルをカスタマイズするためのツール
さまざまな開発用ツール・インフラに対応、k8sを便利に使うための設定方法も載っている
https://starship.rs/config/#kubernetes
5.5.5 kubectl プラグインを使ってみよう
kubectx / kubens は同じ GitHub プロジェクト
https://github.com/ahmetb/kubectx
Macは、brew install kubectx でインストールできる
kubects
コンテキストをスイッチするために利用
複数クラスタを利用するときは、次のことに留意
何もしなければ、デフォルトコンテキストが使用される
デフォルトコンテキスト以外を使用したい場合、kubectl --context か、kubectl config use-context を利用してデフォルトコンテキストを切り替える必要があるが、ここでkubectxが使える
kubens
デフォルトの namespace をスイッチするために利用
毎回 kubectl --naespaceを実行するのも面倒、kubensでNamespaceの切り替え便利にできる
5.6 直す デバッグしてみよう
下(Pod)から上に順番に調べていく
Pod -> ReplicaSet -> Deployment
5.6.1 準備: Podが動いていることを確認する
code:sh
➜ k apply --filename chapter-05/myapp.yaml -n default
pod/myapp created
➜ k get po myapp -n default
NAME READY STATUS RESTARTS AGE
myapp 1/1 Running 0 51s
5.6.2 アプリケーションを壊してみる
code:sh
➜ k apply --filename chapter-05/pod-destruction.yaml -n default
pod/myapp configured
5.6.3 アプリケーションを調査する
1. kubectl get <リソース名>でリソースの状態を確認
code:sh
➜ k get po -n default
NAME READY STATUS RESTARTS AGE
myapp 0/1 ErrImagePull 0 2m20s
➜ k get po myapp -n default
NAME READY STATUS RESTARTS AGE
myapp 0/1 CrashLoopBackOff 0 3m11s
Podの情報を出ているので、Podのリソースは作成できている
PodがRunningではなく、CrashLoopBackOff(テキストでは、ImagePullBackOff)
イメージの取得で問題が発生し、リトライを待っている状態、コンテナは起動できていない
2. kubectl describe <リソース名>でリソースの詳細を確認
code:sh
❯ k describe po myapp -n default
Name: myapp
Namespace: default
Priority: 0
Service Account: default
Node: kind-control-plane/172.18.0.2
Start Time: Wed, 19 Jun 2024 08:41:14 +0900
Labels: <none>
Annotations: <none>
Status: Running
IP: 10.244.0.9
IPs:
IP: 10.244.0.9
Containers:
hello-server:
Container ID: containerd://633b6b9409463bb7cd4bc95ec54438765492ca1fa5122e2ac2aeefe5028b27df
Image: blux2/hello-server:1.1
Image ID: docker.io/blux2/hello-server@sha256:35ab584cbe96a15ad1fb6212824b3220935d6ac9d25b3703ba259973fac5697d
Port: 8080/TCP
Host Port: 0/TCP
State: Waiting
Reason: CrashLoopBackOff
Last State: Terminated
Reason: Error
Exit Code: 2
Started: Wed, 19 Jun 2024 08:41:15 +0900
Finished: Wed, 19 Jun 2024 08:43:01 +0900
Ready: False
Restart Count: 0
Environment: <none>
Mounts:
/var/run/secrets/kubernetes.io/serviceaccount from kube-api-access-6xvxp (ro)
Conditions:
Type Status
PodReadyToStartContainers True
Initialized True
Ready False
ContainersReady False
PodScheduled True
Volumes:
kube-api-access-6xvxp:
Type: Projected (a volume that contains injected data from multiple sources)
TokenExpirationSeconds: 3607
ConfigMapName: kube-root-ca.crt
ConfigMapOptional: <nil>
DownwardAPI: true
QoS Class: BestEffort
Node-Selectors: <none>
Tolerations: node.kubernetes.io/not-ready:NoExecute op=Exists for 300s
node.kubernetes.io/unreachable:NoExecute op=Exists for 300s
Events:
Type Reason Age From Message
---- ------ ---- ---- -------
Normal Scheduled 5m10s default-scheduler Successfully assigned default/myapp to kind-control-plane
Normal Pulled 5m10s kubelet Container image "blux2/hello-server:1.0" already present on machine
Normal Created 5m10s kubelet Created container hello-server
Normal Started 5m10s kubelet Started container hello-server
Normal Killing 3m24s kubelet Container hello-server definition changed, will be restarted
Normal Pulling 2m41s (x3 over 3m24s) kubelet Pulling image "blux2/hello-server:1.1"
Warning Failed 2m40s (x3 over 3m22s) kubelet Failed to pull image "blux2/hello-server:1.1": rpc error: code = NotFound desc = failed to pull and unpack image "docker.io/blux2/hello-server:1.1": failed to resolve reference "docker.io/blux2/hello-server:1.1": docker.io/blux2/hello-server:1.1: not found
Warning Failed 2m40s (x3 over 3m22s) kubelet Error: ErrImagePull
Normal BackOff 2m2s (x3 over 3m22s) kubelet Back-off pulling image "blux2/hello-server:1.1"
Warning Failed 2m2s (x3 over 3m22s) kubelet Error: ImagePullBackOff
Warning BackOff 6s (x10 over 2m27s) kubelet Back-off restarting failed container hello-server in pod myapp_default(580ac839-a633-410a-9ed8-4039496f3756)
Reason: CrashLoopBackOff
Events に、以下がある
code:sh
Failed to pull image "blux2/hello-server:1.1": rpc error: code = NotFound desc = failed to pull and unpack image "docker.io/blux2/hello-server:1.1": failed to resolve reference "docker.io/blux2/hello-server:1.1": docker.io/blux2/hello-server:1.1: not found
docker.io/blux2/hello-server:1.1 のリポジトリがない? or タグが存在しない?
https://hub.docker.com/r/blux2/hello-server/tags をみると、1.1のタグが存在しなかった
3. kubectl edit <リソース名>で修復する
今回は簡単化のために、editで修復するが、本番では正規デプロイフローでをおすすめ
code:sh
k edit po myapp -n default
spec:
containers:
- image: blux2/hello-server:1.0
imagePullPolicy: IfNotPresent
(保存)
➜ k edit po myapp -n default
pod/myapp edited
// ちゃんとRunningになった
➜ k get po myapp -n default
NAME READY STATUS RESTARTS AGE
myapp 1/1 Running 1 (9m3s ago) 10m