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

Build and push multi-arch/os (amazon and windows, no debian) image manifest via Make rules #957

Merged
merged 2 commits into from
Aug 5, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
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
51 changes: 11 additions & 40 deletions .github/workflows/container-image.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,6 @@ jobs:
buildx:
# this is to prevent the job to run at forked projects
if: github.repository == 'kubernetes-sigs/aws-ebs-csi-driver'
env:
IMAGE: aws-ebs-csi-driver
DEB_BUILD_TAG: aws-ebs-csi-driver:debian
AL2_BUILD_TAG: aws-ebs-csi-driver:amazonlinux
runs-on: ubuntu-latest
steps:
- name: Checkout
Expand All @@ -20,49 +16,24 @@ jobs:
uses: docker/setup-buildx-action@v1
- name: Set up QEMU
uses: docker/setup-qemu-action@v1
- name: Build debian target
run: |
docker buildx build \
-t $DEB_BUILD_TAG \
--platform=linux/arm64,linux/amd64 \
--output="type=image,push=false" . \
--target=debian-base
- name: Build amazonlinux target
run: |
docker buildx build \
-t $AL2_BUILD_TAG \
--platform=linux/arm64,linux/amd64 \
--output="type=image,push=false" . \
--target=amazonlinux
- name: Set environment variables
run: |
BRANCH=$(echo $GITHUB_REF | cut -d'/' -f3)
SHORT_SHA=$(echo $GITHUB_SHA | cut -c -7)
echo "BRANCH=$BRANCH" >> $GITHUB_ENV
if [ "$BRANCH" = "master" ]; then
TAG=$SHORT_SHA
REGISTRY_NAME=docker.io/library/amazon
BRANCH_OR_TAG=$(echo $GITHUB_REF | cut -d'/' -f3)
if [ "$BRANCH_OR_TAG" = "master" ]; then
GIT_TAG=$GITHUB_SHA
else
TAG=$BRANCH
GIT_TAG=$BRANCH_OR_TAG
fi
echo "TAG=$TAG" >> $GITHUB_ENV
echo "REGISTRY_NAME=$REGISTRY_NAME" >> $GITHUB_ENV
echo "GIT_TAG=$GIT_TAG" >> $GITHUB_ENV
- name: Login to Docker Hub
uses: docker/login-action@v1
with:
username: ${{ secrets.DOCKERHUB_USER }}
password: ${{ secrets.DOCKERHUB_TOKEN }}
- name: Push debian target to Docker Hub
run: |
DEB_PUSH_TAG="amazon/$IMAGE:$TAG"
docker buildx build \
-t $DEB_PUSH_TAG \
--platform=linux/arm64,linux/amd64 \
--output="type=image,push=true" . \
--target=debian-base
- name: Push amazonlinux target to Docker Hub
- name: Push manifest list containing amazon linux and windows based images to Docker Hub
run: |
AL2_PUSH_TAG="amazon/$IMAGE:$TAG-amazonlinux"
docker buildx build \
-t $AL2_PUSH_TAG \
--platform=linux/arm64,linux/amd64 \
--output="type=image,push=true" . \
--target=amazonlinux
export REGISTRY=$REGISTRY_NAME
export TAG=$GIT_TAG
make all-push
29 changes: 18 additions & 11 deletions Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -12,21 +12,28 @@
# See the License for the specific language governing permissions and
# limitations under the License.

FROM golang:1.16 AS builder
FROM --platform=$BUILDPLATFORM golang:1.16 AS builder
WORKDIR /go/src/github.com/kubernetes-sigs/aws-ebs-csi-driver
COPY . .
RUN make
ARG OS
ARG ARCH
RUN make $OS/$ARCH

FROM amazonlinux:2 AS amazonlinux
RUN yum update -y
RUN yum install ca-certificates e2fsprogs xfsprogs util-linux -y
RUN yum clean all
FROM amazonlinux:2 AS linux-amazon
RUN yum update -y && \
yum install ca-certificates e2fsprogs xfsprogs util-linux -y && \
yum clean all
COPY --from=builder /go/src/github.com/kubernetes-sigs/aws-ebs-csi-driver/bin/aws-ebs-csi-driver /bin/aws-ebs-csi-driver

ENTRYPOINT ["/bin/aws-ebs-csi-driver"]

