【问题标题】:Bazel - Build, Push, Deploy Docker Containers to Kubernetes within MonorepoBazel - 在 Monorepo 中构建、推送、部署 Docker 容器到 Kubernetes
【发布时间】:2020-03-05 20:30:05
【问题描述】:

我有一个带有一些后端 (Node.js) 和前端 (Angular) 服务的 monorepo。目前我的部署过程是这样的:

  1. 检查测试是否通过
  2. 为我的服务构建 docker 映像
  3. 将 docker 镜像推送到容器注册表
  4. 使用 kubectl 将更改应用到 Kubernetes 集群 (GKE)

我的目标是在 Bazel 和 Cloud Build 的帮助下自动化所有这些步骤。但我真的很难开始使用 Bazel:

为了让它工作,我可能需要为我自己的包/服务添加一个带有外部依赖项的WORKSPACE 文件和多个BUILD 文件? 我需要实际实施方面的帮助:

  1. 如何使用 Bazel 构建我的 Dockerfile?
  2. 如何将这些图像推送到注册表中(最好是GCR)?
  3. 如何自动将更改应用到 Google Kubernetes Engine?
  4. 如何将此工具链与 Google Cloud Build 集成?

关于项目的更多信息

我整理了一个小小的 sample monorepo 来展示我的用例

结构

├── kubernetes
├── packages
│   ├── enums
│   ├── utils
└── services
    ├── gateway

一般

  • Gateway 服务依赖于 enums 和 utils
  • 一切都是用打字稿写的
  • 每个服务/包都是一个 Node 模块
  • gateway 文件夹内有一个Dockerfile,我要构建它
  • Kubernetes 配置位于kubernetes 文件夹中。
  • 注意,我不想发布任何npm 包!

