ウェビナーシリーズ:Kubernetesでのマイクロサービスの展開とスケーリング

前書き

Kubernetesは、コンテナ化されたアプリケーションを管理するためのオープンソースのコンテナオーケストレーションツールです。 このシリーズの前のチュートリアルhttps://www.digitalocean.com/community/tutorials/webinar-series-a-closer-look-at-kubernetes[Kubernetesの詳細]では、Kubernetesの構成要素を学習しました。

このチュートリアルでは、以前のチュートリアルの概念を適用して、Kubernetesでエンドツーエンドのマイクロサービスアプリケーションを構築、デプロイ、および管理します。 このチュートリアルで使用するサンプルWebアプリケーションは、MongoDBをデータベースとして使用するNode.jsで記述された「todoリスト」アプリケーションです。 これは、チュートリアルhttps://www.digitalocean.com/community/tutorials/webinar-series-building-containerized-applications [コンテナ化されたアプリケーションの構築]で使用したものと同じアプリケーションです。

このアプリのコンテナーイメージをDockerfileから構築し、そのイメージをDocker Hubにプッシュしてから、クラスターに展開します。 次に、需要の増加に合わせてアプリをスケーリングします。

前提条件

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

  • このチュートリアルシリーズの第3部で構成できるKubernetesクラスターhttps://www.digitalocean.com/community/tutorials/webinar-series-getting-started-with-kubernetes[Getting Started with Kubernetes]。

  • 画像を保存するためのアクティブなhttps://hub.docker.com/[Docker Hub]アカウント。

  • ローカルマシンにインストールされたGit。 チュートリアルhttps://www.digitalocean.com/community/tutorials/contributing-to-open-source-getting-started-with-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

次に、Docker Hubのパブリックレジストリに画像をプッシュします。 これを行うには、Docker Hubアカウントにログインします。

docker login

資格情報を提供したら、Docker Hubのユーザー名を使用して画像にタグを付けます。

docker tag /todo-app

次に、画像をDocker Hubにプッシュします。

docker push

Webブラウザでhttps://hub.docker.com/[Docker Hub]を検索すると、新しいイメージが利用可能であることを確認できます。

Dockerイメージをレジストリにプッシュしたら、Kubernetes用にアプリケーションをパッケージ化しましょう。

ステップ2 – MongoDBポッドをKubernetesにデプロイする

アプリケーションは、MongoDBを使用して、Webアプリケーションで作成されたTo Doリストを保存します。 KubernetesでMongoDBを実行するには、Podとしてパッケージ化する必要があります。 このポッドを起動すると、MongoDBの単一のインスタンスが実行されます。

db-pod.yamlという新しいYAMLファイルを作成します。

nano db-pod.yaml

MongoDBに基づく1つのコンテナーでポッドを定義する次のコードを追加します。 MongoDBが使用する標準ポートであるポート `+ 27017 `を公開します。 定義には、ラベル「 name」と「+ app」が含まれていることに注意してください。 これらのラベルを使用して、特定のポッドを識別および構成します。

db-pod.yaml

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

データは、ノードの「+ / data / db 」ロケーションにマッピングされる「 mongo-storage +」と呼ばれるボリュームに保存されます。 ボリュームの詳細については、公式のhttps://kubernetes.io/docs/concepts/storage/volumes[Kubernetesボリュームドキュメント]を参照してください。

次のコマンドを実行してポッドを作成します。

kubectl create -f db-pod.yml

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

Outputpod "db" created

次に、ポッドの作成を確認します。

kubectl get pods

出力にはポッドが表示され、実行されていることが示されます。

OutputNAME      READY     STATUS    RESTARTS   AGE
db   1/1          0          2m

このポッドをクラスターの内部コンシューマーがアクセスできるようにします。

MongoDBのサービスを定義する次のコードを含む、「+ db-service.yaml +」という新しいファイルを作成します。

db-service.yaml

apiVersion: v1
kind: Service
metadata:
  name: db
  labels:
    name: mongo
    app:

spec:
  selector:
    name: mongo

  type: ClusterIP
  ports:
    - name: db
      port: 27017
      targetPort: 27017

