Helmを使用してKubernetesでMongoDBを使用してNode.jsアプリケーションをスケーリングする方法

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

序章

Kubernetes は、最新のコンテナ化されたアプリケーションを大規模に実行するためのシステムです。 これにより、開発者はマシンのクラスター全体にアプリケーションを展開および管理できます。 また、単一インスタンスのアプリケーションセットアップで効率と信頼性を向上させるために使用できますが、Kubernetesは、マシンのグループ間でアプリケーションの複数のインスタンスを実行するように設計されています。

Kubernetesを使用してマルチサービスデプロイメントを作成する場合、多くの開発者はHelmパッケージマネージャーを使用することを選択します。 Helmは、これらのオブジェクトの相互作用を調整するチャートとテンプレートを提供することにより、複数のKubernetesリソースを作成するプロセスを合理化します。 また、人気のあるオープンソースプロジェクト用にパッケージ化されたチャートも提供しています。

このチュートリアルでは、Helmチャートを使用して、MongoDBデータベースを備えたNode.jsアプリケーションをKubernetesクラスターにデプロイします。 公式HelmMongoDBレプリカセットチャートを使用して、3つのポッドヘッドレスサービス、および3つのStatefulSetオブジェクトを作成します。 PersistentVolumeClaims。 また、カスタムアプリケーションイメージを使用してマルチレプリカNode.jsアプリケーションをデプロイするためのグラフを作成します。 このチュートリアルで構築するセットアップは、 Docker Compose を使用したNode.jsアプリケーションのコンテナー化で説明されているコードの機能を反映し、MongoDBを使用して復元力のあるNode.jsアプリケーションを構築するための良い出発点になります。ニーズに合わせて拡張できるデータストア。

前提条件

このチュートリアルを完了するには、次のものが必要です。

  • ロールベースのアクセス制御(RBAC)が有効になっているKubernetes1.10+クラスター。 このセットアップではDigitalOceanKubernetesクラスターを使用しますが、別の方法を使用してクラスターを自由に作成できます。
  • kubectlコマンドラインツールがローカルマシンまたは開発サーバーにインストールされ、クラスターに接続するように構成されています。 kubectlのインストールの詳細については、公式ドキュメントを参照してください。
  • Helm Package Manager を使用してKubernetesクラスターにソフトウェアをインストールする方法の手順1と2に概説されている手順に従って、ローカルマシンまたは開発サーバーにHelmをインストールし、クラスターにTillerをインストールします。
  • Dockerがローカルマシンまたは開発サーバーにインストールされています。 Ubuntu 18.04を使用している場合は、 Ubuntu18.04にDockerをインストールして使用する方法の手順1と2に従ってください。 それ以外の場合は、他のオペレーティングシステムへのインストールについて、公式ドキュメントに従ってください。 リンクされたチュートリアルのステップ2で説明されているように、root以外のユーザーをdockerグループに必ず追加してください。
  • DockerHubアカウント。 これを設定する方法の概要については、DockerHubのこの紹介を参照してください。

ステップ1—アプリケーションのクローン作成とパッケージ化

アプリケーションをKubernetesで使用するには、kubeletエージェントがイメージをプルできるようにアプリケーションをパッケージ化する必要があります。 ただし、アプリケーションをパッケージ化する前に、アプリケーションコードのMongoDB接続URIを変更して、Helmmongodb-replicasetチャート。

最初のステップは、 DigitalOceanCommunityGitHubアカウントからnode-mongo-docker-devリポジトリのクローンを作成することです。 このリポジトリには、DockerComposeを使用した開発用のNode.jsアプリケーションのコンテナ化で説明されているセットアップのコードが含まれています。 DockerCompose。 アプリケーション自体の詳細については、Node.jsを使用したコンテナーからKubernetesへのシリーズを参照してください。

リポジトリをnode_projectというディレクトリに複製します。

git clone https://github.com/do-community/node-mongo-docker-dev.git node_project

node_projectディレクトリに移動します。

cd node_project

node_projectディレクトリには、ユーザー入力で動作するサメ情報アプリケーションのファイルとディレクトリが含まれています。 コンテナーで動作するように最新化されました。機密性の高い特定の構成情報がアプリケーションコードから削除され、実行時に注入されるようにリファクタリングされ、アプリケーションの状態がMongoDBデータベースにオフロードされました。

最新のコンテナ化されたアプリケーションの設計の詳細については、Kubernetes用アプリケーションのアーキテクチャおよびKubernetes用アプリケーションの最新化を参照してください。

Helm mongodb-replicasetチャートを展開すると、次のようになります。

  • 3つのポッドを持つStatefulSetオブジェクト—MongoDBレプリカセットのメンバー。 各ポッドには、関連付けられたPersistentVolumeClaimがあり、スケジュールが変更された場合でも固定IDを維持します。
  • StatefulSetのポッドで構成されるMongoDBレプリカセット。 セットには、1つのプライマリと2つのセカンダリが含まれます。 データはプライマリからセカンダリに複製され、アプリケーションデータの高可用性を維持します。

アプリケーションがデータベースレプリカと対話するには、コード内のMongoDB接続URIに、レプリカセットメンバーのホスト名とレプリカセット自体の名前の両方を含める必要があります。 したがって、これらの値をURIに含める必要があります。

データベース接続情報を指定するクローンリポジトリ内のファイルは、db.jsと呼ばれます。 nanoまたはお気に入りのエディターを使用して、そのファイルを今すぐ開きます。

nano db.js

