GitHub Actions で pcluster コマンド実行環境の Docker イメージをマルチプラットフォームビルドしてみた

GitHub Actions で pcluster コマンド実行環境の Docker イメージをマルチプラットフォームビルドしてみた

Clock Icon2024.09.06

AWS ParallelCluster のクラスター構築には pclusterコマンドの実行環境が必要です。私は通常、Docker コンテナを使用して実行環境を利用しています。ただ、ローカル PC(arm64)と EC2 インスタンス(amd64)の両方でクラスターの構築作業することがあり、環境の互換性が課題となっていました。

pcluster-local-and-aws(1)

本記事では、GitHub Actions を活用してpclusterコマンドのマルチプラットフォーム(arm64 と amd64)対応 Docker イメージをビルドし、Amazon ECR に保存する方法を紹介します。

pcluster-local-and-aws

背景と課題

背景

現在、pclusterコマンドの実行環境として Docker コンテナを利用しています。詳細は以下の記事で紹介しています。

https://dev.classmethod.jp/articles/how-to-build-pclsuter-commnad-on-docker/

ホストの AWS クレデンシャルをコンテナに渡す構成を採用しており、docker-compose.ymlは以下のようになっています。

docker-compose.yml
version: '3'

services:
  pcluster:
    build:
      context: ./pcluster
      dockerfile: Dockerfile
    volumes:
      - .:/workspace:cached
    tty: true
    environment:
      - AWS_ACCESS_KEY_ID=$AWS_ACCESS_KEY_ID
      - AWS_SECRET_ACCESS_KEY=$AWS_SECRET_ACCESS_KEY
      - AWS_SESSION_TOKEN=$AWS_SESSION_TOKEN
      - AWS_REGION=$AWS_REGION
      - AWS_DEFAULT_REGION=$AWS_DEFAULT_REGION⏎

ときたま、新規の EC2 から ParallelCluster のクラスター環境を作成したいときがあります。pclusterコマンドのインストールからはじめることになります。セットアップが多少手間なのでローカルで利用しているコンテナイメージを使いまわせないか検討しました。

課題

コンテナイメージを使い回すあたり以下の課題があります。

  1. ローカル環境(arm64)と EC2 インスタンス(amd64)でのアーキテクチャの違い
  2. 異なるアーキテクチャ用にイメージをビルドするのが手間

これらの課題を解決するため、GitHub Actions を利用してワークフローで arm64 と amd64 のイメージビルド自動化を試してみました。

マルチプラットフォームビルドするワークフロー

GitHub Actions を利用して、arm64 と amd64 両方のプラットフォーム向けに Docker イメージをビルドし、プライベートの ECR に自動保存するワークフローを作成します。

Dockerfile の作成

最低限必要なコマンドをインストールした Dockerfile を作成しました。

pcluster.yml
FROM node:hydrogen-bullseye-slim

RUN apt-get update && apt-get install -y \
    curl \
    unzip \
	python3.10 \
	python3-pip \
	git \
	jq \
	fish \
	vim \
	&& apt-get clean \
	&& rm -rf /var/lib/apt/lists/*

ARG PARALLELCLUSTER_VERSION=3.10.1
RUN pip3 install aws-parallelcluster==${PARALLELCLUSTER_VERSION}

ワークフローの作成

ワークフローの主な特徴は以下の通りです。

  • main以外のブランチへプッシュした場合は、テスト用のリポジトリにビルドしたイメージを保存
  • mainブランチへマージ(プッシュ)した場合は、本番環境用のリポジトリへ改めてビルドして保存
  • マルチプラットフォーム対応
    • QEMU と Docker Buildx を利用して、arm64 と amd64 両方のイメージをビルド
  • Dockerfile 内の ParallelCluster バージョンをイメージタグに再利用
.github/workflows/build.yml
name: Docker Build and Push

on:
  push:

env:
  AWS_REGION: ap-northeast-1
  DEV_REPOSITORY: dev-aws-pcluster-command
  PROD_REPOSITORY: prod-aws-pcluster-command

jobs:
  build:
    runs-on: ubuntu-latest
    timeout-minutes: 20
    permissions:
      id-token: write
      contents: read
    strategy:
      matrix:
        platform:
          - linux/amd64
          - linux/arm64

    steps:
    - name: Checkout code
      uses: actions/checkout@v4

    - name: Set up QEMU
      uses: docker/setup-qemu-action@v3

    - name: Set up Docker Buildx
      uses: docker/setup-buildx-action@v3

    - name: Configure AWS credentials
      uses: aws-actions/configure-aws-credentials@v4
      with:
        role-to-assume: ${{ secrets.AWS_IAM_ROLE_ARN }}
        aws-region: ${{ env.AWS_REGION }}

    - name: Login to Amazon ECR
      id: login-ecr
      uses: aws-actions/amazon-ecr-login@v2

    - name: Set repository based on event
      run: |
        if [[ "${{ github.ref }}" == "refs/heads/main" ]]; then
          echo "REPOSITORY=${{ env.PROD_REPOSITORY }}" >> $GITHUB_ENV
        else
          echo "REPOSITORY=${{ env.DEV_REPOSITORY }}" >> $GITHUB_ENV
        fi

    - name: Extract ParallelCluster version
      id: extract_version
      run: |
        PARALLELCLUSTER_VERSION=$(grep 'ARG PARALLELCLUSTER_VERSION=' Dockerfile | cut -d'=' -f2)
        echo "version=${PARALLELCLUSTER_VERSION}" >> $GITHUB_OUTPUT

    - name: Docker meta
      id: meta
      uses: docker/metadata-action@v5
      with:
        images: ${{ steps.login-ecr.outputs.registry }}/${{ env.REPOSITORY }}
        tags: |
          type=sha,format=short,prefix=v${{ steps.extract_version.outputs.version }}-,suffix=-${{ matrix.platform }}

    - name: Build and Push
      uses: docker/build-push-action@v5
      with:
        context: .
        push: true
        platforms: ${{ matrix.platform }}
        tags: ${{ steps.meta.outputs.tags }}
        labels: ${{ steps.meta.outputs.labels }}
        cache-from: type=gha
        cache-to: type=gha,mode=max

実行結果

同リポジトリ内に arm64 と amd64 用のイメージが保存されます。

Elastic_Container_Registry_-_Images

今後の改善点

arm64 用ビルドに時間がかかります。
QEMU を利用しているため、arm64 イメージのビルドに約 3 倍の時間がかかっています。

Docker_·_bigmuramura_aws-pcluster-command_affcee3

GitHub Enterprise のラージランナーが利用可能な場合、Arm64 ランナーを使用することでビルド時間を短縮できるはずです。機会があった使いたいものです。

おわりに

Cloud 9 の新規利用が不可能になったことを契機に新たなpclusterの実行環境の構築先を検討していました。この機会に、日頃感じていた不便さも解消してみようかと試してみました。試してみたあとの感想としてはイメージのプルを考慮すると、プライベート ECR ではなく認証不要のパブリックリポジトリの使用も検討の余地があると気づきました。ローカル環境で実行の際にイメージをプルすために ECR の認証をするのが煩わしいです。

参考

この記事をシェアする

facebook logohatena logotwitter logo

© Classmethod, Inc. All rights reserved.