ECS環境のAuto Provisioningを実現する仕組み
はじめに
こんにちは。プラットフォームGでDevOpsエンジニアだったものからOperationToolManagerチームでPlatformEngineeringとかツール周りの開発・運用の役割になった島村です。
KINTOテクノロジーズのプラットフォームGでは、Terraformを使用したIaCを推進しています。社内でよく使われるデザインパターンを定義し、リファレンスアーキテクチャとして提供しており、そのパターンをベースとして各環境を構築しています。開発~本番環境の各環境では、統制のために、チケットベースの依頼にて構築を実施しています。
開発環境を構築する前に、アプリケーション部門の検証のためにサンドボックス環境(AWSアカウント)を準備していますが、手動で構築されることも多く、プラットフォームGの構築する環境とは差分が多くあります。
デザインパターンがあるなら、開発者のリクエストにより環境が自動で構築されれば、環境構築の依頼から作成されるまでの待ち時間もなくなり、開発効率は向上します。
DevOpsではこのようなリクエストベースでの自動構築は要件として一般的な話かなと思いますが、やはり、アプリケーション実行基盤はKubernetesが多いようです。
KINTOテクノロジーズではAmazon ECS+Fargateをアプリケーション実行基盤として使用していますので、ECSを対象とした自動環境構築の(多分)珍しい事例としてご紹介いたします。
背景
課題
- アプリケーション開発担当者が必要なタイミング(検証・走り出し)でシステムが存在しない
- DevOps活動の一環として、AutoProvisioning(自動環境構築)については調査をして、一般的だなと感じたが社内には存在しない
- 比較的自由度の高いサンドボックス環境で構築した環境とプラットフォームGによって提供されるデザインパターンに則った環境での差分が大きい
- IAM権限などセキュリティまわり
- VPC/Subnet/NAT Gatewayなどの共通系コンポーネントの存在
- などなど
- それに伴い、構築依頼の際の双方のコミュニケーションコストが高くなる
解決方法
自動構築の仕組みを作ればいいじゃない
デザインパターンなので不足するAWSサービスもありますが、そこは許容して手動追加を前提としています。
最初の第一歩として、1時間程度でAWS上の環境を自動構築して、アプリケーション動作確認やCICDの準備ができるという状態にすることは価値がある。
作ってみる
ありがたいことに、Terraformの1ファイル(locals.tf)を書くだけで色々なパターンで環境構築できるようにModule化が進んでいるので、こちらをベースに考えます。
- 社内作成のModule群を使うこと(Must)
- 社内のデザインパターンをベースに構築すること(Must)
- DNSは自動で設定されて、HTTPSで通信ができること
- locals.tfを自動生成できること
- GolangのHCLWriteで構造化して生成できるかアプリケーションを試作
- 構造化が難しいことが試作して判明したため、最終的には自動生成を諦めた
- Templateファイルから一部パラメータを置換することで対応
- 置換での処理となったので、各コンポーネントの細かい設定は不可
できたもの
CMDB上のGUIから、
- プロダクト
- デザインパターン
を選択して新規作成を押すと、プロダクトに紐づいた部署のサンドボックス環境に、指定された構成が10分~40分(構成次第)で構築される。
全体構成
個別説明
Terraformコードを作成する部分と実際にサンドボックス環境に構築する部分は分けており、個別にテストできるようにしました。
Terraformコード生成パーツ
- ProvisioningSourceRepo
- Issue管理
- GitHubActions実行
- 作成したサンドボックス環境のTerraformコード
- サンドボックス環境ごとのCIDRリスト
- ProvisioningAppRepo
- デザインパターンのTemplate
- CodeBuildのYaml(buildspec.yml)
- CodeBuild上で動かす各種ShellScript
- InfraRepo
- TerraformModule
AWS環境構築部分
- S3
- CodePipelineのSourceとArtifact
- EventBridge
- CodePipelineのTrigger
- CodePipeline/CodeBuild
- 実構築環境
- Route53(Dev)
- 本番のDNSから権限移譲をしてDev環境のRoute53を使用
Terratest(Apply)
Terratestのサンプルはこのような形。Init、Plan、Applyのどこかで失敗したらテストを終わらせるという条件の関係で入れ子に。Apply途中で失敗した場合は、途中までのものをDestroyする。Golangの知識があればもっと綺麗にかけると思う。
package test
import (
"github.com/gruntwork-io/terratest/modules/terraform"
"testing"
)
func TestTerraformInitPlanApply(t *testing.T) {
t.Parallel()
awsRegion := "ap-northeast-1"
terraformOptions := &terraform.Options{
TerraformDir: "TerraformファイルがあるPATH" + data.uuid,
EnvVars: map[string]string{
"AWS_DEFAULT_REGION": awsRegion,
},
}
// InitでErrorがなければPlan、PlanでErrorがなければApplyと
// IFで入れ子構造の対応を実施(並列だとInitで失敗してもテストとしてすべて走る)
if _, err := terraform.InitE(t, terraformOptions); err != nil {
t.Error("Terraform Init Error.")
} else {
if _, err := terraform.PlanE(t, terraformOptions); err != nil {
t.Error("Terraform Plan Error.")
} else {
if _, err := terraform.ApplyE(t, terraformOptions); err != nil {
t.Error("Terraform Apply Error.")
terraform.Destroy(t, terraformOptions)
} else {
// 正常終了
}
}
}
}
要素
名称 | 概要 |
---|---|
CMDB(内製) | Configuration Management Database。構成管理のデータベースのこと。リッチな機能までは不要でしたので、KINTOテクノロジーズではCMDBを内製しています。その上に自動構築のリクエストフォームを構築しています。また、構築後にFQDNなどをCMDBに自動で登録しています。 |
Terraform | AWSなど色々なサービスをコード化する製品。IaC。社内のデザインパターンとModuleはTerraformで作成されています。 |
GitHub | ソースコードを保存するバージョン管理システム。構築リクエストはIssueを起票する形でログに残るようにしています。また、削除する際などにTerraformのコードが必要なので、サンドボックス環境の各コードも保存しています。 |
GitHubActions | GitHubに包含されているCICDツール。KINTOテクノロジーズではGitHubActionsを使用してアプリケーションのビルド・リリースなどを実行しています。今回はIssue起票をトリガーに、Create/Deleteを判断して必要なコード群を選択し圧縮してAWSに連携するために使用しています。 |
CodePipeline/CodeBuild | AWSが提供しているCICD関連のツール。Terraformコードを実行するために使用しています。GitHubActions上でTerraform/Terratestを走らせてもよいのですが、GitHubActionsはアプリケーションビルドなどで日々使用しているので、Usage limits などによる各プロダクトチームへの影響を避けるためこちらを使用しました。 |
Terratest | インフラコードなどをテストするためのGoライブラリ。モジュールのテストもできますが、今回はTerraformのApply途中で失敗した際にリカバリすることを目的に使用しています。公式はこちら |
制限されること
- 各開発チームに紐づく複数のサンドボックス環境(AWSアカウント)を対象にしますが、作成できるのは同時1つまでにしています(排他)
- DNSの関係でCodePipeline/CodeBuildを1つの環境で動かしているため
- アプリケーションが動く部分以外も作成します
- 無駄も多い気もしますが、構築デザインパターンの関係上こうなりました
- FQDNからDBまで一気通貫のラインとして構築されます
- VPCなどを事前にModuleに設定する必要があります
- 使用する前にVPCなどの共通コンポーネント構築一式が必要
Module群がない場合はどうするのか
KINTOテクノロジーズでは以前からデザインパターン化を進めていましたので、CloudFrontからRDSまでをすべて含めた構築が容易にTerraformでできる利点があります。
そこまで進んでいないけどAutoProvisioningをECSで実現したい場合はどうする方法があるでしょうか。
考えてみた
ECSのClusterまでは事前に作成しておき、
- ECS Service
- ECR Repository
- ALB TargetGroup
- ALB ListenerRule
- IAM Role
- Route53
を書いたTerraformファイルを準備して構築するのが楽なのかなと。TaskDefinitionは権限あれば作れるので、使用する側でよしなに。
構成案
GitHubActionsの代わりにCodePipeline/CodeBuildでもいいと思ってますが、CodeCommitとかGUIの準備を考えるとGitHubにまとめたほうが簡単なんじゃないか?ということで、この構成に。AWS Protonはまだ触れてないので、未検討です。
locals.tfなどのParameter部分を分離しておいて、sedコマンドや、GolangのHCLライブラリをつかって作成できれば行けるかなと思います。Terratestなどで構築が確認出来たら、任意のFQDNをALBのエイリアスに追加して、ListenerRuleと合わせる形。
次のステップ
もともとはプレ提供でフィードバックをもらおうと思っていましたが、現状はあまり利用されていません。そのためにGUIを提供したので、今後さまざまな人にまずは使って貰ってそのフィードバックを受領するところから始めようと考えてます。
とはいえ、対応できるデザインパターンを増やすことや、付随したCICDの設定の簡素化などできることは多いかなと考えています。…本当はKubernetes導入をして、事例の多いAutoProvisioningに進めたいところ。
|・ω・`) だめですか?
所感
本当はGolangでテンプレートを自動生成する方向で頑張ったんですが、社内のデザインパターンのHCL構造が解析、再構成しづらい形だったのであきらめたという経緯もあります。
Consoleの再発明じゃないかという話も内部ではありましたけど、そこまで行けると、サンドボックス環境だけでなくSTG環境くらいまでなら自動化できたかなとも思っています。プラットフォームGもGUI上からポチポチちょっと入力と選択するだけで環境ができる。わあ、楽。
そこまで達したかったのが本音ですが、まずは第一歩でも進めることができたことは良かったかなと。
Kubernetesでは、Helmチャートをテンプレートで準備すれば、似た感じで作れるのではと思っています。別方法も検討してみて、いろいろとやってみたいですね。
まとめ
OperationToolManagerチームは、社内向けの横断ツールを統制して必要なものを開発しています。
前に執筆しましたO11yの記事もですが、仕組みを整理してアプリケーション開発者側に提示してセルフサービスで使用できるようにする、そういった開発者が価値を創造するための下支えの立場で活動しています。
少し前にPlatformEngineeringのMeetUpが開催されましたが、進む方向性として合致してると安心できますね。
OperationToolManagerチームでは内製ツールの構築部門もいますので、開発者が迅速にかつ集中してアプリケーションの価値を作れるようにしていきます。
またこの活動に少しでも興味を持ったり話を聞いてみたい、と思った方はお気軽にご連絡いただければと思います。
関連記事 | Related Posts
We are hiring!
【プラットフォームエンジニア】プラットフォームG/東京・大阪
プラットフォームグループについてAWS を中心とするインフラ上で稼働するアプリケーション運用改善のサポートを担当しています。
【クラウドエンジニア】Cloud Infrastructure G/東京・大阪
KINTO Tech BlogWantedlyストーリーCloud InfrastructureグループについてAWSを主としたクラウドインフラの設計、構築、運用を主に担当しています。