Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
91 changes: 91 additions & 0 deletions .github/workflows/build-azure-capi-image.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
name: Build Azure CAPI VM image

on:
workflow_dispatch:
inputs:
version:
description: Kuberentes version
required: true
type: string
tag:
description: ck8s-capi tag
required: true
type: string
builder_image:
description: image builder image
required: true
type: string
default: "ghcr.io/elastisys/image-builder-amd64:main"

workflow_call:
inputs:
version:
description: Kubernetes version
required: true
type: string
tag:
description: ck8s-capi tag
required: true
type: string
builder_image:
description: image builder image
required: true
type: string
default: "ghcr.io/elastisys/image-builder-amd64:main"

env:
version: ${{ inputs.version }}
tag: ${{ inputs.tag }}
docker_image: ${{ inputs.builder_image }}

defaults:
run:
working-directory: ./images/capi
shell: bash

jobs:
build-image:
runs-on: ubuntu-24.04
steps:
- name: Checkout repo
uses: actions/checkout@v5

- name: replace variables
run: |
package="${version}-1.1"
series="${version%.*}"

sed -r \
-e "s/\\\$KUBERNETES_SERIES/${series}/" \
-e "s/\\\$KUBERNETES_VERSION/${version}/" \
-e "s/\\\$KUBERNETES_DEB_VERSION/${package}/" \
-e "s/\\\$IMAGE_TAG/${tag}/" \
<"template.json" >"kubernetes.json"
Comment on lines +58 to +63

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is not envsubst available?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I just went into copying what we had done in other places.


- name: build azure image
run: |
image_name="ubuntu-2404-kube-${version%%-*}-ck8s-capi-${tag}"

export SIG_IMAGE_DEFINITION="${image_name}"
export SIG_PUBLISHER="elastisys"
export SIG_OFFER="ck8s-capi"
export SIG_SKU="${image_name}"

docker run -i --rm \
-e PACKER_VAR_FILES -e PACKER_GITHUB_API_TOKEN=${{ secrets.GITHUB_TOKEN }} \
-e SIG_IMAGE_DEFINITION -e SIG_PUBLISHER -e SIG_OFFER -e SIG_SKU \
-e AZURE_SUBSCRIPTION_ID -e AZURE_CLIENT_ID -e AZURE_CLIENT_SECRET -e AZURE_TENANT_ID -e AZURE_LOCATION \
-e RESOURCE_GROUP_NAME -e GALLERY_NAME -e BUILD_RESOURCE_GROUP_NAME \
-v ${{ github.workspace }}/images/capi:/tmp/host \
${{ env.docker_image }} build-azure-sig-ubuntu-2404-gen2
Comment on lines +74 to +80

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This looks odd, why do you have to start the container yourself instead of running it as a workflow job task?

Edit: Found multiple manual docker run executions that I don't understand why they couldn't be normal tasks. Please enlighten me! 😄

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There is this option where to run the job inside a container by default.
I tried it multiple times but i couldn't figure out why it did not work. So i opted out for the surefire method.


env:
PACKER_VAR_FILES: /tmp/host/kubernetes.json
AZURE_SUBSCRIPTION_ID: ${{ secrets.AZURE_SUBSCRIPTION_ID}}
AZURE_CLIENT_ID: ${{ secrets.AZURE_CLIENT_ID }}
AZURE_CLIENT_SECRET: ${{ secrets.AZURE_CLIENT_SECRET }}
AZURE_TENANT_ID: ${{ secrets.AZURE_TENANT_ID }}
AZURE_LOCATION: ${{ secrets.AZURE_LOCATION }}
RESOURCE_GROUP_NAME: ${{ secrets.RESOURCE_GROUP_NAME }}
GALLERY_NAME: ${{ secrets.GALLERY_NAME }}
BUILD_RESOURCE_GROUP_NAME: ${{ secrets.RESOURCE_GROUP_NAME }}
38 changes: 38 additions & 0 deletions .github/workflows/build-capi-vm-images.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
name: Build CAPI VM image with manual input

