[Github Actions]terraform-aws-github-runnerでカスタムsgを指定しつつSSM経由でRunnerを起動する

- KDDIアジャイル開発センター（KAG） Advent Calendar 2023 Day 20 を担当します、アーリオオーリオとポモドーロスパゲッティを最近練習してる系男子ですどうもこんにちは。
- 今回は、GithubActionsのSelf-hosted-runnerをSSM経由で利用する方法をご紹介します。
- オートスケーリングするrunnerの設定を、terraformを使ってsgの指定とssm経由での通信の設定を行います。

## 目次
1. 知れること
1. やったこと
1. 手順
1. おわりに
1. Appendix

## 1.知れること
- philips-labs/terraform-aws-github-runnerを活用した、Runnerのオートスケーリングの概要と簡易手順
- terraformでセキュリティグループ(以下、sg)の指定と、セッションマネージャー(以下、SSM)の有効化方法

:::note warn
Runnerの中で動くDockerコンテナとかの話はしません。
:::

## 2.やったこと
- Github Actions(以下、GHA)のSelf-hosted-runnerとして使っているec2のインバウンドポートを全閉塞しているsgを指定して、SSM経由でRunnerを起動します。
めっちゃ簡易で書くと下図のイメージ。sgのインバウンドポートは閉塞する。
![スクリーンショット 2023-12-15 17.07.11.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/754596/98300f05-eb87-4d9b-6100-8f950e4fce2e.png)

- Runnerをオートスケーリングさせる方法ですが、以下のリポジトリを利用することで実現しています。このリポジトリを参照できるようにしてあげることで、簡単にself-hosted-runnerのオートスケーリングを実現できます。

https://github.com/philips-labs/terraform-aws-github-runner/tree/v5.5.1

#### セッションマネージャーってなんぞや
- Session Managerについて、公式の説明をみると、以下のように記載があります。
> 安全かつ監査可能なノード管理を実現し、インバウンドポートを開いたり、踏み台ホストを維持したり、SSH キーの管理したりする必要はありません

https://docs.aws.amazon.com/ja_jp/systems-manager/latest/userguide/session-manager.html

- EC2インスタンスをプライベートサブネットに配置し、SGを通じた直接の通信を制限することで、外部からの不正アクセスを減らすことができます。つまり、SSMはAWSのセキュアなサービスで、必要なアクセスを制御しやすく、セキュリティ向上に寄与してくれます。


#### そもそも、Runnerをオートスケーリングさせて何が嬉しいのか
- CI/CDツールとして、Github Actionsを利用しているのですが、デプロイする際に利用するRunnerが1台だと処理が遅く、例えば、チームで開発していたり、デプロイするリポジトリがたくさんある場合、普通に待ち行列が発生するので、それを必要に応じてAutoScallingによって、Runnerを増やしてあげることで負荷分散を行って処理能力をスケールアップさせます。
- terraform-aws-github-runnerで作成するRunnerは、一度終了して再度立ち上げる(ActionsからRunされたときとか)と、当該リポジトリの設定内容でスポットインスタンスが立ち上がるようになっています。terraformで設定ファイルを、各々の開発環境の要件に沿うように修正してあげることで、立ち上がるインスタンスのsgなどを指定したりすることができます。

#### なぜ、Self-hosted-runnerを使わないといけないか
- 結論から言うと、Gihub Enterprise(以下、GHE)を使っているからです。GHEにおいてActionsを利用する場合、Githubが用意するRunnerを使用することができません。なので、自分でRunnerを作成してあげる必要があります。


<br>
そんなわけで、terraform-aws-github-runnerのリポジトリを活用しつつ、今回の要件である全インバウンドポートを閉塞したsgをRunnerであるEC2に紐づけて、SSM経由で利用できるように設定を追加してあげます。


## 3.手順
#### philips-labs/terraform-aws-github-runnerの概要と設定手順
本項は、あくまで簡単に流れを説明することとします。
まず、仕組みとしては、philips-labs/terraform-aws-github-runnerリポジトリのreadmeにある以下の図を確認いただきたいのですが、Github Actionsの起動をWebhookが拾って、API Gatewary経由でLambdaを実行し、EC2（Runner）を起動するといった流れになります。これによって、Githubから起動したRunnerを利用できるようになります。ジョブが終了するとLambdaはEC2を終了します。
![スクリーンショット 2023-12-14 19.21.19.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/754596/4d3cc830-1233-4e26-86e1-6c39e9770f76.png)

