新卒エンジニアがCICDをモダナイズしてみた話

# はじめに
## `$ whoami`
こんにちは、@Akashi_SN です。
今回は [KDDI エンジニア＆デザイナー Advent Calendar 2024](https://qiita.com/advent-calendar/2024/kddi) の12日目の記事として執筆しています。
<dl>
<dt>経歴</dt>
<dd>
    <ul>
        <li>明石工業高等専門学校 (2015-2020)</li>
        <ul>
            <li>株式会社ヘマタイト (アルバイト：2018-2020)</li>
        </ul>
        <li>豊橋技術科学大学 (2020-2024)</li>
        <ul>
            <li>株式会社Flatt Security (アルバイト：2020-2023)</li>
            <li>NTT社会情報研究所 (インターンシップ：2022)</li>
        </ul>
        <li>KDDI株式会社 (新卒入社：2024-)</li>
        <ul>
            <li>新入社員研修 (4月-8月)</li>
            <li>現部署配属 (9月-)</li>
        </ul>
    </ul>
</dd>
</dl>

趣味は自宅サーバの構築や運用で、技術に触れることが大好きです！

![趣味_自宅サーバ.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/124638/ee264327-2e25-eabd-a190-37f0404c91d8.png)

## `$ jobs`

現在、AWS上で稼働するシステムについてのSREエンジニアとして、主にAWSインフラに関するCI/CDの刷新プロジェクトに携わっています。

# 現状のCI/CDについて

インフラ開発も開発パートナーに依頼していましたが、数年前から内製開発へ移行し、JenkinsによるCI/CD環境も引き継ぎました。このプロジェクトは規模が大きく、複数の開発拠点やパートナー間で共通のCI/CD基盤を構築していたため、複数のリポジトリにまたがるJenkinsスクリプトや設定が存在し、実際にジョブで何が実行されているのか追跡するのが困難でした。
さらに、Jenkinsおじさんとよばれるように、Jenkinsの設定をした人でないと全貌を解明できないといったような属人化してしまう問題もありました。


# GitHub Actions + CodeBuildへの移行
Jenkinsからの移行先として白羽の矢が立ったのは、GitHub ActionsとAWS CodeBuildの組み合わせでした。2024年4月にGitHub ActionsのSelf-hosted RunnerとしてCodeBuildがサポートされるようになったため、これを活用することにしました。
[AWS CodeBuild がマネージド型の GitHub Action ランナーのサポートを開始](https://aws.amazon.com/jp/about-aws/whats-new/2024/04/aws-codebuild-managed-github-action-runners/)


## CI/CDシステム構成

![gha-infra-diagram.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/124638/a97d1826-1a7c-4aeb-ff40-3ced180bc399.png)

弊システムは以下の3つのAWSアカウント環境で構成されています。

1. 内連環境（開発環境）
2. 検証環境
3. 商用環境（本番環境）

検証環境と商用環境ではアウトバウンド通信がProxy経由のWhitelist方式となっているため、デプロイに必要な資材は内連環境のS3に保存し、そこからダウンロードしてオフラインでビルドを行うように設定しました。

また、実行するジョブを以下の2種類に分類し、それぞれに対応するCodeBuildプロジェクトを作成しました。

- **Planジョブ**: 環境に変更を加えない読み取り専用のジョブ
- **Applyジョブ**: 実際に環境を変更するジョブ

これにより、合計で6つのCodeBuildプロジェクト（2種類のジョブ × 3つの環境）を作成しました。

## 権限管理

![gha-iam.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/124638/bb2a9cd1-ee48-b8d4-94fb-659d29b53cd7.png)

CodeBuildプロジェクトでは、`service-role`と`assumed-role`の2種類のロールを切り替えて使用しています。

- ***-service-role**
    - CodeBuildがWebhookから起動された初期状態で付与されるロール
    - 権限は非常に限定的で、信頼ポリシーには`sts:AssumeRole`の許可のみが含まれる
- ***-assumed-role**
    - GitHub ActionsのWorkflow内で明示的にAssumeすることで使用可能なロール
    - 対応する`service-role`からのみAssume可能
    - ジョブに応じて権限が設定されている（Planジョブには`ReadOnlyAccess`、Applyジョブには`AdministratorAccess`）

弊社の運用ルールとして、商用作業時には作業申請が必要であり、特権が必要な場合は別途特権申請が必要です。特権申請は主にAWSマネジメントコンソールからの操作を前提としているため、GitHub Actions経由で行われる操作に対しては制御が困難です（特権が付与されない or 申請なしで特権使用できてしまう）。

この運用フローに対応するため、商用環境ではCodeBuildの`service-role`に`DenyAssumePolicy`を付与し、通常時はAssumeを拒否するようにしています。商用作業を行う際には、特権申請を経てAWSマネジメントコンソール上で`service-role`から`DenyAssumePolicy`をDetachすることでAssumeを行うことができます。これにより、運用上のセキュリティを確保しています。

## Jenkinsジョブの移行

一度にすべてのジョブを移行することはプロジェクトの規模を考えると不可能であるため、まずは身近な我々が開発を行っているインフラコードを管理しているリポジトリで使用しているジョブを移行を行いました。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/124638/224a6252-2d62-059a-55c9-ef5e89f695dc.png)

# まとめ

- 一見するとブラックボックスである複雑怪奇なCI/CDシステムの一部をGitHub Actionsに移行することができた
- 我々が開発を行っているインフラコードでも掘れば古代の遺物が出てくるため、リファクタリングのし甲斐がある
- 現在の部署は（~~弊社としては珍しく~~）実際に手を動かして大きなインフラの開発を行うことができるため、自宅サーバなどをやっているような技術好きな人におすすめです！

# おまけ
escape-from-jenkinsというブランチ名がゲームのEscape From Tarkovみたいで自分の中で気に入っていたので、DALLEに生成してもらいました。

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/124638/03b5e954-fbbd-3892-ae44-4921aff81d29.png" width=30%>