Sansan Builders Blog

Sansanのものづくりを支えるメンバーの技術やデザイン、プロダクトマネジメントの情報を発信

CircleCI Orbが最高だった件

はじめに

こんにちは, Sansan株式会社プロダクト開発部エンジニアの北見です.

最近, 個人開発でCircleCIを使ったビルド&デプロイを構築することができました.

構築過程で「CircleCI Orb」という機能を見つけたのですが, これが非常に有用だったので, 紹介させて頂きます.


CI/CDパイプラインの歴史と構築時の悩み

Jenkins

プロダクトをビルド/デプロイするためのCI(Continuous Integration)CD(Continuous Delivery)がもつ重要性は昔から叫ばれてきました. 

CI/CDサービスでまず皆様が思いつくのは「Jenkins」ではないでしょうか?

www.jenkins.io


オンプレミスサーバーへ簡単にインストールでき, CI/CDの走りとなった最も有名なソフトウェアですね.

GUIをオペレーションのメインとし, 簡単にパイプラインを作れるのが魅力です.


しかし扱うプロダクトが巨大化してくると, Jenkinsのパイプライン/サーバーの保守管理が特定のメンバー(いわゆる「Jenkins職人」)しかできなくなるという属人性も問題視されるようになってきました. 

BlueOceanでパイプラインを可視化したり, Jenkins Configuration as Codeでコード化したりといった改善策は挙げられますが, どちらかというと巨大化して訳が分からなくなった物を押し付けられてしまった, というケースの方が多いのではないでしょうか.


「ジョブの更新しておいて」と言われたけれど

  • 前任者がいない
  • コード管理されてない

から

  • そもそもどんなジョブがあるか分からない
  • デグレった時のリカバリが難しい

 

先駆者として偉大な実績を残しているJenkinsですが, 広く使われるにつれ, 管理面での課題も明らかになっていきました.

CircleCI

時代は流れ, AWSを初めとしたクラウドサービスの利用が当たり前になり, CI/CDもできるだけクラウドサービスにお任せして楽をしたい, というニーズが高まってきました.

circleci.com


CircleCI」は最も成功したクラウドCI/CDサービスの1つです. この記事をご覧の皆様の中にも, 個人/チームで利用されている, という方もいらっしゃるのではないでしょうか?

基本的な使い方は簡単です.

CircleCIのビルドパイプラインとなる仕様書(.ymlファイル)をGithubリポジトリのルート(.circleciフォルダ下)に配置するだけ.

f:id:shokitamihtnblog:20201214220436p:plain
.circleci
f:id:shokitamihtnblog:20201214220512p:plain
config.yml

CircleCIはその性質上「Infrastructure as Code」を(ほぼ)強制するので, Jenkinsよりも属人化するリスクが低いと言われています.

 

f:id:shokitamihtnblog:20201214220551p:plain
Dashboard

管理画面もCircleCIのマネージドサービスです. かっこいい.


 しかし, 賢明な読者なら察したかも知れません.
 

これって処理が複雑になってきたら, 結局Jenkinsの時と同じように, CircleCI職人ができるだけじゃないの?

 

はい, その通りです^^;

.circleci/config.ymlファイルに何行にも渡って記述されたCLIの数々はCI/CDパイプラインの可読性を下げ, 改修を困難にします.

結局CircleCIも, 職人業からは逃げられないのでしょうか?

CircleCI Orb

この問題に一石を投じ, 解決策の1つとなりうるのが「CircleCI Orb」です.

circleci.com


CircleCI Orbは, パッケージ化されたビルドコマンド/パイプラインです.

本来であれば何行にも渡って記述していた処理を, ほんの数行で管理することができます.
AWS連携やSlack連携など, 需要が高いジョブは幸いCircleCI公式経由でリリースされているようですね.
circleci.com

今回は
1. 色々ビルドして
2. デプロイ前イベントとしてAWS CLIを叩き
3. AWS CodeDeployでデプロイする
というフローを想定し, 「AWS CLI」「CodeDeploy」をOrbで利用する例を見てみましょう.

なお, 今回CircleCIそれ自体を具体的に掘り下げることはしないので, ご了承ください.

CircleCI Orbの利用例(AWS CLI/CodeDeploy)

