Files
kind/images/base/Dockerfile
Benjamin Elder 3652d39e04 force GOTOOLCHAIN="go${GO_VERSION}" for now
TODO: look at using deprecating .go-version in favor of GOTOOLCHAIN existing knobs
2024-04-01 15:52:31 -07:00

245 lines
11 KiB
Docker

# Copyright 2018 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.
# kind node base image
#
# For systemd + docker configuration used below, see the following references:
# https://systemd.io/CONTAINER_INTERFACE/
# start from debian slim, this image is reasonably small as a starting point
# for a kubernetes node image, it doesn't contain much (anything?) we don't need
# this stage will install basic files and packages
ARG BASE_IMAGE=debian:bookworm-slim
FROM $BASE_IMAGE as base
# copy in static files
# all scripts and directories are 0755 (rwx r-x r-x)
# all non-scripts are 0644 (rw- r-- r--)
COPY --chmod=0755 files/usr/local/bin/* /usr/local/bin/
COPY --chmod=0644 files/kind/ /kind/
# COPY only applies to files, not the directory itself, so the permissions are
# fixed in RUN below with a chmod.
COPY --chmod=0755 files/kind/bin/ /kind/bin/
COPY --chmod=0644 files/LICENSES/* /LICENSES/*
COPY --chmod=0644 files/etc/* /etc/
COPY --chmod=0644 files/etc/containerd/* /etc/containerd/
COPY --chmod=0644 files/etc/default/* /etc/default/
COPY --chmod=0644 files/etc/sysctl.d/* /etc/sysctl.d/
COPY --chmod=0644 files/etc/systemd/system/* /etc/systemd/system/
COPY --chmod=0644 files/etc/systemd/system/kubelet.service.d/* /etc/systemd/system/kubelet.service.d/
# Install dependencies, first from apt, then from release tarballs.
# NOTE: we use one RUN to minimize layers.
#
# The base image already has a basic userspace + apt but we need to install more packages.
# Packages installed are broken down into (each on a line):
# - packages needed to run services (systemd)
# - packages needed for kubernetes components
# - packages needed for networked backed storage with kubernetes
# - packages needed by the container runtime
# - misc packages kind uses itself
# - packages that provide semi-core kubernetes functionality
# After installing packages we cleanup by:
# - removing unwanted systemd services
# - disabling kmsg in journald (these log entries would be confusing)
#
# Then we install containerd from our nightly build infrastructure, as this
# build for multiple architectures and allows us to upgrade to patched releases
# more quickly.
#
# Next we download and extract crictl and CNI plugin binaries from upstream.
#
# Next we ensure the /etc/kubernetes/manifests directory exists. Normally
# a kubeadm debian / rpm package would ensure that this exists but we install
# freshly built binaries directly when we build the node image.
#
# Finally we adjust tempfiles cleanup to be 1 minute after "boot" instead of 15m
# This is plenty after we've done initial setup for a node, but before we are
# likely to try to export logs etc.
RUN chmod 755 /kind/bin && \
echo "Installing Packages ..." \
&& DEBIAN_FRONTEND=noninteractive clean-install \
systemd \
conntrack iptables nftables iproute2 ethtool util-linux mount kmod \
libseccomp2 pigz fuse-overlayfs \
nfs-common open-iscsi \
bash ca-certificates curl jq procps \
&& find /lib/systemd/system/sysinit.target.wants/ -name "systemd-tmpfiles-setup.service" -delete \
&& rm -f /lib/systemd/system/multi-user.target.wants/* \
&& rm -f /etc/systemd/system/*.wants/* \
&& rm -f /lib/systemd/system/local-fs.target.wants/* \
&& rm -f /lib/systemd/system/sockets.target.wants/*udev* \
&& rm -f /lib/systemd/system/sockets.target.wants/*initctl* \
&& rm -f /lib/systemd/system/basic.target.wants/* \
&& echo "ReadKMsg=no" >> /etc/systemd/journald.conf \
&& ln -s "$(which systemd)" /sbin/init
# NOTE: systemd-binfmt.service will register things into binfmt_misc which is kernel-global
RUN echo "Enabling / Disabling services ... " \
&& systemctl enable kubelet.service \
&& systemctl enable containerd.service \
&& systemctl enable undo-mount-hacks.service \
&& systemctl mask systemd-binfmt.service
RUN echo "Ensuring /etc/kubernetes/manifests" \
&& mkdir -p /etc/kubernetes/manifests
# shared stage to setup go version for building binaries
# NOTE we will be cross-compiling for performance reasons
# This is also why we start again FROM the same base image but a different
# platform and only the files needed for building
# We will copy the built binaries from later stages to the final stage(s)
FROM --platform=$BUILDPLATFORM $BASE_IMAGE as go-build
COPY --chmod=0755 files/usr/local/bin/* /usr/local/bin/
COPY --chmod=0755 scripts/third_party/gimme/gimme /usr/local/bin/
COPY --chmod=0755 scripts/target-cc /usr/local/bin/
# tools needed at build-time only
# first ensure we can install packages for both architectures
RUN dpkg --add-architecture arm64 && dpkg --add-architecture amd64 \
&& clean-install bash ca-certificates curl git make pkg-config \
crossbuild-essential-amd64 crossbuild-essential-arm64 \
libseccomp-dev:amd64 libseccomp-dev:arm64
# set by makefile to .go-version
ARG GO_VERSION
RUN eval "$(gimme "${GO_VERSION}")" \
&& export GOTOOLCHAIN="go${GO_VERSION}" \
&& GOBIN=/usr/local/bin go install github.com/google/go-licenses@latest
# stage for building containerd
FROM go-build as build-containerd
ARG TARGETARCH GO_VERSION
ARG CONTAINERD_VERSION="v1.7.14"
ARG CONTAINERD_CLONE_URL="https://github.com/containerd/containerd"
# we don't build with optional snapshotters, we never select any of these
# they're not ideal inside kind anyhow, and we save some disk space
ARG BUILDTAGS="no_aufs no_zfs no_btrfs no_devmapper"
RUN git clone --filter=tree:0 "${CONTAINERD_CLONE_URL}" /containerd \
&& cd /containerd \
&& git checkout "${CONTAINERD_VERSION}" \
&& eval "$(gimme "${GO_VERSION}")" \
&& export GOTOOLCHAIN="go${GO_VERSION}" \
&& export GOARCH=$TARGETARCH && export CC=$(target-cc) && export CGO_ENABLED=1 \
&& make bin/ctr bin/containerd bin/containerd-shim-runc-v2 \
&& GOARCH=$TARGETARCH go-licenses save --save_path=/_LICENSES \
./cmd/ctr ./cmd/containerd ./cmd/containerd-shim-runc-v2
# stage for building runc
FROM go-build as build-runc
ARG TARGETARCH GO_VERSION
ARG RUNC_VERSION="v1.1.12"
ARG RUNC_CLONE_URL="https://github.com/opencontainers/runc"
RUN git clone --filter=tree:0 "${RUNC_CLONE_URL}" /runc \
&& cd /runc \
&& git checkout "${RUNC_VERSION}" \
&& eval "$(gimme "${GO_VERSION}")" \
&& export GOTOOLCHAIN="go${GO_VERSION}" \
&& export GOARCH=$TARGETARCH && export CC=$(target-cc) && export CGO_ENABLED=1 \
&& make runc \
&& GOARCH=$TARGETARCH go-licenses save --save_path=/_LICENSES .
# stage for building crictl
FROM go-build as build-crictl
ARG TARGETARCH GO_VERSION
ARG CRI_TOOLS_CLONE_URL="https://github.com/kubernetes-sigs/cri-tools"
ARG CRICTL_VERSION="v1.29.0"
RUN git clone --filter=tree:0 "${CRI_TOOLS_CLONE_URL}" /cri-tools \
&& cd /cri-tools \
&& git checkout "${CRICTL_VERSION}" \
&& eval "$(gimme "${GO_VERSION}")" \
&& export GOARCH=$TARGETARCH && export CC=$(target-cc) && export CGO_ENABLED=1 \
&& make BUILD_BIN_PATH=./build crictl \
&& GOARCH=$TARGETARCH go-licenses save --save_path=/_LICENSES ./cmd/crictl
# stage for building cni-plugins
FROM go-build as build-cni
ARG TARGETARCH GO_VERSION
ARG CNI_PLUGINS_VERSION="v1.4.1"
ARG CNI_PLUGINS_CLONE_URL="https://github.com/containernetworking/plugins"
RUN git clone --filter=tree:0 "${CNI_PLUGINS_CLONE_URL}" /cni-plugins \
&& cd /cni-plugins \
&& git checkout "${CNI_PLUGINS_VERSION}" \
&& eval "$(gimme "${GO_VERSION}")" \
&& export GOTOOLCHAIN="go${GO_VERSION}" \
&& mkdir ./bin \
&& export GOARCH=$TARGETARCH && export CC=$(target-cc) && export CGO_ENABLED=1 \
&& go build -o ./bin/host-local -mod=vendor ./plugins/ipam/host-local \
&& go build -o ./bin/loopback -mod=vendor ./plugins/main/loopback \
&& go build -o ./bin/ptp -mod=vendor ./plugins/main/ptp \
&& go build -o ./bin/portmap -mod=vendor ./plugins/meta/portmap \
&& GOARCH=$TARGETARCH go-licenses save --save_path=/_LICENSES \
./plugins/ipam/host-local \
./plugins/main/loopback ./plugins/main/ptp \
./plugins/meta/portmap
# stage for building containerd-fuse-overlayfs
FROM go-build as build-fuse-overlayfs
ARG TARGETARCH GO_VERSION
ARG CONTAINERD_FUSE_OVERLAYFS_VERSION="v1.0.8"
ARG CONTAINERD_FUSE_OVERLAYFS_CLONE_URL="https://github.com/containerd/fuse-overlayfs-snapshotter"
RUN git clone --filter=tree:0 "${CONTAINERD_FUSE_OVERLAYFS_CLONE_URL}" /fuse-overlayfs-snapshotter \
&& cd /fuse-overlayfs-snapshotter \
&& git checkout "${CONTAINERD_FUSE_OVERLAYFS_VERSION}" \
&& eval "$(gimme "${GO_VERSION}")" \
&& export GOTOOLCHAIN="go${GO_VERSION}" \
&& export GOARCH=$TARGETARCH && export CC=$(target-cc) && export CGO_ENABLED=1 \
&& make bin/containerd-fuse-overlayfs-grpc \
&& GOARCH=$TARGETARCH go-licenses save --save_path=/_LICENSES ./cmd/containerd-fuse-overlayfs-grpc
# build final image layout from other stages
FROM base as build
# copy over containerd build and install
COPY --from=build-containerd /containerd/bin/containerd /usr/local/bin/
COPY --from=build-containerd /containerd/bin/ctr /usr/local/bin/
COPY --from=build-containerd /containerd/bin/containerd-shim-runc-v2 /usr/local/bin/
RUN ctr oci spec \
| jq '.hooks.createContainer[.hooks.createContainer| length] |= . + {"path": "/kind/bin/mount-product-files.sh"}' \
| jq 'del(.process.rlimits)' \
> /etc/containerd/cri-base.json \
&& containerd --version
COPY --from=build-containerd /_LICENSES/* /LICENSES/
# copy over runc build and install
COPY --from=build-runc /runc/runc /usr/local/sbin/runc
RUN runc --version
COPY --from=build-runc /_LICENSES/* /LICENSES/
# copy over crictl build and install
COPY --from=build-crictl /cri-tools/build/crictl /usr/local/bin/
COPY --from=build-crictl /_LICENSES/* /LICENSES/
# copy over CNI plugins build and install
RUN mkdir -p /opt/cni/bin
COPY --from=build-cni /cni-plugins/bin/host-local /opt/cni/bin/
COPY --from=build-cni /cni-plugins/bin/loopback /opt/cni/bin/
COPY --from=build-cni /cni-plugins/bin/ptp /opt/cni/bin/
COPY --from=build-cni /cni-plugins/bin/portmap /opt/cni/bin/
COPY --from=build-cni /_LICENSES/* /LICENSES/
# copy over containerd-fuse-overlayfs and install
COPY --from=build-fuse-overlayfs /fuse-overlayfs-snapshotter/bin/containerd-fuse-overlayfs-grpc /usr/local/bin/
COPY --from=build-fuse-overlayfs /_LICENSES/* /LICENSES/
# squash down to one compressed layer, without any lingering whiteout files etc
FROM scratch
COPY --from=build / /
# add metadata, must be done after the squashing
# first tell systemd that it is in docker (it will check for the container env)
# https://systemd.io/CONTAINER_INTERFACE/
ENV container docker
# systemd exits on SIGRTMIN+3, not SIGTERM (which re-executes it)
# https://bugzilla.redhat.com/show_bug.cgi?id=1201657
STOPSIGNAL SIGRTMIN+3
# NOTE: this is *only* for documentation, the entrypoint is overridden later
ENTRYPOINT [ "/usr/local/bin/entrypoint", "/sbin/init" ]