現在、ファイルには、実行時にデータベース接続URIで参照される定数が含まれています。 これらの定数の値は、ノードの process.env プロパティを使用して挿入されます。このプロパティは、実行時にユーザー環境に関する情報を含むオブジェクトを返します。 アプリケーションコードで動的に値を設定すると、動的なステートレス環境で必要な、基盤となるインフラストラクチャからコードを切り離すことができます。 この方法でのアプリケーションコードのリファクタリングの詳細については、DockerComposeを使用した開発用のNode.jsアプリケーションのコンテナ化ステップ2および12ファクターの関連する説明を参照してください。 App

接続URIとURI文字列自体の定数は、現在次のようになっています。

〜/ node_project / db.js

...
const {
  MONGO_USERNAME,
  MONGO_PASSWORD,
  MONGO_HOSTNAME,
  MONGO_PORT,
  MONGO_DB
} = process.env;

...

const url = `mongodb://${MONGO_USERNAME}:${MONGO_PASSWORD}@${MONGO_HOSTNAME}:${MONGO_PORT}/${MONGO_DB}?authSource=admin`;
...

12FAのアプローチに従い、レプリカインスタンスのホスト名またはレプリカセット名をこのURI文字列にハードコーディングする必要はありません。 既存のMONGO_HOSTNAME定数を拡張して、複数のホスト名(レプリカセットのメンバー)を含めることができるため、そのままにしておきます。 ただし、URI文字列のオプションセクションにレプリカセット定数を追加する必要があります。

MONGO_REPLICASETをURI定数オブジェクトと接続文字列の両方に追加します。

〜/ node_project / db.js

...
const {
  MONGO_USERNAME,
  MONGO_PASSWORD,
  MONGO_HOSTNAME,
  MONGO_PORT,
  MONGO_DB,
  MONGO_REPLICASET
} = process.env;

...
const url = `mongodb://${MONGO_USERNAME}:${MONGO_PASSWORD}@${MONGO_HOSTNAME}:${MONGO_PORT}/${MONGO_DB}?replicaSet=${MONGO_REPLICASET}&authSource=admin`;
...

URIのオプションセクションでreplicaSetオプションを使用すると、レプリカセットの名前を渡すことができます。これにより、MONGO_HOSTNAME定数で定義されたホスト名とともに、次のことが可能になります。セットメンバーに接続します。

編集が終了したら、ファイルを保存して閉じます。

レプリカセットで機能するようにデータベース接続情報を変更すると、アプリケーションをパッケージ化し、 docker build コマンドを使用してイメージをビルドし、DockerHubにプッシュできるようになります。

docker build-tフラグを使用してイメージを作成します。これにより、イメージに覚えやすい名前を付けることができます。 この場合、イメージにDocker Hubユーザー名のタグを付け、node-replicasまたは自分で選択した名前を付けます。

docker build -t your_dockerhub_username/node-replicas .

コマンドの.は、ビルドコンテキストが現在のディレクトリであることを指定します。

イメージの作成には1〜2分かかります。 完了したら、画像を確認します。

docker images

次の出力が表示されます。

OutputREPOSITORY                              TAG                 IMAGE ID            CREATED             SIZE
your_dockerhub_username/node-replicas   latest              56a69b4bc882        7 seconds ago       90.1MB
node                                    10-alpine           aa57b0242b33        6 days ago          71MB

次に、前提条件で作成したDockerHubアカウントにログインします。

docker login -u your_dockerhub_username 

プロンプトが表示されたら、DockerHubアカウントのパスワードを入力します。 この方法でログインすると、ルート以外のユーザーのホームディレクトリにDockerHubの資格情報を使用して~/.docker/config.jsonファイルが作成されます。

dockerpushコマンドを使用してアプリケーションイメージをDockerHubにプッシュします。 your_dockerhub_usernameを独自のDockerHubユーザー名に置き換えることを忘れないでください。

docker push your_dockerhub_username/node-replicas

これで、Kubernetesでレプリケートされたアプリケーションを実行するためにプルできるアプリケーションイメージができました。 次のステップは、MongoDBHelmチャートで使用する特定のパラメーターを構成することです。

ステップ2—MongoDBレプリカセットのシークレットを作成する

stable/mongodb-replicasetチャートは、シークレットの使用に関してさまざまなオプションを提供します。チャートの展開で使用する2つを作成します。

  • レプリカセットキーファイルのシークレット。レプリカセットメンバー間で共有パスワードとして機能し、他のメンバーを認証できるようにします。
  • adminデータベースにrootユーザーとして作成されるMongoDB管理者ユーザーの秘密。 この役割により、アプリケーションを本番環境にデプロイするときに、権限が制限された後続のユーザーを作成できます。

これらのシークレットを設定すると、専用の値ファイルに優先パラメーター値を設定し、Helmチャートを使用してStatefulSetオブジェクトとMongoDBレプリカセットを作成できるようになります。

まず、キーファイルを作成しましょう。 opensslコマンドrandオプションを使用して、キーファイルの756バイトのランダムな文字列を生成します。

openssl rand -base64 756 > key.txt

コマンドによって生成される出力は、 base64 でエンコードされ、均一なデータ送信を保証し、 mongodb-replicasetチャート認証ドキュメントに記載されているガイドラインに従って、key.txtというファイルにリダイレクトされます。キー自体は、6〜1024文字の長さで、base64セットの文字のみで構成されている必要があります。

これで、 kubectl create でこのファイルを使用して、keyfilesecretというシークレットを作成できます。