on:
workflow_dispatch:
inputs:
version:
description: k8s version
required: true
type: string
default: "1.33.1"
tag:
description: ck8s capi version
required: true
type: string
default: "0.8"
builder_image:
description: image builder image
required: true
type: string
default: "ghcr.io/elastisys/image-builder-amd64:main"

env:
PACKER_GITHUB_API_TOKEN: ${{ secrets.GITHUB_TOKEN }}

jobs:
build-azure-image:
uses: ./.github/workflows/build-azure-capi-image.yml
with:
version: ${{ inputs.version || '1.33.1' }}
tag: ${{ inputs.tag || '0.8' }}
docker_image: ${{ inputs.docker_image }}
secrets: inherit
build-openstack-image:
uses: ./.github/workflows/build-openstack-capi-image.yml
with:
version: ${{ inputs.version || '1.33.1' }}
tag: ${{ inputs.tag || '0.8' }}
docker_image: ${{ inputs.docker_image }}
45 changes: 45 additions & 0 deletions .github/workflows/build-image-builder.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
name: Build CAPI image builder

on:
push:
branches:
- main

env:
IMAGE_NAME: image-builder
REGISTRY: ghcr.io/elastisys

jobs:
build-image-builder:
runs-on: ubuntu-24.04
steps:
- uses: actions/checkout@v5

- name: get tag
id: get-tag
run: |
if [ "${{ github.event_name }}" == "pull_request" ]; then
PR_TITLE="${{ github.event.pull_request.title }}"
PR_TAG=$(echo "${PR_TITLE}" | sed -e 's/ /-/g')
echo "TAG=${PR_TAG}-${{ github.sha }}" >> $GITHUB_OUTPUT
else
echo "TAG=${GITHUB_REF##*/}-${{ github.sha }}" >> $GITHUB_OUTPUT
fi
shell: bash
Comment on lines +18 to +28

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This feels brittle. This assumes that everone will be good and name their PR correctly and we never change that policy.

Is it not possible to only trigger this on tags being pushed? Then you can also just rely on ${{ github.ref_name }}.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That part actually should be removed, as the image is not intended to be build from anything but main.
The file will be cleaned up accordingly.


- name: "Login to GitHub Container Registry"
uses: docker/login-action@v1
with:
registry: ghcr.io
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}

- name: run make docker-build
run: make docker-build
env:
TAG: ${{ steps.get-tag.outputs.TAG }}

- name: run make docker-push
run: make docker-push
env:
TAG: ${{ steps.get-tag.outputs.TAG }}
89 changes: 89 additions & 0 deletions .github/workflows/build-openstack-capi-image.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
name: Build OpenStack VM CAPI image

on:
workflow_dispatch:
inputs:
version:
description: Kubernetes version
required: true
type: string
tag:
description: ck8s-capi tag
required: true
type: string
builder_image:
description: image builder image
required: true
type: string
default: "ghcr.io/elastisys/image-builder-amd64:main"

workflow_call:
inputs:
version:
description: Kubernetes version
required: true
type: string
tag:
description: ck8s-capi tag
required: true
type: string
builder_image:
description: image builder image
required: true
type: string
default: "ghcr.io/elastisys/image-builder-amd64:main"


env:
version: ${{ inputs.version }}
tag: ${{ inputs.tag }}
docker_image: ${{ inputs.builder_image }}

defaults:
run:
working-directory: ./images/capi
shell: bash

jobs:
build-image:
runs-on: ubuntu-24.04

steps:
- uses: actions/checkout@v5

- name: Enable KVM
run: |
echo 'KERNEL=="kvm", GROUP="kvm", MODE="0666", OPTIONS+="static_node=kvm"' | sudo tee /etc/udev/rules.d/99-kvm4all.rules
sudo udevadm control --reload-rules
sudo udevadm trigger --name-match=kvm
Comment on lines +57 to +58
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Question: Could this also be incorporated into the image? I assume that this is running on the docker_image image now?

