Fork all files needed for kindbase from upstream

This is for reference, to be able to combine them
pull/9330/head
Anders F Björklund 2020-09-12 12:34:51 +02:00
parent 9056687844
commit 85f8d05757
8 changed files with 441 additions and 2 deletions

View File

@ -20,6 +20,7 @@ RAW_VERSION=$(VERSION_MAJOR).$(VERSION_MINOR).$(VERSION_BUILD)
VERSION ?= v$(RAW_VERSION)
KUBERNETES_VERSION ?= $(shell egrep "DefaultKubernetesVersion =" pkg/minikube/constants/constants.go | cut -d \" -f2)
KIND_VERSION ?= v20200430-2c0eee40
KIC_VERSION ?= $(shell egrep "Version =" pkg/drivers/kic/types.go | cut -d \" -f2)
# Default to .0 for higher cache hit rates, as build increments typically don't require new ISO versions
@ -47,6 +48,7 @@ BUILD_IMAGE ?= us.gcr.io/k8s-artifacts-prod/build-image/kube-cross:v$(GO_VERSIO
ISO_BUILD_IMAGE ?= $(REGISTRY)/buildroot-image
KVM_BUILD_IMAGE ?= $(REGISTRY)/kvm-build-image:$(GO_VERSION)
KIND_BASE_IMAGE_GCR ?= $(REGISTRY)/kindbase:$(KIND_VERSION)
KIC_BASE_IMAGE_GCR ?= $(REGISTRY)/kicbase:$(KIC_VERSION)
KIC_BASE_IMAGE_GH ?= $(REGISTRY_GH)/kicbase:$(KIC_VERSION)
KIC_BASE_IMAGE_HUB ?= kicbase/stable:$(KIC_VERSION)
@ -576,8 +578,15 @@ endif
storage-provisioner-image: out/storage-provisioner-$(GOARCH) ## Build storage-provisioner docker image
docker build -t $(STORAGE_PROVISIONER_IMAGE) -f deploy/storage-provisioner/Dockerfile --build-arg arch=$(GOARCH) .
.PHONY: kind-base-image
kind-base-image: ## builds the base image used for kind.
docker rmi -f $(KIND_BASE_IMAGE_GCR)-snapshot || true
docker build -f ./deploy/kindbase/Dockerfile -t local/kindbase:$(KIND_VERSION)-snapshot ./deploy/kindbase
docker tag local/kindbase:$(KIND_VERSION)-snapshot $(KIND_BASE_IMAGE_GCR)-snapshot
docker tag local/kindbase:$(KIND_VERSION)-snapshot $(KIND_BASE_IMAGE_GCR)
.PHONY: kic-base-image
kic-base-image: ## builds the base image used for kic.
kic-base-image: kind-base-image ## builds the base image used for kic.
docker rmi -f $(KIC_BASE_IMAGE_GCR)-snapshot || true
docker build -f ./deploy/kicbase/Dockerfile -t local/kicbase:$(KIC_VERSION)-snapshot --build-arg COMMIT_SHA=${VERSION}-$(COMMIT) --cache-from $(KIC_BASE_IMAGE_GCR) --target base ./deploy/kicbase
docker tag local/kicbase:$(KIC_VERSION)-snapshot $(KIC_BASE_IMAGE_GCR)-snapshot

View File

@ -2,7 +2,7 @@ ARG COMMIT_SHA
# using base image created by kind https://github.com/kubernetes-sigs/kind/blob/v0.8.1/images/base/Dockerfile
# which is an ubuntu 20.04 with an entry-point that helps running systemd
# could be changed to any debian that can run systemd
FROM kindest/base:v20200430-2c0eee40 as base
FROM gcr.io/k8s-minikube/kindbase:v20200430-2c0eee40 as base
USER root
# remove files that were installed by kind, replaced by packages

122
deploy/kindbase/Dockerfile Normal file
View File

@ -0,0 +1,122 @@
# 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://www.freedesktop.org/wiki/Software/systemd/ContainerInterface/
# start from ubuntu 19.10, this image is reasonably small as a starting point
# for a kubernetes node image, it doesn't contain much we don't need
FROM ubuntu:20.04
# Configure containerd and runc binaries from kind-ci/containerd-nightlies repository
# The repository contains latest stable releases and nightlies built for multiple architectures
ARG CONTAINERD_VERSION="v1.3.3-14-g449e9269"
# Configure CNI binaries from upstream
ARG CNI_VERSION="v0.8.5"
# Configure crictl binary from upstream
ARG CRICTL_VERSION="v1.18.0"
# copy in static files (configs, scripts)
COPY files/ /
# Install dependencies, first from apt, then from release tarballs.
# NOTE: we use one RUN to minimize layers.
#
# First we must ensure that our util scripts are executable.
#
# The base image already has: ssh, apt, snapd, 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 by the container runtime
# - misc packages kind uses itself
# 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 debain / 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 echo "Ensuring scripts are executable ..." \
&& chmod +x /usr/local/bin/clean-install /usr/local/bin/entrypoint \
&& echo "Installing Packages ..." \
&& DEBIAN_FRONTEND=noninteractive clean-install \
systemd \
conntrack iptables iproute2 ethtool socat util-linux mount ebtables udev kmod \
libseccomp2 \
bash ca-certificates curl rsync \
&& 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 \
&& echo "Installing containerd ..." \
&& export ARCH=$(dpkg --print-architecture | sed 's/ppc64el/ppc64le/' | sed 's/armhf/arm/') \
&& export CONTAINERD_BASE_URL="https://github.com/kind-ci/containerd-nightlies/releases/download/containerd-${CONTAINERD_VERSION#v}" \
&& curl -sSL --retry 5 --output /tmp/containerd.tgz "${CONTAINERD_BASE_URL}/containerd-${CONTAINERD_VERSION#v}.linux-${ARCH}.tar.gz" \
&& tar -C /usr/local -xzvf /tmp/containerd.tgz \
&& rm -rf /tmp/containerd.tgz \
&& rm -f /usr/local/bin/containerd-stress /usr/local/bin/containerd-shim-runc-v1 \
&& curl -sSL --retry 5 --output /usr/local/sbin/runc "${CONTAINERD_BASE_URL}/runc.${ARCH}" \
&& chmod 755 /usr/local/sbin/runc \
&& containerd --version \
&& systemctl enable containerd \
&& echo "Installing crictl ..." \
&& curl -fSL "https://github.com/kubernetes-sigs/cri-tools/releases/download/${CRICTL_VERSION}/crictl-${CRICTL_VERSION}-linux-${ARCH}.tar.gz" | tar xzC /usr/local/bin \
&& echo "Installing CNI binaries ..." \
&& export ARCH=$(dpkg --print-architecture | sed 's/ppc64el/ppc64le/' | sed 's/armhf/arm/') \
&& export CNI_TARBALL="${CNI_VERSION}/cni-plugins-linux-${ARCH}-${CNI_VERSION}.tgz" \
&& export CNI_URL="https://github.com/containernetworking/plugins/releases/download/${CNI_TARBALL}" \
&& curl -sSL --retry 5 --output /tmp/cni.tgz "${CNI_URL}" \
&& mkdir -p /opt/cni/bin \
&& tar -C /opt/cni/bin -xzf /tmp/cni.tgz \
&& rm -rf /tmp/cni.tgz \
&& find /opt/cni/bin -type f -not \( \
-iname host-local \
-o -iname ptp \
-o -iname portmap \
-o -iname loopback \
\) \
-delete \
&& echo "Ensuring /etc/kubernetes/manifests" \
&& mkdir -p /etc/kubernetes/manifests \
&& echo "Adjusting systemd-tmpfiles timer" \
&& sed -i /usr/lib/systemd/system/systemd-tmpfiles-clean.timer -e 's#OnBootSec=.*#OnBootSec=1min#' \
&& echo "Modifying /etc/nsswitch.conf to prefer hosts" \
&& sed -i /etc/nsswitch.conf -re 's#^(hosts:\s*).*#\1dns files#'
# tell systemd that it is in docker (it will check for the container env)
# https://www.freedesktop.org/wiki/Software/systemd/ContainerInterface/
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" ]

View File

@ -0,0 +1 @@
runtime-endpoint: unix:///var/run/containerd/containerd.sock

View File

@ -0,0 +1,4 @@
# Turn on Source Address Verification in all interfaces to
# prevent some spoofing attacks.
net.ipv4.conf.default.rp_filter=1
net.ipv4.conf.all.rp_filter=1

View File

@ -0,0 +1,29 @@
# derived containerd systemd service file from the official:
# https://github.com/containerd/containerd/blob/master/containerd.service
[Unit]
Description=containerd container runtime
Documentation=https://containerd.io
After=network.target
# disable rate limiting
StartLimitIntervalSec=0
[Service]
ExecStartPre=-/sbin/modprobe overlay
ExecStart=/usr/local/bin/containerd
Restart=always
RestartSec=1
Delegate=yes
KillMode=process
Restart=always
# Having non-zero Limit*s causes performance problems due to accounting overhead
# in the kernel. We recommend using cgroups to do container-local accounting.
LimitNPROC=infinity
LimitCORE=infinity
LimitNOFILE=1048576
# Comment TasksMax if your systemd version does not supports it.
# Only systemd 226 and above support this version.
TasksMax=infinity
[Install]
WantedBy=multi-user.target

View File

@ -0,0 +1,39 @@
#!/bin/sh
# 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.
# A script encapsulating a common Dockerimage pattern for installing packages
# and then cleaning up the unnecessary install artifacts.
# e.g. clean-install iptables ebtables conntrack
set -o errexit
if [ $# = 0 ]; then
echo >&2 "No packages specified"
exit 1
fi
apt-get update
apt-get install -y --no-install-recommends "$@"
apt-get clean -y
rm -rf \
/var/cache/debconf/* \
/var/lib/apt/lists/* \
/var/log/* \
/tmp/* \
/var/tmp/* \
/usr/share/doc/* \
/usr/share/man/* \
/usr/share/local/*

View File

@ -0,0 +1,235 @@
#!/bin/bash
# Copyright 2019 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
fix_mount() {
echo 'INFO: ensuring we can execute /bin/mount even with userns-remap'
# necessary only when userns-remap is enabled on the host, but harmless
# The binary /bin/mount should be owned by root and have the setuid bit
chown root:root /bin/mount
chmod -s /bin/mount
# This is a workaround to an AUFS bug that might cause `Text file
# busy` on `mount` command below. See more details in
# https://github.com/moby/moby/issues/9547
if [[ "$(stat -f -c %T /bin/mount)" == 'aufs' ]]; then
echo 'INFO: detected aufs, calling sync' >&2
sync
fi
echo 'INFO: remounting /sys read-only'
# systemd-in-a-container should have read only /sys
# https://www.freedesktop.org/wiki/Software/systemd/ContainerInterface/
# however, we need other things from `docker run --privileged` ...
# and this flag also happens to make /sys rw, amongst other things
mount -o remount,ro /sys
echo 'INFO: making mounts shared' >&2
# for mount propagation
mount --make-rshared /
}
fix_cgroup() {
echo 'INFO: fix cgroup mounts for all subsystems'
# For each cgroup subsystem, Docker does a bind mount from the current
# cgroup to the root of the cgroup subsystem. For instance:
# /sys/fs/cgroup/memory/docker/<cid> -> /sys/fs/cgroup/memory
#
# This will confuse Kubelet and cadvisor and will dump the following error
# messages in kubelet log:
# `summary_sys_containers.go:47] Failed to get system container stats for ".../kubelet.service"`
#
# This is because `/proc/<pid>/cgroup` is not affected by the bind mount.
# The following is a workaround to recreate the original cgroup
# environment by doing another bind mount for each subsystem.
local docker_cgroup_mounts
docker_cgroup_mounts=$(grep /sys/fs/cgroup /proc/self/mountinfo | grep docker || true)
if [[ -n "${docker_cgroup_mounts}" ]]; then
local docker_cgroup cgroup_subsystems subsystem
docker_cgroup=$(echo "${docker_cgroup_mounts}" | head -n 1 | cut -d' ' -f 4)
cgroup_subsystems=$(echo "${docker_cgroup_mounts}" | cut -d' ' -f 5)
echo "${cgroup_subsystems}" |
while IFS= read -r subsystem; do
mkdir -p "${subsystem}${docker_cgroup}"
mount --bind "${subsystem}" "${subsystem}${docker_cgroup}"
done
fi
}
fix_machine_id() {
# Deletes the machine-id embedded in the node image and generates a new one.
# This is necessary because both kubelet and other components like weave net
# use machine-id internally to distinguish nodes.
echo 'INFO: clearing and regenerating /etc/machine-id' >&2
rm -f /etc/machine-id
systemd-machine-id-setup
}
fix_product_name() {
# this is a small fix to hide the underlying hardware and fix issue #426
# https://github.com/kubernetes-sigs/kind/issues/426
if [[ -f /sys/class/dmi/id/product_name ]]; then
echo 'INFO: faking /sys/class/dmi/id/product_name to be "kind"' >&2
echo 'kind' > /kind/product_name
mount -o ro,bind /kind/product_name /sys/class/dmi/id/product_name
fi
}
fix_product_uuid() {
# The system UUID is usually read from DMI via sysfs, the problem is that
# in the kind case this means that all (container) nodes share the same
# system/product uuid, as they share the same DMI.
# Note: The UUID is read from DMI, this tool is overwriting the sysfs files
# which should fix the attached issue, but this workaround does not address
# the issue if a tool is reading directly from DMI.
# https://github.com/kubernetes-sigs/kind/issues/1027
[[ ! -f /kind/product_uuid ]] && cat /proc/sys/kernel/random/uuid > /kind/product_uuid
if [[ -f /sys/class/dmi/id/product_uuid ]]; then
echo 'INFO: faking /sys/class/dmi/id/product_uuid to be random' >&2
mount -o ro,bind /kind/product_uuid /sys/class/dmi/id/product_uuid
fi
if [[ -f /sys/devices/virtual/dmi/id/product_uuid ]]; then
echo 'INFO: faking /sys/devices/virtual/dmi/id/product_uuid as well' >&2
mount -o ro,bind /kind/product_uuid /sys/devices/virtual/dmi/id/product_uuid
fi
}
fix_kmsg() {
# In environments where /dev/kmsg is not available, the kubelet (1.15+) won't
# start because it cannot open /dev/kmsg when starting the kmsgparser in the
# OOM parser.
# To support those environments, we link /dev/kmsg to /dev/console.
# https://github.com/kubernetes-sigs/kind/issues/662
if [[ ! -e /dev/kmsg ]]; then
if [[ -e /dev/console ]]; then
echo 'WARN: /dev/kmsg does not exist, symlinking /dev/console' >&2
ln -s /dev/console /dev/kmsg
else
echo 'WARN: /dev/kmsg does not exist, nor does /dev/console!' >&2
fi
fi
}
configure_proxy() {
# ensure all processes receive the proxy settings by default
# https://www.freedesktop.org/software/systemd/man/systemd-system.conf.html
mkdir -p /etc/systemd/system.conf.d/
cat <<EOF >/etc/systemd/system.conf.d/proxy-default-environment.conf
[Manager]
DefaultEnvironment="HTTP_PROXY=${HTTP_PROXY:-}" "HTTPS_PROXY=${HTTPS_PROXY:-}" "NO_PROXY=${NO_PROXY:-}"
EOF
}
select_iptables() {
# based on: https://github.com/kubernetes/kubernetes/blob/ffe93b3979486feb41a0f85191bdd189cbd56ccc/build/debian-iptables/iptables-wrapper
local mode=nft
num_legacy_lines=$( (iptables-legacy-save || true; ip6tables-legacy-save || true) 2>/dev/null | grep '^-' | wc -l || true)
if [ "${num_legacy_lines}" -ge 10 ]; then
mode=legacy
else
num_nft_lines=$( (timeout 5 sh -c "iptables-nft-save; ip6tables-nft-save" || true) 2>/dev/null | grep '^-' | wc -l || true)
if [ "${num_legacy_lines}" -ge "${num_nft_lines}" ]; then
mode=legacy
fi
fi
echo "INFO: setting iptables to detected mode: ${mode}" >&2
update-alternatives --set iptables "/usr/sbin/iptables-${mode}" > /dev/null
update-alternatives --set ip6tables "/usr/sbin/ip6tables-${mode}" > /dev/null
}
enable_network_magic(){
# well-known docker embedded DNS is at 127.0.0.11:53
local docker_embedded_dns_ip='127.0.0.11'
# first we need to detect an IP to use for reaching the docker host
local docker_host_ip
docker_host_ip="$( (getent ahostsv4 'host.docker.internal' | head -n1 | cut -d' ' -f1) || true)"
if [[ -z "${docker_host_ip}" ]]; then
docker_host_ip=$(ip -4 route show default | cut -d' ' -f3)
fi
# patch docker's iptables rules to switch out the DNS IP
iptables-save \
| sed \
`# switch docker DNS DNAT rules to our chosen IP` \
-e "s/-d ${docker_embedded_dns_ip}/-d ${docker_host_ip}/g" \
`# we need to also apply these rules to non-local traffic (from pods)` \
-e 's/-A OUTPUT \(.*\) -j DOCKER_OUTPUT/\0\n-A PREROUTING \1 -j DOCKER_OUTPUT/' \
`# switch docker DNS SNAT rules rules to our chosen IP` \
-e "s/--to-source :53/--to-source ${docker_host_ip}:53/g"\
| iptables-restore
# now we can ensure that DNS is configured to use our IP
cp /etc/resolv.conf /etc/resolv.conf.original
sed -e "s/${docker_embedded_dns_ip}/${docker_host_ip}/g" /etc/resolv.conf.original >/etc/resolv.conf
# fixup IPs in manifests ...
curr_ipv4="$( (getent ahostsv4 $(hostname) | head -n1 | cut -d' ' -f1) || true)"
echo "INFO: Detected IPv4 address: ${curr_ipv4}" >&2
if [ -f /kind/old-ipv4 ]; then
old_ipv4=$(cat /kind/old-ipv4)
echo "INFO: Detected old IPv4 address: ${old_ipv4}" >&2
# sanity check that we have a current address
if [[ -z $curr_ipv4 ]]; then
echo "ERROR: Have an old IPv4 address but no current IPv4 address (!)" >&2
exit 1
fi
# kubernetes manifests are only present on control-plane nodes
sed -i "s#${old_ipv4}#${curr_ipv4}#" /etc/kubernetes/manifests/*.yaml || true
# this is no longer required with autodiscovery
sed -i "s#${old_ipv4}#${curr_ipv4}#" /var/lib/kubelet/kubeadm-flags.env || true
fi
if [[ -n $curr_ipv4 ]]; then
echo -n "${curr_ipv4}" >/kind/old-ipv4
fi
# do IPv6
curr_ipv6="$( (getent ahostsv6 $(hostname) | head -n1 | cut -d' ' -f1) || true)"
echo "INFO: Detected IPv6 address: ${curr_ipv6}" >&2
if [ -f /kind/old-ipv6 ]; then
old_ipv6=$(cat /kind/old-ipv6)
echo "INFO: Detected old IPv6 address: ${old_ipv6}" >&2
# sanity check that we have a current address
if [[ -z $curr_ipv6 ]]; then
echo "ERROR: Have an old IPv6 address but no current IPv6 address (!)" >&2
fi
# kubernetes manifests are only present on control-plane nodes
sed -i "s#${old_ipv6}#${curr_ipv6}#" /etc/kubernetes/manifests/*.yaml || true
# this is no longer required with autodiscovery
sed -i "s#${old_ipv6}#${curr_ipv6}#" /var/lib/kubelet/kubeadm-flags.env || true
fi
if [[ -n $curr_ipv6 ]]; then
echo -n "${curr_ipv6}" >/kind/old-ipv6
fi
}
# run pre-init fixups
fix_kmsg
fix_mount
fix_cgroup
fix_machine_id
fix_product_name
fix_product_uuid
configure_proxy
select_iptables
enable_network_magic
# we want the command (expected to be systemd) to be PID1, so exec to it
exec "$@"