Google Cloud Platform

体験して理解しよう!マイクロサービスの開発、ビルド、デプロイ、運用

0108_blog_header_W.jpg

デモ用のマイクロサービスアプリケーションを使って実際に、マイクロサービスアプリケーションの開発、ビルド、デプロイ、運用を体験してみましょう。

このアプリケーションは、10 のサービスで構成されている「Hipster Shop」と呼ばれるデモ用の EC サイトです。ユーザーは、製品を選択し、カートに追加し購入することができます。各サービスは、Go, C#, Node.js, Python, Java といった言語で独自に書かれおり、下記のように、gRPC でコミュニケーションします。また、開発者は skaffold を使用し、1 コマンドでアプリケーションのビルド、デプロイが可能です。実行環境は、Google Kubernetes Engine (GKE) や、Local の Kubernetes 環境を選択することができます。今回は、GKE 環境を使って体験してみたいと思います。
f01

準備

プロジェクトを作成し、Cloud Shell を起動し、デモ用のマイクロサービスアプリケーションをクローンします。

  • GCP アカウントと、GitHub アカウントを作成(既にアカウントを持っている方は必要ありません)
  • GCP Console にログオンし、プロジェクトを作成
f02

  • [Cloud Shell をアクティブにする] をクリック

f03

  • [Cloud Shell 環境] から、Cloud Shell を起動

f04

  • gcloud コマンドの初期設定

  ❯ gcloud config list
[component_manager]
disable_update_check = True
[compute]
gce_metadata_read_timeout_sec = 5
[core]
account = <You Account Name>
disable_usage_reporting = False
project = <YOUR PROJECT ID>
[metrics]
environment = devshell
❯ gcloud projects list
PROJECT_ID              NAME              PROJECT_NUMBER
<YOUR PROJECT ID>  <YOUR PROJECT NAME>   <YOUR PROJECT NUMBER>
❯ gcloud config set project <YOUR PROJECT ID>
f05

  • Cloud Shell にて、Fork した マイクロサービスアプリケーションを Clone

  ❯ git init
❯ git config --global user.name "<YOUR NAME>"
❯ git config --global user.email <YOUR EMAIL>
❯ git clone https://github.com/<YOUR GITHUB ID>/microservices-demo.git
❯ cd microservices-demo

  • 必要な GCP のサービスを有効に

  ❯ gcloud services enable cloudbuild.googleapis.com sourcerepo.googleapis.com containerregistry.googleapis.com container.googleapis.com cloudtrace.googleapis.com cloudprofiler.googleapis.com logging.googleapis.com compute.googleapis.com

  • Container Registry を Docker registry として利用するために、gcloud を Docker 認証ヘルパーとして登録

  ❯ gcloud auth configure-docker -q

アプリケーションのデプロイ

GKE クラスタを作成し、アプリケーションをデプロイします。 

  • GKE クラスタを作成

  ❯ gcloud container clusters create demo --enable-autoupgrade --enable-autoscaling --min-nodes=3 --max-nodes=10 --num-nodes=5 --zone=asia-northeast1-a
❯ kubectl get nodes
NAME                                  STATUS   ROLES    AGE   VERSION
gke-demo-default-pool-31dcfbba-02j8   Ready    <none>   17h   v1.13.11-gke.14
gke-demo-default-pool-31dcfbba-bw3r   Ready    <none>   17h   v1.13.11-gke.14
gke-demo-default-pool-31dcfbba-hx3f   Ready    <none>   25h   v1.13.11-gke.14
gke-demo-default-pool-31dcfbba-n21g   Ready    <none>   25h   v1.13.11-gke.14
gke-demo-default-pool-31dcfbba-t4b5   Ready    <none>   25h   v1.13.11-gke.14

  • アプリケーションのビルドとデプロイ : skaffold を使用し、1 コマンドで、ビルドからデプロイメントまで行います。(全てのサービスをビルドするので、30 分程度かかります。)

  ❯ skaffold run -p gcb --default-repo=gcr.io/<YOUR PROJECT ID>
