Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add multi-arch image via Bazel #1452

Merged
merged 3 commits into from
Oct 9, 2020
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,4 +1,7 @@
out/
bazel-*
*~
BUILD.bazel
.idea
*.iml
.vagrant
26 changes: 26 additions & 0 deletions .travis.yml
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
language: go
os: linux
dist: bionic

env:
global:
- IMAGE_REPO=localhost:5000 REGISTRY=localhost:5000
Expand Down Expand Up @@ -35,3 +36,28 @@ jobs:
- make travis-setup
script:
- make integration-test-misc

- name: bazel amd64
arch: amd64
env: CPU=k8
before_install: &before_install_multiarch
- export PATH=$PATH:$HOME/bin && mkdir -p $HOME/bin
- eval $(go env)
# install bazelisk as bazel to install the appropriate bazel version
- wget https://github.com/bazelbuild/bazelisk/releases/download/v1.6.1/bazelisk-linux-${GOARCH} && chmod +x bazelisk-linux-${GOARCH} && mv bazelisk-linux-${GOARCH} $HOME/bin/bazel
script: &script_multiarch
# Generate BUILD.bazel files (we do not check them in)
- bazel run //:gazelle
- bazel build --cpu=${CPU} --curses=no //cmd/executor:all
# Build all targets tagged with our architecture:
- bazel build --cpu=${CPU} --curses=no $(bazel query 'attr("tags", "'${GOARCH}'", "//...")')
# Run all tests not tagged as "manual":
- bazel test --cpu=${CPU} --curses=no --test_output=errors --test_timeout=900 //cmd/executor:all
# Run all tests tagged with our architecture:
- bazel test --cpu=${CPU} --curses=no --test_output=errors --test_timeout=900 $(bazel query 'attr("tags", "'${GOARCH}'", "//...")')

- name: bazel arm64
arch: arm64
env: CPU=aarch64
before_install: *before_install_multiarch
script: *script_multiarch
4 changes: 4 additions & 0 deletions BUILD
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
load("@bazel_gazelle//:def.bzl", "gazelle")

# gazelle:prefix github.com/GoogleContainerTools/kaniko
gazelle(name = "gazelle")
53 changes: 53 additions & 0 deletions WORKSPACE
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
workspace(name = "kaniko")

load("@bazel_tools//tools/build_defs/repo:http.bzl", "http_archive")

http_archive(
name = "io_bazel_rules_go",
sha256 = "b725e6497741d7fc2d55fcc29a276627d10e43fa5d0bb692692890ae30d98d00",
urls = [
"https://mirror.bazel.build/github.com/bazelbuild/rules_go/releases/download/v0.24.3/rules_go-v0.24.3.tar.gz",
"https://github.com/bazelbuild/rules_go/releases/download/v0.24.3/rules_go-v0.24.3.tar.gz",
],
)

http_archive(
name = "bazel_gazelle",
sha256 = "b85f48fa105c4403326e9525ad2b2cc437babaa6e15a3fc0b1dbab0ab064bc7c",
urls = [
"https://mirror.bazel.build/github.com/bazelbuild/bazel-gazelle/releases/download/v0.22.2/bazel-gazelle-v0.22.2.tar.gz",
"https://github.com/bazelbuild/bazel-gazelle/releases/download/v0.22.2/bazel-gazelle-v0.22.2.tar.gz",
],
)

load("@io_bazel_rules_go//go:deps.bzl", "go_register_toolchains", "go_rules_dependencies")
load("@bazel_gazelle//:deps.bzl", "gazelle_dependencies")

go_rules_dependencies()

go_register_toolchains()

gazelle_dependencies()

# Docker rules.
http_archive(
name = "io_bazel_rules_docker",
sha256 = "cf53839c398e464b10ec2fbeb11aedb446f078c28e3b4ce372461bb105ef435c",
strip_prefix = "rules_docker-f8478e57ab7457e403fda474f06ac0bb120d92a7",
urls = ["https://github.com/bazelbuild/rules_docker/archive/f8478e57ab7457e403fda474f06ac0bb120d92a7.tar.gz"],
)

load(
"@io_bazel_rules_docker//repositories:repositories.bzl",
container_repositories = "repositories",
)

container_repositories()

load("@io_bazel_rules_docker//repositories:deps.bzl", container_deps = "deps")

container_deps()

load("@io_bazel_rules_docker//repositories:pip_repositories.bzl", "pip_deps")

