diff --git a/build/BUILD b/build/BUILD index 7befe25224..3ac15d0705 100644 --- a/build/BUILD +++ b/build/BUILD @@ -1,9 +1,9 @@ package(default_visibility = ["//visibility:public"]) -load("@io_bazel_rules_docker//container:container.bzl", "container_bundle", "container_image") load("@io_k8s_repo_infra//defs:build.bzl", "release_filegroup") load(":code_generation_test.bzl", "code_generation_test_suite") -load(":platforms.bzl", "for_platforms") +load(":container.bzl", "multi_arch_container", "multi_arch_container_push") +load(":platforms.bzl", "SERVER_PLATFORMS", "for_platforms") code_generation_test_suite( name = "code_generation_tests", @@ -31,64 +31,70 @@ filegroup( # in build/common.sh. DOCKERIZED_BINARIES = { "cloud-controller-manager": { - "base": select(for_platforms( - for_node = "@debian-base-{ARCH}//image", - only_os = "linux", - )), + "base": "@debian-base-{ARCH}//image", "target": "//cmd/cloud-controller-manager:cloud-controller-manager", }, "kube-apiserver": { - "base": select(for_platforms( - for_node = "@debian-base-{ARCH}//image", - only_os = "linux", - )), + "base": "@debian-base-{ARCH}//image", "target": "//cmd/kube-apiserver:kube-apiserver", }, "kube-controller-manager": { - "base": select(for_platforms( - for_node = "@debian-base-{ARCH}//image", - only_os = "linux", - )), + "base": "@debian-base-{ARCH}//image", "target": "//cmd/kube-controller-manager:kube-controller-manager", }, "kube-scheduler": { - "base": select(for_platforms( - for_node = "@debian-base-{ARCH}//image", - only_os = "linux", - )), + "base": "@debian-base-{ARCH}//image", "target": "//cmd/kube-scheduler:kube-scheduler", }, "kube-proxy": { - "base": select(for_platforms( - for_node = "@debian-iptables-{ARCH}//image", - only_os = "linux", - )), + "base": "@debian-iptables-{ARCH}//image", "target": "//cmd/kube-proxy:kube-proxy", }, } -[container_image( - name = binary + "-internal", +# In the bash-based build (build/lib/release.sh), the images built for amd64 do not use +# an arch in their name (but other arches do), and the GCE cluster scripts +# (which sideload the images via tarfiles) expect there not to be an arch. +# When pushing to gcr.io, we want to use an arch, since the archless name is now used for a +# manifest list. Bazel doesn't support manifest lists (yet), so we can't do that either. +# For now, we use the archless name for the image tars saved in the server tarball, +# to satisfy GCE and other similar providers. (If one were to pull the images via the manifest +# list, the arch wouldn't appear in the name either.) +[multi_arch_container( + name = binary, + architectures = SERVER_PLATFORMS["linux"], base = meta["base"], cmd = ["/usr/bin/" + binary], debs = select(for_platforms( - for_node = ["//build/debs:%s-{ARCH}.deb" % binary], + for_server = ["//build/debs:%s-{ARCH}.deb" % binary], only_os = "linux", )), + # Since the multi_arch_container macro replaces the {ARCH} format string, + # we need to escape the stamping vars. + # Also see comment above about why the push tags use ARCH while the + # non-push tags do not. + docker_push_tags = ["{{STABLE_DOCKER_PUSH_REGISTRY}}/%s-{ARCH}:{{STABLE_DOCKER_TAG}}" % binary], + docker_tags = ["{{STABLE_DOCKER_REGISTRY}}/%s:{{STABLE_DOCKER_TAG}}" % binary], stamp = True, symlinks = { # Some cluster startup scripts expect to find the binaries in /usr/local/bin, # but the debs install the binaries into /usr/bin. "/usr/local/bin/" + binary: "/usr/bin/" + binary, }, + tags = ["manual"], + visibility = ["//visibility:private"], ) for binary, meta in DOCKERIZED_BINARIES.items()] -[container_bundle( - name = binary, - images = { - "k8s.gcr.io/%s:{STABLE_DOCKER_TAG}" % binary: binary + "-internal", +# Also roll up all images into a single bundle to push with one target. +multi_arch_container_push( + name = "server-images", + architectures = SERVER_PLATFORMS["linux"], + docker_tags_images = { + "{{STABLE_DOCKER_PUSH_REGISTRY}}/%s-{ARCH}:{{STABLE_DOCKER_TAG}}" % binary: "%s-internal" % binary + for binary in DOCKERIZED_BINARIES.keys() }, -) for binary in DOCKERIZED_BINARIES.keys()] + tags = ["manual"], +) [genrule( name = binary + "_docker_tag", diff --git a/build/container.bzl b/build/container.bzl new file mode 100644 index 0000000000..54b45b7423 --- /dev/null +++ b/build/container.bzl @@ -0,0 +1,132 @@ +# Copyright 2019 The Kubernetes Authors. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +load("@io_bazel_rules_docker//container:container.bzl", "container_bundle", "container_image") +load("@io_bazel_rules_docker//contrib:push-all.bzl", "docker_push") +load("//build:platforms.bzl", "go_platform_constraint") + +# multi_arch_container produces a private internal container_image, multiple +# arch-specific tagged container_bundles (named NAME-ARCH), an alias +# from NAME to the appropriately NAME-ARCH container_bundle target, and a +# genrule for NAME.tar copying the appropriate NAME-ARCH container bundle +# tarball output for the currently-configured architecture. +# Additionally, if docker_push_tags is provided, uses multi_arch_container_push +# to create container_bundles named push-NAME-ARCH with the provided push tags, +# along with a push-NAME docker_push target. +# Args: +# name: name used for the alias; the internal container_image and +# container_bundles are based on this name +# architectures: list of architectures (in GOARCH naming parlance) to +# configure +# base: base image to use for the containers. The format string {ARCH} will +# be replaced with the configured GOARCH. +# docker_tags: list of docker tags to apply to the image. The format string +# {ARCH} will be replaced with the configured GOARCH; any stamping variables +# should be escaped, e.g. {{STABLE_MY_VAR}}. +# docker_push_tags: list of docker tags to apply to the image for pushing. +# The format string {ARCH} will be replaced with the configured GOARCH; +# any stamping variables should be escaped, e.g. {{STABLE_MY_VAR}}. +# tags: will be applied to all targets +# visiblity: will be applied only to the container_bundles; the internal +# container_image is private +# All other args will be applied to the internal container_image. +def multi_arch_container( + name, + architectures, + base, + docker_tags, + docker_push_tags = None, + tags = None, + visibility = None, + **kwargs): + container_image( + name = "%s-internal" % name, + base = select({ + go_platform_constraint(os = "linux", arch = arch): base.format(ARCH = arch) + for arch in architectures + }), + tags = tags, + visibility = ["//visibility:private"], + **kwargs + ) + + for arch in architectures: + container_bundle( + name = "%s-%s" % (name, arch), + images = { + docker_tag.format(ARCH = arch): ":%s-internal" % name + for docker_tag in docker_tags + }, + tags = tags, + visibility = visibility, + ) + native.alias( + name = name, + actual = select({ + go_platform_constraint(os = "linux", arch = arch): "%s-%s" % (name, arch) + for arch in architectures + }), + ) + native.genrule( + name = "gen_%s.tar" % name, + outs = ["%s.tar" % name], + srcs = select({ + go_platform_constraint(os = "linux", arch = arch): ["%s-%s.tar" % (name, arch)] + for arch in architectures + }), + cmd = "cp $< $@", + output_to_bindir = True, + ) + + if docker_push_tags: + multi_arch_container_push( + name = name, + architectures = architectures, + docker_tags_images = {docker_push_tag: ":%s-internal" % name for docker_push_tag in docker_push_tags}, + tags = tags, + ) + +# multi_arch_container_push creates container_bundles named push-NAME-ARCH for +# the provided architectures, populating them with the images directory. +# It additionally creates a push-NAME docker_push rule which can be run to +# push the images to a Docker repository. +# Args: +# name: name used for targets created by this macro; the internal +# container_bundles are based on this name +# architectures: list of architectures (in GOARCH naming parlance) to +# configure +# docker_tags_images: dictionary mapping docker tag to the corresponding +# container_image target. The format string {ARCH} will be replaced +# in tags with the configured GOARCH; any stamping variables should be +# escaped, e.g. {{STABLE_MY_VAR}}. +# tags: applied to container_bundle targets +def multi_arch_container_push( + name, + architectures, + docker_tags_images, + tags = None): + for arch in architectures: + container_bundle( + name = "push-%s-%s" % (name, arch), + images = {tag.format(ARCH = arch): image for tag, image in docker_tags_images.items()}, + tags = tags, + visibility = ["//visibility:private"], + ) + docker_push( + name = "push-%s" % name, + bundle = select({ + go_platform_constraint(os = "linux", arch = arch): "push-%s-%s" % (name, arch) + for arch in architectures + }), + ) diff --git a/build/root/BUILD.root b/build/root/BUILD.root index 9fefdf382e..3469dfab6d 100644 --- a/build/root/BUILD.root +++ b/build/root/BUILD.root @@ -32,6 +32,10 @@ filegroup( visibility = ["//visibility:private"], ) +# TODO: collect all relevant docker_push targets into one target that can be run: +# //build:push-server-images +# //cluster/images/conformance:push-conformance +# //cluster/images/hyperkube:push-hyperkube gcs_upload( name = "push-build", data = [ diff --git a/cluster/images/conformance/BUILD b/cluster/images/conformance/BUILD index 399127f2df..14fd8f9859 100644 --- a/cluster/images/conformance/BUILD +++ b/cluster/images/conformance/BUILD @@ -1,4 +1,6 @@ -load("@io_bazel_rules_docker//container:container.bzl", "container_bundle", "container_image", "container_layer") +load("@io_bazel_rules_docker//container:container.bzl", "container_layer") +load("//build:platforms.bzl", "SERVER_PLATFORMS") +load("//build:container.bzl", "multi_arch_container") container_layer( name = "cluster-srcs", @@ -17,14 +19,19 @@ container_layer( ], ) -container_image( - name = "conformance-internal", - base = "@debian-hyperkube-base-amd64//image", +multi_arch_container( + name = "conformance", + architectures = SERVER_PLATFORMS["linux"], + base = "@debian-hyperkube-base-{ARCH}//image", cmd = [ "/bin/bash", "-c", "/run_e2e.sh", ], + # {ARCH} is replaced by the macro, but STABLE_ vars are replaced by the + # build stamping, so we need to escape them + docker_push_tags = ["{{STABLE_DOCKER_PUSH_REGISTRY}}/conformance-{ARCH}:{{STABLE_DOCKER_TAG}}"], + docker_tags = ["{{STABLE_DOCKER_REGISTRY}}/conformance-{ARCH}:{{STABLE_DOCKER_TAG}}"], env = { "E2E_FOCUS": "\[Conformance\]", "E2E_SKIP": "", @@ -41,14 +48,11 @@ container_image( ":bins", ], stamp = True, + tags = ["manual"], + visibility = ["//visibility:public"], workdir = "/usr/local/bin", ) -container_bundle( - name = "conformance", - images = {"k8s.gcr.io/conformance-amd64:{STABLE_DOCKER_TAG}": "conformance-internal"}, -) - filegroup( name = "package-srcs", srcs = glob(["**"]), diff --git a/cluster/images/hyperkube/BUILD b/cluster/images/hyperkube/BUILD index 19c0c75218..cc2653bf9d 100644 --- a/cluster/images/hyperkube/BUILD +++ b/cluster/images/hyperkube/BUILD @@ -1,17 +1,20 @@ -load("@io_bazel_rules_docker//container:container.bzl", "container_bundle", "container_image") +load("//build:container.bzl", "multi_arch_container") +load("//build:platforms.bzl", "SERVER_PLATFORMS") -container_image( - name = "hyperkube-internal", - base = "@debian-hyperkube-base-amd64//image", +multi_arch_container( + name = "hyperkube", + architectures = SERVER_PLATFORMS["linux"], + base = "@debian-hyperkube-base-{ARCH}//image", + # {ARCH} is replaced by the macro, but STABLE_ vars are replaced by the + # build stamping, so we need to escape them + docker_push_tags = ["{{STABLE_DOCKER_PUSH_REGISTRY}}/hyperkube-{ARCH}:{{STABLE_DOCKER_TAG}}"], + docker_tags = ["{{STABLE_DOCKER_REGISTRY}}/hyperkube-{ARCH}:{{STABLE_DOCKER_TAG}}"], files = [ "//cmd/hyperkube", ], stamp = True, -) - -container_bundle( - name = "hyperkube", - images = {"k8s.gcr.io/hyperkube-amd64:{STABLE_DOCKER_TAG}": "hyperkube-internal"}, + tags = ["manual"], + visibility = ["//visibility:public"], ) filegroup( diff --git a/hack/print-workspace-status.sh b/hack/print-workspace-status.sh index 1d334f88a1..fb1d8a5bb9 100755 --- a/hack/print-workspace-status.sh +++ b/hack/print-workspace-status.sh @@ -38,6 +38,8 @@ STABLE_BUILD_SCM_REVISION ${KUBE_GIT_VERSION-} STABLE_BUILD_MAJOR_VERSION ${KUBE_GIT_MAJOR-} STABLE_BUILD_MINOR_VERSION ${KUBE_GIT_MINOR-} STABLE_DOCKER_TAG ${KUBE_GIT_VERSION/+/_} +STABLE_DOCKER_REGISTRY ${KUBE_DOCKER_REGISTRY:-k8s.gcr.io} +STABLE_DOCKER_PUSH_REGISTRY ${KUBE_DOCKER_PUSH_REGISTRY:-${KUBE_DOCKER_REGISTRY:-staging-k8s.gcr.io}} gitCommit ${KUBE_GIT_COMMIT-} gitTreeState ${KUBE_GIT_TREE_STATE-} gitVersion ${KUBE_GIT_VERSION-}