前書き
Kubernetesは、最新のコンテナ化されたアプリケーションを大規模に実行するためのシステムです。 これにより、開発者はマシンのクラスター全体にアプリケーションをデプロイおよび管理できます。 また、Kubernetesは、単一インスタンスアプリケーションのセットアップの効率と信頼性を向上させるために使用できますが、マシンのグループ間でアプリケーションの複数のインスタンスを実行するように設計されています。
Kubernetesを使用してマルチサービスデプロイメントを作成する場合、多くの開発者はHelmパッケージマネージャーを使用することを選択します。 Helmは、これらのオブジェクトの相互作用を調整するチャートとテンプレートを提供することにより、複数のKubernetesリソースを作成するプロセスを合理化します。 また、人気のあるオープンソースプロジェクト用にあらかじめパッケージ化されたチャートも提供しています。
このチュートリアルでは、Helmチャートを使用して、MongoDBデータベースを含むNode.jsアプリケーションをKubernetesクラスターにデプロイします。 official Helm MongoDB replica set chartを使用して、3つのPods、Headless 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 documentationにkubectl
をインストールする方法の詳細を読むことができます。 -
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 ComposeのStep 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
commandとrand
オプションを使用して、キーファイルの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
セットアップ用の特定の名前空間を作成していないため、これにより、default
namespaceに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
。
でリソースを作成する前に、構文を検証することをお勧めします。
次のコードをファイルに追加して、作成したばかりのエンコードされた値でuser
とpassword
を定義するシークレットを作成します。 ここのダミー値は、必ず独自の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を使用しているため、デフォルトのStorageClassprovisioner
はdobs.csi.digitalocean.com
—DigitalOcean 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
ここでのREADY
とSTATUS
の出力は、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
Running
STATUS
は、ポッドがノードにバインドされており、それらのポッドに関連付けられているコンテナーが実行されていることを示します。 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 ResourcesとIngress 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_HOSTNAME
、MONGO_PORT
、MONGO_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_HOSTNAME
、MONGO_PORT
、MONGO_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オブジェクトとレプリカセットは既に作成されているため、ここにリストされているホスト名は、この例に示されているとおりにファイルにリストされている必要があります。 これらのオブジェクトを破棄し、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 Kubernetesのrelevant 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
。
次のランディングページが表示されます。
レプリケートされたアプリケーションが機能するようになったので、テストセットを追加して、レプリカセットのメンバー間でレプリケーションが機能していることを確認します。
[[step-6 -—- testing-mongodb-replication]] ==ステップ6—MongoDBレプリケーションのテスト
アプリケーションを実行し、外部IPアドレスを介してアクセスできるようにすることで、テストデータを追加し、MongoDBレプリカセットのメンバー間で複製されることを確認できます。
まず、ブラウザからアプリケーションのランディングページに移動していることを確認します。
Get Shark Infoボタンをクリックします。 サメの名前とそのサメの一般的なキャラクターの説明を入力できるエントリフォームのページが表示されます。
フォームに、選択した最初のサメを追加します。 実例を示すために、Megalodon Shark
をShark Nameフィールドに追加し、Ancient
をShark Characterフィールドに追加します。
Submitボタンをクリックします。 このサメの情報が表示されたページが表示されます:
次に、上部のナビゲーションバーのSharksをクリックして、サメ情報フォームに戻ります。
お好みの新しいサメを入力してください。 Whale Shark
とLarge
を使用します。
Submitをクリックすると、新しいサメがデータベースのサメコレクションに追加されたことがわかります。
入力したデータがレプリカセットのプライマリメンバーとセカンダリメンバー間で複製されたことを確認しましょう。
ポッドのリストを取得します。
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 2にmongo-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 exec
をmongo-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を利用する際の出発点として機能します。
本番環境に移行するときは、次の実装を検討してください。
-
Centralized logging and monitoring。 一般的な概要については、Modernizing Applications for Kubernetesのrelevant discussionを参照してください。 また、How To Set Up an Elasticsearch, Fluentd and Kibana (EFK) Logging Stack on Kubernetesを調べて、Elasticsearch、Fluentd、およびKibanaでログスタックを設定する方法を学ぶこともできます。 また、Istioのようなサービスメッシュがこの機能を実装する方法については、An Introduction to Service Meshesを確認してください。
-
Ingress Resources to route traffic to your cluster。 これは、それぞれ独自のLoadBalancerを必要とする複数のサービスを実行している場合、またはアプリケーションレベルのルーティング戦略(A / Bおよびカナリアテストなど)を実装する場合に、LoadBalancerの代替として適しています。 詳細については、An Introduction to Service MeshesのサービスメッシュコンテキストでのルーティングのHow to Set Up an Nginx Ingress with Cert-Manager on DigitalOcean Kubernetesとrelated discussionを確認してください。
-
Backup strategies for your Kubernetes objects。 DigitalOceanのKubernetes製品でVelero(以前のHeptio Ark)を使用してバックアップを実装するためのガイダンスについては、How To Back Up and Restore a Kubernetes Cluster on DigitalOcean Using Heptio Arkを参照してください。