Same with other "apt install/pip install" in other workflows as well

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The building is running on the docker image, but it still needs the host machine to have kvm enabled to work as it is disabled by default on the runners.

the pip install was me trying to get the storing of image work on safespring before i realised its not a openstackclient version problem.

I also avoided modifying the docker_image to keep it as aligned from what is expected in upstream.

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Right, so this image is not running on another image. It's the builder that runs on the docker_image image?
If so, shouldn't you be able to build a custom image that already has this set (Like in this example ).

For this particular step it's not as critical since it's fast I guess, but for example this step should be possible to speed up and make more stable if we have a pre-created image with it already installed

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I have opted out of using that example as it caused so much headache when i tried it for the building part.
But i guess for that step it can be done so i can give it a try.


- name: replace variables
run: |
package="${version}-1.1"
series="${version%.*}"

sed -r \
-e "s/\\\$KUBERNETES_SERIES/${series}/" \
-e "s/\\\$KUBERNETES_VERSION/${version}/" \
-e "s/\\\$KUBERNETES_DEB_VERSION/${package}/" \
-e "s/\\\$IMAGE_TAG/${tag}/" \
<"template.json" >"kubernetes.json"
Comment on lines +65 to +70

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should use envsubst here as well


- name: add user
run: |
mkdir -p ${{ github.workspace }}/output
sudo useradd -ms /bin/bash imagebuilder
sudo chmod -R 777 ${{ github.workspace }}/output

- name: build openstack image
run: |
docker run --device=/dev/kvm -i --rm \
-e PACKER_VAR_FILES=/tmp/host/kubernetes.json -e PACKER_LOG -e PACKER_GITHUB_API_TOKEN=${{ secrets.GITHUB_TOKEN }} \
-v ${{ github.workspace }}/images/capi:/tmp/host -v ${{ github.workspace }}/output:/home/imagebuilder/output:rw \
${{ env.docker_image }} build-qemu-ubuntu-2404-efi

- name: store openstack image
uses: actions/upload-artifact@v4
with:
name: ubuntu-2404-efi-kube-${{ env.version }}-ck8s-capi-${{ env.tag }}
path: ${{ github.workspace }}/output/ubuntu-2404-efi-kube-${{ env.version }}-ck8s-capi-${{ env.tag }}
1 change: 1 addition & 0 deletions images/capi/.dockerignore
Original file line number Diff line number Diff line change
Expand Up @@ -9,3 +9,4 @@
!packer
!Makefile
!azure_targets.sh
!template.json
1 change: 1 addition & 0 deletions images/capi/Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,7 @@ COPY --chown=imagebuilder:imagebuilder hack hack/
COPY --chown=imagebuilder:imagebuilder packer packer/
COPY --chown=imagebuilder:imagebuilder Makefile Makefile
COPY --chown=imagebuilder:imagebuilder azure_targets.sh azure_targets.sh
COPY --chown=imagebuilder:imagebuilder template.json template.json

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm a little hesitant to merge this because Dockerfile and .dockerignore exists upstream and I want to avoid future conflicts if possible. If the files needs altering, maybe we can do it with a git patch or something like that and apply as part of the action?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I am not very familiar with the suggested method 😅

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Here's how you do it:

  1. Restore Dockerfile and .dockerignore
  2. Add the changes but don't commit
  3. git diff > patches/dockerfile.patch (lets use a dedicated dir that can be used for future patches too)
  4. To apply the changes when needed: git apply patches/dockerfile.patch

The idea is to commit the patch file which can then be applied in the GH action prior to every build. WDYT?


ENV PATH="/home/imagebuilder/.local/bin:${PATH}"
ENV PACKER_ARGS=''
Expand Down

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Empty file?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, it is needed it seems to ssh capabilty, copied it form https://github.com/elastisys/ck8s-cluster-api/blob/main/scripts/image/roles/sshca/README.md

