Skip to content

Commit 82ac28c

Browse files
benmossclaudiubelu
authored andcommitted
Adds support for building Windows pause image
We can use docker buildx in order to build and push Windows images from the same Linux node, as long as the Dockerfile does not have any RUN commands in the Windows step. We also need to create a non-default builder instance in order to be able to build and push Windows images. The Windows images have to be built and pushed directly to the registry. Because of this, the make target "push" has been removed (the target "all" will build and push the images). We need wincat for a few kubectl proxy scenarios. For Windows containers without Hyper-V isolation, the host OS Version and the Container OS Version need to match, which is why we added multiple Windows OS Versions to the building process. Adds support for Windows OS Versions: 1809, 1903, 1909, 2004. Bumps pause image version to 3.4. Co-Authored-By: Claudiu Belu <[email protected]> Co-Authored-By: Ben Moss <[email protected]> Signed-off-by: Leah Hanson <[email protected]>
1 parent 14a1106 commit 82ac28c

File tree

11 files changed

+281
-57
lines changed

11 files changed

+281
-57
lines changed

build/BUILD

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ filegroup(
2020
name = "all-srcs",
2121
srcs = [
2222
":package-srcs",
23+
"//build/pause/windows/wincat:all-srcs",
2324
"//build/release-tars:all-srcs",
2425
"//build/visible_to:all-srcs",
2526
],

build/dependencies.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -152,7 +152,7 @@ dependencies:
152152
match: tag =
153153

154154
- name: "k8s.gcr.io/pause"
155-
version: 3.3
155+
version: 3.4
156156
refPaths:
157157
- path: build/pause/Makefile
158158
match: TAG =

build/pause/Dockerfile

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,8 @@
1212
# See the License for the specific language governing permissions and
1313
# limitations under the License.
1414

15-
FROM scratch
15+
ARG BASE
16+
FROM ${BASE}
1617
ARG ARCH
17-
ADD bin/pause-${ARCH} /pause
18+
ADD bin/pause-linux-${ARCH} /pause
1819
ENTRYPOINT ["/pause"]

build/pause/Dockerfile_windows

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
# Copyright 2020 The Kubernetes Authors.
2+
#
3+
# Licensed under the Apache License, Version 2.0 (the "License");
4+
# you may not use this file except in compliance with the License.
5+
# You may obtain a copy of the License at
6+
#
7+
# http://www.apache.org/licenses/LICENSE-2.0
8+
#
9+
# Unless required by applicable law or agreed to in writing, software
10+
# distributed under the License is distributed on an "AS IS" BASIS,
11+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
# See the License for the specific language governing permissions and
13+
# limitations under the License.
14+
15+
ARG BASE
16+
FROM ${BASE}
17+
ARG ARCH
18+
ADD bin/pause-windows-${ARCH}.exe /pause.exe
19+
ADD windows/wincat.exe /Windows/System32/wincat.exe
20+
21+
# NOTE(claudiub): docker buildx sets the PATH env variable to a Linux-like PATH,
22+
# which is not desirable. See: https://github.com/moby/buildkit/issues/1560
23+
# TODO(claudiub): remove this once the issue has been resolved.
24+
ENV PATH="C:\Windows\system32;C:\Windows;"
25+
ENTRYPOINT ["/pause.exe"]

build/pause/Makefile

Lines changed: 95 additions & 54 deletions
Original file line numberDiff line numberDiff line change
@@ -12,91 +12,132 @@
1212
# See the License for the specific language governing permissions and
1313
# limitations under the License.
1414

15-
.PHONY: all push container clean orphan all-push push-manifest
15+
.PHONY: all container clean orphan all-push push-manifest
1616

1717
REGISTRY ?= staging-k8s.gcr.io
1818
IMAGE = $(REGISTRY)/pause
19-
IMAGE_WITH_ARCH = $(IMAGE)-$(ARCH)
19+
IMAGE_WITH_OS_ARCH = $(IMAGE)-$(OS)-$(ARCH)
2020

21-
TAG = 3.3
21+
TAG = 3.4
2222
REV = $(shell git describe --contains --always --match='v*')
2323

2424
# Architectures supported: amd64, arm, arm64, ppc64le and s390x
2525
ARCH ?= amd64
26-
27-
ALL_ARCH = amd64 arm arm64 ppc64le s390x
26+
# Operating systems supported: linux, windows
27+
OS ?= linux
28+
# OS Version for the Windows images: 1809, 1903, 1909 2004
29+
OSVERSION ?= 1809 1903 1909 2004
30+
31+
# The output type could either be docker (local), or registry.
32+
# If it is registry, it will also allow us to push the Windows images.
33+
OUTPUT_TYPE ?= docker
34+
35+
ALL_OS = linux windows
36+
ALL_ARCH.linux = amd64 arm arm64 ppc64le s390x
37+
ALL_OS_ARCH.linux = $(foreach arch, ${ALL_ARCH.linux}, linux-$(arch))
38+
ALL_ARCH.windows = amd64
39+
ALL_OSVERSIONS.windows := 1809 1903 1909 2004
40+
ALL_OS_ARCH.windows = $(foreach arch, $(ALL_ARCH.windows), $(foreach osversion, ${ALL_OSVERSIONS.windows}, windows-$(arch)-${osversion}))
41+
ALL_OS_ARCH = $(foreach os, $(ALL_OS), ${ALL_OS_ARCH.${os}})
2842

2943
CFLAGS = -Os -Wall -Werror -static -DVERSION=v$(TAG)-$(REV)
30-
KUBE_CROSS_IMAGE ?= k8s.gcr.io/build-image/kube-cross
31-
KUBE_CROSS_VERSION ?= $(shell cat ../build-image/cross/VERSION)
32-
33-
BIN = pause
34-
SRCS = pause.c
35-
36-
ifeq ($(ARCH),amd64)
37-
TRIPLE ?= x86_64-linux-gnu
38-
endif
39-
40-
ifeq ($(ARCH),arm)
41-
TRIPLE ?= arm-linux-gnueabihf
42-
endif
43-
44-
ifeq ($(ARCH),arm64)
45-
TRIPLE ?= aarch64-linux-gnu
46-
endif
47-
48-
ifeq ($(ARCH),ppc64le)
49-
TRIPLE ?= powerpc64le-linux-gnu
50-
endif
51-
52-
ifeq ($(ARCH),s390x)
53-
TRIPLE ?= s390x-linux-gnu
54-
endif
44+
KUBE_CROSS_IMAGE.linux ?= k8s.gcr.io/build-image/kube-cross
45+
KUBE_CROSS_VERSION.linux ?= $(shell cat ../build-image/cross/VERSION)
46+
KUBE_CROSS_IMAGE.windows ?= dockcross/windows-static-x64
47+
KUBE_CROSS_VERSION.windows ?= latest
48+
KUBE_CROSS_IMAGE := ${KUBE_CROSS_IMAGE.${OS}}
49+
KUBE_CROSS_VERSION := ${KUBE_CROSS_VERSION.${OS}}
50+
51+
# NOTE(claudiub): The Windows pause image also requires the wincat binary we're compiling for the
52+
# port-forwarding scenarios. If it's no longer necessary, it can be removed.
53+
# For more information, see: https://github.com/kubernetes/kubernetes/pull/91452
54+
BIN.linux = pause
55+
BIN.windows = pause wincat
56+
BIN := ${BIN.${OS}}
57+
SRCS.linux = linux/pause.c
58+
SRCS.windows = windows/pause.c
59+
SRCS := ${SRCS.${OS}}
60+
61+
EXTENSION.linux =
62+
EXTENSION.windows = .exe
63+
EXTENSION := ${EXTENSION.${OS}}
64+
65+
# The manifest command is still experimental as of Docker 18.09.3
66+
export DOCKER_CLI_EXPERIMENTAL=enabled
67+
68+
TRIPLE.windows-amd64 := x86_64-w64-mingw32.static
69+
TRIPLE.linux-amd64 := x86_64-linux-gnu
70+
TRIPLE.linux-arm := arm-linux-gnueabihf
71+
TRIPLE.linux-arm64 := aarch64-linux-gnu
72+
TRIPLE.linux-ppc64le := powerpc64le-linux-gnu
73+
TRIPLE.linux-s390x := s390x-linux-gnu
74+
TRIPLE := ${TRIPLE.${OS}-${ARCH}}
75+
BASE.linux := scratch
76+
BASE.windows := mcr.microsoft.com/windows/nanoserver
77+
BASE := ${BASE.${OS}}
5578

5679
# If you want to build AND push all containers, see the 'all-push' rule.
57-
all: all-container
80+
all: all-container-docker
5881

59-
all-push: all-push-images push-manifest
82+
# NOTE(claudiub): A non-default builder instance is needed in order to build Windows images.
83+
all-push: all-container-registry push-manifest
6084

6185
push-manifest:
62-
docker manifest create --amend $(IMAGE):$(TAG) $(shell echo $(ALL_ARCH) | sed -e "s~[^ ]*~$(IMAGE)\-&:$(TAG)~g")
63-
set -x; for arch in $(ALL_ARCH); do docker manifest annotate --arch $${arch} ${IMAGE}:${TAG} ${IMAGE}-$${arch}:${TAG}; done
86+
docker manifest create --amend $(IMAGE):$(TAG) $(shell echo $(ALL_OS_ARCH) | sed -e "s~[^ ]*~$(IMAGE)\-&:$(TAG)~g")
87+
set -x; for arch in $(ALL_ARCH.linux); do docker manifest annotate --os linux --arch $${arch} ${IMAGE}:${TAG} ${IMAGE}-linux-$${arch}:${TAG}; done
88+
# For Windows images, we also need to include the "os.version" in the manifest list, so the Windows node can pull the proper image it needs.
89+
# At the moment, docker manifest annotate doesn't allow us to set the os.version, so we'll have to it ourselves. The manifest list can be found locally as JSONs.
90+
# See: https://github.com/moby/moby/issues/41417
91+
# TODO(claudiub): Clean this up once the above issue has been fixed.
92+
set -x; \
93+
registry_prefix=$(shell (echo ${REGISTRY} | grep -Eq "[a-z]*") && echo "docker.io/" || echo ""); \
94+
manifest_image_folder=`echo "$${registry_prefix}${IMAGE}" | sed "s|/|_|g" | sed "s/:/-/"`; \
95+
for arch in $(ALL_ARCH.windows); do \
96+
for osversion in ${ALL_OSVERSIONS.windows}; do \
97+
docker manifest annotate --os windows --arch $${arch} ${IMAGE}:${TAG} ${IMAGE}-windows-$${arch}-$${osversion}:${TAG}; \
98+
BASEIMAGE=${BASE.windows}:$${osversion}; \
99+
full_version=`docker manifest inspect ${BASE.windows}:$${osversion} | grep "os.version" | head -n 1 | awk '{print $$2}'` || true; \
100+
sed -i -r "s/(\"os\"\:\"windows\")/\0,\"os.version\":$${full_version}/" "${HOME}/.docker/manifests/$${manifest_image_folder}-${TAG}/$${manifest_image_folder}-windows-$${arch}-$${osversion}-${TAG}"; \
101+
done; \
102+
done
64103
docker manifest push --purge ${IMAGE}:${TAG}
65104

66-
sub-container-%:
67-
$(MAKE) ARCH=$* container
68-
69-
sub-push-%:
70-
$(MAKE) ARCH=$* push
71-
72-
all-container: $(addprefix sub-container-,$(ALL_ARCH))
105+
all-container-docker: $(addprefix sub-container-docker-,$(ALL_OS_ARCH.linux))
106+
all-container-registry: $(addprefix sub-container-registry-,$(ALL_OS_ARCH))
73107

74-
all-push-images: $(addprefix sub-push-,$(ALL_ARCH))
108+
# split words on hyphen, access by 1-index
109+
word-hyphen = $(word $2,$(subst -, ,$1))
110+
sub-container-%:
111+
$(MAKE) OUTPUT_TYPE=$(call word-hyphen,$*,1) OS=$(call word-hyphen,$*,2) ARCH=$(call word-hyphen,$*,3) OSVERSION=$(call word-hyphen,$*,4) container
75112

76-
build: bin/$(BIN)-$(ARCH)
113+
build: $(foreach binary, ${BIN}, bin/${binary}-${OS}-${ARCH})
77114

78-
bin/$(BIN)-$(ARCH): $(SRCS)
115+
bin/${BIN.linux}-$(OS)-$(ARCH): $(SRCS)
79116
mkdir -p bin
80117
docker run --rm -u $$(id -u):$$(id -g) -v $$(pwd):/build \
81118
$(KUBE_CROSS_IMAGE):$(KUBE_CROSS_VERSION) \
82119
/bin/bash -c "\
83120
cd /build && \
84121
$(TRIPLE)-gcc $(CFLAGS) -o $@ $^ && \
85-
$(TRIPLE)-strip $@"
122+
$(TRIPLE)-strip $(foreach binary, $@, ${binary}${EXTENSION})"
123+
124+
bin/wincat-windows-${ARCH}:
125+
CGO_ENABLED=0 GOOS=windows GOARCH=${ARCH} go build -o windows/wincat.exe windows/wincat/wincat.go
86126

87-
container: .container-$(ARCH)
88-
.container-$(ARCH): bin/$(BIN)-$(ARCH)
89-
DOCKER_CLI_EXPERIMENTAL=enabled docker buildx build --load --pull --platform linux/$(ARCH) -t $(IMAGE_WITH_ARCH):$(TAG) --build-arg ARCH=$(ARCH) .
127+
container: .container-${OS}-$(ARCH)
128+
.container-linux-$(ARCH): bin/$(BIN)-$(OS)-$(ARCH)
129+
docker buildx build --pull --output=type=${OUTPUT_TYPE} --platform ${OS}/$(ARCH) \
130+
-t $(IMAGE_WITH_OS_ARCH):$(TAG) --build-arg BASE=${BASE} --build-arg ARCH=$(ARCH) .
90131
touch $@
91132

92-
push: .push-$(ARCH)
93-
.push-$(ARCH): .container-$(ARCH)
94-
docker push $(IMAGE_WITH_ARCH):$(TAG)
133+
.container-windows-$(ARCH): $(foreach binary, ${BIN}, bin/${binary}-${OS}-${ARCH})
134+
docker buildx build --pull --output=type=${OUTPUT_TYPE} --platform ${OS}/$(ARCH) \
135+
-t $(IMAGE_WITH_OS_ARCH)-${OSVERSION}:$(TAG) --build-arg BASE=${BASE}:${OSVERSION} --build-arg ARCH=$(ARCH) -f Dockerfile_windows .
95136
touch $@
96137

97138
# Useful for testing, not automatically included in container image
98-
orphan: bin/orphan-$(ARCH)
99-
bin/orphan-$(ARCH): orphan.c
139+
orphan: bin/orphan-linux-$(ARCH)
140+
bin/orphan-linux-$(ARCH): linux/orphan.c
100141
mkdir -p bin
101142
docker run -u $$(id -u):$$(id -g) -v $$(pwd):/build \
102143
$(KUBE_CROSS_IMAGE):$(KUBE_CROSS_VERSION) \
@@ -106,4 +147,4 @@ bin/orphan-$(ARCH): orphan.c
106147
$(TRIPLE)-strip $@"
107148

108149
clean:
109-
rm -rf .container-* .push-* bin/
150+
rm -rf .*-container-* .push-* bin/

build/pause/cloudbuild.yaml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,4 +16,5 @@ steps:
1616
- '-c'
1717
- |
1818
gcloud auth configure-docker \
19+
&& docker buildx create --name img-builder --use \
1920
&& make all-push
File renamed without changes.
File renamed without changes.

build/pause/windows/pause.c

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
/*
2+
Copyright 2020 The Kubernetes Authors.
3+
4+
Licensed under the Apache License, Version 2.0 (the "License");
5+
you may not use this file except in compliance with the License.
6+
You may obtain a copy of the License at
7+
8+
http://www.apache.org/licenses/LICENSE-2.0
9+
10+
Unless required by applicable law or agreed to in writing, software
11+
distributed under the License is distributed on an "AS IS" BASIS,
12+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
See the License for the specific language governing permissions and
14+
limitations under the License.
15+
*/
16+
17+
#include <windows.h>
18+
#include <stdio.h>
19+
20+
BOOL WINAPI CtrlHandler(DWORD fdwCtrlType)
21+
{
22+
switch (fdwCtrlType)
23+
{
24+
case CTRL_C_EVENT:
25+
fprintf(stderr, "Shutting down, got signal\n");
26+
exit(0);
27+
28+
case CTRL_BREAK_EVENT:
29+
fprintf(stderr, "Shutting down, got signal\n");
30+
exit(0);
31+
32+
default:
33+
return FALSE;
34+
}
35+
}
36+
37+
int main(void)
38+
{
39+
if (SetConsoleCtrlHandler(CtrlHandler, TRUE))
40+
{
41+
Sleep(INFINITE);
42+
}
43+
else
44+
{
45+
printf("\nERROR: Could not set control handler\n");
46+
return 1;
47+
}
48+
return 0;
49+
}

build/pause/windows/wincat/BUILD

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
load("@io_bazel_rules_go//go:def.bzl", "go_binary", "go_library")
2+
3+
go_library(
4+
name = "go_default_library",
5+
srcs = ["wincat.go"],
6+
importpath = "k8s.io/kubernetes/build/pause/windows/wincat",
7+
visibility = ["//visibility:private"],
8+
)
9+
10+
go_binary(
11+
name = "windows",
12+
embed = [":go_default_library"],
13+
visibility = ["//visibility:public"],
14+
)
15+
16+
filegroup(
17+
name = "package-srcs",
18+
srcs = glob(["**"]),
19+
tags = ["automanaged"],
20+
visibility = ["//visibility:private"],
21+
)
22+
23+
filegroup(
24+
name = "all-srcs",
25+
srcs = [":package-srcs"],
26+
tags = ["automanaged"],
27+
visibility = ["//visibility:public"],
28+
)

0 commit comments

Comments
 (0)