使用 GitHub 在开发周期的早期估算 GKE 费用

本教程演示了开发团队提前了解 Google Kubernetes Engine (GKE) 费用的最佳做法。这种提前测试做法可在相关过程早期了解费用,有助于您避免 Google Cloud 帐单中出现意外费用。

本教程适用于希望优化 GKE 集群中的费用并在生产环境中使用 GitHub 的开发者、运维人员和 FinOps 从业人员。如果您使用 GitLab,请参阅使用 GitLab 在开发周期的早期估算 GKE 费用

本教程假设您熟悉 DockerGitHubKubernetesGKECloud Build 和 Linux。

概览

许多采用公有云的团队都不习惯随用随付结算模式。他们通常并不完全了解其应用的运行环境(在本例中为 GKE)。FinOps 运营模式促进了这种财务责任文化。FinOps 最佳做法是向团队提供有关支出的实时信息,以便在费用出现问题时能够立即解决。

本文档介绍如何更进一步,在费用结算之前加以评估。如 GitHub 网站中所强调的,“在 GitHub 上,每个拉取请求中都内置了轻量级代码审核工具。”这样,您就可以“改进项目,提议新增功能,并讨论实施细节,然后再更改源代码”。估算费用的最佳时机是在开发过程早期和代码审核期间。这样,从业人员就能够在新增功能和 bug 修复的费用出现问题之前,了解和讨论替代方案。下图总结了此类做法。

尽早估算费用的最佳做法。

如图所示,开发者最好在构建时估算本地环境中的 GKE 费用。通过这次估算,他们可以充分了解每月生产工作负载的费用。当功能或 bug 修复已完成编码时,他们会提出一个拉取请求来触发 Cloud Build 检查新旧费用之间的差异。如果超出预定义阈值,他们可以请求进行新的代码审核。这种做法可帮助开发者更好地了解其工作负载容量,并主动修复应用问题,而不是每次在生产环境中发现不稳定性问题时就添加更多资源。

目标

  • 构建并推送 Kubernetes cost-estimator 映像。
  • 创建 GitHub 代码库。
  • 将 Cloud Build 连接到您的 GitHub 代码库。
  • 将示例代码推送到 GitHub 代码库。
  • 更改代码并提出拉取请求以查看费用估算的效果。

费用

本教程使用 Google Cloud 的以下收费组件:

您可使用价格计算器根据您的预计使用量来估算费用。 Google Cloud 新用户可能有资格申请免费试用

完成本教程后,您可以删除所创建的资源以避免继续计费。如需了解详情,请参阅清理

准备工作

  1. 在 Google Cloud Console 中,转到项目选择器页面。

    转到“项目选择器”

  2. 选择或创建 Google Cloud 项目。

  3. 确保您的 Cloud 项目已启用结算功能。 了解如何确认您的项目是否已启用结算功能

  4. 在 Cloud Console 中,激活 Cloud Shell。

    激活 Cloud Shell

    Cloud Shell 会话随即会在 Cloud Console 的底部启动,并显示命令行提示符。Cloud Shell 是一个已安装 Cloud SDK 的 Shell 环境,其中包括 gcloud 命令行工具以及已为当前项目设置的值。该会话可能需要几秒钟时间来完成初始化。

准备环境

  1. 在 Cloud Shell 中,克隆 gke-shift-left-cost GitHub 代码库:

    git clone https://github.com/GoogleCloudPlatform/gke-shift-left-cost
    cd gke-shift-left-cost
    

    此代码库中的代码构建到以下文件夹中:

    • 根文件夹:包含用于构建 cost-estimator 映像的 Dockerfile 文件,以及用于实现 Estimator 命令行逻辑的 main.go 文件。
    • api/:包含用于操控 Kubernetes 对象和估算费用的 Golang API。
    • samples/:包含 Kubernetes 清单示例,以便您可以先尝试执行相关过程,然后再在您的组织中实现。
  2. 设置 Cloud 项目 ID、GitHub 用户和电子邮件地址,以及另一位作为 FinOps 审核者的 GitHub 用户:

    export GCP_PROJECT_ID=YOUR_PROJECT_ID
    export GITHUB_USER=YOUR_GITHUB_USER
    export GITHUB_EMAIL=YOUR_GITHUB_EMAIL_ADDRESS
    export GITHUB_FINOPS_REVIEWER_USER=ANOTHER_GITHUB_USER
    

    请替换以下内容:

    • YOUR_PROJECT_ID:您在本教程中使用的项目的 Cloud 项目 ID。
    • YOUR_GITHUB_USER:您用于登录 GitHub 帐号的用户。
    • YOUR_GITHUB_EMAIL_ADDRESS:您在 GitHub 帐号中使用的电子邮件地址。
    • ANOTHER_GITHUB_USER:另一位作为 FinOps 审核者的 GitHub 用户。请注意,本教程要求您添加此用户作为代码库协作者,因此不能是您自己。为避免在执行教程步骤过程中遇到问题,请确保该用户在您创建邀请后立即接受邀请。
  3. 设置 Cloud 项目并启用所需的 API:

    gcloud config set project $GCP_PROJECT_ID
    
    gcloud services enable cloudbilling.googleapis.com \
        artifactregistry.googleapis.com \
        cloudbuild.googleapis.com
    