❯ kubectl get services
NAME                    TYPE           CLUSTER-IP     EXTERNAL-IP    PORT(S)      AGE
adservice               ClusterIP      10.7.240.120   <none>         9555/TCP      100m
cartservice             ClusterIP      10.7.246.125   <none>         7070/TCP      100m
checkoutservice         ClusterIP      10.7.255.114   <none>         5050/TCP      100m
currencyservice         ClusterIP      10.7.245.160   <none>         7000/TCP      100m
emailservice            ClusterIP      10.7.242.238   <none>         5000/TCP      100m
frontend                ClusterIP      10.7.241.1     <none>         80/TCP      100m
frontend-external       LoadBalancer   10.7.252.1     35.200.98.25   80:32213/TCP   100m
kubernetes              ClusterIP      10.7.240.1     <none>         443/TCP      107m
paymentservice          ClusterIP      10.7.250.63    <none>         50051/TCP      100m
productcatalogservice   ClusterIP      10.7.241.118   <none>         3550/TCP      100m
recommendationservice   ClusterIP      10.7.253.135   <none>         8080/TCP      100m
redis-cart              ClusterIP      10.7.253.110   <none>         6379/TCP      100m

  • ブラウザを起動し、fronted-external の EXTERNAL-IP にアクセスし、アプリケーションが正常に動作していることを確認

f06

  • Cloud Build のログを確認

f07
f08

  • Container Registry にあるビルドされたコンテナを確認

f09
f10
f11

ソースコードの修正

ソースコードを修正し、GKE クラスタにアプリケーションを再度デプロイします。

  • microservices-demo/src/frontend/templates/header.html の <header> を修正し、再ビルド

  ❯ git diff
diff --git a/src/frontend/templates/header.html b/src/frontend/templates/header.html  
index 62444cf..17d6e65 100644                                                         
--- a/src/frontend/templates/header.html                                              
+++ b/src/frontend/templates/header.html                                              
@@ -14,7 +14,7 @@                                                                     
         <div class="navbar navbar-dark bg-dark box-shadow">                          
             <div class="container d-flex justify-content-between">                   
                 <a href="/" class="navbar-brand d-flex align-items-center">          
-                    Hipster Shop                                                     
+                    CloudNative Shop                                                 
                 </a>                                                                 
                 {{ if $.currencies }}                                                
                 <form class="form-inline ml-auto" method="POST" action="/setCurrency"
 id="currency_form">                                                                  
❯ skaffold run -p gcb --default-repo=gcr.io/<YOUR PROJECT ID>

  • ブラウザを起動し、frontend-external の EXTERNAL-IP にアクセスし、Header 部分が変わっていることを確認

f12

  • Build ログの確認

f13
f14

  • コンテナの確認

f15
f16
f17

レプリケーションとオートヒーリング

Kubernetes の特徴は「アプリケーションのあるべき姿」を設定ファイル(yaml ファイル)で宣言できるという事です。障害があった場合でも、設定ファイルに書いたとおりのインフラを維持(オートヒーリング)するように設計されています。ここでは、adservice サービスに障害が起きたとき、正しくオートヒーリングするか確認します。また、Node がダウンした場合でも影響を与えたくない frontend サービスにはレプリケーションの設定を行います。 

  • クラスタ環境の確認

  ❯ kubectl get nodes; kubectl get pods; kubectl get deployments