kubectl create secret generic keyfilesecret --from-file=key.txt

これにより、default namespace にシークレットオブジェクトが作成されます。これは、セットアップ用の特定の名前空間を作成していないためです。

シークレットが作成されたことを示す次の出力が表示されます。

Outputsecret/keyfilesecret created

key.txtを削除します:

rm key.txt

または、ファイルを保存する場合は、必ずアクセス許可を制限し、.gitignoreファイルに追加してバージョン管理されないようにしてください。

次に、MongoDB管理者ユーザーのシークレットを作成します。 最初のステップは、希望するユーザー名とパスワードをbase64に変換することです。

データベースのユーザー名を変換します。

echo -n 'your_database_username' | base64

出力に表示される値を書き留めます。

次に、パスワードを変換します。

echo -n 'your_database_password' | base64

ここでも出力の値に注意してください。

シークレットのファイルを開きます。

nano secret.yaml

注:Kubernetesオブジェクトは通常YAML を使用して定義されます。これはタブを厳密に禁止し、インデントに2つのスペースを必要とします。 YAMLファイルのフォーマットを確認したい場合は、 linter を使用するか、kubectl create--dry-runおよび[ X174X] フラグ:

kubectl create -f your_yaml_file.yaml --dry-run --validate=true

一般に、kubectlを使用してリソースを作成する前に、構文を検証することをお勧めします。


次のコードをファイルに追加して、作成したエンコード値でuserpasswordを定義するシークレットを作成します。 ここのダミー値は、必ず独自のエンコードされたユーザー名とパスワードに置き換えてください。

〜/ node_project / secret.yaml

apiVersion: v1
kind: Secret
metadata:
  name: mongo-secret
data:
  user: your_encoded_username
  password: your_encoded_password

ここでは、mongodb-replicasetチャートが期待するキー名userおよびpasswordを使用しています。 シークレットオブジェクトにはmongo-secretという名前を付けましたが、好きな名前を付けることができます。

編集が終了したら、ファイルを保存して閉じます。

次のコマンドを使用してSecretオブジェクトを作成します。

kubectl create -f secret.yaml

次の出力が表示されます。

Outputsecret/mongo-secret created

ここでも、secret.yamlを削除するか、そのアクセス許可を制限して.gitignoreファイルに追加することができます。

シークレットオブジェクトを作成したら、mongodb-replicasetチャートで使用するパラメーター値の指定とMongoDBデプロイメントの作成に進むことができます。

ステップ3—MongoDBヘルムチャートの構成とデプロイメントの作成

Helmには、使用するチャートmongodb-replicasetを含むstableと呼ばれるアクティブに保守されているリポジトリが付属しています。 作成したシークレットでこのチャートを使用するには、mongodb-values.yamlという構成パラメーター値を使用してファイルを作成し、このファイルを使用してチャートをインストールします。

mongodb-values.yamlファイルは、mongodb-replicasetチャートリポジトリのデフォルトのvalues.yamlファイルをほぼ反映します。 ただし、ファイルには次の変更を加えます。

  • authパラメーターをtrueに設定して、データベースインスタンスが認証を有効で開始するようにします。 これは、すべてのクライアントがデータベースのリソースと操作にアクセスするために認証する必要があることを意味します。
  • 前のステップで作成したシークレットに関する情報を追加して、チャートがこれらの値を使用してレプリカセットのキーファイルと管理者ユーザーを作成できるようにします。
  • StatefulSetの各ポッドに関連付けられているPersistentVolumeのサイズを小さくして、最小実行可能DigitalOceanブロックストレージユニット、1GBを使用しますが、ストレージ要件に合わせてこれを自由に変更できます。

ただし、mongodb-values.yamlファイルを作成する前に、まず StorageClass が作成され、ストレージリソースをプロビジョニングするように構成されていることを確認する必要があります。 データベースStatefulSet内の各ポッドには、スティッキーIDと関連する PersistentVolumeClaim があり、ポッドのPersistentVolumeを動的にプロビジョニングします。 ポッドが再スケジュールされた場合、PersistentVolumeは、ポッドがスケジュールされているノードにマウントされます(ただし、関連付けられたポッドまたはStatefulSetが完全に削除される場合は、各ボリュームを手動で削除する必要があります)。

DigitalOcean Kubernetes を使用しているため、デフォルトのStorageClassprovisionerdobs.csi.digitalocean.comDigitalOcean Block Storage —に設定されています。

kubectl get storageclass

DigitalOceanクラスターを使用している場合は、次の出力が表示されます。

OutputNAME                         PROVISIONER                 AGE
do-block-storage (default)   dobs.csi.digitalocean.com   21m

DigitalOceanクラスターを使用していない場合は、StorageClassを作成し、選択したprovisionerを構成する必要があります。 これを行う方法の詳細については、公式ドキュメントを参照してください。

StorageClassが構成されていることを確認したので、mongodb-values.yamlを開いて編集します。

nano mongodb-values.yaml

このファイルには、次のような値を設定します。

  • 承認を有効にします。
  • keyfilesecretおよびmongo-secretオブジェクトを参照します。
  • PersistentVolumesに1Giを指定します。
  • レプリカセット名をdbに設定します。
  • セットの3レプリカを指定します。
  • mongoイメージを、執筆時点で最新バージョン4.1.9に固定します。

次のコードをファイルに貼り付けます。

〜/ node_project / mongodb-values.yaml

replicas: 3
port: 27017
replicaSetName: db
podDisruptionBudget: {}
auth:
  enabled: true
  existingKeySecret: keyfilesecret
  existingAdminSecret: mongo-secret