构建和推送 Kubernetes cost-estimator 映像

本教程随附的 Kubernetes cost-estimator 工具只是一个可以执行的操作的示例。该工具具有估算 DaemonSet、Deployment、StatefulSet、ReplicaSet、HorizontalPodAutoScaler 和 PersistentVolumeClaim Kubernetes 对象费用的功能。您还可以实现自己的 cost-estimation 工具,或者提出有关所需改进的拉取请求。

  1. 在 Cloud Shell 中,允许 application-default 使用您的凭据:

    gcloud auth application-default login
    
  2. 构建 Kubernetes cost-estimator 二进制文件:

    mkdir ./bin
    go test ./api
    go build -v -o ./bin/k8s-cost-estimator .
    
  3. 通过在示例文件夹中执行费用估算来测试二进制文件:

    ./bin/k8s-cost-estimator \
        --k8s ./samples/k8s-cost-estimator-local/app-v1  \
        --config ./samples/k8s-cost-estimator-local/example-conf.yaml --v trace
    

    在输出中,您将看到一个 Markdown 表,其中详细说明了 ./samples/k8s-cost-estimator-local/app-v1/ 文件夹的每月估算费用。为了更好地了解应用的每月生产费用,开发者可以在推送到远程代码库之前运行此步骤。

    INFO[0000] Starting cost estimation (version v0.0.1)...
    ...
    
    |         KIND          | MIN REQUESTED (USD) | MIN REQ + HPA CPU BUFFER (USD) | MAX REQUESTED (USD) | MIN LIMITED (USD) | MAX LIMITED (USD) |
    |-----------------------|---------------------|--------------------------------|---------------------|-------------------|-------------------|
    | Deployment            |             $133.31 |                        $198.71 |             $266.54 |           $312.83 |           $579.29 |
    | StatefulSet           |              $36.33 |                         $36.33 |              $36.33 |            $72.67 |            $72.67 |
    | DaemonSet             |              $29.68 |                         $29.68 |              $29.68 |            $53.19 |            $53.19 |
    | PersistentVolumeClaim |              $28.88 |                         $28.88 |              $28.88 |            $33.68 |            $33.68 |
    | **TOTAL**             |         **$228.20** |                    **$293.60** |         **$361.43** |       **$472.38** |       **$738.83** |
    
    INFO[0002] Finished cost estimation!
    
  4. 构建 Kubernetes cost-estimator 容器映像:

    docker build . -t us-central1-docker.pkg.dev/$GCP_PROJECT_ID/docker-repo/k8s-cost-estimator:v0.0.1
    
  5. 创建 Artifact Registry Docker 代码库以存储映像:

    gcloud artifacts repositories create docker-repo \
            --repository-format=docker \
            --location=us-central1 \
            --description="Docker repository"
    
  6. gcloud 注册为 Docker 配置文件的凭据帮助程序。如果出现提示,请确认文件更新。

    gcloud auth configure-docker us-central1-docker.pkg.dev
    
  7. 将映像推送到 Artifact Registry:

    docker push us-central1-docker.pkg.dev/$GCP_PROJECT_ID/docker-repo/k8s-cost-estimator:v0.0.1
    

