kube-apiserver トラブルシュート

# 目的
- kube-apiserverトラブルシュート手順を整理する

# 手段
- killercoda 環境で手を動かす

# トラブルシュート手順
1. ログ調査

- /var/log/pods
- /var/log/containers
- crictl ps + crictl logs
- kubelet logs: /var/log/syslog or journalctl

```bash:/var/log/pods
kube-system_calico-kube-controllers-94fb6bc47-4wx95_882bd272-cd0e-4a50-be8c-e9d6e6007e0d
kube-system_canal-b9w57_361028af-6efa-4805-8d6e-aa7100a9ed71
kube-system_coredns-57888bfdc7-g2dbp_9eee60a1-16b2-4cf2-b4fc-cbcdd291773a
kube-system_coredns-57888bfdc7-nms5t_fdfbf480-f3c8-4734-aaf1-9ae6a2d4b02a
kube-system_etcd-controlplane_4fb3015641784f175e793600c1e22e8c
kube-system_kube-apiserver-controlplane_53ebb29699412c968f4d993ced098d57
kube-system_kube-controller-manager-controlplane_a55d9c391dc5f492555b54cdef44652d
kube-system_kube-proxy-sqc72_36d52577-5a97-4750-9479-e9b6d562142a
kube-system_kube-scheduler-controlplane_0cfa7f19a2c8cf4c1add14122593c823
local-path-storage_local-path-provisioner-6c5cff8948-tmf26_66648569-53fa-488e-943c-1f910c0a09e1
# pod 単位でフォルダが存在する
# kube-apiserver フォルダ内のログを確認する。
# 連続出力しているログ、ERROR、STDERROR あたりを grep 
```

```bash:/var/log/containers
calico-kube-controllers-94fb6bc47-4wx95_kube-system_calico-kube-controllers-cbe49e7bbba2e58678e8d60741997354b4fe95da7f4920c4c2620a5875eacea4.log
calico-kube-controllers-94fb6bc47-4wx95_kube-system_calico-kube-controllers-e0a02f0388b8ba7fe9e1bb7bd24c3fbf341497910ce8a56d61aac84af4098c57.log
canal-b9w57_kube-system_calico-node-94afbc4803c29d28e0dde526297af5b63af4d56b5e017ee372717e3b06dd948b.log
canal-b9w57_kube-system_calico-node-d6e06f3a5672258d08545021e9b21b5d797a14b8cc2a22d5f7f14082048b9822.log
canal-b9w57_kube-system_install-cni-81d8ac98e91144291a3e7b2ff5bd8c9125d6b68fb07a184c1c2493feb18a2138.log
canal-b9w57_kube-system_kube-flannel-7fc352d07387c79f0718c9c0863796d8454a4924d3f55834fbd3889c88ba7d23.log
canal-b9w57_kube-system_kube-flannel-f67a491d23bf0662734963a1b1228be947c37d2574b40fa52b9dd0fd5e50b085.log
canal-b9w57_kube-system_mount-bpffs-c6268539785280596b658229fae4bdac6ec59175489a9a48ac450f5fd137418c.log
coredns-57888bfdc7-g2dbp_kube-system_coredns-69d2530a1916831ba78ab07e2b5d1d5aaa4652c2e5efe56b1d408f03d959be4b.log
coredns-57888bfdc7-g2dbp_kube-system_coredns-e47e13162d0cdddabedddaf1a138447eccfce6c003dc6afd4a04b42cdb06fae1.log
coredns-57888bfdc7-nms5t_kube-system_coredns-1dcaf6a77fd7490c5727d77e6cc84179449dca3d06ecbb18701356b0d6eec3ef.log
coredns-57888bfdc7-nms5t_kube-system_coredns-d38cae2c4384e291906069b33b5d0daa42c92f909ff7574dfe2fa769aef56513.log
etcd-controlplane_kube-system_etcd-1d47f96e65a91113f154f18895cc3ce3484a3cc26b37bd38167aa745c302f30d.log
etcd-controlplane_kube-system_etcd-cb9a58d7b12c5399cc6650a4edad0f155de2bbe77c95a5ab904e40d2d70b8f6f.log
kube-apiserver-controlplane_kube-system_kube-apiserver-e6367f81ddd17db7884fdc6d8d085a87186f0e88622c0efb531cddca6003b1b8.log
kube-controller-manager-controlplane_kube-system_kube-controller-manager-91685a56d80747b03922bb509f6296806b79d66d06a6a028821e2850e12cf0c1.log
kube-controller-manager-controlplane_kube-system_kube-controller-manager-a111e6fdab5c1846830ec90623d627bdcebcdb4038734fc853ab859db0bafe2d.log
kube-proxy-sqc72_kube-system_kube-proxy-72a4de6ab9c220ba719ca43437d4061679cba6edad55cc5393121a3a6a865d35.log
kube-proxy-sqc72_kube-system_kube-proxy-8b1b8fad648f780df98f35d00d3bad185ec61c4d8decfba1a74f7837aa871f5f.log
kube-scheduler-controlplane_kube-system_kube-scheduler-aecb0893555df4abf562f97dfb26cc56e5a72491e322bb0c035820b533a16b55.log
kube-scheduler-controlplane_kube-system_kube-scheduler-b505cc8b63d3cdbf62e61cc92d6c2ef03bb86a315cf1b2e802b40e6fa6b1c59f.log
local-path-provisioner-6c5cff8948-tmf26_local-path-storage_local-path-provisioner-314f66daa8fd4118c454670e62eff79f917b038666ca9b31b3211a5b000a19a7.log
local-path-provisioner-6c5cff8948-tmf26_local-path-storage_local-path-provisioner-f8851c2a0595417fa8e5fd16dadeb4301101ee063b9066ff3523cd30741976cb.log
# container 単位でログが存在する

controlplane $ ls -la |grep kube-api
lrwxrwxrwx  1 root root    107 Jan 21 10:48 kube-apiserver-controlplane_kube-system_kube-apiserver-e6367f81ddd17db7884fdc6d8d085a87186f0e88622c0efb531cddca6003b1b8.log -> /var/log/pods/kube-system_kube-apiserver-controlplane_53ebb29699412c968f4d993ced098d57/kube-apiserver/0.log
# /var/log/pod/...にシンボリックリンクしている

```