サービスは、同じ名前空間で、 `+ name:db `のラベルに一致するすべてのポッドを検出します。 YAMLファイルの ` selector +`セクションは、この関連付けを明示的に定義します。

`+ 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>           14s
kubernetes   ClusterIP   10.96.0.1        <none>        443/TCP     47m

この出力から、サービスがポート `+ 27017 `で利用可能であることがわかります。 Webアプリケーションは、このサービスを通じてMongoDBに到達できます。 ホスト名「 db +」を使用する場合、Kubernetes内で実行されているDNSサービスは、アドレスをサービスに関連付けられたClusterIPに解決します。 このメカニズムにより、ポッドは相互に検出および通信できます。

データベースポッドとサービスを配置したら、Webアプリケーションのポッドを作成しましょう。

ステップ3 – Node.JS Webアプリをポッドとしてデプロイする

このチュートリアルの最初のステップで作成したDockerイメージをポッドとしてパッケージ化し、クラスターにデプロイします。 これは、エンドユーザーがアクセスできるフロントエンドWebアプリケーションレイヤーとして機能します。

`+ web-pod.yaml +`という新しいYAMLファイルを作成します。

nano web-pod.yaml

+ sammy / todo-app + Dockerイメージに基づいて1つのコンテナーでポッドを定義する次のコードを追加します。 TCPプロトコルを介してポート「3000」で公開されます。

web-pod.yaml

apiVersion: v1
kind: Pod

metadata:
  name: web
  labels:
    name: web
    app:

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
       1/1       Running   0          8m
      1/1       Running   0          9s

MongoDBデータベースとWebアプリの両方がPodsとして実行されていることに注意してください。

ここで、 `+ web +`ポッドをパブリックインターネットにアクセスできるようにします。

サービスは、一連のPodを内部または外部に公開します。 `+ web +`ポッドを公開するサービスを定義しましょう。 NodePortを介して公開します。これは、クラスターの各ノードで開かれた任意のポートを介してPodにアクセスできるようにするスキームです。

アプリのサービスを定義する次のコードを含む「+ web-service.yaml +」という新しいファイルを作成します。

apiVersion: v1
kind: Service
metadata:
  name: web
  labels:
    name: web
    app:

spec:
  selector:
    name: web
  type: NodePort
  ports:
   - name: http
     port: 3000
     targetPort: 3000
     protocol: TCP

サービスは、名前空間が「+ web +」のラベルと一致する同じ名前空間内のすべてのポッドを検出します。 YAMLファイルのセレクターセクションは、この関連付けを明示的に定義します。

`+ type:NodePort `宣言により、サービスが ` 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:   12s

この出力から、サービスがポート `+ 30770 +`で利用可能であることがわかります。 ワーカーノードの1つに接続してみましょう。

DigitalOceanコンソールを使用して、Kubernetesクラスターに関連付けられているワーカーノードのいずれかのパブリックIPアドレスを取得します。

image:https://assets.digitalocean.com/articles/webinar_3_kubernetes_stackpoint/w9acP7y.png [ワーカーノードを表示するDigitalOceanコンソール]

IPアドレスを取得したら、 `+ curl `コマンドを使用して、ポート ` 30770 +`上のノードの1つにHTTPリクエストを送信します。

curl http://:30770

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

Output<!DOCTYPE html>
<html>
  <head>
    <title>Containers Todo Example</title>
    <link rel='stylesheet' href='/stylesheets/screen.css' />
    <!--[if lt IE 9]>
    <script src="http://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

次に、新しいレプリカセット宣言を作成します。 レプリカセットの定義はポッドと同じです。 主な違いは、実行する必要があるPodの数を定義する `+ 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=
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=
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つが削除されると、別のポッドがすぐに作成され、目的のカウントが維持されます。 これにより、常に最小数のPodが常に実行されるようになり、アプリケーションの高可用性が確保されます。

次のコマンドを使用して、このチュートリアルで作成したすべてのオブジェクトを削除できます。

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として実行することにより、MongoDBを高可用性にする方法を学習します。