2022年3月からやってきた取り組みとこれからの展望

# 2022年3月からやってきた取り組みとこれからの展望

## 概要

アドベントカレンダーで何を書こうか迷ったので、とりあえず今年の3月からこれまでやってきた取り組みをつらつらと書いていきます。

## 3月から行なった取り組み

- WordPressサイトのEC2構成からLightsailへの移行
  - Terraform、AWS CDKの利用
- Fargate on ECSを利用したWordPressサイトの構築
  - WordPress関連コードの管理方法見直し
  - Terraformの利用
  - taurusを利用したパフォーマンス計測およびチューニング
  - OWASP ZAPを利用した簡易的な脆弱性チェック
  - EFSを利用したCI/CDの仕組み作成
- TerraformやAWS CDKといったIaCツールの導入
- GitHub Enterprise Accountの導入
- OIDCを利用したAWSとGitHub Actionsの繋ぎ込み
- PHPで書いていたAPIをLambda用NodeJSコードにリライト
  - NodeJSではなく一度Denoを検討
  - テストコードの作成
  - GitHub Actionsを利用した自動テストの実施

## WordPressサイトのEC2構成からLightsailへの移行

### 取り組み内容

基本的に弊社でWordPress向けのインフラ環境を作成する際には、EC2を利用してオーソドックスな冗長構成の環境を作成していました。

バックエンドのチームとしてこれからどう動いていこうか、ということを話し合った際にコンテナサービスの導入の話が上がり、OSのサポート切れが起きているサイトもあったため、該当サイトをコンテナサービスに切り替えようということになりました。

