|
| 1 | +# Development Guide |
| 2 | + |
| 3 | +This document explains how the system-agent-installer-k3s image is built in CI and how to build it locally for development and testing. |
| 4 | + |
| 5 | +## Project Overview |
| 6 | + |
| 7 | +This repository builds a minimal Docker image that packages: |
| 8 | +- K3s binary (the Kubernetes distribution) |
| 9 | +- K3s install script |
| 10 | +- SHA256 checksums for verification |
| 11 | +- A runtime script (`run.sh`) that handles installation on target hosts |
| 12 | + |
| 13 | +The final image is built `FROM scratch`, containing only these essential files. |
| 14 | + |
| 15 | +## Architecture |
| 16 | + |
| 17 | +### Key Files |
| 18 | + |
| 19 | +| File | Purpose | |
| 20 | +|------|---------| |
| 21 | +| `scripts/version` | Determines the K3s version/tag to build; sets VERSION, URI_VERSION, IMAGE variables | |
| 22 | +| `scripts/download` | Downloads K3s binary + installer script from GitHub releases (or private PRIME_RIBS server) | |
| 23 | +| `scripts/publish-manifest` | Creates a multi-architecture Docker manifest for both linux/amd64 and linux/arm64 | |
| 24 | +| `package/Dockerfile` | The product Dockerfile; builds the final scratch image with artifacts | |
| 25 | +| `package/run.sh` | Runtime entrypoint; copies K3s binary to host and runs the installer | |
| 26 | +| `Makefile` | Provides `push-image` and `publish-manifest` targets for CI; contains platform detection | |
| 27 | + |
| 28 | +### CI Build Process |
| 29 | + |
| 30 | +The repository uses **GitHub Actions** for all CI/CD: |
| 31 | + |
| 32 | +#### Release Workflow (`.github/workflows/release.yaml`) |
| 33 | + |
| 34 | +Triggered when a GitHub release is published: |
| 35 | + |
| 36 | +1. **Per-architecture build** (matrix: amd64, arm64): |
| 37 | + - Checkout code |
| 38 | + - Set `ARCH`, `OS`, `GIT_TAG` environment variables |
| 39 | + - Run `scripts/download` to fetch K3s artifacts into `artifacts/` directory |
| 40 | + - Load credentials from Vault (Docker Hub, Prime registries) |
| 41 | + - Run `make push-image` to build and push to: |
| 42 | + - Docker Hub (`rancher/system-agent-installer-k3s:TAG-linux-ARCH`) |
| 43 | + - Rancher Prime Staging registry |
| 44 | + - Rancher Prime Production registry (non-RC releases only) |
| 45 | + |
| 46 | +2. **Multi-architecture manifest** (runs after per-arch builds): |
| 47 | + - Source `scripts/version` to determine the IMAGE tag |
| 48 | + - Run `make publish-manifest` to create a multi-arch manifest linking both per-arch images |
| 49 | + - Manifest is pushed to all three registries |
| 50 | + |
| 51 | +#### Pull Request CI (`.github/workflows/ci-on-pull-request.yaml`) |
| 52 | + |
| 53 | +Triggered on every pull request: |
| 54 | + |
| 55 | +1. **Per-architecture validation** (matrix: amd64, arm64): |
| 56 | + - Checkout code |
| 57 | + - Set `ARCH`, `OS` environment variables |
| 58 | + - Run `scripts/download` to fetch K3s artifacts |
| 59 | + - Set up QEMU and Docker Buildx for cross-platform builds |
| 60 | + - Run `docker/build-push-action` with `--load` to build locally (no push to registry) |
| 61 | + - Inspect the built image |
| 62 | + |
| 63 | +#### Automated Version Detection (`.github/workflows/watch-k3s-releases.yml`) |
| 64 | + |
| 65 | +Runs every 2 hours (or manually) to detect new K3s releases and automatically create GitHub releases, which triggers the Release workflow above. |
| 66 | + |
| 67 | +## Local Development: Building Images |
| 68 | + |
| 69 | +### Prerequisites |
| 70 | + |
| 71 | +- Docker with Buildx support (`docker buildx` available) |
| 72 | +- `bash`, `curl`, `jq` installed |
| 73 | +- Git (for version detection fallback) |
| 74 | + |
| 75 | +### Determine the K3s Version |
| 76 | + |
| 77 | +The `scripts/version` script determines what version to build. It uses this priority order: |
| 78 | + |
| 79 | +1. **Environment variable `TAG`** (e.g., `TAG=v1.30.0+k3s1`) |
| 80 | +2. **GitHub Actions environment** (via `GITHUB_TAG`, `GITHUB_REF_NAME`) |
| 81 | +3. **Query GitHub API** for the latest K3s release |
| 82 | +4. **Fallback** to `FALLBACK_VERSION` (defined in `scripts/version`) |
| 83 | + |
| 84 | +### Option 1: Build for Your Local Machine |
| 85 | + |
| 86 | +Build a single-arch image that matches your machine's architecture (amd64 or arm64) and load it into your local Docker daemon: |
| 87 | + |
| 88 | +```bash |
| 89 | +# Step 1: Download K3s artifacts |
| 90 | +TAG=v1.30.0+k3s1 ./scripts/download |
| 91 | + |
| 92 | +# Step 2: Build locally with docker buildx |
| 93 | +TAG=v1.30.0+k3s1 docker buildx build \ |
| 94 | + --platform linux/$(uname -m | sed 's/x86_64/amd64/' | sed 's/aarch64/arm64/') \ |
| 95 | + --build-arg TAG=v1.30.0+k3s1 \ |
| 96 | + --tag rancher/system-agent-installer-k3s:v1.30.0-k3s1 \ |
| 97 | + --load \ |
| 98 | + --file ./package/Dockerfile \ |
| 99 | + . |
| 100 | + |
| 101 | +# Step 3: Inspect the built image |
| 102 | +docker inspect rancher/system-agent-installer-k3s:v1.30.0-k3s1 |
| 103 | +``` |
| 104 | + |
| 105 | +### Option 2: Build for a Specific Architecture |
| 106 | + |
| 107 | +Build for a specific architecture using QEMU: |
| 108 | + |
| 109 | +```bash |
| 110 | +# Download artifacts for the target architecture |
| 111 | +TAG=v1.30.0+k3s1 ARCH=arm64 ./scripts/download |
| 112 | + |
| 113 | +# Build for arm64 (even if you're on amd64) |
| 114 | +TAG=v1.30.0+k3s1 docker buildx build \ |
| 115 | + --platform linux/arm64 \ |
| 116 | + --build-arg TAG=v1.30.0+k3s1 \ |
| 117 | + --tag rancher/system-agent-installer-k3s:v1.30.0-k3s1-linux-arm64 \ |
| 118 | + --load \ |
| 119 | + --file ./package/Dockerfile \ |
| 120 | + . |
| 121 | +``` |
| 122 | + |
| 123 | +### Option 3: Build Multi-arch Image (Same as CI) |
| 124 | + |
| 125 | +Build for both amd64 and arm64, then create a manifest (requires `docker buildx` and appropriate Docker credentials if pushing): |
| 126 | + |
| 127 | +```bash |
| 128 | +# Build amd64 |
| 129 | +TAG=v1.30.0+k3s1 ARCH=amd64 ./scripts/download |
| 130 | +TAG=v1.30.0+k3s1 docker buildx build \ |
| 131 | + --platform linux/amd64 \ |
| 132 | + --build-arg TAG=v1.30.0+k3s1 \ |
| 133 | + --tag rancher/system-agent-installer-k3s:v1.30.0-k3s1-linux-amd64 \ |
| 134 | + --push \ # or --load if building for multiple arches |
| 135 | + --file ./package/Dockerfile \ |
| 136 | + . |
| 137 | + |
| 138 | +# Build arm64 |
| 139 | +TAG=v1.30.0+k3s1 ARCH=arm64 ./scripts/download |
| 140 | +TAG=v1.30.0+k3s1 docker buildx build \ |
| 141 | + --platform linux/arm64 \ |
| 142 | + --build-arg TAG=v1.30.0+k3s1 \ |
| 143 | + --tag rancher/system-agent-installer-k3s:v1.30.0-k3s1-linux-arm64 \ |
| 144 | + --push \ |
| 145 | + --file ./package/Dockerfile \ |
| 146 | + . |
| 147 | + |
| 148 | +# Create multi-arch manifest |
| 149 | +docker buildx imagetools create \ |
| 150 | + --tag rancher/system-agent-installer-k3s:v1.30.0-k3s1 \ |
| 151 | + rancher/system-agent-installer-k3s:v1.30.0-k3s1-linux-amd64 \ |
| 152 | + rancher/system-agent-installer-k3s:v1.30.0-k3s1-linux-arm64 |
| 153 | +``` |
| 154 | + |
| 155 | +### Option 4: Build Without TAG (Uses Latest K3s) |
| 156 | + |
| 157 | +Let `scripts/version` determine the version automatically: |
| 158 | + |
| 159 | +```bash |
| 160 | +# This will query GitHub API for the latest K3s release |
| 161 | +./scripts/download |
| 162 | + |
| 163 | +# Then build (VERSION will be set by scripts/version fallback) |
| 164 | +TAG="" docker buildx build \ |
| 165 | + --platform linux/amd64 \ |
| 166 | + --tag rancher/system-agent-installer-k3s:latest \ |
| 167 | + --load \ |
| 168 | + --file ./package/Dockerfile \ |
| 169 | + . |
| 170 | +``` |
| 171 | + |
| 172 | +### Option 5: Build with Local Artifacts |
| 173 | + |
| 174 | +For faster iteration during development, provide pre-downloaded artifacts: |
| 175 | + |
| 176 | +```bash |
| 177 | +# Create local artifacts directory |
| 178 | +mkdir -p local |
| 179 | + |
| 180 | +# Download what you need (K3s binary, installer.sh, sha256sum file) |
| 181 | +# Then place them in local/ |
| 182 | + |
| 183 | +# Build using local artifacts (skips downloads) |
| 184 | +TAG=v1.30.0+k3s1 LOCAL_ARTIFACTS=true docker buildx build \ |
| 185 | + --platform linux/amd64 \ |
| 186 | + --build-arg TAG=v1.30.0+k3s1 \ |
| 187 | + --tag rancher/system-agent-installer-k3s:v1.30.0-k3s1 \ |
| 188 | + --load \ |
| 189 | + --file ./package/Dockerfile \ |
| 190 | + . |
| 191 | +``` |
| 192 | + |
| 193 | +## Understanding the Build |
| 194 | + |
| 195 | +### What `scripts/download` Does |
| 196 | + |
| 197 | +Located at `scripts/download`, this script: |
| 198 | + |
| 199 | +1. Sources `scripts/version` to determine VERSION, URI_VERSION, ARCH, OS |
| 200 | +2. Creates `artifacts/` directory |
| 201 | +3. Downloads K3s install script from GitHub (k3s-io/k3s repository) |
| 202 | +4. Downloads K3s binary matching ARCH from either: |
| 203 | + - Private PRIME_RIBS server (if `PRIME_RIBS` env var is set) |
| 204 | + - GitHub k3s-io/k3s releases (default) |
| 205 | +5. Downloads corresponding SHA256 checksums |
| 206 | +6. Verifies binary integrity via `sha256sum -c` |
| 207 | + |
| 208 | +Outputs: Files placed in `artifacts/` directory (k3s binary, installer.sh, sha256sum file) |
| 209 | + |
| 210 | +### What `package/Dockerfile` Does |
| 211 | + |
| 212 | +Located at `package/Dockerfile`, this is the product Dockerfile: |
| 213 | + |
| 214 | +```dockerfile |
| 215 | +FROM scratch |
| 216 | +COPY package/run.sh /run.sh |
| 217 | +COPY artifacts/* / |
| 218 | +``` |
| 219 | + |
| 220 | +Builds a minimal scratch image containing: |
| 221 | +- K3s binary |
| 222 | +- K3s install script |
| 223 | +- SHA256 checksum file |
| 224 | +- `run.sh` runtime script |
| 225 | + |
| 226 | +### What `package/run.sh` Does |
| 227 | + |
| 228 | +Located at `package/run.sh`, this is the container entrypoint: |
| 229 | + |
| 230 | +1. Copies K3s binary to `/usr/local/bin/k3s` on the host |
| 231 | +2. Sets `INSTALL_K3S_SKIP_DOWNLOAD=true` (binary already in place) |
| 232 | +3. Runs the K3s install script with retry logic for etcd learner member issues |
| 233 | + |
| 234 | +## Environment Variables |
| 235 | + |
| 236 | +| Variable | Purpose | Example | |
| 237 | +|----------|---------|---------| |
| 238 | +| `TAG` | K3s version to build (e.g., `v1.30.0+k3s1`) | `v1.30.0+k3s1` | |
| 239 | +| `ARCH` | Target architecture (amd64, arm64, arm, s390x) | `arm64` | |
| 240 | +| `OS` | Target OS (always linux) | `linux` | |
| 241 | +| `REPO` | Docker image repository | `rancher` (default), or `your-registry/your-repo` | |
| 242 | +| `PRIME_RIBS` | Private artifact server URL (optional) | `https://artifacts.internal/` | |
| 243 | +| `LOCAL_ARTIFACTS` | Use artifacts from `local/` directory instead of downloading | `true` | |
| 244 | + |
| 245 | +## Troubleshooting |
| 246 | + |
| 247 | +### "No rule to make target 'build'" |
| 248 | + |
| 249 | +This is expected after removing Dapper. Use the steps above to build locally instead. |
| 250 | + |
| 251 | +### "Binary verification failed" |
| 252 | + |
| 253 | +The SHA256 checksum for the downloaded K3s binary didn't match. This usually means: |
| 254 | +- The binary was corrupted during download |
| 255 | +- The wrong binary was downloaded for your ARCH |
| 256 | +- Network issues |
| 257 | + |
| 258 | +Try deleting `artifacts/` and re-running `scripts/download`. |
| 259 | + |
| 260 | +### "Recursive variable `TAG' references itself" |
| 261 | + |
| 262 | +This error occurs if `TAG` is unset. Always provide `TAG` explicitly or let `scripts/version` query the GitHub API (which it does automatically if `TAG` is empty). |
0 commit comments