Share
Embed
メルペイのマイクロサービスの構築と運用 / CloudNative Days Tokyo2019
メルペイのマイクロサービスの構築と運用
2019.07.22 に CloudNative Days Tokyo2019 で発表した内容です。
なぜメルペイがマイクロサービスアーキテクチャを選択したか、メルペイのマイクロサービスの構築と運用をどのように行ったか、などを話しました。
tjun
July 22, 2019
Transcript
64 slides
-
メルペイにおける マイクロサービス 構築と運用 CloudNative Days Tokyo 2019 Merpay SRE @tjun
Junichiro Takagi https://speakerdeck.com/tjun/cloudnative-days-tokyo2019 -
メルペイ マイクロサービス概要 メルペイ マイクロサービス 構築と運用 課題と今後 01 02 03 3
Agenda おまけ: 実際に起きた問題を紹介 04 -
メルペイ概要 年 月 非接触型サービス「 」に対応 年 月 複数回 お買い物をあとからまとめて支払える 「メルペイあと払い」開始
年 月 サイトでも「メルペイ」が利用できる ネット決済提供開始 年 月 大手チェーンや中・小規模店舗で ・バーコード決済に対応 全国135万か所 iD コード払い あと払い ネット決済 -
メルペイ サービス マイクロサービスアーキテクチャ 40以上 マイクロサービス 2019 3Qで 1444億円以上を取り扱うメ ルカリ 決済基盤(US
メルカリ事業も含む数字 ) 200万人以上 利用者 (メルペイ「電子マネー」 登録を行ったユーザー 累計。 コード払い 除く ) -
Why microservices? メルペイ 複数 サービスを短期間で立ち上げるため Focus on single service 各マイクロサービス
機能に集中して開発 Independent releases 独立した開発・リリース サイクル Team independence 組織を拡大しながら 複数 機能を同時に開発 -
マイクロサービス そ 他 メリット Resilience 障害が局所化すること で可用性が高まる Scalability & Flexibility
独立したリソース管理が可能 ストレージも独立 -
メルペイ マイクロサービスで やっていないこと マイクロサービス単位で 自由な技術選択 自由な技術選択 例 自由な言語、好きなデータベース Why? •
共通 ツール・ライブラリを利用することで、開発や運用 度や品質を高めるため • チーム間 情報共有や人 移動を可能にするため -
アーキテクチャ API Gateway Authority API Service X API Service Y
Google Cloud Load Balancer Service A Service B Google Kubernetes Engine Service C Web Service Z Cloud Spanner Project A Cloud Spanner Cloud Pub/Sub Project B Project GKE -
API Gateway Authority API Service X API Service Y Google
Cloud Load Balancer Service A Service B Google Kubernetes Engine Service C Web Service Z Cloud Spanner Project A Cloud Spanner Cloud Pub/Sub Project B Project GKE 共通 GKEクラスタ 3 1 2 個別 Project レイヤーアーキテクチャ -
Google Kubernetes Engine Kubernetes マイクロサービス 実行基盤・オーケストレーション - 自己修復性 あるReplication Controller
- ServiceによるLoad Balancing - DeploymentによるRollout/Rollback - Horizontal Pod Autoscalerによるスケールアウト - Kubernetes 自体 拡張性やエコシステム 早く構築し、安定して運用するためにGKEを利用 -
マイクロサービス on Google Kubernetes Engine すべて マイクロサービスが同じClusterに乗っている - Cluster自体 Platform
Teamが構築・運用 - Namespace内を各チームが開発・運用 Google Kubernetes Engine Namespace: service-a Container A Container A Container A Namespace: service-b Container A Container A Container B -
マイクロサービス on Google Cloud Platform • 1つ マイクロサービスが1つ GCP Projectを持つ
• 各 Project 中に Spanner や Pub/Sub などを作成 • 権限設定したService Account を Kubernetes Secretに配置 • Terraformで管理 CircleCI Project A Cloud Spanner Cloud Pub/Sub GitHub Terraform Code Project B Cloud Spanner Big Query -
マイクロサービス 階層構 アプリ、加盟店等 パートナー様 全て リクエストが を通る 共通処理とルーティング サービス クライアントから
リクエストとレスポンス 責任を持つ 裏側にある複数 マイクロサービス アグリゲーション サービス 機能 ロジックを実現する Backend Service API Gateway API Service Client -
メルペイ マイクロサービス 例 iD決済を実現する流れ API-Gateway NFC-api NFC-service payment- service リクエスト
認証と ルーティング clientへ返すため response 作成 NFC決済を実現する ため 処理 共通 決済処理 -
API Gateway • Goで書かれたマイクロサービス • リクエストを各マイクロサービスへルーティングする 共通 リクエスト処理をAPI Gateway と
Cloud Load Balancerで実現 • TLS termination • DDoS protection • Request buffering • Authマイクロサービスを利用したAuthN/AuthZ -
開発組織とマイクロサービス 各機能を実現する マイクロサービス開発チーム • バックエンドエンジニア • フロントエンドエンジニア • iOS/Androidエンジニア •
デザイナー • PM 共通基盤とサービス全体を 見る横串チーム • SRE • アーキテクトチーム • Microservices Platformチーム • Data platformチーム • ソリューションチーム -
メルペイ マイクロサービス開発で 気をつけていること 一貫性 • データ 一貫性 • リトライと冪等性 •
リコンサイル 信頼性 • Go template projectやlibraryによる 標準化 • Production Readiness checklist • DesignDoc • 権限管理 -
メルペイ マイクロサービス開発で 気をつけていること 一貫性 • データ 一貫性 • リトライと冪等性 •
リコンサイル 信頼性 • Go template projectやlibraryによる 標準化 • Production Readiness checklist • DesignDoc • 権限管理 -
マイクロサービスにおける一貫性 分散システムにおけるデータ 一貫性 担保 難しい • 決済トランザクションが複数サービスをまたがる • DBへ 書き込みや外部サービスへ
接続が分散している • どこかで処理が失敗しても、全体として一貫性が必要 冪等性 • リトライしても二重に処理されず、正しく動く 詳しく メルカリtech blog 記事を参照 - マイクロサービスにおける決済トランザクション管理 - メルペイにおけるお客さま残高 管理手法 -
マイクロサービスにおける一貫性 リコンサイル • 本当にデータ整合性が取れている か? • 不整合を見つけて修正する必要がある メルペイで • バッチ処理によるリコンサイル
• 非同期な結果イベント通知によるリコンサイル によって不整合 チェックと修正を行っている -
メルペイ マイクロサービス開発で 気をつけていること 一貫性 • データ 一貫性 • リトライと冪等性 •
リコンサイル 信頼性 • Go template projectやlibraryによる 標準化 • Production Readiness checklist • DesignDoc • 権限管理 -
メルペイ マイクロサービスとGo ほとんど サービスがGoで書かれている(一部Node.js) マイクロサービス テンプレート • Liveness/ReadinessProbe対応、Graceful シャットダウンなど Kubernetes上で動かすために必要な機能を持つ
社内で開発した共通 Goライブラリ • Logging, 分散Tracing, クライアントサイド LoadBalancingなどに対 応 -
マイクロサービス レビュー DesignDoc 設計をアーキテクト、SRE、Security、関連マイクロサービス エンジニアがレビュー・議論する Production Readiness Checklist 本番リリース前に、Kubernetes yaml等で必要な設定が
されているか、運用 準備が十分かなどをチェックする 例: Horizontal Pod AutoscalerやPod Disruption Budget 設定 -
開発を加 する共通 仕組み Microservices platform 各チームがOwnershipを持ってサービスを構築・運用する • microservice-starter-kitによるマイクロサービス 初期化 •
Protocol Buffersによるサービス インターフェース 定義 共通化 • GCP上 リソース 全てTerraformで管理 • Kubernetes上 リソースをYAMLで管理 • 共通 デプロイフロー Platformをメルカリ Microservices platform teamが構築・運用 -
マイクロサービス 初期化 microservices-starter-kit という仕組みで自動化 • GCP Project 作成+Application用Service Account 作成、
開発者へ IAM権限 付与 • Kubernetes Namespace 作成+必要なRBAC&Secret 設定 GCP project for GKE Centralized cluster Namespace: Service A Service A RBAC: Team A -
GCPリソース 作成 • Cloud Spanner, Pub/Sub, Cloud Storage等 リソース •
すべてTerraformで作成・管理 CircleCI Cloud Spanner Cloud Pub/Sub GitHub Terraform Code Project B Cloud Spanner Big Query Project A -
Kubernetesリソース単体 デプロイ Manifest 単体をCircleCIからデプロイ - Job、Horizontal Pod Autoscalerなど YAML CircleCI
Google Kubernetes Engine yaml GitHub Namespace: service-a Container A Container A Container A Namespace: service-b Container A Container A Container B -
Microservicesアプリケーション デプロイ 必要なYAMLとImageを指定してSpinnaker経由でデプロイ CI Google Kubernetes Engine yaml Namespace: service-a
Container A Container A Container A Namespace: service-b Container A Container A Container B Cloud Build Container Registry code CI -
マイクロサービス 運用 大変 マイクロサービス 数が増えるだけ運用する要素が増える • 各マイクロサービス アプリケーション • 各マイクロサービスが利用するリソース(データベース等)
• マイクロサービス間 通信 運用 手間を減らす仕組み • マイクロサービス 構成をできるだけ揃える • Kubernetes によるオートスケールや自己修復 • Managedなクラウドサービス それでもさまざまなところで問題 起きる -
マイクロサービス 運用体制 マイクロサービスで 各チームが担当マイクロサービスを運用 • 元から運用経験があるエンジニア 多くない Google Kubernetes Engine
Container A Container A Container A Cloud Spanner Project A Container A Container A Container B Cloud Spanner Project B Cloud Pub/Sub -
マイクロサービス運用で気をつけていること SLOを設定する • サービスが正常な状態を各サービスで定義する • アラートをしたり問題を修正したりする判断 基準 Observability • Metrics問題が起きたときに調査する&問題が起きる前に気づく
• 分散Tracing: リクエスト どこで時間がかかっているか -
SLO(Service Level Objective) 運用を考えると出てくる疑問例 • 自分たち サービス 今正常な か? •
自分たち サービス 遅い?一部 お客さまに対してだけ遅い? • CPU使用率が一瞬上がっていたが、問題ない か? SLO • 可用性、レイテンシなどシステム 信頼性 目標値 • SLOを定義することで、自分たち サービスが正常な か、Alertする か、何を修正・改善するか 判断ができる 例: あるAPI で 最低でも99.99% リクエストが 5xx以外を返す -
Observability Microservicesで 、1リクエストが複数 マイクロサービスを経由 する • どこでどれだけ時間がかかっている か • なぜ時間がかかっている
か、どんなエラーが出ている か • 各マイクロサービス SLOを満たしている か Metrics, Trace, Logをサービス横断して見られるようにすることで、 問題 特定がスムーズにできる -
監視体制 Datadogに集約してTimeboardやAPM、Monitor 機能を利用 Google Kubernetes Engine Container A Container A
Container A Cloud Spanner Project A Go, gRPC, Docker, Kubernetes メトリクス GLB, Spanner, Pub/Sub, Stackdriver Logging 等 メトリクス -
ここまで まとめ メルペイで • 短期間で サービスリリースを実現するため マイクロサービスアーキテクチャを採用 • 共通化された開発・運用 Platformがある
• Platform 上で、各チームがOwnershipを持って開発運用 • 一貫性と信頼性を実現するため、各マイクロサービス アプリケーション上や開発運用 プロセスでさまざまな 仕組みを作っている -
開発・運用で出てきた課題 一部 マイクロサービスがモノリス化する • 機能をど マイクロサービスに実装するか、判断が難しいことがある • 1つ マイクロサービスにさまざまなビジネスロジックが集まってしまう QAが難しい
• ど マイクロサービス ど バージョン 組み合わせな か • リリース以前 開発環境 どこかが壊れている状態だった 運用と開発 リソース 調整 • 開発が落ち着いてきたけど運用が続くサービスもあれ 、これから 開発が活発になるサービスもある -
メルペイ マイクロサービス 今後 リリースを振り返って • サービス 信頼性を高めて運用負荷を下げる改善中 今後に向けて • さらに広く使われるメルペイを目指して、引き続きさまざま機能を
企画・開発しています • バックエンド、SREなど各職種で採用してます! Go、Microservice、Kubernetes、GCPやりたい人 ご連絡ください -
[1] Deploy時にリクエスト 一部がエラー まずやること • Graceful Shutdown • Readiness/Liveness 適切な設定
上記をやらないと、 • 消えていくPodが正しくリクエストを処理しない • 準備ができていないPodへリクエストが届く -
[1] Deploy時にエラーが出る まだ、Kubernetesで必ず起きる問題や、gRPCだから起きる 問題が残っていた • containers.lifecycle.preStop に sleepを入れる • terminationGracePeriodSeconds
を設定する • strategy.rollingUpdate.maxSurge を 100%にしない 等 設定を入れて、RollingUpdateをなめらかに行う -
[2] Ingress 再作成に失敗 前提 • メルペイで 、Ingress-GCEを利用 起きたこと • 開発環境
Ingressを作り直したところ ◦ External-IPが当たらない ◦ Backend-serviceが作られない ◦ 設定を少し変えると作成されることもある … ◦ ログに 何も出ていない -
[2] Ingress 再作成に失敗 原因 • GKE v1.10.6 (に含まれるIngress-GCE) バグだった 対策
$ kubectl apply -f merpay-ingress1.yaml $ kubectl apply -f merpay-ingress2.yaml $ kubectl apply -f merpay-ingress3.yaml -> OK $ kubectl apply -f merpay-ingress4.yaml -
[3] Ingress を追加したら既存 Ingressが 壊れた 起きたこと • 新しい用途 Ingressを追加したら、前から使っていたIngress (触ってない)方でリクエストが全てエラー
• 設定したい証明書と 違う証明書が設定されている 対応 • いろんな設定とログを調べたが全く分からず、 新しいIngressを 消すと問題が解消した • Ingress-controller ログが見られない… -
[3] Ingress を追加したら既存 Ingressが 壊れた 原因 • 2つ Ingress 設定を元に
同じ HTTPS proxy を交互に更新 していた • Namespace名+Ingress名 先頭55文字で区別しているため、 長くて似た名前で作っていたIngressがぶつかっていた • 実 ドキュメントに書いてある ◦ The total length of the namespace and name of an Ingress must not exceed 55 characters. -
[3] Ingress を追加したら既存 Ingressが 壊れた 対策 • Ingress 名前を短くした •
長い名前 Ingressを作れないようなLintを追加した -
[4] Podが減っていく… 起きたこと(イメージ) • 5つあった ず Podが3つになっている • 他 2つ
起動できずにRestartを繰り返している • 他 3つがRestartして起動できなくなる も時間 問題… 調査 • エラーが曖昧なも しか出せず、原因調査が難航 • 今動いているも を止めたくない で、ログを増やしたPodをデ プロイすることもできない -
[4] Podが減っていく… 原因 • 起動時 処理に必要な GCP APIが意図せずdisableされてい た •
Terraform Diffで出ていたが、レビューでそ 影響に気づけ ていなかった 対策 • Terraform 設定を修正して各サービスを更新 -
[5] Spannerへ リクエスト レイテンシが ときどき大きくなる 前提 • GKE上 Go アプリケーションからCloud
Spanner へ読み書き を行う 起きたこと • アプリケーションを動かしていると、数100ms-数秒かかるときが ときどき発生 -
[5] Spannerへ リクエスト レイテンシが ときどき大きくなる さまざまな原因 • クライアントライブラリgoogle-cloud-go 問題 •
Kubernetesクラスタ DNS 問題 • アクセストークン リフレッシュ 対策 • クライアントライブラリ 修正 • DNSをアプリケーション側でキャッシュ • アクセストークンをバックグラウンドで定期更新 -
[5] Spannerへ リクエスト レイテンシが ときどき大きくなる 詳細 メルカリ Tech Blog メルペイで
Spannerと 戦い 日々 で紹介しています。 -
最後に宣伝 Google Kubernetes Engine と Cloud Spanner について 2019.07.31 Google
Cloud Next Tokyo で発表します