```bash:kubelet logs: /var/log/syslog or journalctl
# kubelet logs コマンドは kube-apiserver 自体が起動しない時は使えない
# /var/log/syslog は kube-apiserver.yaml 内に構文エラー等が存在するときにエラー出力あり
# journalctl は `journalctl |grep kube-apiserver` などで利用する
```

2.コンテナランタイム調査

crictl コマンドでコンテナランタイム側の調査を実施する。

- watch crictl ps 
- crictl logs [containerID]

```bash: watch crictl ps 
Every 2.0s: crictl ps                                                                                                         controlplane: Tue Jan 21 11:03:49 2025

CONTAINER           IMAGE               CREATED             STATE               NAME                      ATTEMPT             POD ID              POD
cbe49e7bbba2e       f9c3c1813269c       14 minutes ago      Running             calico-kube-controllers   7                   07fbe57b89ab1       calico-kube-contro
llers-94fb6bc47-4wx95
e6367f81ddd17       604f5db92eaa8       15 minutes ago      Running             kube-apiserver            0                   93c924f4cd744       kube-apiserver-con
trolplane
b505cc8b63d3c       1766f54c897f0       18 minutes ago      Running             kube-scheduler            4                   5f38ffd4159a6       kube-scheduler-con
trolplane
91685a56d8074       045733566833c       18 minutes ago      Running             kube-controller-manager   4                   90af4775ef0e1       kube-controller-ma
nager-controlplane
f8851c2a05954       95fef08b8bf89       36 minutes ago      Running             local-path-provisioner    1                   dffddfa11e19e       local-path-provisi
oner-6c5cff8948-tmf26
e47e13162d0cd       cbb01a7bd410d       36 minutes ago      Running             coredns                   1                   2d7613359bcee       coredns-57888bfdc7
-g2dbp
1dcaf6a77fd74       cbb01a7bd410d       36 minutes ago      Running             coredns                   1                   6900cf74ce539       coredns-57888bfdc7
-nms5t
f67a491d23bf0       e6ea68648f0cd       36 minutes ago      Running             kube-flannel              1                   6dd8835e73dc7       canal-b9w57
94afbc4803c29       75392e3500e36       36 minutes ago      Running             calico-node               1                   6dd8835e73dc7       canal-b9w57
8b1b8fad648f7       ad83b2ca7b09e       37 minutes ago      Running             kube-proxy                1                   0793bccc6e512       kube-proxy-sqc72
cb9a58d7b12c5       2e96e5913fc06       37 minutes ago      Running             etcd                      1                   5d364a510c02e       etcd-controlplane
# watch コマンドで kube-apiserver コンテナの起動確認を実施
```

```bash:crictl logs [containerID]
# crictl ps コマンドで kube-apiserver の containerIDを確認後、crictl logs コマンドで対象コンテナのログを確認する。

controlplane $ crictl ps |grep kube-apiserver
e6367f81ddd17       604f5db92eaa8       17 minutes ago      Running             kube-apiserver            0                   93c924f4cd744       kube-apiserver-controlplane

controlplane $ crictl logs -f e6367f81ddd17
# --follow オプション等で最新ログを確認
```

3.noderestriction
kubeapiserver にアクセス可能な node の制限設定について説明します。

```bash
export KUBECONFIG=/etc/kubernetes/kubelet.conf
# KUBECONFIG に kubelet.conf ファイルをアサインすれば kubectl コマンド実行可能となる
```

なぜ KUBECONFIG に kubeletl.conf ファイルをアサインすれば kubectl コマンド実行可能となるのだろうか？一つずつ理解してきます。