imagePullSecrets: []
installImage:
  repository: unguiculus/mongodb-install
  tag: 0.7
  pullPolicy: Always
copyConfigImage:
  repository: busybox
  tag: 1.29.3
  pullPolicy: Always
image:
  repository: mongo
  tag: 4.1.9
  pullPolicy: Always
extraVars: {}
metrics:
  enabled: false
  image:
    repository: ssalaues/mongodb-exporter
    tag: 0.6.1
    pullPolicy: IfNotPresent
  port: 9216
  path: /metrics
  socketTimeout: 3s
  syncTimeout: 1m
  prometheusServiceDiscovery: true
  resources: {}
podAnnotations: {}
securityContext:
  enabled: true
  runAsUser: 999
  fsGroup: 999
  runAsNonRoot: true
init:
  resources: {}
  timeout: 900
resources: {}
nodeSelector: {}
affinity: {}
tolerations: []
extraLabels: {}
persistentVolume:
  enabled: true
  #storageClass: "-"
  accessModes:
    - ReadWriteOnce
  size: 1Gi
  annotations: {}
serviceAnnotations: {}
terminationGracePeriodSeconds: 30
tls:
  enabled: false
configmap: {}
readinessProbe:
  initialDelaySeconds: 5
  timeoutSeconds: 1
  failureThreshold: 3
  periodSeconds: 10
  successThreshold: 1
livenessProbe:
  initialDelaySeconds: 30
  timeoutSeconds: 5
  failureThreshold: 3
  periodSeconds: 10
  successThreshold: 1

persistentVolume.storageClassパラメーターはここでコメント化されています。コメントを削除してその値を"-"に設定すると、動的プロビジョニングが無効になります。 この場合、この値を未定義のままにしているため、チャートはデフォルトのprovisionerを選択します—この場合はdobs.csi.digitalocean.comです。

また、persistentVolumeキーに関連付けられているaccessModeにも注意してください。ReadWriteOnceは、プロビジョニングされたボリュームが単一ノードによってのみ読み取り/書き込みされることを意味します。 さまざまなアクセスモードの詳細については、ドキュメントを参照してください。

ファイルに含まれている他のパラメーターの詳細については、リポジトリに含まれている構成テーブルを参照してください。

編集が終了したら、ファイルを保存して閉じます。

mongodb-replicasetチャートを展開する前に、stableリポジトリをhelmrepoupdateコマンドで更新する必要があります。

helm repo update

これにより、stableリポジトリから最新のチャート情報が取得されます。

最後に、次のコマンドを使用してチャートをインストールします。

helm install --name mongo -f mongodb-values.yaml stable/mongodb-replicaset

注:チャートをインストールする前に、--dry-runおよび--debugオプションを指定してhelm installを実行し、リリース用に生成されたマニフェストを確認できます。

helm install --name your_release_name -f your_values_file.yaml --dry-run --debug your_chart

Helmにreleasemongoという名前を付けていることに注意してください。 この名前は、指定した構成オプションを使用したチャートのこの特定の展開を示します。 -fフラグとmongodb-values.yamlファイルを含めることで、これらのオプションを示しました。

また、helm install--namespaceフラグが含まれていないため、チャートオブジェクトはdefault名前空間に作成されることに注意してください。

リリースを作成すると、作成されたオブジェクトに関する情報とそれらを操作するための手順とともに、そのステータスに関する出力が表示されます。

OutputNAME:   mongo
LAST DEPLOYED: Tue Apr 16 21:51:05 2019
NAMESPACE: default
STATUS: DEPLOYED

RESOURCES:
==> v1/ConfigMap
NAME                              DATA  AGE
mongo-mongodb-replicaset-init     1     1s
mongo-mongodb-replicaset-mongodb  1     1s
mongo-mongodb-replicaset-tests    1     0s
...

これで、次のコマンドを使用してポッドの作成を確認できます。

kubectl get pods

ポッドが作成されると、次のような出力が表示されます。

OutputNAME                         READY   STATUS     RESTARTS   AGE
mongo-mongodb-replicaset-0   1/1     Running    0          67s
mongo-mongodb-replicaset-1   0/1     Init:0/3   0          8s

ここでのREADYおよびSTATUS出力は、StatefulSet内のポッドの準備が完全に整っていないことを示しています。ポッドのコンテナーに関連付けられた InitContainersはまだ実行中です。 StatefulSetメンバーは順番に作成されるため、次のポッドが作成される前に、StatefulSetの各ポッドはRunningおよびReadyである必要があります。

ポッドが作成され、関連するすべてのコンテナが実行されると、次の出力が表示されます。

OutputNAME                         READY   STATUS    RESTARTS   AGE
mongo-mongodb-replicaset-0   1/1     Running   0          2m33s
mongo-mongodb-replicaset-1   1/1     Running   0          94s
mongo-mongodb-replicaset-2   1/1     Running   0          36s

Running STATUSは、ポッドがノードにバインドされており、それらのポッドに関連付けられているコンテナーが実行されていることを示します。 READYは、ポッド内で実行されているコンテナーの数を示します。 詳細については、ポッドライフサイクルに関するドキュメントを参照してください。

注: STATUS列に予期しないフェーズが表示された場合は、次のコマンドを使用してポッドのトラブルシューティングを行うことができることに注意してください。

kubectl describe pods your_pod
kubectl logs your_pod

