この記事は Kubernetes道場 Advent Calendar 2018 13日目の記事です。
今回はStatefulSetとDaemonSetについて。
StatefulSet
StatefulSetの概要
StatefulSetは状態を保持する(ステートフルな)アプリケーションを管理するためのKubernetesオブジェクトだ。
イメージ的にはPodTemplateを持つDeploymentにPVCも追加した感じ。
StatefulSetには以下のような特徴がある。
- 安定したネットワーク識別子
- 安定した永続ストレージ
- 順序付けされたグレースフルなデプロイとスケール
- 順序付けされた自動ローリングアップデート
1つずつ見ていこう。
安定したネットワーク識別子
StatefulSetで管理されるPodは順序付けされたユニークな識別子が付与される。 StatefulSetで複製数をNにした際には、0からN-1の序数が使用される。
この識別子がネットワークの識別子にも利用される。Podのホスト名は $(StatefulSet Name)-$(Ordinal) になる。
また、Headless Serviceを使ってPodのドメインを設定することが出来る。
その場合は $(StatefulSet Name)-$(Ordinal).$(Service Name).$(Namespace).svc.$(Cluster Domain) というドメインになる。
(通常、コンテナの resolve.conf の search に $(Namespace).svc.$(Cluster Domain) が設定されているため $(StatefulSet Name)-$(Ordinal).$(Service Name) で引けるはずだ)
安定した永続ストレージ
StatefulSetはVolumeClaimTemplateで指定されたClaimそれぞれに1つずつのPVが作成され、Podにマウントされる。
StatefulSetによって作成されたPVCは、StatefulSetが削除された際にはPVCは削除されない。PVCを削除する場合は手動で削除する必要がある。
順序付けされたグレースフルなデプロイとスケール
StatefulSetが作成・削除された際の動きを確認しよう。
StatefulSet作成時
複製数NのStatefulSetを作成され、Podが作成される際は、0から順に1つずつN-1まで作成される。
StatefulSetのPodが削除される際
Podが削除される際は、StatefulSetの序数の逆順で停止・削除が実行される。
StatefulSetスケール時
StatefulSetのスケール時には既にあるStatefulSetのPodが全てReady状態である必要がある。
StatefulSetのPod停止時
StatefulSetのPodを停止する際には、対象のPodより序数が大きいPod全てが完全にシャットダウンしている必要がある。
StatefulSetの管理ポリシー
StatefulSetのPodを管理するポリシーを変更することが出来る。ポリシーは現状2種類ある。
OrderedReady
StatefulSetのデフォルトで上記で解説した動きでPodの管理を行う。
Parallel
Parallel ではStatefulSetで管理する全てのPodの起動や停止を並行して行う。
また、起動や停止の際にReady状態や完全に停止するのを待たずに行う。
順序付けされた自動ローリングアップデート
StatefulSetは spec.updateStrategy フィールドでPodの自動ローリングアップデートを有効や無効に設定できる。
StatefulSetの更新戦略(Update Strategies)
RollingUpdate
StatefulSetのPodを自動的に更新する。デフォルトはこの RollingUpdate が使用される。
StatefulSetのローリングアップデートは停止処理と同様で序数が大きいPodから順位1つずつ更新が行われる。
パーティションについて
RollingUpdate で自動的に更新する際に updateStrategy.partition を指定すると、指定した数値以上のPodのみを対象として更新が行われる。
以下のように指定する。
|
|
OnDelete
OnDelete は古い動作の設定だ。この値を指定すると、StatefulSetのPodは自動的に更新されない。
更新するには手動でPodを削除する。するとStatefulSetが自動的に新しいアプリケーションのPodを作成する。
StatefulSetのフィールドについて
StatefulSetのフィールドについて見ていこう。しかし、殆どのフィールドがDeplyomentと同じ内容なので簡単に解説する。
StatefulSet特有のフィールド
podManagementPolicy
Podの管理ポリシーを指定する。 詳細はこちら。 OrderedReady か Parallel を指定する。デフォルトは OrderedReady だ。
serviceName
StatefulSetのPodを対象としているServiceの名前を指定する。このフィールドで指定されるServiceはStatefulSetが作成されるよりも先に作成される必要がある。
updateStrategy
StatefulSetの更新戦略を指定する。詳細はこちら。
updateStrategy.type に RollingUpdate か OnDelete を指定する。デフォルトは RollingUpdate だ。
volumeClaimTemplates
PVCのTemplateのリストを指定する。ここで指定したPVCの名前は少なくとも1つのコンテナの volumeMount で指定されている必要がある。
PVCについては Kubernetes道場 12日目 - PersistentVolume / PersistentVolumeClaim / StorageClassについて を参考にしてほしい。
Deploymentと同じフィールド
Deploymentと同じものを指定するので復習程度に見ていこう。
replicas: Podの複製数revisionHistoryLimit: リビジョンの履歴の保持数selector: 管理対象のPodを選択するLabelSelectorを指定template: Podのテンプレートを指定
StatefulSetを使用してみる
StatefulSetの作成
StatefulSetの作成の前に、StatefulSetで作成されるPodを対象とするServiceをHeadless Serviceとして作成しよう。
以下のようなManifestを作成した。
|
|
上記のManifestを適用しよう。
|
|
さて、それではStatefulSetを作成してみよう。
|
|
上記のManifestは、複製数3で 64MiB のPVCをPodのコンテナの /data にマウントするStatefulSetだ。
次に起動時のPodの挙動を見るため、別のターミナルで kubectl get po -w を実行しておく。
それでは先程のManifestを適用してみよう。
|
|
適用後の kubectl get po -w の表示だ。
|
|
0から順に1つずつPodが作成されていることが分かる。
また、StatefulSetの取得は statefulset か省略形の sts で行う。
|
|
StatefulSetのローリングアップデート
さて、次にローリングアップデートを確認しよう。
先程作成したStatefulSetのManifestを少し変更した。(Shellのsleepを5に変更しただけ)
|
|
先程同様、 kubectl get po -w を別で実行させつつ上記のManifestを適用してみる。
|
|
kubectl get po -w の表示を確認する。
|
|
Podの更新が序数が大きいものから順番に1つずつ更新されているのが分かる。
さて、最後にStatefulSetを削除しよう。
|
|
この時のPVとPVCを確認してみよう。
|
|
この様にStatefulSetが削除されてもPVCとPVCによって作成されたPVは削除されない。同名で同様の設定をしたStatefulSetが作成された際に再利用される。削除する際は手動で削除する必要がある。
StatefulSetはこのへんで終わりにしよう。
DaemonSet
DaemonSetの概要
DaemonSetは全て・一部のノードで指定されたPodを実行することを保証する。特徴としては以下の通りだ。
- ノードが追加されるとDaemonSetで指定されたPodが追加される
- ノードが削除されるとDaemonSetで管理されていたPodが削除される
- DaemonSet自体が削除されると対象のPodが削除される
DaemonSetの使用例としては以下のようなものがある。
glusterdやcephのようなクラスタデーモンを実行fluentdのようなログ収集デーモンを実行NodeExpoterやdatadog-agentなどのメトリクスエージェントの実行
特定のいくつかのノードでだけでPodを実行させることも可能だが、 nodeSelector や nodeAffinity を利用する必要がある。
こちらについては後日解説するため一旦置いておこう。
DaemonSetは更新の際にはDeployment同様にローリングアップデートが可能だ。
DaemonSetのフィールドについて
DaemonSetのフィールドは殆どDeploymentのものと同じだ。一応確認しておこう。
minReadySeconds: Podが作成されてから有効とされるまでの時間を指定revisionHistoryLimit: リビジョンの履歴の保持数selector: 管理対象のPodを選択するLabelSelectorを指定template: Podのテンプレートを指定updateStrategy: 更新戦略の指定type: 戦略の種類を指定。RollingUpdateかOnDelete指定可能。デフォルトはRollingUpdaterollingUpdate: ローリングアップデートの設定を指定。typeでRollingUpdateを指定した際にだけ使用maxUnavailable: 更新中に無効になっていいPodの数を指定。絶対値か全体のPodの数の百分率で指定
DaemonSetを使用してみる
一応Minikubeの環境でDaemonSetを作成してみよう。
以下のようなManifestを用意した。
|
|
上記のManifestを適用してみる。
|
|
DaemonSetの取得は daemonset か省略形の ds を指定する。
|
|
1つのPodが作成されていることが分かる。
ここで複数Nodeのクラスタの場合、そのNode数分だけのPodが各Nodeに1つずつ作成される。
しかし、今回はMinikubeで作成したローカル環境なのでNode数が1となっている。そのため1つのPodしか作成されない。
もし余裕がある方はマネージドサービスなどのクラスタで複数Nodeに展開されるのを確認してみると良いだろう。
というわけで今回はここまで。
次回はJob / CronJobについて見ていこう。
それでは。
