【連載 第7回】クレジットカードのインフラ作ってみた

どうもSREのid:renjikariです。この記事はfreeeカード Unlimited の開発の裏側について紹介する連載の第7回目になります。

私は直近でfreeeカード UnlimitedのStaging&Production向けのインフラ構築などを担当していました。(id:nekottyo が検証用アカウント作成&整備や検証環境作成といった下地作りをしてくれてました:ty:)

最近ベータリリースを果たしまして実際にお客様がクレジットカードで決済を通せるようになりました。感激ぃ!

さて、このdevelopersブログでぜひインフラについて書いてほしいという依頼を受けまして嬉しい限りなんですが、実のところインフラについて言えば他のfreeeのサービスと大きく違うところはあまりなく、(blogに書いて自慢できるほどではないのですが)freeeでつくっているインフラ構成の一つとしてfreeeカード Unlimitedの裏側を紹介しようかと思います。

freeeカード Unlimitedは子会社での開発のためAWSアカウントがそのほかの自社サービスと別なためインフラ構築についてはクロスアカウント対応に苦労したというところがあるので、それについては知見をかけたらと思っています。

AWS EKSを利用したサービス構成

freeeカード UnlimitedはComputingにAWS EKSを利用しています。まずは概略図を示します。

f:id:renjikari:20211019143513p:plain
構成概略図

これは実際のものとは違いますが似たような構成のサービス群になっています。 freeeカード Unlimitedでは1つのEKSクラスターにweb/カード管理/決済/請求/通知など複数のサービスが乗っているマイクロサービスになっています。 それぞれのサービスにはHTTP(S)で外部から通信するものとクラスター内でRPC通信するものがあります。 自社の他サービスとも連携する必要があり、それは別のEKSクラスター上に存在するサービスと通信する形となっています。

サービスの構成についてもう少し詳しく書くために、一つのサービスを抜き出して少しだけ詳細に書いた図を書きます。

f:id:renjikari:20211019143624p:plain
サービス詳細図

一つのサービスはAWS ALBのロードバランサーで通信を受けたあと、基本的にEnvoy Proxyを通ってサービスのDeployment(Pod)に到達する構成になっています。Envoyをかませてサービスへ通信させるような構成はサービスメッシュぽさがありますが、freeeでは外部からの通信がある商用サービスにおいてIstioを始めとするサービスメッシュを利用した事例がまだ存在せず、このfreeeカード Unlimitedで初めて運用にのせるのはハードルが高かったので採用していません。freeeの各サービスで同じ構成をとっているので社内での標準化のためにもこの構成になっています。 他にもウェブアプリケーションにおいて標準的な構成ではありますが非同期的な処理にはSNS+SQSをCronJobから呼び出したりしています。非同期通信については連載第2回で詳しく書かれていますのでそちらをご参照ください。 また、詳細は省きますが協力会社様との情報のやりとりにS3などを利用したりしています。

ここまで出てきたAWSリソースやKubernetesについてのInfrastructure as Codeについても紹介します。 EKS含むすべてのAWSリソースはTerraformによってコード化されています。中でもEKSの構築にはTerraformのmumoshu/terraform-provider-eksctlを利用しています。これ以外にもAWSのprovider以外のものを利用していくつかの初期設定などを行っています(ex. EKS構築時のaws-authの設定) Kubernetes内のリソースについてはhelm + helmfileでtemplate化しており、ArgoCDによってGitOpsを利用したデプロイを行っています。また、freeeカード Unlimitedだけの話ではなく社内での標準化の話ですが、helmによる社内向けの共通チャート(ex. http-server/grpc-server/application-worker)などを用意しており、Docker Imageのrepositoryやtag、環境変数などのいくつかのvaluesを入力するだけで使えるようなものが用意されています。これによって(SRE以外のアプリケーションエンジニアでも)簡単にアプリケーションを動かせるだけでなく、社内の各サービスごとにmanifestを共通化できSREの運用を楽にしています。

そろそろ話が広がってきたのでマイクロサービスアーキテクチャの章に移りましょう。

マイクロサービスアーキテクチャの採用

freeeカード Unlimitedは 連載第一回の記事でも紹介されています通りgRPCを利用してマイクロサービスアーキテクチャになるよう設計されています。 コード上についてはすでに上記の記事で解説されているので、この章ではインフラ周りについて触れます。

さて、マイクロサービスという言葉が使われるようになってからはすでに久しいですが、freeeでも様々なマイクロサービスが存在しています。 ただし多くのものは大きなモノリスなサービスから一部を切り出したり、新規機能を別サービスとして切り出したりするような構成になっています。 今回のfreeeカード Unlimitedはかなり大きなサービスでありながら最初からマイクロサービスとしてインフラ的に各々が切り離された構成をとっているfreeeにとっての初めてのサービスになったと思います。そういった意味で良い挑戦でした。(とはいえ一つのサービスをどこからどこまでと決めるのは難しいのですでにマイクロサービスと言っても過言ではないサービスはあったというエクスキューズを書いておきます)

マイクロサービス構成をとるにあたってインフラ的にいくつかの選択肢がでてきたところがサービス間の通信設計でした。 再度各サービスの図を貼りますが、

f:id:renjikari:20211019143513p:plain
構成概略図

freeeカード Unlimited外部からの通信は基本的にHTTP(S)でおこないます。考える余地があったのはサービス間のEKS cluster内部の通信で、結果的には(前述のように)すべてのサービスの前段にEnvoy Proxyをおいて、cluster内部のRPC通信は全てEnvoy経由にしました。 他の案としてはマイクロサービスAからマイクロサービスBへK8sのkind:Serviceむけに直接通信する/毎回cluster外にでてAWS ALB経由で通信するというものもあったのですが、以下の理由でEnvoy経由に決定しました。 ① Envoyであれば負荷分散しやすい(Service向けに直接通信する場合HTTP2のコネクションが永続化されるため負荷分散に向いていない) ② 他のサービスの構成を踏襲したい

クロスアカウント

最後にクロスアカウント対応について話します。 とても複雑というわけでは無いのですが、多くの構築作業時にクロスアカウントの対応が必要であり作業が大変でした。 freeeカード Unlimitedがクロスアカウントで連携している図を載せておきます。ここに乗っているのは一部のサービスであり、また詳細は省略されています。

f:id:renjikari:20211019153739p:plain
クロスアカウント連携図

どんなところでクロスアカウントの対応が必要だったかというところを箇条書きにまとめて書きまして、最後の知見共有とします。

  • freeeカード Unlimitedのサービスと他サービスの通信で、以下の対応が必要
    • VPC Peering(transit gatewayにしたい…)
    • Peering ~ SubnetのRoute設定
    • SecurityGroupの設定
  • internal DNSの権限移譲
  • Deploy(Argo CD)Cluster とのクロスアカウントIAMにおいてaws-auth設定
    • Argo CDからKubernetes APIが叩けるようにするための設定
  • 監査対応(詳細省略)

さいごに

冒頭で書くことは特に無いとか言った割に長々と書いた気がします。 自身でもまさかクレジットカード事業のインフラを担当する日が来るとは思わなかったので時間的な制約などもありましたが、プロジェクトに参加できてよかったです。

この記事でも詳細には言及できなかったところもあるので、また機会があったら書こうと思います。とくにArgoCDやCDまわりについては、Cloud Native Days Tokyo にて登壇予定ですので興味があればそちらも合わせてどうぞ(宣伝)

freeeのSREでは一緒にはたらく仲間を募集しています https://freeecommunity.force.com/jobs/s/detail/a4l1000000170inAAA?_ga=2.14218231.1353744525.1634048794-37020062.1554095000