StatefulSet内の各ポッドには、StatefulSetの名前とポッドの序数インデックスを組み合わせた名前が付いています。 3つのレプリカを作成したため、StatefulSetメンバーには0〜2の番号が付けられ、それぞれに次の要素で構成される安定したDNSエントリがあります:$(statefulset-name)-$(ordinal).$(service name).$(namespace).svc.cluster.local

この場合、mongodb-replicasetチャートによって作成されたStatefulSetとHeadlessServiceの名前は同じです。

kubectl get statefulset
OutputNAME                       READY   AGE
mongo-mongodb-replicaset   3/3     4m2s
kubectl get svc
OutputNAME                              TYPE        CLUSTER-IP   EXTERNAL-IP   PORT(S)     AGE
kubernetes                        ClusterIP   10.245.0.1   <none>        443/TCP     42m
mongo-mongodb-replicaset          ClusterIP   None         <none>        27017/TCP   4m35s
mongo-mongodb-replicaset-client   ClusterIP   None         <none>        27017/TCP   4m35s

これは、StatefulSetの最初のメンバーが次のDNSエントリを持つことを意味します。

mongo-mongodb-replicaset-0.mongo-mongodb-replicaset.default.svc.cluster.local

アプリケーションは各MongoDBインスタンスに接続する必要があるため、サービスではなくポッドと直接通信できるように、この情報を持っていることが不可欠です。 カスタムアプリケーションのヘルムチャートを作成するとき、環境変数を使用して各ポッドのDNSエントリをアプリケーションに渡します。

データベースインスタンスが稼働していると、ノードアプリケーションのグラフを作成する準備が整います。

ステップ4—カスタムアプリケーションチャートの作成とパラメーターの構成

Nodeアプリケーション用のカスタムHelmチャートを作成し、標準チャートディレクトリのデフォルトファイルを変更して、アプリケーションが作成したばかりのレプリカセットで動作できるようにします。 また、アプリケーションのConfigMapオブジェクトとSecretオブジェクトを定義するファイルも作成します。

まず、次のコマンドを使用して、nodeappという新しいチャートディレクトリを作成します。

helm create nodeapp

これにより、~/node_projectフォルダにnodeappというディレクトリが作成され、次のリソースが使用されます。

  • チャートに関する基本情報を含むChart.yamlファイル。
  • MongoDBデプロイメントで行ったように、特定のパラメーター値を設定できるvalues.yamlファイル。
  • チャートをパッケージ化するときに無視されるファイルとディレクトリのパターンを含む.helmignoreファイル。
  • Kubernetesマニフェストを生成するテンプレートファイルを含むtemplates/ディレクトリ。
  • テストファイル用のtemplates/tests/ディレクトリ。
  • このチャートが依存するチャートのcharts/ディレクトリ。

これらのデフォルトファイルから変更する最初のファイルはvalues.yamlです。 今すぐそのファイルを開きます:

nano nodeapp/values.yaml

ここで設定する値は次のとおりです。

  • レプリカの数。
  • 使用したいアプリケーションイメージ。 この場合、これはステップ1で作成したnode-replicasイメージになります。
  • ServiceType。 この場合、 LoadBalancer を指定して、テスト目的でアプリケーションへのアクセスポイントを作成します。 DigitalOcean Kubernetesクラスターを使用しているため、チャートをデプロイすると DigitalOcean LoadBalancerが作成されます。 本番環境では、入力リソースおよび入力コントローラーを使用してトラフィックをサービスにルーティングするようにグラフを構成できます。
  • targetPort は、アプリケーションが公開されるポッドのポートを指定します。

このファイルには環境変数を入力しません。 代わりに、ConfigMapオブジェクトとSecretオブジェクトのテンプレートを作成し、これらの値を~/node_project/nodeapp/templates/deployment.yamlにあるアプリケーションDeploymentマニフェストに追加します。

values.yamlファイルで次の値を構成します。

〜/ node_project / nodeapp / values.yaml

# Default values for nodeapp.
# This is a YAML-formatted file.
# Declare variables to be passed into your templates.

replicaCount: 3

image:
  repository: your_dockerhub_username/node-replicas
  tag: latest
  pullPolicy: IfNotPresent

nameOverride: ""
fullnameOverride: ""

service:
  type: LoadBalancer
  port: 80
  targetPort: 8080
...

編集が終了したら、ファイルを保存して閉じます。

次に、nodeapp/templatesディレクトリにあるsecret.yamlファイルを開きます。

nano nodeapp/templates/secret.yaml

このファイルで、MONGO_USERNAMEおよびMONGO_PASSWORDアプリケーション定数の値を追加します。 これらは、データベース接続ファイルであるdb.jsで指定されているように、アプリケーションが実行時にアクセスすることを期待する定数です。 これらの定数の値を追加するときは、mongo-secretオブジェクトを作成するときにステップ2で使用したbase64-エンコードされた値を使用することを忘れないでください。 これらの値を再作成する必要がある場合は、ステップ2に戻って、関連するコマンドを再度実行できます。

次のコードをファイルに追加します。

〜/ node_project / nodeapp / templates / secret.yaml

apiVersion: v1
kind: Secret
metadata:
  name: {{ .Release.Name }}-auth
data:
  MONGO_USERNAME: your_encoded_username
  MONGO_PASSWORD: your_encoded_password

このシークレットオブジェクトの名前は、アプリケーションチャートをデプロイするときに指定するHelmリリースの名前によって異なります。

終了したら、ファイルを保存して閉じます。

次に、ファイルを開いて、アプリケーションのConfigMapを作成します。

