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

前書き

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

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

このチュートリアルでは、Helmチャートを使用して、MongoDBデータベースを含むNode.jsアプリケーションをKubernetesクラスターにデプロイします。 official Helm MongoDB replica set chartを使用して、3つのPodsHeadless Service、および3つのPersistentVolumeClaimsで構成されるStatefulSet objectを作成します。 また、カスタムアプリケーションイメージを使用してマルチレプリカNode.jsアプリケーションをデプロイするチャートを作成します。 このチュートリアルで構築するセットアップは、Containerizing a Node.js Application with Docker Composeで説明されているコードの機能を反映し、ニーズに合わせて拡張できるMongoDBデータストアを備えた復元力のあるNode.jsアプリケーションを構築するための良い出発点になります。

前提条件

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

  • 役割ベースのアクセス制御(RBAC)が有効になっているKubernetes 1.10+クラスター。 この設定ではDigitalOcean Kubernetes clusterを使用しますが、create a cluster using another methodは自由に使用できます。

  • ローカルマシンまたは開発サーバーにインストールされ、クラスターに接続するように構成されたkubectlコマンドラインツール。 official documentationkubectlをインストールする方法の詳細を読むことができます。

  • How To Install Software on Kubernetes Clusters with the Helm Package Managerのステップ1および2で概説されている指示に従って、ローカルマシンまたは開発サーバーにインストールされたHelmとクラスターにインストールされたTiller。

  • Dockerがローカルマシンまたは開発サーバーにインストールされています。 Ubuntu 18.04を使用している場合は、How To Install and Use Docker on Ubuntu 18.04の手順1と2に従います。それ以外の場合は、他のオペレーティングシステムへのインストールについて、official documentationに従ってください。 リンクされたチュートリアルのステップ2で説明されているように、root以外のユーザーを必ずdockerグループに追加してください。

  • Docker Hubアカウント。 これを設定する方法の概要については、Docker Hubへのthis introductionを参照してください。

[[step-1 -—- cloning-and-packaging-the-application]] ==ステップ1—アプリケーションのクローン作成とパッケージ化

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

最初のステップは、DigitalOcean Community GitHub accountからnode-mongo-docker-dev repositoryを複製することです。 このリポジトリには、Containerizing a Node.js Application for Development With Docker Composeで説明されているセットアップのコードが含まれています。このコードは、MongoDBデータベースでデモNode.jsアプリケーションを使用して、DockerComposeで開発環境をセットアップする方法を示しています。 アプリケーション自体の詳細については、シリーズFrom Containers to Kubernetes with Node.jsを参照してください。

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

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

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

cd node_project

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

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

Helmmongodb-replicasetチャートをデプロイすると、次のものが作成されます。

  • 3つのポッドを持つStatefulSetオブジェクト— MongoDBreplica setのメンバー。 各PodにはPersistentVolumeClaimが関連付けられており、再スケジュールの際に固定IDを維持します。

  • StatefulSetのPodで構成されるMongoDBレプリカセット。 セットには、1つのプライマリと2つのセカンダリが含まれます。 データはプライマリからセカンダリに複製され、アプリケーションデータの高可用性が維持されます。

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

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

nano db.js

現在、ファイルには、実行時にデータベース接続URIで参照されるconstantsが含まれています。 これらの定数の値は、ノードのprocess.envプロパティを使用して挿入されます。このプロパティは、実行時にユーザー環境に関する情報を含むオブジェクトを返します。 アプリケーションコードで値を動的に設定すると、動的なステートレス環境で必要な、基盤となるインフラストラクチャからコードを分離できます。 この方法でのアプリケーションコードのリファクタリングの詳細については、Containerizing a Node.js Application for Development With Docker ComposeStep 2と、The 12-Factor 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文字列のoptions sectionにレプリカセット定数を追加する必要があります。

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

~/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 optionを使用すると、レプリカセットの名前を渡すことができます。これにより、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

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

docker login -u your_dockerhub_username

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

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

docker push your_dockerhub_username/node-replicas

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

[[step-2 -—- creating-secrets-for-the-mongodb-replica-set]] ==ステップ2—MongoDBレプリカセットのシークレットを作成する

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

  • レプリカセットメンバー間で共有パスワードとして機能し、他のメンバーを認証できるようにするreplica set keyfileのシークレット。

  • adminデータベースにroot userとして作成されるMongoDB管理者ユーザーのシークレット。 このロールを使用すると、アプリケーションを実稼働環境にデプロイするときに、制限された権限を持つ後続のユーザーを作成できます。

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

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

