ウェビナーシリーズ:Kubernetesでのステートフルサービスのデプロイ
この記事は、クラウドでのコンテナー化されたワークロードのデプロイと管理に関するウェビナーシリーズを補足するものです。 このシリーズでは、コンテナライフサイクルの管理、マルチコンテナアプリケーションのデプロイ、ワークロードのスケーリング、Kubernetesの操作など、コンテナの基本事項について説明します。 また、ステートフルアプリケーションを実行するためのベストプラクティスについても説明します。
このチュートリアルには、シリーズの5番目のセッションであるKubernetesでのステートフルサービスのデプロイの概念とコマンドが含まれています。
###序章
Kubernetes は、コンテナー化されたアプリケーションを管理するためのオープンソースのコンテナーオーケストレーションツールです。 このシリーズの前のパートでは、Kubernetesのビルディングブロックとパッケージ化されたコンテナをKubernetesReplicaSetsとして学習しました。 ReplicaSetはステートレスポッドの可用性を保証しますが、データベースクラスターなどのステートフルワークロードでは使用できません。
Kubernetesで最新のクラウドネイティブアプリケーションをパッケージ化、デプロイ、管理、スケーリングするのは簡単かもしれませんが、コンテナ化された環境でデータベースやコンテンツ管理システムなどの従来のワークロードをデプロイおよび管理するには、別のアプローチが必要です。 StatefulSets は、KubernetesReplicaSetの柔軟性をステートフルワークロードにもたらします。
このチュートリアルシリーズの最終回では、Kubernetesの人気のあるオープンソースパッケージマネージャーである Helm を使用して、高可用性のMongoDBReplicaSetをStatefulSetとしてKubernetesにデプロイします。
前提条件
このチュートリアルを完了するには、次のものが必要です。
- StackPointCloud を介してインストールされた、DigitalOceanで実行されているアクティブなKubernetesクラスター。これは、チュートリアル Getting Started withKubernetesに従って実行できます。
- チュートリアルKubernetesでのマイクロサービスのデプロイとスケーリングで紹介されたサンプルWebアプリケーションは、Node.jsとMongoDBに基づいており、データベースに高可用性をもたらすように拡張されています。 アプリケーション設計の詳細については、コンテナ化されたアプリケーションの構築チュートリアルを参照してください。
- アプリケーションのDockerイメージを保存するためのアクティブなDockerHubアカウント。
- Gitがインストールされているローカルマシン macOSを使用している場合は、Homebrewがインストールされていることを確認してください。
ステップ1-開発マシンへのHelmクライアントのインストール
Helmを使用すると、管理者は1つのコマンドで複雑なKubernetesアプリケーションをデプロイできます。 アプリケーションは、Kubernetesアプリケーションを定義、インストール、アップグレードするChartsとしてパッケージ化されています。 グラフは、ポッド、デプロイ、サービスなどのKubernetesオブジェクトを抽象化したものです。
Helmには、サーバーとクライアントの2つのコンポーネントがあります。 Helmのサーバー側は、Tillerと呼ばれるサービスとしてKubernetesで実行されます。 クライアントは、Tillerと対話するコマンドラインツールです。
MongoDB ReplicaSet Helm Chartをデプロイするため、Helmのサーバー側コンポーネントであるTillerと通信するCLIが必要です。 DigitalOceanでKubernetesをセットアップするために使用したStackPointCloudには、Tillerがプリインストールされています。
注:これらの手順はmacOS用です。 他のオペレーティングシステムを使用している場合は、ヘルムインストールガイドを参照してください。
MacにHomebrewがインストールおよび構成されていると仮定して、次のコマンドを実行してHelmをインストールします。
brew install kubernetes-helm
Output==> Downloading https://homebrew.bintray.com/bottles/kubernetes-helm-2.8.2.high_sierra.bottle.tar.gz ... ==> Summary 🍺 /usr/local/Cellar/kubernetes-helm/2.8.2: 50 files, 121.7MB
Helmをインストールしたら、現在のバージョンを確認して、Helmを実行できることを確認します。
helm version
OutputClient: &version.Version{SemVer:"v2.7.2", GitCommit:"8478fb4fc723885b155c924d1c8c410b7a9444e6", GitTreeState:"clean"} Server: &version.Version{SemVer:"v2.8.2", GitCommit:"a80231648a1473929271764b920a8e346f6de844", GitTreeState:"clean"}
これにより、クライアントが正しくインストールされ、Tillerと通信できることが確認されます。
次のステップでは、Helmを使用してMongoDBReplicaSetをKubernetesにデプロイします。
ステップ2–KubernetesにMongoDBReplicaSetをデプロイする
KubernetesのStorageClassは、管理者が提供するストレージの「クラス」を説明する方法を提供します。 たとえば、ユーザーがストレージボリュームを要求すると、StorageClassは、ユーザーからプロビジョニングされるストレージバックエンドのクラスを決定します。 クラスには、標準のHDDとより高速なSSDが含まれる場合があります。 舞台裏では、StorageClassはクラウドプロバイダーのAPIなどの基盤となるインフラストラクチャと対話して、ストレージをプロビジョニングします。
MongoDBデータを保存するには永続ストレージが必要なため、DigitalOceanブロックストレージボリュームをワーカーノードに接続し、永続性のためにストレージボリュームを使用するようにMongoDBポッドを指定することをお勧めします。
この場合、StorageClassはポッドとDigitalOceanブロックストレージサービス間のインターフェイスとして機能します。 ブロックストレージのボリュームを要求すると、StorageClassは、ブロックストレージボリュームの割り当て方法を知っている事前構成されたドライバーと通信します。
StackPointCloudは、DigitalOceanストレージドライバーをインストールし、セットアップ中にStorageClassをKubernetesに登録します。 これにより、ドライバーとStorageClassのインストールと構成に関連する手順を省くことができます。
MongoDBクラスターをデプロイする前に、DigitalOceanボリュームのStorageClassが構成されていることを確認しましょう。
kubectl get storageclass
出力は、StorageClassが構成されて準備ができていることを確認します。
[secondary_label Output NAME PROVISIONER AGE digitalocean (default) digitalocean/flex-volume-provisioner 1d
次に、DigitalOceanStorageClassに基づいてMongoDBReplicaSetを構成してデプロイします。
プロジェクトの新しいディレクトリを作成し、新しいディレクトリに切り替えます。
mkdir ~/mongo-rs cd ~/mongo-rs
GitHubからHelmChartリポジトリのクローンを作成します。
git clone https://github.com/kubernetes/charts.git
MongoDB ReplicaSetディレクトリ(charts/stable/mongodb-replicaset/
)に移動し、ファイルvalues.yaml
が存在することを確認します。
cd charts/stable/mongodb-replicaset/ ls values.yaml
Outputvalues.yaml
このファイルには、チャートのパラメーターと構成が含まれています。 DigitalOceanStorageClassを使用するようにMongoDBReplicaSetを構成するには、このファイルを変更する必要があります。
values.yaml
を編集します:
nano values.yaml
次のセクションを見つけてコメントを外します。
values.yaml
... # storageClass: "-" ...
次のように、"-"
を"digitalocean"
に置き換えます。
values.yaml
... storageClass: "digitalocean" ...
ファイルを保存して、エディターを終了します。
次に、~/mongo-rs
フォルダーに移動します。
cd ~/mongo-rs
これで、DigitalOceanのブロックストレージを利用して、MongoDBReplicaSetをKubernetesクラスターにデプロイする準備が整いました。 次のコマンドを実行して、データベースクラスターを起動します。
helm install --name=todo -f charts/stable/mongodb-replicaset/values.yaml stable/mongodb-replicaset
上記のコマンドで、--name
はヘルムチャートの名前を指します。 スイッチ-f
は、values.yaml
に保存されている構成設定を指します。
チャートの作成が開始されたことを確認する出力がすぐに表示されます。
OutputNAME: todo LAST DEPLOYED: Sat Mar 31 10:37:06 2018 NAMESPACE: default STATUS: DEPLOYED RESOURCES: ==> v1/Service NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE todo-mongodb-replicaset ClusterIP None <none> 27017/TCP 1s ==> v1beta1/StatefulSet NAME DESIRED CURRENT AGE todo-mongodb-replicaset 3 1 0s ==> v1/Pod(related) NAME READY STATUS RESTARTS AGE todo-mongodb-replicaset-0 0/1 Init:0/2 0 0s ==> v1/ConfigMap NAME DATA AGE todo-mongodb-replicaset 1 1s todo-mongodb-replicaset-tests 1 1s NOTES: 1. After the statefulset is created completely, one can check which instance is primary by running: $ for ((i = 0; i < 3; ++i)); do kubectl exec --namespace default todo-mongodb-replicaset-$i -- sh -c 'mongo --eval="printjson(rs.isMaster())"'; done 2. One can insert a key into the primary instance of the mongodb replica set by running the following: MASTER_POD_NAME must be replaced with the name of the master found from the previous step. $ kubectl exec --namespace default MASTER_POD_NAME -- mongo --eval="printjson(db.test.insert({key1: 'value1'}))" 3. One can fetch the keys stored in the primary or any of the slave nodes in the following manner. POD_NAME must be replaced by the name of the pod being queried. $ kubectl exec --namespace default POD_NAME -- mongo --eval="rs.slaveOk(); db.test.find().forEach(printjson)"
次に、一連のコマンドを実行して、クラスターのステータスを追跡しましょう。
まず、StatefulSetを見てください。
kubectl get statefulset
このコマンドは、MongoDBReplicaSetがKubernetesStatefulSetとして作成されたことを確認します。
OutputNAME DESIRED CURRENT AGE todo-mongodb-replicaset 3 2 2m
次に、ポッドを探索します。
kubectl get pods
ポッドの数とその命名規則は、MongoDBReplicaSetが正常に構成されていることを示しています。
OutputNAME READY STATUS RESTARTS AGE todo-mongodb-replicaset-0 1/1 Running 0 3m todo-mongodb-replicaset-1 1/1 Running 0 1m todo-mongodb-replicaset-2 1/1 Running 0 54s
各ポッドには、StatefulSetの特徴的な機能である連番で終わる接尾辞があることに注意してください。
次に、MongoDBインスタンスが相互に通信しているかどうかを確認しましょう。 これを行うには、ポッドの1つにあるMongoDBシェルでコマンドを実行します。
kubectl
を使用して、ホストの1つでmongo
コンソールを起動します。
kubectl exec -it todo-mongodb-replicaset-0 mongo
接続すると、MongoDBシェルが表示されます。
OutputMongoDB shell version v3.6.3 connecting to: mongodb://127.0.0.1:27017 MongoDB server version: 3.6.3 Welcome to the MongoDB shell. For interactive help, type "help". ... 2018-03-31T05:08:20.239+0000 I CONTROL [initandlisten]
次のコマンドを使用して、ReplicaSetの構成を確認します。
rs.conf()
出力は、ReplicaSetとして実行されているMongoDBの3つのインスタンスがあることを確認します。
Output{ "_id" : "rs0", "version" : 3, "protocolVersion" : NumberLong(1), "members" : [ { "_id" : 0, "host" : "todo-mongodb-replicaset-0.todo-mongodb-replicaset.default.svc.cluster.local:27017", "arbiterOnly" : false, "buildIndexes" : true, "hidden" : false, "priority" : 1, "tags" : { }, "slaveDelay" : NumberLong(0), "votes" : 1 }, { "_id" : 1, "host" : "todo-mongodb-replicaset-1.todo-mongodb-replicaset.default.svc.cluster.local:27017", "arbiterOnly" : false, "buildIndexes" : true, "hidden" : false, "priority" : 1, "tags" : { }, "slaveDelay" : NumberLong(0), "votes" : 1 }, { "_id" : 2, "host" : "todo-mongodb-replicaset-2.todo-mongodb-replicaset.default.svc.cluster.local:27017", "arbiterOnly" : false, "buildIndexes" : true, "hidden" : false, "priority" : 1, "tags" : { }, "slaveDelay" : NumberLong(0), "votes" : 1 } ], "settings" : { "chainingAllowed" : true, "heartbeatIntervalMillis" : 2000, "heartbeatTimeoutSecs" : 10, "electionTimeoutMillis" : 10000, "catchUpTimeoutMillis" : -1, "catchUpTakeoverDelayMillis" : 30000, "getLastErrorModes" : { }, "getLastErrorDefaults" : { "w" : 1, "wtimeout" : 0 }, "replicaSetId" : ObjectId("5abdb4f61d952afc4b0b8218") } }
MongoDBコンソールを終了します。
exit
これにより、リモートホストからも切断されます。
ギアを切り替えて、DigitalOceanコントロールパネルでクラスターに関連付けられているブロックストレージボリュームを確認しましょう。 DigitalOceanアカウントにログインし、Volumesタブを選択します。
それぞれ10GBの3つのボリュームがKubernetesワーカーノードに接続されていることがわかります。 MongoDB StatefulSetの各ポッドは、ブロックストレージボリュームの1つにデータを保存しています。 10GBのサイズは、persistentVolume
セクションのvalues.yaml
で定義されています。
values.yaml
persistentVolume: enabled: true ## mongodb-replicaset data Persistent Volume Storage Class ## If defined, storageClassName: <storageClass> ## If set to "-", storageClassName: "", which disables dynamic provisioning ## If undefined (the default) or set to null, no storageClassName spec is ## set, choosing the default provisioner. (gp2 on AWS, standard on ## GKE, AWS & OpenStack) ## storageClass: digitalocean accessModes: - ReadWriteOnce size: 10Gi annotations: {}
これで、Kubernetesで実行される可用性の高いMongoDBReplicaSetが正常に構成されました。
次に、MongoDBクラスターと通信するWebアプリケーションをデプロイしましょう。
ステップ3–KubernetesでのWebアプリケーションのデプロイとスケーリング
このチュートリアルシリーズの前の部分で使用したToDoNode.jsアプリケーションを拡張して、MongoDBクラスターを利用してみましょう。
注:ソースコードからコンテナイメージをビルドしたり、KubernetesファイルのYAMLファイルを直接使用したりすることもできます。 イメージをビルドしてアプリケーションをKubernetesにデプロイする手順については、チュートリアルKubernetesでのマイクロサービスのデプロイとスケーリングを参照してください。
新しい作業ディレクトリを作成することから始めます。
mkdir ~/web-app cd ~/web-app
次に、コードとKubernetesアーティファクトを含むToDoアプリケーションのリポジトリのクローンを作成します。
git clone https://github.com/janakiramm/todo.git
Kubernetes構成ファイルが含まれているtodo-app/kubernetes
ディレクトリに切り替えます。
cd todo-app/kubernetes
エディターでファイルweb-rs-ss.yaml
を開きます。
nano web-rs-ss.yaml
YAMLファイルのenv
セクションに注目してください。
web-rs-ss.yaml
containers: - name: web image: janakiramm/todo env: - name: "DBHOST" value: "mongodb://todo-mongodb-replicaset-0.todo-mongodb-replicaset,todo-mongodb-replicaset-1.todo-mongodb-replicaset,todo-mongodb-replicaset-2.todo-mongodb-replicaset:27017" ports: - containerPort: 3000
これにより、データベース接続文字列が実行時に環境変数としてアプリケーションに渡されます。 このバージョンのアプリは、アプリケーションを単純なMongoDBポッドにポイントする代わりに、作成したStatefulSetを使用します。 value
セクションの各エントリは、MongoDBStatefulSetのポッドの1つを参照します。
kubectl
を使用して、web
レプリカセットをweb
サービスと一緒にデプロイします
kubectl create -f web-rs-ss.yaml -f web-service.yaml
両方が作成されていることがわかります。
Outputreplicaset "web" created service "web" created
ポッドを再度リストします。
kubectl get pods
これで、MongoDBとWebアプリに属するすべてのポッドが表示されます。
OutputNAME READY STATUS RESTARTS AGE todo-mongodb-replicaset-0 1/1 Running 0 26m todo-mongodb-replicaset-1 1/1 Running 0 24m todo-mongodb-replicaset-2 1/1 Running 0 23m web-t5zzk 1/1 Running 0 17s web-x6dh8 1/1 Running 0 17s Let’s check out the Kubernetes services ```command kubectl get svc
OutputNAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE kubernetes ClusterIP 10.3.0.1 <none> 443/TCP 1d todo-mongodb-replicaset ClusterIP None <none> 27017/TCP 27m web NodePort 10.3.0.167 <none> 3000:31201/TCP 14s
web
ポッドは、todo-mongodb-replicaset
サービスを介してMongoDBクラスターと通信します。 Webアプリケーションは、NodePort31201
のweb
サービスから利用できます。
いずれかのワーカーノードでこのポートにアクセスすると、Webアプリケーションが表示されます。
ReplicaSet内のポッドの数を増やすことで、Webアプリケーションをスケーリングできます。
kubectl scale rs/web --replicas=10
Outputreplicaset "web" scaled
その後、アプリケーションを2つのポッドにスケールバックできます。
kubectl scale rs/web --replicas=2
Outputreplicaset "web" scaled
それでは、可用性についていくつかのテストを実行してみましょう。
ステップ4–高可用性についてMongoDBReplicaSetをテストする
StatefulSetを実行する利点の1つは、ワークロードの高可用性です。 MongoDB StatefulSetのポッドの1つを削除して、これをテストしてみましょう。
kubectl delete pod todo-mongodb-replicaset-2
Outputpod "todo-mongodb-replicaset-2" deleted
ポッドの数を確認します。
kubectl get pods
todo-mongodb-replicaset-2
が終了していることがわかります。
OutputNAME READY STATUS RESTARTS AGE todo-mongodb-replicaset-0 1/1 Running 0 33m todo-mongodb-replicaset-1 1/1 Running 0 32m todo-mongodb-replicaset-2 0/1 Terminating 0 31m web-t5zzk 1/1 Running 0 8m web-x6dh8 1/1 Running 0 8m
数分以内に、Kubernetesが別のポッドを初期化して削除されたポッドを置き換えることがわかります。
kubectl get pods
todo-mongodb-replicaset-2
が初期化されていることがわかります。
NAME READY STATUS RESTARTS AGE todo-mongodb-replicaset-0 1/1 Running 0 34m todo-mongodb-replicaset-1 1/1 Running 0 33m todo-mongodb-replicaset-2 0/1 Init:0/2 0 29s web-t5zzk 1/1 Running 0 8m web-x6dh8 1/1 Running 0 8m
すべてが機能することがわかったので、物事をクリーンアップできます。
次のコマンドを使用して、このチュートリアル中に作成されたすべてのオブジェクトを削除します。
helm delete --purge todo
kubectl delete -f web-rs-ss.yaml -f web-service.yaml
Outputreplicaset "web" deleted service "web" deleted
Kubernetesクラスタ自体を削除するには、StackPointCloudにアクセスし、コントロールパネルから削除します。
結論
このチュートリアルでは、耐久性があり、永続的で、可用性の高いMonogDBReplicaSetをKubernetesStatefulSetとしてデプロイしました。 また、同じKubernetesクラスターにデプロイされた他のアプリケーションからStatefulSetにアクセスする方法も学びました。