diff --git a/README.md b/README.md index ba9aa3e962..ab459866b3 100644 --- a/README.md +++ b/README.md @@ -60,6 +60,7 @@ | [jdk](./images/jdk) | `cgr.dev/chainguard/jdk` | stable | [![](https://storage.googleapis.com/chainguard-images-build-outputs/badges/jdk.build.status.openjdk-17.svg)](https://registry-ui.chainguard.app/?image=cgr.dev/chainguard/jdk:openjdk-17) | | [jenkins](./images/jenkins) | `cgr.dev/chainguard/jenkins` | stable | [![](https://storage.googleapis.com/chainguard-images-build-outputs/badges/jenkins.build.status.latest.svg)](https://registry-ui.chainguard.app/?image=cgr.dev/chainguard/jenkins:latest) | | [jre](./images/jre) | `cgr.dev/chainguard/jre` | stable | [![](https://storage.googleapis.com/chainguard-images-build-outputs/badges/jre.build.status.openjdk-17.svg)](https://registry-ui.chainguard.app/?image=cgr.dev/chainguard/jre:openjdk-17) | +| [k3s](./images/k3s) | `cgr.dev/chainguard/k3s` | stable | [![](https://storage.googleapis.com/chainguard-images-build-outputs/badges/k3s.build.status.latest.svg)](https://registry-ui.chainguard.app/?image=cgr.dev/chainguard/k3s:latest) | | [k8s-sidecar](./images/k8s-sidecar) | `cgr.dev/chainguard/k8s-sidecar` | experimental | [![](https://storage.googleapis.com/chainguard-images-build-outputs/badges/k8s-sidecar.build.status.latest.svg)](https://registry-ui.chainguard.app/?image=cgr.dev/chainguard/k8s-sidecar:latest) | | [k8sgpt](./images/k8sgpt) | `cgr.dev/chainguard/k8sgpt` | stable | [![](https://storage.googleapis.com/chainguard-images-build-outputs/badges/k8sgpt.build.status.latest.svg)](https://registry-ui.chainguard.app/?image=cgr.dev/chainguard/k8sgpt:latest) | | [k8sgpt-operator](./images/k8sgpt-operator) | `cgr.dev/chainguard/k8sgpt-operator` | stable | [![](https://storage.googleapis.com/chainguard-images-build-outputs/badges/k8sgpt-operator.build.status.latest.svg)](https://registry-ui.chainguard.app/?image=cgr.dev/chainguard/k8sgpt-operator:latest) | diff --git a/images/k3s/README.md b/images/k3s/README.md new file mode 100644 index 0000000000..2963cfd87a --- /dev/null +++ b/images/k3s/README.md @@ -0,0 +1,40 @@ + +# k3s +| | | +| - | - | +| **Status** | stable | +| **OCI Reference** | `cgr.dev/chainguard/k3s` | + + +* [View Image in Chainguard Academy](https://edu.chainguard.dev/chainguard/chainguard-images/reference/k3s/overview/) +* [View Image Catalog](https://console.enforce.dev/images/catalog) for a full list of available tags. +*[Contact Chainguard](https://www.chainguard.dev/chainguard-images) for enterprise support, SLAs, and access to older tags.* + +--- + + +Minimal image with kubectl binary. **EXPERIMENTAL** + +## Get It! + +The image is available on `cgr.dev`: + +``` +docker pull cgr.dev/chainguard/k3s:latest +``` + +This image is a drop in replacement for the upstream `rancher/k3s` image, which means it works everywhere you would expect. + +The quickest way to test it is locally with `docker`: + +```bash +docker run --rm -v `pwd`:/etc/rancher/k3s --privileged -p 6443:6443 cgr.dev/chainguard/k3s:latest + +KUBECONFIG=k3s.yaml kubectl get po -A +``` + +You can also use it as a drop in replacement in `k3d`: + +```bash +k3d cluster create -i cgr.dev/chainguard/k3s:latest +``` diff --git a/images/k3s/configs/latest.apko.yaml b/images/k3s/configs/latest.apko.yaml new file mode 100644 index 0000000000..12157ec746 --- /dev/null +++ b/images/k3s/configs/latest.apko.yaml @@ -0,0 +1,42 @@ +contents: + packages: + - k3s + - mount + - umount + - kmod + # Optional features + - fuse-overlayfs + - fuse-overlayfs-snapshotter + # - btrfs-progs # TODO: This is relatively heavy, so only enable if eventually needed + +accounts: + groups: + - groupname: nonroot + gid: 65532 + users: + - username: nonroot + uid: 65532 + gid: 65532 + # TODO: Provide a nonroot variant with slirp4netns and rootlesskit + run-as: 0 + +paths: + - path: /etc/rancher + type: directory + uid: 65532 + gid: 65532 + permissions: 0o755 + recursive: true + +volumes: + - /var/lib/rancher/k3s + +entrypoint: + command: /bin/k3s +cmd: agent + +annotations: + "org.opencontainers.image.authors": "Chainguard Team https://www.chainguard.dev/" + "org.opencontainers.image.url": https://edu.chainguard.dev/chainguard/chainguard-images/reference/k3s/ + "org.opencontainers.image.source": https://github.com/chainguard-images/images/tree/main/images/k3s + diff --git a/images/k3s/configs/latest.embedded.apko.yaml b/images/k3s/configs/latest.embedded.apko.yaml new file mode 100644 index 0000000000..e9e3d89491 --- /dev/null +++ b/images/k3s/configs/latest.embedded.apko.yaml @@ -0,0 +1,38 @@ +contents: + packages: + - mount + - umount + - kmod + - k3s-embedded + +accounts: + groups: + - groupname: nonroot + gid: 65532 + users: + - username: nonroot + uid: 65532 + gid: 65532 + # TODO: Provide a nonroot variant with slirp4netns and rootlesskit + run-as: 0 + +paths: + - path: /etc/rancher + type: directory + uid: 65532 + gid: 65532 + permissions: 0o755 + recursive: true + +volumes: + - /var/lib/rancher/k3s + +entrypoint: + command: /bin/k3s +cmd: agent + +annotations: + "org.opencontainers.image.authors": "Chainguard Team https://www.chainguard.dev/" + "org.opencontainers.image.url": https://edu.chainguard.dev/chainguard/chainguard-images/reference/k3s/ + "org.opencontainers.image.source": https://github.com/chainguard-images/images/tree/main/images/k3s + diff --git a/images/k3s/configs/latest.images.apko.yaml b/images/k3s/configs/latest.images.apko.yaml new file mode 100644 index 0000000000..d9f7460784 --- /dev/null +++ b/images/k3s/configs/latest.images.apko.yaml @@ -0,0 +1,39 @@ +contents: + packages: + - mount + - umount + - kmod + - k3s + - k3s-images + +accounts: + groups: + - groupname: nonroot + gid: 65532 + users: + - username: nonroot + uid: 65532 + gid: 65532 + # TODO: Provide a nonroot variant with slirp4netns and rootlesskit + run-as: 0 + +paths: + - path: /etc/rancher + type: directory + uid: 65532 + gid: 65532 + permissions: 0o755 + recursive: true + +volumes: + - /var/lib/rancher/k3s + +entrypoint: + command: /bin/k3s +cmd: agent + +annotations: + "org.opencontainers.image.authors": "Chainguard Team https://www.chainguard.dev/" + "org.opencontainers.image.url": https://edu.chainguard.dev/chainguard/chainguard-images/reference/k3s/ + "org.opencontainers.image.source": https://github.com/chainguard-images/images/tree/main/images/k3s + diff --git a/images/k3s/embedded.tf b/images/k3s/embedded.tf new file mode 100644 index 0000000000..d1ee60a7eb --- /dev/null +++ b/images/k3s/embedded.tf @@ -0,0 +1,17 @@ +# embedded does not have a dev variant since the dev packages are already there +module "latest-embedded" { + source = "../../tflib/publisher" + target_repository = "${var.target_repository}-embedded" + config = file("${path.module}/configs/latest.embedded.apko.yaml") +} + +module "test-embedded" { + source = "./tests" + digest = module.latest-embedded.image_ref +} + +module "version-tags-embedded" { + source = "../../tflib/version-tags" + package = "k3s-embedded" + config = module.latest-embedded.config +} diff --git a/images/k3s/image.yaml b/images/k3s/image.yaml new file mode 100644 index 0000000000..b286ab5206 --- /dev/null +++ b/images/k3s/image.yaml @@ -0,0 +1,3 @@ +versions: + - apko: + config: configs/latest.apko.yaml diff --git a/images/k3s/main.tf b/images/k3s/main.tf new file mode 100644 index 0000000000..b2606863e8 --- /dev/null +++ b/images/k3s/main.tf @@ -0,0 +1,74 @@ +terraform { + required_providers { + apko = { source = "chainguard-dev/apko" } + } +} + +variable "target_repository" { + description = "The docker repo into which the image and attestations should be published." +} + +module "latest" { + source = "../../tflib/publisher" + + target_repository = var.target_repository + config = file("${path.module}/configs/latest.apko.yaml") +} + +module "dev" { source = "../../tflib/dev-subvariant" } + +module "latest-dev" { + source = "../../tflib/publisher" + target_repository = var.target_repository + config = jsonencode(module.latest.config) + extra_packages = concat(module.dev.extra_packages, [ + "crictl", + "kubectl", + "ctr", + ]) +} + +module "latest-images" { + source = "../../tflib/publisher" + target_repository = "${var.target_repository}-images" + config = file("${path.module}/configs/latest.images.apko.yaml") +} + +module "latest-images-dev" { + source = "../../tflib/publisher" + target_repository = "${var.target_repository}-images" + config = file("${path.module}/configs/latest.images.apko.yaml") + extra_packages = concat(module.dev.extra_packages, [ + "crictl", + "kubectl", + "ctr", + ]) +} + +module "version-tags" { + source = "../../tflib/version-tags" + package = "k3s" + config = module.latest.config +} + +module "test-latest" { + source = "./tests" + digest = module.latest.image_ref +} + +module "tagger" { + source = "../../tflib/tagger" + + depends_on = [ + module.test-latest, + module.test-embedded, + ] + + tags = merge( + { for t in toset(concat(["latest"], module.version-tags.tag_list)) : t => module.latest.image_ref }, + { for t in toset(concat(["latest"], module.version-tags.tag_list)) : "${t}-dev" => module.latest-dev.image_ref }, + { for t in toset(concat(["latest"], module.version-tags-embedded.tag_list)) : "${t}-embedded" => module.latest-embedded.image_ref }, + { for t in toset(concat(["latest"], module.version-tags.tag_list)) : "${t}-images" => module.latest-images.image_ref }, + { for t in toset(concat(["latest"], module.version-tags.tag_list)) : "${t}-images-dev" => module.latest-images-dev.image_ref }, + ) +} diff --git a/images/k3s/tests/main.tf b/images/k3s/tests/main.tf new file mode 100644 index 0000000000..a6ca28d5b9 --- /dev/null +++ b/images/k3s/tests/main.tf @@ -0,0 +1,14 @@ +terraform { + required_providers { + oci = { source = "chainguard-dev/oci" } + } +} + +variable "digest" { + description = "The image digest to run tests over." +} + +data "oci_exec_test" "test" { + digest = var.digest + script = "${path.module}/smoke.sh" +} diff --git a/images/k3s/tests/smoke.sh b/images/k3s/tests/smoke.sh new file mode 100755 index 0000000000..30ff473934 --- /dev/null +++ b/images/k3s/tests/smoke.sh @@ -0,0 +1,27 @@ +#!/usr/bin/env bash + +set -o errexit -o nounset -o errtrace -o pipefail -x + +uid="k3s-$FREE_PORT" +TMPDIR=$uid +mkdir -p $TMPDIR + +# Simple test to make sure the server comes up and has running pods after ~1m +docker run --name "$uid" -d --rm -it --privileged \ + -p $FREE_PORT:$FREE_PORT \ + -v $(pwd)/$TMPDIR:/etc/rancher/k3s/ \ + $IMAGE_NAME server --https-listen-port $FREE_PORT --write-kubeconfig-mode 0644 + +cleanup() { + rm -rf $TMPDIR + docker stop "$uid" -t 1 +} +trap cleanup EXIT + +# Wait just a hot second for the server to boot before we can kubectl +sleep 20 + +# Wait for the traefik jobs, to complete, this flexes pod creation as well as +# the svc lb creation, and more importantly, can fit into a kubectl wait +# oneliner +KUBECONFIG=$TMPDIR/k3s.yaml kubectl wait --for=condition=complete job --all -n kube-system --timeout=60s diff --git a/main.tf b/main.tf index 1df679a12f..cffe2eab98 100644 --- a/main.tf +++ b/main.tf @@ -332,6 +332,11 @@ module "jre" { target_repository = "${var.target_repository}/jre" } +module "k3s" { + source = "./images/k3s" + target_repository = "${var.target_repository}/k3s" +} + module "k8s-sidecar" { source = "./images/k8s-sidecar" target_repository = "${var.target_repository}/k8s-sidecar"