From 07b1f81c1468ba15717549699727493ed87f42b3 Mon Sep 17 00:00:00 2001 From: John Gardiner Myers Date: Tue, 1 Aug 2023 09:52:08 -0700 Subject: [PATCH] Build image with ko --- .github/workflows/staging-image-tester.yml | 13 +--- .github/workflows/trivy.yml | 21 ------- .ko.yaml | 11 ++++ Dockerfile | 39 ------------ Dockerfile.mini | 40 ------------ Makefile | 73 ++++++++-------------- cloudbuild.yaml | 14 ++--- docs/contributing/getting-started.md | 4 +- docs/faq.md | 2 +- scripts/install-ko.sh | 24 +++++++ scripts/run-trivy.sh | 13 ---- 11 files changed, 69 insertions(+), 185 deletions(-) delete mode 100644 .github/workflows/trivy.yml create mode 100644 .ko.yaml delete mode 100644 Dockerfile delete mode 100644 Dockerfile.mini create mode 100755 scripts/install-ko.sh delete mode 100755 scripts/run-trivy.sh diff --git a/.github/workflows/staging-image-tester.yml b/.github/workflows/staging-image-tester.yml index 138674e6fd..79d2da579b 100644 --- a/.github/workflows/staging-image-tester.yml +++ b/.github/workflows/staging-image-tester.yml @@ -33,14 +33,5 @@ jobs: run: | go get -v -t -d ./... - - name: Test build on amd64 - run: make build.image-amd64 - - - name: Clean - run: make clean - - - name: Test build on arm64 - run: make build.image-arm64 - - - name: Clean - run: make clean + - name: Test + run: make build.image/multiarch diff --git a/.github/workflows/trivy.yml b/.github/workflows/trivy.yml deleted file mode 100644 index 08bb97159d..0000000000 --- a/.github/workflows/trivy.yml +++ /dev/null @@ -1,21 +0,0 @@ -name: trivy vulnerability scanner -on: - push: - -permissions: - contents: read # to fetch code (actions/checkout) - -jobs: - build: - name: Build - runs-on: ubuntu-latest - steps: - - name: Checkout code - uses: actions/checkout@v3 - - name: Build an image from Dockerfile - run: | - make build.docker - - name: Run trivy - run: | - ./scripts/run-trivy.sh - diff --git a/.ko.yaml b/.ko.yaml new file mode 100644 index 0000000000..b457e288b6 --- /dev/null +++ b/.ko.yaml @@ -0,0 +1,11 @@ +defaultBaseImage: gcr.io/distroless/static-debian11:latest +builds: +- env: + - CGO_ENABLED=0 + flags: + - -v + ldflags: + - -s + - -w + - -X sigs.k8s.io/external-dns/pkg/apis/externaldns.Version={{.Env.VERSION}} + diff --git a/Dockerfile b/Dockerfile deleted file mode 100644 index f4eca39004..0000000000 --- a/Dockerfile +++ /dev/null @@ -1,39 +0,0 @@ -# Copyright 2017 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. - -# builder image -ARG ARCH -FROM golang:1.20 as builder -ARG ARCH - -WORKDIR /sigs.k8s.io/external-dns - -COPY go.mod . -COPY go.sum . -RUN go mod download - -COPY . . - -FROM alpine:3.18 - -RUN apk update && apk add "libcrypto3>=3.1.1-r0" "libssl3>=3.1.1-r0" && rm -rf /var/cache/apk/* - -COPY --from=builder /etc/ssl/certs/ca-certificates.crt /etc/ssl/certs/ca-certificates.crt -COPY --from=builder /sigs.k8s.io/external-dns/build/external-dns /bin/external-dns - -# Run as UID for nobody since k8s pod securityContext runAsNonRoot can't resolve the user ID: -# https://github.com/kubernetes/kubernetes/issues/40958 -USER 65534 - -ENTRYPOINT ["/bin/external-dns"] diff --git a/Dockerfile.mini b/Dockerfile.mini deleted file mode 100644 index 2428351aed..0000000000 --- a/Dockerfile.mini +++ /dev/null @@ -1,40 +0,0 @@ -# Copyright 2017 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. - -FROM golang:1.20 as builder - -WORKDIR /sigs.k8s.io/external-dns - -RUN apt-get update \ - && apt-get install \ - ca-certificates \ - && update-ca-certificates - -COPY go.mod . -COPY go.sum . -RUN go mod download - -COPY . . -RUN make test build - -FROM gcr.io/distroless/static - -COPY --from=builder /etc/ssl/certs/ca-certificates.crt /etc/ssl/certs/ca-certificates.crt -COPY --from=builder /sigs.k8s.io/external-dns/build/external-dns /bin/external-dns - -# Run as UID for nobody since k8s pod securityContext runAsNonRoot can't resolve the user ID: -# https://github.com/kubernetes/kubernetes/issues/40958 -USER 65534 - -ENTRYPOINT ["/bin/external-dns"] diff --git a/Makefile b/Makefile index e32015fabf..7f0cc52141 100644 --- a/Makefile +++ b/Makefile @@ -44,18 +44,16 @@ else CONTROLLER_GEN=$(shell which controller-gen) endif -.PHONY: go-lint - golangci-lint: @command -v golangci-lint > /dev/null || curl -sSfL https://raw.githubusercontent.com/golangci/golangci-lint/master/install.sh | sh -s -- -b $(go env GOPATH)/bin v1.53.3 # Run the golangci-lint tool +.PHONY: go-lint go-lint: golangci-lint golangci-lint run --timeout=15m ./... -.PHONY: licensecheck - # Run the licensecheck script to check for license headers +.PHONY: licensecheck licensecheck: @echo ">> checking license header" @licRes=$$(for file in $$(find . -type f -iname '*.go' ! -path './vendor/*') ; do \ @@ -66,58 +64,51 @@ licensecheck: exit 1; \ fi -.PHONY: lint - # Run all the linters +.PHONY: lint lint: licensecheck go-lint -.PHONY: crd - # generates CRD using controller-gen +.PHONY: crd crd: controller-gen ${CONTROLLER_GEN} crd:crdVersions=v1 paths="./endpoint/..." output:crd:stdout > docs/contributing/crd-source/crd-manifest.yaml # The verify target runs tasks similar to the CI tasks, but without code coverage -.PHONY: verify test - +.PHONY: test test: go test -race -coverprofile=profile.cov ./... -# The build targets allow to build the binary and docker image -.PHONY: build build.docker build.mini +# The build targets allow to build the binary and container image +.PHONY: build BINARY ?= external-dns SOURCES = $(shell find . -name '*.go') -IMAGE_STAGING = gcr.io/k8s-staging-external-dns/$(BINARY) -IMAGE ?= us.gcr.io/k8s-artifacts-prod/external-dns/$(BINARY) +REGISTRY ?= us.gcr.io/k8s-artifacts-prod/external-dns +IMAGE ?= $(REGISTRY)/$(BINARY) VERSION ?= $(shell git describe --tags --always --dirty --match "v*") BUILD_FLAGS ?= -v LDFLAGS ?= -X sigs.k8s.io/external-dns/pkg/apis/externaldns.Version=$(VERSION) -w -s -ARCHS = amd64 arm64 arm/v7 ARCH ?= amd64 -DEFAULT_ARCH = amd64 SHELL = /bin/bash -OUTPUT_TYPE ?= docker - +IMG_PLATFORM ?= linux/amd64,linux/arm64,linux/arm/v7 +IMG_PUSH ?= true +IMG_SBOM ?= none build: build/$(BINARY) build/$(BINARY): $(SOURCES) CGO_ENABLED=0 go build -o build/$(BINARY) $(BUILD_FLAGS) -ldflags "$(LDFLAGS)" . -build.push/multiarch: $(addprefix build.push-,$(ARCHS)) - arch_specific_tags=() - for arch in $(ARCHS); do \ - image="$(IMAGE):$(VERSION)-$$(echo $$arch | tr / -)" ;\ - arch_specific_tags+=( " $${image}" ) ;\ - done ;\ - echo $${arch_specific_tags[@]} ;\ - DOCKER_CLI_EXPERIMENTAL=enabled docker buildx imagetools create --tag "$(IMAGE):$(VERSION)" $${arch_specific_tags[@]} ;\ +build.push/multiarch: ko + KO_DOCKER_REPO=${IMAGE} \ + VERSION=${VERSION} \ + ko build --tags ${VERSION} --platform=${IMG_PLATFORM} --bare --sbom ${IMG_SBOM} --push=${IMG_PUSH} . -build.image/multiarch: $(addprefix build.image-,$(ARCHS)) +build.image/multiarch: + $(MAKE) IMG_PUSH=false build.push/multiarch build.image: - $(MAKE) ARCH=$(ARCH) OUTPUT_TYPE=docker build.docker + $(MAKE) IMG_PLATFORM=linux/$(ARCH) build.image/multiarch build.image-amd64: $(MAKE) ARCH=amd64 build.image @@ -129,7 +120,7 @@ build.image-arm/v7: $(MAKE) ARCH=arm/v7 build.image build.push: - $(MAKE) ARCH=$(ARCH) OUTPUT_TYPE=registry build.docker + $(MAKE) IMG_PLATFORM=linux/$(ARCH) build.push/multiarch build.push-amd64: $(MAKE) ARCH=amd64 build.push @@ -149,25 +140,6 @@ build.amd64: build.arm/v7: CGO_ENABLED=0 GOOS=linux GOARCH=arm GOARM=7 go build -o build/$(BINARY) $(BUILD_FLAGS) -ldflags "$(LDFLAGS)" . -build.setup: - docker buildx inspect img-builder > /dev/null || docker buildx create --name img-builder --use - -build.docker: build.setup build.$(ARCH) - docker build --rm --tag "$(IMAGE):$(VERSION)" --build-arg VERSION="$(VERSION)" --build-arg ARCH="$(ARCH)" . - image="$(IMAGE):$(VERSION)-$(subst /,-,$(ARCH))"; \ - docker buildx build \ - --pull \ - --provenance=false \ - --sbom=false \ - --output=type=$(OUTPUT_TYPE) \ - --platform linux/$(ARCH) \ - --build-arg ARCH="$(ARCH)" \ - --build-arg VERSION="$(VERSION)" \ - --tag $${image} . - -build.mini: - docker build --rm --tag "$(IMAGE):$(VERSION)-mini" --build-arg VERSION="$(VERSION)" -f Dockerfile.mini . - clean: @rm -rf build @go clean -cache @@ -176,7 +148,12 @@ clean: .PHONY: release.staging release.staging: test + @echo "Perhaps use ${IMAGE} instead of ${IMAGE_STAGING} ?" IMAGE=$(IMAGE_STAGING) $(MAKE) build.push/multiarch release.prod: test $(MAKE) build.push/multiarch + +.PHONY: ko +ko: + scripts/install-ko.sh diff --git a/cloudbuild.yaml b/cloudbuild.yaml index 8d2f519432..af82a21b19 100644 --- a/cloudbuild.yaml +++ b/cloudbuild.yaml @@ -4,20 +4,14 @@ options: substitution_option: ALLOW_LOOSE machineType: 'N1_HIGHCPU_8' steps: - - name: "gcr.io/k8s-staging-test-infra/gcb-docker-gcloud:v20230206-8160eea68e" - entrypoint: bash + - name: 'docker.io/library/golang:1.20.6-bullseye' + entrypoint: make env: - - DOCKER_CLI_EXPERIMENTAL=enabled - VERSION=$_GIT_TAG - PULL_BASE_REF=$_PULL_BASE_REF - - HOME=/root + - REGISTRY=$_DOCKER_REGISTRY args: - - -c - - | - gcloud auth configure-docker - /buildx-entrypoint version - apk add musl-dev gcc - make release.staging + - release.staging substitutions: # _GIT_TAG will be filled with a git-based tag for the image, of the form vYYYYMMDD-hash, and # can be used as a substitution diff --git a/docs/contributing/getting-started.md b/docs/contributing/getting-started.md index 7cf42ca09f..0d82cca54d 100644 --- a/docs/contributing/getting-started.md +++ b/docs/contributing/getting-started.md @@ -4,7 +4,7 @@ - [Go 1.20+](https://golang.org/dl/) - [Go modules](https://github.com/golang/go/wiki/Modules) - [golangci-lint](https://github.com/golangci/golangci-lint) -- [Docker](https://docs.docker.com/install/) +- [ko](https://ko.build/) - [kubectl](https://kubernetes.io/docs/tasks/tools/install-kubectl) Compile and run locally against a remote k8s cluster. @@ -24,7 +24,7 @@ make cover-html Build container image. ```shell -make build.docker +make build.push IMAGE=your-registry/external-dns ``` # Design diff --git a/docs/faq.md b/docs/faq.md index 6da020c5d8..4463ffd2df 100644 --- a/docs/faq.md +++ b/docs/faq.md @@ -317,7 +317,7 @@ registry.k8s.io/external-dns/external-dns As tags, you use the external-dns release of choice(i.e. `v0.7.6`). A `latest` tag is not provided in the container registry. -If you wish to build your own image, you can use the provided [Dockerfile](../Dockerfile) as a starting point. +If you wish to build your own image, you can use the provided [.ko.yaml](../.ko.yaml) as a starting point. ### Which architectures are supported? diff --git a/scripts/install-ko.sh b/scripts/install-ko.sh new file mode 100755 index 0000000000..47307f4d42 --- /dev/null +++ b/scripts/install-ko.sh @@ -0,0 +1,24 @@ +#!/usr/bin/env bash + +# Copyright 2022 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. + +set -o errexit +set -o nounset +set -o pipefail + +if ! command -v ko &> /dev/null; then + cd "$(dirname "${BASH_SOURCE[0]}")" || exit 1 + go install github.com/google/ko@v0.14.1 +fi diff --git a/scripts/run-trivy.sh b/scripts/run-trivy.sh deleted file mode 100755 index 07b7aa2b86..0000000000 --- a/scripts/run-trivy.sh +++ /dev/null @@ -1,13 +0,0 @@ -#! /bin/bash -set -e - -# install trivy -cd /tmp -curl -LO https://github.com/aquasecurity/trivy/releases/download/v0.20.2/trivy_0.20.2_Linux-64bit.tar.gz -echo "38a6de48e21a34e0fa0d2cf63439c0afcbbae0e78fb3feada7a84a9cf6e7f60c trivy_0.20.2_Linux-64bit.tar.gz" | sha256sum -c -tar -xvf trivy_0.20.2_Linux-64bit.tar.gz -chmod +x trivy - -# run trivy -cd - -/tmp/trivy image --exit-code 1 us.gcr.io/k8s-artifacts-prod/external-dns/external-dns:$(git describe --tags --always --dirty --match "v*")