必要な設定としては、以下の流れになります。
1. GithubAppからWebhookを利用できるようにする
1. Terraformの設定ファイルを作成する（Ex.awsの設定やmain.tfなど
1. terraformディレクトリ配下で、terraform-aws-github-runnerのmain.tfにも記載されてる以下３つのzipをcurl(ダウンロード)する。
１：lambdas-download/webhook.zip
２：lambdas-download/runner-binaries-syncer.zip
３：lambdas-download/runners.zip
上記3つのLambdaのスクリプトは、以下にあります。
https://github.com/philips-labs/terraform-aws-github-runner/releases

1. カスタマイズしたい内容はmain.tfに記述する。
1. awsのクレデンシャル(アクセスキーとシークレットキー)をローカルの~/aws/credentialsに登録する。
1. terraform init/plan/applyを実行
1. applyで出力されるWebhookエンドポイントとシークレットをgithubに登録する。
1. ActionsをRunしてRunnerが立ち上がるか確認する（EC2(Runner)が起動済みの場合はEC2を終了してからActionsを動作させる）


#### カスタマイズしたsgを指定する
前項の4番の内容になります。main.tfを修正して自分で作成したsgを指定したいと思います。
1：AWSマネジメントコンソールからsgを作成します（ここでは説明を割愛）。作成したsgのセキュリティグループIDを控えておきます。ちなみに、今回このsgはインバウンドポートを閉塞しています。
2：main.tfに以下の記述を行い、先ほど控えたsgのidを指定してあげます。
```terraform:main.tf
runner_additional_security_group_ids = ["作成したセキュリティグループのID"]
```
３：以下の項目をfalseにすることで、マネージドなsgではなく指定したsgをec2に紐づけることができる。
```terraform:main.tf
enable_managed_runner_security_group = false
```

一応、以下のurlからterraformで設定したいことと、記述方法を探すことができます。

https://registry.terraform.io/modules/philips-labs/github-runner/aws/latest/submodules/runners


#### SSMを有効化する
以下の記述でSSM経由での通信を有効化できます。ec2にSSMを使用するためのエージェントをインストールしてくれる感じです(必要なポリシーとかも設定してくれる)。
```terraform:main.tf
 # enable access to the runners via SSM
  enable_ssm_on_runners = true
```
実際に起動したらセッションマネージャーからセッションの開始をすることでSSM経由でアクセスできるEC2が表示されるので、最後に確認してみてください。


#### terraformコマンドを実行して設定内容を反映させる
main.tfをカスタマイズすることができたら、terraformコマンドで設定内容を反映してあげます。
```terminal
terraform init
terraform plan
terraform apply
```
もし、initでエラーが出た場合は、お使いの環境のterraformのバージョンが古い可能性があるので、tfenv listでバージョンを確認して必要に応じてinstallとuseを実行して、最新verを使えるようにしてください(tfenvでterraformのバージョン管理をしている場合)。また、planとかでコマンドの入力が求められたら、"yes"と入力してEnterで先に進めます。
ちなみに、破壊するときはCLIからのterraform destoryと手動でのec2の終了です。


#### インスタンスを立ち上げる
applyが成功したら、actionsからrunnerを起動してみましょう。このとき、ec2インスタンスが既に起動している場合は一旦ec2を終了してからrunnerを起動します。スポットインスタンスなのでec2の停止はできないので注意しましょう。ちなみに、Runnerとしてインスタンスが元から動いている状態でapplyだけしても設定は反映されないので、一度終了してからRunnerを起動してください。


#### 確認してみる
- Actionsが想定通り動作し、ec2に指定したsgが紐づけられていることを確認できたら完了です。
- Actionsのジョブを見ても、SSMでセッションを開始することのできるec2のインスタンスidを指定して、ジョブを実行していることが確認できるかと思います。
- これで、Runnerを起動するec2に紐づくsgのインバウンドポートを閉じた状態で、SSM経由でのAutoScaling Runnerの利用が可能となりました。

## 4.おわりに
- 今回は、GHAにおいてAutoScallingされるRunnerに指定したsgを割り当てて、ssm経由で利用する設定をterraformで追加する方法を紹介しました。
- これで、今回のタームで参加させていただいたAdvent Calender全3日分の記事を書き終えました。
- Advent Calenderに参加することの意義を私は、記事を書くぞ！という宣言/トリガーから、言わばOutput DrivenでのInputの質向上を狙えたり、学びの深度を深める/速度を加速できることだと思っているので、今から次回が楽しみです。


## 5.Appendix
今回のタームで参加したAdventCalenderの記事を以下に置いておくので、気になるものがあればご覧ください(・∀・)

- KDDIアジャイル開発センター（KAG） Advent Calendar 2023 4日目

https://qiita.com/ayumun_jp/items/f4ac83f599146e168ff8

- KDDI Engineer & Designer Advent Calendar 2023 8日目

https://qiita.com/ayumun_jp/items/9e1843f92bd26c6e5201

Catch you later!