使用 GitHub CI 自动推送镜像到 GAR

· Maintenance

这篇博客将向您介绍如何使用 GitHub CI 自动将 Docker 镜像推送到 Google Artifact Registry(GAR)的自动构建仓库。

GitHub CI 的功能使得代码推送到 GitHub 仓库时,能够自动构建 Docker 镜像并推送到 GAR。这种自动化流程有助于提高了开发效率,同时还可确保在发布新版本时代码和镜像的一致性和可靠性。

本文将为您提供详细的步骤和指南,帮助您轻松实现自动构建和推送 Docker 镜像的流程。

相关服务介绍

在本章中,我们将简要介绍 Google Artifact Registry 和 IAM 的 Service Account 授权模式的概念和特点,以便读者更好地理解如何使用它们来构建和管理 Docker 镜像。我们还将介绍 Artifact Registry 和 IAM Service Account 之间的关联,并讨论如何创建和配置 Service Account,以便在使用 Artifact Registry 时获得安全和便利的身份验证和授权体验。

Google Artifact Registry

Google Artifact Registry 是 Google Cloud Platform (GCP) 提供的一种全托管的 Docker 镜像存储库服务,它可以帮助开发者更好地管理和分享 Docker 镜像。Google Artifact Registry 支持 Docker、Maven、npm 和 NuGet 等常用的软件包管理工具,可以帮助开发者将应用程序构建和部署过程更好地集成到 DevOps 流程中,从而提高开发效率和软件交付速度。

与其他 Docker 镜像存储库服务不同,Google Artifact Registry 与 GCP 集成紧密,可以使用 GCP 的身份验证和授权机制来管理和保护镜像的访问。这为企业级的应用程序提供了更高的安全性和可靠性保障。此外,Artifact Registry 支持多个区域的镜像存储,以提供更好的地理位置灵活性和应用程序的可用性。

使用 Google Artifact Registry,开发者可以轻松地上传、管理和分享 Docker 镜像。它还支持版本管理,开发者可以根据应用程序版本来管理镜像,并轻松地回退到之前的版本。此外,Artifact Registry 还提供了一个易于使用的 UI 界面,使得开发者可以更直观地管理和浏览镜像。

除了基本的镜像存储和管理功能外,Google Artifact Registry 还提供了一些其他的高级功能,如容器镜像签名和高速并发拉取等,以满足不同应用场景下的需求。其中,容器镜像签名功能可以帮助开发者更好地保护镜像的完整性和安全性,而高速并发拉取则可以帮助大规模应用程序的快速部署和扩展。

总之,Google Artifact Registry 是一种功能强大的全托管 Docker 镜像存储库服务,它与 GCP 集成紧密,支持多个区域的镜像存储和管理,并提供了易于使用的 UI 界面和多种高级功能,可以帮助开发者更好地管理和分享 Docker 镜像,并加速应用程序的构建和部署过程。

GCP Service Account 授权模式

Google Cloud Platform (GCP) 的 Service Account 授权模式是 GCP 身份验证和授权机制的一种重要形式,它允许用户为应用程序创建一种特殊的账号,以便应用程序可以访问和管理 GCP 资源。与其他授权方式相比,Service Account 模式具有更高的安全性和可控性,可以帮助用户更好地保护应用程序的机密信息和敏感数据。

在 GCP 中,每个项目都有一个默认的 Service Account,用户可以为这个 Service Account 分配不同的角色,以便在访问 GCP 资源时获取相应的授权。例如,用户可以为 Service Account 分配 “阅读”、“写入”、“编辑” 等不同的角色,以限制其访问和管理资源的范围。此外,用户还可以创建自定义的 Service Account,并将其分配给特定的应用程序或服务,以实现更精细的授权管理。

使用 Service Account 授权模式,用户可以通过各种方式访问和管理 GCP 资源,如 Google Cloud Console、gcloud 命令行工具和 GCP API 等。此外,Service Account 还支持 OAuth2 和 OpenID Connect 等标准身份验证协议,以便用户可以更好地集成 Service Account 到现有的身份验证和授权机制中。

需要注意的是,在使用 Service Account 授权模式时,用户需要为 Service Account 配置合适的角色和权限,并将其与 GCP 资源建立关联。

总之,Google Cloud Platform 的 Service Account 授权模式是一种强大而灵活的身份验证和授权机制,可以帮助用户更好地管理和保护 GCP 资源。通过为应用程序分配不同的角色和权限,并与 GCP 资源建立关联,用户可以实现更精细的授权管理,提高应用程序的安全性和可靠性。

问题的重现