FROM k8s.gcr.io/build-image/debian-base:buster-v1.8.0 AS debian-base
RUN clean-install ca-certificates e2fsprogs mount udev util-linux xfsprogs
COPY --from=builder /go/src/github.com/kubernetes-sigs/aws-ebs-csi-driver/bin/aws-ebs-csi-driver /bin/aws-ebs-csi-driver
FROM mcr.microsoft.com/windows/servercore:1809 AS windows-1809
COPY --from=builder /go/src/github.com/kubernetes-sigs/aws-ebs-csi-driver/bin/aws-ebs-csi-driver.exe /aws-ebs-csi-driver.exe
ENTRYPOINT ["/aws-ebs-csi-driver.exe"]

ENTRYPOINT ["/bin/aws-ebs-csi-driver"]
FROM mcr.microsoft.com/windows/servercore:2004 AS windows-2004
COPY --from=builder /go/src/github.com/kubernetes-sigs/aws-ebs-csi-driver/bin/aws-ebs-csi-driver.exe /aws-ebs-csi-driver.exe
ENTRYPOINT ["/aws-ebs-csi-driver.exe"]

FROM mcr.microsoft.com/windows/servercore:20H2 AS windows-20H2
COPY --from=builder /go/src/github.com/kubernetes-sigs/aws-ebs-csi-driver/bin/aws-ebs-csi-driver.exe /aws-ebs-csi-driver.exe
ENTRYPOINT ["/aws-ebs-csi-driver.exe"]
23 changes: 0 additions & 23 deletions Dockerfile.windows

This file was deleted.

92 changes: 83 additions & 9 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -12,28 +12,103 @@
# See the License for the specific language governing permissions and
# limitations under the License.

PKG=github.com/kubernetes-sigs/aws-ebs-csi-driver
IMAGE?=amazon/aws-ebs-csi-driver
VERSION=v1.2.0
VERSION_AMAZONLINUX=$(VERSION)-amazonlinux

PKG=github.com/kubernetes-sigs/aws-ebs-csi-driver
GIT_COMMIT?=$(shell git rev-parse HEAD)
BUILD_DATE?=$(shell date -u +"%Y-%m-%dT%H:%M:%SZ")
BUILD_DATE?=$(shell date -u -Iseconds)

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Any reason to not use human readable here?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

it is the same, just shows offest instead of Z, e.g. 2021-08-05T21:02:49+00:00


LDFLAGS?="-X ${PKG}/pkg/driver.driverVersion=${VERSION} -X ${PKG}/pkg/cloud.driverVersion=${VERSION} -X ${PKG}/pkg/driver.gitCommit=${GIT_COMMIT} -X ${PKG}/pkg/driver.buildDate=${BUILD_DATE} -s -w"

GO111MODULE=on
GOPROXY=direct
GOPATH=$(shell go env GOPATH)
GOOS=$(shell go env GOOS)
GOBIN=$(shell pwd)/bin

REGISTRY?=gcr.io/k8s-staging-provider-aws
IMAGE?=$(REGISTRY)/aws-ebs-csi-driver
TAG?=$(GIT_COMMIT)

OUTPUT_TYPE?=docker

OS?=linux
ARCH?=amd64
OSVERSION?=amazon

ALL_OS?=linux windows
ALL_ARCH_linux?=amd64 arm64
ALL_OSVERSION_linux?=amazon
ALL_OS_ARCH_OSVERSION_linux=$(foreach arch, $(ALL_ARCH_linux), $(foreach osversion, ${ALL_OSVERSION_linux}, linux-$(arch)-${osversion}))
ALL_ARCH_windows?=amd64
ALL_OSVERSION_windows?=1809 2004 20H2
ALL_OS_ARCH_OSVERSION_windows=$(foreach arch, $(ALL_ARCH_windows), $(foreach osversion, ${ALL_OSVERSION_windows}, windows-$(arch)-${osversion}))
ALL_OS_ARCH_OSVERSION=$(foreach os, $(ALL_OS), ${ALL_OS_ARCH_OSVERSION_${os}})

# split words on hyphen, access by 1-index
word-hyphen = $(word $2,$(subst -, ,$1))

.EXPORT_ALL_VARIABLES:

.PHONY: bin/aws-ebs-csi-driver
.PHONY: linux/$(ARCH)
linux/$(ARCH): bin/aws-ebs-csi-driver
bin/aws-ebs-csi-driver: | bin
CGO_ENABLED=0 GOOS=linux go build -mod=vendor -ldflags ${LDFLAGS} -o bin/aws-ebs-csi-driver ./cmd/
CGO_ENABLED=0 GOOS=linux GOARCH=$(ARCH) go build -mod=vendor -ldflags ${LDFLAGS} -o bin/aws-ebs-csi-driver ./cmd/