openssl rand -base64 756 > key.txt

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

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

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

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

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

Outputsecret/keyfilesecret created

key.txtを削除します。

rm key.txt

または、ファイルを保存する場合は、必ずrestrict its permissionsを作成し、それを.gitignore fileに追加して、バージョン管理されないようにします。

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

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

echo -n 'your_database_username' | base64

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

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

echo -n 'your_database_password' | base64

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

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

nano secret.yaml

[。注意]##

Note: KubernetesオブジェクトはYAMLを使用するtypically definedであり、タブを厳密に禁止し、インデントのために2つのスペースを必要とします。 YAMLファイルのフォーマットを確認したい場合は、linterを使用するか、kubectl create--dry-runおよび--validateを使用して構文の有効性をテストできます。フラグ:

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

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

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

~/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という名前を付けましたが、好きな名前を付けることができます。

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

次のコマンドでシークレットオブジェクトを作成します。

kubectl create -f secret.yaml

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

Outputsecret/mongo-secret created

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

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

[[step-3 -—- configuring-the-mongodb-helm-chart-and-creating-a-deployment]] ==ステップ3—MongoDBヘルムチャートの構成とデプロイメントの作成

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

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

  • データベースインスタンスがauthorization enabledで始まるように、authパラメータをtrueに設定します。 これは、すべてのクライアントがデータベースリソースと操作にアクセスするために認証する必要があることを意味します。

  • 前の手順で作成したシークレットに関する情報を追加して、チャートがこれらの値を使用してレプリカセットキーファイルと管理ユーザーを作成できるようにします。

  • StatefulSet内の各ポッドに関連付けられているPersistentVolumesのサイズを減らして、minimum viable DigitalOcean Block Storage unit、1GBを使用しますが、ストレージ要件に合わせてこれを自由に変更できます。

