Masayan tech blog.

  1. ブログ記事一覧>
  2. 【GCP】インフラのマイクロサービスをモノレポ構成でCI/CD

【GCP】インフラのマイクロサービスをモノレポ構成でCI/CD

公開日

特に、インフラ関連のサービスは比較的小さな単位で複数作成される傾向にあるので、そのサービス1つ1つにリポジトリを作っていくのはあまり現実的ではないし、管理が煩雑になる。なので、モノレポが適していると思う。

ここで問題となるのはどのようにCI/CDパイプラインを組むかということ。業務で使用する上で自分なりの案が出せたので1つのサンプルを本記事では紹介する。

プロジェクト構成

ソースコードの管理にGithub、CI/CDパイプライン構築にCloud Build、Cloud Functions等で作成された複数のマイクロサービスが存在するとする。例えば想定するディレクトリ構造は以下の通り

  • project-root-dir
    • micro-service-one
      • src
      • cloudbuld.yaml
    • micro-service-two
      • src
      • cloudbuld.yaml
    • micro-service-three
      • src
      • cloudbuld.yaml
  • cloudbuld.yaml
  • README.md

CI/CDパイプライン構築

すでにお気づきだとは思うが、上記のディレクトリにはcloudbuild.yamlが複数存在する。順序としては、まずCloud Buildのトリガーを作成(developに対してfeatureがマージされたら等)しトリガーが実行されたら、プロジェクトルートのcloudbuild.yamlが走るようにしておく。

これに関しては、デフォルトでルートのyamlを見るようになっているので特に何か設定をしないといけないというわけではないので、確認だけしておく

プロジェクトルートのcloudbuild.yamlの役割は、「gitで差分のあるファイルからそのディレクトリを特定し、該当のディレクトリに存在するcloudbuild.yamlを使ってトリガーを実行する」という内容。

これによって、ソースコードに変更のあったサービスのみをデプロイするということが実現できるようになる。

プロジェクトルートのcloudbuild.yaml

全体像

大きくは2ステップに分かれる

steps:
  - name: 'gcr.io/cloud-builders/git'
    entrypoint: /bin/bash
    args:
    - -c
    - |
      git fetch --depth=2 origin main
      git log
      git --no-pager diff --name-only HEAD^ HEAD | grep "/" | cut -d/ -f1 | sort | uniq > /workspace/diff.txt
  - name: 'gcr.io/cloud-builders/gcloud'
    entrypoint: /bin/bash
    args: 
    - -c
    - |
       while read line
       do 
       config="${line}/cloudbuild.yaml"
       echo $config
       if [[ ! -f "${config}" ]]; then
        echo "no such file"
        continue
       fi
       gcloud builds submit $line --config=${config}
       done < /workspace/diff.txt

ポイント

ステップ1

まず、Gitビルダーを使用して、git diffを行い、変更のあったディレクトリ名のみを抽出してテキストファイルに書き出す。例えば、micro-service-two内のsrcに対して変更があれば、micro-service-twoというディレクトリ名が書き出されることになる。

steps:
  - name: 'gcr.io/cloud-builders/git'
    entrypoint: /bin/bash
    args:
    - -c
    - |
      git fetch --depth=2 origin main
      git --no-pager diff --name-only HEAD^ HEAD | grep "/" | cut -d/ -f1 | sort | uniq > /workspace/diff.txt

リモートのmainブランチを取得(最新のコミットから2つのコミットの履歴のみを取得しローカルリポジトリに反映)

最新のコミット (HEAD) とその前のコミット (HEAD^) の間の差分情報を取得。--name-only オプションを使用して、差分されたファイルの名前のみを表示

`grep "/"` を使用して、ディレクトリ階層があるファイルのみをフィルタリング。`cut -d/ -f1` を使用して、ファイルパスの最初のセグメント (ディレクトリ名) を抽出

`sort` を使用して、ディレクトリ名をアルファベット順にソート。`uniq` を使用して、重複したディレクトリ名を削除。最後にテキストに書き出す

ステップ2

次に、書き出したテキストファイルを読み取り、ディレクトリ名を取得。例えばmicro-service-twoというディレクトリ内のソースコードに変更があった場合はmicro-service-two/cloudbuild.yamlということになり、これが存在していればそのディレクトリにあるソースはgcloud builds submitによりビルド処理が実行される

steps:
  # ・・・割愛・・・
  - name: 'gcr.io/cloud-builders/gcloud'
    entrypoint: /bin/bash
    args: 
    - -c
    - |
       while read line
       do 
       config="${line}/cloudbuild.yaml"
       echo $config
       if [[ ! -f "${config}" ]]; then
        echo "no such file"
        continue
       fi
       gcloud builds submit $line --config=${config}
       done < /workspace/diff.txt

各サービス内のyamlファイルは以下の通り。これはデプロイしたいサービスの内容により異なるが、今回はCloud Functionsとしている

micro-service-two/bloudbuild.yaml

steps:
- name: 'gcr.io/google.com/cloudsdktool/cloud-sdk'
  args:
  - gcloud
  - functions
  - deploy
  # デプロイするfunction名
  - sample_func
  - --region=asia-northeast1
  # 関数のソースコードの場所
  - --source=.
  # ソースコード内に存在する関数名または完全修飾クラス名
  - --entry-point=main

まとめ

いかがでしたでしょうか。本記事では、GCPのインフラのマイクロサービスをモノレポ構成でCI/CD環境を構築する方法について紹介しました。ぜひ参考にしてみて下さい。