.PHONY: bin/aws-ebs-csi-driver.exe
.PHONY: windows/$(ARCH)
windows/$(ARCH): bin/aws-ebs-csi-driver.exe
bin/aws-ebs-csi-driver.exe: | bin
CGO_ENABLED=0 GOOS=windows go build -mod=vendor -ldflags ${LDFLAGS} -o bin/aws-ebs-csi-driver.exe ./cmd/
CGO_ENABLED=0 GOOS=windows GOARCH=$(ARCH) go build -mod=vendor -ldflags ${LDFLAGS} -o bin/aws-ebs-csi-driver.exe ./cmd/

# Builds all linux images (not windows because it can't be exported with OUTPUT_TYPE=docker)
all: all-image-docker

# Builds all linux and windows images and pushes them
all-push: all-image-registry push-manifest

push-manifest: create-manifest all-annotate-manifest
docker manifest push --purge $(IMAGE):$(TAG)

create-manifest:
# sed expression:
# LHS: match 0 or more not space characters
# RHS: replace with $(IMAGE):$(TAG)-& where & is what was matched on LHS
docker manifest create --amend $(IMAGE):$(TAG) $(shell echo $(ALL_OS_ARCH_OSVERSION) | sed -e "s~[^ ]*~$(IMAGE):$(TAG)\-&~g")

all-annotate-manifest: $(addprefix sub-annotate-manifest-,$(ALL_OS_ARCH_OSVERSION))

sub-annotate-manifest-%:
$(MAKE) OS=$(call word-hyphen,$*,1) ARCH=$(call word-hyphen,$*,2) OSVERSION=$(call word-hyphen,$*,3) annotate-manifest

annotate-manifest: .annotate-manifest-$(OS)-$(ARCH)-$(OSVERSION)
.annotate-manifest-$(OS)-$(ARCH)-$(OSVERSION):
set -x; docker manifest annotate --os $(OS) --arch $(ARCH) --os-version $(OSVERSION) $(IMAGE):$(TAG) $(IMAGE):$(TAG)-$(OS)-$(ARCH)-$(OSVERSION)

# only linux for OUTPUT_TYPE=docker because windows image cannot be exported
# "Currently, multi-platform images cannot be exported with the docker export type. The most common usecase for multi-platform images is to directly push to a registry (see registry)."
# https://docs.docker.com/engine/reference/commandline/buildx_build/#output
all-image-docker: $(addprefix sub-image-docker-,$(ALL_OS_ARCH_OSVERSION_linux))
all-image-registry: $(addprefix sub-image-registry-,$(ALL_OS_ARCH_OSVERSION))

sub-image-%:
$(MAKE) OUTPUT_TYPE=$(call word-hyphen,$*,1) OS=$(call word-hyphen,$*,2) ARCH=$(call word-hyphen,$*,3) OSVERSION=$(call word-hyphen,$*,4) image

image: .image-$(TAG)-$(OS)-$(ARCH)-$(OSVERSION)
.image-$(TAG)-$(OS)-$(ARCH)-$(OSVERSION):
docker buildx build \
--platform=$(OS)/$(ARCH) \
--build-arg OS=$(OS) \
--build-arg ARCH=$(ARCH) \
--progress=plain \
--target=$(OS)-$(OSVERSION) \
--output=type=$(OUTPUT_TYPE) \
-t=$(IMAGE):$(TAG)-$(OS)-$(ARCH)-$(OSVERSION) \

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is there a standard for this format of tag? If not we should make sure we come up with something across the provider-aws subprojects (i.e. just use the same format that you are using). This docker post shows a buildx example where the different platforms share a tag, but I'm not clear how pulling works in that case.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

the tag is only used for local build and adding the locally built image to the manifest list, it won't get pushed with the same tag as far as I can tell . At least, when I pushed it to public ECR as a test it did not expose these intermediary tags anywhere https://gallery.ecr.aws/b5w6x5z2/aws-ebs-csi-driver

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah, makes sense 👍

.
touch $@

.PHONY: clean
clean:
rm -rf .*image-* bin/

bin /tmp/helm /tmp/kubeval:
@mkdir -p $@
Expand Down Expand Up @@ -142,7 +217,6 @@ verify-vendor:
@ echo; echo "### $@:"
@ ./hack/verify-vendor.sh


.PHONY: generate-kustomize
generate-kustomize: bin/helm
cd charts/aws-ebs-csi-driver && ../../bin/helm template kustomize . -s templates/clusterrole-attacher.yaml > ../../deploy/kubernetes/base/clusterrole-attacher.yaml
Expand Down
6 changes: 3 additions & 3 deletions examples/kubernetes/windows/README.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
## Windows

