Google Cloud で成果物・パッケージ管理をしてみよう
雪が降ったり寒い年末ですが、みなさんお元気ですか?体調にはお気をつけて。
さて、本記事は Google Cloud Japan Advent Calendar 2022(今から始める Google Cloud) 19 日目です。今日は 12 月 23 日ですが・・
新しいレジストリ サービス、ロゴがより青くなりました (?)
今日は Artifact Registry という、以下のものを適切に管理・共有したい方向けのサービスをご紹介します。
- コンテナのイメージや Helm チャート
- Maven、npm、Python、Go といったプログラミング言語ごとのパッケージ
- Apt、Yum といった OS パッケージ
TL;DR
Artifact Registry は成果物をパッケージとしてまとめ、管理するためのサービスです。何を管理するかによらず、こんな使い方ができます。
- パッケージの種類を選んでリポジトリを作り
- パッケージをアップロードし
- 共有したい相手に権限を設定すると安全に共有できます
- 脆弱性スキャンも設定しておくとより安心です
用語のおさらい
パッケージとは、その単位でインストールしたりライブラリとして組み込むことのできるソフトウェアの集合です。パッケージとしてソフトウェアがまとめられていると、ソフトウェアを部品として探して使うのが簡単になったり、依存関係が明確になるので壊れにくい・直しやすいソフトウェアを作りやすくなったりします。
リポジトリとは、パッケージ置き場です。パッケージのデータそのものを管理するのはもちろんのこと、誰がいつ公開したといったメタデータを保持したり、パッケージにバージョンを持たせられたり、利用者からのアクセスを適切に制御をしたりといったことを任せられます。社内用ライブラリなどは、世界中からアクセスされる公開リポジトリではなく、自社管理の非公開リポジトリを使うのが一般的です。
脆弱性とは、セキュリティ上懸念されるソフトウェアの欠陥です。そもそも設計がよくないこともあれば、実装に不具合があることもあります。ソフトウェアに新しい脆弱性が見つかると、開発元が修正版を用意し、利用者側はそれを取り込み、改めてその動作に支障がないかを確認するといったイベントが起こります。ここで大切なのは、自分たちのソフトウェアが影響を受ける脆弱性にいち早く気付けること、そして後続の対応を迅速にきちんと行えることです。
Artifact Registry とは
Google Cloud がみなさんに代わって管理をする、様々なパッケージに対応したリポジトリです。
特徴
- ストレージの運用はクラウドにお任せ
- 誰が何をできるといった細やかな権限を設定できます
- Google Cloud または既存の CI / CD ツールから簡単に繋がります
- パッケージを利用・実行する環境への配布も容易に行えます
- Container Analysis の併用で、脆弱性スキャンもできます
使ってみよう(コンテナ編)
6 ステップです。
- API(サービス)を有効化
- 脆弱性スキャンを有効化(オプション)
- リポジトリを作成
- イメージを push
- アクセス権を設定
- 別の場所からイメージを pull
1. API(サービス)を有効化
コンソールにログインし、画面上部の検索画面に「artifact registry」と入力してみましょう。検索結果から "Artifact Registry" を選択します。Artifact Registry の画面に切り替わったら「有効にする」ボタンをクリックしてください。
Google Cloud のコマンドライン ツール、gcloud からであれば以下で OK です。
gcloud services enable artifactregistry.googleapis.com
2. 脆弱性スキャンを有効化(オプション)
脆弱性スキャンは、執筆時点でイメージ push 後の自動スキャンが走るごとに $0.26 かかるのですが、もしよければこのタイミングでぜひ有効化してみてください。
gcloud からであればこちら。
gcloud services enable containerscanning.googleapis.com
3. リポジトリを作成
ではイメージを格納するためのリポジトリを作成します。のですが、ここでひとつ考えるべきことがあります。
どういった粒度でリポジトリを作るか
それを決めるために、3 つ、Artifact Registry の仕組みをご紹介します。
イメージ
まず、Artifact Registry のリポジトリにはそれぞれ、以下のような URI がつきます。
HOSTNAME/PROJECT_ID/REPOSITORY_ID
そしてこのリポジトリごとに、複数のイメージとタグを保持できます。 例えば、とあるアプリケーションが複数のサービス a と b から構成されるような場合、リポジトリはアプリケーション単位でひとつだけ作り、サービスごとのイメージはそのリポジトリに置くようなこともできます。
- host-name/my-project/my-application/my-service-a:1.0
- host-name/my-project/my-application/my-service-a:1.1
- host-name/my-project/my-application/my-service-b:1.0
アクセス制御
リポジトリごとに読み取り / 書き込みアクセス権の設定ができます。方法については後述しますが、誰が何をしていいかを分けたい場合、リポジトリは分けて作る必要があります。
ロケーション
リポジトリごとにデータの保存場所が指定できます。デプロイ先の環境によっては、レイテンシ、可用性、帯域幅、費用の観点からデータの保存場所を別に設定できるよう、リポジトリを分けることを検討してもいいかもしれません。
リポジトリの作成
上記考慮点を鑑みつつ、実際にリポジトリを作ってみましょう。「リポジトリを作成」をクリックします。
名前とロケーションを指定して「作成」をクリックしてください。
同じことを gcloud から実行する場合は以下の通りです。
REPO_NAME=my-application
REPO_LOCATION=asia-northeast1
REPO_DESCRIPTION='A repo for my app'
gcloud artifacts repositories create ${REPO_NAME} \
--location "${REPO_LOCATION}" --repository-format "docker" \
--description "${REPO_DESCRIPTION}"
4. イメージを push
認証の設定
リポジトリが完成したので、コンテナのイメージを push してみましょう。そのためには docker push
を実行するユーザー(あなた)が、今作ったリポジトリに対して十分な権限があることをリポジトリに示す必要があります。つまり
- コマンド実行者が Google Cloud のユーザーであることを示す、つまりクラウドにログインして
- docker の認証でも適切な権限をもっていることを示せるように準備
- docker push
という作業が必要です。認証の方法は 4 つあるのですが、以下では gcloud を併用する方法をご案内します。ここまで画面で進めて来た方も gcloud をインストールしていただきつつ、まずはクラウドへログインします。
gcloud auth login
そして docker との連携を設定します。これにより docker pull
や docker push
するとき、アクセス権限が適切であれば Artifact Registry に用意したリポジトリを自由に扱えるようになります。
gcloud auth configure-docker ${REPO_LOCATION}-docker.pkg.dev
イメージの push
準備ができたので、リポジトリにコンテナ イメージを push します。今回は Python のイメージをそのまま使って
- Docker Hub からイメージを pull
- それに Artifact Registry リポジトリの URI に一致するタグをつけて
- Artifact Registry へ push してみます
REPO_URI="${REPO_LOCATION}-docker.pkg.dev/$( gcloud config \
get-value project )/${REPO_NAME}"
docker pull python:3.11.1-slim
docker tag python:3.11.1-slim "${REPO_URI}/python:3.11.1-slim"
docker push "${REPO_URI}/python:3.11.1-slim"
脆弱性の確認
脆弱性スキャンを有効化していればですが、実際に、コンソールで見つかった脆弱性を確認することができます。直前で push したイメージの詳細を確認すると、画像のように「脆弱性」に発見数が計上されていることがあります。
クリックすると緊急度ごとの集計値や、すでに修正されている脆弱性の数が表示されます。依存するソフトウェアに修正版がある場合は、画像の右下「修正を表示」をクリックすると、修正されたバージョンを確認できます。ご活用ください :)
5. アクセス権を設定
Artifact Registry においたパッケージへのアクセス管理には IAM を利用します。IAM の "誰が、何に対して、何ができるか" を定義し、制御できること を用いてパッケージへのアクセス制御を実現します。うまく設定すると、こんなことができます。
- 特定アカウントだけがパッケージをアップロード(イメージを push)できるようにする
- 世界中の誰であってもパッケージをダウンロード(イメージを pull)できるようにする
- 特定の Google グループに参加しているメンバーだけがダウンロードできるようにする
ここでは、先ほど作ったリポジトリに、誰もがアクセスできる権限を設定してみましょう。リポジトリを選択したら、画面右上の「情報パネルを表示」をクリックします。パネルが表示されたら「プリンシパルを追加」を押してください。
権限を渡す相手を絞りたい場合は、プリンシパルとして、相手のメールアドレスを指定します。Google グループでもいいですし、機械的に自動化する時に利用するサービス アカウントのアドレスでも大丈夫です。
今回はあえて、誰もがアクセスできるリポジトリにしたので。画像にある「allUsers」を選択しましょう。(allAuthenticatedUsers という選択肢もありますが、Google Cloud としては allUsers を推奨しています)
また、読み取り権限ということで「Artifact Registry 読み取り」という事前に定義されたロールを選択し、保存してください。(割り当てられる権限は、厳密には「権限」という粒度で設定されます。興味がある方は こちら をみてみるとおもしろいかもしれません。カスタマイズもできます)
同じことを gcloud から実行するなら以下です。
gcloud artifacts repositories add-iam-policy-binding \
${REPO_NAME} --location "${REPO_LOCATION}" \
--member "allUsers" --role "roles/artifactregistry.reader"
6. 別の場所からイメージを pull
リポジトリに権限が適切に設定されていれば、どんな場所からでも 4. で認証を設定した gcloud auth login
と gcloud auth configure-docker
といった組み合わせで docker pull
することができます。
ただ今回は、誰もがアクセスできるリポジトリを作りました。試しに認証の設定がされていない環境からイメージが pull できるかを試してみてください。ちなみに画像の矢印のところをクリックすると docker pull
するときの名前(またはその一部)がコピーできます。ご参考まで。
pull、うまくいきましたか?
使ってみよう(Python 編)
冒頭記載した通り、Artifact Registry はプログラミング言語ごとのパッケージ管理もできます。ソフトウェア サプライチェーンへの攻撃も一般化し始めている昨今、より一層、セキュアなプライベート リポジトリの需要は高まってくると思われます。ということで、Python での例をさらっとみてみましょう。
この Hello World プログラム の依存を Artifact Registry に引っ越してみます。
4 ステップです。
- プライベート リポジトリを作る
- プライベート リポジトリを使う準備をする
- 依存パッケージのアップロード
- コンテナビルド時に依存解決させ、動かしてみる
1. プライベート リポジトリを作る
「リポジトリを作成」をクリックします。
Docker のときとは違い、ちゃんと形式として Python を選択することを忘れずに、名前とロケーションを指定して「作成」をクリックしてください。
gcloud から実行する場合は以下の通りです。
REPO_NAME=my-libs
REPO_LOCATION=asia-northeast1
gcloud artifacts repositories create ${REPO_NAME} \
--location "${REPO_LOCATION}" --repository-format "python" \
--description "My Python package libraries"
2. プライベート リポジトリを使う準備
ではサンプル プログラムを git clone してきて、簡単に動作を確認してみましょう。
git clone https://github.com/GoogleCloudPlatform/python-docs-samples.git
cd python-docs-samples/run/helloworld
pip install -r requirements.txt
python main.py
ここで、Python パッケージを公開するためのツールである Twine と、Google Cloud が推奨している キーリング ライブラリによる認証 を支援する keyrings.google-artifactregistry-auth をインストールします。
pip install twine
pip install keyring
pip install keyrings.google-artifactregistry-auth
以下のコマンドで出力された内容に従い .pypirc
と pip.conf
を作ります。.pypirc
は Linux か macOS なら $HOME/.pypirc
、Windows なら %USERPROFILE%\.pypirc
に作りましょう。
gcloud artifacts print-settings python \
--repository "${REPO_NAME}" --location "${REPO_LOCATION}"
pip.conf
はカレント ディレクトリに保存しつつ、環境変数を利用して、一時的にそれを使うよう Python に指示してあげると周辺プロジェクトに影響がなく、検証するにはよいかもしれません。
export PIP_CONFIG_FILE=pip.conf
3. 依存パッケージのアップロード
先ほど挙動を確認したアプリの依存パッケージを、いったん dist フォルダにダウンロードし
pip download --destination-directory dist -r requirements.txt
それを Artifact Registry にアップロードしてみます。
project_id=$( gcloud config get-value project )
twine upload --skip-existing --repository-url \
"https://${REPO_LOCATION}-python.pkg.dev/${project_id}/${REPO_NAME}" \
dist/*
できましたか?うまくいったのであれば、このように画面からもアップロードしたパッケージを確認できていると思います。簡単ですね!!
コマンドからであれば、以下でパッケージの様子を確認できます。
gcloud artifacts packages list --repository "${REPO_NAME}" \
--location "${REPO_LOCATION}"
4. コンテナビルド時に依存解決させ、動かしてみる
Dockerfile の RUN pip install
より前の行に、以下の指示を追加してみてください。
RUN pip install keyring
RUN pip install keyrings.google-artifactregistry-auth
COPY pip.conf pip.conf
ENV PIP_CONFIG_FILE=pip.conf
コンテナをビルドし、起動してみましょう。
docker build -t test .
docker run -e PORT=8080 -p 8080:8080 test
ビルド時のログをみると、パッケージが Artifact Registry からダウンロードされているかと思います。そして http://localhost:8080 には無事アクセスできたでしょうか?
ちょっと難しい話にはなりますが、もしインターネットへの接続のない環境でビルドしたい場合は こちらの記事 を翻訳しつつ、参考にしてみてください。
最後に
いかがでしたか?Artifact Registry がどんなものかをイメージする助けになったのであれば幸いです。ちなみに Google Cloud には類似の Container Registry というサービスがあるのですが「Artifact Registry: 次世代の Container Registry」というブログがあるほどで、理由がなければぜひ Artifact Registry を検討いただければと思います。気になる方はこちらの比較表をご利用ください。
アドベント カレンダーも 2022 年もあと少しで終わりですね。みなさま、よいお年をお迎えください!
Discussion