NAME                                  STATUS   ROLES    AGE     VERSION
gke-demo-default-pool-f11743f4-3sqz   Ready    <none>   9m21s   v1.13.11-gke.14
gke-demo-default-pool-f11743f4-k407   Ready    <none>   9m21s   v1.13.11-gke.14
gke-demo-default-pool-f11743f4-nmms   Ready    <none>   9m22s   v1.13.11-gke.14
gke-demo-default-pool-f11743f4-vpr3   Ready    <none>   9m20s   v1.13.11-gke.14
gke-demo-default-pool-f11743f4-w32q   Ready    <none>   9m21s   v1.13.11-gke.14
NAME                                     READY   STATUS    RESTARTS   AGE
adservice-98447d4c5-77tnm                1/1     Running   0          2m22s
cartservice-5c67bcf9cd-9z8nf             1/1     Running   2          2m21s
checkoutservice-d98558fd4-fqtnp          1/1     Running   0          2m21s
currencyservice-6bc9cdf975-7mxfz         1/1     Running   0          2m21s
emailservice-56858878b9-dc688            1/1     Running   0          2m20s
frontend-56cc98d94f-c6bnq                1/1     Running   0          2m20s
loadgenerator-7f6885986-r5kz2            1/1     Running   4          2m19s
paymentservice-7774b87dc-6zbfr           1/1     Running   0          2m19s
productcatalogservice-59cdb4dfb-t8w8g    1/1     Running   0          2m19s
recommendationservice-765499f89f-wl4gd   1/1     Running   0          2m19s
redis-cart-85589759fc-qdvm2              1/1     Running   0          2m18s
shippingservice-c9f7f88ff-q62rb          1/1     Running   0          2m18s
NAME                    READY   UP-TO-DATE   AVAILABLE   AGE
adservice               1/1     1            1           5h22m
cartservice             1/1     1            1           5h22m
checkoutservice         1/1     1            1           5h22m
currencyservice         1/1     1            1           5h22m
emailservice            1/1     1            1           5h22m
frontend                1/1     1            1           5h22m
loadgenerator           1/1     1            1           5h22m
paymentservice          1/1     1            1           5h22m
productcatalogservice   1/1     1            1           5h22m
recommendationservice   1/1     1            1           5h22m
redis-cart              1/1     1            1           5h22m
shippingservice         1/1     1            1           5h22m

  • Replica の設定: kubectl scale を使用するには、--replicas フラグを設定して新しいレプリカ数を指定します。たとえば frontend を 3 つのレプリカにスケーリングするには、次のコマンドを実行します。

  ❯ kubectl scale deployment frontend --replicas 3
deployment.extensions/frontend scaled
❯ kubectl get deployments                                                                       
NAME                    READY   UP-TO-DATE   AVAILABLE   AGE
adservice               1/1     1            1           5h26m
cartservice             1/1     1            1           5h26m
checkoutservice         1/1     1            1           5h26m
currencyservice         1/1     1            1           5h26m
emailservice            1/1     1            1           5h26m
frontend                3/3     3            3           5h26m
loadgenerator           1/1     1            1           5h26m
paymentservice          1/1     1            1           5h26m
productcatalogservice   1/1     1            1           5h26m
recommendationservice   1/1     1            1           5h26m
redis-cart              1/1     1            1           5h26m
shippingservice         1/1     1            1           5h26m

  • コンソールからも設定可能: [Kubernetes Engine] - [ワークロード] で Replica の設定を行いたいサービスを選択し、 [操作] - [スケール] を選択し Replica 数を設定します。

f18

  • クラスタの状態を監視: Cloud Shell で、Ctrl + b → % キーを押し、セッションウィンドウを分割し分割したウインドウで下記コマンドを実行します。(移動は Ctrl + b → o 、解除は Ctrl + b → x です。)

  ❯ watch -n1 "kubectl get Node; kubectl get pods; kubectl get deployment; kubectl get hpa"