在 Kubernetes 中,自定义 Docker 镜像是一种常见的应用程序打包和部署方式。在使用自定义 Docker 镜像时,通常需要将这些镜像上传到某个镜像存储库中,以便在 Kubernetes 集群中进行部署。然而,这种方式也带来了一些安全问题,如镜像的安全性、可用性和可靠性等方面的问题。

  1. 镜像的安全性是一个重要问题。如果自定义 Docker 镜像存在漏洞或不安全的配置,可能会导致应用程序受到攻击或数据泄露。此外,如果镜像存储库没有足够的安全措施,例如访问控制、身份验证和加密等,也可能会被黑客入侵或数据泄露。
  2. 镜像的可用性和可靠性也是一个重要问题。如果镜像存储库在部署过程中不可用或出现错误,可能会导致应用程序部署失败或无法正常运行。因此,需要使用可靠的镜像存储库,并定期备份和恢复镜像数据以保证其可用性和可靠性。
  3. 需要注意镜像存储库的访问控制和权限管理。如果没有正确地配置访问控制和权限管理,可能会导致未授权的用户或应用程序访问或篡改镜像数据,从而导致安全问题或应用程序异常。

而对于诸多问题,GAR 均提供了较好的解决方案。作为 Google Cloud Platform(GCP)的一项全托管服务,GAR 提供了丰富的功能和工具,以帮助用户更好地管理和保护 Docker 镜像,从而提高应用程序的安全性、可用性和可靠性。

  1. GAR 提供了完善的安全功能和机制,如访问控制、身份验证和加密等,以确保镜像的安全性和保密性。用户可以使用 GCP 的 Identity and Access Management(IAM)和 Service Account 等机制来管理和授权对镜像的访问权限,并使用 Container Analysis 等工具来识别和修复镜像中存在的漏洞和安全风险。
  2. GAR 支持多个区域的镜像存储,并提供了高速并发拉取和容器镜像签名等高级功能,以满足不同应用场景下的需求。用户可以根据应用程序的地理位置和性能需求来选择合适的镜像存储区域,并使用高速并发拉取来提高部署和扩展效率。容器镜像签名则可以帮助用户保护镜像的完整性和安全性,防止镜像被篡改或植入恶意代码。

GAR 提供了丰富的功能和工具,以帮助用户更好地管理和保护 Docker 镜像。通过使用 GCP 的身份验证和授权机制、多个区域的镜像存储、高级功能和易于使用的界面,用户可以更好地保护和管理镜像,并提高应用程序的安全性、可用性和可靠性。

使用 CI 进行自动推送

GitHub CI 可以用于自动化构建、测试和推送 Docker 镜像,并将其保存到 Google Artifact Registry(GAR)等镜像存储库中。这种自动化流程可以大大提高开发效率,并确保在发布新版本时代码和镜像的一致性和可靠性。

CI 的工作内容

使用 GitHub CI 部署 Google Artifact Registry(GAR)可以帮助用户更好地集成 DevOps 流程,并实现自动化构建和部署。下面是 GitHub CI 部署 GAR 的操作内容:

  1. 使用 actions/checkout 签出仓库
  2. 使用 google-github-actions/auth 生成 Service Account 的临时 Token
  3. 使用 docker/login-action 登录到 GAR
  4. 生成 Tag 并推送到 Docker Registry

上述是 GitHub CI 的主要内容,而我们所需做的是在 GCP 为其配置 OIDC 等授权服务。

在这里我们选择通过 GitHub Action 的 OIDC 生成临时 Token 而非持久性 Token 的主要原因是避免因数据泄露导致的服务信息流出等,是保证服务安全性的体现。

创建和配置 Workload Identity Federation

此部分内容取材自 google-github-actions/authREADME,有进行部分修改。

在此之前,你需要对你的 gcloud cli 进行配置。你可以使用 gcloud auth login 命令进行登录:https://cloud.google.com/sdk/gcloud/reference/auth/login

为了方便后续操作,我们会将一些重复使用的定义为临时变量。这些变量会在 Bash 关闭后自动删除,您无需担心。需要注意的是,此命令仅可用于 Linux 系统,因此您无法使用 cmd 等工具跟随教程。

export PROJECT_ID=ci-project
export SERVICE_ACCOUNT=ci-service-account
export WORKLOAD_IDENTITY_POOL=ci-service-pool
export WORKLOAD_PROVIDER=github-provider

首先,创建或使用现有的 Google Cloud 项目。 您必须有权创建工作负载身份池、工作负载身份提供者以及管理服务帐户和 IAM 权限。

