環境構築

継続的インテグレーション(GitLab CI)をはじめてみました

こんにちは、インフラエンジニアのトシです。

社内GitLabを更新して継続的インテグレーションツール(GitLab CI)の使用を開始しました!!

継続的インテグレーションとは


まずはじめに、継続的インテグレーション(以下CIとします)とは何でしょうか。簡単に言うと「定型的な作業を自動化しよう」のことです。

CIを行なうことによって、例えば次のようなケースの手作業を効率化できます。

  • コーディング規約が守られているかをチェックしたい
  • 使われていないプログラムや重複した機能のプログラムがないかチェックしたい
  • ユニットテストをしたい
  • ソースコードをコンパイルしたい

例に上げたものは、統合開発環境で開発をしていれば、簡単に行なうことができることばかりです。
規約などはコードレビューの際にチェックするようにすれば十分、と思われる方もいると思います。
しかし、そうは言っても、手作業に任せていると、チェックされないことも起こります。
実際に弊社の某プロジェクトでは、久しぶりにコードの静的解析を行なったところ、あまりコーディング規約が守られていなかったため、警告やエラーが大量に検出されてしまった。。。といったことも過去には発生しています。

CIをおこない、上記のような作業を自動化することによって、手作業で行なっていた時間を品質向上や新しい技術への挑戦などができるようになり、生産性向上ができると私は信じています。

今回は社内のGitLabサーバーを更新して、カタリストシステムでも継続的インテグレーションツールのGitLab CIを使い始めましたので、構成や構築方法について紹介いたします。

GitLab CIって何?といった方や、GitLab CIを始めたいが何をすればよいのかわからない、といったような方の参考になれば幸いです。

GitLabサーバー更新の経緯と方針および内容

旧GitLabサーバーは下記のスペックのサーバーにLinux KVMを使用してサーバーを構築していました。

CPU:Intel Xeon E5 2420 @ 1.9GHz
メモリー:16GB
HDD:3TB×2 Raid1

このスペックのうち、CPU 4 コア、メモリー 8 GBを割当てて、旧GitLabサーバーを動かしていました。
しかし、GitLabサーバーの負荷が上昇すると、同じサーバー筐体内の他サーバーの動作が遅くなったり、そもそもGitLabのレスポンスが遅延するようなことが発生してしまっていました。
やはり、ハイパーバイザー型の仮想化は、オーバーヘッドが大きく、ボトルネックになりやすいという実感です。

新GitLab用のサーバーのスペックは旧サーバーの問題を反省し下記としました。

CPU:Intel Core i5 i5-4570 @ 3.20GHz
メモリー:16GB
SSD:120GB
HDD:1TB×2 Raid1

スペックはあまり高くありませんが専用サーバーとしましたので、問題なくサクサク動作するようになりました。

なお、サーバー再構築にあたっては下記の方針としました。

  • Ansibleを使用してInfrastructure as Codeにする。
  • GitLabサービス群はDockerを使用して構築する。

Docker composeで構築する


nginx-proxy + letsencrypt-nginx-proxy-companion + gitlab-ce + gitlab-runnerのコンテナをDocker composeで構築します。

docker-compose.ymlは記事用に若干変えていますが、下記のようにしました。