创建新的 GitHub 代码库

  1. 在 Cloud Shell 中,将目录更改为 GitHub 示例:

    cd samples/k8s-cost-estimator-github
    
  2. 在 GitHub 中,创建访问令牌:

    转到“GitHub 个人访问令牌”(GitHub Personal Access Tokens) 页面

    1. 备注字段中,输入令牌说明。
    2. 选择范围下,选中 repoadmin:public_keydelete_repo 复选框。
    3. 点击生成令牌,然后复制页面顶部的您的新个人访问令牌 (Your new personal access token) 值。
  3. 在 Cloud Shell 中,将您的个人访问令牌保存在变量中。

    GITHUB_TOKEN=YOUR_NEW_PERSONAL_ACCESS_TOKEN
    

    请替换以下内容:

    • YOUR_NEW_PERSONAL_ACCESS_TOKEN:您刚刚创建的个人访问令牌。
  4. 创建 GitHub 代码库:

    curl -X POST \
      -H "Accept: application/vnd.github.v3+json" \
      -H "Authorization: Bearer $GITHUB_TOKEN" \
      https://api.github.com/user/repos \
      -d '{"name":"k8s-cost-estimator-github"}' | jq
    

    输出内容类似如下:

    {
      "id": 36099474,
      "node_id": "MDEwOldfsdjA5OTQ3Njc=",
      "name": "k8s-cost-estimator-github",
      ...
    }
    
  5. 将 FinOps 审核者添加为代码库的协作者:

    curl -X PUT \
      -H "Accept: application/vnd.github.v3+json" \
      -H "Authorization: Bearer $GITHUB_TOKEN" \
      https://api.github.com/repos/$GITHUB_USER/k8s-cost-estimator-github/collaborators/$GITHUB_FINOPS_REVIEWER_USER  | jq -r .html_url
    

    输出内容类似如下:

    https://github.com/your-user/k8s-cost-estimator-github/invitations
    
  6. 与您在 GITHUB_FINOPS_REVIEWER_USER 变量中设置的用户共享输出网址,以便他们接受邀请。在继续下一步之前,请访问同一个网址以确保邀请已接受。

    验证邀请是否已接受。

将 Cloud Build 连接到 GitHub 代码库

本部分介绍如何安装 Cloud Build GitHub 应用。在此安装过程中,您可以将 GitHub 代码库与 Cloud 项目连接,以便 Cloud Build 可以在每次拉取请求时自动运行 Kubernetes Estimator 工具。

  1. 转到 Cloud Build 应用的 GitHub Marketplace 页面:

    打开 Cloud Build 应用页面

  2. 为应用设置 GitHub 帐号访问权限:

    1. 如果您是第一次在 GitHub 中配置应用,请点击页面底部的使用 Google Cloud Build 进行设置 (Setup with Google Cloud Build),然后点击向此应用授予对您的 GitHub 帐号的访问权限 (Grant this app access to your GitHub account)。
    2. 如果您之前在 GitHub 中设置过应用,请点击配置访问权限
  3. 在打开的应用页面中,按照以下步骤操作:

    1. 在“Google Cloud Build”行中,点击配置
    2. 选择仅选择代码库 (Only select repositories) 选项。
    3. 选择 k8s-cost-estimator-github 以连接到刚刚创建的代码库。
    4. 点击保存安装(按钮标签因您执行的流而异)。
  4. 系统现在会将您重定向到 Google Cloud 以继续安装。使用您的 Google Cloud 帐号登录。如果出现提示,请授权 Cloud Build 与 GitHub 集成。

  5. Cloud Build 页面中,选择您的项目。系统会显示一个向导。

  6. 在向导的选择代码库部分中,选择您的 GitHub 帐号和 k8s-cost-estimator-github 代码库。

  7. 如果您同意条款及条件,请选中复选框,然后点击连接

  8. 创建触发器部分,点击创建触发器,然后按照以下步骤操作:

    1. 输入触发器名称。
    2. 事件部分中,选择拉取请求(仅限 GitHub 应用)
    3. 来源部分中:
      • 确保使用 your-github-user/k8s-cost-estimator-github(GitHub 应用)自动填充代码库字段。
      • 基本分支下拉列表中,选择 .*
    4. 配置类型部分中,选择 Cloud Build 配置文件(yaml 或 json)
    5. 高级部分中,添加以下替代变量:

      • _GITHUB_TOKEN = YOUR_PERSONAL_ACCESS_TOKEN
      • _GITHUB_FINOPS_REVIEWER_USER = THE_GITHUB_FINOPS_REVIEWER_USER
      • _GITHUB_FINOPS_COST_USD_THRESHOLD = 10

      请替换以下内容:

      • YOUR_PERSONAL_ACCESS_TOKEN:您创建的 GitHub 个人访问令牌。Cloud Shell 的 GITHUB_TOKEN 变量中提供了此令牌。
      • THE_GITHUB_FINOPS_REVIEWER_USER:您邀请担任 GitHub 代码库中的协作者的用户。Cloud Shell 的 GITHUB_FINOPS_REVIEWER_USER 变量中提供了此用户名。
  9. 点击创建

Cloud Build GitHub 应用现已配置完毕,GitHub 代码库已关联到 Cloud 项目。对 GitHub 代码库的拉取请求现在会触发 Cloud Build 执行作业,该作业会使用 GitHub 检查将结果报告回 GitHub。

