この記事は株式会社クロノスの「~2020年春~勝手にやりますアドベントカレンダー」の8日目の記事です!
TL;DR
- GitLab & GitLab CIを
- Docker(docker-compose)使って
- サクッと立てちまう
- (しかもオートスケール対応しちまう)
企業内での開発などクローズドな開発はよくあると思います。
リポジトリやCIなんかも、外部サービスは好まれず、、そんな環境はまだまだ沢山あるんだと思います。
で、そんな中でもちゃんとCI/CDしたい!
でも、、GitLabとか知ってるけど、、セットアップとか結構大変そう…とか思ってるヒトに向けた記事です。
まずは動かすところまで最速で行こう。
注意: とりあえず動かすまでなので、あんまり細かいところは書いてません
前提
今回はAWS上でDockerやdocker-composeを使ってセットアップします。
ここらへんがある程度触れるヒト向けの記事です。
(とは言え、何回か触ったことあるぐらいで十分だと思います)
主な登場ツール達
GitLab
ひとことで言うと「GitHubクローン」。
Gitリモートリポジトリの管理を中心にIssue管理やマージリクエスト(プルリクエスト)&レビュー機能がある。Ruby製。
GitLab CI
GitLabへのGitプッシュなどをトリガーにジョブを実行。ビルドパイプラインを構築できるCI/CDツール
その他
- AWS EC2
- Docker
- docker-compose
もはや説明不要と思われるため割愛。
レシピ
1. まずは動かす場所を用意
GitLabを動かすサーバを用意しましょう。
今回はEC2インスタンス上で動かします。
- インスタンスタイプ: t2.medium
- AMI: AmazonLinux2
その他はお好みで。
詳しく手順が知りたい方はこちらとかを参考に。
1点注意としては、インスタンスタイプがt2.medium
より小さいとGitLab自体が動いてくれません(なのでAWS無料枠じゃ試せない...)
2. Docker(+ docker-compose)インストール
今回のレシピでは、DockerコンテナでGitLabを実行します。
逆にDocker以外はインストール不要。
AmazonLinux2上でのインストールコマンドは↓
sudo yum update -y
# Dockerインストール
sudo yum install -y docker
sudo service docker start
sudo usermod -a -G docker ec2-user
sudo systemctl enable docker
# docker-composeインストール
sudo curl -L https://github.com/docker/compose/releases/download/1.25.4/docker-compose-`uname -s`-`uname -m` -o /usr/local/bin/docker-compose
sudo chmod +x /usr/local/bin/docker-compose
特筆することはなく、、
一応インストールされたかバージョン確認しときましよう。
$ docker -v
Docker version 18.09.9-ce, build 039a7df
$ docker-compose -v
docker-compose version 1.25.4, build 8d51620a
3. GitLabのセットアップ
ここから本題。
まずは本体であるGitLabをセットアップ。
GitLabはありがたいことにDockerイメージを公開してくれてる。なので、細かいインストール作業は不要。
docker-compose
で起動するための設定ファイルdocker-compose.yml
を書きます。
version: '3'
services:
gitlab:
image: 'gitlab/gitlab-ce:latest'
restart: always
hostname: 'your_domain'
environment:
GITLAB_OMNIBUS_CONFIG: |
external_url 'http://your_domain/'
gitlab_rails['gitlab_shell_ssh_port'] = 4022
ports:
- '80:80'
- '443:443'
- '4022:22'
volumes:
- '/srv/gitlab/config:/etc/gitlab'
- '/srv/gitlab/logs:/var/log/gitlab'
- '/srv/gitlab/data:/var/opt/gitlab'
細かい説明は端折りますが、GITLAB_OMNIBUS_CONFIG
(Dockerコンテナ内で使用される環境変数)がGitLab自体の詳細な設定ができる部分。
この設定はオフィシャルでも紹介されています。(ほぼそのまま、、)
↑ファイルをEC2インスタンスの適当なパスに配置して実行してみましょう。
cd ~
vim docker-compose.yml # ↑を参考にファイル編集
docker-compose up -d gitlab # GitLab起動
たったこれだけで、プライベートなGitリポジトリ環境が起動しました!
(t2.mediumだと少し起動に時間かかるんで数分してから)EC2へhttpアクセスしてみましょう。
初回アクセス時にrootユーザーパスワードとファーストユーザーの登録を求められます。お好みで。
4. GitLab CIセットアップ
さてさてここからが真打ち。
CI/CD環境としてGitLab CI
をセットアップしていきます。
GitLab CIの実態としては GitLab Runner
というアプリケーションになります。
GitLab Runner
がGitLabの変更を検知して、Gitリポジトリから最新srcを取得、設定ファイルに従ってビルド処理を実行する仕組みです。
GitLab Runnerも本体同様Dockerイメージが公開されているので、それを使っていきます。
↑で作成した docker-compose.yml
に↓のrunner設定を書き加えます。
runner:
image: 'gitlab/gitlab-runner:latest'
restart: always
volumes:
- /srv/gitlab-runner/config:/etc/gitlab-runner
- /var/run/docker.sock:/var/run/docker.sock
できたら起動
docker-compose up -d runner # GitLab Runner起動
起動しただけだと、まだCIはできません。
GitLab Runner
とGitLab
を接続する設定が必要です。
設定をするための事前準備として、↓の2つの情報をGitLabにアクセスして取得します。
- URL(GitLabのURL)
- トークン
この情報はGitLab上の /admin/runners
パスにアクセスすることで確認できます。
↑パスは管理者権限でしかアクセスできません。rootユーザー
でログインしてアクセスしましょう(user: root / password: 初回アクセス時に設定したパスワード)
2つの情報が確認できたら、↓コマンドを実行して設定していきます。
docker-compose exec runner gitlab-runner register
コマンドライン上で質問に答えていきます。(実際の質問内容はこちら)
設定が完了すると、↓パスに設定ファイルが生成されます。
/srv/gitlab-runner/config/config.toml
以下のように設定すると恐らくこんな感じの設定になっているはず。
- gitlab-ci coordinator URL: http://your_domain/
- gitlab-ci token: token
- gitlab-ci description for this runner: default-runner
- gitlab-ci tags for this runner: (空)
- executor: docker
- Docker image: alpine
concurrent = 1
check_interval = 0
[session_server]
session_timeout = 1800
[[runners]]
name = "default-runner"
url = "http://your_domain/"
token = "token"
executor = "docker"
[runners.custom_build_dir]
[runners.cache]
[runners.cache.s3]
[runners.cache.gcs]
[runners.docker]
tls_verify = false
image = "alpine"
privileged = true
disable_entrypoint_overwrite = false
oom_kill_disable = false
disable_cache = false
volumes = ["/cache"]
shm_size = 0
これでとりあえずのCI環境は完了です。
なにかサンプルsrcがあれば実際にGitLabでリポジトリを作成してpushしてみてください。
プロジェクト側に配置するCIパイプラインの設定方法は↓
5. GitLab CI Runnerをオートスケール対応
ソロプロジェクトであれば前段の設定まででも十分使えると思うのでここはいらないかもしれませんが、
今回はもう少し踏み込んで、複数エンジニアが活躍するプロジェクトを想定します。
複数人の開発になると、当然同時にpushすることもあり、CI/CDジョブを並列で処理する必要があります。
また、開発が進むとビルドやテストに必要なリソースはかなり大きくなる場合もあります。
(↑設定のような単体サーバでビルドは結構早めに限界を迎えます)
そんな環境のためにGitLabはRunnerをオートスケールする手段を提供しています。
https://docs.gitlab.com/runner/configuration/runner_autoscale_aws/
具体的にはCIビルドジョブ毎にRunnerをEC2インスタンスとして起動することで、同時多発的に発生するビルド処理をさばいていくと。素晴らしい。
先に結論を書くと、設定ファイルを↓のように書き換えるとそうなります。
concurrent = 10
check_interval = 0
[session_server]
session_timeout = 1800
[[runners]]
name = "default-runner"
url = "http://your_domain/"
token = "token"
executor = "docker+machine"
[runners.custom_build_dir]
[runners.cache]
[runners.cache.s3]
[runners.cache.gcs]
[runners.docker]
tls_verify = false
image = "alpine"
privileged = true
disable_entrypoint_overwrite = false
oom_kill_disable = false
disable_cache = false
volumes = ["/cache"]
shm_size = 0
[runners.machine]
IdleCount = 1
IdleTime = 1800
MaxBuilds = 100
OffPeakPeriods = [
"* * 0-9,18-23 * * mon-fri *",
"* * * * * sat,sun *"
]
OffPeakIdleCount = 0
OffPeakIdleTime = 1200
MachineDriver = "amazonec2"
MachineName = "gitlab-docker-machine-%s"
MachineOptions = [
"amazonec2-access-key=accesskey",
"amazonec2-secret-key=secret",
"amazonec2-region=us-east-1",
"amazonec2-zone=d",
"amazonec2-vpc-id=vpc-xxxxxx",
"amazonec2-subnet-id=subnet-xxxxxx",
"amazonec2-use-private-address=true",
"amazonec2-tags=runner-manager-name,gitlab-aws-autoscaler,gitlab,true,gitlab-runner-autoscale,true",
"amazonec2-security-group=default",
"amazonec2-instance-type=t2.micro",
"amazonec2-request-spot-instance=true",
]
ポイントをまとめます。
concurrent = 10
同時並列実行数を決めます
executor = "docker+machine"
dockerからdocker+machineへ変更しました。
Docker Machineは "仮想マシン上に Docker Engine をインストールするツール" であり、ネットワークを経由した先のインスタンスにもDockerをセットアップした上で実行環境として接続できるようになるツールです。
Docker Machine オフィシャル
この仕組を使って、EC2インスタンスをDocker化し、ジョブ実行環境として使用します。(とてもおもしろい!)
今回はAWS EC2でのセットアップですが、Docker Machineが扱える接続先ならどこでもこの仕組みでノード化できるので、DigitalOceanなんかも対象にできます。
素晴らしい仕組みなんですが、Docker MachineがWindowsOSには対応していない、、ので"docker+machine"executorのオートスケールは今のところWindows非対応のようです
https://gitlab.com/gitlab-org/gitlab-runner/issues/4582
MachineOptions
ここが今回の設定の一番肝な部分ですが、この設定がAWS上に自動作成されるEC2インスタンスの各種オプションになります。
設定内容はDocker MachineのAWSオプションと同じなので、詳しくは←を参照しながら設定を調整してください。
ここもいくつかポイントだけ紹介しておきます。
amazonec2-zone
EC2インスタンスを作成するアベイラビリティゾーンの設定です。
今回のデモ環境を適当に作ったらデフォルトでus-east-1d
で作成してしまい、この設定がないとデフォルトAZはa
で自動設定されるのでVPCがないとか怒られました、、
amazonec2-security-group
EC2インスタンスに設定されるセキュリティグループの指定です。
セキュリティグループIDではなくセキュリティグループ名で指定する必要があります。
ここの指定がないとdocker-machineというsshとDockerポートがIPフル開放(0.0.0.0/0)のセキュリティグループが自動生成されて勝手に設定されます。
折角のブライベートな環境が台無しです。。
amazonec2-request-spot-instance
EC2にはスポットインスタンスという素敵な仕組みがあります。
すごいざっくり言うと、空いてるいるインスタンスが安く叩き売られる仕組みです。
必ず安くなるわけではないですし、安くなる分強制停止されたりするらしいですが、ビルド処理にそこまで高い可用性を求める必要もないかと思われるので、お財布に優しい方がより良いかと。
(もちろんCI/CDの処理内容によります、適切に判断してください!)
説明は一旦ここまで。
設定ファイル(config.toml)を書き換えるとrunnerが自動で読み込み直してくれます。
CIを実行するとEC2スポットインスタンスが自動で作られて処理されるはず。
試してみてください。
まとめ
便利な世の中になったもんだ!
"こうしたい" がすぐに実現できる。(実際今回も2つの設定ファイルと数コマンド実行だけでそれなりに動く環境ができた)
特にDocker周りの知識があれば、環境周りや下準備の初速をかなり上げれると思います。
またスケールしやすいことや、環境の情報がすべてコード化できる点もすごいメリット。
本質に注力するためにも、その他のことにエネルギーをさかない技術も大事。
Enjoy!!
感謝&参考資料
- https://qiita.com/C910/items/772329aa2d59a7f9236d
- https://qiita.com/str416yb/items/2932052a6ead78c167e4
- https://qiita.com/TomoyukiSugiyama/items/b17800d4e142e3dc549b
- https://aimstogeek.hatenablog.com/entry/2020/03/02/080000
- https://dev.classmethod.jp/ci/gitlab-runner-ci-cd-1/
- https://tech.myrefer.co.jp/entry/infrastructure_1
- https://docs.gitlab.com/omnibus/docker/
- https://docs.gitlab.com/runner/
あと、このアドベントカレンダーの仲間たち