GCP の Microservices demo を GKE で動かしてみる

今年の初めに Google Cloud からマイクロサービスアーキテクチャのデモアプリを GCP にデプロイするハンズオンが出てました。

cloud.google.com

Hipster Shop という EC サイトのデモアプリケーションを fork して使用します。

github.com

ベースは2年ぐらい前のコードですが、メンテナンスされ続けている模様です。以下のマイクロサービスから構成されています。

micro service description
adservice Java で書かれた アドサービス
cartservice C# で書かれたカートサービス
checkoutservice Go で書かれたチェックアウトサービス
currencyservice Node.js で書かれた通貨換算サービス
emailservice Python で書かれたメールサービス
frontend Go で書かれた Web フロントエンド
paymentservice Node.js で書かれた支払いサービス
productcatalogservice Go で書かれた商品カタログサービス
recommendationservice Python で書かれたレコメンドサービス
shippingservice Go で書かれた出荷サービス

このように Multi language な MonoRepo になっています。やっぱ Go が多い。なお、loadgenerator という Python のサブプロジェクトがありますが、これは LOCUST を使った負荷テスト (ユーザの買い物に伴うリクエストを投げ続ける) のようです。

Locust - A modern load testing framework

Frontend を中心に各マイクロサービスと連携することで、買い物のサービスを提供します。マイクロサービス間の通信は gRPC で行います。

https://github.com/GoogleCloudPlatform/microservices-demo/raw/master/docs/img/architecture-diagram.png

https://github.com/GoogleCloudPlatform/microservices-demo/raw/master/docs/img/architecture-diagram.png
README の Architecture 図

各マイクロサービスは Kubernetes クラスターに Skaffold によりデプロイできる manifest が用意されています*1

GitHub Actions による CI も作られています。

microservices-demo/ci.yml at master · GoogleCloudPlatform/microservices-demo · GitHub

CI を実行するには GCP の VM に Self-hosted runner を立てて実行する必要があります。

microservices-demo/README.md at master · GoogleCloudPlatform/microservices-demo · GitHub

Kubernetes クラスターとしては kind を使って LOCUST を使ったテストを流しています。

github.com

以下ハンズオンにしたがってデプロイしていきます。

必要な GCP のサービス有効化は数分かかりました。

$ gcloud services enable cloudbuild.googleapis.com sourcerepo.googleapis.com containerregis
try.googleapis.com container.googleapis.com cloudtrace.googleapis.com cloudprofiler.googleapis.com logging.googleapis.com compute.g
oogleapis.com
Operation "operations/xxxxxxxxxxxxxxxxx" finished successfully.

ワーカーノード max 10 の GKE クラスターを作成。これは5分ぐらいで起動。作成時はノード数は5でした。

$ gcloud container clusters create demo --enable-autoupgrade --enable-autoscaling --min-nodes=3 --max-nodes=10 --num-nodes=5 --zone=asia-northeast1-a

:
Creating cluster demo in asia-northeast1-a... Cluster is being health-checked (master is healthy)...done.
kubeconfig entry generated for demo.
:

$ kubectl get nodes
NAME                                  STATUS   ROLES    AGE   VERSION
gke-demo-default-pool-c6ce71ca-3185   Ready    <none>   30s   v1.14.10-gke.27
gke-demo-default-pool-c6ce71ca-d7h0   Ready    <none>   30s   v1.14.10-gke.27
gke-demo-default-pool-c6ce71ca-j1t7   Ready    <none>   28s   v1.14.10-gke.27
gke-demo-default-pool-c6ce71ca-rdxq   Ready    <none>   27s   v1.14.10-gke.27
gke-demo-default-pool-c6ce71ca-sxgl   Ready    <none>   29s   v1.14.10-gke.27

skaffold を使ってアプリをデプロイ。Java や Node.js や Go のプログラムのビルドとコンテナイメージ作成をしているのでフルビルドだとそれなりに待ちます*2

$ skaffold run -p gcb --default-repo=gcr.io/<YOUR PROJECT ID>

