從第三方登錄檔遷移容器映像檔

如果直接從第三方登錄檔提取部分容器映像檔,並部署至 Google Kubernetes Engine 或 Cloud Run 等環境, Google Cloud 映像檔提取的速率限制或第三方服務中斷,可能會導致建構和部署作業中斷。本頁說明如何找出這些映像檔並複製到 Artifact Registry,以進行統一且一致的容器映像檔管理。

Artifact Registry 不會監控第三方登錄檔,以瞭解您複製到 Artifact Registry 的映像檔是否有更新。如要在管線中納入較新版本的映像檔,就必須將其推送至 Artifact Registry。

遷移作業總覽

遷移容器映像檔的步驟如下:

  1. 設定先決條件
  2. 找出要遷移的圖片。
    • 在 Dockerfile 檔案和部署資訊清單中,搜尋對第三方登錄檔的參照
    • 使用 Cloud Logging 和 BigQuery,判斷從第三方登錄檔提取映像檔的頻率。
  3. 將識別出的映像檔複製到 Artifact Registry。
  4. 確認登錄檔的權限設定正確無誤,特別是當 Artifact Registry 和您的 Google Cloud部署環境位於不同專案時。
  5. 更新部署作業的資訊清單
  6. 重新部署工作負載。

事前準備

  1. 登入 Google Cloud 帳戶。如果您是 Google Cloud新手,歡迎 建立帳戶,親自評估產品在實際工作環境中的成效。新客戶還能獲得價值 $300 美元的免費抵免額,可用於執行、測試及部署工作負載。
  2. 安裝 Google Cloud CLI。

  3. 若您採用的是外部識別資訊提供者 (IdP),請先使用聯合身分登入 gcloud CLI

  4. 執行下列指令,初始化 gcloud CLI:

    gcloud init
  5. 建立或選取 Google Cloud 專案

    選取或建立專案所需的角色

    • 選取專案:選取專案時,不需要具備特定 IAM 角色,只要您已獲授角色,即可選取任何專案。
    • 建立專案:如要建立專案,您需要具備專案建立者角色 (roles/resourcemanager.projectCreator),其中包含 resourcemanager.projects.create 權限。瞭解如何授予角色
    • 建立 Google Cloud 專案:

      gcloud projects create PROJECT_ID

      PROJECT_ID 替換為您要建立的 Google Cloud 專案名稱。

    • 選取您建立的 Google Cloud 專案:

      gcloud config set project PROJECT_ID

      PROJECT_ID 替換為 Google Cloud 專案名稱。

  6. 確認專案已啟用計費功能 Google Cloud

  7. 啟用 Artifact Registry API:

    啟用 API 時所需的角色

    如要啟用 API,您需要具備服務使用情形管理員 IAM 角色 (roles/serviceusage.serviceUsageAdmin),其中包含 serviceusage.services.enable 權限。瞭解如何授予角色

    gcloud services enable artifactregistry.googleapis.com
  8. 安裝 Google Cloud CLI。

  9. 若您採用的是外部識別資訊提供者 (IdP),請先使用聯合身分登入 gcloud CLI

  10. 執行下列指令,初始化 gcloud CLI:

    gcloud init
  11. 建立或選取 Google Cloud 專案

    選取或建立專案所需的角色

    • 選取專案:選取專案時,不需要具備特定 IAM 角色,只要您已獲授角色,即可選取任何專案。
    • 建立專案:如要建立專案,您需要具備專案建立者角色 (roles/resourcemanager.projectCreator),其中包含 resourcemanager.projects.create 權限。瞭解如何授予角色
    • 建立 Google Cloud 專案:

      gcloud projects create PROJECT_ID

      PROJECT_ID 替換為您要建立的 Google Cloud 專案名稱。

    • 選取您建立的 Google Cloud 專案:

      gcloud config set project PROJECT_ID

      PROJECT_ID 替換為 Google Cloud 專案名稱。

  12. 確認專案已啟用計費功能 Google Cloud

  13. 啟用 Artifact Registry API:

    啟用 API 時所需的角色

    如要啟用 API,您需要具備服務使用情形管理員 IAM 角色 (roles/serviceusage.serviceUsageAdmin),其中包含 serviceusage.services.enable 權限。瞭解如何授予角色

    gcloud services enable artifactregistry.googleapis.com
  14. 如果沒有 Artifact Registry 存放區,請建立存放區,並為需要存取存放區的第三方用戶端設定驗證
  15. 確認權限。您必須在要將映像檔遷移至 Artifact Registry 的專案中,具備擁有者或編輯者 IAM 角色。
  16. 匯出下列環境變數:
    export PROJECT=$(gcloud config get-value project)
  17. 確認是否已安裝 Go 1.13 以上版本。
    go version
    如要安裝或更新 Go,請參閱 Go 安裝說明文件

