From a72034c636047d21e0b87c3e86ac2298cbc555e7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Emmanuel=20Fr=C3=A9con?= Date: Sat, 2 Mar 2024 22:10:08 +0100 Subject: [PATCH 01/10] Add ubuntu to base image --- Dockerfile | 2 +- Dockerfile.base => Dockerfile.base.fedora | 0 Dockerfile.base.ubuntu | 11 + base/base.sh | 237 ++++++++++++++++------ 4 files changed, 183 insertions(+), 67 deletions(-) rename Dockerfile.base => Dockerfile.base.fedora (100%) create mode 100644 Dockerfile.base.ubuntu diff --git a/Dockerfile b/Dockerfile index ca9e619..5f37782 100644 --- a/Dockerfile +++ b/Dockerfile @@ -9,7 +9,7 @@ COPY runner/*.sh ${INSTALL_NAMESPACE}/bin/ # Redundant, but this makes this image more standalone. COPY lib/*.sh ${INSTALL_NAMESPACE}/lib/ RUN chmod a+x ${INSTALL_NAMESPACE}/bin/*.sh \ - && "${INSTALL_NAMESPACE}/bin/install.sh" -v -l /dev/stdout + && "${INSTALL_NAMESPACE}/bin/install.sh" -v ENTRYPOINT ["${INSTALL_NAMESPACE}/bin/entrypoint.sh"] CMD ["./bin/Runner.Listener", "run", "--startuptype", "service"] \ No newline at end of file diff --git a/Dockerfile.base b/Dockerfile.base.fedora similarity index 100% rename from Dockerfile.base rename to Dockerfile.base.fedora diff --git a/Dockerfile.base.ubuntu b/Dockerfile.base.ubuntu new file mode 100644 index 0000000..b8c4a67 --- /dev/null +++ b/Dockerfile.base.ubuntu @@ -0,0 +1,11 @@ +# syntax=docker/dockerfile:1 +ARG UBUNTU_VERSION=22.04 +FROM ubuntu:${UBUNTU_VERSION} + +ARG INSTALL_NAMESPACE=/opt/gh-runner-krunvm + +COPY base/*.sh ${INSTALL_NAMESPACE}/bin/ +COPY lib/*.sh ${INSTALL_NAMESPACE}/lib/ +RUN chmod a+x "${INSTALL_NAMESPACE}/bin/base.sh" \ + && "${INSTALL_NAMESPACE}/bin/base.sh" -dv +COPY base/root/ / diff --git a/base/base.sh b/base/base.sh index eed57a8..83d3a44 100755 --- a/base/base.sh +++ b/base/base.sh @@ -48,14 +48,10 @@ BASE_UID=${BASE_UID:-1001} BASE_GROUP=${BASE_GROUP:-runner} BASE_GID=${BASE_GID:-121} -# Name of the "sudo" group - wheel on Fedora, sudo on Ubuntu -BASE_SUDO=${BASE_SUDO:-"wheel"} BASE_DOCKER_WRAPPER=${BASE_DOCKER_WRAPPER:-$BASE_ROOTDIR/docker.sh} -# shellcheck disable=SC2034 # Used in sourced scripts KRUNVM_RUNNER_DESCR="Install a base GitHub runner environment in Fedora" - while getopts "dl:vh-" opt; do case "$opt" in d) # Install docker @@ -76,46 +72,114 @@ shift $((OPTIND-1)) KRUNVM_RUNNER_LOG=$BASE_LOG KRUNVM_RUNNER_VERBOSE=$BASE_VERBOSE +BASE_DISTRO=$(get_env /etc/os-release ID | to_lower) + +# Update the apt cache and install the packages passed as arguments. This is a +# convenience function to avoid repeating those lines over and over and to +# provide additional logging over those operations. +apt_install() { + debug "Installing apt packages: $*" + apt-get update + apt-get install -y "$@" +} + # TODO: locales? -verbose "Installing base packages" -dnf -y install \ - lsb-release \ - curl \ - tar \ - unzip \ - zip \ - sudo \ - ca-certificates \ - @development-tools \ - git-lfs \ - zlib-devel \ - zstd \ - gettext \ - libcurl-devel \ - iputils \ - jq \ - wget \ - dirmngr \ - openssh-clients \ - python3-pip \ - python3-setuptools \ - python3-virtualenv \ - python3 \ - dumb-init \ - procps \ - nodejs \ - rsync \ - libpq-devel \ - pkg-config \ - podman \ - buildah \ - skopeo \ - 'dnf-command(config-manager)' - -if [ "$BASE_DOCKER" = "1" ]; then +install_base() { + verbose "Installing base packages" + case "$BASE_DISTRO" in + fedora) + dnf -y install \ + lsb-release \ + curl \ + tar \ + unzip \ + zip \ + sudo \ + ca-certificates \ + @development-tools \ + git-lfs \ + zlib-devel \ + zstd \ + gettext \ + libcurl-devel \ + iputils \ + jq \ + wget \ + dirmngr \ + openssh-clients \ + python3-pip \ + python3-setuptools \ + python3-virtualenv \ + python3 \ + dumb-init \ + procps \ + nodejs \ + rsync \ + libpq-devel \ + pkg-config \ + podman \ + buildah \ + skopeo + ;; + ubuntu) + apt_install \ + lsb-release \ + curl \ + tar \ + unzip \ + zip \ + sudo \ + ca-certificates \ + build-essential \ + git-lfs \ + zlib1g-dev \ + zstd \ + gettext \ + libcurl4-openssl-dev \ + iputils-ping \ + jq \ + wget \ + dirmngr \ + openssh-client \ + python3-pip \ + python3-setuptools \ + python3-venv \ + python3 \ + dumb-init \ + procps \ + nodejs \ + rsync \ + libpq-dev \ + pkg-config \ + podman \ + buildah \ + skopeo + ;; + *) + error "Unsupported distribution: $BASE_DISTRO";; + esac +} + +install_docker() { verbose "Installing docker" - dnf -y config-manager --add-repo https://download.docker.com/linux/fedora/docker-ce.repo - dnf -y install docker-ce-cli docker-buildx-plugin docker-compose-plugin + case "$BASE_DISTRO" in + fedora) + dnf install 'dnf-command(config-manager)' + dnf -y config-manager --add-repo https://download.docker.com/linux/fedora/docker-ce.repo + dnf -y install docker-ce-cli docker-buildx-plugin docker-compose-plugin + ;; + ubuntu) + apt_install \ + apt-transport-https \ + gnupg-agent \ + software-properties-common + curl -fsSL https://download.docker.com/linux/ubuntu/gpg | apt-key add - + add-apt-repository "deb [arch=amd64] https://download.docker.com/linux/ubuntu $(lsb_release -cs) stable" + apt_install docker-ce docker-ce-cli containerd.io + ;; + *) + error "Unsupported distribution: $BASE_DISTRO";; + esac # Replace the real docker binary with our wrapper so we will be able to force # running containers on the host network. @@ -126,27 +190,68 @@ if [ "$BASE_DOCKER" = "1" ]; then mv -f "$docker" "${docker}.orig" verbose "Moved regular docker client to ${docker}.orig, installing wrapper from $BASE_DOCKER_WRAPPER instead" mv -f "$BASE_DOCKER_WRAPPER" "$docker" -fi - -verbose "Installing gh CLI" -dnf -y config-manager --add-repo https://cli.github.com/packages/rpm/gh-cli.repo -dnf -y install gh - -verbose "Installing yq" -wget -qO /usr/local/bin/yq https://github.com/mikefarah/yq/releases/latest/download/yq_linux_amd64 -chmod a+x /usr/local/bin/yq - -verbose "Creating user (${BASE_USER}:${BASE_UID}) and group (${BASE_GROUP}:${BASE_GID})" -groupadd --gid "$BASE_GID" "$BASE_GROUP" -useradd \ - --system \ - --create-home \ - --home-dir "/home/$BASE_USER" \ - --uid "$BASE_UID" \ - --gid "$BASE_GID" \ - "$BASE_USER" -usermod --append --groups "$BASE_SUDO" "$BASE_USER" -if [ "$BASE_DOCKER" = "1" ]; then - usermod --append --groups docker "$BASE_USER" -fi -printf '%%%s ALL=(ALL) NOPASSWD: ALL\n' "$BASE_SUDO">> /etc/sudoers +} + +install_gh() { + verbose "Installing GitHub CLI" + case "$BASE_DISTRO" in + fedora) + dnf -y install 'dnf-command(config-manager)' + dnf -y config-manager --add-repo https://cli.github.com/packages/rpm/gh-cli.repo + dnf -y install gh + ;; + ubuntu) + # shellcheck disable=SC2174 + mkdir -p -m 755 /etc/apt/keyrings + wget -qO- https://cli.github.com/packages/githubcli-archive-keyring.gpg | tee /etc/apt/keyrings/githubcli-archive-keyring.gpg > /dev/null + chmod go+r /etc/apt/keyrings/githubcli-archive-keyring.gpg + echo "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/githubcli-archive-keyring.gpg] https://cli.github.com/packages stable main" | tee /etc/apt/sources.list.d/github-cli.list > /dev/null + apt_install gh + ;; + *) + error "Unsupported distribution: $BASE_DISTRO";; + esac +} + +install_yq() { + verbose "Installing yq" + wget -qO /usr/local/bin/yq https://github.com/mikefarah/yq/releases/latest/download/yq_linux_amd64 + chmod a+x /usr/local/bin/yq +} + +create_user() { + verbose "Creating user (${BASE_USER}:${BASE_UID}) and group (${BASE_GROUP}:${BASE_GID})" + + # Name of the "sudo" group - wheel on Fedora, sudo on Ubuntu + case "$BASE_DISTRO" in + fedora) + BASE_SUDO=${BASE_SUDO:-"wheel"} + ;; + ubuntu) + BASE_SUDO=${BASE_SUDO:-"sudo"} + ;; + *) + error "Unsupported distribution: $BASE_DISTRO";; + esac + + groupadd --gid "$BASE_GID" "$BASE_GROUP" + useradd \ + --system \ + --create-home \ + --home-dir "/home/$BASE_USER" \ + --uid "$BASE_UID" \ + --gid "$BASE_GID" \ + "$BASE_USER" + usermod --append --groups "$BASE_SUDO" "$BASE_USER" + if [ "$BASE_DOCKER" = "1" ]; then + usermod --append --groups docker "$BASE_USER" + fi + printf '%%%s ALL=(ALL) NOPASSWD: ALL\n' "$BASE_SUDO">> /etc/sudoers +} + +install_base +[ "$BASE_DOCKER" = "1" ] && install_docker +install_gh +install_yq + +create_user From 822a0c944dde76f19247ff5b561ccebe0982fd0e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Emmanuel=20Fr=C3=A9con?= Date: Sun, 3 Mar 2024 20:04:48 +0100 Subject: [PATCH 02/10] Generate one image for each distro in dev --- .github/workflows/dev.yml | 13 ++++++++++--- Dockerfile | 3 ++- 2 files changed, 12 insertions(+), 4 deletions(-) diff --git a/.github/workflows/dev.yml b/.github/workflows/dev.yml index 1c2a121..c8002ce 100644 --- a/.github/workflows/dev.yml +++ b/.github/workflows/dev.yml @@ -8,9 +8,12 @@ on: jobs: build-base: uses: ./.github/workflows/_build.yml + strategy: + matrix: + os: [ubuntu, fedora] with: - image: ${{ github.actor }}/runner-krunvm-base - file: Dockerfile.base + image: ${{ github.actor }}/runner-krunvm-base-${{ matrix.os }} + file: Dockerfile.base.${{ matrix.os }} platforms: linux/amd64 secrets: username: ${{ github.actor }} @@ -20,12 +23,16 @@ jobs: needs: - build-base uses: ./.github/workflows/_build.yml + strategy: + matrix: + os: [ubuntu, fedora] with: - image: ${{ github.actor }}/runner-krunvm + image: ${{ github.actor }}/runner-krunvm-${{ matrix.os }} file: Dockerfile platforms: linux/amd64 build-args: | VERSION=${{ needs.build-base.outputs.version }} + DISTRO=${{ matrix.os }} secrets: username: ${{ github.actor }} password: ${{ secrets.GITHUB_TOKEN }} diff --git a/Dockerfile b/Dockerfile index 5f37782..aac794e 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,6 +1,7 @@ # syntax=docker/dockerfile:1 ARG VERSION=main -FROM ghcr.io/efrecon/runner-krunvm-base:${VERSION} +ARG DISTRO=fedora +FROM ghcr.io/efrecon/runner-krunvm-base-${DISTRO}:${VERSION} ARG INSTALL_VERSION=latest ARG INSTALL_NAMESPACE=/opt/gh-runner-krunvm From 2cd2255d6b974eaa62ba1c13760e8024c3751885 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Emmanuel=20Fr=C3=A9con?= Date: Sun, 3 Mar 2024 22:16:59 +0100 Subject: [PATCH 03/10] Enforce yes for dnf --- base/base.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/base/base.sh b/base/base.sh index 83d3a44..8a9cf8c 100755 --- a/base/base.sh +++ b/base/base.sh @@ -164,7 +164,7 @@ install_docker() { verbose "Installing docker" case "$BASE_DISTRO" in fedora) - dnf install 'dnf-command(config-manager)' + dnf -y install 'dnf-command(config-manager)' dnf -y config-manager --add-repo https://download.docker.com/linux/fedora/docker-ce.repo dnf -y install docker-ce-cli docker-buildx-plugin docker-compose-plugin ;; From dfcec9c9264eee7a6fa2c9119fdc3459186f8028 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Emmanuel=20Fr=C3=A9con?= Date: Mon, 4 Mar 2024 18:50:15 +0100 Subject: [PATCH 04/10] Build main image <= ubuntu+fedora --- .github/workflows/ci.yml | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index a5bf6e7..05c978e 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -8,9 +8,12 @@ on: jobs: build-base: uses: ./.github/workflows/_build.yml + strategy: + matrix: + os: [ubuntu, fedora] with: - image: ${{ github.actor }}/runner-krunvm-base - file: Dockerfile.base + image: ${{ github.actor }}/runner-krunvm-base-${{ matrix.os }} + file: Dockerfile.base.${{ matrix.os }} secrets: username: ${{ github.actor }} password: ${{ secrets.GITHUB_TOKEN }} @@ -19,11 +22,15 @@ jobs: needs: - build-base uses: ./.github/workflows/_build.yml + strategy: + matrix: + os: [ubuntu, fedora] with: - image: ${{ github.actor }}/runner-krunvm + image: ${{ github.actor }}/runner-krunvm-${{ matrix.os }} file: Dockerfile build-args: | VERSION=${{ needs.build-base.outputs.version }} + DISTRO=${{ matrix.os }} secrets: username: ${{ github.actor }} password: ${{ secrets.GITHUB_TOKEN }} From 08f73c7f3bd282e629ce1691deef6eaf8c9c8369 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Emmanuel=20Fr=C3=A9con?= Date: Wed, 6 Mar 2024 22:58:37 +0100 Subject: [PATCH 05/10] Add storage conf to force overlayfs --- base/root/etc/containers/storage.conf | 247 ++++++++++++++++++++++++++ 1 file changed, 247 insertions(+) create mode 100644 base/root/etc/containers/storage.conf diff --git a/base/root/etc/containers/storage.conf b/base/root/etc/containers/storage.conf new file mode 100644 index 0000000..c4edd45 --- /dev/null +++ b/base/root/etc/containers/storage.conf @@ -0,0 +1,247 @@ +# This file is the configuration file for all tools +# that use the containers/storage library. The storage.conf file +# overrides all other storage.conf files. Container engines using the +# container/storage library do not inherit fields from other storage.conf +# files. +# +# Note: The storage.conf file overrides other storage.conf files based on this precedence: +# /usr/containers/storage.conf +# /etc/containers/storage.conf +# $HOME/.config/containers/storage.conf +# $XDG_CONFIG_HOME/containers/storage.conf (If XDG_CONFIG_HOME is set) +# See man 5 containers-storage.conf for more information +# The "container storage" table contains all of the server options. +[storage] + +# Default Storage Driver, Must be set for proper operation. +driver = "overlay" + +# Temporary storage location +runroot = "/run/containers/storage" + +# Primary Read/Write location of container storage +# When changing the graphroot location on an SELINUX system, you must +# ensure the labeling matches the default locations labels with the +# following commands: +# semanage fcontext -a -e /var/lib/containers/storage /NEWSTORAGEPATH +# restorecon -R -v /NEWSTORAGEPATH +graphroot = "/var/lib/containers/storage" + +# Optional alternate location of image store if a location separate from the +# container store is required. If set, it must be different than graphroot. +# imagestore = "" + + +# Storage path for rootless users +# +# rootless_storage_path = "$HOME/.local/share/containers/storage" + +# Transient store mode makes all container metadata be saved in temporary storage +# (i.e. runroot above). This is faster, but doesn't persist across reboots. +# Additional garbage collection must also be performed at boot-time, so this +# option should remain disabled in most configurations. +# transient_store = true + +[storage.options] +# Storage options to be passed to underlying storage drivers + +# AdditionalImageStores is used to pass paths to additional Read/Only image stores +# Must be comma separated list. +#additionalimagestores = [ +#"/usr/lib/containers/storage", +#] + +# Allows specification of how storage is populated when pulling images. This +# option can speed the pulling process of images compressed with format +# zstd:chunked. Containers/storage looks for files within images that are being +# pulled from a container registry that were previously pulled to the host. It +# can copy or create a hard link to the existing file when it finds them, +# eliminating the need to pull them from the container registry. These options +# can deduplicate pulling of content, disk storage of content and can allow the +# kernel to use less memory when running containers. + +# containers/storage supports three keys +# * enable_partial_images="true" | "false" +# Tells containers/storage to look for files previously pulled in storage +# rather then always pulling them from the container registry. +# * use_hard_links = "false" | "true" +# Tells containers/storage to use hard links rather then create new files in +# the image, if an identical file already existed in storage. +# * ostree_repos = "" +# Tells containers/storage where an ostree repository exists that might have +# previously pulled content which can be used when attempting to avoid +# pulling content from the container registry +pull_options = {enable_partial_images = "true", use_hard_links = "false", ostree_repos=""} + +# Remap-UIDs/GIDs is the mapping from UIDs/GIDs as they should appear inside of +# a container, to the UIDs/GIDs as they should appear outside of the container, +# and the length of the range of UIDs/GIDs. Additional mapped sets can be +# listed and will be heeded by libraries, but there are limits to the number of +# mappings which the kernel will allow when you later attempt to run a +# container. +# +# remap-uids = "0:1668442479:65536" +# remap-gids = "0:1668442479:65536" + +# Remap-User/Group is a user name which can be used to look up one or more UID/GID +# ranges in the /etc/subuid or /etc/subgid file. Mappings are set up starting +# with an in-container ID of 0 and then a host-level ID taken from the lowest +# range that matches the specified name, and using the length of that range. +# Additional ranges are then assigned, using the ranges which specify the +# lowest host-level IDs first, to the lowest not-yet-mapped in-container ID, +# until all of the entries have been used for maps. This setting overrides the +# Remap-UIDs/GIDs setting. +# +# remap-user = "containers" +# remap-group = "containers" + +# Root-auto-userns-user is a user name which can be used to look up one or more UID/GID +# ranges in the /etc/subuid and /etc/subgid file. These ranges will be partitioned +# to containers configured to create automatically a user namespace. Containers +# configured to automatically create a user namespace can still overlap with containers +# having an explicit mapping set. +# This setting is ignored when running as rootless. +# root-auto-userns-user = "storage" +# +# Auto-userns-min-size is the minimum size for a user namespace created automatically. +# auto-userns-min-size=1024 +# +# Auto-userns-max-size is the maximum size for a user namespace created automatically. +# auto-userns-max-size=65536 + +[storage.options.overlay] +# ignore_chown_errors can be set to allow a non privileged user running with +# a single UID within a user namespace to run containers. The user can pull +# and use any image even those with multiple uids. Note multiple UIDs will be +# squashed down to the default uid in the container. These images will have no +# separation between the users in the container. Only supported for the overlay +# and vfs drivers. +#ignore_chown_errors = "false" + +# Inodes is used to set a maximum inodes of the container image. +# inodes = "" + +# Path to an helper program to use for mounting the file system instead of mounting it +# directly. +mount_program = "/usr/bin/fuse-overlayfs" + +# mountopt specifies comma separated list of extra mount options +mountopt = "nodev,metacopy=on" + +# Set to skip a PRIVATE bind mount on the storage home directory. +# skip_mount_home = "false" + +# Set to use composefs to mount data layers with overlay. +# use_composefs = "false" + +# Size is used to set a maximum size of the container image. +# size = "" + +# ForceMask specifies the permissions mask that is used for new files and +# directories. +# +# The values "shared" and "private" are accepted. +# Octal permission masks are also accepted. +# +# "": No value specified. +# All files/directories, get set with the permissions identified within the +# image. +# "private": it is equivalent to 0700. +# All files/directories get set with 0700 permissions. The owner has rwx +# access to the files. No other users on the system can access the files. +# This setting could be used with networked based homedirs. +# "shared": it is equivalent to 0755. +# The owner has rwx access to the files and everyone else can read, access +# and execute them. This setting is useful for sharing containers storage +# with other users. For instance have a storage owned by root but shared +# to rootless users as an additional store. +# NOTE: All files within the image are made readable and executable by any +# user on the system. Even /etc/shadow within your image is now readable by +# any user. +# +# OCTAL: Users can experiment with other OCTAL Permissions. +# +# Note: The force_mask Flag is an experimental feature, it could change in the +# future. When "force_mask" is set the original permission mask is stored in +# the "user.containers.override_stat" xattr and the "mount_program" option must +# be specified. Mount programs like "/usr/bin/fuse-overlayfs" present the +# extended attribute permissions to processes within containers rather than the +# "force_mask" permissions. +# +force_mask = "" + +[storage.options.thinpool] +# Storage Options for thinpool + +# autoextend_percent determines the amount by which pool needs to be +# grown. This is specified in terms of % of pool size. So a value of 20 means +# that when threshold is hit, pool will be grown by 20% of existing +# pool size. +# autoextend_percent = "20" + +# autoextend_threshold determines the pool extension threshold in terms +# of percentage of pool size. For example, if threshold is 60, that means when +# pool is 60% full, threshold has been hit. +# autoextend_threshold = "80" + +# basesize specifies the size to use when creating the base device, which +# limits the size of images and containers. +# basesize = "10G" + +# blocksize specifies a custom blocksize to use for the thin pool. +# blocksize="64k" + +# directlvm_device specifies a custom block storage device to use for the +# thin pool. Required if you setup devicemapper. +# directlvm_device = "" + +# directlvm_device_force wipes device even if device already has a filesystem. +# directlvm_device_force = "True" + +# fs specifies the filesystem type to use for the base device. +# fs="xfs" + +# log_level sets the log level of devicemapper. +# 0: LogLevelSuppress 0 (Default) +# 2: LogLevelFatal +# 3: LogLevelErr +# 4: LogLevelWarn +# 5: LogLevelNotice +# 6: LogLevelInfo +# 7: LogLevelDebug +# log_level = "7" + +# min_free_space specifies the min free space percent in a thin pool require for +# new device creation to succeed. Valid values are from 0% - 99%. +# Value 0% disables +# min_free_space = "10%" + +# mkfsarg specifies extra mkfs arguments to be used when creating the base +# device. +# mkfsarg = "" + +# metadata_size is used to set the `pvcreate --metadatasize` options when +# creating thin devices. Default is 128k +# metadata_size = "" + +# Size is used to set a maximum size of the container image. +# size = "" + +# use_deferred_removal marks devicemapper block device for deferred removal. +# If the thinpool is in use when the driver attempts to remove it, the driver +# tells the kernel to remove it as soon as possible. Note this does not free +# up the disk space, use deferred deletion to fully remove the thinpool. +# use_deferred_removal = "True" + +# use_deferred_deletion marks thinpool device for deferred deletion. +# If the device is busy when the driver attempts to delete it, the driver +# will attempt to delete device every 30 seconds until successful. +# If the program using the driver exits, the driver will continue attempting +# to cleanup the next time the driver is used. Deferred deletion permanently +# deletes the device and all data stored in device will be lost. +# use_deferred_deletion = "True" + +# xfs_nospace_max_retries specifies the maximum number of retries XFS should +# attempt to complete IO when ENOSPC (no space) error is returned by +# underlying storage device. +# xfs_nospace_max_retries = "0" From 3bf83715b51f29b31852cf086722a21e26feab38 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Emmanuel=20Fr=C3=A9con?= Date: Wed, 6 Mar 2024 22:58:50 +0100 Subject: [PATCH 06/10] Upgrade ubuntu --- Dockerfile.base.ubuntu | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Dockerfile.base.ubuntu b/Dockerfile.base.ubuntu index b8c4a67..916c159 100644 --- a/Dockerfile.base.ubuntu +++ b/Dockerfile.base.ubuntu @@ -1,5 +1,5 @@ # syntax=docker/dockerfile:1 -ARG UBUNTU_VERSION=22.04 +ARG UBUNTU_VERSION=24.04 FROM ubuntu:${UBUNTU_VERSION} ARG INSTALL_NAMESPACE=/opt/gh-runner-krunvm From a1adbf18d2d054d340ccc72c6e605e1292688e52 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Emmanuel=20Fr=C3=A9con?= Date: Wed, 6 Mar 2024 23:36:14 +0100 Subject: [PATCH 07/10] Downgrade to 23.10, waiting for docker --- Dockerfile.base.ubuntu | 2 +- base/base.sh | 13 +++++-------- 2 files changed, 6 insertions(+), 9 deletions(-) diff --git a/Dockerfile.base.ubuntu b/Dockerfile.base.ubuntu index 916c159..cc229fe 100644 --- a/Dockerfile.base.ubuntu +++ b/Dockerfile.base.ubuntu @@ -1,5 +1,5 @@ # syntax=docker/dockerfile:1 -ARG UBUNTU_VERSION=24.04 +ARG UBUNTU_VERSION=23.10 FROM ubuntu:${UBUNTU_VERSION} ARG INSTALL_NAMESPACE=/opt/gh-runner-krunvm diff --git a/base/base.sh b/base/base.sh index 8a9cf8c..37d0b09 100755 --- a/base/base.sh +++ b/base/base.sh @@ -169,12 +169,10 @@ install_docker() { dnf -y install docker-ce-cli docker-buildx-plugin docker-compose-plugin ;; ubuntu) - apt_install \ - apt-transport-https \ - gnupg-agent \ - software-properties-common - curl -fsSL https://download.docker.com/linux/ubuntu/gpg | apt-key add - - add-apt-repository "deb [arch=amd64] https://download.docker.com/linux/ubuntu $(lsb_release -cs) stable" + install -m 755 -d /etc/apt/keyrings + wget -qO- https://download.docker.com/linux/ubuntu/gpg | tee /etc/apt/keyrings/docker.asc > /dev/null + chmod a+r /etc/apt/keyrings/docker.asc + echo "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.asc] https://download.docker.com/linux/ubuntu $(. /etc/os-release && echo "$VERSION_CODENAME") stable" | tee /etc/apt/sources.list.d/docker.list > /dev/null apt_install docker-ce docker-ce-cli containerd.io ;; *) @@ -201,8 +199,7 @@ install_gh() { dnf -y install gh ;; ubuntu) - # shellcheck disable=SC2174 - mkdir -p -m 755 /etc/apt/keyrings + install -m 755 -d /etc/apt/keyrings wget -qO- https://cli.github.com/packages/githubcli-archive-keyring.gpg | tee /etc/apt/keyrings/githubcli-archive-keyring.gpg > /dev/null chmod go+r /etc/apt/keyrings/githubcli-archive-keyring.gpg echo "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/githubcli-archive-keyring.gpg] https://cli.github.com/packages stable main" | tee /etc/apt/sources.list.d/github-cli.list > /dev/null From a6f369df0499f5cbe4c840fbaca1efa2acc6492d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Emmanuel=20Fr=C3=A9con?= Date: Thu, 7 Mar 2024 22:43:57 +0100 Subject: [PATCH 08/10] Add docker to test --- .github/workflows/test.yml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 9cb0bc4..204e28e 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -22,3 +22,7 @@ jobs: echo "" echo "RUNNER_ variables" env | grep RUNNER_ + echo "" + echo "Docker Containers" + docker ps -a + docker run --rm hello-world From cd32229366aac664177908c2f61ba46efeab4e1b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Emmanuel=20Fr=C3=A9con?= Date: Thu, 7 Mar 2024 23:09:35 +0100 Subject: [PATCH 09/10] Make Ubuntu default --- runner.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/runner.sh b/runner.sh index 23f2fde..e2c1625 100755 --- a/runner.sh +++ b/runner.sh @@ -40,7 +40,7 @@ RUNNER_VERBOSE=${RUNNER_VERBOSE:-0} RUNNER_LOG=${RUNNER_LOG:-2} # Name of the OCI image (fully-qualified) to use. You need to have access. -RUNNER_IMAGE=${RUNNER_IMAGE:-"ghcr.io/efrecon/runner-krunvm:main"} +RUNNER_IMAGE=${RUNNER_IMAGE:-"ghcr.io/efrecon/runner-krunvm-ubuntu:main"} # Memory to allocate to the VM (in MB). Regular runners use more than the # default. From 07ab1270544073787785f6c04b188468bb00eb96 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Emmanuel=20Fr=C3=A9con?= Date: Thu, 7 Mar 2024 23:09:47 +0100 Subject: [PATCH 10/10] Document ubuntu --- README.md | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/README.md b/README.md index d3f4e26..9c3dc49 100644 --- a/README.md +++ b/README.md @@ -5,14 +5,16 @@ This project creates [self-hosted][self] (ephemeral) GitHub [runners] based on [runners] inside your infrastruture, as opposed to [solutions] based on Kubernetes or Docker containers. MicroVMs boot fast, providing an experience close to running containers. [krunvm] creates and starts VMs based on the -multi-platform OCI [images][image] created for this project. +multi-platform OCI images created for this project -- [ubuntu] (default) or +[fedora]. [self]: https://docs.github.com/en/actions/hosting-your-own-runners/managing-self-hosted-runners/about-self-hosted-runners [runners]: https://docs.github.com/en/actions/using-github-hosted-runners/about-github-hosted-runners/about-github-hosted-runners [krunvm]: https://github.com/containers/krunvm [microVM]: https://github.com/infracloudio/awesome-microvm [solutions]: https://github.com/jonico/awesome-runners - [image]: https://github.com/efrecon/gh-runner-krunvm/pkgs/container/runner-krunvm + [ubuntu]: https://github.com/efrecon/gh-runner-krunvm/pkgs/container/runner-krunvm-ubuntu + [fedora]: https://github.com/efrecon/gh-runner-krunvm/pkgs/container/runner-krunvm-fedora ## Example @@ -33,7 +35,7 @@ the value of the token, nor the value of the runner registration token will be visible to the workflows using your runners. The default is to create far-less capable runners than the GitHub [runners], i.e. 1G or memory and 2 vCPUs. Unless otherwise specified, runners have random names and carry labels with the name of -the base repository, e.g. `fedora` and `krunvm`. The GitHub runner +the base repository, e.g. `ubuntu` and `krunvm`. The GitHub runner implementation will automatically add other labels in addition to those. In the example above, the double-dash `--` separates options given to the @@ -95,8 +97,6 @@ installed on the host. Installation is easiest on Fedora ## Limitations + Linux host installation easiest on Fedora -+ Runners are (also) based on Fedora. While standard images are based on Fedora, - running on top of ubuntu should also be possible. + Inside the runners: Docker not supported. Replaced by `podman` in [emulation] mode. + Inside the runners: No support for docker network, containers run in "host" @@ -117,11 +117,11 @@ will be created. The OCI image is built in two parts: -+ The [base](./Dockerfile.base) image installs a minimal set of binaries and ++ The base images -- [fedora](./Dockerfile.base.fedora) and + [ubuntu](./Dockerfile.base.ubuntu) -- install a minimal set of binaries and packages, both the ones necessary to execute the runner, but also a sane minimal default for workflows. Regular GitHub [runners] have a wide number of - installed packages. The base image has much less. Also note that it is based - on Fedora, rather than Ubuntu. + installed packages. The base images have much less. + The [main](./Dockerfile) installs the runner binaries and scripts and creates a directory structure that is used by the rest of the project.