LoginSignup
14
4

More than 3 years have passed since last update.

CircleCI Runnerのセットアップ

Last updated at Posted at 2020-12-05

はじめに

この記事は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によって構成されています。
Runner構成図

ローンチ エージェント (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で作成します。

/opt/circleci/launch-agent-config.yaml
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で作成します。

/opt/circleci/launch-task
#!/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で作成します。

/opt/circleci/circleci.service
[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を利用する場合は、machinetrueを設定し、resource_classに作成した名前を指定します。

config.yml
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の世界に触れてみてください。

14
4
1

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
14
4