ウェビナーシリーズ:Kubernetesでのマイクロサービスのデプロイとスケーリング
この記事は、クラウドでのコンテナー化されたワークロードのデプロイと管理に関するウェビナーシリーズを補足するものです。 このシリーズでは、コンテナーライフサイクルの管理、マルチコンテナーアプリケーションのデプロイ、ワークロードのスケーリング、Kubernetesの操作など、コンテナーの基本事項について説明します。 また、ステートフルアプリケーションを実行するためのベストプラクティスについても説明します。
このチュートリアルには、シリーズの5番目のセッションであるKubernetesでのマイクロサービスのデプロイとスケーリングの概念とコマンドが含まれています。
序章
Kubernetes は、コンテナー化されたアプリケーションを管理するためのオープンソースのコンテナーオーケストレーションツールです。 このシリーズの前回のチュートリアルでは、 Kubernetesの詳細で、Kubernetesの構成要素を学習しました。
このチュートリアルでは、前のチュートリアルの概念を適用して、Kubernetesでエンドツーエンドのマイクロサービスアプリケーションを構築、デプロイ、管理します。 このチュートリアルで使用するサンプルWebアプリケーションは、MongoDBをデータベースとして使用するNode.jsで記述された「todoリスト」アプリケーションです。 これは、チュートリアルコンテナ化されたアプリケーションの構築で使用したものと同じアプリケーションです。
このアプリのコンテナーイメージをDockerfileからビルドし、イメージをDocker Hubにプッシュしてから、クラスターにデプロイします。 次に、需要の増加に合わせてアプリをスケーリングします。
前提条件
このチュートリアルを完了するには、次のものが必要です。
-
このチュートリアルシリーズの第3部であるKubernetes入門で構成できるKubernetesクラスター。
-
イメージを保存するためのアクティブなDockerHubアカウント。
-
Gitがローカルマシンにインストールされています。 チュートリアルオープンソースへの貢献:Git入門に従って、コンピューターにGitをインストールしてセットアップすることができます。
ステップ1-Dockerfileを使用してイメージを構築する
まず、WebアプリケーションをDockerイメージにパッケージ化してコンテナー化します。
まずホームディレクトリに移動し、Gitを使用してこのチュートリアルのサンプルWebアプリケーションをGitHubの公式リポジトリから複製します。
- cd ~
- git clone https://github.com/janakiramm/todo-app.git
Dockerfileからコンテナーイメージをビルドします。 -tスイッチを使用して、レジストリのユーザー名、イメージ名、およびオプションのタグでイメージにタグを付けます。
- docker build -t sammy/todo .
出力は、イメージが正常に構築され、適切にタグ付けされたことを確認します。
OutputSending build context to Docker daemon 8.238MB
Step 1/7 : FROM node:slim
---> 286b1e0e7d3f
Step 2/7 : LABEL maintainer = "[email protected]"
---> Using cache
---> ab0e049cf6f8
Step 3/7 : RUN mkdir -p /usr/src/app
---> Using cache
---> 897176832f4d
Step 4/7 : WORKDIR /usr/src/app
---> Using cache
---> 3670f0147bed
Step 5/7 : COPY ./app/ ./
---> Using cache
---> e28c7c1be1a0
Step 6/7 : RUN npm install
---> Using cache
---> 7ce5b1d0aa65
Step 7/7 : CMD node app.js
---> Using cache
---> 2cef2238de24
Successfully built 2cef2238de24
Successfully tagged sammy/todo-app:latest
docker imagesコマンドを実行して、イメージが作成されていることを確認します。
- docker images
画像のサイズと作成後の時間を確認できます。
OutputREPOSITORY TAG IMAGE ID CREATED SIZE
sammy/todo-app latest 81f5f605d1ca 9 minutes ago 236MB
次に、イメージをDockerHubのパブリックレジストリにプッシュします。 これを行うには、DockerHubアカウントにログインします。
- docker login
クレデンシャルを入力したら、DockerHubユーザー名を使用してイメージにタグを付けます。
- docker tag your_docker_hub_username/todo-app
次に、イメージをDockerHubにプッシュします。
- docker push
WebブラウザでDockerHub を検索すると、新しいイメージが利用可能であることを確認できます。
Dockerイメージをレジストリにプッシュしたら、Kubernetes用のアプリケーションをパッケージ化します。
ステップ2–KubernetesにMongoDBポッドをデプロイする
このアプリケーションは、MongoDBを使用して、Webアプリケーションを介して作成されたToDoリストを保存します。 KubernetesでMongoDBを実行するには、ポッドとしてパッケージ化する必要があります。 このポッドを起動すると、MongoDBの単一インスタンスが実行されます。
db-pod.yamlという名前の新しいYAMLファイルを作成します。
- nano db-pod.yaml
MongoDBに基づいて1つのコンテナーでポッドを定義する次のコードを追加します。 ポートを公開します 27017
、MongoDBで使用される標準ポート。 定義にラベルが含まれていることに注意してください name
と app
. これらのラベルを使用して、特定のポッドを識別および構成します。
apiVersion: v1
kind: Pod
metadata:
name: db
labels:
name: mongo
app: todoapp
spec:
containers:
- image: mongo
name: mongo
ports:
- name: mongo
containerPort: 27017
volumeMounts:
- name: mongo-storage
mountPath: /data/db
volumes:
- name: mongo-storage
hostPath:
path: /data/db
データはと呼ばれるボリュームに保存されます mongo-storage
これはにマップされます /data/db
ノードの場所。 ボリュームの詳細については、公式のKubernetesボリュームのドキュメントを参照してください。
次のコマンドを実行して、ポッドを作成します。
- kubectl create -f db-pod.yml
次の出力が表示されます。
Outputpod "db" created
次に、ポッドの作成を確認します。
- kubectl get pods
出力にはポッドが表示され、ポッドが実行中であることが示されます。
OutputNAME READY STATUS RESTARTS AGE
db 1/1 Running 0 2m
このポッドをクラスターの内部コンシューマーがアクセスできるようにしましょう。
と呼ばれる新しいファイルを作成します db-service.yaml
これには、MongoDBのサービスを定義する次のコードが含まれています。
apiVersion: v1
kind: Service
metadata:
name: db
labels:
name: mongo
app: todoapp
spec:
selector:
name: mongo
type: ClusterIP
ports:
- name: db
port: 27017
targetPort: 27017
サービスは、ラベルと一致する同じ名前空間内のすべてのポッドを検出します name: db
. The selector
YAMLファイルのセクションは、この関連付けを明示的に定義します。
宣言を通じて、サービスがクラスター内に表示されることを指定します type: ClusterIP
.
ファイルを保存して、エディターを終了します。 次に、 kubectl
クラスターに送信します。
- kubectl create -f db-service.yml
サービスが正常に作成されたことを示す次の出力が表示されます。
Outputservice "db" created
ポッドが使用可能なポートを取得しましょう。
- kubectl get services
次の出力が表示されます。
OutputNAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
db ClusterIP 10.109.114.243 <none> 27017/TCP 14s
kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 47m
この出力から、サービスがポートで利用可能であることがわかります 27017
. Webアプリケーションは、このサービスを介してMongoDBに到達できます。 ホスト名を使用する場合 db
、Kubernetes内で実行されているDNSサービスは、サービスに関連付けられたClusterIPにアドレスを解決します。 このメカニズムにより、ポッドは相互に検出して通信できます。
データベースのポッドとサービスを配置したら、Webアプリケーションのポッドを作成しましょう。
ステップ3–Node.JSWebアプリをポッドとしてデプロイする
このチュートリアルの最初のステップで作成したDockerイメージをポッドとしてパッケージ化し、クラスターにデプロイしてみましょう。 これは、エンドユーザーがアクセスできるフロントエンドWebアプリケーション層として機能します。
と呼ばれる新しいYAMLファイルを作成します web-pod.yaml
:
- nano web-pod.yaml
に基づいて1つのコンテナでポッドを定義する次のコードを追加します sammy/todo-app
Dockerイメージ。 ポートで公開されています 3000
TCPプロトコルを介して。
apiVersion: v1
kind: Pod
metadata:
name: web
labels:
name: web
app: todoapp
spec:
containers:
- image: sammy/todo-app
name: myweb
ports:
- containerPort: 3000
定義にラベルが含まれていることに注意してください name
と app
. サービスはこれらのラベルを使用して、インバウンドトラフィックを適切なポートにルーティングします。
次のコマンドを実行してポッドを作成します。
- kubectl create -f web-pod.yaml
Outputpod "web" created
ポッドの作成を確認しましょう。
- kubectl get pods
OutputNAME READY STATUS RESTARTS AGE
db 1/1 Running 0 8m
web 1/1 Running 0 9s
MongoDBデータベースとWebアプリの両方がポッドとして実行されていることに注意してください。
今、私たちは作ります web
パブリックインターネットにアクセス可能なポッド。
サービスは、ポッドのセットを内部または外部に公開します。 を作るサービスを定義しましょう web
ポッドは公開されています。 これは、クラスターの各ノードで開かれた任意のポートを介してポッドにアクセスできるようにするスキームであるNodePortを介して公開します。
と呼ばれる新しいファイルを作成します web-service.yaml
アプリのサービスを定義する次のコードが含まれています。
apiVersion: v1
kind: Service
metadata:
name: web
labels:
name: web
app: todoapp
spec:
selector:
name: web
type: NodePort
ports:
- name: http
port: 3000
targetPort: 3000
protocol: TCP
サービスは、ラベルと名前が一致する同じ名前空間内のすべてのポッドを検出します web
. YAMLファイルのセレクターセクションは、この関連付けを明示的に定義します。
サービスのタイプを指定します NodePort
を通って type: NodePort
宣言。
使用する kubectl
これをクラスターに送信します。
- kubectl create -f web-service.yml
サービスが正常に作成されたことを示す次の出力が表示されます。
Outputservice "web" created
ポッドが使用可能なポートを取得しましょう。
- kubectl get services
OutputNAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
db ClusterIP 10.109.114.243 <none> 27017/TCP 12m
kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 59m
web NodePort 10.107.206.92 <none> 3000:30770/TCP 12s
この出力から、サービスがポートで利用可能であることがわかります 30770
. ワーカーノードの1つに接続してみましょう。
DigitalOceanコンソールを使用して、Kubernetesクラスターに関連付けられているワーカーノードの1つのパブリックIPアドレスを取得します。
IPアドレスを取得したら、 curl
ポート上のノードの1つにHTTPリクエストを送信するコマンド 30770
:
- curl http://your_worker_ip_address:30770
次のような出力が表示されます。
Output<!DOCTYPE html>
<html>
<head>
<title>Containers Todo Example</title>
<link rel='stylesheet' href='/stylesheets/screen.css' />
<!--[if lt IE 9]>
<script src="https://html5shiv.googlecode.com/svn/trunk/html5.js"></script>
<![endif]-->
</head>
<body>
<div id="layout">
<h1 id="page-title">Containers Todo Example</h1>
<div id="list">
<form action="/create" method="post" accept-charset="utf-8">
<div class="item-new">
<input class="input" type="text" name="content" />
</div>
</form>
</div>
<div id="layout-footer"></div>
</div>
<script src="/javascripts/ga.js"></script>
</body>
</html>
Webポッドとサービスを定義しました。 次に、レプリカセットを使用してスケーリングする方法を見てみましょう。
ステップ5–Webアプリケーションのスケーリング
レプリカセットにより、クラスター内で常に最小数のポッドが実行されていることが保証されます。 ポッドがレプリカセットとしてパッケージ化されている場合、Kubernetesは常に仕様で定義されている最小数のポッドを実行します。
現在のポッドを削除し、レプリカセットを使用して2つのポッドを再作成しましょう。 ポッドを実行したままにすると、レプリカセットの一部にはなりません。 したがって、カウントが1つだけの場合でも、レプリカセットを介してポッドを起動することをお勧めします。
まず、既存のポッドを削除します。
- kubectl delete pod web
Outputpod "web" deleted
次に、新しいレプリカセット宣言を作成します。 レプリカセットの定義はポッドと同じです。 主な違いは、 replica
実行する必要のあるポッドの数を定義する要素。 ポッドと同様に、サービス検出に役立つメタデータとしてのラベルも含まれています。
ファイルを作成する web-rs.yaml
次のコードをファイルに追加します。
apiVersion: extensions/v1beta1
kind: ReplicaSet
metadata:
name: web
labels:
name: web
app: todoapp
spec:
replicas: 2
template:
metadata:
labels:
name: web
spec:
containers:
- name: web
image: sammy/todo-app
ports:
- containerPort: 3000
ファイルを保存して閉じます。
次に、レプリカセットを作成します。
- kubectl create -f web-rs.yaml
Outputreplicaset "web" created
次に、ポッドの数を確認します。
- kubectl get pods
OutputNAME READY STATUS RESTARTS AGE
db 1/1 Running 0 18m
web-n5l5h 1/1 Running 0 25s
web-wh6nf 1/1 Running 0 25s
NodePortを介してサービスにアクセスすると、レプリカセットによって管理されているポッドの1つにリクエストが送信されます。
ポッドの1つを削除し、何が起こるかを確認して、レプリカセットの機能をテストしてみましょう。
- kubectl delete pod web-wh6nf
Outputpod "web-wh6nf" deleted
ポッドをもう一度見てください。
- kubectl get pods
OutputNAME READY STATUS RESTARTS AGE
db 1/1 Running 0 19m
web-n5l5h 1/1 Running 0 1m
web-wh6nf 1/1 Terminating 0 1m
web-ws59m 0/1 ContainerCreating 0 2s
ポッドが削除されるとすぐに、Kubernetesは別のポッドを作成して、目的のカウントが維持されるようにします。
レプリカセットをスケーリングして、追加のWebポッドを実行できます。
次のコマンドを実行して、Webアプリケーションを10ポッドにスケーリングします。
- kubectl scale rs/web --replicas=10
Outputreplicaset "web" scaled
ポッド数を確認します。
- kubectl get pods
次の出力が表示されます。
OutputNAME READY STATUS RESTARTS AGE
db 1/1 Running 0 22m
web-4nh4g 1/1 Running 0 21s
web-7vbb5 1/1 Running 0 21s
web-8zd55 1/1 Running 0 21s
web-f8hvq 0/1 ContainerCreating 0 21s
web-ffrt6 1/1 Running 0 21s
web-k6zv7 0/1 ContainerCreating 0 21s
web-n5l5h 1/1 Running 0 3m
web-qmdxn 1/1 Running 0 21s
web-vc45m 1/1 Running 0 21s
web-ws59m 1/1 Running 0 2m
Kubernetesはスケーリングのプロセスを開始しました web
ポッド。 リクエストがNodePortを介してサービスに到着すると、レプリカセット内のポッドの1つにルーティングされます。
トラフィックと負荷が落ち着くと、2つのポッドの元の構成に戻すことができます。
kubectl scale rs/web --replicas=2
Outputreplicaset "web" scaled
このコマンドは、2つを除くすべてのポッドを終了します。
- kubectl get pods
OutputNAME READY STATUS RESTARTS AGE
db 1/1 Running 0 24m
web-4nh4g 1/1 Terminating 0 2m
web-7vbb5 1/1 Terminating 0 2m
web-8zd55 1/1 Terminating 0 2m
web-f8hvq 1/1 Terminating 0 2m
web-ffrt6 1/1 Terminating 0 2m
web-k6zv7 1/1 Terminating 0 2m
web-n5l5h 1/1 Running 0 5m
web-qmdxn 1/1 Terminating 0 2m
web-vc45m 1/1 Terminating 0 2m
web-ws59m 1/1 Running 0 4m
レプリカセットの可用性を確認するには、ポッドの1つを削除して、カウントを確認してください。
- kubectl delete pod web-ws59m
Outputpod "web-ws59m" deleted
- kubectl get pods
OutputNAME READY STATUS RESTARTS AGE
db 1/1 Running 0 25m
web-n5l5h 1/1 Running 0 7m
web-ws59m 1/1 Terminating 0 5m
web-z6r2g 0/1 ContainerCreating 0 5s
ポッドカウントが変更されるとすぐに、KubernetesはYAMLファイルで定義されたカウントと一致するようにポッドカウントを調整します。 レプリカセット内のWebポッドの1つが削除されると、必要な数を維持するために別のポッドがすぐに作成されます。 これにより、最小数のポッドが常に実行されるようになり、アプリケーションの高可用性が保証されます。
次のコマンドを使用して、このチュートリアル中に作成されたすべてのオブジェクトを削除できます。
- kubectl delete -f db-pod.yaml -f db-service.yaml -f web-rs.yaml -f web-service.yaml
Outputpod "db" deleted
service "db" deleted
replicaset "web" deleted
service "web" deleted
結論
このチュートリアルでは、シリーズで取り上げたすべての概念を適用して、マイクロサービスアプリケーションをパッケージ化、デプロイ、スケーリングしました。
このシリーズの次のパートでは、MongoDBをStatefulSetとして実行して高可用性を実現する方法を学習します。