nano nodeapp/templates/configmap.yaml

このファイルでは、アプリケーションが期待する残りの変数MONGO_HOSTNAMEMONGO_PORTMONGO_DB、およびMONGO_REPLICASETを定義します。 MONGO_HOSTNAME変数には、レプリカセット内の each インスタンスのDNSエントリが含まれます。これは、MongoDB接続URIがに必要なものだからです。

Kubernetesのドキュメントによると、アプリケーションが活性と準備のチェックを実装する場合、ポッドに接続するときにSRVレコードを使用する必要があります。 ステップ3で説明したように、ポッドSRVレコードは$(statefulset-name)-$(ordinal).$(service name).$(namespace).svc.cluster.localのパターンに従います。 MongoDB StatefulSetは活性と準備のチェックを実装しているため、MONGO_HOSTNAME変数の値を定義するときに、これらの安定した識別子を使用する必要があります。

次のコードをファイルに追加して、MONGO_HOSTNAMEMONGO_PORTMONGO_DB、およびMONGO_REPLICASET変数を定義します。 MONGO_DBデータベースには別の名前を自由に使用できますが、MONGO_HOSTNAMEおよびMONGO_REPLICASETの値は次のように記述する必要があります。

〜/ node_project / nodeapp / templates / configmap.yaml

apiVersion: v1
kind: ConfigMap
metadata:
  name: {{ .Release.Name }}-config
data:
  MONGO_HOSTNAME: "mongo-mongodb-replicaset-0.mongo-mongodb-replicaset.default.svc.cluster.local,mongo-mongodb-replicaset-1.mongo-mongodb-replicaset.default.svc.cluster.local,mongo-mongodb-replicaset-2.mongo-mongodb-replicaset.default.svc.cluster.local"  
  MONGO_PORT: "27017"
  MONGO_DB: "sharkinfo"
  MONGO_REPLICASET: "db"

StatefulSetオブジェクトとレプリカセットはすでに作成されているため、ここにリストされているホスト名は、この例に示されているとおりにファイルにリストされている必要があります。 これらのオブジェクトを破棄してMongoDBHelmリリースの名前を変更する場合は、このConfigMapに含まれる値を変更する必要があります。 MongoDBリリースでレプリカセット名を指定したため、MONGO_REPLICASETにも同じことが当てはまります。

また、ここにリストされている値は引用符で囲まれていることに注意してください。これは、Helmの環境変数の期待値です。

編集が終了したら、ファイルを保存して閉じます。

チャートパラメーター値を定義し、SecretマニフェストとConfigMapマニフェストを作成したら、アプリケーションデプロイメントテンプレートを編集して環境変数を使用できます。

ステップ5—環境変数をHelmデプロイメントに統合する

アプリケーションSecretとConfigMapのファイルを配置したら、アプリケーションDeploymentがこれらの値を使用できることを確認する必要があります。 また、展開マニフェストですでに定義されているライブネスおよび準備プローブをカスタマイズします。

編集用にアプリケーションデプロイメントテンプレートを開きます。

nano nodeapp/templates/deployment.yaml

これはYAMLファイルですが、Helmテンプレートはマニフェストを生成するために標準のKubernetesYAMLファイルとは異なる構文を使用します。 テンプレートの詳細については、ヘルムのドキュメントを参照してください。

ファイルで、最初にenvキーをアプリケーションコンテナの仕様に追加します。imagePullPolicyキーの下、portsの上にあります。

〜/ node_project / nodeapp / templates / deployment.yaml

apiVersion: apps/v1
kind: Deployment
metadata:
...
  spec:
    containers:
      - name: {{ .Chart.Name }}
        image: "{{ .Values.image.repository }}:{{ .Values.image.tag }}"
        imagePullPolicy: {{ .Values.image.pullPolicy }}
        env:
        ports:

次に、env変数のリストに次のキーを追加します。

〜/ node_project / nodeapp / templates / deployment.yaml

apiVersion: apps/v1
kind: Deployment
metadata:
...
  spec:
    containers:
      - name: {{ .Chart.Name }}
        image: "{{ .Values.image.repository }}:{{ .Values.image.tag }}"
        imagePullPolicy: {{ .Values.image.pullPolicy }}
        env:
        - name: MONGO_USERNAME
          valueFrom:
            secretKeyRef:
              key: MONGO_USERNAME
              name: {{ .Release.Name }}-auth
        - name: MONGO_PASSWORD
          valueFrom:
            secretKeyRef:
              key: MONGO_PASSWORD
              name: {{ .Release.Name }}-auth
        - name: MONGO_HOSTNAME
          valueFrom:
            configMapKeyRef:
              key: MONGO_HOSTNAME
              name: {{ .Release.Name }}-config
        - name: MONGO_PORT
          valueFrom:
            configMapKeyRef:
              key: MONGO_PORT
              name: {{ .Release.Name }}-config
        - name: MONGO_DB
          valueFrom:
            configMapKeyRef:
              key: MONGO_DB
              name: {{ .Release.Name }}-config      
        - name: MONGO_REPLICASET
          valueFrom:
            configMapKeyRef:
              key: MONGO_REPLICASET
              name: {{ .Release.Name }}-config        

各変数には、シークレット値の場合は secretKeyRef key で定義され、ConfigMap値の場合はconfigMapKeyRefで定義された値への参照が含まれます。 これらのキーは、前のステップで作成したシークレットファイルとConfigMapファイルを指します。

