🛴

soci-snapshotterでECSタスク起動を高速化

に公開

これは何?

コンテナ起動を早くするためのSOCIインデックスを作るサンプル。より具体で言うとsoci-snapshotterというCLIツールを使って、CI/CD(GitHub Actions)上でSOCIアーティファクトを作成、レジストリへプッシュをするサンプルを置いておく。

やること

  • dockerのイメージストアとしてcontainerd-snapshotterの利用を有効化
  • soci-snapshotterのインストール
  • SOCIインデックスの作成、push
name: soci-snapshotter-sample

on: workflow_dispatch

env:
  SOCI_SNAPSHOTTER_VERSION: 0.8.0

jobs:
  soci-index-create-and-push:
    runs-on: ubuntu-latest
    permissions:
      id-token: write
      contents: read
      actions: read
    steps:
      - name: checkout
        uses: actions/checkout@v4

      - name: authenticate to aws
        uses: aws-actions/configure-aws-credentials@v4
        with:
          role-to-assume: ${{ secrets.AWS_IAM_ROLE }}
          aws-region: ${{ secrets.AWS_REGION }}

      - name: setup buildx
        uses: docker/setup-buildx-action@v3

      - name: setup containerd as a docker imagestore
        run: |
          echo '{"features":{"containerd-snapshotter":true}}' | jq | sudo tee /etc/docker/daemon.json
          sudo systemctl restart docker

      - name: login ecr
        uses: docker/login-action@v3
        with:
          registry: ${{ secrets.AWS_ECR_REGISTRY }}

      - name: get secrets from aws secrets manager
        uses: aws-actions/aws-secretsmanager-get-secrets@v2
        with:
          secret-ids: SECRETS,soci-sample/secrets
          parse-json-secrets: true

      - name: build, push and load container image
        uses: docker/build-push-action@v6
        with:
          push: true
          load: true
          context: .
          file: ./Dockerfile
          tags: ${{ secrets.AWS_ECR_REGISTRY }}/soci-sample/hoge:${{ github.sha }}
          build-args: |
            env=production
          cache-from: type=gha,scope=hoge
          cache-to: type=gha,mode=max,scope=hoge

      - name: install soci-snapshotter
        run: |
          wget --quiet https://github.com/awslabs/soci-snapshotter/releases/download/v${{ env.SOCI_SNAPSHOTTER_VERSION }}/soci-snapshotter-${{ env.SOCI_SNAPSHOTTER_VERSION }}-linux-amd64.tar.gz
          sudo tar -C /usr/local/bin -xvf soci-snapshotter-${{ env.SOCI_SNAPSHOTTER_VERSION }}-linux-amd64.tar.gz soci soci-snapshotter-grpc

      - name: create and push soci index
        run: |
          sudo soci --namespace moby create ${{ secrets.AWS_ECR_REGISTRY }}/soci-sample/hoge:${{ github.sha }}
          sudo soci --namespace moby push --existing-index allow --user AWS:$(aws ecr get-login-password --region ${{ secrets.AWS_REGION }}) ${{ secrets.AWS_ECR_REGISTRY }}/soci-sample/hoge:${{ github.sha }}

説明

  • Dockerでcontainerd-snapshotterをイメージストアとして利用できるようにする
    • Experimentalな機能なので本番環境での利用には要検討
  • docker/build-push-actionloadオプションを有効化
    • SOCIインデックスを作成する際にsoci-snapshotterをローカルのイメージストアに存在するイメージ情報を利用するため必要
  • sociコマンドにDockerで利用する名前空間を指定
  • SOCIインデックスを作成するのはコンテナイメージサイズが250MB以上のものを優先
    • イメージサイズが小さいとpull時のオーバーヘッドがSOCIインデックス読み込みになるらしい

おまけ

  • ECSタスク起動にSOCIが利用されているかはコンテナの中に入って確認可能
    $ curl -s $ECS_CONTAINER_METADATA_URI_V4 | jq -r '.Snapshotter'
    soci
    
  • ECSタスク起動に選択的にSOCIを適用することが可能
    • タスク内の全てのコンテナに適用する必要がない、例えばログルーターなどの軽量なコンテナにはSOCIを使わないといった制御
  • github actionsのdocker/build-push-actionアクションのprovenanceオプションをfalseに指定した状態でSOCIインデックスのプッシュができない
    • 正確にはprovenance attestationで作成されるメタデータなどの存在確認を行い見つからないため、プッシュ前に処理が失敗してしまう
  • ECSタスクの起動時間を見比べて効果を測定
    • startedAt
    • createdAt

参考資料

https://kakehashi-dev.hatenablog.com/entry/2023/09/25/100000
https://aws.amazon.com/jp/blogs/news/under-the-hood-lazy-loading-container-images-with-seekable-oci-and-aws-fargate/
https://sreake.com/blog/container-lazy-pull-soci-snapshotter/
https://github.com/awslabs/soci-snapshotter

Discussion