StatefulSets
Deploymentと同様に、StatefulSetsは同一のコンテナスペックに基づいたPodを管理します。Deploymentとは異なり、StatefulSetは各Podに固有のIDを維持します。これらのPodは同じ仕様から作成されますが、互換性がなく、それぞれが再スケジューリングイベントの間も維持される永続的な識別子を持っています。
ワークロードに永続性を提供するためにストレージボリュームを使用したい場合は、StatefulSetをソリューションの一部として使用できます。StatefulSetの個々のPodは障害の影響を受けやすいですが、永続的なPod識別子があることで、障害が発生したPodを置き換える新しいPodに既存のボリュームをマッチさせることが容易になります。
StatefulSetは、以下のうち1つ以上を必要とするアプリケーションに価値があります:
- 安定した一意のネットワーク識別子
- 安定した永続的なストレージ
- 順序付けられた優雅なデプロイメントとスケーリング
- 順序付けられた自動ローリングアップデート
私たちのEコマースアプリケーションでは、Catalogマイクロサービスの一部としてすでにStatefulSetがデプロイされています。CatalogマイクロサービスはEKS上で実行されているMySQLデータベースを利用しています。データベースは永続的なストレージを必要とするため、StatefulSetの使用例として最適です。MySQLデータベースPodを分析して、現在のボリューム構成を確認してみましょう:
Name: catalog-mysql
Namespace: catalog
[...]
Containers:
mysql:
Image: public.ecr.aws/docker/library/mysql:8.0
Port: 3306/TCP
Host Port: 0/TCP
Environment:
MYSQL_ROOT_PASSWORD: my-secret-pw
MYSQL_USER: <set to the key 'username' in secret 'catalog-db'> Optional: false
MYSQL_PASSWORD: <set to the key 'password' in secret 'catalog-db'> Optional: false
MYSQL_DATABASE: <set to the key 'name' in secret 'catalog-db'> Optional: false
Mounts:
/var/lib/mysql from data (rw)
Volumes:
data:
Type: EmptyDir (a temporary directory that shares a pod's lifetime)
Medium:
SizeLimit: <unset>
Volume Claims: <none>
[...]
StatefulSetのVolumesセクションを見ると、「Podのライ フタイムを共有する」EmptyDirボリュームタイプのみを使用していることがわかります。

emptyDirボリュームは、Podがノードに割り当てられたときに最初に作成され、そのPodがそのノードで実行されている限り存在します。名前が示すように、emptyDirボリュームは最初は空です。Podのすべてのコンテナは、同じemptyDirボリュームの同じファイルを読み書きできますが、そのボリュームは各コンテナで同じまたは異なるパスにマウントできます。**Podが何らかの理由でノードから削除されると、emptyDirのデータは永久に削除されます。**したがって、EmptyDirは私たちのMySQLデータベースには適していません。
これを実証するために、MySQLコンテナ内でシェルセッションを開始してテストファイルを作成してみましょう。その後、StatefulSetで実行されているPodを削除します。Podが永続ボリューム(PV)ではなくemptyDirを使用しているため、ファイルはPodの再起動後に残りません。まず、MySQLコンテナ内でemptyDir /var/lib/mysqlパス(MySQLがデータベースファイルを保存する場所)にファイルを作成するコマンドを実行しましょう:
次に、test.txtファイルが/var/lib/mysqlディレクトリに作成されたことを確認しましょう:
-rw-r--r-- 1 root root 4 Oct 18 13:38 test.txt
ここで、現在のcatalog-mysql Podを削除します。これによってStatefulSetコントローラーが自動的に新しいcatalog-mysql Podを再作成します:
pod "catalog-mysql-0" deleted
数秒待ってから、以下のコマンドを実行してcatalog-mysql Podが再作成されたことを確認しましょう:
pod/catalog-mysql-0 condition met
NAME READY STATUS RESTARTS AGE
catalog-mysql-0 1/1 Running 0 29s
最後に、MySQLコンテナのシェルに戻り、/var/lib/mysqlパスでlsコマンドを実行して、以前作成したtest.txtファイルを探しましょう:
cat: /var/lib/mysql/test.txt: No such file or directory
command terminated with exit code 1
ご覧のとおり、emptyDirボリュームは一時的なものであるため、test.txtファイルはもう存在しません。今後のセクションでは、同じ実験を行い、永続ボリューム(PV)がtest.txtファイルを保持し、Podの再起動や障害を乗り越えて存続することを実証します。
次のページでは、KubernetesのストレージとAWSクラウドエコシステムとの統合に関する主要な概念について理解を深めます。