一部のコンテナ イメージをサードパーティのレジストリから直接 pull して、Google Kubernetes Engine や Cloud Run などの Google Cloud 環境にデプロイすると、イメージの pull やサードパーティの停止に対するレート制限がビルドとデプロイを中断することがあります。このページでは、それらのイメージを特定して、整合性のある統合されたコンテナ イメージ管理のために Artifact Registry にコピーする方法について説明します。
Artifact Registry は、Artifact Registry にコピーされたイメージの更新に関し、サードパーティのレジストリをモニタリングしません。新しいバージョンのイメージをパイプラインに組み込むには、Artifact Registry に push する必要があります。
移行の概要
コンテナ イメージの移行には次の手順が含まれます。
- 前提条件を設定する。
- 移行するイメージを特定する。
- Dockerfile ファイルとデプロイメント マニフェストを検索して、サードパーティのレジストリへの参照を確認する
- Cloud Logging と BigQuery を使用して、サードパーティのレジストリからイメージを pull する頻度を決定する
- 特定されたイメージを Artifact Registry にコピーする。
- レジストリへの権限が正しく構成されていることを確認します(特に、Artifact Registry と Google Cloud のデプロイ環境が異なるプロジェクトに存在する場合)。
- デプロイのマニフェストを更新する。
- ワークロードを再デプロイする。
始める前に
- 権限を確認します。イメージを Artifact Registry に移行するプロジェクトで、オーナーまたは編集者の IAM ロールが割り当てられている必要があります。
-
- Artifact Registry を使用する Google Cloud プロジェクトを選択します
- Google Cloud コンソールで、Cloud Shell に移動します。
プロジェクト ID を検索して Cloud Shell に設定します。
YOUR_PROJECT_ID
は実際のプロジェクト ID に置き換えます。gcloud config set project YOUR_PROJECT_ID
次の環境変数をエクスポートします。
export PROJECT=$(gcloud config get-value project)
次のコマンドを使用して、BigQuery、Artifact Registry、Cloud Monitoring API を有効にします。
gcloud services enable \ artifactregistry.googleapis.com \ stackdriver.googleapis.com \ logging.googleapis.com \ monitoring.googleapis.com
現在、Artifact Registry を使用していない場合は、イメージのリポジトリを構成します。
- リポジトリを作成する
- リポジトリへのアクセス権を必要とするサードパーティのクライアントの認証を構成します。
Go バージョン 1.13 以降がインストールされていることを確認します。
次のコマンドを使用して、インストールされた既存の Go のバージョンを確認します。
go version
Go をインストールまたは更新する必要がある場合は、Go のインストールのドキュメントをご覧ください。
費用
このガイドでは、課金対象である次の Google Cloud コンポーネントを使用します。
移行するイメージを特定する
サードパーティのレジストリの参照用としてコンテナ イメージのビルドとデプロイに使用するファイルを検索し、そのイメージを pull する頻度を確認します。
Dockerfile で参照を特定する
この手順は、Dockerfile が保存されている場所で実行します。これは、コードが局所的にチェックアウトされている場所の場合もあれば、ファイルが VM で利用可能な場合は Cloud Shell で使用されている場合もあります。
Dockerfile があるディレクトリで、次のコマンドを実行します。
grep -inr -H --include Dockerfile\* "FROM" . | grep -i -v -E 'docker.pkg.dev|gcr.io'
出力は、次の例のようになります。
./code/build/baseimage/Dockerfile:1:FROM debian:stretch
./code/build/ubuntubase/Dockerfile:1:FROM ubuntu:latest
./code/build/pythonbase/Dockerfile:1:FROM python:3.5-buster
このコマンドは、ディレクトリ内のすべての Dockerfile を検索し、"FROM" 行を特定します。必要に応じてコマンドを調整し、Dockerfile の保存方法に合わせます。
マニフェストで参照を特定する
この手順は、GKE または Cloud Run マニフェストが保存されている場所で実行してください。これは、コードが局所的にチェックアウトされている場所の場合もあれば、ファイルが VM で利用可能な場合は Cloud Shell で使用されている場合もあります。
GKE または Cloud Run マニフェストがあるディレクトリで次のコマンドを実行します。
grep -inr -H --include \*.yaml "image:" . | grep -i -v -E 'docker.pkg.dev|gcr.io'
出力例:
./code/deploy/k8s/ubuntu16-04.yaml:63: image: busybox:1.31.1-uclibc ./code/deploy/k8s/master.yaml:26: image: kubernetes/redis:v1
このコマンドはディレクトリ内のすべての YAML ファイルを調べて image: 行を特定し、必要に応じてマニフェストの保存方法を調整します。
クラスタで現在実行中のイメージを一覧表示するには、次のコマンドを実行します。
kubectl get all --all-namespaces -o yaml | grep image: | grep -i -v -E 'docker.pkg.dev|gcr.io'
このコマンドは、現在選択されている Kubernetes クラスタで実行中のすべてのオブジェクトを返し、イメージ名を取得します。
出力例:
- image: nginx image: nginx:latest - image: nginx - image: nginx
適用範囲を全体的に確認するため、すべての Google Cloud プロジェクトですべての GKE クラスタに対してこのコマンドを実行します。
サードパーティのレジストリからの pull 頻度を特定する
サードパーティのレジストリから pull するプロジェクトでは、イメージの pull 頻度に関する情報を使用して、使用量がサードパーティのレジストリに適用されるレート制限と同等、または超過しているかを判断します。
ログデータを収集する
BigQuery にデータをエクスポートするログシンクを作成します。ログシンクに記述された宛先やクエリで、エクスポートするログエントリを選択します。個々のプロジェクトに対してクエリを実行してシンクを作成するか、スクリプトを使用してプロジェクト間でデータを収集できます。
単一のプロジェクトのシンクを作成するには:
Google Cloud プロジェクトを選択します。
[クエリビルダー] タブに、次のクエリを入力します。
resource.type="k8s_pod" jsonPayload.reason="Pulling"
履歴のフィルタを [過去 1 時間] から [過去 7 日間] に変更します。
[実行] をクリックします。
結果が正しく表示されたことを確認したら、[アクション] > [シンクを作成] をクリックします。
シンクのリストで、[BigQuery データセット] を選択し、[次へ] をクリックします。
[シンクを編集] パネルで、次の操作を行います。
- [シンク名] フィールドに「
image_pull_logs
」と入力します。 - [シンクのエクスポート先] フィールドに新しいデータセットを作成するか、別のプロジェクトの宛先データセットを選択します。
- [シンク名] フィールドに「
[シンクを作成] をクリックします。
複数のプロジェクトのシンクを作成するには:
Cloud Shell で次のコマンドを実行します。
PROJECTS="PROJECT-LIST" DESTINATION_PROJECT="DATASET-PROJECT" DATASET="DATASET-NAME" for source_project in $PROJECTS do gcloud logging --project="${source_project}" sinks create image_pull_logs bigquery.googleapis.com/projects/${DESTINATION_PROJECT}/datasets/${DATASET} --log-filter='resource.type="k8s_pod" jsonPayload.reason="Pulling"' done
ここで
- PROJECT-LIST は、スペースで区切られた Google Cloud プロジェクト ID のリストです。例:
project1 project2 project3
。 - DATASET-PROJECT は、データセットを保存するプロジェクトです。
- DATASET-NAME は、データセットの名前です(たとえば、
image_pull_logs
)。
- PROJECT-LIST は、スペースで区切られた Google Cloud プロジェクト ID のリストです。例:
シンクを作成した後、BigQuery テーブルにデータが流れるまでに時間がかかりますが、これはイメージを pull する頻度に応じて変わります。
pull 頻度のクエリ
ビルドが行うイメージ pull の代表サンプルを取得したら、pull 頻度のクエリを実行します。
次のクエリを実行します。
SELECT REGEXP_EXTRACT(jsonPayload.message, r'"(.*?)"') AS imageName, COUNT(*) AS numberOfPulls FROM `DATASET-PROJECT.DATASET-NAME.events_*` GROUP BY imageName ORDER BY numberOfPulls DESC
ここで
- DATASET-PROJECT は、データセットを含むプロジェクトです。
- DATASET-NAME は、データセットの名前です。
次の例は、クエリからの出力を示しています。imageName 列で、Artifact Registry または Container Registry に保存されていないイメージの pull 頻度を確認できます。
Artifact Registry のイメージをコピーする
サードパーティのレジストリでイメージを特定したら、それらのイメージを Artifact Registry にコピーできます。gcrane ツールは、コピープロセスに利用できます。
Cloud Shell で、特定したイメージの名前を使用してテキスト ファイル
images.txt
を作成します。例:ubuntu:18.04 debian:buster hello-world:latest redis:buster jupyter/tensorflow-notebook
gcrane をダウンロードします。
GO111MODULE=on go get github.com/google/go-containerregistry/cmd/gcrane
copy_images.sh
という名前のスクリプトを作成して、ファイルのリストをコピーします。#!/bin/bash images=$(cat images.txt) if [ -z "${AR_PROJECT}" ] then echo ERROR: AR_PROJECT must be set before running this exit 1 fi for img in ${images} do gcrane cp ${img} LOCATION-docker.pkg.dev/${AR_PROJECT}/${img} done
LOCATION は、リポジトリのリージョンまたはマルチリージョンに置き換えます。
スクリプトを実行可能にします。
chmod +x copy_images.sh
スクリプトを実行してファイルをコピーします。
AR_PROJECT=${PROJECT} ./copy_images.sh
権限を確認する
デフォルトでは、Google Cloud CI / CD サービスには同じ Google Cloud プロジェクト内の Artifact Registry に対するアクセス権が割り当てられています。
- Cloud Build はイメージの push と pull ができます
- GKE、Cloud Run、App Engine フレキシブル環境、Compute Engine などのランタイム環境では、イメージを pull できます。
プロジェクト間でイメージを push または pull する必要がある場合、または Artifact Registry にアクセスする必要があるパイプラインをサードパーティ製ツールで使用する場合は、ワークロードを更新して再デプロイする前に権限が正しく構成されていることを確認してください。
詳細については、アクセス制御のドキュメントをご覧ください。
マニフェストを更新して Artifact Registry を参照する
Dockerfile とマニフェストを更新して、サードパーティのレジストリではなく Artifact Registry を参照するようにします。
次の例は、サードパーティのレジストリを参照するマニフェストを示しています。
apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx-deployment
spec:
selector:
matchLabels:
app: nginx
replicas: 2
template:
metadata:
labels:
app: nginx
spec:
containers:
- name: nginx
image: nginx:1.14.2
ports:
- containerPort: 80
更新されたバージョンのこのマニフェストは、us-docker.pkg.dev
上のイメージを指しています。
apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx-deployment
spec:
selector:
matchLabels:
app: nginx
replicas: 2
template:
metadata:
labels:
app: nginx
spec:
containers:
- name: nginx
image: us-docker.pkg.dev/<AR_PROJECT>/nginx:1.14.2
ports:
- containerPort: 80
多数のマニフェストを使用する場合は、多くのテキスト ファイル間で更新を処理できる sed などのツールを使用します。
ワークロードを再デプロイする
更新されたマニフェストでワークロードを再デプロイします。
BigQuery コンソールで次のクエリを実行して、新しいイメージの pull を追跡します。
SELECT`
FORMAT_TIMESTAMP("%D %R", timestamp) as timeOfImagePull,
REGEXP_EXTRACT(jsonPayload.message, r'"(.*?)"') AS imageName,
COUNT(*) AS numberOfPulls
FROM
`image_pull_logs.events_*`
GROUP BY
timeOfImagePull,
imageName
ORDER BY
timeOfImagePull DESC,
numberOfPulls DESC
新しいイメージの pull はすべて Artifact Registry から行われ、文字列 docker.pkg.dev
が含まれている必要があります。