Bazel Monorepo - Как Rebuild and Publi sh только изменили Docker изображения? - PullRequest
3 голосов
/ 18 февраля 2020

Цель

У меня есть монопо-установка с растущим числом сервисов сервисов . При развертывании приложения я запускаю команду, и каждый сервис будет перестроен, а окончательные Docker образы будут опубликованы. Но с ростом количества сервисов время, необходимое для восстановления всех из них, становится все длиннее и длиннее, хотя изменения были внесены только в несколько из них.

Почему моя установка перестроила все Docker изображения хоть немного изменились? Моя цель - перестроить и опубликовать sh только те изображения, которые на самом деле изменились .

Подробности

Я использую Базель для создания Docker изображения, таким образом, в root моего проекта есть один файл BUILD, который содержит цель, которую я запускаю, когда хочу развернуть. Это просто набор k8s_objects, в который включены все службы:

load("@io_bazel_rules_k8s//k8s:objects.bzl", "k8s_objects")
k8s_objects(
    name = "kubernetes_deployment",
    objects = [
        "//services/service1",
        "//services/service2",
        "//services/service3",
        "//services/service4",
        # ...
    ]
)

Аналогично, существует один файл BUILD для каждого сервиса, который сначала создает библиотеку Typescript из всех исходных файлов, а затем создает Node.Js image и, наконец, передает изображение в объект Kubernetes:


load("@npm_bazel_typescript//:index.bzl", "ts_library")
ts_library(
    name = "lib",
    srcs = glob(
        include = ["**/*.ts"],
        exclude = ["**/*.spec.ts"]
    ),
    deps = [
      "//packages/package1",
      "//packages/package2",
      "//packages/package3",
    ],
)

load("@io_bazel_rules_docker//nodejs:image.bzl", "nodejs_image")
nodejs_image(
    name = "image",
    data = [":lib", "//:package.json"],
    entry_point = ":index.ts",
)

load("@k8s_deploy//:defaults.bzl", "k8s_deploy")
k8s_object(
  name = "service",
  template = ":service.yaml",
  kind = "deployment",
  cluster = "my-cluster"
  images = {
    "gcr.io/project/service:latest": ":image"
  },
)

Обратите внимание, что библиотека Typescript также зависит от некоторых пакетов, которые также должны учитываться при повторном развертывании!

Для развертывания я запускаю bazel run :kubernetes_deployment.apply


Первоначально я решил выбрать Bazel, потому что думал, что он будет обрабатывать только измененные сервисы. Но, очевидно, это не тот случай, или моя установка каким-то образом ошибочна.

Если вам нужно более детальное понимание проекта, вы можете проверить его здесь: https://github.com/flolude/cents-ideas

1 Ответ

2 голосов
/ 20 апреля 2020

Похоже, что сам репозиторий Bazel делает что-то похожее:

https://github.com/bazelbuild/bazel/blob/ef0f8e61b5d3a139016c53bf04361a8e9a09e9ab/scripts/ci/ci.sh

Грубые шаги:

  • Рассчитать список файлов, которые изменились
  • Используйте список файлов и найдите их зависимости (например, запрос bazel kind(.*_binary, rdeps(//..., set(file1.txt file2.txt))) найдет все двоичные цели, которые являются зависимыми от file1.txt или file2.txt)
  • построить / протестировать список целей

Вам нужно будет адаптировать этот скрипт к вашим потребностям (например, убедитесь, что он находит docker целей изображения)

Чтобы выяснить вид цели, вы можете использовать bazel query //... --output label_kind

EDIT: небольшое предупреждение для тех, кто хочет go вниз по этой кроличьей норе (особенно если вы абсолютно не хотите пропустить тесты в CI):

Вам нужно подумать о:

  • Удаленных файлах / файлах BUILD (которые зависели от них)
    • Обратите внимание, что перемещенные файлы == Удалено + также добавлено
    • Также вы не можете запрашивать обратные ссылки файлов / BUILD, которые больше не существуют!

Я думаю, что здесь очень много сложностей, идущих по этому маршруту (если возможно) ). Возможно, было бы менее склонно к ошибкам полагаться на саму Базель, чтобы выяснить, что изменилось, используя удаленные кэши и --subcommands, чтобы вычислить, какие побочные эффекты необходимо выполнить.

...