ただし、mongodb-values.yamlファイルを書き込む前に、ストレージリソースをプロビジョニングするためにStorageClassが作成および構成されていることを最初に確認する必要があります。 データベースStatefulSet内の各ポッドには、スティッキーIDと関連するPersistentVolumeClaimがあり、ポッドのPersistentVolumeを動的にプロビジョニングします。 Podが再スケジュールされると、PersistentVolumeはPodがスケジュールされているノードにマウントされます(ただし、関連するPodまたは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を構成する必要があります。 これを行う方法の詳細については、official documentationを参照してください。

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は、プロビジョニングされたボリュームが単一ノードによってのみ読み取り/書き込み可能であることを意味します。 さまざまなアクセスモードの詳細については、documentationを参照してください。

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

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

mongodb-replicasetチャートを展開する前に、stableリポジトリをhelm repo update commandで更新する必要があります。

helm repo update

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

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

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

[。注意]##

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

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

ヘルムに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

ここでのREADYSTATUSの出力は、StatefulSet内のポッドの準備が完全に整っていないことを示しています。ポッドのコンテナに関連付けられているInit Containersはまだ実行中です。 StatefulSetメンバーはcreated in sequential orderであるため、次のポッドが作成される前に、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

RunningSTATUSは、ポッドがノードにバインドされており、それらのポッドに関連付けられているコンテナーが実行されていることを示します。 READYは、ポッド内で実行されているコンテナーの数を示します。 詳細については、documentation on Pod lifecyclesを参照してください。

[。注意]##

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

kubectl describe pods your_pod
kubectl logs your_pod

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

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

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           443/TCP     42m
mongo-mongodb-replicaset          ClusterIP   None                 27017/TCP   4m35s
mongo-mongodb-replicaset-client   ClusterIP   None                 27017/TCP   4m35s

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

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

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

データベースインスタンスを起動して実行すると、Nodeアプリケーションのチャートを作成する準備が整います。

[[step-4 -—- creating-a-custom-application-chart-and-configuring-parameters]] ==ステップ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

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

  • レプリカの数。

  • 使用するアプリケーションイメージ。 この場合、これはStep 1で作成したnode-replicasイメージになります。

  • ServiceType。 この場合、LoadBalancerを指定して、テスト目的でアプリケーションへのアクセスポイントを作成します。 DigitalOcean Kubernetesクラスターを使用しているため、グラフをデプロイするとDigitalOcean Load Balancerが作成されます。 本番環境では、Ingress ResourcesIngress Controllersを使用してトラフィックをサービスにルーティングするようにグラフを構成できます。

  • 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オブジェクトを作成するときにStep 2で以前に使用したbase64-encoded値を使用することを忘れないでください。 これらの値を再作成する必要がある場合は、手順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

このSecretオブジェクトの名前は、Helmリリースの名前に依存します。Helmリリースは、アプリケーションチャートを展開するときに指定します。

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

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

nano nodeapp/templates/configmap.yaml

このファイルでは、アプリケーションが期待する残りの変数、MONGO_HOSTNAMEMONGO_PORTMONGO_DB、およびMONGO_REPLICASETを定義します。 MONGO_HOSTNAME変数には、レプリカセット内のeachインスタンスのDNSエントリが含まれます。これはMongoDB connection URI requiresであるためです。

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

次のコードをファイルに追加して、MONGO_HOSTNAMEMONGO_PORTMONGO_DB、およびMONGO_REPLICASET変数を定義します。 MONGO_DBデータベースには別の名前を自由に使用できますが、MONGO_HOSTNAMEMONGO_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オブジェクトとレプリカセットは既に作成されているため、ここにリストされているホスト名は、この例に示されているとおりにファイルにリストされている必要があります。 これらのオブジェクトを破棄し、MongoDB Helmリリースの名前を変更した場合、このConfigMapに含まれる値を修正する必要があります。 MongoDBリリースでレプリカセット名を指定したため、同じことがMONGO_REPLICASETにも当てはまります。

また、ここにリストされている値は引用符で囲まれていることに注意してください。これはthe expectation for environment variables in Helmです。

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

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

[[step-5 --- integrating-environment-variables-into-your-helm-deployment]] ==ステップ5—環境変数をHelmデプロイメントに統合する

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

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

nano nodeapp/templates/deployment.yaml

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

ファイルで、最初に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で定義された値への参照が含まれます。 これらのキーは、前の手順で作成したSecretファイルと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
      ...

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

  • レディネスプローブは、ポッドがトラフィックを処理する準備ができているかどうかを評価し、チェックが成功するまでポッドへのすべてのリクエストを停止します。

  • Livenessプローブは、基本的なアプリケーションの動作を確認して、コンテナ内のアプリケーションが実行され、予想どおりに動作しているかどうかを判断します。 活性プローブが失敗すると、Kubernetesはコンテナを再起動します。

両方の詳細については、Architecting Applications for Kubernetesrelevant discussionを参照してください。

この場合、Helmがデフォルトで提供するhttpGet requestに基づいて構築し、アプリケーションが/sharksエンドポイントでリクエストを受け入れているかどうかをテストします。 kubelet serviceは、アプリケーションポッドのコンテナで実行されているノードサーバーに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を使用してアプリケーションリリースを作成する準備ができました。 次のhelm install commandを実行します。これには、リリースの名前とチャートディレクトリの場所が含まれます。

helm install --name nodejs ./nodeapp

Step 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

Podを起動して実行したら、サービスを確認します。

kubectl get svc
OutputNAME                              TYPE           CLUSTER-IP     EXTERNAL-IP       PORT(S)        AGE
kubernetes                        ClusterIP      10.245.0.1                 443/TCP        96m
mongo-mongodb-replicaset          ClusterIP      None                       27017/TCP      58m
mongo-mongodb-replicaset-client   ClusterIP      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が表示されたら、ブラウザでそのIPに移動します:http://your_lb_ip

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

Application Landing Page

レプリケートされたアプリケーションが機能するようになったので、テストセットを追加して、レプリカセットのメンバー間でレプリケーションが機能していることを確認します。

[[step-6 -—- testing-mongodb-replication]] ==ステップ6—MongoDBレプリケーションのテスト

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

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

Application Landing Page

Get Shark Infoボタンをクリックします。 サメの名前とそのサメの一般的なキャラクターの説明を入力できるエントリフォームのページが表示されます。

Shark Info Form

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

Filled Shark Form

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

Shark Output

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

Shark Info Form

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

Enter New Shark

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

Complete Shark Collection

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

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

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

ポッドのmongo shellにアクセスするには、kubectl exec commandと、Step 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() methodを使用して、どのレプリカセットメンバーがプライマリであるかを手動で確認できます。

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リポジトリとother chart repositoriesを利用する際の出発点として機能します。

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

Related