diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml index 0ffe6b4..571ad85 100644 --- a/.github/workflows/ci.yaml +++ b/.github/workflows/ci.yaml @@ -26,6 +26,14 @@ jobs: test: true build: uses: ./.github/workflows/build.yaml + publish-node-installer-image: + uses: ./.github/workflows/node-installer.yaml + needs: build + # This action requires use of the GITHUB_TOKEN to publish the image + # By default, PRs from forks don't have access, so we only run when the PR branch is on origin. + if: ${{ ! github.event.pull_request.head.repo.fork }} + with: + ref: ${{ github.ref }} test: needs: build runs-on: ubuntu-latest diff --git a/.github/workflows/docker-build-push.yaml b/.github/workflows/docker-build-push.yaml index aa7b20b..a0382fe 100644 --- a/.github/workflows/docker-build-push.yaml +++ b/.github/workflows/docker-build-push.yaml @@ -26,7 +26,7 @@ jobs: steps: - uses: actions/checkout@v3 - name: Set RELEASE_VERSION ENV var - run: echo "RELEASE_VERSION=${GITHUB_REF:10}" >> $GITHUB_ENV + run: echo "RELEASE_VERSION=$(echo -n ${GITHUB_REF} | cut -d '/' -f 3)" >> $GITHUB_ENV - name: lowercase the runner OS name shell: bash run: | diff --git a/.github/workflows/node-installer.yaml b/.github/workflows/node-installer.yaml new file mode 100644 index 0000000..6517619 --- /dev/null +++ b/.github/workflows/node-installer.yaml @@ -0,0 +1,69 @@ +name: Publish node-installer image + +on: + workflow_call: + inputs: + ref: + description: 'the git ref for the associated workflow' + type: string + required: true + +jobs: + # Note: assumes being called in a workflow where build has already run and + # required artifacts have been uploaded + publish: + permissions: + contents: read + packages: write + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + + - name: Set RELEASE_VERSION env var + run: | + if [[ "${{ startsWith(inputs.ref, 'refs/tags/v')}}" == "true" ]]; then + echo "RELEASE_VERSION=$(echo -n ${{ inputs.ref }} | cut -d '/' -f 3)" >> $GITHUB_ENV + else + echo "RELEASE_VERSION=$(date +%Y%m%d-%H%M%S)-g$(git rev-parse --short HEAD)" >> $GITHUB_ENV + fi + + - uses: actions/download-artifact@v3 + with: + path: _artifacts + + # Setup buildx to build multiarch image: https://github.com/docker/build-push-action/blob/master/docs/advanced/multi-platform.md + - name: Set up QEMU + uses: docker/setup-qemu-action@v3 + + - name: setup buildx + uses: docker/setup-buildx-action@v2 + + - name: login to GitHub container registry + uses: docker/login-action@v2 + with: + registry: ghcr.io + username: ${{ github.actor }} + password: ${{ secrets.GITHUB_TOKEN }} + + # Build and push node-installer image + # TODO: remove once https://github.com/spinkube/runtime-class-manager handles this + - name: untar musl artifacts into ./node-installer/.tmp/linux/(amd64|arm64) dir + run: | + mkdir -p ./node-installer/.tmp/linux/amd64 + mkdir -p ./node-installer/.tmp/linux/arm64 + for f in ./_artifacts/*/*-x86_64.tar.gz; do tar -xf $f --directory ./node-installer/.tmp/linux/amd64; done + for f in ./_artifacts/*/*-aarch64.tar.gz; do tar -xf $f --directory ./node-installer/.tmp/linux/arm64; done + + - name: build and push node-installer image + uses: docker/build-push-action@v5 + with: + push: true + tags: | + ghcr.io/${{ github.repository }}/node-installer:${{ env.RELEASE_VERSION }} + context: node-installer + platforms: linux/amd64,linux/arm64 + + - name: clear + if: always() + run: | + rm -f ${HOME}/.docker/config.json diff --git a/.github/workflows/release.yaml b/.github/workflows/release.yaml index bd61368..a413893 100644 --- a/.github/workflows/release.yaml +++ b/.github/workflows/release.yaml @@ -1,6 +1,8 @@ name: release on: push: + branches: + - main tags: - "v[0-9]+.[0-9]+.*" jobs: @@ -12,31 +14,42 @@ jobs: with: test: false + publish-node-installer-image: + uses: ./.github/workflows/node-installer.yaml + needs: build + with: + ref: ${{ github.ref }} + release: permissions: contents: write packages: write needs: build - if: startsWith(github.ref, 'refs/tags/v') runs-on: ubuntu-latest steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 + - name: Set RELEASE_VERSION ENV var - run: echo "RELEASE_VERSION=${GITHUB_REF:10}" >> $GITHUB_ENV - - name: lowercase the runner OS name - shell: bash run: | - OS=$(echo "${{ runner.os }}" | tr '[:upper:]' '[:lower:]') - echo "RUNNER_OS=$OS" >> $GITHUB_ENV + if [[ "${{ startsWith(github.ref, 'refs/tags/v') }}" == "true" ]]; then + echo "RELEASE_VERSION=${{ github.ref_name }}" >> $GITHUB_ENV + else + echo "RELEASE_VERSION=$(date +%Y%m%d-%H%M%S)-g$(git rev-parse --short HEAD)" >> $GITHUB_ENV + fi + + - uses: actions/download-artifact@v3 + with: + path: _artifacts + - name: copy release workload assets into _dist + if: startsWith(github.ref, 'refs/tags/v') run: | mkdir -p _dist cp ./deployments/workloads/runtime.yaml _dist/runtime.yaml cp ./deployments/workloads/workload.yaml _dist/workload.yaml - - uses: actions/download-artifact@v3 - with: - path: _artifacts + - name: create release + if: startsWith(github.ref, 'refs/tags/v') env: GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} run: | @@ -51,8 +64,10 @@ jobs: # Setup buildx to build multiarch image: https://github.com/docker/build-push-action/blob/master/docs/advanced/multi-platform.md - name: Set up QEMU uses: docker/setup-qemu-action@v3 + - name: setup buildx uses: docker/setup-buildx-action@v2 + - name: login to GitHub container registry uses: docker/login-action@v2 with: @@ -67,17 +82,18 @@ jobs: mkdir -p ./deployments/k3d/.tmp/linux/arm64 for f in ./_artifacts/*/*-x86_64.tar.gz; do tar -xf $f --directory ./deployments/k3d/.tmp/linux/amd64; done for f in ./_artifacts/*/*-aarch64.tar.gz; do tar -xf $f --directory ./deployments/k3d/.tmp/linux/arm64; done + - name: build and push k3d shim image uses: docker/build-push-action@v5 with: push: true tags: | ghcr.io/${{ github.repository }}/k3d:${{ env.RELEASE_VERSION }} - ghcr.io/${{ github.repository }}/k3d:latest context: deployments/k3d platforms: linux/amd64,linux/arm64 build-args: | STAGE=release + - name: clear if: always() run: | diff --git a/node-installer/Dockerfile b/node-installer/Dockerfile new file mode 100644 index 0000000..ca7df49 --- /dev/null +++ b/node-installer/Dockerfile @@ -0,0 +1,5 @@ +FROM busybox +ARG TARGETPLATFORM +COPY script/installer.sh /script/installer.sh +COPY ./.tmp/${TARGETPLATFORM} /assets +CMD sh /script/installer.sh diff --git a/node-installer/Makefile b/node-installer/Makefile new file mode 100644 index 0000000..68d08fd --- /dev/null +++ b/node-installer/Makefile @@ -0,0 +1,18 @@ +SPIN_VERSION = v2 +IMAGE_NAME ?= ghcr.io/spinkube/containerd-shim-spin/node-installer +PLATFORM ?= linux/amd64 +ARCH ?= x86_64 +TARGET ?= $(ARCH)-unknown-linux-musl + +compile-musl: + make build-spin-cross-$(TARGET) -C ../ + +move-musl-to-tmp: compile-musl + mkdir -p ./.tmp + cp ../../containerd-shim-spin/target/$(TARGET)/release/containerd-shim-spin-$(SPIN_VERSION) ./.tmp/ + +build-multi-installer-image: move-musl-to-tmp + docker buildx build -t $(IMAGE_NAME) --platform linux/amd64,linux/arm64 . + +build-dev-installer-image: move-musl-to-tmp + docker buildx build -t $(IMAGE_NAME) --load --platform $(PLATFORM) . diff --git a/node-installer/README.md b/node-installer/README.md new file mode 100644 index 0000000..957fcb7 --- /dev/null +++ b/node-installer/README.md @@ -0,0 +1,9 @@ +This directory contains resources for a custom node-installer image +intended to be used in conjunction with the [Kwasm Operator](https://github.com/KWasm/kwasm-operator). + +This version of the image only contains the containerd-shim-spin-v2 shim, as +opposed to the default [kwasm-node-installer image](https://github.com/KWasm/kwasm-node-installer) +which also bundles other shims. + +The intention is for the [spinkube/runtime-class-manager](https://github.com/spinkube/runtime-class-manager) +project to handle this concern in the future. diff --git a/node-installer/script/installer.sh b/node-installer/script/installer.sh new file mode 100644 index 0000000..43ef011 --- /dev/null +++ b/node-installer/script/installer.sh @@ -0,0 +1,59 @@ +#!/usr/bin/env sh +set -euo pipefail + +# Based on https://github.com/KWasm/kwasm-node-installer/blob/main/script/installer.sh +# Distilled to only configuring the Spin shim + +KWASM_DIR=/opt/kwasm + +CONTAINERD_CONF=/etc/containerd/config.toml +IS_MICROK8S=false +IS_K3S=false +IS_RKE2_AGENT=false +if ps aux | grep kubelet | grep -q snap/microk8s; then + CONTAINERD_CONF=/var/snap/microk8s/current/args/containerd-template.toml + IS_MICROK8S=true + if nsenter -m/$NODE_ROOT/proc/1/ns/mnt -- ls /var/snap/microk8s/current/args/containerd-template.toml > /dev/null 2>&1 ;then + KWASM_DIR=/var/snap/microk8s/common/kwasm + else + echo "Installer seems to run on microk8s but 'containerd-template.toml' not found." + exit 1 + fi +elif ls $NODE_ROOT/var/lib/rancher/rke2/agent/etc/containerd/config.toml > /dev/null 2>&1 ; then + IS_RKE2_AGENT=true + cp $NODE_ROOT/var/lib/rancher/rke2/agent/etc/containerd/config.toml $NODE_ROOT/var/lib/rancher/rke2/agent/etc/containerd/config.toml.tmpl + CONTAINERD_CONF=/var/lib/rancher/rke2/agent/etc/containerd/config.toml.tmpl +elif ls $NODE_ROOT/var/lib/rancher/k3s/agent/etc/containerd/config.toml > /dev/null 2>&1 ; then + IS_K3S=true + cp $NODE_ROOT/var/lib/rancher/k3s/agent/etc/containerd/config.toml $NODE_ROOT/var/lib/rancher/k3s/agent/etc/containerd/config.toml.tmpl + CONTAINERD_CONF=/var/lib/rancher/k3s/agent/etc/containerd/config.toml.tmpl +fi + +mkdir -p $NODE_ROOT$KWASM_DIR/bin/ + +cp /assets/containerd-shim-spin-v2 $NODE_ROOT$KWASM_DIR/bin/ + +if ! grep -q spin $NODE_ROOT$CONTAINERD_CONF; then + echo ' +[plugins."io.containerd.grpc.v1.cri".containerd.runtimes.spin] + runtime_type = "'$KWASM_DIR'/bin/containerd-shim-spin-v2" +' >> $NODE_ROOT$CONTAINERD_CONF + rm -Rf $NODE_ROOT$KWASM_DIR/active +fi + +if [ ! -f $NODE_ROOT$KWASM_DIR/active ]; then + touch $NODE_ROOT$KWASM_DIR/active + if $IS_MICROK8S; then + nsenter -m/$NODE_ROOT/proc/1/ns/mnt -- systemctl restart snap.microk8s.daemon-containerd + elif ls $NODE_ROOT/etc/init.d/containerd > /dev/null 2>&1 ; then + nsenter --target 1 --mount --uts --ipc --net -- /etc/init.d/containerd restart + elif ls $NODE_ROOT/etc/init.d/k3s > /dev/null 2>&1 ; then + nsenter --target 1 --mount --uts --ipc --net -- /etc/init.d/k3s restart + elif $IS_RKE2_AGENT; then + nsenter --target 1 --mount --uts --ipc --net -- /bin/systemctl restart rke2-agent + else + nsenter -m/$NODE_ROOT/proc/1/ns/mnt -- /bin/systemctl restart containerd + fi +else + echo "No change in containerd/config.toml" +fi