次に、portsキーの下で、containerPort定義を変更して、アプリケーションが公開されるコンテナーのポートを指定します。

〜/ node_project / nodeapp / templates / deployment.yaml

apiVersion: apps/v1
kind: Deployment
metadata:
...
  spec:
    containers:
    ...
      env:
    ...
      ports:
        - name: http
          containerPort: 8080
          protocol: TCP
      ...

次に、このデプロイメントマニフェストにデフォルトで含まれている活性と準備のチェックを変更しましょう。 これらのチェックにより、アプリケーションポッドが実行され、トラフィックを処理する準備ができていることが確認されます。

  • 準備プローブは、ポッドがトラフィックを処理する準備ができているかどうかを評価し、チェックが成功するまでポッドへのすべての要求を停止します。
  • 活性プローブは、基本的なアプリケーションの動作をチェックして、コンテナー内のアプリケーションが実行され、期待どおりに動作しているかどうかを判断します。 ライブネスプローブが失敗した場合、Kubernetesはコンテナを再起動します。

両方の詳細については、Kubernetes用アプリケーションのアーキテクチャ関連するディスカッションを参照してください。

この例では、Helmがデフォルトで提供する httpGet request に基づいて構築し、アプリケーションが/sharksエンドポイントでリクエストを受け入れているかどうかをテストします。 kubeletサービスは、アプリケーションポッドのコンテナで実行されているノードサーバーにGETリクエストを送信し、ポート8080でリッスンすることでプローブを実行します。 応答のステータスコードが200〜400の場合、kubeletはコンテナが正常であると判断します。 それ以外の場合、ステータスが400または500の場合、kubeletは、準備プローブの場合はコンテナーへのトラフィックを停止するか、活性プローブの場合はコンテナーを再起動します。

活気と準備のプローブについて、記載されているpathに次の変更を追加します。

〜/ node_project / nodeapp / templates / deployment.yaml

apiVersion: apps/v1
kind: Deployment
metadata:
...
  spec:
    containers:
    ...
      env:
    ...
      ports:
        - name: http
          containerPort: 8080
          protocol: TCP
      livenessProbe:
        httpGet:
          path: /sharks
          port: http
      readinessProbe:
        httpGet:
          path: /sharks
          port: http

編集が終了したら、ファイルを保存して閉じます。

これで、Helmを使用してアプリケーションリリースを作成する準備が整いました。 次のhelminstallコマンドを実行します。これには、リリースの名前とチャートディレクトリの場所が含まれます。

helm install --name nodejs ./nodeapp

ステップ3で説明したように、最初に--dry-runおよび--debug オプションを指定してhelm installを実行し、リリース用に生成されたマニフェストを確認できることを忘れないでください。

ここでも、helm install--namespaceフラグが含まれていないため、チャートオブジェクトはdefault名前空間に作成されます。

リリースが作成されたことを示す次の出力が表示されます。

OutputNAME:   nodejs
LAST DEPLOYED: Wed Apr 17 18:10:29 2019
NAMESPACE: default
STATUS: DEPLOYED

RESOURCES:
==> v1/ConfigMap
NAME           DATA  AGE
nodejs-config  4     1s

==> v1/Deployment
NAME            READY  UP-TO-DATE  AVAILABLE  AGE
nodejs-nodeapp  0/3    3           0          1s

...

この場合も、出力には、作成されたオブジェクトとそれらを操作する方法に関する情報とともに、リリースのステータスが示されます。

ポッドのステータスを確認します。

kubectl get pods
OutputNAME                              READY   STATUS    RESTARTS   AGE
mongo-mongodb-replicaset-0        1/1     Running   0          57m
mongo-mongodb-replicaset-1        1/1     Running   0          56m
mongo-mongodb-replicaset-2        1/1     Running   0          55m
nodejs-nodeapp-577df49dcc-b5fq5   1/1     Running   0          117s
nodejs-nodeapp-577df49dcc-bkk66   1/1     Running   0          117s
nodejs-nodeapp-577df49dcc-lpmt2   1/1     Running   0          117s

ポッドが稼働したら、サービスを確認します。

kubectl get svc
OutputNAME                              TYPE           CLUSTER-IP     EXTERNAL-IP       PORT(S)        AGE
kubernetes                        ClusterIP      10.245.0.1     <none>            443/TCP        96m
mongo-mongodb-replicaset          ClusterIP      None           <none>            27017/TCP      58m
mongo-mongodb-replicaset-client   ClusterIP      None           <none>            27017/TCP      58m
nodejs-nodeapp                    LoadBalancer   10.245.33.46   your_lb_ip        80:31518/TCP   3m22s

nodejs-nodeappサービスに関連付けられているEXTERNAL_IPは、クラスターの外部からアプリケーションにアクセスできるIPアドレスです。 EXTERNAL_IP列に<pending>ステータスが表示されている場合は、ロードバランサーがまだ作成中であることを意味します。

その列にIPが表示されたら、ブラウザでhttp://your_lb_ipに移動します。

次のランディングページが表示されます。

レプリケートされたアプリケーションが機能しているので、いくつかのテストデータを追加して、レプリカセットのメンバー間でレプリケーションが機能していることを確認しましょう。

ステップ6—MongoDBレプリケーションのテスト

アプリケーションが実行され、外部IPアドレスを介してアクセスできるようになったら、テストデータを追加して、MongoDBレプリカセットのメンバー間で複製されていることを確認できます。

まず、ブラウザをアプリケーションのランディングページに移動したことを確認します。