pip_deps()
126 changes: 126 additions & 0 deletions cmd/executor/BUILD
Original file line number Diff line number Diff line change
@@ -0,0 +1,126 @@
load("@io_bazel_rules_go//go:def.bzl", "go_binary", "go_library")
load("@io_bazel_rules_docker//container:container.bzl", "container_image")

go_library(
name = "executor_lib",
srcs = ["main.go"],
importpath = "github.com/GoogleContainerTools/kaniko/cmd/executor",
visibility = ["//visibility:private"],
deps = ["//cmd/executor/cmd"],
)

go_binary(
name = "executor",
embed = [":executor_lib"],
pure = "on",
visibility = ["//visibility:public"],
)

ARCHITECTURES = [
"amd64",
"arm64",
]

[
go_binary(
name = "executor_" + arch,
embed = [":executor_lib"],
goarch = arch,
goos = "linux",
pure = "on",
visibility = ["//visibility:public"],
)
for arch in ARCHITECTURES
]

[
container_image(
name = "image_" + arch,
architecture = arch,
base = "//files:image",
directory = "/kaniko",
entrypoint = ["/kaniko/executor_" + arch],
env = {
"HOME": "/root",
"USER": "root",
"PATH": "/usr/local/bin:/kaniko",
"SSL_CERT_DIR": "/kaniko/ssl/certs",
"DOCKER_CONFIG": "/kaniko/.docker/",
},
files = [
":executor_" + arch,
],
symlinks = {
"/kaniko/executor": "/kaniko/executor_" + arch,
},
workdir = "/workspace",
)
for arch in ARCHITECTURES
]

# Image with testdata
[
container_image(
name = "buildtest_image_" + arch,
architecture = arch,
base = ":image_" + arch,
directory = "/workspace",
files = [
":testdata/Dockerfile.trivial",
],
)
for arch in ARCHITECTURES
]

load("@io_bazel_rules_docker//contrib:test.bzl", "container_test")

# Non-executable tests can run on any architecture,
# so do not tag them.
[
container_test(
mattmoor marked this conversation as resolved.
Show resolved Hide resolved
name = "image_files_" + arch + "_test",
configs = ["testdata/files.yaml"],
image = ":image_" + arch,
# tags = ["manual", arch],
mattmoor marked this conversation as resolved.
Show resolved Hide resolved
)
for arch in ARCHITECTURES
]

[
container_test(
name = "buildtest_image_" + arch + "_test",
configs = [
"testdata/files.yaml",
"testdata/testfiles.yaml",
],
image = ":buildtest_image_" + arch,
# tags = ["manual", arch],
)
for arch in ARCHITECTURES
]

[
container_test(
name = "image_exec_" + arch + "_test",
configs = ["testdata/exec.yaml"],
image = ":image_" + arch,
tags = [
"manual",
arch,
],
)
for arch in ARCHITECTURES
]