将示例代码推送到 GitHub 代码库

  1. 创建 SSH 密钥对,以允许您将示例代码推送到 GitHub 代码库:

    mkdir -p ssh && cd ssh
    ssh-keygen -t rsa -b 4096 -N '' -f github-key
    eval `ssh-agent` && ssh-add $(pwd)/github-key
    curl -X POST \
      -H "Accept: application/vnd.github.v3+json" \
      -H "Authorization: Bearer $GITHUB_TOKEN" \
      https://api.github.com/user/keys \
      -d "{\"title\":\"k8s-cost-estimator-key\", \"key\":\"$(cat github-key.pub)\"}" | jq
    cd ..
    

    输出内容类似如下:

    {
      "id": 52356205,
      "key": "ssh-rsa AAAAB3NzaC….wJICyt0yvWjGFZGCWBPUw==",
      "url": "https://api.github.com/user/keys/526205",
      "title": "k8s-cost-estimator-key",
      "verified": true,
      "created_at": "2021-04-23T16:22:58Z",
      "read_only": false
    }
    
  2. 将内容推送到新的 GitHub 代码库:

    sed "s/GCP_PROJECT_ID/$GCP_PROJECT_ID/g; s/GITHUB_USER/$GITHUB_USER/g; s/GITHUB_EMAIL/$GITHUB_EMAIL/g;" templates/cloudbuild.yaml.tpl > cloudbuild.yaml
    
    GITHUB_SSH_URL_REPO=$(curl -X GET \
      -H "Accept: application/vnd.github.v3+json" \
      -H "Authorization: Bearer $GITHUB_TOKEN" \
      https://api.github.com/repos/$GITHUB_USER/k8s-cost-estimator-github | jq -r .ssh_url)
    [ -z "$GITHUB_SSH_URL_REPO" ] && echo "GITHUB_SSH_URL_REPO is not exported" || echo "GITHUB_SSH_URL_REPO is $GITHUB_SSH_URL_REPO"
    
    git init
    git remote add origin $GITHUB_SSH_URL_REPO
    git add -A .
    git commit -m "Initial commit"
    git checkout -b main
    git push -u origin main
    

更改代码并提出拉取请求以测试费用估算

  1. 在 Cloud Shell 中,获取文件 wordpress/wordpress_hpa.yaml 的 GitHub 网址:

    echo "https://github.com/$GITHUB_USER/k8s-cost-estimator-github/edit/main/wordpress/wordpress_hpa.yaml"
    
  2. Ctrl+click(对于 Mac 用户为 Cmd+click)输出网址,转到 GitHub 并修改 wordpress/wordpress_hpa.yaml 文件。

  3. 在 GitHub 中,将 minReplicas 更改为 5

  4. 选择为此提交创建新分支并启动拉取请求 (Create a new branch for this commit and start a pull request),然后点击建议更改

  5. 打开拉取请求 (Open a pull request) 屏幕中,点击创建拉取请求 (Create pull request)。

    除了创建新的拉取请求之外,此步骤还会根据您之前创建的 cloudbuild.yaml 文件触发 Cloud Build 执行作业。该 Cloud Build 执行作业使用您在构建和推送 Kubernetes cost-estimator 映像中构建的容器映像,并在需要 FinOps 审核者时做出决策。

  6. 等待一分钟左右,以便流水线完成。完成后,拉取请求中会添加一条包含费用详情的注释,并且由于您建议的代码费用的增加超出了 $10 的阈值,因此也需要 FinOps 审核者。

    输出内容类似如下:

    在拉取请求中添加了费用明细。

您现在已经知道如何在开发周期的早期让开发者了解他们的支出。此设置可帮助您和您的组织避免 Google Cloud 帐单出现意外费用。

清除数据

为避免系统因本教程中使用的资源向您的 Google Cloud 帐号收取费用,您可以删除您的项目。

删除项目

  1. 在 Cloud Console 中,转到管理资源页面。

    转到“管理资源”

  2. 在项目列表中,选择要删除的项目,然后点击删除
  3. 在对话框中输入项目 ID,然后点击关闭以删除项目。

删除 GitHub 代码库

如果您不想保留 GitHub 代码库,请按照以下步骤操作:

  1. 在 Cloud Shell 中,删除您的 GitHub 代码库:

    curl -X DELETE \
      -H "Accept: application/vnd.github.v3+json" \
      -H "Authorization: Bearer $GITHUB_TOKEN" \
      https://api.github.com/repos/$GITHUB_USER/k8s-cost-estimator-github
    

    如果与 Cloud Shell 的连接断开,则需要重置 GITHUB_TOKENGITHUB_USER 变量。

后续步骤