```bash
node01 $ ps -aux |grep kubelet
root        1097  1.1  4.2 1904504 86372 ?       Ssl  10:53   0:09 /usr/bin/kubelet --bootstrap-kubeconfig=/etc/kubernetes/bootstrap-kubelet.conf --kubeconfig=/etc/kubernetes/kubelet.conf --config=/var/lib/kubelet/config.yaml --container-runtime-endpoint=unix:///var/run/containerd/containerd.sock --pod-infra-container-image=registry.k8s.io/pause:3.10 --container-runtime-endpoint unix:///run/containerd/containerd.sock --cgroup-driver=systemd --eviction-hard imagefs.available<5%,memory.available<100Mi,nodefs.available<5% --fail-swap-on=false
# node 上で apiserver と通信するデーモンは kubelet になる
# kubelt はいくつかの設定ファイルを渡して実行している
```

/var/lib/kubelet/cofnig.yamlの中身を確認する。

```bash
node01 $ cat /var/lib/kubelet/config.yaml 
apiVersion: kubelet.config.k8s.io/v1beta1
authentication:
  anonymous:
    enabled: false
  webhook:
    cacheTTL: 0s
    enabled: true
  x509:
    clientCAFile: /etc/kubernetes/pki/ca.crt
authorization:
  mode: Webhook
  webhook:
    cacheAuthorizedTTL: 0s
    cacheUnauthorizedTTL: 0s
cgroupDriver: systemd
clusterDNS:
- 10.96.0.10
clusterDomain: cluster.local
containerRuntimeEndpoint: ""
cpuManagerReconcilePeriod: 0s
evictionPressureTransitionPeriod: 0s
fileCheckFrequency: 0s
healthzBindAddress: 127.0.0.1
healthzPort: 10248
httpCheckFrequency: 0s
imageMaximumGCAge: 0s
imageMinimumGCAge: 0s
kind: KubeletConfiguration
logging:
  flushFrequency: 0
  options:
    json:
      infoBufferSize: "0"
    text:
      infoBufferSize: "0"
  verbosity: 0
memorySwap: {}
nodeStatusReportFrequency: 0s
nodeStatusUpdateFrequency: 0s
resolvConf: /run/systemd/resolve/resolv.conf
rotateCertificates: true
runtimeRequestTimeout: 0s
shutdownGracePeriod: 0s
shutdownGracePeriodCriticalPods: 0s
staticPodPath: /etc/kubernetes/manifests
streamingConnectionIdleTimeout: 0s
syncFrequency: 0s
volumeStatsAggPeriod: 0s
# むむむ、直接的な記述は見当たらない
```

通常 kubelet は `~/.kube/config` を設定ファイルとして利用する。KUBECOFNIG 変数を設定することで、kubelet が参照する設定ファイルを変更できます。
続いて、kubelet.conf は特定の node が apiserver と通信するための設定が含まれています。言い換えると、`~/.kube/config` に通信したい apiserver の設定ファイルが記述されていないため、KUBECONFIG で kubelet が利用する設定ファイルを切り替える必要があるということになります。

kubectlは、デフォルトで`~/.kube/config`ファイルを参照しますが、KUBECONFIG環境変数が設定されている場合は、その変数に指定されたファイルを優先して使用します。kubectlの設定ファイル参照順序は以下の通りです。

  1. KUBECONFIG(環境変数)を参照
  1. `~/.kube/config` を参照

nodeRestriction(Admission Controllerの機能)は node に対する Label 操作を制限する機能です。例えば、自 node は OK、他 node からの label 編集は NG など、Label 操作に制限を設けることができます。一部(`node-restriction.kubernetes.io/`) システム用途として操作可能な Label も存在します。編集可能な Lable の一覧は公式 doc([nodeRestriction](https://kubernetes.io/docs/reference/access-authn-authz/admission-controllers/#noderestriction))を参照しましょう。

noteRestriction は kube-apiserver 側で有効化します。

```bash
controlplane $ diff ~/kube-apiserver.yaml /etc/kubernetes/manifests/kube-apiserver.yaml 
20a21
>     - --enable-admission-plugins=NodeRestriction
# --enable-admission-plugins で note Restriction を有効化
```

```bash
node01 $ k label node controlplane killercoda/two=123
Error from server (Forbidden): nodes "controlplane" is forbidden: node "node01" is not allowed to modify node "controlplane"
# node01 から controleplane 上の label 変更不可

node01 $ k label node node01 node-restriction.kubernetes.io/two=123
Error from server (Forbidden): nodes "node01" is forbidden: is not allowed to modify labels: node-restriction.kubernetes.io/two
# 自 node に対する `node-restriction.kubernetes.io/` label の変更不可

node01 $ k label node node01 test/two=123
node/node01 labeled
# 自 node に対する label 追加は成功
```

# ソース
- [https://killercoda.com/](https://killercoda.com/)