[
container_test(
name = "image_build_" + arch + "_test",
configs = ["testdata/build.yaml"],
image = ":buildtest_image_" + arch,
tags = [
"manual",
arch,
],
)
for arch in ARCHITECTURES
]
6 changes: 4 additions & 2 deletions cmd/executor/cmd/root.go
Original file line number Diff line number Diff line change
Expand Up @@ -95,8 +95,10 @@ var RootCmd = &cobra.Command{
}
logrus.Warn("kaniko is being run outside of a container. This can have dangerous effects on your system")
}
if err := executor.CheckPushPermissions(opts); err != nil {
exit(errors.Wrap(err, "error checking push permissions -- make sure you entered the correct tag name, and that you are authenticated correctly, and try again"))
if !opts.NoPush {
if err := executor.CheckPushPermissions(opts); err != nil {
exit(errors.Wrap(err, "error checking push permissions -- make sure you entered the correct tag name, and that you are authenticated correctly, and try again"))
}
}
if err := resolveRelativePaths(); err != nil {
exit(errors.Wrap(err, "error resolving relative paths to absolute paths"))
Expand Down
2 changes: 2 additions & 0 deletions cmd/executor/testdata/Dockerfile.trivial
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
FROM ubuntu
mattmoor marked this conversation as resolved.
Show resolved Hide resolved
RUN echo Hello
5 changes: 5 additions & 0 deletions cmd/executor/testdata/build.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
schemaVersion: "1.0.0"
commandTests:
- name: Trivial build
command: ["/kaniko/executor", "--no-push", "--dockerfile", "./Dockerfile.trivial"]
exitCode: 0
10 changes: 10 additions & 0 deletions cmd/executor/testdata/exec.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
schemaVersion: "1.0.0"
commandTests:
- name: check fixed name
command: ["/kaniko/executor"]
expectedError: ['Usage:']
exitCode: 1
- name: check PATH
command: ["executor"]
expectedError: ['Usage:']
exitCode: 1
12 changes: 12 additions & 0 deletions cmd/executor/testdata/files.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
schemaVersion: "1.0.0"
fileExistenceTests:
# Basic FS sanity checks.
- name: root
path: '/'
shouldExist: true
- name: certs
path: '/kaniko/ssl/certs/ca-certificates.crt'
shouldExist: true
- name: certs
path: '/etc/nsswitch.conf'
shouldExist: true
6 changes: 6 additions & 0 deletions cmd/executor/testdata/testfiles.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
schemaVersion: "1.0.0"
fileExistenceTests:
# Basic FS sanity checks.
- name: trivial testdata Dockerfile
path: '/workspace/Dockerfile.trivial'
shouldExist: true
70 changes: 70 additions & 0 deletions deploy/cloudbuild-release.yaml
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
# This cloudbuild is run on the creation of new tags, which should signify releases.
timeout: 1800s

steps:

# First, build kaniko
- name: "gcr.io/cloud-builders/docker"
args: ["build", "-f", "deploy/Dockerfile",
Expand All @@ -21,6 +24,73 @@ steps:
- name: "gcr.io/cloud-builders/docker"
args: ["tag", "gcr.io/kaniko-project/warmer:$TAG_NAME",
"gcr.io/kaniko-project/warmer:latest"]


# Build each of the multi-arch images with Bazel and load them into the Docker daemon.
- name: gcr.io/cloud-marketplace-containers/google/bazel:3.4.1
entrypoint: sh
args:
- -c
- |
#!/bin/sh
set -o errexit
set -o xtrace

bazel run //:gazelle
bazel run --host_force_python=PY2 //cmd/executor:image_amd64
bazel run --host_force_python=PY2 //cmd/executor:image_arm64

# Publish the individual container images
- name: docker
entrypoint: sh
args:
- -c
- |
#!/bin/sh
set -o errexit
set -o xtrace

docker tag bazel/cmd/executor:image_amd64 gcr.io/kaniko-project/executor:amd64
docker tag bazel/cmd/executor:image_amd64 gcr.io/kaniko-project/executor:amd64-$TAG_NAME
docker tag bazel/cmd/executor:image_arm64 gcr.io/kaniko-project/executor:arm64
docker tag bazel/cmd/executor:image_arm64 gcr.io/kaniko-project/executor:arm64-$TAG_NAME

docker push gcr.io/kaniko-project/executor:amd64
docker push gcr.io/kaniko-project/executor:amd64-$TAG_NAME
docker push gcr.io/kaniko-project/executor:arm64
docker push gcr.io/kaniko-project/executor:arm64-$TAG_NAME

# Enable "manifest list" support in docker, and publish one covering the per-architecture
# images published above.
- name: docker
entrypoint: sh
args:
- -c
- |
#!/bin/sh
set -o errexit
set -o xtrace

# Publish manifest lists second, after all of the binary material
# has been uploaded, so that it is fast. We want fast because enabling
# the experimental features in docker changes ~/.docker/config.json, which
# GCB periodically tramples.
#
# Enable support for 'docker manifest create'
# https://docs.docker.com/engine/reference/commandline/manifest_create/
sed -i 's/^{/{"experimental": "enabled",/g' ~/.docker/config.json

docker manifest create gcr.io/kaniko-project/executor:multi-arch \
gcr.io/kaniko-project/executor:amd64 \
gcr.io/kaniko-project/executor:arm64
docker manifest push gcr.io/kaniko-project/executor:multi-arch

docker manifest create gcr.io/kaniko-project/executor:multi-arch-$TAG_NAME \
gcr.io/kaniko-project/executor:amd64-$TAG_NAME \
gcr.io/kaniko-project/executor:arm64-$TAG_NAME
docker manifest push gcr.io/kaniko-project/executor:multi-arch-$TAG_NAME


images: ["gcr.io/kaniko-project/executor:$TAG_NAME",
"gcr.io/kaniko-project/executor:latest",
"gcr.io/kaniko-project/executor:debug-$TAG_NAME",
Expand Down
Loading