はじめに
こんにちは!虎の穴ラボの鷺山です。
業務の効率化のために社内用ツールサーバーを作って活用することは、よく行われる取り組みだと思います。
弊社も同様にツールサーバーで既製ツールや自製ツールのホスティングを行い、さまざまなタスクを効率化しています。
ただ、このようなツールサーバーは手動でセットアップされることが多いと思います。 SSHで接続し、コマンドを実行して構築するような方法です。 また、ツールサーバーは(顧客向けの本番サーバーと比べて)優先度が低く、バックアップの対応が後回しになりがちです。
その結果、何らかのトラブルでツールサーバーが使えなくなると手動で一から環境を再構築し直すことになり、復旧に手間と時間を要してしまいます。近年はランサムウェアなどの脅威も増加しており、社内用サーバーであっても攻撃リスクを軽視できなくなっています。
そこで今回は、この問題を解決する一つの方法として「AWSのEC2オートスケーリングを使ってツールサーバーを毎日自動で作り直す」アプローチを紹介します。
目次
- はじめに
- 実現のためのポイント
- 1. 各ツールのセットアップコマンドの明確化
- 2. EC2起動テンプレートの活用
- 3. EC2オートスケーリングによる「サーバー再構築」のスケジュール化
- まとめ
- 採用情報
前提
- ツールサーバーはAWSのEC2を使用します。
- 使用するAMIはAmazon Linux 2023です。
- 1台のサーバーで複数のツールをホスティングします。
- 各ツールのリソースはGitHubリポジトリに登録済みであると仮定します。
全体像
本記事で紹介する仕組みの全体像を示します。
今回のアプローチの利点
今回紹介する「ツールサーバーを毎日自動で作り直す」アプローチにはいくつかのメリットがあります。
- いつでも再構築が可能な環境の実現
- 環境を自動で再構築する仕組みを導入することで、トラブル発生時にも素早く復旧できるようになります。
- 手作業による構築ミスを防止できます。
- スクリプトや設定ファイルの不備があっても、毎日の再構築プロセスで早期発見できます。
- セキュリティリスクの軽減
- 毎日サーバーを新しくすることで、不正アクセスやランサムウェアによる攻撃の影響を最小化できます。
- 仮に攻撃を受けても、翌日には新しい環境に置き換えられるため、継続的な被害を防げます。
- 常に最新のOS、パッケージ、ライブラリを利用可能な状態を維持できます。
- アップデートの遅れによるセキュリティホールを未然に防ぐことができます。
- 毎日サーバーを新しくすることで、不正アクセスやランサムウェアによる攻撃の影響を最小化できます。
実現のためのポイント
「ツールサーバーを毎日自動で作り直す」仕組みを実現するための技術的なポイントは以下の3点です。
- 各ツールのセットアップコマンドの明確化
- EC2起動テンプレートの活用
- EC2オートスケーリングによる「サーバー再構築」のスケジュール化
次のセクションからそれぞれの詳細を解説します。
1. 各ツールのセットアップコマンドの明確化
各ツールのセットアップや起動に必要なコマンドを事前に明確化しておきます。
(例: npm install && npm run dev
など)
あるいはDockerやDocker Composeで実行できるように、Dockerfile
や docker-compose.yml
を整備しておきます。
2. EC2起動テンプレートの活用
EC2の起動テンプレートに設定できるユーザーデータ(本記事では以降「初回構築スクリプト」と呼びます)を使うと、サーバーの初回起動時に指定したコマンドを自動実行できます。
これを使って、EC2起動後の初期化プロセス内で各ツールのセットアップと起動が自動で完了するようにします。
- まず、スクリプトの冒頭で必要なパッケージをインストールします。
- 次に、各ツールのリソースをGitHubリポジトリから取得 (
git clone
) します。 - そして「事前に明確化したセットアップコマンド」を使って、各ツールをセットアップして起動します。
以下は初回構築スクリプトの記述例です。
#!/bin/bash set -euox pipefail # システムアップデートと必要パッケージのインストール dnf update -y dnf install -y docker git # Dockerのセットアップ systemctl start docker systemctl enable docker usermod -aG docker ec2-user # Docker Composeのセットアップ su - ec2-user -c ' COMPOSE_VERSION=$(curl -s https://api.github.com/repos/docker/compose/releases/latest | grep 'tag_name' | cut -d\" -f4) mkdir -p ~/.docker/cli-plugins curl -L "https://github.com/docker/compose/releases/download/${COMPOSE_VERSION}/docker-compose-$(uname -s)-$(uname -m)" -o ~/.docker/cli-plugins/docker-compose chmod +x ~/.docker/cli-plugins/docker-compose ' # GitHubへの接続準備 su - ec2-user -c ' aws ssm get-parameter --name "github-deploy-key" --query "Parameter.Value" --output text --with-decryption > ~/.ssh/github_deploy_key aws ssm get-parameter --name "github-ssh-config" --query "Parameter.Value" --output text > ~/.ssh/config chmod 600 ~/.ssh/github_deploy_key chmod 600 ~/.ssh/config ssh -o StrictHostKeyChecking=accept-new git@github.com || true ' # ツールの起動 su - ec2-user -c ' git clone --depth 1 git@github.com:XXXXX/my-tool-server.git cd my-tool-server docker compose up -d '
それぞれのステップについて詳しく解説します。
2.1. 事前準備
#!/bin/bash set -euox pipefail
- ユーザーデータのシェルスクリプトは
#!/bin/bash
から始めます(※ Bashを使う場合)。 set -euox pipefail
はスクリプトを安全に実行し、デバッグしやすくするための設定です。- Amazon Linux 2023の場合、初期化プロセスのログは
/var/log/cloud-init-output.log
に出力されます。このログからスクリプトの実行結果を確認できます。
# システムアップデートと必要パッケージのインストール dnf update -y dnf install -y docker git
- システムアップデートを実施して、必要なパッケージ(DockerやGitなど)をインストールします。
- もし他に必要なパッケージがあれば、ここに追加することができます。
dnf install -y docker git nodejs ...
2.2. DockerやDocker Composeのセットアップ
# Dockerのセットアップ systemctl start docker systemctl enable docker usermod -aG docker ec2-user
# Docker Composeのセットアップ su - ec2-user -c ' COMPOSE_VERSION=$(curl -s https://api.github.com/repos/docker/compose/releases/latest | grep 'tag_name' | cut -d\" -f4) mkdir -p ~/.docker/cli-plugins curl -L "https://github.com/docker/compose/releases/download/${COMPOSE_VERSION}/docker-compose-$(uname -s)-$(uname -m)" -o ~/.docker/cli-plugins/docker-compose chmod +x ~/.docker/cli-plugins/docker-compose '
- DockerおよびDocker Composeをセットアップしています。
- Docker Composeは
su
でユーザーを切り替えてec2-user
にインストールしています。 - 参考: Where to get Docker Compose
- Docker Composeは
- DockerやDocker Composeを使わない場合はスキップ可能です。
2.3. GitHubへの接続準備
ツールサーバーのリソースをGitHubリポジトリから取得するための準備をします。
対象がプライベートリポジトリの場合は、必要な認証を通す必要があります。
本記事ではデプロイキーによる認証方法を紹介します。ローカルで公開鍵と秘密鍵のペアを生成し、公開鍵を対象のGitHubリポジトリに、秘密鍵をAWS Systems Managerに登録します。
ローカルでの公開鍵と秘密鍵の生成には ssh-keygen
コマンドなどを使用します。
ssh-keygen -t ed25519 -C "your_email@example.com" -f ~/.ssh/github_deploy_key
生成した公開鍵は、対象のリポジトリにデプロイキーとして登録します。
秘密鍵の方は、Systems Managerのパラメータストアに登録します。秘密鍵は秘匿性が高いので「安全な文字列 (SecureString)」として登録します。 パラメータ名は github-deploy-key
を設定します。
あわせて、GitHubへのSSH接続に必要な設定ファイルもパラメータストアに登録します。パラメータ名は github-ssh-config
を設定します。
Host github.com HostName github.com IdentityFile ~/.ssh/github_deploy_key User git
そして、初回構築スクリプトでGitHubへの接続設定を以下のように記述します。
# GitHubへの接続準備 su - ec2-user -c ' aws ssm get-parameter --name "github-deploy-key" --query "Parameter.Value" --output text --with-decryption > ~/.ssh/github_deploy_key aws ssm get-parameter --name "github-ssh-config" --query "Parameter.Value" --output text > ~/.ssh/config chmod 600 ~/.ssh/github_deploy_key chmod 600 ~/.ssh/config ssh -o StrictHostKeyChecking=accept-new git@github.com || true '
su
コマンドでユーザーを切り替えて、ec2-user
ユーザーとして実行します。aws ssm
コマンドで、パラメータストアに登録したgithub-deploy-key
やgithub-ssh-config
を読み出し、それぞれをファイルパス~/.ssh/github_deploy_key
や~/.ssh/config
に保存します。- 「安全な文字列」を読み出す際は、
--with-decryption
オプションが必要です。
- 「安全な文字列」を読み出す際は、
chmod 600
コマンドで、保存したファイルに適切な権限を設定します。ssh -o StrictHostKeyChecking=accept-new git@github.com
で github.com をknown_hosts
に登録します。
なお aws ssm
コマンドの実行には、起動テンプレートのIAMインスタンスプロフィールに ssm:GetParameter
の許可ポリシーを設定する必要があります。
{ "Effect": "Allow", "Action": "ssm:GetParameter", "Resource": [ "arn:aws:ssm:ap-northeast-1:123456789012:parameter/github-deploy-key", "arn:aws:ssm:ap-northeast-1:123456789012:parameter/github-ssh-config" ] }
2.4. 各ツールのセットアップと起動
各ツールのリソースをGitHubから取得し、セットアップと起動を行います。
リポジトリのクローンは以下のコマンドで実行します(対象のリポジトリを XXXXX/my-tool-server
と仮定します)。
git clone --depth 1 git@github.com:XXXXX/my-tool-server.git
リポジトリをクローンしたら「事前に明確化したセットアップコマンド」を使って、各ツールをセットアップして起動します。
ツールがDocker Composeに対応している場合は、以下のように記述します。
su - ec2-user -c ' git clone --depth 1 git@github.com:XXXXX/my-tool-server.git cd my-tool-server docker compose up -d '
Node.jsアプリケーションの場合は、たとえば以下のように記述します。
su - ec2-user -c ' git clone --depth 1 git@github.com:XXXXX/my-tool-server.git cd my-tool-server npm install nohup npm run dev > output.log 2>&1 & '
参考: cron の設定方法
cron を使用して、ツールサーバーで何らかの処理をスケジュール実行させるケースは多いと思います。
初回構築スクリプトでそれを設定する方法を紹介します。
タイムゾーンの設定
まず、サーバーのタイムゾーンをローカル時間に合わせておきます。 AWSのEC2はデフォルトがUTC時間になっており、ローカル時間と異なると設定ミスや混乱を招く可能性があります。 以下は日本時間に合わせるための例です。
timedatectl set-timezone Asia/Tokyo
cronie のセットアップ
Amazon Linux 2023はデフォルトではcronを使用できません。このため、同機能を提供するcronieパッケージをインストールする必要があります。
dnf install -y cronie
インストール後は、crondサービスを起動する必要があります。
systemctl start crond
systemctl enable crond
crontab エントリーの登録
初回構築スクリプトの中でcrontabのエントリーを記述して登録できます。
su - ec2-user -c " echo \"0-58/2 * * * * echo 'Hello!' >> ~/greetings.txt\" >> mycron echo \"1-59/2 * * * * echo 'Goodbye!' >> ~/greetings.txt\" >> mycron crontab mycron && rm mycron "
あるいは、crontabの設定ファイルをあらかじめGitHubリポジトリに登録しておき、それを使うこともできます。
su - ec2-user -c ' git clone --depth 1 git@github.com:XXXXX/my-tool-server.git ... crontab my-tool-server/mycron '
まとめると以下のようになります。
timedatectl set-timezone Asia/Tokyo dnf install -y cronie systemctl start crond systemctl enable crond su - ec2-user -c " echo \"0-58/2 * * * * echo 'Hello!' >> ~/greetings.txt\" >> mycron echo \"1-59/2 * * * * echo 'Goodbye!' >> ~/greetings.txt\" >> mycron crontab mycron && rm mycron "
3. EC2オートスケーリングによる「サーバー再構築」のスケジュール化
EC2オートスケーリングの予定されたアクション (Scheduled Scaling) と前述の起動テンプレート(初回構築スクリプト)を組み合わせることで、「ツールサーバーを毎日自動で作り直す」仕組みを構築できます。
まず、ツールサーバー用のオートスケーリンググループを作成します。このとき、起動テンプレートには前のセクションで作成したものを指定します。
オートスケーリンググループを作成後、オートスケーリングタブ内の予定されたアクションから、ツールサーバーの構築と破棄をスケジューリングできます。スケジュールは予定されたアクションを作成するから追加できます。
ここで、希望するキャパシティ(サーバー台数)を「業務時間外は 0」「業務時間内は 1」に設定することで、夜間はサーバーを落としつつ、毎朝の始業時にサーバーが自動構築される仕組みを実現します。
これにより、毎日のサーバー再構築プロセスを自動化すると同時に、夜間の稼働コストも削減できます。
以下は「21時に停止」して「9時に起動」するための設定例です。
(セットアップにかかる時間を考慮して開始時間を8時55分に設定しています。)
⚠注意点
オートスケーリングを使用すると、EC2インスタンスのIPアドレスが固定されなくなる点にご注意ください。固定のURLが必要な場合はロードバランサーの導入などが必要になります。
まとめ
起動テンプレートとオートスケーリングを活用した「ツールサーバーを毎日自動で作り直す」仕組みの構築方法を紹介しました。
すでにGitHubにツール類を登録してある場合には、導入しやすいアプローチなのではないかと思います。
本記事が皆様の社内環境効率化の一助になれば幸いです!
採用情報
虎の穴ラボでは一緒に働く仲間を募集中です!
この記事を読んで、興味を持っていただけた方はぜひ弊社の採用情報をご覧ください。
toranoana-lab.co.jp