Empty file.
18 changes: 18 additions & 0 deletions images/capi/ansible/roles/sshca/tasks/main.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
- name: add the ssh ca public key
ansible.builtin.copy:
dest: /etc/ssh/ssh_ca.pub
mode: "644"
src: ssh_ca.pub
- name: set authorized principals
ansible.builtin.copy:
dest: /etc/ssh/authorized_principals
# Couldn't get this to use the `ssh_username` variable
content: |
ubuntu
- name: add ssh ca settings
ansible.builtin.copy:
dest: /etc/ssh/sshd_config.d/ca.conf
content: |
TrustedUserCAKeys /etc/ssh/ssh_ca.pub
AuthorizedPrincipalsFile /etc/ssh/authorized_principals

38 changes: 38 additions & 0 deletions images/capi/template.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
{
"crictl_arch": "amd64",
"crictl_sha256": "https://github.com/kubernetes-sigs/cri-tools/releases/download/v{{user `crictl_version`}}/crictl-v{{user `crictl_version`}}-linux-{{user `crictl_arch`}}.tar.gz.sha256",
"crictl_source_type": "pkg",
"crictl_url": "https://github.com/kubernetes-sigs/cri-tools/releases/download/v{{user `crictl_version`}}/crictl-v{{user `crictl_version`}}-linux-{{user `crictl_arch`}}.tar.gz",
"crictl_version": "$KUBERNETES_SERIES.0",
"kubeadm_template": "etc/kubeadm.yml",
"kubernetes_apiserver_port": "6443",
"kubernetes_container_registry": "registry.k8s.io",
"kubernetes_deb_gpg_key": "https://pkgs.k8s.io/core:/stable:/{{ user `kubernetes_series` }}/deb/Release.key",
"kubernetes_deb_repo": "https://pkgs.k8s.io/core:/stable:/{{ user `kubernetes_series` }}/deb/",
"kubernetes_deb_version": "$KUBERNETES_DEB_VERSION",
"kubernetes_goarch": "amd64",
"kubernetes_http_source": "https://dl.k8s.io/release",
"kubernetes_load_additional_imgs": "false",
"kubernetes_rpm_gpg_check": "True",
"kubernetes_rpm_gpg_key": "https://pkgs.k8s.io/core:/stable:/{{ user `kubernetes_series` }}/rpm/repodata/repomd.xml.key",
"kubernetes_rpm_repo": "https://pkgs.k8s.io/core:/stable:/{{ user `kubernetes_series` }}/rpm/",
"kubernetes_rpm_repo_arch": "x86_64",
"kubernetes_rpm_version": "$KUBERNETES_VERSION",
"kubernetes_semver": "v$KUBERNETES_VERSION",
"kubernetes_series": "v$KUBERNETES_SERIES",
"kubernetes_source_type": "pkg",
"node_custom_roles_post": "sshca",
"systemd_prefix": "/usr/lib/systemd",
"sysusr_prefix": "/usr",
"sysusrlocal_prefix": "/usr/local",
"vm_name": "{{user `build_name`}}-kube-$KUBERNETES_VERSION-ck8s-capi-$IMAGE_TAG",
"artifact_name": "{{user `build_name`}}-kube-$KUBERNETES_VERSION-ck8s-capi-$IMAGE_TAG",
"output_directory": "./output/{{user `build_name`}}-kube-$KUBERNETES_VERSION-ck8s-capi-$IMAGE_TAG",
"image_name": "{{user `distribution`}}-{{user `distribution_version`}}-kube-$KUBERNETES_VERSION-ck8s-capi-$IMAGE_TAG",
"aws_region": "eu-north-1",
"ami_regions": "eu-north-1",
"ami_groups": "",
"snapshot_groups": "",
"containerd_version": "1.7.27",
"containerd_url": "https://github.com/containerd/containerd/releases/download/v1.7.27/containerd-1.7.27-linux-amd64.tar.gz"
}