NAME                                  STATUS   ROLES    AGE   VERSION
gke-demo-default-pool-31dcfbba-02j8   Ready    <none>   12h   v1.13.11-gke.14 
gke-demo-default-pool-31dcfbba-bw3r   Ready    <none>   12h   v1.13.11-gke.14 
gke-demo-default-pool-31dcfbba-hx3f   Ready    <none>   20h   v1.13.11-gke.14 
gke-demo-default-pool-31dcfbba-n21g   Ready    <none>   20h   v1.13.11-gke.14 
gke-demo-default-pool-31dcfbba-t4b5   Ready    <none>   20h   v1.13.11-gke.14 
NAME                                     READY   STATUS    RESTARTS   AGE     
adservice-6ddc9946c8-bdmqb               1/1     Running   0          11h     
cartservice-586ff4f58f-2hf8h             1/1     Running   0          11h     
checkoutservice-7f65db74db-q4zxf         1/1     Running   0          11h     
currencyservice-85974f87bd-9xg6h         1/1     Running   1          11h     
emailservice-584b5f69f8-t94gk            1/1     Running   0          11h     
frontend-6c6b8fdbf-5mjsd                 1/1     Running   0          2m54s   
frontend-6c6b8fdbf-7jsfx                 1/1     Running   0          2m54s   
frontend-6c6b8fdbf-fnt4x                 1/1     Running   0          11h     
loadgenerator-7475f6d475-j65ln           1/1     Running   0          11h     
paymentservice-99b7787bb-j5xwg           1/1     Running   0          11h     
productcatalogservice-74df8697c-gggs2    1/1     Running   0          11h     
recommendationservice-7cd77d46b9-lz6bt   1/1     Running   0          11h     
redis-cart-6d689df55-v4dlv               1/1     Running   0          11h     
shippingservice-7ffd8d5db8-f75t4         1/1     Running   0          11h     
NAME                    READY   UP-TO-DATE   AVAILABLE   AGE                  
adservice               1/1     1            1           19h                  
cartservice             1/1     1            1           19h                  
checkoutservice         1/1     1            1           19h                  
currencyservice         1/1     1            1           19h                  
emailservice            1/1     1            1           19h                  
frontend                3/3     3            3           19h                  
loadgenerator           1/1     1            1           19h                  
paymentservice          1/1     1            1           19h                  
productcatalogservice   1/1     1            1           19h                  
recommendationservice   1/1     1            1           19h                  
redis-cart              1/1     1            1           19h                  
shippingservice         1/1     1            1           19h                  
No resources found.

  • オートヒーリングのテスト: 元のウインドウに戻り(Ctrl + b → o)、Pod が落ちたときでも、自動的に新しくコンテナを作成されることを確認します。(分割ウインドウの状態を確認)

  ❯ kubectl delete pod <adservice POD NAME>

  • オートヒーリングのテスト: Node が落ちたときでも、自動的に Node が再起動されることを確認します。(分割ウインドウを確認)

  ❯ kubectl describe pod <adservice pod name> | grep Node
Node:               gke-demo-default-pool-f11743f4-7ddf/99.99.99.99
Node-Selectors:  <none>
❯ kubectl delete Node <NODE NAME e.g. gke-demo-default-pool-f11743f4-7ddf>

  • adservice とサイト全体の状態をブラウザで確認: adservice は ページ下部に広告を表示するサービスです。adservice の Pod や Node が落ちると、一時的に広告が表示されなくなりますが、サイト全体は落ちません。また、オートヒーリングにより、すぐに adservice が再作成され、広告も正常に表示されます。

f19
f20

オートスケーリング

Horizontal Pod Autoscaler (HPA) により、各サービスの CPU 使用率に応じて、Pod を自動的にスケールすることができます。ここでは、負荷がかかりやすい frontend サービスを自動的にスケールするように設定したいと思います。 

  • オートスケーリングの設定: kubectl autoscale を使用するときは、アプリケーションの最大レプリカ数と最小レプリカ数、CPU 使用率の目標を指定します。たとえば、レプリカの最大数を 6、最小数を 3 にして、CPU 使用率の目標を 50% に設定するには、下記コマンドを実行します。(オートスケーリングの設定を解除する場合は、kubectl delete hpa frontend)

  ❯ kubectl autoscale deployment frontend --max 6 --min 3 --cpu-percent 50
❯ kubectl get hpa frontend
NAME       REFERENCE             TARGETS   MINPODS   MAXPODS   REPLICAS   AGE
frontend   Deployment/frontend   3%/50%    3         6         3          48m

  • コンソールからも設定可能: [Kubernetes Engine] - [ワークロード] で autoscale の設定を行いたいサービスを選択し、 [操作] - [自動スケーリング] を選択し設定します。

