ウェビナーシリーズ:Kubernetesでのステートフルサービスのデプロイ

提供:Dev Guides
移動先:案内検索

この記事は、クラウドでのコンテナー化されたワークロードのデプロイと管理に関するウェビナーシリーズを補足するものです。 このシリーズでは、コンテナライフサイクルの管理、マルチコンテナアプリケーションのデプロイ、ワークロードのスケーリング、Kubernetesの操作など、コンテナの基本事項について説明します。 また、ステートフルアプリケーションを実行するためのベストプラクティスについても説明します。

このチュートリアルには、シリーズの5番目のセッションであるKubernetesでのステートフルサービスのデプロイの概念とコマンドが含まれています。


YouTubeビデオを見る

###序章

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アプリケーションは、NodePort31201webサービスから利用できます。

いずれかのワーカーノードでこのポートにアクセスすると、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にアクセスする方法も学びました。