Static Podとは、APIサーバーが監視せず、特定のノード上のkubeletデーモンによって直接管理されるPodです。 コントロールプレーンに管理されるPod(たとえばDeploymentなど)とは異なり、kubeletがそれぞれのstatic Podを監視(および障害時には再起動)します。
Static Podは、常に特定のノード上の1つのKubeletに紐付けられます。
kubeletは、各static Podに対して、自動的にKubernetes APIサーバー上にミラーPodの作成を試みます。 つまり、ノード上で実行中のPodはAPIサーバーから検出されますが、APIサーバー自身から制御されることはないということです。 Pod名は、先頭にハイフンを付けたノードのホスト名がサフィックスとして追加されます。
Kubernetesクラスターが必要、かつそのクラスターと通信するためにkubectlコマンドラインツールが設定されている必要があります。 このチュートリアルは、コントロールプレーンのホストとして動作していない少なくとも2つのノードを持つクラスターで実行することをおすすめします。 まだクラスターがない場合、minikubeを使って作成するか、 以下のいずれかのKubernetesプレイグラウンドも使用できます:
バージョンを確認するには次のコマンドを実行してください: kubectl version.
このページの説明では、Podを実行するためにCRI-Oを使用しており、ノード上のOSがFedoraであることを前提としています。 他のディストリビューションやKubernetesのインストール方法によっては、操作が異なる場合があります。
static Podは、ファイルシステム上でホストされた設定ファイルまたはウェブ上でホストされた設定ファイルを使用して設定できます。
マニフェストは、JSONまたはYAML形式の標準のPod定義で、特定のディレクトリに置きます。
kubeletの設定ファイルの中で、staticPodPath: <ディレクトリの場所>というフィールドを使用すると、kubeletがこのディレクトリを定期的にスキャンして、YAML/JSONファイルが作成/削除されるたびに、static Podの作成/削除が行われるようになります。
指定したディレクトリをスキャンする際、kubeletはドットから始まる名前のファイルを無視することに注意してください。
cp kube-apiserver.yaml kube-apiserver.yaml.backupを実行してマニフェストのバックアップを作成した場合、kubeletは両方のファイルを読み込み、それぞれからstatic Podを作成しようとします。
2つのファイルが同じ名前のPodを定義している場合、その結果の動作は未定義であり、バックアップの古いspecが現在のマニフェストの代わりに気づかないうちに有効になる可能性があります。
バックアップを作成する場合は、static Podディレクトリの外(例えば/etc/kubernetes/backup/)に保存してください。例として、単純なウェブサーバーをstatic Podとして実行する方法を示します:
static Podを実行したいノードを選択します。
この例では、my-node1です。
ssh my-node1
ディレクトリを選び(ここでは/etc/kubernetes/manifestsとします)、ここにウェブサーバーのPodの定義を置きます。
たとえば、/etc/kubernetes/manifests/static-web.yamlに置きます:
# このコマンドは、kubeletが実行中のノード上で実行してください
mkdir -p /etc/kubernetes/manifests/
cat <<EOF >/etc/kubernetes/manifests/static-web.yaml
apiVersion: v1
kind: Pod
metadata:
name: static-web
labels:
role: myrole
spec:
containers:
- name: web
image: nginx
ports:
- name: web
containerPort: 80
protocol: TCP
EOF
そのノードのkubeletで、kubelet設定ファイルのstaticPodPathの値を設定します。
詳細については、設定ファイルによるkubeletパラメーターの設定を参照してください。
別の非推奨の方法として、コマンドライン引数を使用して、そのノードのkubeletがstatic Podマニフェストをローカルで検索するように設定する方法があります。
非推奨のアプローチを使用するには、--pod-manifest-path=/etc/kubernetes/manifests/引数を指定してkubeletを起動します。
kubeletを再起動します。 Fedoraの場合、次のコマンドを実行します:
# このコマンドは、kubeletが実行中のノード上で実行してください
systemctl restart kubelet
kubeletは、--manifest-url=<URL>引数で指定されたファイルを定期的にダウンロードし、Podの定義が含まれたJSON/YAMLファイルとして解釈します。
kubeletは、ファイルシステム上でホストされたマニフェストでの動作方法と同じように、定期的にマニフェストを再取得します。
static Podのリスト中に変更が見つかると、kubeletがその変更を適用します。
このアプローチを採用する場合、次のように設定します:
YAMLファイルを作成し、kubeletにファイルのURLを渡せるようにするために、ウェブサーバー上に保存します。
apiVersion: v1
kind: Pod
metadata:
name: static-web
labels:
role: myrole
spec:
containers:
- name: web
image: nginx
ports:
- name: web
containerPort: 80
protocol: TCP
選択したノード上のkubeletを--manifest-url=<manifest-url>を使用して実行することで、このウェブ上のマニフェストを使用するように設定します。
Fedoraの場合、/etc/kubernetes/kubeletに次の行が含まれるように編集します:
KUBELET_ARGS="--cluster-dns=10.254.0.10 --cluster-domain=kube.local --manifest-url=<マニフェストのURL>"
kubeletを再起動します。 Fedoraの場合、次のコマンドを実行します:
# このコマンドは、kubeletが実行中のノード上で実行してください
systemctl restart kubelet
kubeletが起動すると、定義されたすべてのstatic Podが自動的に起動されます。 static Podを設定してkubeletを再起動したため、すでに新しいstatic Podが実行中になっているはずです。
次のコマンドを(ノード上で)実行することで、(static Podを含む)実行中のコンテナを確認できます:
# このコマンドは、kubeletが実行中のノード上で実行してください
crictl ps
出力は次のようになります:
CONTAINER IMAGE CREATED STATE NAME ATTEMPT POD ID
129fd7d382018 docker.io/library/nginx@sha256:... 11 minutes ago Running web 0 34533c6729106
crictlは、イメージのURIとSHA-256チェックサムを出力します。
NAMEは次のような形式になります:
docker.io/library/nginx@sha256:0d17b565c37bcbd895e9d92315a05c1c3c9a29f762b011a10c54a66cd53c9b31APIサーバー上では、ミラーPodを確認できます:
kubectl get pods
NAME READY STATUS RESTARTS AGE
static-web-my-node1 1/1 Running 0 2m
static Podに付けたラベルはミラーPodに伝播します。 ミラーPodに付けたラベルは、通常のPodと同じようにセレクターなどから利用できます。
もしkubectlを使用してAPIサーバーからミラーPodを削除しようとしても、kubeletはstatic Podを削除しません。
kubectl delete pod static-web-my-node1
pod "static-web-my-node1" deleted
Podはまだ実行中であることがわかります。
kubectl get pods
NAME READY STATUS RESTARTS AGE
static-web-my-node1 1/1 Running 0 4s
kubeletが動いているノードに戻って、コンテナを手動で停止してみてください。 しばらくすると、kubeletがそれに気づき、Podを自動的に再起動します。
# このコマンドは、kubeletが実行中のノード上で実行してください
crictl stop 129fd7d382018 # 実際のコンテナIDと置き換えてください
sleep 20
crictl ps
CONTAINER IMAGE CREATED STATE NAME ATTEMPT POD ID
89db4553e1eeb docker.io/library/nginx@sha256:... 19 seconds ago Running web 1 34533c6729106
適切なコンテナを特定したら、crictlを使用してそのコンテナのログを取得できます:
# このコマンドは、コンテナが実行中のノード上で実行してください
crictl logs <container_id>
10.240.0.48 - - [16/Nov/2022:12:45:49 +0000] "GET / HTTP/1.1" 200 612 "-" "curl/7.47.0" "-"
10.240.0.48 - - [16/Nov/2022:12:45:50 +0000] "GET / HTTP/1.1" 200 612 "-" "curl/7.47.0" "-"
10.240.0.48 - - [16/Nove/2022:12:45:51 +0000] "GET / HTTP/1.1" 200 612 "-" "curl/7.47.0" "-"
crictlを使ったデバッグの詳細については、crictlによるKubernetesノードのデバッグを参照してください。
実行中のkubeletは設定ディレクトリ(この例では/etc/kubernetes/manifests)の変更を定期的にスキャンし、このディレクトリ内にファイルが追加/削除されると、Podの追加/削除を行います。
# これは、ファイルシステムでホストされているstatic Podの設定を使用していることを前提としています
# このコマンドは、コンテナが実行中のノード上で実行してください
#
mv /etc/kubernetes/manifests/static-web.yaml /tmp
sleep 20
crictl ps
# nginxコンテナが実行されていないことを確認できます
mv /tmp/static-web.yaml /etc/kubernetes/manifests/
sleep 20
crictl ps
CONTAINER IMAGE CREATED STATE NAME ATTEMPT POD ID
f427638871c35 docker.io/library/nginx@sha256:... 19 seconds ago Running web 1 34533c6729106
crictlを使ってデバッグするcrictlについてさらに学ぶ