Blog株式会社マネーフォワード公式開発者向けブログです。技術や開発手法、イベント登壇などを発信します。サービスに関するご質問は、各サービス窓口までご連絡ください。Appsを導入しましたこんにちは。マネーフォワードでインフラエンジニアとして働いているkappy(@kappyhappy)です。Appsのdeploy-botを紹介します。deploy-botが必要だったのかデプロイに使用しているコンポーネントdeploy-bot導入の経緯の説明の前に、デプロイのために使用しているコンポーネントとその用途を説明します。EKS上で稼働させています。我々は、複数サービスをEKSクラスタで稼働させる為に、いくつかの理由から1つのクラスタ上に複数のサービスを同居させるマルチテナント構成を採用しました。マルチテナント構成におけるマニフェスト管理の運用として、マニフェストファイルを単一のGitHubリポジトリに集約し、サービス単位でディレクトリを作成しています。Repository)」を分割しました。そのような環境でアプリケーションをデプロイするために、デプロイフローを以下のように定義しました。Repositoryに対して(デプロイするDockerイメージを変更する)PRを作成&アプルーブ&マージデプロイフローのイメージですstep1およびstep3の段階で開発者がPRを作成しアプルーブするというフローになっており、デプロイの度にPRのアプルーブ&マージを2回実施する必要があります。EKSでの運用開始直後は、このフローを手作業で実施していました。RepositoryにPRがマージされたらTEST環境に対しては自動でデプロイができるようになって欲しい」という要望をいただきました。そこで、上記の要望を実現するためにdeploy-botを作成することにしました。Appsという2つの選択肢がありました。Tokenを使用したdeploy-bot作成も可能性としてはありましたが、ユーザーに紐づいた権限付与を避けたかったため、選択肢から外しました。StepFunctionsを採用しました。構成は以下のとおりです。設計のポイントcreate-botとapprove-botに分けて作成したことが重要な点です。最初は1つのbotとして作成を進めていましたが、PRを自分で作成して自分でアプルーブすることができなかったため、2つに分けています。処理フローそれぞれのbotの処理フローは以下になります。全ての処理のコードを記載して説明すると長くなるので、重要そうな箇所を説明します。Repositoryの名前、トリガーになったブランチもしくはタグを用いて判断しています。沿った書き方にする必要があります。最初に、GitHubから(正確にはCircleCIから)送られてくる情報を受け取るためのstructを用意しました。TagとPullRequestのどちらをトリガーにしても動作するように作成したので、以下のような項目になっています。いくつかの項目は毎回取得できるわけではなく、例えばPullRequestの情報はGitHubでPRが作成された時やPRがマージされた時に取得可能な情報です。Tagを追加する、というトリガーではPullRequestにはデータが入らないため、データを取得しようと試してもエラーにはなりませんが何も情報は得られません。Lambda用のmain関数は以下のようになっています。{}リポジトリ毎にTESTとPRODに適用したいブランチやタグが異なるので、PR作成条件を定義しています。example1はブランチで適用する環境を変えたい例、example2はタグで適用する環境を変えたい例です。受け取った情報とPR作成条件を組み合わせてPRを作成するべきか判別します。トリガーがPullRequestなのかTagなのかによって処理が変わりますが、それぞれブランチ名とタグ名がPR作成条件と合致しているかを確認しています。nil}ここまでの処理が終わるとPRの作成処理に移ります。AppsのTokenを使って行うために、GitHub用のClientと、Git用のTokenを作成します。cloneを行います。tokenを使用するとusernameの値は何でも構わない、という点です。Lambdaにアップロードするzipファイルはgolangのバイナリファイルとkustomizeを含めて作成しています。commit/pushしてPRを作成し、結果をSlack通知に送ってcreate-botの処理は終了です。approve-botPRの作成者がcreate-botであることを確認approve-botが使用しているstructは以下のとおりです。PR番号やPR編集者の情報を取得しています。`json:"sender"`}PR編集者がcreate-botかどうかを判別します。これによって誰かが間違えてcreate-botと同じブランチ名でPRを作成してしまってもapprove-botはマージしなくなります。}この後、変更されているファイルが正しいか確認してから、CI終了を待つ処理に移ります。なっていることを確認しています。Tokenを用いてクライアントを作成して、アプルーブします。nil}アプルーブが終わったら、マージしてSlackに通知してpr-approve-botの処理は完了です。作成している最中に問題になったこととを以下に記載します。Appsは追加できないとのことでした。Tokenを使うことにしました。Gatewayの制約である29秒以内に完了しなくなったのは原因があります。Repositoryに作成するPRに記載しています。大量のPRが含まれている場合、処理が29秒以内に完了できませんでした。approve-botの場合は、PRのマージを行う条件としてCIのテストが終わっている必要があるのですが、CIのテストが29秒以内に終わらない場合がありました。Gateway+Lambdaの構成では不十分だということがわかりました。GatewayとLambdaの間にStepFucntionsを挟むことで最長でLambdaの制約である15分は動かせるようにしました。Repositoryのブランチに立て続けにPRがマージされた際に、既存のPRに簡単にpushすることができず、PRを削除して再作成しなければなりません。pushにforceオプションがあると良いなと考えました。対策として、OSS貢献のチャンス!ということでPRを出しました。無事PRはマージされていて、go-gitのv5.1.0からはgo-gitを使ってpushする時にもforceオプションが使用可能です。Experienceを上げることができました。サーバレスでツールを開発する経験が少なかったので、勉強になりました。Gateway+Lambdaの構成であればサクッと作れるようになりました。普段お世話になってばかりのOSSにコントリビュートできました。仲間から喜びの声をもらえました。おわりにマネーフォワードでは、Kubernetesを使用したサービスの安定化や、業務の効率化を促進するエンジニアを募集しています。ご応募お待ちしています。読者になるこのブログについてはてなブログをはじめよう!moneyforwardDevさんは、はてなブログを使っています。ブログを報告する引用をストックしましたストック一覧を見る閉じる引用するにはまずログインしてくださいログイン閉じる引用をストックできませんでした。再度お試しください閉じる限定公開記事のため引用できません。