我们需要创建一个 GCP Service Account。 如果您已有 Service Account,请记下其电子邮件地址并跳过此步骤。

gcloud iam service-accounts create "${SERVICE_ACCOUNT}" \
  --project "${PROJECT_ID}" # 创建 Service Account

gcloud services enable iamcredentials.googleapis.com \
  --project "${PROJECT_ID}" # 允许使用 IAM API

创建一个 Workload Identity Pool,用于管理 GitHub Action 在 Google Cloud 权限系统中的角色:

gcloud iam workload-identity-pools create "${WORKLOAD_IDENTITY_POOL}" \
  --project="${PROJECT_ID}" \
  --location="global" \
  --display-name="${WORKLOAD_IDENTITY_POOL}"

而后通过命令获取 Workload Identity Pool 的标识:

gcloud iam workload-identity-pools describe "${WORKLOAD_IDENTITY_POOL}" \
  --project="${PROJECT_ID}" \
  --location="global" \
  --format="value(name)"

# This should look like:
#
#   projects/123456789/locations/global/workloadIdentityPools/my-pool
#

将输出内容保存为一个新的变量:

export WORKLOAD_IDENTITY_POOL_ID=whatever-you-got-back

创建一个在池内为 GitHub 访问提供服务的 OIDC Provider:

gcloud iam workload-identity-pools providers create-oidc "${WORKLOAD_PROVIDER}" \
  --project="${PROJECT_ID}" \
  --location="global" \
  --workload-identity-pool="${WORKLOAD_IDENTITY_POOL}" \
  --display-name="${WORKLOAD_PROVIDER}" \
  --attribute-mapping="google.subject=assertion.sub,attribute.actor=assertion.actor,attribute.repository=assertion.repository" \
  --issuer-uri="https://token.actions.githubusercontent.com"

允许基于您的存储库的 GitHub Action 通过提供程序登录到服务账户:

export REPO=my-username/my-repo # 你的仓库名,需要指定大小写

gcloud iam service-accounts add-iam-policy-binding "${SERVICE_ACCOUNT}@${PROJECT_ID}.iam.gserviceaccount.com" \
  --project="${PROJECT_ID}" \
  --role="roles/iam.workloadIdentityUser" \
  --member="principalSet://iam.googleapis.com/${WORKLOAD_IDENTITY_POOL_ID}/attribute.repository/${REPO}"

向 Google 请求返回该提供程序的标识符:

gcloud iam workload-identity-pools providers describe "${WORKLOAD_PROVIDER}" \
  --project="${PROJECT_ID}" \
  --location="global" \
  --workload-identity-pool="${WORKLOAD_IDENTITY_POOL}" \
  --format="value(name)"

随后你会得到一个不同于上述 WORKLOAD_IDENTITY_POOL_ID 的标识符,它应当是更长的。你需要保存这个字符串,后续我们会在 GitHub Action 用到它。

最后,我们需要确保在开始时创建的服务账户有权限操作 Google Artifact Registry。使用上述命令,为该服务账户添加适当的 IAM 角色和权限,使其能够访问和管理 Google Artifact Registry 中的资源:

gcloud projects add-iam-policy-binding $PROJECT_ID \
    --member="serviceAccount:${SERVICE_ACCOUNT}@${PROJECT_ID}.iam.gserviceaccount.com" \
    --role="roles/artifactregistry.admin"

为了验证是否成功,你可以向 Google 请求打印出分配给服务账户的权限:

gcloud projects get-iam-policy $PROJECT_ID \
    --flatten="bindings[].members" \
    --format='table(bindings.role)' \
    --filter="bindings.members:${SERVICE_ACCOUNT}@${PROJECT_ID}.iam.gserviceaccount.com"

创建一个 GAR Repository

前往 Google Cloud Platform 的 GAR 控制台:https://console.cloud.google.com/artifacts

选择上方按钮新建代码库,选择 Docker 并指定区域,在本文中我们的示例使用 us-west-2

新建 GAR Repository
新建 GAR Repository

新建 Repository

创建 GitHub Action Workflow

你需要在 .github/workflows 文件夹中添加一个新的 YAML 文件,请注意替换示例中给予的信息。

name: Docker Release
on:
  push:

jobs:
  gar-push:
    name: Docker release to Google Artifact Registry
    runs-on: ubuntu-latest

    permissions:
      contents: 'read'
      id-token: 'write'

    steps:
      - id: checkout
        name: Checkout
        uses: actions/checkout@v3

      - id: auth
        name: Authenticate with Google Cloud
        uses: google-github-actions/auth@v1
        with:
          token_format: access_token
          workload_identity_provider: ${{ secrets.GCP_PROVIDER_ID }}
          service_account: ${{ secrets.GCP_SERVICE_ACCOUNT }}@${{ secrets.GCP_PROJECT_ID }}.iam.gserviceaccount.com
          access_token_lifetime: 300s

      - name: Login to Artifact Registry
        uses: docker/login-action@v2
        with:
          registry: ${{ secrets.GCP_REGISTRY_REGION }}-docker.pkg.dev
          username: oauth2accesstoken
          password: ${{ steps.auth.outputs.access_token }}

      - name: Get tag
        id: get-tag
        run: echo ::set-output name=short_ref::${GITHUB_REF#refs/*/}

      - id: docker-push-tagged
        name: Tag Docker image and push to Google Artifact Registry
        uses: docker/build-push-action@v4
        with:
          push: true
          tags:
            ${{ secrets.GCP_REGISTRY_REGION }}-docker.pkg.dev/${{ secrets.GCP_PROJECT_ID }}/${{ secrets.GCP_REGISTRY_ID }}/<your-docker-image-name>:${{ steps.get-tag.outputs.short_ref }}
            ${{ secrets.GCP_REGISTRY_REGION }}-docker.pkg.dev/${{ secrets.GCP_PROJECT_ID }}/${{ secrets.GCP_REGISTRY_ID }}/<your-docker-image-name>:latest

此文件创建后,应当会发起一个 GitHub Action 。如果此任务成功推送,那么本文章的主要任务便结束了。

成功推送镜像
成功推送镜像

成功推送镜像

使用 GAR 中的镜像

本段讲述如何从 Google Artifact Registry 中拉取或推送 Docker 镜像。使用 GAR 中的镜像可以方便地管理和部署 Docker 镜像,提高应用程序的安全性、可用性和可靠性。

使用 Docker 进行 Pull / Push

使用 GAR 中的镜像可以通过 Docker 客户端来完成。首先,用户需要在 GCP 控制台上获取 GAR 的凭据(例如身份验证令牌),以便可以使用 Docker 客户端连接到 GAR。然后,用户可以使用 Docker 客户端拉取或推送 Docker 镜像到 GAR 中。

具体来说,用户需要使用以下命令从 GAR 拉取镜像:

docker pull [REGION]-docker.pkg.dev/[PROJECT-ID]/[REPOSITORY-ID]/[IMAGE]:[TAG]

其中,[REGION] 是 GAR 的区域,[PROJECT-ID] 是 GCP 项目 ID,[REPOSITORY-ID] 是 GAR 仓库的 ID,[IMAGE] 是镜像名称,[TAG] 是镜像的标签。

用户还可以使用以下命令将 Docker 镜像推送到 GAR 中:

docker push [REGION]-docker.pkg.dev/[PROJECT-ID]/[REPOSITORY-ID]/[IMAGE]:[TAG]

在这个命令中,用户需要指定要推送的镜像和其对应的标签。

总之,使用 GAR 中的镜像可以通过 Docker 客户端完成。通过获取 GAR 的凭据、使用 Docker 客户端拉取或推送镜像,用户可以方便地管理和部署 Docker 镜像,并提高应用程序的安全性、可用性和可靠性。

在 GKE 中使用

由于 GKE 使用的节点服务 Compute Engine 默认使用的角色具有对 GAR 的只读权限,你可以直接将其当作无身份验证的 Dockers 拉取镜像。

你只需要照常在容器组的 Image 部分填入镜像地址,如 asia-east2-docker.pkg.dev/ahdark-services/ahdark-services/ahdark-blog ,即可正常拉取镜像。

总结

本文详细介绍了如何使用 GitHub Action 和 Google Artifact Registry 将 Docker 镜像自动推送到 GAR 中。

首先,我们介绍了 GAR 的概念和特点,以及 GCP 中的 Service Account 授权模式。

接着,我们详细讲述了如何创建和配置 Workload Identity Federation,以及如何使用 GitHub CI 实现自动推送 Docker 镜像到 GAR 中。

最后,我们提供了如何使用 Docker 客户端从 GAR 中拉取或推送 Docker 镜像的步骤。

通过本文的指南和步骤,用户可以快速和方便地将 Docker 镜像自动推送到 GAR 中,实现镜像的版本管理和共享,并提高应用程序的安全性、可用性和可靠性。在实际的应用开发中,使用 GitHub Action 和 GAR 的自动化流程可以大大提高开发效率,帮助用户更好地实现 DevOps 流程。

Comments

Send Comments

Markdown supported. Please keep comments clean.