Pod
Pod は、Kubernetes内で作成・管理できるコンピューティングの最小のデプロイ可能なユニットです。
Pod (Podという名前は、たとえばクジラの群れ(pod of whales)やえんどう豆のさや(pea pod)などの表現と同じような意味です)は、1つまたは複数のコンテナ のグループであり、ストレージやネットワークの共有リソースを持ち、コンテナの実行方法に関する仕様を持っています。同じPodに含まれるリソースは、常に同じ場所で同時にスケジューリングされ、共有されたコンテキストの中で実行されます。Podはアプリケーションに特化した「論理的なホスト」をモデル化します。つまり、1つのPod内には、1つまたは複数の比較的密に結合されたアプリケーションコンテナが含まれます。クラウド外の文脈で説明すると、アプリケーションが同じ物理ホストや同じバーチャルマシンで実行されることが、クラウドアプリケーションの場合には同じ論理ホスト上で実行されることに相当します。
アプリケーションコンテナと同様に、Podでも、Podのスタートアップ時に実行されるinitコンテナ を含めることができます。また、クラスターで利用できる場合には、エフェメラルコンテナ を注入してデバッグすることもできます。
Podとは何か?
備考: KubernetesはDockerだけでなく複数の
コンテナランタイム をサポートしていますが、
Docker が最も一般的に知られたランタイムであるため、Docker由来の用語を使ってPodを説明するのが理解の助けとなります。
Podの共有コンテキストは、Dockerコンテナを隔離するのに使われているのと同じ、Linuxのnamespaces、cgroups、場合によっては他の隔離技術の集合を用いて作られます。Podのコンテキスト内では、各アプリケーションが追加の準隔離技術を適用することもあります。
Dockerの概念を使って説明すると、Podは共有の名前空間と共有ファイルシステムのボリュームを持つDockerコンテナのグループに似ています。
Podを使用する
以下は、nginx:1.14.2
イメージが実行されるコンテナからなるPodの例を記載しています。
apiVersion : v1
kind : Pod
metadata :
name : nginx
spec :
containers :
- name : nginx
image : nginx:1.14.2
ports :
- containerPort : 80
上記のようなPodを作成するには、以下のコマンドを実行します:
kubectl apply -f https://k8s.io/examples/pods/simple-pod.yaml
Podは通常、直接作成されず、ワークロードリソースで作成されます。ワークロードリソースでPodを作成する方法の詳細については、Podを利用する を参照してください。
Podを管理するためのワークロードリソース
通常、たとえ単一のコンテナしか持たないシングルトンのPodだとしても、自分でPodを直接作成する必要はありません。その代わりに、Deployment やJob などのワークロードリソースを使用してPodを作成します。もしPodが状態を保持する必要がある場合は、StatefulSet リソースを使用することを検討してください。
Kubernetesクラスター内のPodは、主に次の2種類の方法で使われます。
単一のコンテナを稼働させるPod 。「1Pod1コンテナ」構成のモデルは、Kubernetesでは最も一般的なユースケースです。このケースでは、ユーザーはPodを単一のコンテナのラッパーとして考えることができます。Kubernetesはコンテナを直接管理するのではなく、Podを管理します。
協調して稼働させる必要がある複数のコンテナを稼働させるPod 。単一のPodは、密に結合してリソースを共有する必要があるような、同じ場所で稼働する複数のコンテナからなるアプリケーションをカプセル化することもできます。これらの同じ場所で稼働するコンテナ群は、単一のまとまりのあるサービスのユニットを構成します。たとえば、1つのコンテナが共有ボリュームからファイルをパブリックに配信し、別のサイドカー コンテナがそれらのファイルを更新するという構成が考えられます。Podはこれらの複数のコンテナ、ストレージリソース、一時的なネットワークIDなどを、単一のユニットとしてまとめます。
備考: 複数のコンテナを同じ場所で同時に管理するように単一のPod内にグループ化するのは、比較的高度なユースケースです。このパターンを使用するのは、コンテナが密に結合しているような特定のインスタンス内でのみにするべきです。
各Podは、与えられたアプリケーションの単一のインスタンスを稼働するためのものです。もしユーザーのアプリケーションを水平にスケールさせたい場合(例: 複数インスタンスを稼働させる)、複数のPodを使うべきです。1つのPodは各インスタンスに対応しています。Kubernetesでは、これは一般的にレプリケーション と呼ばれます。レプリケーションされたPodは、通常ワークロードリソースと、それに対応するコントローラー によって、作成・管理されます。
Kubernetesがワークロードリソースとそのコントローラーを活用して、スケーラブルで自動回復するアプリケーションを実装する方法については、詳しくはPodとコントローラー を参照してください。
Podが複数のコンテナを管理する方法
Podは、まとまりの強いサービスのユニットを構成する、複数の協調する(コンテナとして実行される)プロセスをサポートするために設計されました。単一のPod内の複数のコンテナは、クラスター内の同じ物理または仮想マシン上で、自動的に同じ場所に配置・スケジューリングされます。コンテナ間では、リソースや依存関係を共有したり、お互いに通信したり、停止するときにはタイミングや方法を協調して実行できます。
たとえば、あるコンテナが共有ボリューム内のファイルを配信するウェブサーバーとして動作し、別の「サイドカー」コンテナがリモートのリソースからファイルをアップデートするような構成が考えられます。この構成を以下のダイアグラムに示します。
Podによっては、appコンテナ に加えてinitコンテナ を持っている場合があります。initコンテナはappコンテナが起動する前に実行・完了するコンテナです。
Podは、Podを構成する複数のコンテナに対して、ネットワーク とストレージ の2種類の共有リソースを提供します。
Podを利用する
通常Kubernetesでは、たとえ単一のコンテナしか持たないシングルトンのPodだとしても、個別のPodを直接作成することはめったにありません。その理由は、Podがある程度一時的で使い捨てできる存在として設計されているためです。Podが作成されると(あなたが直接作成した場合でも、コントローラー が間接的に作成した場合でも)、新しいPodはクラスター内のノード 上で実行されるようにスケジューリングされます。Podは、実行が完了するか、Podオブジェクトが削除されるか、リソース不足によって強制退去 されるか、ノードが停止するまで、そのノード上にとどまります。
備考: Pod内のコンテナの再起動とPodの再起動を混同しないでください。Podはプロセスではなく、コンテナが実行するための環境です。Podは削除されるまでは残り続けます。
Podオブジェクトのためのマニフェストを作成したときは、指定したPodの名前が有効なDNSサブドメイン名 であることを確認してください。
Pod OS
FEATURE STATE: Kubernetes v1.25 [stable]
.spec.os.name
フィールドでwindows
かlinux
のいずれかを設定し、Podを実行させたいOSを指定する必要があります。Kubernetesは今のところ、この2つのOSだけサポートしています。将来的には増える可能性があります。
Kubernetes v1.26では、このフィールドに設定した値はPodのスケジューリング に影響を与えません。.spec.os.name
を設定することで、Pod OSに権限を認証することができ、バリデーションにも使用されます。kubeletが実行されているノードのOSが、指定されたPod OSと異なる場合、kubeletはPodの実行を拒否します。
Podセキュリティの標準 もこのフィールドを使用し、指定したOSと関係ないポリシーの適用を回避しています。
Podとコンテナコントローラー
ワークロードリソースは、複数のPodを作成・管理するために利用できます。リソースに対応するコントローラーが、複製やロールアウトを扱い、Podの障害時には自動回復を行います。たとえば、あるノードに障害が発生した場合、コントローラーはそのノードの動作が停止したことを検知し、代わりのPodを作成します。そして、スケジューラーが代わりのPodを健全なノード上に配置します。
以下に、1つ以上のPodを管理するワークロードリソースの一例をあげます。
Podテンプレート
workload リソース向けのコントローラーは、PodをPodテンプレート を元に作成し、あなたの代わりにPodを管理してくれます。
PodTemplateはPodを作成するための仕様で、Deployment 、Job 、DaemonSet などのワークロードリソースの中に含まれています。
ワークロードリソースに対応する各コントローラーは、ワークロードオブジェクト内にあるPodTemplate
を使用して実際のPodを作成します。PodTemplate
は、アプリを実行するために使われるワークロードリソースがどんな種類のものであれ、その目的の状態の一部を構成するものです。
以下は、単純なJobのマニフェストの一例で、1つのコンテナを実行するtemplate
があります。Pod内のコンテナはメッセージを出力した後、一時停止します。
apiVersion : batch/v1
kind : Job
metadata :
name : hello
spec :
template :
# これがPodテンプレートです
spec :
containers :
- name : hello
image : busybox:1.28
command : ['sh' , '-c' , 'echo "Hello, Kubernetes!" && sleep 3600' ]
restartPolicy : OnFailure
# Podテンプレートはここまでです
Podテンプレートを修正するか新しいPodに切り替えたとしても、すでに存在するPodには直接の影響はありません。ワークロードリソース内のPodテンプレートを変更すると、そのリソースは更新されたテンプレートを使用して代わりとなるPodを作成する必要があります。
たとえば、StatefulSetコントローラーは、各StatefulSetごとに、実行中のPodが現在のPodテンプレートに一致することを保証します。Podテンプレートを変更するためにStatefulSetを編集すると、StatefulSetは更新されたテンプレートを元にした新しいPodを作成するようになります。最終的に、すべての古いPodが新しいPodで置き換えられ、更新は完了します。
各ワークロードリソースは、Podテンプレートへの変更を処理するための独自のルールを実装しています。特にStatefulSetについて更に詳しく知りたい場合は、StatefulSetの基本チュートリアル内のアップデート戦略 を読んでください。
ノード上では、kubelet はPodテンプレートに関する詳細について監視や管理を直接行うわけではありません。こうした詳細は抽象化されています。こうした抽象化や関心の分離のおかげでシステムのセマンティクスが単純化され、既存のコードを変更せずにクラスターの動作を容易に拡張できるようになっているのです。
Podの更新と取替
前のセクションで述べたように、ワークロードリソースのPodテンプレートが変更されると、コントローラーは既存のPodを更新したりパッチを適用したりするのではなく、更新されたテンプレートに基づいて新しいPodを作成します。
KubernetesはPodを直接管理することを妨げません。実行中のPodの一部のフィールドをその場で更新することが可能です。しかし、patch
とreplace
といった、Podのアップデート操作にはいくつかの制限があります:
Podのメタデータのほとんどは固定されたものです。たとえばnamespace
、name
、uid
またはcreationTimestamp
フィールドは変更できません。generation
フィールドは特別で、現在の値を増加させる更新のみを受け付けます。
metadata.deletionTimestamp
が設定されている場合、metadata.finalizers
リストに新しい項目を追加することはできません。
Podの更新ではspec.containers[*].image
、spec.initContainers[*].image
、spec.activeDeadlineSeconds
またはspec.tolerations
以外のフィールドを変更してはなりません。
spec.tolerations
については新しい項目のみを追加することができます。
spec.activeDeadlineSeconds
フィールドを更新する場合、2種類の更新が可能です:
未割り当てのフィールドに正の数を設定する
現在の値から負の数でない、より小さい数に更新する
リソースの共有と通信
Podは、データの共有と構成するコンテナ間での通信を可能にします。
Pod内のストレージ
Podでは、共有ストレージであるボリューム の集合を指定できます。Pod内のすべてのコンテナは共有ボリュームにアクセスできるため、それら複数のコンテナでデータを共有できるようになります。また、ボリュームを利用すれば、Pod内のコンテナの1つに再起動が必要になった場合にも、Pod内の永続化データを保持し続けられるようにできます。Kubernetesの共有ストレージの実装方法とPodで利用できるようにする方法に関するさらに詳しい情報は、ストレージ を読んでください。
Podネットワーク
各Podには、各アドレスファミリーごとにユニークなIPアドレスが割り当てられます。Pod内のすべてのコンテナは、IPアドレスとネットワークポートを含むネットワーク名前空間を共有します。Podの中では(かつその場合にのみ )、そのPod内のコンテナはlocalhost
を使用して他のコンテナと通信できます。Podの内部にあるコンテナがPodの外部にある エンティティと通信する場合、(ポートなどの)共有ネットワークリソースの使い方をコンテナ間で調整しなければなりません。Pod内では、コンテナはIPアドレスとポートの空間を共有するため、localhost
で他のコンテナにアクセスできます。また、Pod内のコンテナは、SystemVのセマフォやPOSIXの共有メモリなど、標準のプロセス間通信を使って他のコンテナと通信することもできます。異なるPod内のコンテナは異なるIPアドレスを持つため、特別な設定をしない限り、OSレベルIPCで通信することはできません。異なるPod上で実行中のコンテナ間でやり取りをしたい場合は、IPネットワークを使用して通信できます。
Pod内のコンテナは、システムのhostnameがPodに設定したname
と同一であると考えます。ネットワークについての詳しい情報は、ネットワーク で説明しています。
コンテナの特権モード
Linuxでは、Pod内のどんなコンテナも、privileged
フラグをコンテナのspecのsecurity context に設定することで、特権モード(privileged mode)を有効にできます。これは、ネットワークスタックの操作やハードウェアデバイスへのアクセスなど、オペレーティングシステムの管理者の権限が必要なコンテナの場合に役に立ちます。
WindowsHostProcessContainers
機能を有効にしたクラスターの場合、Pod仕様のsecurityContextにwindowsOptions.hostProcess
フラグを設定することで、Windows HostProcess Pod を作成することが可能です。これらのPod内のすべてのコンテナは、Windows HostProcessコンテナとして実行する必要があります。HostProcess Podはホスト上で直接実行され、Linuxの特権コンテナで行われるような管理作業を行うのにも使用できます。
備考: この設定を有効にするには、
コンテナランタイム が特権コンテナの概念をサポートしていなければなりません。
static Pod
static Pod は、APIサーバー には管理されない、特定のノード上でkubeletデーモンによって直接管理されるPodのことです。大部分のPodはコントロープレーン(たとえばDeployment )によって管理されますが、static Podの場合はkubeletが各static Podを直接管理します(障害時には再起動します)。
static Podは常に特定のノード上の1つのKubelet に紐付けられます。static Podの主な用途は、セルフホストのコントロールプレーンを実行すること、言い換えると、kubeletを使用して個別のコントロールプレーンコンポーネント を管理することです。
kubeletは自動的にKubernetes APIサーバー上に各static Podに対応するミラーPod の作成を試みます。つまり、ノード上で実行中のPodはAPIサーバー上でも見えるようになるけれども、APIサーバー上から制御はできないということです。
コンテナのProbe
Probe はkubeletがコンテナに対して行う定期診断です。診断を実行するために、kubeletはさまざまなアクションを実行できます:
ExecAction
(コンテナランタイムの助けを借りて実行)
TCPSocketAction
(kubeletにより直接チェック)
HTTPGetAction
(kubeletにより直接チェック)
更に詳しく知りたい場合は、PodのライフサイクルドキュメントにあるProbe を読んでください。
次の項目
Kubernetesが共通のPod APIを他のリソース内(たとえばStatefulSet やDeployment など)にラッピングしている理由の文脈を理解するためには、Kubernetes以前から存在する以下のような既存技術について読むのが助けになります。
1 - Podの概観
このページでは、Kubernetesのオブジェクトモデルにおいて、デプロイ可能な最小単位のオブジェクトであるPod
に関して説明します。
Podについて理解する
Pod は、Kubernetesアプリケーションの基本的な実行単位です。これは、作成またはデプロイするKubernetesオブジェクトモデルの中で最小かつ最も単純な単位です。Podは、クラスター で実行されているプロセスを表します。
Podは、アプリケーションのコンテナ(いくつかの場合においては複数のコンテナ)、ストレージリソース、ユニークなネットワークIP、およびコンテナの実行方法を管理するオプションをカプセル化します。Podはデプロイメントの単位、すなわちKubernetesのアプリケーションの単一インスタンス で、単一のコンテナ または密結合なリソースを共有する少数のコンテナで構成される場合があります。
Docker はKubernetesのPod内で使われる最も一般的なコンテナランタイムですが、Podは他のコンテナランタイム も同様にサポートしています。
Kubernetesクラスター内でのPodは2つの主な方法で使うことができます。
単一のコンテナを稼働させるPod : いわゆる*「1Pod1コンテナ」* 構成のモデルは、最も一般的なKubernetesのユースケースです。
このケースでは、ユーザーはPodを単一のコンテナのラッパーとして考えることができ、Kubernetesはコンテナを直接扱うというよりは、Podを管理することになります。
協調して稼働させる必要がある複数のコンテナを稼働させるPod : 単一のPodは、リソースを共有する必要があるような、密接に連携した複数の同じ環境にあるコンテナからなるアプリケーションをカプセル化することもできます。 これらの同じ環境にあるコンテナ群は、サービスの結合力の強いユニットを構成することができます。
-- 1つのコンテナが、共有されたボリュームからファイルをパブリックな場所に送信し、一方では分割されたサイドカー コンテナがそれらのファイルを更新します。そのPodはそれらのコンテナとストレージリソースを、単一の管理可能なエンティティとしてまとめます。
Kubernetes Blog にて、Podのユースケースに関するいくつかの追加情報を見ることができます。さらなる情報を得たい場合は、下記のページを参照ください。
各Podは、与えられたアプリケーションの単一のインスタンスを稼働するためのものです。もしユーザーのアプリケーションを水平にスケールさせたい場合(例: 複数インスタンスを稼働させる)、複数のPodを使うべきです。1つのPodは各インスタンスに対応しています。
Kubernetesにおいて、これは一般的に レプリケーション と呼ばれます。
レプリケーションされたPodは、通常コントローラーと呼ばれる抽象概念によって単一のグループとして作成、管理されます。
さらなる情報に関してはPodとコントローラー を参照して下さい。
Podがどのように複数のコンテナを管理しているか
Podは凝集性の高いサービスのユニットを構成するような複数の協調プロセス(コンテナ)をサポートするためにデザインされました。
単一のPod内のコンテナ群は、クラスター内において同一の物理マシンもしくは仮想マシン上において自動で同じ環境に配備され、スケジュールされます。コンテナはリソースや依存関係を共有し、お互いにコミュニケートし、それらがいつ、どのように削除されるかを調整できます。
注意点として、単一のPod内で同じ環境に配備され、同時管理される複数のコンテナをグルーピングするのは、比較的に発展的なユースケースとなります。
ユーザーは、コンテナ群が密接に連携するような、特定のインスタンスにおいてのみこのパターンを使用するべきです。
例えば、ユーザーが共有ボリューム内にあるファイル用のWebサーバとして稼働するコンテナと、下記のダイアグラムにあるような、リモートのソースからファイルを更新するような分離されたサイドカー コンテナを持っているような場合です。
Podは、Podによって構成されたコンテナ群のために2種類の共有リソースを提供します。 ネットワーキング とストレージ です。
ネットワーキング
各Podは固有のIPアドレスを割り当てられます。単一のPod内の各コンテナは、IPアドレスやネットワークポートを含む、そのネットワークの名前空間を共有します。Pod内の コンテナはlocalhost
を使用してお互いに疎通できます。単一のPod内のコンテナがPod外 のエンティティと疎通する場合、共有されたネットワークリソース(ポートなど)をどのように使うかに関して調整しなければなりません。
ストレージ
単一のPodは共有されたストレージボリューム のセットを指定できます。Pod内の全てのコンテナは、その共有されたボリュームにアクセスでき、コンテナ間でデータを共有することを可能にします。ボリュームもまた、もしPod内のコンテナの1つが再起動が必要になった場合に備えて、データを永続化できます。
単一のPod内での共有ストレージをKubernetesがどう実装しているかについてのさらなる情報については、Volumes を参照してください。
Podを利用する
ユーザーはまれに、Kubernetes内で独立したPodを直接作成する場合があります(シングルトンPodなど)。
これはPodが比較的、一時的な使い捨てエンティティとしてデザインされているためです。Podが作成された時(ユーザーによって直接的、またはコントローラーによって間接的に作成された場合)、ユーザーのクラスター内の単一のノード 上で稼働するようにスケジューリングされます。そのPodはプロセスが停止されたり、Podオブジェクトが削除されたり、Podがリソースの欠如のために追い出され たり、ノードが故障するまでノード上に残り続けます。
備考: 単一のPod内でのコンテナを再起動することと、そのPodを再起動することを混同しないでください。Podはそれ自体は実行されませんが、コンテナが実行される環境であり、削除されるまで存在し続けます。
Podは、Podそれ自体によって自己修復しません。もし、稼働されていないノード上にPodがスケジュールされた場合や、スケジューリング操作自体が失敗した場合、Podが削除されます。同様に、Podはリソースの欠如や、ノードのメンテナンスによる追い出しがあった場合はそこで停止します。Kubernetesはコントローラー と呼ばれる高レベルの抽象概念を使用し、それは比較的使い捨て可能なPodインスタンスの管理を行います。
このように、Podを直接使うのは可能ですが、コントローラーを使用したPodを管理する方がより一般的です。KubernetesがPodのスケーリングと修復機能を実現するためにコントローラーをどのように使うかに関する情報はPodとコントローラー を参照してください。
Podとコントローラー
単一のコントローラーは、ユーザーのために複数のPodを作成・管理し、レプリケーションやロールアウト、クラスターのスコープ内で自己修復の機能をハンドリングします。例えば、もしノードが故障した場合、コントローラーは異なるノード上にPodを置き換えるようにスケジューリングすることで、自動的にリプレース可能となります。
1つまたはそれ以上のPodを含むコントローラーの例は下記の通りです。
通常は、コントローラーはユーザーが作成したPodテンプレートを使用して、担当するPodを作成します。
Podテンプレート
Podテンプレートは、ReplicationController 、 Job や、
DaemonSet のような他のオブジェクト内で含まれるPodの仕様となります。
コントローラーは実際のPodを作成するためにPodテンプレートを使用します。
下記のサンプルは、メッセージを表示する単一のコンテナを含んだ、シンプルなPodのマニフェストとなります。
apiVersion : v1
kind : Pod
metadata :
name : myapp-pod
labels :
app : myapp
spec :
containers :
- name : myapp-container
image : busybox
command : ['sh' , '-c' , 'echo Hello Kubernetes! && sleep 3600' ]
全てのレプリカの現在の理想的な状態を指定するというよりも、Podテンプレートはクッキーの抜き型のようなものです。一度クッキーがカットされると、そのクッキーは抜き型から離れて関係が無くなります。そこにはいわゆる”量子もつれ”といったものはありません。テンプレートに対するその後の変更や新しいテンプレートへの切り替えは、すでに作成されたPod上には直接的な影響はありません。
同様に、ReplicationControllerによって作成されたPodは、変更後に直接更新されます。これはPodとの意図的な違いとなり、そのPodに属する全てのコンテナの現在の理想的な状態を指定します。このアプローチは根本的にシステムのセマンティクスを単純化し、機能の柔軟性を高めます。
次の項目
Pod についてさらに学びましょう
Podの振る舞いに関して学ぶには下記を参照してください
2 - Podのライフサイクル
このページではPodのライフサイクルについて説明します。Podは定義されたライフサイクルに従い Pending
フェーズ から始まり、少なくとも1つのプライマリーコンテナが正常に開始した場合はRunning
を経由し、次に失敗により終了したコンテナの有無に応じて、Succeeded
またはFailed
フェーズを経由します。
Podの実行中、kubeletはコンテナを再起動して、ある種の障害を処理できます。Pod内で、Kubernetesはさまざまなコンテナのステータス を追跡して、回復させるためのアクションを決定します。
Kubernetes APIでは、Podには仕様と実際のステータスの両方があります。Podオブジェクトのステータスは、PodのCondition のセットで構成されます。カスタムのReadiness情報 をPodのConditionデータに挿入することもできます。
Podはその生存期間に1回だけスケジューリング されます。PodがNodeにスケジュール(割り当て)されると、Podは停止または終了 するまでそのNode上で実行されます。
Podのライフタイム
個々のアプリケーションコンテナと同様に、Podは(永続的ではなく)比較的短期間の存在と捉えられます。Podが作成されると、一意のID(UID )が割り当てられ、(再起動ポリシーに従って)終了または削除されるまでNodeで実行されるようにスケジュールされます。
ノード が停止した場合、そのNodeにスケジュールされたPodは、タイムアウト時間の経過後に削除 されます。
Pod自体は、自己修復しません。Podがnode にスケジュールされ、その後に失敗した場合、Podは削除されます。同様に、リソースの不足またはNodeのメンテナンスによりPodはNodeから立ち退きます。Kubernetesは、比較的使い捨てのPodインスタンスの管理作業を処理する、controller と呼ばれる上位レベルの抽象化を使用します。
特定のPod(UIDで定義)は新しいNodeに"再スケジュール"されません。代わりに、必要に応じて同じ名前で、新しいUIDを持つ同一のPodに置き換えることができます。
volume など、Podと同じ存続期間を持つものがあると言われる場合、それは(そのUIDを持つ)Podが存在する限り存在することを意味します。そのPodが何らかの理由で削除された場合、たとえ同じ代替物が作成されたとしても、関連するもの(例えばボリューム)も同様に破壊されて再作成されます。
Podの図
file puller(ファイル取得コンテナ)とWebサーバーを含むマルチコンテナのPod。コンテナ間の共有ストレージとして永続ボリュームを使用しています。
Podのフェーズ
Podのstatus
項目はPodStatus オブジェクトで、それはphase
のフィールドがあります。
Podのフェーズは、そのPodがライフサイクルのどの状態にあるかを、簡単かつ高レベルにまとめたものです。このフェーズはコンテナやPodの状態を包括的にまとめることを目的としたものではなく、また包括的なステートマシンでもありません。
Podの各フェーズの値と意味は厳重に守られています。ここに記載されているもの以外にphase
の値は存在しないと思ってください。
これらがphase
の取りうる値です。
値
概要
Pending
PodがKubernetesクラスターによって承認されましたが、1つ以上のコンテナがセットアップされて稼働する準備ができていません。これには、スケジュールされるまでの時間と、ネットワーク経由でイメージをダウンロードするための時間などが含まれます。
Running
PodがNodeにバインドされ、すべてのコンテナが作成されました。少なくとも1つのコンテナがまだ実行されているか、開始または再起動中です。
Succeeded
Pod内のすべてのコンテナが正常に終了し、再起動されません。
Failed
Pod内のすべてのコンテナが終了し、少なくとも1つのコンテナが異常終了しました。つまり、コンテナはゼロ以外のステータスで終了したか、システムによって終了されました。
Unknown
何らかの理由によりPodの状態を取得できませんでした。このフェーズは通常はPodのホストとの通信エラーにより発生します。
備考: Podの削除中に、kubectlコマンドには
Terminating
が出力されることがあります。この
Terminating
ステータスは、Podのフェーズではありません。Podには、正常に終了するための期間を与えられており、デフォルトは30秒です。
--force
フラグを使用して、
Podを強制的に削除する ことができます。
Nodeが停止するか、クラスタの残りの部分から切断された場合、Kubernetesは失われたNode上のすべてのPodのPhase
をFailedに設定するためのポリシーを適用します。
コンテナのステータス
Pod全体のフェーズ と同様に、KubernetesはPod内の各コンテナの状態を追跡します。container lifecycle hooks を使用して、コンテナのライフサイクルの特定のポイントで実行するイベントをトリガーできます。
Podがscheduler によってNodeに割り当てられると、kubeletはcontainer runtime を使用してコンテナの作成を開始します。コンテナの状態はWaiting
、Running
またはTerminated
の3ついずれかです。
Podのコンテナの状態を確認するにはkubectl describe pod [POD_NAME]
のコマンドを使用します。Pod内のコンテナごとにStateの項目として表示されます。
各状態の意味は次のとおりです。
Waiting
コンテナがRunning
またはTerminated
のいずれの状態でもない場合コンテナはWaiting
の状態になります。Waiting状態のコンテナは引き続きコンテナイメージレジストリからイメージを取得したりSecret を適用したりするなど必要な操作を実行します。Waiting
状態のコンテナを持つPodに対してkubectl
コマンドを使用すると、そのコンテナがWaiting
の状態である理由の要約が表示されます。
Running
Running
状態はコンテナが問題なく実行されていることを示します。postStart
フックが構成されていた場合、それはすでに実行が完了しています。Running
状態のコンテナを持つPodに対してkubectl
コマンドを使用すると、そのコンテナがRunning
状態になった時刻が表示されます。
Terminated
Terminated
状態のコンテナは実行されて、完了したときまたは何らかの理由で失敗したことを示します。Terminated
状態のコンテナを持つPodに対してkubectl
コマンドを使用すると、いずれにせよ理由と終了コード、コンテナの開始時刻と終了時刻が表示されます。
コンテナがTerminated
に入る前にpreStop
フックがあれば実行されます。
コンテナの再起動ポリシー
Podのspec
には、Always、OnFailure、またはNeverのいずれかの値を持つrestartPolicy
フィールドがあります。デフォルト値はAlwaysです。
restartPolicy
は、Pod内のすべてのコンテナに適用されます。restartPolicy
は、同じNode上のkubeletによるコンテナの再起動のみを参照します。Pod内のコンテナが終了した後、kubeletは5分を上限とする指数バックオフ遅延(10秒、20秒、40秒...)でコンテナを再起動します。コンテナが10分間実行されると、kubeletはコンテナの再起動バックオフタイマーをリセットします。
PodのCondition
PodにはPodStatusがあります。それにはPodが成功したかどうかの情報を持つPodCondition の配列が含まれています。kubeletは、下記のPodConditionを管理します:
PodScheduled
: PodがNodeにスケジュールされました。
PodHasNetwork
: (アルファ版機能; 明示的に有効 にしなければならない) Podサンドボックスが正常に成功され、ネットワークの設定が完了しました。
ContainersReady
: Pod内のすべてのコンテナが準備できた状態です。
Initialized
: すべてのInitコンテナ が正常に終了しました。
Ready
: Podはリクエストを処理でき、一致するすべてのサービスの負荷分散プールに追加されます。
フィールド名
内容
type
このPodの状態の名前です。
status
その状態が適用可能かどうか示します。可能な値は"True
"、"False
"、"Unknown
"のうちのいずれかです。
lastProbeTime
Pod Conditionが最後に確認されたときのタイムスタンプが表示されます。
lastTransitionTime
最後にPodのステータスの遷移があった際のタイムスタンプが表示されます。
reason
最後の状態遷移の理由を示す、機械可読のアッパーキャメルケースのテキストです。
message
ステータスの遷移に関する詳細を示す人間向けのメッセージです。
PodのReadiness
FEATURE STATE: Kubernetes v1.14 [stable]
追加のフィードバックやシグナルをPodStatus:Pod readiness に注入できるようにします。これを使用するには、Podのspec
でreadinessGates
を設定して、kubeletがPodのReadinessを評価する追加の状態のリストを指定します。
ReadinessゲートはPodのstatus.conditions
フィールドの現在の状態によって決まります。KubernetesがPodのstatus.conditions
フィールドでそのような状態を発見できない場合、ステータスはデフォルトでFalse
になります。
以下はその例です。
Kind : Pod
...
spec :
readinessGates :
- conditionType : "www.example.com/feature-1"
status :
conditions :
- type : Ready # これはビルトインのPodCondition
status : "False"
lastProbeTime : null
lastTransitionTime : 2018-01-01T00:00:00Z
- type : "www.example.com/feature-1" # 追加のPodCondition
status : "False"
lastProbeTime : null
lastTransitionTime : 2018-01-01T00:00:00Z
containerStatuses :
- containerID : docker://abcd...
ready : true
...
PodのConditionは、Kubernetesのlabel key format に準拠している必要があります。
PodのReadinessの状態
kubectl patch
コマンドはオブジェクトステータスのパッチ適用をまだサポートしていません。Podにこれらのstatus.conditions
を設定するには、アプリケーションとoperators はPATCH
アクションを使用する必要があります。Kubernetes client library を使用して、PodのReadinessのためにカスタムのPodのConditionを設定するコードを記述できます。
カスタムのPodのConditionが導入されるとPodは次の両方の条件に当てはまる場合のみ 準備できていると評価されます:
Pod内のすべてのコンテナが準備完了している。
ReadinessGates
で指定された条件が全てTrue
である。
Podのコンテナは準備完了ですが、少なくとも1つのカスタムのConditionが欠落しているか「False」の場合、kubeletはPodのCondition をContainersReady
に設定します。
PodのネットワークのReadiness
FEATURE STATE: Kubernetes v1.25 [alpha]
Podがノードにスケジュールされた後、kubeletによって承認され、任意のボリュームがマウントされる必要があります。これらのフェーズが完了すると、kubeletはコンテナランタイム(Container runtime interface (CRI) を使用)と連携して、ランタイムサンドボックスのセットアップとPodのネットワークを構成します。もしPodHasNetworkCondition
フィーチャーゲート が有効になっている場合、kubeletは、Podがこの初期化の節目に到達したかどうかをPodのstatus.conditions
フィールドにあるPodHasNetwork
状態を使用して報告します。
ネットワークが設定されたランタイムサンドボックスがPodにないことを検出すると、PodHasNetwork
状態は、kubelet によってFalse
に設定されます。これは、以下のシナリオで発生します:
Podのライフサイクルの初期で、kubeletがコンテナランタイムを使用してPodのサンドボックスのセットアップをまだ開始していないとき
Podのライフサイクルの後期で、Podのサンドボックスが以下のどちらかの原因で破壊された場合:
Podを退去させず、ノードが再起動する
コンテナランタイムの隔離に仮想マシンを使用している場合、Podサンドボックスの仮想マシンが再起動し、新しいサンドボックスと新しいコンテナネットワーク設定を作成する必要があります
ランタイムプラグインによるサンドボックスの作成とPodのネットワーク設定が正常に完了すると、kubeletによってPodHasNetwork
状態がTrue
に設定されます。PodHasNetwork
状態がTrue
に設定された後、kubeletはコンテナイメージの取得とコンテナの作成を開始することができます。
initコンテナを持つPodの場合、initコンテナが正常に完了すると(ランタイムプラグインによるサンドボックスの作成とネットワーク設定が正常に行われた後に発生)、kubeletはInitialized
状態をTrue
に設定します。initコンテナがないPodの場合、サンドボックスの作成およびネットワーク設定が開始する前にkubeletはInitialized
状態をTrue
に設定します。
コンテナのProbe
Probe はkubelet により定期的に実行されるコンテナの診断です。診断を行うために、kubeletはコンテナ内でコードを実行するか、ネットワークリクエストします。
チェックのメカニズム
probeを使ってコンテナをチェックする4つの異なる方法があります。
各probeは、この4つの仕組みのうち1つを正確に定義する必要があります:
exec
コンテナ内で特定のコマンドを実行します。コマンドがステータス0で終了した場合に診断を成功と見なします。
grpc
gRPC を使ってリモートプロシージャコールを実行します。
ターゲットは、gRPC health checks を実装する必要があります。
レスポンスのstatus
がSERVING
の場合に診断を成功と見なします。
gRPCはアルファ版の機能のため、GRPCContainerProbe
フィーチャーゲート が
有効の場合のみ利用可能です。
httpGet
PodのIPアドレスに対して、指定されたポートとパスでHTTP GET
のリクエストを送信します。
レスポンスのステータスコードが200以上400未満の際に診断を成功とみなします。
tcpSocket
PodのIPアドレスに対して、指定されたポートでTCPチェックを行います。
そのポートが空いていれば診断を成功とみなします。
オープンしてすぐにリモートシステム(コンテナ)が接続を切断した場合、健全な状態としてカウントします。
Probeの結果
各Probe 次の3つのうちの一つの結果を持ちます:
Success
コンテナの診断が成功しました。
Failure
コンテナの診断が失敗しました。
Unknown
コンテナの診断が失敗しました(何も実行する必要はなく、kubeletはさらにチェックを行います)。
Probeの種類
kubeletは3種類のProbeを実行中のコンテナで行い、また反応することができます:
livenessProbe
コンテナが動いているかを示します。
livenessProbeに失敗すると、kubeletはコンテナを殺します、そしてコンテナはrestart policy に従います。
コンテナにlivenessProbeが設定されていない場合、デフォルトの状態はSuccess
です。
readinessProbe
コンテナがリクエスト応答する準備ができているかを示します。
readinessProbeに失敗すると、エンドポイントコントローラーにより、ServiceからそのPodのIPアドレスが削除されます。
initial delay前のデフォルトのreadinessProbeの初期値はFailure
です。
コンテナにreadinessProbeが設定されていない場合、デフォルトの状態はSuccess
です。
startupProbe
コンテナ内のアプリケーションが起動したかどうかを示します。
startupProbeが設定された場合、完了するまでその他のすべてのProbeは無効になります。
startupProbeに失敗すると、kubeletはコンテナを殺します、そしてコンテナはrestart policy に従います。
コンテナにstartupProbeが設定されていない場合、デフォルトの状態はSuccess
です。
livenessProbe、readinessProbeまたはstartupProbeを設定する方法の詳細については、Liveness Probe、Readiness ProbeおよびStartup Probeを使用する を参照してください。
livenessProbeをいつ使うべきか?
FEATURE STATE: Kubernetes v1.0 [stable]
コンテナ自体に問題が発生した場合や状態が悪くなった際にクラッシュすることができればlivenessProbeは不要です。
この場合kubeletが自動でPodのrestartPolicy
に基づいたアクションを実行します。
Probeに失敗したときにコンテナを殺したり再起動させたりするには、livenessProbeを設定しrestartPolicy
をAlwaysまたはOnFailureにします。
readinessProbeをいつ使うべきか?
FEATURE STATE: Kubernetes v1.0 [stable]
Probeが成功したときにのみPodにトラフィックを送信したい場合は、readinessProbeを指定します。
この場合readinessProbeはlivenessProbeと同じになる可能性がありますが、readinessProbeが存在するということは、Podがトラフィックを受けずに開始され、Probe成功が開始した後でトラフィックを受け始めることになります。
コンテナがメンテナンスのために停止できるようにするには、livenessProbeとは異なる、特定のエンドポイントを確認するreadinessProbeを指定することができます。
アプリがバックエンドサービスと厳密な依存関係にある場合、livenessProbeとreadinessProbeの両方を実装することができます。アプリ自体が健全であればlivenessProbeはパスしますが、readinessProbeはさらに、必要なバックエンドサービスが利用可能であるかどうかをチェックします。これにより、エラーメッセージでしか応答できないPodへのトラフィックの転送を避けることができます。
コンテナの起動中に大きなデータ、構成ファイル、またはマイグレーションを読み込む必要がある場合は、startupProbe を使用できます。ただし、失敗したアプリと起動データを処理中のアプリの違いを検出したい場合は、readinessProbeを使用した方が良いかもしれません。
備考: Podが削除されたときにリクエストを来ないようにするためには必ずしもreadinessProbeが必要というわけではありません。Podの削除時にはreadinessProbeが存在するかどうかに関係なくPodは自動的に自身をunreadyにします。Pod内のコンテナが停止するのを待つ間Podはunreadyのままです。
startupProbeをいつ使うべきか?
FEATURE STATE: Kubernetes v1.20 [stable]
startupProbeは、サービスの開始に時間がかかるコンテナを持つPodに役立ちます。livenessProbeの間隔を長く設定するのではなく、コンテナの起動時に別のProbeを構成して、livenessProbeの間隔よりも長い時間を許可できます。
コンテナの起動時間が、initialDelaySeconds + failureThreshold x periodSeconds
よりも長い場合は、livenessProbeと同じエンドポイントをチェックするためにstartupProbeを指定します。periodSeconds
のデフォルトは10秒です。次に、failureThreshold
をlivenessProbeのデフォルト値を変更せずにコンテナが起動できるように、十分に高い値を設定します。これによりデッドロックを防ぐことができます。
Podの終了
Podは、クラスター内のNodeで実行中のプロセスを表すため、不要になったときにそれらのプロセスを正常に終了できるようにすることが重要です(対照的なケースは、KILLシグナルで強制終了され、クリーンアップする機会がない場合)。
ユーザーは削除を要求可能であるべきで、プロセスがいつ終了するかを知ることができなければなりませんが、削除が最終的に完了することも保証できるべきです。ユーザーがPodの削除を要求すると、システムはPodが強制終了される前に意図された猶予期間を記録および追跡します。強制削除までの猶予期間がある場合、kubelet 正常な終了を試みます。
通常、コンテナランタイムは各コンテナのメインプロセスにTERMシグナルを送信します。多くのコンテナランタイムは、コンテナイメージで定義されたSTOPSIGNAL値を尊重し、TERMシグナルの代わりにこれを送信します。猶予期間が終了すると、プロセスにKILLシグナルが送信され、PodはAPI server から削除されます。プロセスの終了を待っている間にkubeletかコンテナランタイムの管理サービスが再起動されると、クラスターは元の猶予期間を含めて、最初からリトライされます。
フローの例は下のようになります。
ユーザーがデフォルトの猶予期間(30秒)でPodを削除するためにkubectl
コマンドを送信する。
API server内のPodは、猶予期間を越えるとPodが「死んでいる」と見なされるように更新される。
削除中のPodに対してkubectl describe
コマンドを使用すると、Podは「終了中」と表示される。
Podが実行されているNode上で、Podが終了しているとマークされている(正常な終了期間が設定されている)とkubeletが認識するとすぐに、kubeletはローカルでPodの終了プロセスを開始します。
Pod内のコンテナの1つがpreStop
フック を定義している場合は、コンテナの内側で呼び出される。猶予期間が終了した後もpreStop
フックがまだ実行されている場合は、一度だけ猶予期間を延長される(2秒)。
備考: preStop
フックが完了するまでにより長い時間が必要な場合は、terminationGracePeriodSeconds
を変更する必要があります。
kubeletはコンテナランタイムをトリガーして、コンテナ内のプロセス番号1にTERMシグナルを送信する。
備考: Pod内のすべてのコンテナが同時にTERMシグナルを受信するわけではなく、シャットダウンの順序が問題になる場合はそれぞれにpreStop
フックを使用して同期することを検討する。
kubeletが正常な終了を開始すると同時に、コントロールプレーンは、終了中のPodをEndpointSlice(およびEndpoints)オブジェクトから削除します。これらのオブジェクトは、selector が設定されたService を表します。ReplicaSets とその他のワークロードリソースは、終了中のPodを有効なサービス中のReplicaSetとして扱いません。ゆっくりと終了するPodは、(サービスプロキシーのような)ロードバランサーが終了猶予期間が始まる とエンドポイントからそれらのPodを削除するので、トラフィックを継続して処理できません。
猶予期間が終了すると、kubeletは強制削除を開始する。コンテナランタイムは、Pod内でまだ実行中のプロセスにSIGKILL
を送信する。kubeletは、コンテナランタイムが非表示のpause
コンテナを使用している場合、そのコンテナをクリーンアップします。
kubeletは猶予期間を0(即時削除)に設定することでAPI server上のPodの削除を終了する。
API serverはPodのAPIオブジェクトを削除し、クライアントからは見えなくなります。
Podの強制削除
注意: 強制削除は、Podによっては潜在的に危険な場合があるため、慎重に実行する必要があります。
デフォルトでは、すべての削除は30秒以内に正常に行われます。kubectl delete
コマンドは、ユーザーがデフォルト値を上書きして独自の値を指定できるようにする --grace-period=<seconds>
オプションをサポートします。
--grace-period
を0
に設定した場合、PodはAPI serverから即座に強制的に削除されます。PodがNode上でまだ実行されている場合、その強制削除によりkubeletがトリガーされ、すぐにクリーンアップが開始されます。
備考: 強制削除を実行するために --grace-period=0
と共に --force
というフラグを追加で指定する必要があります。
強制削除が実行されると、API serverは、Podが実行されていたNode上でPodが停止されたというkubeletからの確認を待ちません。API内のPodは直ちに削除されるため、新しいPodを同じ名前で作成できるようになります。Node上では、すぐに終了するように設定されるPodは、強制終了される前にわずかな猶予期間が与えられます。
注意: 即時削除では、実行中のリソースの終了を待ちません。
リソースはクラスタ上で無期限に実行し続ける可能性があります。
StatefulSetのPodについては、StatefulSetからPodを削除するためのタスクのドキュメント を参照してください。
終了したPodのガベージコレクション
失敗したPodは人間またはcontroller が明示的に削除するまで存在します。
コントロールプレーンは終了状態のPod(SucceededまたはFailedのphase
を持つ)の数が設定された閾値(kube-controller-manager内のterminated-pod-gc-threshold
によって定義される)を超えたとき、それらのPodを削除します。これはPodが作成されて時間とともに終了するため、リソースリークを避けます。
次の項目
3 - Initコンテナ
このページでは、Initコンテナについて概観します。Initコンテナとは、Pod 内でアプリケーションコンテナの前に実行される特別なコンテナです。
Initコンテナにはアプリケーションコンテナのイメージに存在しないセットアップスクリプトやユーティリティーを含めることができます。
Initコンテナは、Podの仕様のうちcontainers
という配列(これがアプリケーションコンテナを示します)と並べて指定します。
Initコンテナを理解する
単一のPod は、Pod内にアプリケーションを実行している複数のコンテナを持つことができますが、同様に、アプリケーションコンテナが起動する前に実行されるInitコンテナも1つ以上持つことができます。
Initコンテナは下記の項目をのぞいて、通常のコンテナと全く同じものとなります。
Initコンテナは常に完了するまで稼働します。
各Initコンテナは、次のInitコンテナが稼働する前に正常に完了しなくてはなりません。
もしあるPodの単一のInitコンテナが失敗した場合、Kubeletは成功するまで何度もそのInitコンテナを再起動します。しかし、もしそのPodのrestartPolicy
がNeverで、そのPodの起動時にInitコンテナが失敗した場合、KubernetesはそのPod全体を失敗として扱います。
PodにInitコンテナを指定するためには、Podの仕様 にinitContainers
フィールドをcontainer
アイテムの配列として追加してください(アプリケーションのcontainers
フィールドとそのコンテンツに似ています)。
詳細については、APIリファレンスのContainer を参照してください。
Initコンテナのステータスは、.status.initContainerStatuses
フィールドにコンテナのステータスの配列として返されます(.status.containerStatuses
と同様)。
通常のコンテナとの違い
Initコンテナは、リソースリミット、ボリューム、セキュリティ設定などのアプリケーションコンテナの全てのフィールドと機能をサポートしています。しかし、Initコンテナに対するリソースリクエストやリソースリミットの扱いは異なります。リソース にて説明します。
また、InitコンテナはそのPodの準備ができる前に完了しなくてはならないため、lifecycle
、livenessProbe
、readinessProbe
およびstartupProbe
をサポートしていません。
複数のInitコンテナを単一のPodに対して指定した場合、KubeletはそれらのInitコンテナを1つずつ順番に実行します。各Initコンテナは、次のInitコンテナが稼働する前に正常終了しなくてはなりません。全てのInitコンテナの実行が完了すると、KubeletはPodのアプリケーションコンテナを初期化し、通常通り実行します。
Initコンテナを使用する
Initコンテナはアプリケーションコンテナのイメージとは分離されているため、コンテナの起動に関連したコードにおいていくつかの利点があります。
Initコンテナはアプリケーションのイメージに存在しないセットアップ用のユーティリティーやカスタムコードを含むことができます。例えば、セットアップ中にsed
、awk
、python
や、dig
のようなツールを使うためだけに、別のイメージを元にしてアプリケーションイメージを作る必要がなくなります。
アプリケーションイメージをビルドする役割とデプロイする役割は、共同で単一のアプリケーションイメージをビルドする必要がないため、それぞれ独立して実施することができます。
Initコンテナは同一Pod内のアプリケーションコンテナと別のファイルシステムビューで稼働することができます。その結果、アプリケーションコンテナがアクセスできないSecret に対するアクセス権限を得ることができます。
Initコンテナはアプリケーションコンテナが開始する前に完了するまで実行されるため、Initコンテナを使用することで、特定の前提条件が満たされるまでアプリケーションコンテナの起動をブロックしたり遅らせることができます。前提条件が満たされると、Pod内の全てのアプリケーションコンテナを並行して起動することができます。
Initコンテナはアプリケーションコンテナイメージの安全性を低下させるようなユーティリティーやカスタムコードを安全に実行することができます。不必要なツールを分離しておくことで、アプリケーションコンテナイメージのアタックサーフィスを制限することができます。
例
Initコンテナを活用する方法について、いくつかのアイデアを次に示します。
シェルコマンドを使って単一のService が作成されるのを待機する。
for i in { 1..100} ; do sleep 1; if dig myservice; then exit 0; fi ; done ; exit 1
以下のようなコマンドを使って下位のAPIからPodの情報をリモートサーバに登録する。
curl -X POST http://$MANAGEMENT_SERVICE_HOST :$MANAGEMENT_SERVICE_PORT /register -d 'instance=$(<POD_NAME>)&ip=$(<POD_IP>)'
以下のようなコマンドを使ってアプリケーションコンテナの起動を待機する。
gitリポジトリをVolume にクローンする。
いくつかの値を設定ファイルに配置し、メインのアプリケーションコンテナのための設定ファイルを動的に生成するためのテンプレートツールを実行する。例えば、そのPodのPOD_IP
の値を設定ファイルに配置し、Jinjaを使ってメインのアプリケーションコンテナの設定ファイルを生成する。
Initコンテナの具体的な使用方法
下記の例は2つのInitコンテナを含むシンプルなPodを定義しています。
1つ目のInitコンテナはmyservies
の起動を、2つ目のInitコンテナはmydb
の起動をそれぞれ待ちます。両方のInitコンテナの実行が完了すると、Podはspec
セクションにあるアプリケーションコンテナを実行します。
apiVersion : v1
kind : Pod
metadata :
name : myapp-pod
labels :
app.kubernetes.io/name : MyApp
spec :
containers :
- name : myapp-container
image : busybox:1.28
command : ['sh' , '-c' , 'echo The app is running! && sleep 3600' ]
initContainers :
- name : init-myservice
image : busybox:1.28
command : ['sh' , '-c' , "until nslookup myservice.$(cat /var/run/secrets/kubernetes.io/serviceaccount/namespace).svc.cluster.local; do echo waiting for myservice; sleep 2; done" ]
- name : init-mydb
image : busybox:1.28
command : ['sh' , '-c' , "until nslookup mydb.$(cat /var/run/secrets/kubernetes.io/serviceaccount/namespace).svc.cluster.local; do echo waiting for mydb; sleep 2; done" ]
次のコマンドを実行して、このPodを開始できます。
kubectl apply -f myapp.yaml
実行結果は下記のようになります。
pod/myapp-pod created
そして次のコマンドでステータスを確認します。
kubectl get -f myapp.yaml
実行結果は下記のようになります。
NAME READY STATUS RESTARTS AGE
myapp-pod 0/1 Init:0/2 0 6m
より詳細な情報は次のコマンドで確認します。
kubectl describe -f myapp.yaml
実行結果は下記のようになります。
Name: myapp-pod
Namespace: default
[...]
Labels: app.kubernetes.io/name=MyApp
Status: Pending
[...]
Init Containers:
init-myservice:
[...]
State: Running
[...]
init-mydb:
[...]
State: Waiting
Reason: PodInitializing
Ready: False
[...]
Containers:
myapp-container:
[...]
State: Waiting
Reason: PodInitializing
Ready: False
[...]
Events:
FirstSeen LastSeen Count From SubObjectPath Type Reason Message
--------- -------- ----- ---- ------------- -------- ------ -------
16s 16s 1 {default-scheduler } Normal Scheduled Successfully assigned myapp-pod to 172.17.4.201
16s 16s 1 {kubelet 172.17.4.201} spec.initContainers{init-myservice} Normal Pulling pulling image "busybox"
13s 13s 1 {kubelet 172.17.4.201} spec.initContainers{init-myservice} Normal Pulled Successfully pulled image "busybox"
13s 13s 1 {kubelet 172.17.4.201} spec.initContainers{init-myservice} Normal Created Created container with docker id 5ced34a04634; Security:[seccomp=unconfined]
13s 13s 1 {kubelet 172.17.4.201} spec.initContainers{init-myservice} Normal Started Started container with docker id 5ced34a04634
このPod内のInitコンテナのログを確認するためには、次のコマンドを実行します。
kubectl logs myapp-pod -c init-myservice # 1つ目のInitコンテナを調査する
kubectl logs myapp-pod -c init-mydb # 2つ目のInitコンテナを調査する
この時点で、これらのInitコンテナはmydb
とmyservice
という名前のServiceの検出を待機しています。
これらのServiceを検出させるための構成は以下の通りです。
---
apiVersion : v1
kind : Service
metadata :
name : myservice
spec :
ports :
- protocol : TCP
port : 80
targetPort : 9376
---
apiVersion : v1
kind : Service
metadata :
name : mydb
spec :
ports :
- protocol : TCP
port : 80
targetPort : 9377
mydb
およびmyservice
というServiceを作成するために、以下のコマンドを実行します。
kubectl apply -f services.yaml
実行結果は下記のようになります。
service/myservice created
service/mydb created
Initコンテナが完了し、myapp-pod
というPodがRunning状態に移行したことが確認できます。
kubectl get -f myapp.yaml
実行結果は下記のようになります。
NAME READY STATUS RESTARTS AGE
myapp-pod 1/1 Running 0 9m
このシンプルな例を独自のInitコンテナを作成する際の参考にしてください。次の項目 にさらに詳細な使用例に関するリンクがあります。
Initコンテナのふるまいに関する詳細
Podの起動時に、kubeletはネットワークおよびストレージの準備が整うまで、Initコンテナを実行可能な状態にしません。また、kubeletはPodのspecに定義された順番に従ってPodのInitコンテナを起動します。
各Initコンテナは次のInitコンテナが起動する前に正常に終了しなくてはなりません。もしあるInitコンテナがランタイムにより起動失敗した場合、もしくはエラーで終了した場合、そのPodのrestartPolicy
の値に従ってリトライされます。しかし、もしPodのrestartPolicy
がAlways
に設定されていた場合、InitコンテナのrestartPolicy
はOnFailure
が適用されます。
Podは全てのInitコンテナが完了するまでReady
状態となりません。Initコンテナ上のポートはServiceによって集約されません。初期化中のPodのステータスはPending
となりますが、Initialized
という値はtrueとなります。
もしそのPodを再起動 するとき、または再起動されたとき、全てのInitコンテナは必ず再度実行されます。
Initコンテナの仕様の変更は、コンテナイメージのフィールドのみに制限されています。
Initコンテナのイメージフィールド値を変更すると、そのPodは再起動されます。
Initコンテナは何度も再起動、リトライおよび再実行可能なため、べき等(Idempotent)である必要があります。特に、EmptyDirs
にファイルを書き込むコードは、書き込み先のファイルがすでに存在している可能性を考慮に入れる必要があります。
Initコンテナはアプリケーションコンテナの全てのフィールドを持っています。しかしKubernetesは、Initコンテナが完了と異なる状態を定義できないためreadinessProbe
が使用されることを禁止しています。これはバリデーションの際に適用されます。
Initコンテナがずっと失敗し続けたままの状態を防ぐために、PodにactiveDeadlineSeconds
を設定してください。activeDeadlineSeconds
の設定はInitコンテナが実行中の時間にも適用されます。しかしactiveDeadlineSeconds
はInitコンテナが終了した後でも効果があるため、チームがアプリケーションをJobとしてデプロイする場合にのみ使用することが推奨されています。
すでに正しく動作しているPodはactiveDeadlineSeconds
を設定すると強制終了されます。
Pod内の各アプリケーションコンテナとInitコンテナの名前はユニークである必要があります。他のコンテナと同じ名前を共有していた場合、バリデーションエラーが返されます。
リソース
Initコンテナの順序と実行を考えるとき、リソースの使用に関して下記のルールが適用されます。
全てのInitコンテナの中で定義された最も高いリソースリクエストとリソースリミットが、有効なinitリクエスト/リミット になります。いずれかのリソースでリミットが設定されていない場合、これが最上級のリミットとみなされます。
Podのリソースの有効なリクエスト/リミット は、下記の2つの中のどちらか高い方となります。
リソースに対する全てのアプリケーションコンテナのリクエスト/リミットの合計
リソースに対する有効なinitリクエスト/リミット
スケジューリングは有効なリクエスト/リミットに基づいて実行されます。つまり、InitコンテナはPodの生存中には使用されない初期化用のリソースを確保することができます。
Podの有効なQoS(quality of service)ティアー は、Initコンテナとアプリケーションコンテナで同様です。
クォータとリミットは有効なPodリクエストとリミットに基づいて適用されます。
Podレベルのコントロールグループ(cgroups)は、スケジューラーと同様に、有効なPodリクエストとリミットに基づいています。
Podの再起動の理由
以下の理由によりPodは再起動し、Initコンテナの再実行も引き起こす可能性があります。
そのPodのインフラストラクチャーコンテナが再起動された場合。これはあまり起きるものでなく、Nodeに対するルート権限を持ったユーザーにより行われることがあります。
restartPolicy
がAlways
と設定されているPod内の全てのコンテナが停止され、強制的に再起動が行われたことで、ガベージコレクションによりInitコンテナの完了記録が失われた場合。
Kubernetes v1.20以降では、initコンテナのイメージが変更されたり、ガベージコレクションによってinitコンテナの完了記録が失われたりした場合でも、Podは再起動されません。以前のバージョンを使用している場合は、対応バージョンのドキュメントを参照してください。
次の項目
4 - Pod Preset
FEATURE STATE: Kubernetes v1.6 [alpha]
このページではPodPresetについて概観します。PodPresetは、Podの作成時にそのPodに対して、Secret、Volume、VolumeMountや環境変数など、特定の情報を注入するためのオブジェクトです。
PodPresetを理解する
PodPreset
はPodの作成時に追加のランタイム要求を注入するためのAPIリソースです。ユーザーはPodPresetを適用する対象のPodを指定するために、ラベルセレクター を使用します。
PodPresetの使用により、Podテンプレートの作者はPodにおいて、全ての情報を明示的に指定する必要がなくなります。この方法により、特定のServiceを使っているPodテンプレートの作者は、そのServiceについて全ての詳細を知る必要がなくなります。
クラスターでPodPresetを有効にする
ユーザーのクラスター内でPodPresetを使うためには、クラスター内の以下の項目をご確認ください。
settings.k8s.io/v1alpha1/podpreset
というAPIを有効にします。例えば、これはAPI Serverの --runtime-config
オプションにsettings.k8s.io/v1alpha1=true
を含むことで可能になります。Minikubeにおいては、クラスターの起動時に--extra-config=apiserver.runtime-config=settings.k8s.io/v1alpha1=true
をつけることで可能です。
PodPreset
に対する管理コントローラーを有効にします。これを行うための1つの方法として、API Serverの--enable-admission-plugins
オプションの値にPodPreset
を含む方法があります。例えば、Minikubeにおいては、クラスターの起動時に
--extra-config= apiserver.enable-admission-plugins= NamespaceLifecycle,LimitRanger,ServiceAccount,DefaultStorageClass,DefaultTolerationSeconds,NodeRestriction,MutatingAdmissionWebhook,ValidatingAdmissionWebhook,ResourceQuota,PodPreset
を追加することで可能になります。
PodPresetはどのように動くか
KubernetesはPodPreset
に対する管理用コントローラーを提供し、これが有効になっている時、コントローラーはリクエストされたPod作成要求に対してPodPresetを適用します。Pod作成要求が発生した時、Kubernetesシステムは下記の処理を行います。
使用可能な全てのPodPreset
を取得する。
それらのPodPreset
のラベルセレクターが、作成されたPod上のラベルと一致するかチェックする。
PodPreset
によって定義された様々なリソースを、作成されたPodにマージしようと試みる。
エラーが起きた時、そのPod上でマージエラーが起きたことを説明するイベントをスローし、PodPreset
からリソースを1つも注入されていないPodを作成します。
PodPreset
によって修正されたことを示すために、マージ後の修正されたPodにアノテーションをつけます。そのアノテーションはpodpreset.admission.kubernetes.io/podpreset-<PodPreset名>: "<リソースのバージョン>"
という形式になります。
各Podは0以上のPodPresetにマッチすることができます。そして各PodPresetは0以上のPodに適用されます。単一のPodPresetが1以上のPodに適用された時、KubernetesはそのPodのSpecを修正します。env
、envFrom
、volumeMounts
への変更があると、KubernetesはそのPod内の全てのコンテナのSpecを修正します。volumes
への変更があった場合、KubernetesはそのPodのSpecを修正します。
備考: 単一のPodPresetは必要に応じてPodのspec内の以下のフィールドを修正することができます。
.spec.containers
フィールド
.spec.initContainers
フィールド
特定のPodに対するPodPresetを無効にする
PodPresetによるPodの変更を受け付けたくないようなインスタンスがある場合があります。このようなケースでは、ユーザーはそのPodの.spec
内に次のような形式のアノテーションを追加できます。
podpreset.admission.kubernetes.io/exclude: "true"
次の項目
PodPresetを使ったPodへのデータの注入
PodPresetの内部についてのさらなる情報は、PodPresetのデザインプロポーザル を参照してください。
5 - エフェメラルコンテナ
FEATURE STATE: Kubernetes v1.16 [alpha]
このページでは、特別な種類のコンテナであるエフェメラルコンテナの概要を説明します。エフェメラルコンテナは、トラブルシューティングなどのユーザーが開始するアクションを実行するために、すでに存在するPod 内で一時的に実行するコンテナです。エフェメラルコンテナは、アプリケーションの構築ではなく、serviceの調査のために利用します。
警告: エフェメラルコンテナは初期のアルファ状態であり、本番クラスタには適しません。
Kubernetesの非推奨ポリシー に従って、このアルファ機能は、将来大きく変更されたり、完全に削除される可能性があります。
エフェメラルコンテナを理解する
Pod は、Kubernetesのアプリケーションの基本的なビルディングブロックです。Podは破棄可能かつ置き換え可能であることが想定されているため、一度Podが作成されると新しいコンテナを追加することはできません。その代わりに、通常はDeployment を使用してPodを削除して置き換えます。
たとえば、再現困難なバグのトラブルシューティングなどのために、すでに存在するPodの状態を調査する必要が出てくることがあります。このような場合、既存のPod内でエフェメラルコンテナを実行することで、Podの状態を調査したり、任意のコマンドを実行したりできます。
エフェメラルコンテナとは何か?
エフェメラルコンテナは、他のコンテナと異なり、リソースや実行が保証されず、自動的に再起動されることも決してないため、アプリケーションを構築する目的には適しません。エフェメラルコンテナは、通常のコンテナと同じContainerSpec
で記述されますが、多くのフィールドに互換性がなかったり、使用できなくなっています。
エフェメラルコンテナはポートを持つことができないため、ports
、livenessProbe
、readinessProbe
などは使えなくなっています。
Podリソースの割り当てはイミュータブルであるため、resources
の設定が禁止されています。
利用が許可されているフィールドの一覧については、EphemeralContainerのリファレンスドキュメント を参照してください。
エフェメラルコンテナは、直接pod.spec
に追加するのではなく、API内の特別なephemeralcontainers
ハンドラを使用して作成します。そのため、エフェメラルコンテナをkubectl edit
を使用して追加することはできません。
エフェメラルコンテナをPodに追加した後は、通常のコンテナのようにエフェメラルコンテナを変更または削除することはできません。
エフェメラルコンテナの用途
エフェメラルコンテナは、コンテナがクラッシュしてしまったり、コンテナイメージにデバッグ用ユーティリティが同梱されていない場合など、kubectl exec
では不十分なときにインタラクティブなトラブルシューティングを行うために役立ちます。
特に、distrolessイメージ を利用すると、攻撃対象領域を減らし、バグや脆弱性を露出する可能性を減らせる最小のコンテナイメージをデプロイできるようになります。distrolessイメージにはシェルもデバッグ用のユーティリティも含まれないため、kubectl exec
のみを使用してdistrolessイメージのトラブルシューティングを行うのは困難です。
エフェメラルコンテナを利用する場合には、他のコンテナ内のプロセスにアクセスできるように、プロセス名前空間の共有 を有効にすると便利です。
エフェメラルコンテナを利用してトラブルシューティングを行う例については、デバッグ用のエフェメラルコンテナを使用してデバッグする を参照してください。
Ephemeral containers API
備考: このセクションの例を実行するには、
EphemeralContainers
フィーチャーゲート を有効にして、Kubernetesクライアントとサーバーのバージョンをv1.16以上にする必要があります。
このセクションの例では、API内でエフェメラルコンテナを表示する方法を示します。通常は、APIを直接呼び出すのではなく、kubectl alpha debug
やその他のkubectl
プラグイン を使用して、これらのステップを自動化します。
エフェメラルコンテナは、Podのephemeralcontainers
サブリソースを使用して作成されます。このサブリソースは、kubectl --raw
を使用して確認できます。まずはじめに、以下にEphemeralContainers
リストとして追加するためのエフェメラルコンテナを示します。
{
"apiVersion" : "v1" ,
"kind" : "EphemeralContainers" ,
"metadata" : {
"name" : "example-pod"
},
"ephemeralContainers" : [{
"command" : [
"sh"
],
"image" : "busybox" ,
"imagePullPolicy" : "IfNotPresent" ,
"name" : "debugger" ,
"stdin" : true ,
"tty" : true ,
"terminationMessagePolicy" : "File"
}]
}
すでに実行中のexample-pod
のエフェメラルコンテナを更新するには、次のコマンドを実行します。
kubectl replace --raw /api/v1/namespaces/default/pods/example-pod/ephemeralcontainers -f ec.json
このコマンドを実行すると、新しいエフェメラルコンテナのリストが返されます。
{
"kind" :"EphemeralContainers" ,
"apiVersion" :"v1" ,
"metadata" :{
"name" :"example-pod" ,
"namespace" :"default" ,
"selfLink" :"/api/v1/namespaces/default/pods/example-pod/ephemeralcontainers" ,
"uid" :"a14a6d9b-62f2-4119-9d8e-e2ed6bc3a47c" ,
"resourceVersion" :"15886" ,
"creationTimestamp" :"2019-08-29T06:41:42Z"
},
"ephemeralContainers" :[
{
"name" :"debugger" ,
"image" :"busybox" ,
"command" :[
"sh"
],
"resources" :{
},
"terminationMessagePolicy" :"File" ,
"imagePullPolicy" :"IfNotPresent" ,
"stdin" :true ,
"tty" :true
}
]
}
新しく作成されたエフェメラルコンテナの状態を確認するには、kubectl describe
を使用します。
kubectl describe pod example-pod
...
Ephemeral Containers:
debugger:
Container ID: docker://cf81908f149e7e9213d3c3644eda55c72efaff67652a2685c1146f0ce151e80f
Image: busybox
Image ID: docker-pullable://busybox@sha256:9f1003c480699be56815db0f8146ad2e22efea85129b5b5983d0e0fb52d9ab70
Port: <none>
Host Port: <none>
Command:
sh
State: Running
Started: Thu, 29 Aug 2019 06:42:21 +0000
Ready: False
Restart Count: 0
Environment: <none>
Mounts: <none>
...
新しいエフェメラルコンテナとやりとりをするには、他のコンテナと同じように、kubectl attach
、kubectl exec
、kubectl logs
などのコマンドが利用できます。例えば、次のようなコマンドが実行できます。
kubectl attach -it example-pod -c debugger