費用

本指南使用下列 Google Cloud計費元件:

找出要遷移的圖片

搜尋您用來建構及部署容器映像檔的檔案,找出對第三方登錄檔的參照,然後檢查您提取映像檔的頻率。

找出 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 資訊清單的位置執行這些步驟。這可能是您在本機簽出程式碼的位置,或是 Cloud Shell (如果檔案位於 VM 中)。
  1. 在含有 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: 行。視需要調整指令,配合資訊清單的儲存方式
  2. 如要列出叢集上執行的映像檔,請執行下列指令:
    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 叢集執行上述指令,確保全面涵蓋。

從第三方登錄檔找出提取頻率

在從第三方登錄檔提取內容的專案中,請使用映像檔提取頻率的相關資訊,判斷您的用量是否接近或超過第三方登錄檔強制執行的任何速率限制。

收集記錄資料

建立記錄接收器,將資料匯出至 BigQuery。記錄接收器包含目的地和查詢,可選取要匯出的記錄項目。您可以查詢個別專案來建立接收器,也可以使用指令碼收集跨專案的資料。

如要為單一專案建立接收器,請按照下列步驟操作:

  1. 前往 Google Cloud 控制台的 「Logs Explorer」頁面

    前往「Logs Explorer」(記錄檔探索工具)

    如果您是使用搜尋列尋找這個頁面,請選取子標題為「Logging」的結果

  2. 選擇 Google Cloud 專案。

  3. 在「查詢建立工具」分頁中,輸入下列查詢:

      resource.type="k8s_pod"
      jsonPayload.reason="Pulling"
    
  4. 將變更記錄篩選器從「過去 1 小時」變更為「過去 7 天」圖片

  5. 按一下 [Run Query] (執行查詢)。

  6. 確認結果正確顯示後,依序點選「動作」 >「建立接收器」

  7. 在「接收器詳細資料」對話方塊中,完成下列步驟:

    1. 在「Sink Name」(接收器名稱) 欄位中輸入 image_pull_logs
    2. 在「Sink description」(接收器說明) 中,輸入接收器的說明。
  8. 點選「下一步」

  9. 在「接收器目的地」對話方塊中,選取下列值:

    1. 在「選取接收器服務」欄位中,選取「BigQuery 資料集」
    2. 在「選取 BigQuery 資料集」欄位中,選取「建立新的 BigQuery 資料集」,然後在開啟的對話方塊中填寫必要資訊。如要進一步瞭解如何建立 BigQuery 資料集,請參閱「建立資料集」。
    3. 點選「建立資料集」
  10. 點選「下一步」

    在「Choose logs to include in sink」(選擇要納入接收器的記錄檔) 部分,查詢會與您在「Query builder」(查詢建立工具) 分頁中執行的查詢相符。

  11. 點選「下一步」

  12. 選用:選擇要從接收器排除的記錄檔。如要進一步瞭解如何查詢及篩選 Cloud Logging 資料,請參閱「記錄查詢語言」。

  13. 按一下「建立接收器」

    記錄檔接收器已建立。

如要為多個專案建立接收器,請按照下列步驟操作:

  1. 開啟 Cloud Shell

  2. 在 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

建立接收器後,資料需要一段時間才會流向 BigQuery 資料表,時間長短取決於圖片的擷取頻率。

查詢提取頻率

取得建構作業提取的代表性映像檔樣本後,請執行提取頻率查詢。

  1. 前往 BigQuery 主控台

  2. 執行以下查詢:

    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」(映像檔名稱)imageName 欄中,您可以查看未儲存在 Artifact Registry 中的映像檔提取頻率。

圖片

將映像檔複製到 Artifact Registry

找出第三方登錄檔中的映像檔後,即可將其複製到 Artifact Registry。gcrane 工具可協助您完成複製程序。

  1. 建立文字檔 images.txt,並在其中加入您識別的圖片名稱。例如:

    ubuntu:18.04
    debian:buster
    hello-world:latest
    redis:buster
    jupyter/tensorflow-notebook
    
  2. 下載 gcrane

      GO111MODULE=on go get github.com/google/go-containerregistry/cmd/gcrane
    
  3. 建立名為 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
    
  4. 執行指令碼來複製檔案:

    AR_PROJECT=${PROJECT}
    ./copy_images.sh
    

驗證權限

更新及重新部署工作負載前,請確認權限設定正確無誤。

詳情請參閱存取權控管說明文件。

更新資訊清單,參照 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 控制台中執行下列查詢,追蹤新的映像檔提取作業:

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

所有新的映像檔提取作業都應來自 Artifact Registry,且包含字串 docker.pkg.dev