https://circleci.com/developer/orbs/orb/circleci/aws-cli
https://circleci.com/developer/ja/orbs/orb/circleci/aws-code-deploy

CircleCI Orbを使うには以下の2つの設定が最低でも必要です(2020年12月現在)

  • CircleCIのバージョン指定を2.1に指定
  • 使用するOrbを宣言する

今回はAWS CLIと AWS CodeDeployなので, config.ymlファイルは

version: 2.1
orbs:
  aws-code-deploy: circleci/aws-code-deploy@1.0.1
  aws-cli: circleci/aws-cli@0.1
  ...


のようにしてあげればOKです.
 
https://circleci.com/developer/orbs/orb/circleci/aws-cli#commands-setup

またAWS CLIのOrbは公式ドキュメントを見ると,  CLIを実行するIAMユーザのRegion/Access Key ID/Secret Access Keyをプロジェクトの環境変数に登録する必要があることが分かります.

f:id:shokitamihtnblog:20201214222152p:plain
CircleCI環境変数設定

それでは肝心のOrbを使う処理を見てみましょう.
以下に示す `pre-deploy` ジョブは, AWS CLIをインストール&CLIによる操作を行います.

...
jobs:
  pre-deploy:
    steps:
      - checkout
      - aws-cli/setup <-AWS CLIのインストールがこれだけで記述できます!
      - run:
          command: |
            aws XXXXX ... <-ここでもうAWS CLIのコマンドを実行できる!
...

マジで短くないですか?


ではさらに AWS Code Deploy を workflows に組み込んでみましょう.

masterブランチにmergeされた時だけ, backend/frontendをビルドし, pre-deploy 処理でAWS CLIによる何かしらの事前チェックをして, AWS CodeDeployを実行する
という実際にありそうなシチュエーションをconfig.ymlに書きおこしてみます.

...
jobs:
  pre-deploy:
    ...
  build-frontend:
   ...
  build-backend:
   ...

workflows:
  version: 2
  build-and-deploy:
    jobs:
      - build-frontend:
      - build-backend:
      - pre-deploy:
          requires:
            - build-frontend
            - build-backend
          filters:
            branches:
              only: master
      ## ↓を書くだけで, AWS CodeDeployが走ります!
      ## CodeDeployの設定は各自頑張ってくださいm(_ _)m
      - aws-code-deploy/deploy:
           application-name: your-application-name
           bundle-bucket: your-bucket-name
           bundle-key: your-bundle-key
           deployment-group: your-deployment-group
           service-role-arn: your-servicerole-arn
           requires:
            - pre-deploy
           filters:
            branches:
              only: master

これ, 短くないですか?(確信)
やりたいことを生のCLIで長々と書くケースに比べ, 大分短いですし, 分かりやすいですね.

これを生の処理と比較してみましょう.
↓の公式サイトから「aws-code-deploy/deploy」がラップしている生のジョブリストを見てみます.
https://circleci.com/developer/ja/orbs/orb/circleci/aws-code-deploy#jobs-deploy

description: >-
  Ensures an application and deployment group exist then proceeds to bundle and
  upload an application revision to S3. Once uploaded this job will finally
  create a deployment based on that revision.
executor: aws-cli/default
parameters:
  application-name:
    description: >-
      The name of an AWS CodeDeploy application associated with the applicable
      IAM user or AWS account.
    type: string
  arguments:
    default: ''
    description: If you wish to pass any additional arguments to the aws deploy command
    type: string
  bundle-bucket:
    description: The s3 bucket where an application revision will be stored
    type: string
  bundle-key:
    description: A key under the s3 bucket where an application revision will be stored
    type: string
  bundle-source:
    default: .
    description: >-
      The directory relative to your project to package up into an application
      revision.
    type: string
  bundle-type:
    default: zip
    description: >-
      The file type used for an application revision bundle. Currently defaults
      to 'zip'
    type: string
  deployment-config:
    default: CodeDeployDefault.OneAtATime
    description: Predefined deployment configuration name.
    type: string
  deployment-group:
    description: The name of a new deployment group for the specified application.
    type: string
  get-deployment-group-arguments:
    default: ''
    description: >-
      If you wish to pass any additional arguments to the get-deployment-group
      command
    type: string
  service-role-arn:
    description: The service role for a deployment group.
    type: string