この時に移行先として決定したのが、AWS内で提供されている[Lightsail](https://aws.amazon.com/jp/lightsail/pricing/)というサービスです。

Lightsailは決まったスペックを一定の月額で提供してくれるサービスで、コンテナサービスのプロダクト利用実績が無い中進めるためにも、ある程度の設定をAWS側に任せるという意味で学習のハードルも低いという理由から決定しました。

また、元々のサーバがそれなりのスペックで動作していましたが、ここ数年のアクセス数を見る限り、スペックダウンをしても問題無いだろうということから元の金額を抑えるといった金額コスト的な面も理由にはあります。

Lightsailにはサーバのプランとして、仮想サーバとコンテナサービスの二つのプランがありますが、二つのプランで同スペックのリソースを利用しようとした際にはコンテナの方が割高となっています。

厳密に費用のみを抑えることに注力するのであれば、仮想サーバで構築を行った方が安価だとは思います。

### 苦労した点

Lightsailへの移行に際して苦労した点として、

- IaCでの管理
- CI/CDの側面

という二つの側面で大きく苦労をしました。

#### IaCの管理

移行をするにあたり、今後の活用も考えて新規で作成するLightsailリソース、変更を行う既存のリソースについてはIaCで管理を行おうと考えました。

この時の問題点としては、実施したタイミングでは[Terraform](https://www.terraform.io/)の導入を進めるために学習を行い始めていた時期でもあったので、全てをTerraformで管理することを前提にしようとしていました。

しかし、当時のAWS ProviderではLightsailのコンテナサービスが対応されておらず、結果的にLightsailリソースはAWS CDKで、Lightsail外のリソースについてはTerraformでという棲み分けを行いました。

この棲み分けの理由としては、どちらも学習初期の段階ではありましたが、既存リソースのインポートに関してはTerraformの方が簡易に感じられたためです。

変更という一点においてもCDKのdiffの結果よりもTerraformでのplanの結果の方が見やすく感じました。

#### CI/CDの側面

弊社ではGitHub Enterpriseを導入しているため、IaCのコードはGitHub上で管理を行いました。

この時、CI/CDの対象としては新規で作成するAWS CDKのみをCI/CDの対象としました。

また、前提としてIaCのコードとWordPressに関するコードは別々のリポジトリにしています。

ここから本題ですが、なぜCDKのみをCI/CDの対象にしたかというと、

- 開発初期のため頻繁に反映作業が発生するため
- 今後の反映ミスを防ぐため本番、検証、開発の環境構築を人手を解さず行いたいため
- WordPressに関する開発内容の反映は主にバックエンドエンジニア以外が行うので、簡易的に行えるようにしたいため

といった理由があります。

これらを行うためには一番の懸念点として、反映に時間がかかってしまうことがあがっていました。

なぜ時間がかかるのかというと、

- サービスで利用するためのイメージのビルド時間
- イメージを環境に反映する時間

の二つで時間がかかってしまい、全てを一緒にした場合には一度の反映に10分程度かかってしまう状態でした。

しかし、これに関してはどうしてもかかってしまうため、解決策としては、

- WordPress用のリポジトリで特定の変更が行われた場合にはイメージのビルドとレジストリへのプッシュを行う
- 反映したいタイミングでIaC側のリポジトリでイメージを環境に反映する

といった風にステップを分割することにしました。

これにより、まだ多少は時間がかかってしまいますが、時間の減少には成功しました。

また、ステップの分割に際して、CI/CDに使用するツールも分けています。

イメージのビルドにはCodeBuild、イメージの環境反映についてはGitHub Actionsを利用しています。

この分割理由については本番など一部の環境については、反映の契機をコミットしたタイミングではなく、手動で実行したいといったケースがあるため、すでに開発者がアクセスできるGitHub側で反映を実施できた方が簡易だろうという判断の元行っています。

### 今後の展望

おそらく仕事としてのLightsailの採用は優先度としてかなり低くなると考えています。

というのも、この対応を行なった後にTerraformでECS環境を構築したこと、Lightsailではログが90日分しか残らないことから積極採用はしない考えです。

## Fargate on ECSを利用したWordPressサイトの構築

### 取り組み内容

#### WordPress関連コードの管理方法見直し

弊社ではWordPressを使用したサイトの構築が多くあります。

そのため、案件のたびにより良いWordPressの管理方法を模索し、ブラッシュアップをおこなっていたりします。

その流れとして、コンテナサービスでインフラ環境を構築するにあたり、WordPressの管理についても見直しました。

まず、今までの管理方法としては、WordPress本体、プラグインを含めて全てのソースをGitリポジトリで管理していました。

しかし、WordPressに関する開発において、基本的に開発者が作成しているものはテーマであり、ケースによってテーマが依存するプラグインの管理も行いたいという話であり、WordPress本体やプラグインといったテーマ外の物に関しては基本的に管理に含める必要は無いと考えています。

そのため、今回ECSを利用するにあたり、反映するものを最小限にするために管理対象の分割を行いました。

分割した結果としては、

- ECSで利用するイメージのDockerfileを管理するリポジトリ
  - IaCのリポジトリ内で管理をする
- WordPress本体を管理するリポジトリ
  - プラグインの追加はこのリポジトリに対して行う
- テーマを管理するリポジトリ

としました。

この分割にした理由としては、反映が発生する頻度とイメージのサイズを小さくするためにイメージの管理はミドルウェアのみとするためです。

反映の頻度が、**テーマ > WordPress**となる理由としては、純粋にWordPressに対してコードの変更は行わず、プラグインに関しても基本利用するものは決まっているため、最初に用意してしまえばその後はほぼ触らないためです。

#### Terraformの利用

全体を通じてインフラ構成の再利用による構築のスピードアップを目指しているため、この対応についてもTerraformを利用しました。

リソース監視として、Mackerelを導入していますが、そちらについてはTerraform管理の対象外とし、AWSリソースのみを管理対象としています。

#### taurusを利用したパフォーマンス計測およびチューニング

この対応がECSの初導入になるため、月額の費用を抑えるためにできるだけ抑えたスペックで安定動作できるようにtaurusを利用してパフォーマンスチューニングを実施しました。

自分が入社したタイミングではすでに実績がある形でEC2を使った構成が決まっていたことと、 CloudFrontを介すため厳密に計測を行わなくてもある程度のアクセスは捌けることが分かっていたので、おそらくWordPress系のサイトでちゃんとしたチューニングは初めて行ったのでは思います。

なぜ実施したかについては、冒頭で述べた通り、月額の費用を抑えるための他に今後同じ構成で作成をする際にこの構成であればこの金額でこれぐらいのアクセスに耐えられますという指標を示すためという理由もありました。

パフォーマンスのチューニングとしては、PHPでOPCacheを利用したチューニング（レスポンス速度の向上）とPHPがメモリ不足のエラーを出力していたため、単純にコンテナサービスで利用するメモリをログを確認しながら予算内で収まるように設定を行いました。

また、オートスケーリングも設定しており、今回はCPUの閾値チェックを契機にスケールが行われるようにしています。

#### OWASP ZAPを利用した簡易的な脆弱性チェック

今回、リリース直前に急遽脆弱性チェックが行われることになったため、自分の方でも事前に対応できるものに関しては対応できるようにOWASP ZAPを利用して簡易的なチェックを行いました。

なぜOWASP ZAPを利用したかというと、この対応を行ったサイトがフォームや検索でWordPressの基本機能外（自分達でコードを書いたりしたもの）が無いサイトであったため、今まで実施された多くの脆弱性診断サービスでフィードバックを受け取った際にOWASPの情報が参照されていたためです。

今回OWASP ZAPの簡易利用で上がった内容については全てCloudFrontの設定で対応できるものであったため、脆弱性診断実施前に対応を行い、無事に通過することができました。

#### EFSを利用したCI/CDの仕組み作成

[WordPress関連コードの管理方法見直し](#WordPress関連コードの管理方法見直し)で述べた通り、この対応ではECSへ反映するイメージのサイズをできるだけ小さくするためミドルウェアのみをイメージに含めています。

そのため、アプリケーションとなるWordPressに関してはEFSへ反映を行い、ECS側でそのEFSをドキュメントルートにマウントする形としています。

EFSへの反映についてはGitHub → S3 → DataSync → EFSといった流れでWordPress本体、WordPressのテーマを反映しています。

### 苦労した点

この対応で苦労した点としては以下がありました。

- Terraformのモジュール管理
- パフォーマンスのチューニング
- EFSへの反映
- .htaccessの管理とWordPressプラグインの共存

#### Terraformのモジュール管理

Terrformで複数環境の管理を行う際ですが、方法として

- workspaceでの管理
- 純粋に環境ごとにリソースを定義

といった方法が考えられると思います。

今後の案件でも再利用したいと考えた場合、弊社の案件の性質上料金を抑えるために一つのリソースを複数環境で利用するというケース（例えば一つのRDS内に複数環境のDBを持つなど）が考えられるためworkspaceではなく、使うリソースを愚直に定義して管理する方法を取りました。

この時に愚直に管理をするにしても、ある程度のリソースは設定値が決まっていてその設定値を環境ごとに変えただけのコードが量産されることになるため、カプセル化のような形でリソース群をモジュールにまとめる構成としました。

このモジュールの単位ですが、基本的にそのリソース群で独立できる単位を一つのモジュールにまとめています。

具体的な例としては、ECSのサービス、タスク、EFSといったようなものを一つのモジュールとしています。

正直このモジュールの内容をどこまで汎用性を持たせるか、どこまでを一つのモジュールにするかは対応時にも悩みましたが、今でも悩んでる部分ではあります。

#### パフォーマンスのチューニング

チューニングについては自分としてもしっかり実施するのは初めてだったため、どの程度をボーダーとすべきか、という点がわからず苦心することが多かったです。

例えば、初期の時点では分間50UU程度のアクセスを想定していたチューニングをしていたのですが、PHP周りのチューニングを行なっていく中、最終的にRDSの接続数がボトルネックになるなど、最終的に費用をどこまでかけるか、という部分の判断が必要になった点は悩みどころでした。

最終的にRDSの接続数がギリギリ耐えられる程度のアクセス数を探る形で負荷をかけ、ここまでならギリギリ耐えられるといった形で他メンバーに共有を行いました。

また、チューニングについてはオートスケールの設定も行なっているため、スケールする閾値をどの程度にするのか、どの程度が続くとサイトを安定的に運用できなくなるのかを計測と判断に苦心をした印象です。

#### EFSの反映

EFSの反映ですが、どう反映すべきかという部分も悩みの種でした。

方法としては、

- Transfer Familyを経由してFTPで反映をする
- EFSマウント用のEC2を作成、EC2経由で反映をする
- CodeBuildでマウントしたEFSにCloneしてきた情報をコピーする
- DataSyncを利用してEFSに転送をする

といった方法が考えられました。

最終的にとった手法としてはDataSyncを使った方法を選択しました。

理由としては単純に金額の話であり、他の方法については月の費用がそこそこかかってしまうためです。

また、最初に作った際にはEFSに反映した際のパーミッションがApacheが書き込みができる権限では無かったため、その点についても調整が必要でした。

#### .htaccessの管理とWordPressプラグインの共存

正直苦労した点としてはこれが一番かもしれません。

というのも、WordPressプラグインとして[SiteGuard WP Plugin](https://www.jp-secure.com/siteguard_wp_plugin/)を導入していたのですが、このプラグインで機能を有効化するといくつかの機能についてはhtaccessを直接プラグインが書き換えを行います。

そのため、管理しているhtaccessを含めたWordPressをEFSに反映をするとプラグインが書き換えた情報が上書きされて消えてしまうということが発生していました。

最終的には初回反映後にhtaccessは反映対象から除外するというかなりの力技でいったん解消するには至りました。

### 今後の展望

今後の展望としては、こちらをベースにTerraformのモジュール管理、WordPressの管理方法、EFSへの反映方法について最適解を模索していきたいと考えています。

現時点では、お金がかかる分は仕方ないと割り切ってしまって、EFSへの反映にはDataSyncを使わない方法の方が安全牌と考えています。

## TerraformやAWS CDKといったIaCツールの導入

### 取り組み内容

弊社ではこれまでIaCは積極的に取り入れておらず、多くの案件では担当者ごとにコンソールから作成をしていました。

そのため、初期設計の資料はあるもののメンテナンスがされているのか、インフラ構築時の知見などが担当者のみで完結している状態でした。

そういった状態の解消や同じような環境の構築スピードアップのためにIaCの導入を進めています。

### 苦労した点

ひとえに言ってしまうとメンバーへの周知と教育という点が苦労している点ではあります。

自分自身が今まで積極的な発信をしてこなかった（聞かれたら答えたり、チーム内で口頭で喋るなどレベル）だったのでそもそもそこに関するスキルが不足しており、どうすべきか悩む点ではあります。

### 今後の展望

デファクトスタンダードにしようとしている動きのため、メンバー全員が自分でモジュールに作成や改修などが行えるレベルで理解ができるように周知と教育を進めていきたいと考えています。

## GitHub Enterprise Accountへの切り替え

### 取り組み内容

2年ほど前まで弊社では無料の枠でできる範囲でGitHubを利用していました。

しかし、それでは今後本格利用するためには色々と不都合があったため、今年の4月からGitHub Enterprise Accountの導入を行いました。

主に利用したかった機能としては、インナーソース用のリポジトリの可視性ですが、その他にも複数のオーガナイゼーションをGitHub Enterprise Accountに所属させることでEnterprise Organizationとして利用できたりするのも利点かと思います。

### 苦労した点

これに関しては主に社内フローの手続きが大変でした。

導入に際して、自分が代理店とのやりとりや法務部とやりとりを初めてしたためそれが大変だった印象です。

### 今後の展望

インナーソースの活用などを行い、開発メンバーの手間（車輪の再発明）などをある程度軽減できればなと思っています。

## OIDCを利用したAWSとGitHub Actionsの繋ぎ込み

### 取り組み内容

昨年あたりにAWSとGitHub ActionsがOIDCで連携ができるようになった情報が出ていたかと思います。

この情報が出てからも弊社ではしばらくの間は従来のアクセスキーを使用した連携をしていました。

しかし、セキュリティ面を鑑みて、3月以降の案件では基本的にOIDCでの連携を行うようにしています。

### 苦労した点

単純な話ですがこちらの対応をするにあたり、GitHub側のドキュメントの読み込みが足りず、GitHub側の一部機能を使用した際の連携でうまく連携ができず、時間的にその機能を利用した連携について断念することになりました。

具体的にはsubjectの設定に関して、[environemntを使用した際と使用してない際](https://docs.github.com/ja/actions/deployment/security-hardening-your-deployments/about-security-hardening-with-openid-connect#example-subject-claims)で構文が変わることに気づかず、environmentを使わずに連携を実施しました。

### 今後の展望

今後もOIDCでの連携を実施していきます。

また、OIDC連携についてはterraformのモジュール化を行なっているので、これのブラッシュアップも行っていきます。

## PHPで書いていたAPIをLambda用NodeJSコードにリライト

### 取り組み内容

#### NodeJSではなく一度Denoを検討

こちらの取り組みをNodeJSにする前に実は一度Denoでのリライトを進めていました。

TypeScriptがそのまま動くことや実際に動作が速いことなど利点が多く見られましたが、AWSサービスとの連携についてライブラリを介して行おうとした際に、Deno向けの公式APIはまだ無く、npmでインストールをしたAWS SDK for JavaScript v3も正常に動作せず、ある程度作成していた段階でDenoへのリライトを断念しました。

ライブラリを使わずに連携することも一つの手段だったとは思いますが、今回は時間的に独自実装はせずに公式ライブラリが利用できるNodeJSに転換することとしました。

#### テストコードの作成

今回の対応をするにあたり、Lambdaで確認しなくてもローカルで期待値が担保できるようにテストコードの作成を行いました。

このテストコードも初期はDenoで作成していたのですが、ほぼ手を入れることなくJestへの変更がしやすかったため転換後のチェックもスムーズに進めることができました。

#### GitHub Actionsを利用した自動テストの実施

今までGitHub Actionsはデプロイを行うためだけに利用していましたが、今回バックエンドのみで完結する内容ではあったため自動テストの導入を行いました。

導入した個人的所感としては、ある程度の担保がされるためリファクタリングに対する安心感が生まれていました。

### 苦労した点

一番苦労した点として、やはりDenoの導入がハードルが高かったように感じます。

Lambdaでの動作は比較的簡単に行えたのですが、ライブラリのimportなどがnpmなどのように簡易的に済まず、少し管理しにくい印象を受けました。

また、NodeJSに書き直した際にはmiddyというフレームワークを利用したのですが、これで利用するミドルウェアのコードを作成することが既存のミドルウェアコードを参考にしたりと少し苦労した印象です。

（コード自体はかなり軽量なので読む分には苦ではありません）

### 今後の展望

ひとまず作成したAPIがまだ日の目を見てはいないので、リリースを目指していく所存です。

また、今回作成したテストコードを参考にテストを書くということを啓蒙していこうかとも考えています。

## 全体を踏まえてのこれから

これまでの取り組みを振り返ったわけですが、これからの展望として個人的にはIaCでの管理方法やCI/CDの実施方法、テストコードの書き方などを自分が所属しているチームだけでなく、部署全体に広げていきたいなと感じました。

なので、これからはインナーに向けたナレッジの共有などを意識的に強めていこうかと思います。