chore: refactor Dockerfile for cross-compilation

This has two big visible changes:

* `installer` image now contains assets for both `amd64` and `arm64`, so
it can be used to generate any Talos image (including RPi on amd64 host)
* Talos is using cross-compilation instead of emulation to build
non-native architectures: on amd64, Go amd64 compiler produces binaries
for both arm64 and amd64
(before this change: Go arm64 compiler via QEMU produces arm64 binaries on amd64)

CI implications: we no longer require arm64 nodes.

Changes walkthrough:

* `installer` container now keeps assets under `/usr/install/<arch>`
* Dockerfile build starts forcing toolchain/base image to use the build
host native architecture, not target architecture
* lots of duplication for amd64/arm64 as we want to combine assets for
both arches in a single image (e.g. we have multi-arch amd64/arm64
installer image, each arch has native installer binary, but both arches
contain full set of amd64/arm64 assets)
* fixed a small bug preventing arm64 on amd64 talosctl cluster create

Signed-off-by: Andrey Smirnov <smirnov.andrey@gmail.com>
This commit is contained in:
Andrey Smirnov 2021-04-16 14:33:34 +03:00 committed by talos-bot
parent a8f1e526bf
commit 5fb38d3e5f
17 changed files with 272 additions and 124 deletions

View File

@ -103,7 +103,7 @@ local volumes = {
// This provides the docker service.
local docker = {
name: 'docker',
image: 'docker:19.03-dind',
image: 'docker:20.10-dind',
entrypoint: ['dockerd'],
privileged: true,
command: [
@ -194,15 +194,13 @@ local check_dirty = Step("check-dirty", depends_on=[generate]);
local build = Step("build", target="talosctl-linux talosctl-darwin kernel initramfs installer talos", depends_on=[check_dirty], environment={"IMAGE_REGISTRY": local_registry, "PUSH": true});
local lint = Step("lint", depends_on=[build]);
local talosctl_cni_bundle = Step('talosctl-cni-bundle', depends_on=[build, lint]);
local iso_amd64 = Step("iso-amd64", target="iso", depends_on=[build], environment={"IMAGE_REGISTRY": local_registry});
local iso_arm64 = Step("iso-arm64", target="iso", depends_on=[build], environment={"IMAGE_REGISTRY": local_registry, "DOCKER_HOST": "tcp://docker-arm64.ci.svc:2376"});
local images_amd64 = Step("images-amd64", target="images", depends_on=[iso_amd64], environment={"IMAGE_REGISTRY": local_registry});
local images_arm64 = Step("images-arm64", target="images", depends_on=[iso_arm64], environment={"IMAGE_REGISTRY": local_registry, "DOCKER_HOST": "tcp://docker-arm64.ci.svc:2376"});
local sbcs_arm64 = Step("sbcs-arm64", target="sbcs", depends_on=[images_amd64, images_arm64], environment={"IMAGE_REGISTRY": local_registry, "DOCKER_HOST": "tcp://docker-arm64.ci.svc:2376"});
local iso = Step("iso", target="iso", depends_on=[build], environment={"IMAGE_REGISTRY": local_registry});
local images = Step("images", target="images", depends_on=[iso], environment={"IMAGE_REGISTRY": local_registry});
local sbcs = Step("sbcs", target="sbcs", depends_on=[images], environment={"IMAGE_REGISTRY": local_registry});
local unit_tests = Step("unit-tests", target="unit-tests unit-tests-race", depends_on=[build, lint]);
local e2e_docker = Step("e2e-docker-short", depends_on=[build, unit_tests], target="e2e-docker", environment={"SHORT_INTEGRATION_TEST": "yes", "IMAGE_REGISTRY": local_registry});
local e2e_qemu = Step("e2e-qemu-short", privileged=true, target="e2e-qemu", depends_on=[build, unit_tests, talosctl_cni_bundle], environment={"IMAGE_REGISTRY": local_registry, "SHORT_INTEGRATION_TEST": "yes"}, when={event: ['pull_request']});
local e2e_iso = Step("e2e-iso", privileged=true, target="e2e-iso", depends_on=[build, unit_tests, iso_amd64, talosctl_cni_bundle], when={event: ['pull_request']}, environment={"IMAGE_REGISTRY": local_registry});
local e2e_iso = Step("e2e-iso", privileged=true, target="e2e-iso", depends_on=[build, unit_tests, iso, talosctl_cni_bundle], when={event: ['pull_request']}, environment={"IMAGE_REGISTRY": local_registry});
local coverage = {
name: 'coverage',
@ -279,7 +277,7 @@ local save_artifacts = {
's3cmd --host=rook-ceph-rgw-ci-store.rook-ceph.svc --host-bucket=rook-ceph-rgw-ci-store.rook-ceph.svc --no-ssl --stats sync _out s3://${CI_COMMIT_SHA}${DRONE_TAG//./-}',
],
volumes: volumes.ForStep(),
depends_on: [build.name, images_amd64.name, images_arm64.name, iso_amd64.name, iso_arm64.name, sbcs_arm64.name, talosctl_cni_bundle.name],
depends_on: [build.name, images.name, iso.name, sbcs.name, talosctl_cni_bundle.name],
};
local load_artifacts = {
@ -304,11 +302,9 @@ local default_steps = [
build,
lint,
talosctl_cni_bundle,
iso_amd64,
iso_arm64,
images_amd64,
images_arm64,
sbcs_arm64,
iso,
images,
sbcs,
unit_tests,
save_artifacts,
coverage,
@ -565,7 +561,7 @@ local release = {
when: {
event: ['tag'],
},
depends_on: [build.name, boot.name, talosctl_cni_bundle.name, images_amd64.name, images_arm64.name, sbcs_arm64.name, iso_amd64.name, iso_arm64.name, push.name, release_notes.name]
depends_on: [build.name, boot.name, talosctl_cni_bundle.name, images.name, sbcs.name, iso.name, push.name, release_notes.name]
};
local release_steps = default_steps + [

View File

@ -11,29 +11,74 @@ ARG EXTRAS
FROM ghcr.io/talos-systems/fhs:${PKGS} AS pkg-fhs
FROM ghcr.io/talos-systems/ca-certificates:${PKGS} AS pkg-ca-certificates
FROM ghcr.io/talos-systems/cryptsetup:${PKGS} AS pkg-cryptsetup
FROM ghcr.io/talos-systems/containerd:${PKGS} AS pkg-containerd
FROM ghcr.io/talos-systems/dosfstools:${PKGS} AS pkg-dosfstools
FROM ghcr.io/talos-systems/eudev:${PKGS} AS pkg-eudev
FROM --platform=amd64 ghcr.io/talos-systems/cryptsetup:${PKGS} AS pkg-cryptsetup-amd64
FROM --platform=arm64 ghcr.io/talos-systems/cryptsetup:${PKGS} AS pkg-cryptsetup-arm64
FROM --platform=amd64 ghcr.io/talos-systems/containerd:${PKGS} AS pkg-containerd-amd64
FROM --platform=arm64 ghcr.io/talos-systems/containerd:${PKGS} AS pkg-containerd-arm64
FROM --platform=amd64 ghcr.io/talos-systems/dosfstools:${PKGS} AS pkg-dosfstools-amd64
FROM --platform=arm64 ghcr.io/talos-systems/dosfstools:${PKGS} AS pkg-dosfstools-arm64
FROM --platform=amd64 ghcr.io/talos-systems/eudev:${PKGS} AS pkg-eudev-amd64
FROM --platform=arm64 ghcr.io/talos-systems/eudev:${PKGS} AS pkg-eudev-arm64
FROM ghcr.io/talos-systems/grub:${PKGS} AS pkg-grub
FROM ghcr.io/talos-systems/iptables:${PKGS} AS pkg-iptables
FROM ghcr.io/talos-systems/libjson-c:${PKGS} AS pkg-libjson-c
FROM ghcr.io/talos-systems/libpopt:${PKGS} AS pkg-libpopt
FROM ghcr.io/talos-systems/libressl:${PKGS} AS pkg-libressl
FROM ghcr.io/talos-systems/libseccomp:${PKGS} AS pkg-libseccomp
FROM ghcr.io/talos-systems/linux-firmware:${PKGS} AS pkg-linux-firmware
FROM ghcr.io/talos-systems/lvm2:${PKGS} AS pkg-lvm2
FROM ghcr.io/talos-systems/libaio:${PKGS} AS pkg-libaio
FROM ghcr.io/talos-systems/musl:${PKGS} AS pkg-musl
FROM ghcr.io/talos-systems/open-iscsi:${PKGS} AS pkg-open-iscsi
FROM ghcr.io/talos-systems/open-isns:${PKGS} AS pkg-open-isns
FROM ghcr.io/talos-systems/runc:${PKGS} AS pkg-runc
FROM ghcr.io/talos-systems/xfsprogs:${PKGS} AS pkg-xfsprogs
FROM ghcr.io/talos-systems/util-linux:${PKGS} AS pkg-util-linux
FROM ghcr.io/talos-systems/kmod:${PKGS} AS pkg-kmod
FROM --platform=amd64 ghcr.io/talos-systems/grub:${PKGS} AS pkg-grub-amd64
FROM --platform=arm64 ghcr.io/talos-systems/grub:${PKGS} AS pkg-grub-arm64
FROM --platform=amd64 ghcr.io/talos-systems/iptables:${PKGS} AS pkg-iptables-amd64
FROM --platform=arm64 ghcr.io/talos-systems/iptables:${PKGS} AS pkg-iptables-arm64
FROM --platform=amd64 ghcr.io/talos-systems/libjson-c:${PKGS} AS pkg-libjson-c-amd64
FROM --platform=arm64 ghcr.io/talos-systems/libjson-c:${PKGS} AS pkg-libjson-c-arm64
FROM --platform=amd64 ghcr.io/talos-systems/libpopt:${PKGS} AS pkg-libpopt-amd64
FROM --platform=arm64 ghcr.io/talos-systems/libpopt:${PKGS} AS pkg-libpopt-arm64
FROM --platform=amd64 ghcr.io/talos-systems/libressl:${PKGS} AS pkg-libressl-amd64
FROM --platform=arm64 ghcr.io/talos-systems/libressl:${PKGS} AS pkg-libressl-arm64
FROM --platform=amd64 ghcr.io/talos-systems/libseccomp:${PKGS} AS pkg-libseccomp-amd64
FROM --platform=arm64 ghcr.io/talos-systems/libseccomp:${PKGS} AS pkg-libseccomp-arm64
FROM --platform=amd64 ghcr.io/talos-systems/linux-firmware:${PKGS} AS pkg-linux-firmware-amd64
FROM --platform=arm64 ghcr.io/talos-systems/linux-firmware:${PKGS} AS pkg-linux-firmware-arm64
FROM --platform=amd64 ghcr.io/talos-systems/lvm2:${PKGS} AS pkg-lvm2-amd64
FROM --platform=arm64 ghcr.io/talos-systems/lvm2:${PKGS} AS pkg-lvm2-arm64
FROM --platform=amd64 ghcr.io/talos-systems/libaio:${PKGS} AS pkg-libaio-amd64
FROM --platform=arm64 ghcr.io/talos-systems/libaio:${PKGS} AS pkg-libaio-arm64
FROM --platform=amd64 ghcr.io/talos-systems/musl:${PKGS} AS pkg-musl-amd64
FROM --platform=arm64 ghcr.io/talos-systems/musl:${PKGS} AS pkg-musl-arm64
FROM --platform=amd64 ghcr.io/talos-systems/open-iscsi:${PKGS} AS pkg-open-iscsi-amd64
FROM --platform=arm64 ghcr.io/talos-systems/open-iscsi:${PKGS} AS pkg-open-iscsi-arm64
FROM --platform=amd64 ghcr.io/talos-systems/open-isns:${PKGS} AS pkg-open-isns-amd64
FROM --platform=arm64 ghcr.io/talos-systems/open-isns:${PKGS} AS pkg-open-isns-arm64
FROM --platform=amd64 ghcr.io/talos-systems/runc:${PKGS} AS pkg-runc-amd64
FROM --platform=arm64 ghcr.io/talos-systems/runc:${PKGS} AS pkg-runc-arm64
FROM --platform=amd64 ghcr.io/talos-systems/xfsprogs:${PKGS} AS pkg-xfsprogs-amd64
FROM --platform=arm64 ghcr.io/talos-systems/xfsprogs:${PKGS} AS pkg-xfsprogs-arm64
FROM --platform=amd64 ghcr.io/talos-systems/util-linux:${PKGS} AS pkg-util-linux-amd64
FROM --platform=arm64 ghcr.io/talos-systems/util-linux:${PKGS} AS pkg-util-linux-arm64
FROM --platform=amd64 ghcr.io/talos-systems/kmod:${PKGS} AS pkg-kmod-amd64
FROM --platform=arm64 ghcr.io/talos-systems/kmod:${PKGS} AS pkg-kmod-arm64
FROM ghcr.io/talos-systems/kernel:${PKGS} AS pkg-kernel
FROM ghcr.io/talos-systems/u-boot:${PKGS} AS pkg-u-boot
FROM ghcr.io/talos-systems/raspberrypi-firmware:${PKGS} AS pkg-raspberrypi-firmware
FROM --platform=amd64 ghcr.io/talos-systems/kernel:${PKGS} AS pkg-kernel-amd64
FROM --platform=arm64 ghcr.io/talos-systems/kernel:${PKGS} AS pkg-kernel-arm64
FROM --platform=arm64 ghcr.io/talos-systems/u-boot:${PKGS} AS pkg-u-boot-arm64
FROM --platform=arm64 ghcr.io/talos-systems/raspberrypi-firmware:${PKGS} AS pkg-raspberrypi-firmware-arm64
# Resolve package images using ${EXTRAS} to be used later in COPY --from=.
@ -43,7 +88,7 @@ FROM ghcr.io/talos-systems/talosctl-cni-bundle-install:${EXTRAS} AS extras-talos
FROM $IMPORTVET as importvet
FROM $TOOLS AS tools
FROM --platform=${BUILDPLATFORM} $TOOLS AS tools
ENV PATH /toolchain/bin:/toolchain/go/bin
RUN ["/toolchain/bin/mkdir", "/bin", "/tmp"]
RUN ["/toolchain/bin/ln", "-svf", "/toolchain/bin/bash", "/bin/sh"]
@ -65,8 +110,7 @@ COPY --from=importvet /importvet /toolchain/go/bin/importvet
# The build target creates a container that will be used to build Talos source
# code.
FROM scratch AS build
COPY --from=tools / /
FROM --platform=${BUILDPLATFORM} tools AS build
SHELL ["/toolchain/bin/bash", "-c"]
ENV PATH /toolchain/bin:/toolchain/go/bin
ENV GO111MODULE on
@ -123,7 +167,7 @@ WORKDIR /pkg/machinery
RUN --mount=type=cache,target=/.cache go generate /pkg/machinery/config/types/v1alpha1/...
WORKDIR /
FROM scratch AS generate
FROM --platform=${BUILDPLATFORM} scratch AS generate
COPY --from=generate-build /api/common/*.pb.go /pkg/machinery/api/common/
COPY --from=generate-build /api/health/*.pb.go /pkg/machinery/api/health/
COPY --from=generate-build /api/security/*.pb.go /pkg/machinery/api/security/
@ -155,25 +199,43 @@ WORKDIR /src
# The init target builds the init binary.
FROM base AS init-build
FROM base AS init-build-amd64
WORKDIR /src/internal/app/init
ARG GO_BUILDFLAGS
ARG GO_LDFLAGS
RUN --mount=type=cache,target=/.cache go build ${GO_BUILDFLAGS} -ldflags "${GO_LDFLAGS}" -o /init
RUN --mount=type=cache,target=/.cache GOOS=linux GOARCH=amd64 go build ${GO_BUILDFLAGS} -ldflags "${GO_LDFLAGS}" -o /init
RUN chmod +x /init
FROM base AS init-build-arm64
WORKDIR /src/internal/app/init
ARG GO_BUILDFLAGS
ARG GO_LDFLAGS
RUN --mount=type=cache,target=/.cache GOOS=linux GOARCH=arm64 go build ${GO_BUILDFLAGS} -ldflags "${GO_LDFLAGS}" -o /init
RUN chmod +x /init
FROM init-build-${TARGETARCH} AS init-build
FROM scratch AS init
COPY --from=init-build /init /init
# The machined target builds the machined binary.
FROM base AS machined-build
FROM base AS machined-build-amd64
WORKDIR /src/internal/app/machined
ARG GO_BUILDFLAGS
ARG GO_LDFLAGS
RUN --mount=type=cache,target=/.cache go build ${GO_BUILDFLAGS} -ldflags "${GO_LDFLAGS}" -o /machined
RUN --mount=type=cache,target=/.cache GOOS=linux GOARCH=amd64 go build ${GO_BUILDFLAGS} -ldflags "${GO_LDFLAGS}" -o /machined
RUN chmod +x /machined
FROM base AS machined-build-arm64
WORKDIR /src/internal/app/machined
ARG GO_BUILDFLAGS
ARG GO_LDFLAGS
RUN --mount=type=cache,target=/.cache GOOS=linux GOARCH=arm64 go build ${GO_BUILDFLAGS} -ldflags "${GO_LDFLAGS}" -o /machined
RUN chmod +x /machined
FROM machined-build-${TARGETARCH} AS machined-build
FROM scratch AS machined
COPY --from=machined-build /machined /machined
@ -240,33 +302,33 @@ COPY --from=pkg-kernel /boot/vmlinuz /vmlinuz-${TARGETARCH}
# The rootfs target provides the Talos rootfs.
FROM build AS rootfs-base
FROM build AS rootfs-base-amd64
COPY --from=pkg-fhs / /rootfs
COPY --from=pkg-ca-certificates / /rootfs
COPY --from=pkg-cryptsetup / /rootfs
COPY --from=pkg-containerd / /rootfs
COPY --from=pkg-dosfstools / /rootfs
COPY --from=pkg-eudev / /rootfs
COPY --from=pkg-iptables / /rootfs
COPY --from=pkg-libjson-c / /rootfs
COPY --from=pkg-libpopt / /rootfs
COPY --from=pkg-libressl / /rootfs
COPY --from=pkg-libseccomp / /rootfs
COPY --from=pkg-linux-firmware /lib/firmware/bnx2 /rootfs/lib/firmware/bnx2
COPY --from=pkg-linux-firmware /lib/firmware/bnx2x /rootfs/lib/firmware/bnx2x
COPY --from=pkg-lvm2 / /rootfs
COPY --from=pkg-libaio / /rootfs
COPY --from=pkg-musl / /rootfs
COPY --from=pkg-open-iscsi / /rootfs
COPY --from=pkg-open-isns / /rootfs
COPY --from=pkg-runc / /rootfs
COPY --from=pkg-xfsprogs / /rootfs
COPY --from=pkg-util-linux /lib/libblkid.* /rootfs/lib/
COPY --from=pkg-util-linux /lib/libuuid.* /rootfs/lib/
COPY --from=pkg-util-linux /lib/libmount.* /rootfs/lib/
COPY --from=pkg-kmod /usr/lib/libkmod.* /rootfs/lib/
COPY --from=pkg-kernel /lib/modules /rootfs/lib/modules
COPY --from=machined /machined /rootfs/sbin/init
COPY --from=pkg-cryptsetup-amd64 / /rootfs
COPY --from=pkg-containerd-amd64 / /rootfs
COPY --from=pkg-dosfstools-amd64 / /rootfs
COPY --from=pkg-eudev-amd64 / /rootfs
COPY --from=pkg-iptables-amd64 / /rootfs
COPY --from=pkg-libjson-c-amd64 / /rootfs
COPY --from=pkg-libpopt-amd64 / /rootfs
COPY --from=pkg-libressl-amd64 / /rootfs
COPY --from=pkg-libseccomp-amd64 / /rootfs
COPY --from=pkg-linux-firmware-amd64 /lib/firmware/bnx2 /rootfs/lib/firmware/bnx2
COPY --from=pkg-linux-firmware-amd64 /lib/firmware/bnx2x /rootfs/lib/firmware/bnx2x
COPY --from=pkg-lvm2-amd64 / /rootfs
COPY --from=pkg-libaio-amd64 / /rootfs
COPY --from=pkg-musl-amd64 / /rootfs
COPY --from=pkg-open-iscsi-amd64 / /rootfs
COPY --from=pkg-open-isns-amd64 / /rootfs
COPY --from=pkg-runc-amd64 / /rootfs
COPY --from=pkg-xfsprogs-amd64 / /rootfs
COPY --from=pkg-util-linux-amd64 /lib/libblkid.* /rootfs/lib/
COPY --from=pkg-util-linux-amd64 /lib/libuuid.* /rootfs/lib/
COPY --from=pkg-util-linux-amd64 /lib/libmount.* /rootfs/lib/
COPY --from=pkg-kmod-amd64 /usr/lib/libkmod.* /rootfs/lib/
COPY --from=pkg-kernel-amd64 /lib/modules /rootfs/lib/modules
COPY --from=machined-build-amd64 /machined /rootfs/sbin/init
# NB: We run the cleanup step before creating extra directories, files, and
# symlinks to avoid accidentally cleaning them up.
COPY ./hack/cleanup.sh /toolchain/bin/cleanup.sh
@ -282,23 +344,81 @@ RUN ln -s /etc/ssl /rootfs/usr/share/ca-certificates
RUN ln -s /etc/ssl /rootfs/usr/local/share/ca-certificates
RUN ln -s /etc/ssl /rootfs/etc/ca-certificates
FROM rootfs-base AS rootfs-squashfs
FROM build AS rootfs-base-arm64
COPY --from=pkg-fhs / /rootfs
COPY --from=pkg-ca-certificates / /rootfs
COPY --from=pkg-cryptsetup-arm64 / /rootfs
COPY --from=pkg-containerd-arm64 / /rootfs
COPY --from=pkg-dosfstools-arm64 / /rootfs
COPY --from=pkg-eudev-arm64 / /rootfs
COPY --from=pkg-iptables-arm64 / /rootfs
COPY --from=pkg-libjson-c-arm64 / /rootfs
COPY --from=pkg-libpopt-arm64 / /rootfs
COPY --from=pkg-libressl-arm64 / /rootfs
COPY --from=pkg-libseccomp-arm64 / /rootfs
COPY --from=pkg-linux-firmware-arm64 /lib/firmware/bnx2 /rootfs/lib/firmware/bnx2
COPY --from=pkg-linux-firmware-arm64 /lib/firmware/bnx2x /rootfs/lib/firmware/bnx2x
COPY --from=pkg-lvm2-arm64 / /rootfs
COPY --from=pkg-libaio-arm64 / /rootfs
COPY --from=pkg-musl-arm64 / /rootfs
COPY --from=pkg-open-iscsi-arm64 / /rootfs
COPY --from=pkg-open-isns-arm64 / /rootfs
COPY --from=pkg-runc-arm64 / /rootfs
COPY --from=pkg-xfsprogs-arm64 / /rootfs
COPY --from=pkg-util-linux-arm64 /lib/libblkid.* /rootfs/lib/
COPY --from=pkg-util-linux-arm64 /lib/libuuid.* /rootfs/lib/
COPY --from=pkg-util-linux-arm64 /lib/libmount.* /rootfs/lib/
COPY --from=pkg-kmod-arm64 /usr/lib/libkmod.* /rootfs/lib/
COPY --from=pkg-kernel-arm64 /lib/modules /rootfs/lib/modules
COPY --from=machined-build-arm64 /machined /rootfs/sbin/init
# NB: We run the cleanup step before creating extra directories, files, and
# symlinks to avoid accidentally cleaning them up.
COPY ./hack/cleanup.sh /toolchain/bin/cleanup.sh
RUN cleanup.sh /rootfs
COPY hack/containerd.toml /rootfs/etc/cri/containerd.toml
RUN touch /rootfs/etc/resolv.conf
RUN touch /rootfs/etc/hosts
RUN touch /rootfs/etc/os-release
RUN mkdir -pv /rootfs/{boot,usr/local/share,mnt,system}
RUN mkdir -pv /rootfs/{etc/kubernetes/manifests,etc/cni,usr/libexec/kubernetes}
RUN ln -s /etc/ssl /rootfs/etc/pki
RUN ln -s /etc/ssl /rootfs/usr/share/ca-certificates
RUN ln -s /etc/ssl /rootfs/usr/local/share/ca-certificates
RUN ln -s /etc/ssl /rootfs/etc/ca-certificates
FROM rootfs-base-${TARGETARCH} AS rootfs-base
FROM rootfs-base-arm64 AS rootfs-squashfs-arm64
RUN mksquashfs /rootfs /rootfs.sqsh -all-root -noappend -comp xz -Xdict-size 100% -no-progress
FROM scratch AS squashfs
COPY --from=rootfs-squashfs /rootfs.sqsh /
FROM rootfs-base-amd64 AS rootfs-squashfs-amd64
RUN mksquashfs /rootfs /rootfs.sqsh -all-root -noappend -comp xz -Xdict-size 100% -no-progress
FROM scratch AS squashfs-arm64
COPY --from=rootfs-squashfs-arm64 /rootfs.sqsh /
FROM scratch AS squashfs-amd64
COPY --from=rootfs-squashfs-amd64 /rootfs.sqsh /
FROM scratch AS rootfs
COPY --from=rootfs-base /rootfs /
# The initramfs target provides the Talos initramfs image.
FROM build AS initramfs-archive
FROM build AS initramfs-archive-arm64
WORKDIR /initramfs
COPY --from=squashfs /rootfs.sqsh .
COPY --from=init /init .
COPY --from=squashfs-arm64 /rootfs.sqsh .
COPY --from=init-build-arm64 /init .
RUN set -o pipefail && find . 2>/dev/null | cpio -H newc -o | xz -v -C crc32 -0 -e -T 0 -z >/initramfs.xz
FROM build AS initramfs-archive-amd64
WORKDIR /initramfs
COPY --from=squashfs-amd64 /rootfs.sqsh .
COPY --from=init-build-amd64 /init .
RUN set -o pipefail && find . 2>/dev/null | cpio -H newc -o | xz -v -C crc32 -0 -e -T 0 -z >/initramfs.xz
FROM initramfs-archive-${TARGETARCH} AS initramfs-archive
FROM scratch AS initramfs
ARG TARGETARCH
COPY --from=initramfs-archive /initramfs.xz /initramfs-${TARGETARCH}.xz
@ -318,12 +438,27 @@ FROM base AS installer-build
ARG GO_BUILDFLAGS
ARG GO_LDFLAGS
WORKDIR /src/cmd/installer
RUN --mount=type=cache,target=/.cache go build ${GO_BUILDFLAGS} -ldflags "${GO_LDFLAGS}" -o /installer
ARG TARGETARCH
RUN --mount=type=cache,target=/.cache GOOS=linux GOARCH=${TARGETARCH} go build ${GO_BUILDFLAGS} -ldflags "${GO_LDFLAGS}" -o /installer
RUN chmod +x /installer
FROM alpine:3.13.5 AS unicode-pf2
RUN apk add --no-cache --update grub
FROM scratch AS install-artifacts
COPY --from=pkg-grub-amd64 /usr/lib/grub /usr/lib/grub
COPY --from=pkg-grub-arm64 /usr/lib/grub /usr/lib/grub
COPY --from=pkg-grub / /
COPY --from=unicode-pf2 /usr/share/grub/unicode.pf2 /usr/share/grub/unicode.pf2
COPY --from=pkg-kernel-amd64 /boot/vmlinuz /usr/install/amd64/vmlinuz
COPY --from=pkg-kernel-arm64 /boot/vmlinuz /usr/install/arm64/vmlinuz
COPY --from=pkg-kernel-amd64 /dtb /usr/install/amd64/dtb
COPY --from=pkg-kernel-arm64 /dtb /usr/install/arm64/dtb
COPY --from=initramfs-archive-amd64 /initramfs.xz /usr/install/amd64/initramfs.xz
COPY --from=initramfs-archive-arm64 /initramfs.xz /usr/install/arm64/initramfs.xz
COPY --from=pkg-u-boot-arm64 / /usr/install/arm64/u-boot
COPY --from=pkg-raspberrypi-firmware-arm64 / /usr/install/arm64/raspberrypi-firmware
FROM alpine:3.13.5 AS installer
RUN apk add --no-cache --update \
bash \
@ -335,14 +470,8 @@ RUN apk add --no-cache --update \
xfsprogs \
xorriso \
xz
COPY --from=pkg-grub / /
COPY --from=unicode-pf2 /usr/share/grub/unicode.pf2 /usr/share/grub/unicode.pf2
ARG TARGETARCH
COPY --from=kernel /vmlinuz-${TARGETARCH} /usr/install/vmlinuz
COPY --from=pkg-kernel /dtb /usr/install/dtb
COPY --from=initramfs /initramfs-${TARGETARCH}.xz /usr/install/initramfs.xz
COPY --from=pkg-u-boot / /usr/install/u-boot
COPY --from=pkg-raspberrypi-firmware / /usr/install/raspberrypi-firmware
COPY --from=install-artifacts / /
COPY --from=installer-build /installer /bin/installer
RUN ln -s /bin/installer /bin/talosctl
ARG TAG
@ -356,7 +485,7 @@ ONBUILD RUN apk add --no-cache --update \
xz
ONBUILD WORKDIR /initramfs
ONBUILD ARG RM
ONBUILD RUN xz -d /usr/install/initramfs.xz \
ONBUILD RUN xz -d /usr/install/${TARGETARCH}/initramfs.xz \
&& cpio -idvm < /usr/install/initramfs \
&& unsquashfs -f -d /rootfs rootfs.sqsh \
&& for f in ${RM}; do rm -rfv /rootfs$f; done \
@ -365,7 +494,7 @@ ONBUILD RUN xz -d /usr/install/initramfs.xz \
ONBUILD COPY --from=customization / /rootfs
ONBUILD RUN find /rootfs \
&& mksquashfs /rootfs rootfs.sqsh -all-root -noappend -comp xz -Xdict-size 100% -no-progress \
&& set -o pipefail && find . 2>/dev/null | cpio -H newc -o | xz -v -C crc32 -0 -e -T 0 -z >/usr/install/initramfs.xz \
&& set -o pipefail && find . 2>/dev/null | cpio -H newc -o | xz -v -C crc32 -0 -e -T 0 -z >/usr/install/${TARGETARCH}/initramfs.xz \
&& rm -rf /rootfs \
&& rm -rf /initramfs
ONBUILD WORKDIR /
@ -440,7 +569,7 @@ RUN --mount=type=cache,target=/.cache golangci-lint run --config ../../.golangci
WORKDIR /src
RUN --mount=type=cache,target=/.cache importvet github.com/talos-systems/talos/...
RUN find . -name '*.pb.go' | xargs rm
RUN FILES="$(gofumports -l -local github.com/talos-systems/talos .)" && test -z "${FILES}" || (echo -e "Source code is not formatted with 'gofumports -w -local github.com/talos-systems/talos .':\n${FILES}"; exit 1)
RUN --mount=type=cache,target=/.cache FILES="$(gofumports -l -local github.com/talos-systems/talos .)" && test -z "${FILES}" || (echo -e "Source code is not formatted with 'gofumports -w -local github.com/talos-systems/talos .':\n${FILES}"; exit 1)
# The protolint target performs linting on protobuf files.

View File

@ -198,20 +198,26 @@ talosctl: $(TALOSCTL_DEFAULT_TARGET) ## Builds the talosctl binary for the local
image-%: ## Builds the specified image. Valid options are aws, azure, digital-ocean, gcp, and vmware (e.g. image-aws)
@docker pull $(REGISTRY_AND_USERNAME)/installer:$(TAG)
@docker run --rm -v /dev:/dev --privileged $(REGISTRY_AND_USERNAME)/installer:$(TAG) image --platform $* --tar-to-stdout | tar xz -C $(ARTIFACTS)
@for platform in $(subst $(,),$(space),$(PLATFORM)); do \
arch=`basename "$${platform}"` ; \
docker run --rm -v /dev:/dev --privileged $(REGISTRY_AND_USERNAME)/installer:$(TAG) image --platform $* --arch $$arch --tar-to-stdout | tar xz -C $(ARTIFACTS) ; \
done
images: image-aws image-azure image-digital-ocean image-gcp image-metal image-openstack image-vmware ## Builds all known images (AWS, Azure, DigitalOcean, GCP, Metal, Openstack, and VMware).
sbc-%: ## Builds the specified SBC image. Valid options are rpi_4, rock64, bananapi_m64, libretech_all_h3_cc_h5, and rockpi_4 (e.g. sbc-rpi_4)
@docker pull $(REGISTRY_AND_USERNAME)/installer:$(TAG)
@docker run --rm -v /dev:/dev --privileged $(REGISTRY_AND_USERNAME)/installer:$(TAG) image --platform metal --board $* --tar-to-stdout | tar xz -C $(ARTIFACTS)
@docker run --rm -v /dev:/dev --privileged $(REGISTRY_AND_USERNAME)/installer:$(TAG) image --platform metal --arch arm64 --board $* --tar-to-stdout | tar xz -C $(ARTIFACTS)
sbcs: sbc-rpi_4 sbc-rock64 sbc-bananapi_m64 sbc-libretech_all_h3_cc_h5 sbc-rockpi_4 ## Builds all known SBC images (Raspberry Pi 4 Model B, Rock64, Banana Pi M64, Radxa ROCK Pi 4, and Libre Computer Board ALL-H3-CC).
.PHONY: iso
iso: ## Builds the ISO and outputs it to the artifact directory.
@docker pull $(REGISTRY_AND_USERNAME)/installer:$(TAG)
@docker run --rm -i $(REGISTRY_AND_USERNAME)/installer:$(TAG) iso --tar-to-stdout | tar xz -C $(ARTIFACTS)
@for platform in $(subst $(,),$(space),$(PLATFORM)); do \
arch=`basename "$${platform}"` ; \
docker run --rm -i $(REGISTRY_AND_USERNAME)/installer:$(TAG) iso --arch $$arch --tar-to-stdout | tar xz -C $(ARTIFACTS) ; \
done
.PHONY: boot
boot: ## Creates a compressed tarball that includes vmlinuz-{amd64,arm64} and initramfs-{amd64,arm64}.xz. Note that these files must already be present in the artifacts directory.

View File

@ -10,7 +10,6 @@ import (
"log"
"os"
"path/filepath"
stdruntime "runtime"
"strings"
"github.com/spf13/cobra"
@ -97,7 +96,7 @@ func runImageCmd() (err error) {
return err
}
if err := finalize(p, img); err != nil {
if err := finalize(p, img, options.Arch); err != nil {
return err
}
@ -111,7 +110,7 @@ func runImageCmd() (err error) {
}
//nolint:gocyclo
func finalize(platform runtime.Platform, img string) (err error) {
func finalize(platform runtime.Platform, img, arch string) (err error) {
dir := filepath.Dir(img)
file := filepath.Base(img)
@ -119,7 +118,7 @@ func finalize(platform runtime.Platform, img string) (err error) {
switch platform.Name() {
case "aws":
if err = tar(fmt.Sprintf("aws-%s.tar.gz", stdruntime.GOARCH), file, dir); err != nil {
if err = tar(fmt.Sprintf("aws-%s.tar.gz", arch), file, dir); err != nil {
return err
}
case "azure":
@ -129,28 +128,28 @@ func finalize(platform runtime.Platform, img string) (err error) {
return err
}
if err = tar(fmt.Sprintf("azure-%s.tar.gz", stdruntime.GOARCH), file, dir); err != nil {
if err = tar(fmt.Sprintf("azure-%s.tar.gz", arch), file, dir); err != nil {
return err
}
case "digital-ocean":
if err = tar(fmt.Sprintf("digital-ocean-%s.tar.gz", stdruntime.GOARCH), file, dir); err != nil {
if err = tar(fmt.Sprintf("digital-ocean-%s.tar.gz", arch), file, dir); err != nil {
return err
}
case "gcp":
if err = tar(fmt.Sprintf("gcp-%s.tar.gz", stdruntime.GOARCH), file, dir); err != nil {
if err = tar(fmt.Sprintf("gcp-%s.tar.gz", arch), file, dir); err != nil {
return err
}
case "openstack":
if err = tar(fmt.Sprintf("openstack-%s.tar.gz", stdruntime.GOARCH), file, dir); err != nil {
if err = tar(fmt.Sprintf("openstack-%s.tar.gz", arch), file, dir); err != nil {
return err
}
case "vmware":
if err = ova.CreateOVAFromRAW(name, img, outputArg); err != nil {
if err = ova.CreateOVAFromRAW(name, img, outputArg, arch); err != nil {
return err
}
case "metal":
if options.Board != constants.BoardNone {
name := fmt.Sprintf("metal-%s-%s.img", options.Board, stdruntime.GOARCH)
name := fmt.Sprintf("metal-%s-%s.img", options.Board, arch)
file = filepath.Join(outputArg, name)
@ -168,7 +167,7 @@ func finalize(platform runtime.Platform, img string) (err error) {
break
}
name := fmt.Sprintf("metal-%s.tar.gz", stdruntime.GOARCH)
name := fmt.Sprintf("metal-%s.tar.gz", arch)
if err = tar(name, file, dir); err != nil {
return err

View File

@ -11,7 +11,6 @@ import (
"log"
"os"
"path/filepath"
"runtime"
"github.com/spf13/cobra"
@ -58,8 +57,8 @@ func runISOCmd() error {
}
files := map[string]string{
"/usr/install/vmlinuz": "/mnt/boot/vmlinuz",
"/usr/install/initramfs.xz": "/mnt/boot/initramfs.xz",
fmt.Sprintf("/usr/install/%s/vmlinuz", options.Arch): "/mnt/boot/vmlinuz",
fmt.Sprintf("/usr/install/%s/initramfs.xz", options.Arch): "/mnt/boot/initramfs.xz",
}
for src, dest := range files {
@ -103,7 +102,7 @@ func runISOCmd() error {
log.Println("creating ISO")
out := fmt.Sprintf("/tmp/talos-%s.iso", runtime.GOARCH)
out := fmt.Sprintf("/tmp/talos-%s.iso", options.Arch)
if err := pkg.CreateISO(out, "/mnt"); err != nil {
return err

View File

@ -7,6 +7,7 @@ package cmd
import (
"fmt"
"os"
"runtime"
"github.com/spf13/cobra"
@ -36,6 +37,7 @@ func init() {
rootCmd.PersistentFlags().StringVar(&options.ConfigSource, "config", "", "The value of "+constants.KernelParamConfig)
rootCmd.PersistentFlags().StringVar(&options.Disk, "disk", "", "The path to the disk to install to")
rootCmd.PersistentFlags().StringVar(&options.Platform, "platform", "", "The value of "+constants.KernelParamPlatform)
rootCmd.PersistentFlags().StringVar(&options.Arch, "arch", runtime.GOARCH, "The target architecture")
rootCmd.PersistentFlags().StringVar(&options.Board, "board", constants.BoardNone, "The value of "+constants.KernelParamBoard)
rootCmd.PersistentFlags().StringArrayVar(&options.ExtraKernelArgs, "extra-kernel-arg", []string{}, "Extra argument to pass to the kernel")
rootCmd.PersistentFlags().BoolVar(&options.Bootloader, "bootloader", true, "Install a booloader to the specified disk")

View File

@ -29,6 +29,7 @@ type Options struct {
ConfigSource string
Disk string
Platform string
Arch string
Board string
ExtraKernelArgs []string
Bootloader bool
@ -92,6 +93,7 @@ func NewInstaller(cmdline *procfs.Cmdline, seq runtime.Sequence, opts *Options)
options: opts,
bootloader: &grub.Grub{
BootDisk: opts.Disk,
Arch: opts.Arch,
},
}

View File

@ -118,11 +118,11 @@ func NewManifest(label string, sequence runtime.Sequence, bootPartitionFound boo
PreserveContents: bootPartitionFound,
Assets: []*Asset{
{
Source: constants.KernelAssetPath,
Source: fmt.Sprintf(constants.KernelAssetPath, opts.Arch),
Destination: filepath.Join(constants.BootMountPoint, label, constants.KernelAsset),
},
{
Source: constants.InitramfsAssetPath,
Source: fmt.Sprintf(constants.InitramfsAssetPath, opts.Arch),
Destination: filepath.Join(constants.BootMountPoint, label, constants.InitramfsAsset),
},
},

View File

@ -12,7 +12,6 @@ import (
"io/ioutil"
"os"
"path/filepath"
"runtime"
"strings"
"text/template"
@ -132,7 +131,7 @@ const ovfTpl = `<?xml version="1.0" encoding="UTF-8"?>
// CreateOVAFromRAW creates an OVA from a RAW disk.
//nolint:gocyclo
func CreateOVAFromRAW(name, src, out string) (err error) {
func CreateOVAFromRAW(name, src, out, arch string) (err error) {
dir, err := ioutil.TempDir("/tmp", "talos")
if err != nil {
return err
@ -187,7 +186,7 @@ func CreateOVAFromRAW(name, src, out string) (err error) {
return err
}
if _, err = cmd.Run("tar", "-cvf", filepath.Join(out, fmt.Sprintf("vmware-%s.ova", runtime.GOARCH)), "-C", dir, name+".ovf", name+".mf", name+".vmdk"); err != nil {
if _, err = cmd.Run("tar", "-cvf", filepath.Join(out, fmt.Sprintf("vmware-%s.ova", arch)), "-C", dir, name+".ovf", name+".mf", name+".vmdk"); err != nil {
return err
}

View File

@ -20,7 +20,7 @@ import (
)
var (
bin = fmt.Sprintf("/usr/install/u-boot/%s/u-boot-sunxi-with-spl.bin", constants.BoardBananaPiM64)
bin = fmt.Sprintf("/usr/install/arm64/u-boot/%s/u-boot-sunxi-with-spl.bin", constants.BoardBananaPiM64)
off int64 = 1024 * 8
dtb = "/dtb/allwinner/sun50i-a64-bananapi-m64.dtb"
)
@ -74,7 +74,7 @@ func (b *BananaPiM64) Install(disk string) (err error) {
return err
}
src := "/usr/install" + dtb
src := "/usr/install/arm64" + dtb
dst := "/boot/EFI" + dtb
err = os.MkdirAll(filepath.Dir(dst), 0o600)

View File

@ -20,7 +20,7 @@ import (
)
var (
bin = fmt.Sprintf("/usr/install/u-boot/%s/u-boot-sunxi-with-spl.bin", constants.BoardLibretechAllH3CCH5)
bin = fmt.Sprintf("/usr/install/arm64/u-boot/%s/u-boot-sunxi-with-spl.bin", constants.BoardLibretechAllH3CCH5)
off int64 = 1024 * 8
dtb = "/dtb/allwinner/sun50i-h5-libretech-all-h3-cc.dtb"
)
@ -71,7 +71,7 @@ func (l *LibretechAllH3CCH5) Install(disk string) (err error) {
return err
}
src := "/usr/install" + dtb
src := "/usr/install/arm64" + dtb
dst := "/boot/EFI" + dtb
err = os.MkdirAll(filepath.Dir(dst), 0o600)

View File

@ -20,7 +20,7 @@ import (
)
var (
bin = fmt.Sprintf("/usr/install/u-boot/%s/u-boot-rockchip.bin", constants.BoardRock64)
bin = fmt.Sprintf("/usr/install/arm64/u-boot/%s/u-boot-rockchip.bin", constants.BoardRock64)
off int64 = 512 * 64
dtb = "/dtb/rockchip/rk3328-rock64.dtb"
)
@ -71,7 +71,7 @@ func (r *Rock64) Install(disk string) (err error) {
return err
}
src := "/usr/install" + dtb
src := "/usr/install/arm64" + dtb
dst := "/boot/EFI" + dtb
err = os.MkdirAll(filepath.Dir(dst), 0o600)

View File

@ -20,7 +20,7 @@ import (
)
var (
bin = fmt.Sprintf("/usr/install/u-boot/%s/u-boot-rockchip.bin", constants.BoardRockpi4)
bin = fmt.Sprintf("/usr/install/arm64/u-boot/%s/u-boot-rockchip.bin", constants.BoardRockpi4)
off int64 = 512 * 64
dtb = "/dtb/rockchip/rk3399-rock-pi-4c.dtb"
)
@ -69,7 +69,7 @@ func (r *Rockpi4) Install(disk string) (err error) {
return err
}
src := "/usr/install" + dtb
src := "/usr/install/arm64" + dtb
dst := "/boot/EFI" + dtb
err = os.MkdirAll(filepath.Dir(dst), 0o600)

View File

@ -30,12 +30,12 @@ func (r *RPi4) Name() string {
// Install implements the runtime.Board.
func (r *RPi4) Install(disk string) (err error) {
err = copy.Dir("/usr/install/raspberrypi-firmware/boot", "/boot/EFI")
err = copy.Dir("/usr/install/arm64/raspberrypi-firmware/boot", "/boot/EFI")
if err != nil {
return err
}
err = copy.File("/usr/install/u-boot/rpi_4/u-boot.bin", "/boot/EFI/u-boot.bin")
err = copy.File("/usr/install/arm64/u-boot/rpi_4/u-boot.bin", "/boot/EFI/u-boot.bin")
if err != nil {
return err
}

View File

@ -60,9 +60,15 @@ menuentry "{{ $label.Root }}" {
{{ end }}
`
const (
amd64 = "amd64"
arm64 = "arm64"
)
// Grub represents the grub bootloader.
type Grub struct {
BootDisk string
Arch string
}
// Labels implements the Bootloader interface.
@ -135,12 +141,18 @@ func (g *Grub) Install(fallback string, config interface{}, sequence runtime.Seq
loopDevice := strings.HasPrefix(blk, "/dev/loop")
// default: run for GRUB default platform
platforms := []string{""}
var platforms []string
if goruntime.GOARCH == "amd64" && loopDevice {
// building cloud image for amd64, install both BIOS & UEFI GRUB
switch g.Arch {
case amd64:
platforms = []string{"x86_64-efi", "i386-pc"}
case arm64:
platforms = []string{"arm64-efi"}
}
if goruntime.GOARCH == amd64 && g.Arch == amd64 && !loopDevice {
// let grub choose the platform automatically if not building an image
platforms = []string{""}
}
for _, platform := range platforms {

View File

@ -325,7 +325,7 @@ const (
KernelAssetWithArch = "vmlinuz-" + ArchVariable
// KernelAssetPath is the path to the kernel on disk.
KernelAssetPath = "/usr/install/" + KernelAsset
KernelAssetPath = "/usr/install/%s/" + KernelAsset
// InitramfsAsset defines a well known name for our initramfs filename.
InitramfsAsset = "initramfs.xz"
@ -334,7 +334,7 @@ const (
InitramfsAssetWithArch = "initramfs-" + ArchVariable + ".xz"
// InitramfsAssetPath is the path to the initramfs on disk.
InitramfsAssetPath = "/usr/install/" + InitramfsAsset
InitramfsAssetPath = "/usr/install/%s/" + InitramfsAsset
// RootfsAsset defines a well known name for our rootfs filename.
RootfsAsset = "rootfs.sqsh"

View File

@ -76,6 +76,10 @@ func (check *preflightCheckContext) qemuExecutable(ctx context.Context) error {
func (check *preflightCheckContext) checkFlashImages(ctx context.Context) error {
for _, flashImage := range check.arch.PFlash(check.options.UEFIEnabled) {
if len(flashImage.SourcePaths) == 0 {
continue
}
found := false
for _, path := range flashImage.SourcePaths {