クラウドワークス エンジニアブログ

日本最大級のクラウドソーシング「クラウドワークス」の開発の裏側をお届けするエンジニアブログ

散らばったAWS LambdaのGitHubリポジトリをモノレポ構成にしてメンテナンスコストを削減する

初めまして。crowdworks.jpのSREチームに所属しています @ciloholic です。
入社してかれこれ1年経ちますが、筆を執る機会がなかったため、今回が初エンジニアブログとなります。

この記事では、入社して3か月ほど行なっていた「AWS Lambda周りのメンテナンスコスト削減」の取り組みを紹介していきます。

背景

crowdworks.jpでは、多くのエンジニアがさまざまなGitHubリポジトリに色々な言語でLambdaを活用してきました。GitHubリポジトリは30個以上、使用言語はNode.js / Ruby / Goとさまざま、CI/CDもCircleCI / GitHub Actionsとバラバラです。

SREチームでは、定期的に各種言語のEOL対応やライブラリのアップデート作業を行なっているのですが、GitHubリポジトリもそれぞれ異なる、使用言語もCI/CDもバラバラだったので、メンテナンスコストが多くかかっていました。

問題点と解決策

上記のような背景があり、Lambda周りで多くの問題が発生していたため、それぞれの問題に対する解決策を練ることにしました。

(1)乱立したGitHubリポジトリ

GitHubリポジトリが多いとメンテナンスが困難になるため、まとめられるGitHubリポジトリは1つにまとめるようにしました。いわゆる、モノレポ構成です。

(2)バラついてる使用言語

大半のLambdaがGoで書かれていたこともあり、できるだけGoに寄せるようにしました。一部はNode.jsやRubyで実装されていますが、書き換えコストが高かったため、今後の課題としています。

Ruby3.2のLambdaランタイムが遅くとも2023年6月末頃とのコメントがあったので、もしかしたらGoへの書き換えではなく、Ruby3.2のLambdaランタイムへの移行になるかもしれません。

(3)バラついてるCI/CD

CI/CDでそこまで複雑な処理をしていない、かつ、GitHubとCircleCIを連携させるメリットも無いので、GitHub Actionsに寄せるようにしました。

2023年3月時点で、最近ではGitHub Actions Importerという移行ツールが登場しているため、より簡単に移行できるようになりました。

(4)バラついてるデプロイツール

古くからLambdaをデプロイしている場合、デプロイツールも時代によって移り変わります。

crowdworks.jpでは、ApexやServerless Frameworkが使用されていました。Apexは現在だとアーカイブされていたり、Serverless Frameworkは裏でAWS CloudFormationを使用していてTerreformとの相性が悪かったりと問題が多くあったため、よりシンプルなLambdaのデプロイツールである「lambroll」に統一することにしました。

結果

途中で色々試行錯誤しましたが、最終的に落ち着いたモノレポ構成です。

.
├── .github
│   ├── actions
│   │   ├── deploy
│   │   ├── deploy_go
│   │   └── deploy_ruby
│   └── workflows
│       ├── lambda_1_deploy_production.yml
│       └── lambda_2_deploy_production.yml
├── .lambroll-version
├── lambda_1
└── lambda_2

lambrollのバージョン

lambrollのバージョンを変更しやすくするため、.lambroll-versionに記載しています。GitHub Actions内では、.lambroll-versionを参照するようにしています。

├── .lambroll-version => 0.14.2(2023年3月時点で最新)

デプロイのワークフロー

デプロイのワークフローについて、下記にサンプルコードを載せています。詳細はサンプルコード内のコメントに記載しています。

# .github/workflows/lambda_1_deploy_production.yml
name: deploy production

permissions:
  contents: read
  id-token: write

on:
  push:
    branches:
      - main
    paths:
      # lambda_1の変更をトリガーに起動する
      - 'lambda_1/**'
      - '!lambda_1/README.md'

# デプロイが連続で起動しないように同時デプロイを禁止しています
# https://docs.github.com/ja/actions/using-jobs/using-concurrency
concurrency:
  group: lambda-1-deploy-production

jobs:
  deploy_production:
    runs-on: ubuntu-latest
    timeout-minutes: 5
    environment:
      name: production

    steps:
      - uses: actions/checkout@v3

      # Lambdaのデプロイは、処理内容が共通だったため、Composite Actionに切り出しています
      # https://docs.github.com/ja/actions/creating-actions/creating-a-composite-action
      # GoやRubyは、言語ごとにビルドや前処理が異なるため、Composite Actionを分けて作成しています
      - name: deploy
        uses: ./.github/actions/deploy
        with:
          working-directory: lambda_1
          app-name: lambda-1
          stage: production
          aws-account-id: 123456789
# .github/actions/deploy/action.yml
name: deploy

permissions:
  contents: read
  id-token: write

inputs:
  working-directory:
    required: true
    description: 作業ディレクトリの指定
  app-name:
    required: true
    description: アプリケーション名
  stage:
    required: true
    description: デプロイ先の環境名
  aws-account-id:
    required: true
    description: デプロイ先のAWSアカウントID

runs:
  using: composite
  steps:
    # .lambroll-versionのバージョンを取得する
    - name: set environment variables
      shell: bash
      run: echo "LAMBROLL_VERSION=v`cat .lambroll-version`" >> $GITHUB_ENV

    # AWSへのアクセスは、OIDC認証を使用しています
    # https://docs.github.com/ja/actions/deployment/security-hardening-your-deployments/configuring-openid-connect-in-amazon-web-services
    - name: configure AWS credentials
      uses: aws-actions/configure-aws-credentials@v2
      with:
        aws-region: ap-northeast-1
        role-to-assume: arn:aws:iam::${{ inputs.aws-account-id }}:role/${{ inputs.app-name }}-${{ inputs.stage }}-deploy
        role-session-name: github-actions-${{ github.run_id }}

    # lambrollは、公式で配布されているアクションを使用しています
    # https://github.com/fujiwara/lambroll#github-actions
    - uses: fujiwara/lambroll@v0
      with:
        version: ${{ env.LAMBROLL_VERSION }}

    - name: deploy
      shell: bash
      working-directory: ${{ inputs.working-directory }}
      run: デプロイ処理は省略

最後に

今回の対応以前は、デプロイツールが古過ぎてデプロイできない、また長らく触っていなかったため、ビルドが失敗するなどの事故が多発していましたが、今回の対応によりかなり改善できたと思います。すべてのLambdaをGoにする課題が残っているので、まだまだ改善活動を続けていく所存です。

We're hiring!

crowdworks.jpでは、サービスが持続的に成長するために改善し続けるエンジニアを募集しています! ご興味ある方は、ぜひお気軽にご連絡ください。

https://herp.careers/v1/crowdworks/J7bA_cEqURXa

© 2016 CrowdWorks, Inc., All rights reserved.