version: '3'
services:
  # proxyコンテナ
  proxy:
    container_name: proxy
    image: jwilder/nginx-proxy
    privileged: true
    environment:
      ENABLE_IPV6: "true"
    ports:
      - 80:80
      - 443:443
    volumes:
      - /export/certs:/etc/nginx/certs:ro
      - /etc/nginx/htpasswd
      - /etc/nginx/vhost.d
      - /usr/share/nginx/html
      - /var/run/docker.sock:/tmp/docker.sock:ro

  # Let's Encrypt取得・更新用のコンテナ
  letsencrypt-nginx:
    container_name: letsencrypt-nginx
    depends_on:
      - "proxy"
    image: jrcs/letsencrypt-nginx-proxy-companion
    privileged: true
    volumes:
      - /srv/certs:/etc/nginx/certs:rw
      - /var/run/docker.sock:/var/run/docker.sock:ro
    links:
      - proxy:proxy
    volumes_from:
      - proxy

  # GitLabコンテナ
  gitlab:
    image: gitlab/gitlab-ce:10.0.3-ce.0
    container_name : gitlab
    hostname: gitlab.example.com
    environment:
      VIRTUAL_HOST: gitlab.example.com
      VIRTUAL_PORT: 80
      LETSENCRYPT_HOST: gitlab.example.com
      LETSENCRYPT_EMAIL: gitlab-user@gitlab.example.com
      LETSENCRYPT_TEST: "false"
      GITLAB_OMNIBUS_CONFIG: |
        external_url = 'https://gitlab.example.com/'
        gitlab_rails['time_zone'] = 'Asia/Tokyo'
        gitlab_rails['backup_keep_time'] = '600'
        gitlab_rails['gitlab_email_enabled'] = true
        gitlab_rails['gitlab_email_from'] = 'hogehoge@gmail.com'
        gitlab_rails['gitlab_email_reply_to'] = 'hogehoge@gmail.com'
        gitlab_rails['smtp_enable'] = true
        gitlab_rails['smtp_address'] = "smtp.gmail.com"
        gitlab_rails['smtp_port'] = 587
        gitlab_rails['smtp_user_name'] = "googleUSER"
        gitlab_rails['smtp_password'] = "googlePASSWD"
        gitlab_rails['smtp_domain'] = "smtp.gmail.com"
        gitlab_rails['smtp_authentication'] = "login"
        gitlab_rails['smtp_enable_starttls_auto'] = true
        gitlab_rails['smtp_tls'] = false
        gitlab_rails['smtp_openssl_verify_mode'] = 'peer'
        gitlab_workhorse['enable'] = true
        gitlab_workhorse['listen_network'] = "tcp"
        gitlab_workhorse['listen_addr'] = "127.0.0.1:8181"
    volumes:
      - /etc/localtime:/etc/localtime:ro
      - /srv/gitlab/log:/var/log/gitlab
      - /srv/gitlab/opt:/var/opt/gitlab
      - /srv/gitlab/etc:/etc/gitlab
      - /srv/gitlab/runner:/etc/gitlab-runner
    ports:
      - "80"
      - "443"
      - "10022:22"

  # GitLab-CI Runner
  gitlab-runner:
    image: gitlab/gitlab-runner:latest
    container_name : gitlab-runner
    depends_on:
      - "gitlab"
    volumes:
      - /var/run/docker.sock:/var/run/docker.sock
      - /srv/gitlab/log:/var/log/gitlab
      - /srv/gitlab/opt:/var/opt/gitlab
      - /srv/gitlab/etc:/etc/gitlab
      - /srv/gitlab/runner:/etc/gitlab-runner

無料SSLのLet’s Encryptの手続きを自動でやってくれるletsencrypt-nginx-proxy-companionというコンテナを一緒に構築します。
このコンテナはSSL証明書の期限切れが近くなったら自動的に更新してくれるナイスなコンテナです。
Runnerサーバーはリソースを考えると、別サーバーに構築したほうが良いのですが、空いてるサーバーがなかったので今回はGitLabサーバーと同居しています。

RunnerサーバーをGitLabへ登録してCIを開始する


実際にはサーバー移行でしたので、リストア作業をしましたが、わかりやすくご紹介するためにデータがない状態で紹介します。

Docker composeでサービス全体を起動したら、ブラウザーからdocker-compose.ymlのexternal_url に設定したURLへアクセスします。
パスワード変更の画面が表示されますので、パスワードを設定します。

設定したパスワードでログインします。

リポジトリがないと設定ができないので適当にプロジェクトを作成します。

リポジトリの[ Settings ] → [ CI/CD ] → [Runners settings] を開きます。

[General pipelines settings]の右のExpandボタンをクリックして開きます。

2.の接続先URLと3.のregistration tokenを確認してください。

確認した情報でRunnerをGitLabと連携させます。
下記コマンドで対話型設定が開始できます。

# sudo docker exec -it gitlab-runner gitlab-runner register
Running in system-mode.

Please enter the gitlab-ci coordinator URL (e.g. https://gitlab.com/ci):
https://gitlab.example.com    # 確認したURLを入力します。
Please enter the gitlab-ci token for this runner:
registration token        # 確認したregistration tokenを入力します。
Please enter the gitlab-ci description for this runner:

Please enter the gitlab-ci tags for this runner (comma separated):
Enter
Registering runner... succeeded                     runner=hogehoge
Please enter the executor: parallels, docker, docker-ssh, virtualbox, ssh, shell:
docker             # dockerが推奨されています。
Runner registered successfully. Feel free to start it, but if it's running already the config should be automatically reloaded!

成功したあとに、GitLab側で確認すると画像のようにRunnerが確認できます。

GitLab CIはリポジトリ root直下に.gitlab-ci.ymlを作成することで実行されます。

image: php:alpine

before_script:
  - bundle install

stages:
  - test

job1:
  stage: test
  script:
    - execute-script-for-job1

このような形です。詳しい記法などに関しては公式ドキュメントを参照下さい。

まとめと予告


今回の記事の件は1度行ってしまえば.gitlab-ci.ymlを作成するだけでCIを開始することができるようになります。
よい自動化ライフを!


次回は、ササテンさんによる「CIを活用したPHPの実装」をお届けします。
お楽しみに!

引用元・出典
Configuration of your jobs with .gitlab-ci.yml

LINEで送る
Pocket

この記事を書いた人・プロフィール
toshi
ニックネーム: toshi

2013年10月からカタリストシステムに在籍。以前は独立系SIerで監視業務を行っていました。
Androidアプリ、サーバサイド開発(PHP)、サーバインフラ関連等手広く対応しています。
コミケは毎回行ってます。

趣味:自作PC、バイク、萌え系、インディーズゲーム