f21

  • オートスケーリングのテスト: Apache Bench によるストレステストを行い、正しくオートスケールされるか確かめてみます。frontend サービスの CPU 使用率が 50% を超えたあたりから、pod 数が自動的に増加することを確認します。

  ❯ sudo apt-get install apache2-utils
❯ ab -n 50000 -c 500 http://<EXTERNAL-IP>/
This is ApacheBench, Version 2.3 <$Revision: 1757674 $> 
Copyright 1996 Adam Twiss, Zeus Technology Ltd, http://www.zeustech.net/ 
Licensed to The Apache Software Foundation, http://www.apache.org/       
                                                                         
Benchmarking 34.84.68.23 (be patient)                                    
Completed 5000 requests                                                  
Completed 10000 requests                                                 
Completed 15000 requests                                                
Completed 20000 requests                                                 
Completed 25000 requests

クリーンアップ

利用したリソースを今後利用しない場合は、課金を避けるためにも削除しましょう。 

  • アプリケーションを削除する場合: skaffold run コマンドを使ってデプロイした場合は、skaffold delete コマンドで、デプロイしたアプリケーションをクリーンアップすることができます。kubectl apply -f [...] コマンドを使ってデプロイした場合は、kubectl delete -f [...] コマンドで、デプロイしたアプリケーションをクリーンアップしてください。

  ❯ skaffold delete
Cleaning up...
 - deployment.apps "adservice" deleted
 - service "adservice" deleted
 - deployment.apps "cartservice" deleted
 - service "cartservice" deleted
 - deployment.apps "checkoutservice" deleted
 - service "checkoutservice" deleted
 - deployment.apps "currencyservice" deleted
 - service "currencyservice" deleted
 - deployment.apps "emailservice" deleted
 - service "emailservice" deleted
 - deployment.apps "frontend" deleted
 - service "frontend" deleted
 - service "frontend-external" deleted
 - deployment.apps "loadgenerator" deleted
 - deployment.apps "paymentservice" deleted
 - service "paymentservice" deleted
 - deployment.apps "productcatalogservice" deleted
 - service "productcatalogservice" deleted
 - deployment.apps "recommendationservice" deleted
 - service "recommendationservice" deleted
 - deployment.apps "redis-cart" deleted
 - service "redis-cart" deleted
 - deployment.apps "shippingservice" deleted
 - service "shippingservice" deleted

  • クラスタごと削除する場合

  ❯ gcloud container clusters list
NAME                LOCATION           MASTER_VERSION  MASTER_IP     MACHINE_TYPE   NODE_VERSION    NUM_NODES  STATUS
standard-cluster-1  us-central1-a      1.13.11-gke.14  99.99.99.99   n1-standard-1  1.13.11-gke.14  3          RUNNING
❯ gcloud container clusters delete <CLUSTER NAME e.g. standard-cluster-1> --zone <ZONE NAME e.g. us-central1-a>
The following clusters will be deleted.
 - [standard-cluster-1] in [us-central1-a]

Do you want to continue (Y/n)?  y

Deleting cluster standard-cluster-1...done.
Deleted [https://container.googleapis.com/v1/projects/digital-heading-264207/zones/us-central1-a/clusters/standard-cluster-1].

  • プロジェクトごと削除する場合

  ❯ gcloud projects list
curious-athlete-264501  My Project 30444  858566370586
❯ gcloud projects delete <PROJECT NAME e.g. curious-athlete-264501>
Your project will be deleted.
Do you want to continue (Y/n)?  Y
Deleted [https://cloudresourcemanager.googleapis.com/v1/projects/curious-athlete-264501].
You can undo this operation for a limited period by running the commands below.
    $ gcloud projects undelete curious-athlete-264501

いかがでしょうか。マイクロサービスの開発、ビルド、デプロイ、運用を体験できたでしょうか。本来のマイクロサービスアプリケーションは、もっと大規模なものになるとは思いますが、少しでも実感が湧いてもらえればと思います。