**This example requires pre-release versions of csi-proxy and the driver that do not exist yet. It is intended for developers only for now. Only basic read/write (mount/unmount and attach/detach) functionality has been tested, other features like resize don't work yet.**
**This example requires unreleased versions of csi-proxy and the driver that. It is intended for developers only for now. It will be updated once the driver has been released. Only basic read/write (mount/unmount and attach/detach) functionality has been tested, other features like resize don't work yet.**

This example shows how to create a EBS volume and consume it from a Windows container dynamically.

Expand All @@ -9,8 +9,8 @@ This example shows how to create a EBS volume and consume it from a Windows cont

1. A 1.18+ Windows node. Windows support has only been tested on 1.18 EKS Windows nodes. https://docs.aws.amazon.com/eks/latest/userguide/windows-support.html
2. [csi-proxy](https://github.com/kubernetes-csi/csi-proxy) v1.0.0+ installed on the Windows node.
3. The driver v1.2.0+ Node plugin (DaemonSet) installed on the Windows node.
4. The driver v1.2.0+ Controller plugin (Deployment) installed on a Linux node (as it cannot run on a Windows node).
3. An image of the driver built for Windows. It can be built and pushed with the command `TAG=$MY_TAG REGISTRY=$MY_REGISTRY make all-push` where `MY_TAG` refers to the image tag to push and `MY_REGISTRY` to the destination image registry like "XXXXXXXXXXXX.dkr.ecr.us-west-2.amazonaws.com"
4. The driver installed with the Node plugin on the Windows node and the Controller plugin on a Linux node: `helm upgrade --install aws-ebs-csi-driver --namespace kube-system ./charts/aws-ebs-csi-driver --set node.enableWindows=true --set image.repository=$MY_REGISTRY/aws-ebs-csi-driver --set image.tag=$MY_TAG`

## Usage

Expand Down
3 changes: 2 additions & 1 deletion hack/e2e/ecr.sh
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,8 @@ function ecr_build_and_push() {
set -e
loudecho "Building and pushing test driver image to ${IMAGE_NAME}:${IMAGE_TAG}"
aws ecr get-login-password --region "${REGION}" | docker login --username AWS --password-stdin "${AWS_ACCOUNT_ID}".dkr.ecr."${REGION}".amazonaws.com
docker build -t "${IMAGE_NAME}":"${IMAGE_TAG}" .
IMAGE=${IMAGE_NAME} TAG=${IMAGE_TAG} OS=linux ARCH=amd64 OSVERSION=amazon make image
docker tag "${IMAGE_NAME}":"${IMAGE_TAG}"-linux-amd64-amazon "${IMAGE_NAME}":"${IMAGE_TAG}"
docker push "${IMAGE_NAME}":"${IMAGE_TAG}"
fi
}
24 changes: 5 additions & 19 deletions hack/prow.sh
Original file line number Diff line number Diff line change
Expand Up @@ -30,29 +30,15 @@ gcloud auth configure-docker
loudecho "Set up Docker Buildx"
# See https://github.com/docker/setup-buildx-action
# and https://github.com/kubernetes-csi/csi-release-tools/blob/master/build.make#L132
DOCKER_CLI_EXPERIMENTAL=enabled
export DOCKER_CLI_EXPERIMENTAL
export DOCKER_CLI_EXPERIMENTAL=enabled
trap "docker buildx rm multiarchimage-buildertest" EXIT
docker buildx create --use --name multiarchimage-buildertest

loudecho "Set up QEMU"
# See https://github.com/docker/setup-qemu-action
docker run --rm --privileged multiarch/qemu-user-static --reset -p yes

loudecho "Build and push debian target"
docker buildx build \
--tag="${REGISTRY_NAME}"/aws-ebs-csi-driver:"${GIT_TAG}" \
--platform=linux/arm64,linux/amd64 \
--progress=plain \
--push=true \
--target=debian-base \
.

loudecho "Build and push amazonlinux target"
docker buildx build \
--tag="${REGISTRY_NAME}"/aws-ebs-csi-driver:"${GIT_TAG}"-amazonlinux \
--platform=linux/arm64,linux/amd64 \
--progress=plain \
--push=true \
--target=amazonlinux \
.
loudecho "Push manifest list containing amazon linux and windows based images to GCR"
export REGISTRY=$REGISTRY_NAME
export TAG=$GIT_TAG
make all-push