steps:
  - checkout
  - aws-cli/setup
  - create-application:
      application-name: << parameters.application-name >>
      arguments: << parameters.arguments >>
  - create-deployment-group:
      application-name: << parameters.application-name >>
      arguments: << parameters.arguments >>
      deployment-config: << parameters.deployment-config >>
      deployment-group: << parameters.deployment-group >>
      get-deployment-group-arguments: << parameters.get-deployment-group-arguments >>
      service-role-arn: << parameters.service-role-arn >>
  - push-bundle:
      application-name: << parameters.application-name >>
      arguments: << parameters.arguments >>
      bundle-bucket: << parameters.bundle-bucket >>
      bundle-key: << parameters.bundle-key >>
      bundle-source: << parameters.bundle-source >>
      bundle-type: << parameters.bundle-type >>
  - deploy-bundle:
      application-name: << parameters.application-name >>
      arguments: << parameters.arguments >>
      bundle-bucket: << parameters.bundle-bucket >>
      bundle-key: << parameters.bundle-key >>
      bundle-type: << parameters.bundle-type >>
      deployment-config: << parameters.deployment-config >>
      deployment-group: << parameters.deployment-group >>


長い^^;
さらに個々のジョブ内でCLIの処理が走る訳ですが, それも生で書いていくとなると... ymlファイルはかなりの長さになってしまいそうですね.
しかし, Orbとしてラップされたジョブを利用した場合はたったの 6行です.

      - aws-code-deploy/deploy:
           application-name: your-application-name
           bundle-bucket: your-bucket-name
           bundle-key: your-bundle-key
           deployment-group: your-deployment-group
           service-role-arn: your-servicerole-arn

さらに今回はCircleCI公式が出しているOrbを利用しているので, 自分たちでこのパイプラインのメンテをする必要もありません.

config.ymlの例(一部抜粋)

ここまでの処理をconfig.ymlにまとめると↓のような形になります.

version: 2.1
orbs:
  aws-code-deploy: circleci/aws-code-deploy@1.0.1
  aws-cli: circleci/aws-cli@0.1
executors:
  default:
    your-own-executor-here:
jobs:
  build-backend:
    ...
  build-frontend:
    ...
  pre-deploy:
    executor: default
    steps:
      - checkout
      - aws-cli/setup
      - run:
          command: |
            aws cli XXXX 
workflows:
  version: 2
  build-and-deploy:
    jobs:
      - build-backend:
      - build-frontend:
      - pre-deploy:
          requires:
            - build-frontend
            - build-backend
          filters:
            branches:
              only: master
      - aws-code-deploy/deploy:
           application-name: your-application-name
           bundle-bucket: your-bucket-name
           bundle-key: your-bundle-key
           deployment-group: your-deployment-group
           service-role-arn: your-servicerole-arn
           requires:
            - pre-deploy
           filters:
            branches:
              only: master

色々と端折ってありますが, 大枠の部分は参考になるかと思います.

CircleCI Orbを使う上での注意点

非常に便利なOrbですが, 使用する上では以下のような注意点もあります.

  • CircleCIのバージョンは2.1以上
  • 公式提供されている各Orbの挙動はドキュメントを良く読んだ上で使う
  • 複数のOrbを組み合わせた時, 思わぬ副作用が発生する場合がある

各Orbでラップしてくれているコマンド/ジョブは公式ドキュメントに生の処理が書かれてますので, 利用前に一読されることをお勧めします.

さいごに

以上, 私が使って良かったと感じている「CircleCI Orb」の紹介をさせて頂きました.

CI/CDの属人性を完全に解消するのは難しいですが, 短い記述が出来るに越したことはないです.
CircleCIのバージョン2.1以上が必要だったり, 各Orb独自の制約/ハマり所などもありますが, CI/CDパイプラインの改善に大きく貢献しうる選択肢であることに間違いありません.
 
circleci.com

気になったOrbはありましたか?

是非, 皆さんもCircleCI Orbにチャレンジしてみて下さい.



buildersbox.corp-sansan.com
buildersbox.corp-sansan.com

© Sansan, Inc.