Pod や Service は default namespace にデプロイされました。

$ kubectl get po,svc
NAME                                         READY   STATUS    RESTARTS   AGE
pod/adservice-649b679899-x9b8d               1/1     Running   0          3m52s
pod/cartservice-5c8bcb96b-5pwx7              1/1     Running   2          3m51s
pod/checkoutservice-777768cbf8-n6t8v         1/1     Running   0          3m51s
pod/currencyservice-85dc68bfbb-2rwzt         1/1     Running   0          3m50s
pod/emailservice-5d79bd9fd6-tjpt7            1/1     Running   0          3m50s
pod/frontend-74f6c656df-hzfmw                1/1     Running   0          3m50s
pod/loadgenerator-7cb8bdb989-vsb46           1/1     Running   4          3m49s
pod/paymentservice-795fb7654b-p576r          1/1     Running   0          3m49s
pod/productcatalogservice-57466c6bd7-jwrbp   1/1     Running   0          3m49s
pod/recommendationservice-649f74ff78-6tp5m   1/1     Running   0          3m49s
pod/redis-cart-7b6f64b5cd-p79nc              1/1     Running   0          3m48s
pod/shippingservice-6ff68f9b69-4jtxh         1/1     Running   0          3m48s
NAME                            TYPE           CLUSTER-IP     EXTERNAL-IP     PORT(S)        AGE
service/adservice               ClusterIP      10.7.247.68    <none>          9555/TCP       3m51s
service/cartservice             ClusterIP      10.7.252.157   <none>          7070/TCP       3m51s
service/checkoutservice         ClusterIP      10.7.247.183   <none>          5050/TCP       3m51s
service/currencyservice         ClusterIP      10.7.251.225   <none>          7000/TCP       3m50s
service/emailservice            ClusterIP      10.7.246.34    <none>          5000/TCP       3m50s
service/frontend                ClusterIP      10.7.251.19    <none>          80/TCP         3m50s
service/frontend-external       LoadBalancer   10.7.241.65    35.xxx.xxx.xx   80:32118/TCP   3m50s
service/kubernetes              ClusterIP      10.7.240.1     <none>          443/TCP        14m
service/paymentservice          ClusterIP      10.7.252.240   <none>          50051/TCP      3m49s
service/productcatalogservice   ClusterIP      10.7.253.164   <none>          3550/TCP       3m49s
service/recommendationservice   ClusterIP      10.7.254.110   <none>          8080/TCP       3m49s
service/redis-cart              ClusterIP      10.7.253.45    <none>          6379/TCP       3m48s
service/shippingservice         ClusterIP      10.7.252.132   <none>          50051/TCP      3m48s

frontend-external の EXTERNAL-IP にアクセスしたらアプリに接続できました。

f:id:kondoumh:20200430162730p:plain

Container Registry を確認すると push 済みの image が並んでいます。

f:id:kondoumh:20200430163255p:plain

カートに商品を入れてみて通貨換算が機能しているのも確認できます。

f:id:kondoumh:20200430164153p:plain

f:id:kondoumh:20200430164210p:plain

この後、コードの修正とビルド・再デプロイや Kubernetes の機能を活かしたオートヒーリングやオートスケーリングの動作を確認するというハンズオンが続きます。

商品をカートに入れてオーダーして出荷という一連の処理をした後にログを確認してみました。

f:id:kondoumh:20200430170745p:plain

Kubernetes のログもちゃんと Web UI で取れますね。kubectl logs <Pod name> でも取れますが、大量になるのでプラットフォームにインテグレートされているのはいいことです。

以上、Microservices デモを GKE にデプロイして動かしてみました。frontend の Go は 1.12 とちょっと古いですが、マイクロサービスなのでマイグレーションも楽そうです。gRPC のサンプルとしても良さそうですね。

Argo CD を導入して GitOps の素振りなどにも使えそうです。

blog.kondoumh.com

*1:デプロイについては、kustomize の方が主流になっていく気がしますが。

*2:ハンズオンには30分かかると書いてありますが、そこまではかかりませんでした。