【问题讨论】:

    标签: docker kubernetes bazel google-cloud-build monorepo


    【解决方案1】:

    我们想要的是一个可移植的 Docker 容器,它可以容纳我们的 Angular 应用程序及其服务器以及它需要的任何机器映像,我们可以在任何云提供商上启动它,我们将创建一个增量管道。 “Docker 规则”很快。本质上,它通过添加新的 Docker 层来提供工具,因此您对应用程序所做的更改是唯一通过网络发送到云主机的内容。此外,由于 Docker 镜像带有 SHA 标记,我们只重新部署更改的镜像。为了管理我们的生产部署,我们将使用 Kubernetes,其中也存在 Bazel 规则。据我所知,使用 Bazel 从 Dockerfile 构建 docker 映像是不可能的,因为 由于 Dockerfile 的非密封性质,这是设计上不允许的。(来源: https://blog.bazel.build/2015/07/28/docker_build.html)

    作为源代码的一部分所做的更改将部署在 Kubernetes 集群中,这是使用 Bazel 实现以下目标的一种方法。

    1. 我们必须将 Bazel 置于 watch 模式,Deploy replace 告诉 Kubernetes 集群更新应用程序的部署版本。 一个。

      命令:ibazel run :deploy.replace

    2. 如果有任何源代码更改,请在 Angular 中进行。

    3. Bazel 仅增量重建依赖于已更改文件的构建图部分,在这种情况下,包括已更改的 ng_module、包含该模块的 Angular 应用程序以及保存服务器的 Docker nodejs_image .正如我们要求更新部署一样,构建完成后,它会将新的 Docker 容器推送到 Google Container Registry,并且 Kubernetes Engine 实例开始为其提供服务。 Bazel 了解构建图,它只重新构建更改的内容。

    这里有一些片段级别的提示,它们实际上可以提供帮助。

    工作空间文件:

    创建一个 Bazel 工作区文件,WORKSPACE 文件告诉 Bazel 这个目录是一个“工作区”,它就像一个项目根目录。下面列出了要在 Bazel 工作区中完成的事情。 • 工作空间的名称应该与我们发布的npm 包匹配,这样这些导入在引用发布的包时也有意义。 • 使用“http_archive”提及 Bazel 工作区中的所有规则,当我们使用 angular 和 node 时,应提及 rxjs、angular、angular_material、io_bazel_rules_sass、angular-version、build_bazel_rules_typescript、build_bazel_rules_nodejs 的规则。 • -接下来我们必须使用“load”加载依赖项。 sass_repositories, ts_setup_workspace,angular_material_setup_workspace,ng_setup_workspace, • 加载 docker 基础镜像,在我们的例子中是“@io_bazel_rules_docker//nodejs:image.bzl”, • 不要忘记提及浏览器和 Web 测试存储库 web_test_repositories() browser_repositories( 铬=真, 火狐=真, )

    “BUILD.bazel”文件。

    • 加载已下载的模块 ng_module、项目模块等。 • 使用“default_visibility”设置默认可见性 • 如果您有任何 Jasmine 测试,请使用 ts_config 并提及其中的依赖关系。 • ng_module(此处应提及资产、来源和依赖关系) • 如果您有任何延迟加载脚本,请将其作为捆绑包的一部分提及 • 提及web_package 中的根目录。 • 最后提及数据和欢迎页面/默认页面。

    示例片段:

    load("@angular//:index.bzl", "ng_module")
    ng_module(
        name = "src",
        srcs = glob(["*.ts"]),
        tsconfig = ":tsconfig.json",
        deps = ["//src/hello-world"],
    )
    load("@build_bazel_rules_nodejs//:future.bzl", "rollup_bundle")
    rollup_bundle(
      name = "bundle",
      deps = [":src"]
      entry_point = "angular_bazel_example/src/main.js"
    )
    

    使用以下命令构建捆绑包。

    bazel build :bundle
    

    管道:通过 Jenkins

    通过 Jenkins 创建管道并运行管道有几个阶段。每个 Stage 执行单独的任务,但在我们的例子中,我们使用 Stage 通过 BaZel Run 发布图像。

    pipeline {
      agent any
      stages {
        stage('Publish image') {
          steps {
            sh 'bazel run //src/server:push'
          }
        }
      }
    }
    

    注意:

    bazel run :dev.apply
    
    1. Dev 将映射应用到 kubectl apply,这将创建或替换现有配置。(有关更多信息,请参阅 kubectl 文档。)这将应用已解析的模板,其中包括重新发布图像。此操作旨在成为快速迭代开发(重建/重新发布/重新部署)的主力。

    2. 如果你想使用 workpsace 文件拉取容器,请使用下面的标签

      container_pull( name = "debian_base", 摘要 =“sha256:**”, 注册表=“gcr.io”, 存储库 = "google-appengine/debian9", )

    如果使用GKE,则需要安装gcloud sdk,由于我们使用的是GKE(Google Contianer Enginer),可以使用以下方法进行身份验证。

    gcloud container clusters get-credentials <CLUSTER NAME>
    

    Deploymnet 对象应按以下格式提及:

    load("@io_bazel_rules_k8s//k8s:object.bzl", "k8s_object")

    k8s_object(
      name = "dev",
      kind = "deployment",
      template = ":deployment.yaml",
      images = {
        "gcr.io/rules_k8s/server:dev": "//server:image"
      },
    )
    

    来源:

    【讨论】:

    • 这很棒。现在我知道了,这是可能的。但老实说,我尝试的任何事情都给了我错误。所以感谢你的努力,但我需要一些时间来理解 bazel(这让我很困惑)
    【解决方案2】:

    几个月后,我在整个过程中走得比较远。 在这里发布每个细节都太过分了!

    这里是实现了大部分需求的开源项目:https://github.com/flolu/fullstack-bazel

    如有具体问题,请随时与我联系! :)

    祝你好运

    【讨论】:

      【解决方案3】:

      Flo,您是否考虑过使用 terraform 和 makefile 来自动构建集群?

      在我最近的项目中,我使用 make 和 terraform 实现端到端的自动化基础架构。本质上,这种方法构建整个集群,在 3 - 5 分钟内使用一个命令构建和部署整个项目。取决于特定日期 gcp 的速度。

      虽然 terraform 配置已过时,需要用符合当前 0.13 / 0/14 语法的配置替换,但有一个 google 示例项目显示了这个想法。

      https://github.com/GoogleCloudPlatform/gke-bazel-demo#build--deploy-with-bazel

      启用单命令端到端自动化的makefile:

      https://github.com/GoogleCloudPlatform/gke-bazel-demo/blob/master/Makefile

      再次,为您的项目替换或自定义脚本;我实际上又写了两个脚本,一个用于检查/安装客户端要求,即 git / kubctl 和 gcloud,另一个用于检查或配置和身份验证 gcloud,以防它尚未配置和验证。从那里,terraform 脚本接管并构建整个集群,一旦完成,通常的自动部署就会开始。

      我发现在 terraform 和 bazel 上进行分层以实现端到端自动化的想法非常棒。

      【讨论】:

      • 我已经有一段时间没有问这个问题了。我已经使用 Bazel 完成了大部分工作。但是 Terraform 对我来说似乎总是很有趣。但是,我从来没有花时间深入研究它。我有一个入门项目:github.com/flolu/fullstack-bazel 我想在其中尝试 Terraform。我可能会在 gke-bazel-demo 的帮助下尝试一下,并在需要任何帮助时回复您。感谢您的回复,马文!
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-01-12
      • 1970-01-01
      • 1970-01-01
      • 2021-04-25
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多