遷移第三方登錄檔中的容器

如果您直接從第三方註冊資料庫提取某些容器映像檔,然後部署至 Google Kubernetes Engine 或 Cloud Run 等 Google Cloud 環境,映像檔提取的速率限制或第三方服務中斷可能會中斷建構和部署作業。本頁說明如何找出這些映像檔,並將其複製到 Google Cloud 中的登錄檔,以便統一管理容器映像檔。

此外,您還可以利用其他功能,例如透過安全漏洞掃描保護軟體供應鏈,以及透過二進位授權強制執行部署政策。

選擇登錄檔

建議您使用 Artifact Registry 服務,在 Google Cloud中儲存及管理容器映像檔和其他建構構件。

  • 如果您未使用 Container Registry,請改為將映像檔遷移至 Artifact Registry。Artifact Registry 提供更大的彈性和控管功能,包括在區域中儲存圖片,而非多個區域、更精細的存取權控管,以及支援其他構件格式。
  • 如果您使用的是 Container Registry,可以轉換至 Artifact Registry

遷移作業總覽

容器映像檔遷移作業包括下列步驟:

  1. 設定前置條件
  2. 找出要遷移的圖片。
    • 搜尋 Dockerfile 檔案和部署資訊清單,找出第三方登錄資料庫的參照
    • 使用 Cloud Logging 和 BigQuery,判斷從第三方註冊中心擷取映像檔的頻率。
  3. 將已辨識的映像檔複製到 Container Registry。
  4. 確認已正確設定登錄項的權限,尤其是當 Container Registry 和您的 Google Cloud部署環境位於不同專案時。
  5. 更新部署作業的資訊清單
  6. 重新部署工作負載。
  7. (選用) 禁止部署第三方來源的映像檔。

Container Registry 不會監控第三方登錄檔,以便更新您複製到 Container Registry 的映像檔。如果您想將較新版本的映像檔納入管道,必須將該映像檔推送至 Container Registry。

事前準備

  1. 確認權限。您必須在將圖片遷移至 Container Registry 的專案中,具備擁有者或編輯者 IAM 角色。
  2. 前往專案選取器頁面

    1. 選取要使用 Container Registry 的 Google Cloud 專案
    2. 前往 Google Cloud 控制台的 Cloud Shell
    3. 找出您的專案 ID,並在 Cloud Shell 中設定。請將 YOUR_PROJECT_ID 替換為您的專案 ID。

      gcloud config set project YOUR_PROJECT_ID
      
  3. 匯出下列環境變數:

      export PROJECT=$(gcloud config get-value project)
    
  4. 使用下列指令啟用 BigQuery、Container Registry 和 Cloud Monitoring API:

    gcloud services enable \
    containerregistry.googleapis.com \
    stackdriver.googleapis.com \
    logging.googleapis.com \
    monitoring.googleapis.com
    
  5. 確認已安裝 Go 1.13 以上版本。

    • 使用下列指令,查看現有 Go 安裝版本:

      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 資訊清單的位置執行此步驟。這可能是在本機檢出程式碼的位置,如果檔案可在 VM 中使用,則會在 Cloud Shell 中。

  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. 前往「Logs Explorer」頁面

  2. 選擇 Google Cloud 專案。

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

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

    圖片

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

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

  7. 在接收器清單中選取「BigQuery 資料集」,然後按一下「下一步」

  8. 在「Edit Sink」面板中執行下列步驟:

    • 在「Sink Name」欄位中輸入 image_pull_logs
    • 在「Sink Destination」(接收器目的地) 欄位中,建立新的資料集,或選擇其他專案中的目的地資料集。
  9. 按一下「建立接收器」

如要為多個專案建立匯流處,請按照下列步驟操作:

  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欄中,您可以查看未儲存在 Container Registry 或 Artifact Registry 中的映像檔提取頻率。

圖片

將映像檔複製到 Container Registry

找出第三方登錄檔中的映像檔後,您就可以將這些映像檔複製到 Container Registry。gcrane 工具可協助您進行複製程序。

  1. 在 Cloud Shell 中建立文字檔案 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 "${GCR_PROJECT}" ]
    then
        echo ERROR: GCR_PROJECT must be set before running this
        exit 1
    fi
    
    for img in ${images}
    do
        gcrane cp ${img} gcr.io/${GCR_PROJECT}/${img}
    done
    

    將指令碼設定為可執行:

      chmod +x copy_images.sh
    
  4. 執行指令碼來複製檔案:

    GCR_PROJECT=${PROJECT}
    ./copy_images.sh
    

驗證權限

根據預設, Google Cloud CI/CD 服務可存取同一個 Google Cloud 專案中的 Container Registry。

  • Cloud Build 可推送及提取映像檔
  • 執行階段環境 (例如 GKE、Cloud Run、App Engine 彈性環境和 Compute Engine) 可以提取映像檔。

如果您需要跨專案推送或提取映像檔,或是在管道中使用需要存取 Container Registry 的第三方工具,請務必先確認權限設定正確無誤,再更新及重新部署工作負載。

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

更新資訊清單以參照 Container Registry

更新 Dockerfile 和資訊清單,以便參照 Container 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

這個更新版的資訊清單會指向 Container 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: gcr.io/<GCR_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

所有新的映像檔提取作業都應來自 Container Registry,且包含 gcr.io 字串。

(選用) 封鎖從第三方登錄檔提取圖片的行為

對於使用二進位授權的 GKE 叢集,您定義的政策會自動封鎖來自不受信任來源的拉取作業。將遷移的圖片加入例外狀況清單,確保政策不會封鎖這些圖片。本操作說明將說明如何針對專案中 Container Registry 中儲存的所有圖片指定例外狀況。

首次更新政策時,建議您啟用模擬測試模式。二進位授權不會封鎖映像檔,而是建立稽核記錄項目,讓您能夠找出第三方登錄檔中需要遷移至 Container Registry 的未完成映像檔。

如要進一步瞭解如何設定部署政策,請參閱二進位授權說明文件

  1. 前往「二進位授權」頁面
  2. 按一下「編輯政策」
  3. 在「專案預設規則」下方,啟用「模擬測試模式」
  4. 在「不受部署規則限制的映像檔」下方,請保留「信任 Google 提供的所有系統映像檔」的選取狀態。
  5. 展開「圖片路徑」
  6. 將圖片路徑新增為預設專案規則的例外狀況:
    1. 按一下圖片清單底部的「新增圖片」
    2. 輸入 Google Cloud 專案的圖片路徑。例如,gcr.io/my-project/* 會豁免專案 my-project 中的所有圖片。
  7. 針對含有您要部署圖片的其他專案重複執行上述步驟。

在部署的記錄中查看模擬測試事件。遷移您定期從第三方登錄檔提取的任何剩餘圖片。所有圖片都完成遷移後,您可以編輯政策,停用模擬測試模式,並封鎖來自不安全來源的圖片。