こんにちは。合同会社もなみ屋 FLOSS プロフェッショナルサポートチームです。

本稿では、タイトル通りのことを、実例を交えて解説していきます。

PizzaFactory/Contorno の紹介

弊社が提供しているサポートサービス対象には、 PizzaFactory/Contorno プロジェクトの成果物が含まれています。 聞き慣れないプロジェクトかと思いますので、軽く説明しますと…。

PizzaFactory/Contorno が提供するコンテナイメージは、Eclipse/Che での利用を想定しているため、下記のような特徴を持っています。

  • kubectl exec -it を使って作業する前提でイメージが作られています。
  • 一般ユーザ権限で動作します。
  • プログラミングをコンテナ内で行う想定ですので、利用シーンをに応じたプログラミング言語やツールがインストールされています。

Eclipse/Che 本家も PizzaFactory/Contorno と同様のコンテナイメージを配布していますが、下記の点で差異があります。優劣ではなく、方針の違いです。

  • ベースイメージとして Alpine, Ubuntu, Debian を採用しています。
    • Eclipse/Che は開発主体が Red Hat なので、Eclipse/Che 公式が配布しているイメージ群は、 Red Hat の Linux がベースイメージになっています。
  • sudo コマンドを含めています。
    • Red Hat が推している Kuberntes ディストリビューション OpenShift は、デフォルトではコンテナ内での root ユーザ権限実行を許していません。しかし一般的な Kubernetes 環境では root ユーザ環境を許していますし、開発環境では sudo コマンドが欲しくなる瞬間はあります。
    • セキュリティ面でのリスクは増しますが、利便性とのトレードオフです。
  • 比較的具体的なユースケースを想定しています。
    • PizzaFactory プロジェクトは、組込みシステム開発向けの環境を提供する目的でスタートしています。サブプロジェクトである Contorno も、Android AOSP ビルドや ARM 向け GCC のような、組込みシステム寄りの開発支援を想定したコンテナイメージが多めになっています。
  • 可能な限り multi target のサポートを広めに取っています。
    • amd64 と arm64 は当然として、s390 や riscv といった現時点では需要が不明なものも、可能である限り含める方針です。
  • ベースイメージの更新を常に監視して更新しています。
    • 残念ながら全てのイメージで実現できている状態ではないのですが、いくつかの重要なイメージについては、 Renovate を用いたベースイメージの更新追随を行っています。

PizzaFactory/Contorno の成果物を argo-workflows で活用する

Eclipse/Che での利用を想定しているとはいえ、本質的には Docker イメージです。Docker や Kubernetes のエコシステムに存在するツールやフレームワークへの流用もできます。ただし、利用時にはいくつか留意点があります。

ここでは具体例の一つとして、Kubernetes ネイティブなワークフローエンジンである argo-workflows での活用を紹介していきます。 Tekton など他のワークフローエンジンでも、留意点は同じであるはずです。

例題: Android AAOS のビルド

Android なら普通に AOSP でも構わなかったかもしれませんが、ここは一捻りして車載向け派生 Android である AAOS の、Raspberry Pi 向けビルドを試みてみます。

AAOS の概要を日本語で読みたい方については Zenn に掲載されている記事をお勧めしておきます。

自動車のスマホ化 - Android Automotive OS完全入門!

ただし掲載から時間が経っていることもあり、記事内容そのままではビルドが通りませんでしたので、諸々の修正は行っています。

Workflow リソースの全体については稿末に掲載し、PizzaFactory/Controrno の成果物利用時に留意が必要な部分だけ引用しながら解説します。

image: の指定

        image: pizzafactory0contorno/aosp-dev:13_ubuntu-22.04_xpra

今回は AAOS のビルドですので、aosp-dev を選びます。README が貧弱なのでどのタグを選べばよいのか悩むかもしれませんが、追々整備される…はず…。

command: の指定

        command: [bash]

Eclipse/Che との併用を前提としているため、command や entrypoint が Argo-workflows の期待するものと異なります。整合させるため、command を明示する必要があります。PizzaFactory/Contorno では Alpine 系のイメージでも bash を必ず含めています。シェルスクリプトを書きたい場合には、bash 固定でも問題はありません。