Get SharkInfoボタンをクリックします。 サメの名前とそのサメの一般的な性格の説明を入力できる入力フォームのあるページが表示されます。

フォームに、選択した最初のサメを追加します。 実例を示すために、Megalodon SharkShark Name フィールドに追加し、AncientSharkCharacterフィールドに追加します。

送信ボタンをクリックします。 このサメの情報が表示されたページが表示されます。

次に、上部のナビゲーションバーにある Sharks をクリックして、サメ情報フォームに戻ります。

お好みの新しいサメを入力してください。 Whale SharkLargeを使用します。

送信をクリックすると、新しいサメがデータベースのサメコレクションに追加されたことがわかります。

入力したデータがレプリカセットのプライマリメンバーとセカンダリメンバーの間で複製されていることを確認しましょう。

ポッドのリストを取得します。

kubectl get pods
OutputNAME                              READY   STATUS    RESTARTS   AGE
mongo-mongodb-replicaset-0        1/1     Running   0          74m
mongo-mongodb-replicaset-1        1/1     Running   0          73m
mongo-mongodb-replicaset-2        1/1     Running   0          72m
nodejs-nodeapp-577df49dcc-b5fq5   1/1     Running   0          5m4s
nodejs-nodeapp-577df49dcc-bkk66   1/1     Running   0          5m4s
nodejs-nodeapp-577df49dcc-lpmt2   1/1     Running   0          5m4s

ポッドのmongoshell にアクセスするには、kubectlexecコマンドステップ2mongo-secretを作成するために使用したユーザー名を使用できます。 ]。 次のコマンドを使用して、StatefulSetの最初のポッドのmongoシェルにアクセスします。

kubectl exec -it mongo-mongodb-replicaset-0 -- mongo -u your_database_username -p --authenticationDatabase admin

プロンプトが表示されたら、このユーザー名に関連付けられているパスワードを入力します。

OutputMongoDB shell version v4.1.9
Enter password: 

管理シェルにドロップされます:

OutputMongoDB server version: 4.1.9
Welcome to the MongoDB shell.
...

db:PRIMARY>

プロンプト自体にこの情報が含まれていますが、 rs.isMaster()メソッドを使用して、どのレプリカセットメンバーがプライマリであるかを手動で確認できます。

rs.isMaster()

プライマリのホスト名を示す次のような出力が表示されます。

Outputdb:PRIMARY> rs.isMaster()
{
        "hosts" : [
                "mongo-mongodb-replicaset-0.mongo-mongodb-replicaset.default.svc.cluster.local:27017",
                "mongo-mongodb-replicaset-1.mongo-mongodb-replicaset.default.svc.cluster.local:27017",
                "mongo-mongodb-replicaset-2.mongo-mongodb-replicaset.default.svc.cluster.local:27017"
        ],
        ...
        "primary" : "mongo-mongodb-replicaset-0.mongo-mongodb-replicaset.default.svc.cluster.local:27017",
        ...

次に、sharkinfoデータベースに切り替えます。

use sharkinfo
Outputswitched to db sharkinfo

データベース内のコレクションを一覧表示します。

show collections
Outputsharks

コレクション内のドキュメントを出力します。

db.sharks.find()

次の出力が表示されます。

Output{ "_id" : ObjectId("5cb7702c9111a5451c6dc8bb"), "name" : "Megalodon Shark", "character" : "Ancient", "__v" : 0 }
{ "_id" : ObjectId("5cb77054fcdbf563f3b47365"), "name" : "Whale Shark", "character" : "Large", "__v" : 0 }

MongoDBシェルを終了します。

exit

プライマリのデータを確認したので、セカンダリにデータが複製されていることを確認しましょう。 次のコマンドを使用して、kubectl execmongo-mongodb-replicaset-1に挿入します。

kubectl exec -it mongo-mongodb-replicaset-1 -- mongo -u your_database_username -p --authenticationDatabase admin

管理シェルに入ったら、db.setSlaveOk()メソッドを使用して、セカンダリインスタンスからの読み取り操作を許可する必要があります。

db.setSlaveOk(1)

sharkinfoデータベースに切り替えます。

use sharkinfo
Outputswitched to db sharkinfo

sharksコレクション内のドキュメントの読み取り操作を許可します。

db.setSlaveOk(1)

コレクション内のドキュメントを出力します。

db.sharks.find()

これで、プライマリインスタンスでこのメソッドを実行したときに表示されたのと同じ情報が表示されます。

Outputdb:SECONDARY> db.sharks.find()
{ "_id" : ObjectId("5cb7702c9111a5451c6dc8bb"), "name" : "Megalodon Shark", "character" : "Ancient", "__v" : 0 }
{ "_id" : ObjectId("5cb77054fcdbf563f3b47365"), "name" : "Whale Shark", "character" : "Large", "__v" : 0 }

この出力は、アプリケーションデータがレプリカセットのメンバー間で複製されていることを確認します。

結論

これで、Helmチャートを使用して、複製された高可用性のサメ情報アプリケーションをKubernetesクラスターにデプロイしました。 このデモアプリケーションとこのチュートリアルで概説されているワークフローは、アプリケーションのカスタムチャートを作成し、Helmのstableリポジトリと他のチャートリポジトリを利用する際の出発点として機能します。

本番環境に移行するときは、次の実装を検討してください。

Helmの詳細については、 Helmの概要、KubernetesのパッケージマネージャーHelm Package Manager を使用してKubernetesクラスターにソフトウェアをインストールする方法、およびHelmのドキュメントを参照してください。