CircleCIを使って「完全サーバーレス運用」を実現した話

はじめに

こんにちは、BizHint事業部でエンジニアのとみーです!今回はCircleCIを使ってCI環境を構築した件について書かせていただきます。

背景

BizHint事業部では現在、GCPのApp Engineなどを使ったサーバーレスなアプリケーションを開発しています。新規サービスのβリリースに際し、CI環境を整備する必要がありました。

AWS上ですでに運用されている別サービスではCI環境としてJenkinsサーバーを使っているのですが、VPC内専用としているため、GCPに新しく自前のJenkinsサーバーを構築する必要があります。

チーム内では「完全サーバーレス運用(NoOps!)」することを目指していたため、 CI環境だけサーバを構築/運用をするなど言語道断 という結論になりました。そこで、CIツールのクラウドサービスはないか調査したところCircleCIに出会ったのです!

CircleCIとは

CircleCIとは、CIツールのCloudサービスです。

Jenkinsと簡単に比較すると

サーバー管理 設定 自由度 料金
Jenkins 自前 シェルスクリプトなど 高い 無料(サーバー代は別途必要)
CircleCI 不要 yaml 任意タイミングでのジョブ実行などが難しい 1コンテナ無料(追加1コンテナ毎に$50/月)

NoOps!を目指していたこと、Jenkinsの自由度の高さがいまのところ必要なかったことから、CircleCIを導入し実運用ができるのか試してみました。

実際の運用フロー

以下のようなCIフローを構築しました。

Buildの中では

  • Javascriptのトランスパイル
  • Golangで書かれたAPIのビルド&デプロイ

を行っています。

さて、CircleCIの設定ファイルを見ていきましょう。

まずはJobを定義します。

Javascriptのトランスパイル

jobs:
  js_build:
    docker:
      - image: circleci/node:8.12
    steps:
    - checkout
    - run:
        command: |
          yarn install
          yarn run build
    - persist_to_workspace:
        root: /project-dir
        paths:
        - /builded-js-path

トランスパイルしたファイルをGolangのサーバーで配信するため、共有するパスを persist_to_workspace で設定します。

Golangサーバーのデプロイ

# 先程の続きに記述
  deploy:
    docker:
      - image: google/cloud-sdk:alpine
    steps:
      - checkout
      - attach_workspace:
          at: /project-dir
      - run:
          command: |
            echo $GAE_SERVICE_ACCOUNT_KEY > /tmp/secret.json
            gcloud auth activate-service-account $GAE_SERVICE_ACCOUNT_CLIENT_EMAIL --key-file /tmp/secret.json
            gcloud app deploy app.yaml --project=your-project-name --quiet

attach_workspace で共有されたファイルを読み込み、gcloudコマンドでGolangのアプリケーションをGCPにデプロイしています。

認証情報はCircleCIの環境変数で管理することができます。

最後にWorkflowを定義します。

workflows:
  version: 2
  build_and_deploy:
    jobs:
    - test
    - hold:
        type: approval
        requires:
        - test
    - js_build:
        requires:
        - hold
    - deploy:
        requires:
        - js_build

test とは、定義箇所を省略しましたがテストコマンド実行するJobを定義したと思ってください。

type: approval を設定するとWorkflowが一時停止し、CircleCIのコンソールで再開ボタンを押すまでWorkflowを止めることができます。この機能を使うと「何をデプロイするか確認する」フローを挟むことができるので、検証環境に入れるトピックブランチや、本番リリースするプログラムをコントロールすることができました。

CircleCIの設定はyaml形式で記述でき、ビルド用のDockerイメージはCircleCIで用意しているものが利用できるため、簡単にビルド設定を記述することができます。

導入してみて

サーバーの運用が必要ないのは狙いどおりでしたが、他にも導入して良い点がありました。

CircleCIは様々なCloudサービスとの連携が可能なため、GitHubへのプッシュをフックにビルドを走らせたり、ビルド結果の通知をSlackにと、簡単に設定できます。

また、アプリケーションのソースコードと同じレポジトリに設定ファイルを配置するため、プログラム改修ブランチと同期してCIの設定を変更できること、開発者が自分でCIの設定を確認して改善できることで、開発効率の向上にも繋がりました。

まとめ

  • CircleCIを使うことで、サーバーレスCI環境の構築をすることができた
  • yaml形式で記述できるため学習コストが低く、サーバーサイドエンジニアでもCIの改善ができる

AWS上の既存サービスでも自動テストにCircleCIを使っていて、CIツールも徐々にJenkinsからCircleCIに移行をしていこうと考えています。