はじめに
この記事はCircleCI Advent Calendar 2020の5日目の記事です。
CircleCIでソリューションズエンジニアをしている車井と言います。
2020年11月17日にCircleCI Runner(以下、Runner)がリリースされました。
Runnerは自分・自社で管理しているサーバをCircleCIのビルドサーバとして利用することが出来る機能です。
本記事の執筆時点ではまだ日本語のマニュアルが出ていませんが、細かなユースケースや制限事項などは本家のマニュアルにおまかせするとして、ここではとりあえず動かしてみたいと思います。
タイミングよく、先日のAWS re:Invent 2020で、EC2にMacが加わったというニュースもありましたので、今回はLinuxとMacの両方をRunnerとして動かしてみたいと思います。
トライしてみましたが、Macのインスタンスがうまく作れなかったので、ここではLinuxだけをセットアップしてみます。
なお、実際にRunnerを使うには事前にCircleCIに問い合わせて、鍵開けしてもらう必要があります。
もし使ってみたいという方は、問い合わせて見てください。
Runnerの構成要素
Runnerは下記の図に記載されているとおり、Launch AgentとTask Agentによって構成されています。
- ローンチ エージェント (launch-agent)
- CircleCI本体と通信して必要な情報を収集したり、タスクエージェントを起動したりします。
- タスク エージェント (task-agent)
- 1つ1つのタスクの実行を行います。
すなわち、この2つのエージェントをセットアップすれば動くことになりますが、実際にはタスクエージェントはダウンロードしてきたものをそのまま動かすだけですので、ローンチエージェントの設定が主な作業になります。
なお、図でもわかるとおり、永続化が必要なデータ(キャッシュデータやアーティファクトなど)はCircleCIが管理しているストレージ領域に保存されるため、Runner専用の領域を別に作成する必要はありません。
事前準備
Runnerをセットアップするには、事前に名前空間、リソースクラス、認証トークンを作成しておく必要があります。
これらの作成にはCircleCI CLI(コマンドラインツール)をインストールしておく必要があります。CircleCI CLIのインストール方法はこちらのマニュアルを参照してください。
まず、名前空間を作成します。名前空間はVCS(GitHubやBitbucket)上の組織に対して一意に割り当てることができる名前です。
# circleci create <名前空間名> <VCS種別> <Org名>
VCS種別は"github"か"bitbucket"を指定しますので、例えば私の https://github.com/kurumai というOrgに対して "kurumai"という名前空間を作成する場合は下記のコマンドを実行します。
# circleci namespace create kurumai github kurumai
これで名前空間が出来ましたので、次にリソースクラス名を登録します。
# circleci runner resource-class create <resource-class> <description>
<resource-class>
には"名前空間/リソースクラス名"の書式で指定します。
リソースクラス名は任意で構いませんが、CircleCIのconfig.ymlで実行環境として指定する値になりますので、サーバの種類や特性を表す文字列が分かりやすいと思います。
今回はCircleCIの標準の実行環境にはない、Armベースのプロセッサを搭載しているAWS EC2のa1.medium
をリソースクラスとして登録してみたいので、arm-runner
という名前で登録しました。
# circleci runner resource-class create kurumai/arm-runner "Arm runner"
+--------------------+-------------+
| RESOURCE CLASS | DESCRIPTION |
+--------------------+-------------+
| kurumai/arm-runner | Arm runner |
+--------------------+-------------+
最後に、これらのリソースクラスを認証するためのトークンを作成しておきます。
# circleci runner token create <resource-class> <nickname>
nicknameは任意で構いません。
ここではリソースクラスと同じ名前を使っています。
# circleci runner token create kurumai/arm-runner arm-runner
api:
auth_token: ********
これで事前準備は完了です。
Arm Runnerのセットアップ
まず、 a1.medium
タイプのEC2インスタンスにRunnerをセットアップします。OSはUbuntuで東京リージョンに作成しています。
セキュリティグループはアウトバウンドはすべて許可、インバウンドはセットアップのためにSSH(22)だけを許可しています。
RunnerはCircleCIに対してポーリングしてジョブを実行しますので、CircleCI側から(インターネット側から)の通信は許可する必要はありません。
それでは、SSHでログインして、まずはエージェントモジュールをダウンロードします。
いきなりいろいろなものを実行していますが、1行目の platform=linux/arm64
だけ環境によって変更する必要がありますが、それ以外はマニュアルをそのままコピー&ペーストすれば動くと思います。
platform=linux/arm64
prefix=/opt/circleci
sudo mkdir -p "$prefix/workdir"
base_url="https://circleci-binary-releases.s3.amazonaws.com/circleci-launch-agent"
echo "Determining latest version of CircleCI Launch Agent"
agent_version=$(curl "$base_url/release.txt")
echo "Using CircleCI Launch Agent version $agent_version"
echo "Downloading and verifying CircleCI Launch Agent Binary"
curl -sSL "$base_url/$agent_version/checksums.txt" -o checksums.txt
file="$(grep -F "$platform" checksums.txt | cut -d ' ' -f 2)"
file="${file:1}"
mkdir -p "$platform"
echo "Downloading CircleCI Launch Agent: $file"
curl --compressed -L "$base_url/$agent_version/$file" -o "$file"
echo "Verifying CircleCI Launch Agent download"
sha256sum --check --ignore-missing checksums.txt && chmod +x "$file"; sudo cp "$file" "$prefix/circleci-launch-agent" || echo "Invalid checksum for CircleCI Launch Agent, please try download again"
次に /opt/circleci/launch-agent-config.yaml
オーナーをroot、パーミッションは600で作成します。
api:
auth_token: AUTH_TOKEN <- こちらに先程取得したトークン文字列を記載します
runner:
name: RUNNER_NAME <- こちらは任意の名前で構いません
command_prefix: ["/opt/circleci/launch-task"]
working_directory: /opt/circleci/workdir/%s
cleanup_working_directory: true
エージェントを実行するためのユーザーを作成します。
ここでは circleci
というユーザーを作成しています。
id -u circleci &>/dev/null || adduser --uid 1500 --disabled-password --gecos GECOS circleci
mkdir -p /opt/circleci/workdir
chown -R circleci /opt/circleci/workdir
ローンチエージェントのスクリプトを /opt/circleci/launch-task
とし、オーナーをroot、パーミッションは755で作成します。
#!/bin/bash
set -euo pipefail
## This script launches the build-agent using systemd-run in order to create a
## cgroup which will capture all child processes so they're cleaned up correctly
## on exit.
# The user to run the build-agent as - must be numeric
USER_ID=$(id -u circleci)
# Give the transient systemd unit an inteligible name
unit="circleci-$CIRCLECI_LAUNCH_ID"
# When this process exits, tell the systemd unit to shut down
abort() {
if systemctl is-active --quiet "$unit"; then
systemctl stop "$unit"
fi
}
trap abort EXIT
systemd-run \
--pipe --collect --quiet --wait \
--uid "$USER_ID" --unit "$unit" -- "$@"
ローンチエージェントをサービスとして起動するため、/opt/circleci/circleci.service
ファイルを作成します。先程と同様にオーナーはroot、パーミッションは755で作成します。
[Unit]
Description=CircleCI Runner
After=network.target
[Service]
ExecStart=/opt/circleci/circleci-launch-agent --config /opt/circleci/launch-agent-config.yaml
Restart=always
User=root
NotifyAccess=exec
TimeoutStopSec=18300
[Install]
WantedBy = multi-user.target
サービスを起動します。
systemctl enable /opt/circleci/circleci.service
正常に動いているかどうか確認しておきます。
systemctl start circleci.service
これでセットアップは完了です。
それでは、正しく動くかどうかチェックしてみます。
CircleCIの config.yml
を下記のように作って動かしてみました。
Runnerを利用する場合は、machine
にtrue
を設定し、resource_class
に作成した名前を指定します。
version: 2
jobs:
prepare:
docker:
- image: circleci/node:latest
steps:
- checkout
- run:
name: Generate temp file
command: |
mkdir -p tmp
echo "Hello CircleCI!!" > tmp/hello.txt
- persist_to_workspace:
root: .
paths:
- "tmp"
arm-runner:
machine: true
resource_class: kurumai/arm-runner
steps:
- checkout
- attach_workspace:
at: .
- run: cat tmp/hello.txt
workflows:
version: 2
runner-workflow:
jobs:
- prepare
- arm-runner:
requires:
- prepare
結果です。なんとかちゃんと動きました。
もしジョブがキューの状態で動かない場合は、サービスがちゃんと動いているのかや、設定を変更した場合はサービスを再起動したかどうかを確認すると良いと思います。
実際、私も設定を変更したにも関わらず、サービスを再起動するのを忘れてはまりかけました。
おわりに
CircleCI Runnerをセットアップして、通常のCircleCIのExecutorと組み合わせたワークフローを動かしてみました。
セットアップは手作業が伴いますが、それほどはまるところは多くはないと思いますので、ぜひ興味のあるかたはトライしてみてください。
Runnerをうまく使うことで、スケーラビリティが必要なテストはCircleCIの標準のものを使い、セキュリティが気になるデプロイのところだけRunnerを使うということが簡単にできるようになりました。
また、これまではテストが難しかった組み込み系のシステムでもRunnerは活躍できるのではないかと思っています。
CI/CDはWebやモバイルアプリのサービス開発を中心にSaaS利用が広まっていますが、まだまだソフトウェア開発の世界にはCI/CDに着手できていないところがいっぱいあると思います。ぜひ、この機会にCircleCIを触ってみてCI/CDの世界に触れてみてください。