スクリプト系の言語を直接使いたい場合には、そのコマンドを指定してください。

fsgroup: の指定

  securityContext:
    fsGroup: 0

PizzaFactory/Contorno のイメージで起動するコンテナは、全て一般ユーザ権限で起動します。 一方、PVC でマウントされたストレージは、書き込み権限が root ユーザに限られています。 よって、デフォルト状態ではマウントされた領域に書き込みができません。

書き込めるようにするには、securityContext.fsGroup0 に設定する必要があります。

なお、この tips は、OpenShift での利用を想定して作成されたコンテナイメージを他の Kubernetes で使う際には、必ず必要となります。汎用性が高いものです。

まとめ

「PizzaFactory/Contorno プロジェクトの成果物を、Eclipse/Che 以外で使う方法」について、実例を交えてご紹介しました。

先にも触れましたが、PizzaFactory/Contorno は、弊社 FLOSS プロフェッショナルサポートの対象となっています。サポートサービスの性質上、お約束できることに限界はありますが、お困りの際にはご協力できるかと思います。ご興味のある方は お問い合わせ ください。

付録: 今回記事のために作成した Workflow リソース全文

apiVersion: argoproj.io/v1alpha1
kind: Workflow
metadata:
  generateName: aaos-build-
  namespace: argo-workflows
spec:
  serviceAccountName: argo-workflow
  arguments:
    parameters:
      - name: skip-repo-sync
        value: "false"
  entrypoint: aaos-build
  podGC:
    strategy: OnWorkflowSuccess
  volumes:
    - name: projects
      persistentVolumeClaim:
        claimName: aaos-build
  securityContext:
    fsGroup: 0

  templates:
    - name: aaos-build
      inputs:
        parameters:
          - name: skip-repo-sync
      steps:
        - - name: repo-init
            template: repo-init
            when: "{{inputs.parameters.skip-repo-sync}} != true"
        - - name: apply-local-manifests
            template: apply-local-manifests
            when: "{{inputs.parameters.skip-repo-sync}} != true"
        - - name: repo-sync
            template: repo-sync
            when: "{{inputs.parameters.skip-repo-sync}} != true"
        - - name: build
            template: build

    - name: repo-init
      script:
        image: pizzafactory0contorno/aosp-dev:13_ubuntu-22.04_xpra
        command: [bash]
        source: |
          if [ ! -d .repo ]; then
            repo init -u http://android.googlesource.com/platform/manifest.git -b android-13.0.0_r52 --depth=1
          fi
        resources:
          requests:
            memory: 4Gi
            cpu: 2000m
        volumeMounts:
          - name: projects
            mountPath: /projects

    - name: apply-local-manifests
      script:
        image: pizzafactory0contorno/aosp-dev:13_ubuntu-22.04_xpra
        command: [bash]
        source: |
          if [ -d .repo/local_manifests ]; then
            rm -fr .repo/local_manifests
          fi
          git clone https://github.com/pizzafactory/aaos_local_manifest.git .repo/local_manifests --depth=1
        resources:
          requests:
            memory: 4Gi
            cpu: 2000m
        volumeMounts:
          - name: projects
            mountPath: /projects

    - name: repo-sync
      script:
        image: pizzafactory0contorno/aosp-dev:13_ubuntu-22.04_xpra
        command: [bash]
        source: |
          repo sync -j 32
        resources:
          requests:
            memory: 16Gi
            cpu: 16000m
        volumeMounts:
          - name: projects
            mountPath: /projects

    - name: build
      outputs:
        artifacts:
          - name: boot-img
            path: /projects/out/target/product/rpi4/boot.img
          - name: system-img
            path: /projects/out/target/product/rpi4/system.img
          - name: vendor-img
            path: /projects/out/target/product/rpi4/vendor.img
      script:
        image: pizzafactory0contorno/aosp-dev:13_ubuntu-22.04_xpra
        command: [bash]
        source: |
          . build/envsetup.sh
          lunch aosp_rpi4-userdebug
          make bootimage systemimage vendorimage
        resources:
          requests:
            memory: 32Gi
            cpu: 16000m
        volumeMounts:
          - name: projects
            mountPath: /projects