diff --git a/.github/workflows/build_test_ci.yml b/.github/workflows/build_test_ci.yml
index 0dd08964a..6ae6ff2d9 100644
--- a/.github/workflows/build_test_ci.yml
+++ b/.github/workflows/build_test_ci.yml
@@ -2,9 +2,17 @@ name: Build and Test CI
on:
push:
- branches: [ "main" ]
+ branches:
+ - main
+ paths-ignore:
+ - '**/**.md'
+ - 'docs/**'
pull_request:
- branches: [ "main" ]
+ branches:
+ - main
+ paths-ignore:
+ - '**/**.md'
+ - 'docs/**'
permissions:
contents: read
diff --git a/.github/workflows/codeql.yml b/.github/workflows/codeql.yml
index bad54e204..1b9b404b3 100644
--- a/.github/workflows/codeql.yml
+++ b/.github/workflows/codeql.yml
@@ -2,10 +2,17 @@ name: "CodeQL"
on:
push:
- branches: [ "main" ]
+ branches:
+ - main
+ paths-ignore:
+ - '**/**.md'
+ - 'docs/**'
pull_request:
- # The branches below must be a subset of the branches above
- branches: [ "main" ]
+ branches:
+ - main
+ paths-ignore:
+ - '**/**.md'
+ - 'docs/**'
permissions:
contents: read
diff --git a/.github/workflows/gh-pages.yml b/.github/workflows/gh-pages.yml
new file mode 100644
index 000000000..c65c9e0f0
--- /dev/null
+++ b/.github/workflows/gh-pages.yml
@@ -0,0 +1,44 @@
+name: Deploy Github Pages
+
+on:
+ push:
+ branches:
+ - main
+ paths:
+ - 'README.md'
+ - 'docs/book/**'
+ pull_request:
+ paths:
+ - 'README.md'
+ - 'docs/book/**'
+
+jobs:
+ deploy:
+ runs-on: ubuntu-latest
+ # Grant GITHUB_TOKEN the permissions required to make a Pages deployment
+
+ permissions:
+ pages: write # to deploy to Pages
+ id-token: write # to verify the deployment originates from an appropriate source
+
+ concurrency:
+ group: ${{ github.workflow }}-${{ github.ref }}
+
+ steps:
+ - uses: actions/checkout@v4
+
+ - name: Setup mdBook
+ uses: peaceiris/actions-mdbook@v1
+ with:
+ mdbook-version: '0.4.35'
+
+ - run: cd docs/book && mdbook build
+
+ - name: Deploy
+ uses: peaceiris/actions-gh-pages@v3
+ if: ${{ github.ref == 'refs/heads/main' }}
+ with:
+ github_token: ${{ secrets.GITHUB_TOKEN }}
+ publish_dir: ./docs/book
+ user_name: 'github-actions[bot]'
+ user_email: 'github-actions[bot]@users.noreply.github.com'
diff --git a/.gitignore b/.gitignore
index 938e4bfb2..dea5abdff 100644
--- a/.gitignore
+++ b/.gitignore
@@ -3,4 +3,5 @@
bin/*
kind-logs-*
cover.out
-kubeconfig
+kubeconfig*
+.devbox/*
diff --git a/README.md b/README.md
index f281b6399..3c8325229 100644
--- a/README.md
+++ b/README.md
@@ -1,67 +1,53 @@
-[![Go Report Card](https://goreportcard.com/badge/github.com/linode/cluster-api-provider-linode)](https://goreportcard.com/report/github.com/linode/cluster-api-provider-linode)
-[![Go Reference](https://pkg.go.dev/badge/github.com/linode/cluster-api-provider-linode.svg)](https://pkg.go.dev/github.com/linode/cluster-api-provider-linode)
-[![Go Build and Test CI](https://github.com/linode/cluster-api-provider-linode/actions/workflows/go-test.yml/badge.svg)](https://github.com/linode/cluster-api-provider-linode/actions/workflows/go-test.yml)
-[![CodeQL](https://github.com/linode/cluster-api-provider-linode/actions/workflows/codeql.yml/badge.svg)](https://github.com/linode/cluster-api-provider-linode/actions/workflows/codeql.yml)
-[![Docker Image Build CI](https://github.com/linode/cluster-api-provider-linode/actions/workflows/build-docker-image.yml/badge.svg)](https://github.com/linode/cluster-api-provider-linode/actions/workflows/build-docker-image.yml)
-[![PRs Welcome](https://img.shields.io/badge/PRs-welcome-brightgreen.svg)](http://makeapullrequest.com)
-
-
-
# Cluster API Provider Linode
-A [Cluster API](https://cluster-api.sigs.k8s.io/) implementation for [Linode](https://www.linode.com/) to create kubernetes clusters.
-
-## Local development
-
-### Using Devbox
-
-1. [Download Devbox](https://jetpack.io/devbox/docs/installing_devbox/)
-2. Install dependent packages in your project
- ```shell
- devbox install
- ```
-3. Use devbox environment
- ```shell
- # use a devbox shell
- devbox shell
- # or run a single command in devbox
- devbox run make tilt-cluster
- # or leverage direnv integration
- devbox generate direnv
- ```
-
-
-### Enable git hooks
-To enable automatic code validation on code push, execute the following commands:
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-```bash
-PATH="$PWD/bin:$PATH" make husky && husky install
-```
+------
-If you would like to temporarily disable git hook, set `SKIP_GIT_PUSH_HOOK` value:
+## What is Cluster API Provider Linode (CAPL)
-```bash
-SKIP_GIT_PUSH_HOOK=1 git push
-```
+This is a [Cluster API](https://cluster-api.sigs.k8s.io/) implementation for [Linode](https://www.linode.com/)
+to create, configure, and manage Kubernetes clusters.
-### Local development with Tilt
+------
-For local development execute the following `make` target:
+## Compatibility
-```bash
-LINODE_TOKEN= make tilt-cluster
-```
+### Cluster API Versions
+CAPL is compatible only with the `v1beta1` version of CAPI (v1.0.x).
-This command creates a Kind cluster, and deploys resources via Tilt. You can freely change the code and wait for Tilt to update provider.
+### Kubernetes Versions
-### E2E testing
+CAPL is able to install and manage the [versions of Kubernetes supported by the Cluster API (CAPI) project](https://cluster-api.sigs.k8s.io/reference/versions.html#supported-kubernetes-versions).
-For local development execute the following `make` target:
+------
-```bash
-LINODE_TOKEN= make e2etest
-```
+## Documentation
-This command creates a Kind cluster, and executes all the defined tests.
+Please see our [Book](https://linode.github.io/cluster-api-provider-linode) for in-depth user documentation.
-> Please ensure you have increased maximum open files on your host: https://kind.sigs.k8s.io/docs/user/known-issues/#pod-errors-due-to-too-many-open-files
+Additional docs can be found in the [/docs](/docs) directory.
diff --git a/docs/README.md b/docs/README.md
new file mode 100644
index 000000000..c478ab34e
--- /dev/null
+++ b/docs/README.md
@@ -0,0 +1,14 @@
+# Documentation Index
+
+## Quick Start
+
+- [Getting started](https://linode.github.io/cluster-api-provider-linode/topics/getting-started.html)
+- [Cluster API quick start](https://cluster-api.sigs.k8s.io/user/quick-start.html)
+
+## Development
+
+- [Development guide](https://linode.github.io/cluster-api-provider-linode/developers/development.html)
+
+## Troubleshooting
+
+- [Troubleshooting guide](ihttps://linode.github.io/cluster-api-provider-linode/topics/troubleshooting.html)
diff --git a/docs/book/.gitignore b/docs/book/.gitignore
new file mode 100644
index 000000000..7585238ef
--- /dev/null
+++ b/docs/book/.gitignore
@@ -0,0 +1 @@
+book
diff --git a/docs/book/book.toml b/docs/book/book.toml
new file mode 100644
index 000000000..e2f1c07b5
--- /dev/null
+++ b/docs/book/book.toml
@@ -0,0 +1,19 @@
+[book]
+authors = ["Ashley Dumaine"]
+language = "en"
+multilingual = false
+src = "src"
+title = "Cluster API Provider Linode Book"
+
+[build]
+build-dir = "book"
+
+[output.html]
+git-repository-url = "https://github.com/linode/cluster-api-provider-linode"
+additional-css = ["./theme/mdbook-admonish.css"]
+
+[preprocessor]
+
+[preprocessor.admonish]
+command = "mdbook-admonish"
+assets_version = "3.0.2" # do not edit: managed by `mdbook-admonish install`
diff --git a/docs/book/src/SUMMARY.md b/docs/book/src/SUMMARY.md
new file mode 100644
index 000000000..22ae96fce
--- /dev/null
+++ b/docs/book/src/SUMMARY.md
@@ -0,0 +1,9 @@
+# Summary
+
+- [Introduction](./introduction.md)
+- [Topics](./topics/topics.md)
+ - [Getting Started](./topics/getting-started.md)
+ - [Troubleshooting](./topics/troubleshooting.md)
+ - [Addons](./topics/addons.md)
+- [Development](./developers/development.md)
+- [Reference](./reference/reference.md)
diff --git a/docs/book/src/developers/development.md b/docs/book/src/developers/development.md
new file mode 100644
index 000000000..ab5cb2317
--- /dev/null
+++ b/docs/book/src/developers/development.md
@@ -0,0 +1,193 @@
+# Developing Cluster API Provider Linode
+
+## Contents
+
+
+
+- [Setting up](#setting-up)
+ - [Base requirements](#base-requirements)
+ - [Clone the source code](#clone-the-source-code)
+ - [Get familiar with basic concepts](#get-familiar-with-basic-concepts)
+- [Developing](#developing)
+ - [Enable git hooks](#enable-git-hooks)
+ - [Setting up the environment](#setting-up-the-environment)
+ - [Using devbox](#using-devbox)
+ - [Tilt Requirements](#tilt-requirements)
+ - [Using Tilt](#using-tilt)
+ - [Deploying a workload cluster](#deploying-a-workload-cluster)
+ - [Customizing the cluster deployment](#customizing-the-cluster-deployment)
+ - [Creating the workload cluster](#creating-the-workload-cluster)
+ - [Cleaning up the workload cluster](#cleaning-up-the-workload-cluster)
+ - [Automated Testing](#automated-testing)
+ - [E2E Testing](#e2e-testing)
+
+
+
+## Setting up
+
+### Base requirements
+
+There are no requirements since development dependencies are fetched as
+needed via the make targets, but a recommendation is to
+[install Devbox](https://jetpack.io/devbox/docs/installing_devbox/)
+
+### Clone the source code
+
+```shell
+git clone https://github.com/linode/cluster-api-provider-linode
+cd cluster-api-provider-linode
+```
+
+### Get familiar with basic concepts
+
+This provider is based on the [Cluster API project](https://github.com/kubernetes-sigs/cluster-api).
+It's recommended to familiarize yourself with Cluster API resources, concepts, and conventions
+outlined in the [Cluster API Book](https://cluster-api.sigs.k8s.io/).
+
+## Developing
+
+This repository uses [Go Modules](https://github.com/golang/go/wiki/Modules)
+to track and vendor dependencies.
+
+To pin a new dependency, run:
+```bash
+go get @
+```
+
+### Enable git hooks
+
+To enable automatic code validation on code push, execute the following commands:
+
+```bash
+PATH="$PWD/bin:$PATH" make husky && husky install
+```
+
+If you would like to temporarily disable git hook, set `SKIP_GIT_PUSH_HOOK` value:
+
+```bash
+SKIP_GIT_PUSH_HOOK=1 git push
+```
+
+### Setting up the environment
+
+```admonish warning
+Ensure you have your `LINODE_TOKEN` set as outlined in the
+[getting started prerequisites](../topics/getting-started.md#Prerequisites) section.
+```
+
+All development dependencies should be taken care of via Devbox and/or make target dependencies.
+
+#### Using devbox
+
+1. Install dependent packages in your project
+ ```shell
+ devbox install
+ ```
+
+ ```admonish success title=""
+ This will take a while, go and grab a drink of water.
+ ```
+
+2. Use devbox environment
+ ```shell
+ devbox shell
+ ```
+
+From this point you can use the devbox shell like a regular shell.
+The rest of the guide assumes a devbox shell is used, but the make target
+dependencies will install any missing dependencies if needed when running
+outside of a devbox shell.
+
+### Using tilt
+To build a kind cluster and start Tilt, simply run:
+```shell
+make tilt-cluster
+```
+
+Once your kind management cluster is up and running, you can
+[deploy a workload cluster](#deploying-a-workload-cluster).
+
+To tear down the tilt-cluster, run
+
+```shell
+kind delete cluster --name tilt
+```
+
+### Deploying a workload cluster
+
+After your kind management cluster is up and running with Tilt, you should be ready to deploy your first cluster.
+
+#### Customizing the cluster deployment
+
+Here is a list of required configuration parameters:
+
+```bash
+# Cluster settings
+export CLUSTER_NAME=capl-cluster
+export KUBERNETES_VERSION=v1.29.1
+
+# Linode settings
+export LINODE_REGION=us-ord
+export LINODE_TOKEN=
+export LINODE_CONTROL_PLANE_MACHINE_TYPE=g6-standard-2
+export LINODE_MACHINE_TYPE=g6-standard-2
+```
+
+~~~admonish tip
+You can also use `clusterctl generate` to see which variables need to be set:
+
+```
+clusterctl generate cluster $CLUSTER_NAME --from ./templates/cluster-template.yaml --list-variables
+```
+
+~~~
+
+```admonish warning
+Please note the templates require the use of `clusterctl generate` to substitute the environment variables properly.
+```
+
+#### Creating the workload cluster
+
+Once you have all the necessary environment variables set,
+you can deploy a workload cluster with the following command:
+
+```shell
+clusterctl generate cluster $CLUSTER_NAME \
+ --kubernetes-version v1.29.1 \
+ --from templates/cluster-template.yaml \
+ | kubectl apply -f -
+```
+
+This will provision the cluster with the CNI defaulted to [cilium](../topics/addons.md#cilium)
+and the [linode-ccm](../topics/addons.md#ccm) installed.
+
+```admonish question title=""
+For any issues, please refer to the [troubleshooting guide](../topics/troubleshooting.md).
+```
+
+#### Cleaning up the workload cluster
+
+To delete the cluster, simply run:
+
+```bash
+kubectl delete cluster $CLUSTER_NAME
+```
+
+```admonish question title=""
+For any issues, please refer to the [troubleshooting guide](../topics/troubleshooting.md).
+```
+
+### Automated Testing
+
+#### E2E Testing
+
+To run E2E locally run:
+```bash
+make e2etest
+```
+
+This command creates a KIND cluster, and executes all the defined tests.
+
+```admonish warning
+Please ensure you have [increased maximum open files on your host](https://kind.sigs.k8s.io/docs/user/known-issues/#pod-errors-due-to-too-many-open-files)
+```
diff --git a/docs/book/src/introduction.md b/docs/book/src/introduction.md
new file mode 100644
index 000000000..3bad00702
--- /dev/null
+++ b/docs/book/src/introduction.md
@@ -0,0 +1 @@
+{{#include ../../../README.md}}
diff --git a/docs/book/src/reference/reference.md b/docs/book/src/reference/reference.md
new file mode 100644
index 000000000..5bf870049
--- /dev/null
+++ b/docs/book/src/reference/reference.md
@@ -0,0 +1,4 @@
+# Reference
+
+For reference documentation for CAPL API types, please refer to
+the [godocs](https://pkg.go.dev/github.com/linode/cluster-api-provider-linode@v0.0.0-20240201213736-1a737bd24eca/api/v1alpha1)
diff --git a/docs/book/src/topics/addons.md b/docs/book/src/topics/addons.md
new file mode 100644
index 000000000..9a8964a5a
--- /dev/null
+++ b/docs/book/src/topics/addons.md
@@ -0,0 +1,93 @@
+# Overview
+
+This section documents addons for self-managed clusters.
+
+```admonish note
+Currently, all addons are installed via
+[Cluster API Addon Provider Helm (CAAPH)](https://github.com/kubernetes-sigs/cluster-api-addon-provider-helm).
+
+CAAPH is installed by default in the KIND cluster created by `make tilt-cluster`.
+
+For more information, please refer to the
+[CAAPH Quick Start](https://github.com/kubernetes-sigs/cluster-api-addon-provider-helm/blob/main/docs/quick-start.md).
+```
+
+```admonish note
+The [Linode Cloud Controller Manager](#linode-cloud-controller-manager) and
+[Linode Blockstorage CSI Driver](#linode-blockstorage-csi-driver) addons require the `ClusterResourceSet` feature flag
+to be set on the management cluster.
+
+This feature flag is enabled by default in the KIND cluster created by `make tilt-cluster`.
+
+For more information, please refer to [the ClusterResourceSet page in The Cluster API Book](https://cluster-api.sigs.k8s.io/tasks/experimental-features/cluster-resource-set).
+```
+
+
+## Contents
+
+
+
+- [CNI](#cni)
+ - [Cilium](#cilium)
+- [CCM](#ccm)
+ - [Linode Cloud Controller Manager](#linode-cloud-controller-manager)
+- [Container Storage](#container-storage)
+ - [Linode Blockstorage CSI Driver](#linode-blockstorage-csi-driver)
+
+
+
+## CNI
+
+In order for pod networking to work properly, a Container Network Interface (CNI) must be installed.
+
+### Cilium
+
+```admonish success title=""
+Installed by default
+```
+
+To install [Cilium](https://cilium.io/) on a self-managed cluster, simply apply the `cni: cilium`
+label on the `Cluster` resource if not already present.
+
+```bash
+kubectl label cluster $CLUSTER_NAME cni=cilium --overwrite
+```
+
+Cilium will then be automatically installed via CAAPH into the labeled cluster.
+
+## CCM
+
+In order for the `InternalIP` and `ExternalIP` of the provisioned Nodes to be set correctly,
+a Cloud Controller Manager (CCM) must be installed.
+
+### Linode Cloud Controller Manager
+
+```admonish success title=""
+Installed by default
+```
+
+To install the [linode-cloud-controller-manager (linode-ccm)](https://github.com/linode/linode-cloud-controller-manager)
+on a self-managed cluster, simply apply the `ccm: linode`
+label on the `Cluster` resource if not already present.
+
+```bash
+kubectl label cluster $CLUSTER_NAME ccm=linode --overwrite
+```
+
+The linode-ccm will then be automatically installed via CAAPH into the labeled cluster.
+
+## Container Storage
+
+In order for stateful workloads to create PersistentVolumes (PVs), a storage driver must be installed.
+
+### Linode Blockstorage CSI Driver
+
+To install the [linode-blockstorage-csi-driver](https://github.com/linode/linode-blockstorage-csi-driver)
+on a self-managed cluster, simply apply the `csi-driver: linode`
+label on the `Cluster` resource if not already present.
+
+```bash
+kubectl label cluster $CLUSTER_NAME csi-driver=linode --overwrite
+```
+
+The linode-blockstorage-csi-driver will then be automatically installed via CAAPH into the labeled cluster.
diff --git a/docs/book/src/topics/getting-started.md b/docs/book/src/topics/getting-started.md
new file mode 100644
index 000000000..bb6327681
--- /dev/null
+++ b/docs/book/src/topics/getting-started.md
@@ -0,0 +1,30 @@
+# Getting started with CAPL
+
+## Prerequisites
+
+- A [Linode account](https://linode.com/)
+- A Personal Access Token (PAT) created via [the Linode Cloud Manager](https://cloud.linode.com/profile/tokens).
+Make sure to create the token with at least the following read/write permissions (or "all"):
+ - Linodes
+ - NodeBalancers
+ - Images
+ - Volumes
+ - VPCs
+ - IPs
+
+```admonish question title=""
+For more information please see the
+[Linode Guide](https://www.linode.com/docs/products/tools/api/guides/manage-api-tokens/#create-an-api-token).
+```
+
+## Setting up your Linode environment
+
+Once you have provisioned your PAT, save it in an environment variable:
+```bash
+export LINODE_TOKEN=""
+```
+
+## Building your first cluster
+
+Please continue from the [setting up the environment](../developers/development.md#setting-up-the-environment)
+section for creating your first Kubernetes cluster on Linode using Cluster API.
diff --git a/docs/book/src/topics/topics.md b/docs/book/src/topics/topics.md
new file mode 100644
index 000000000..ad3e26d59
--- /dev/null
+++ b/docs/book/src/topics/topics.md
@@ -0,0 +1,4 @@
+# Topics
+
+This section contains information about enabling and configuring various
+features for Cluster API Provider Linode
diff --git a/docs/book/src/topics/troubleshooting.md b/docs/book/src/topics/troubleshooting.md
new file mode 100644
index 000000000..afd95a905
--- /dev/null
+++ b/docs/book/src/topics/troubleshooting.md
@@ -0,0 +1,75 @@
+# Troubleshooting Guide
+
+This guide covers common issues users might run into when using Cluster API Provider Linode.
+This list is work-in-progress, please feel free to open a PR to add this guide if you find
+that useful information is missing.
+
+## Examples of common issues
+
+### No Linode resources are getting created
+
+This could be due to the `LINODE_TOKEN` either not being set in your environment or expired.
+If expired, [provision a new token](../topics/getting-started.md#prerequisites) and optionally
+set the "Expiry" to "Never" (default expiry is 6 months).
+
+### One or more control plane replicas are missing
+
+Take a look at the `KubeadmControlPlane` controller logs and look for any potential errors:
+
+```bash
+kubectl logs deploy/capi-kubeadm-control-plane-controller-manager -n capi-kubeadm-control-plane-system manager
+```
+
+In addition, make sure all pods on the workload cluster are healthy, including pods in the `kube-system` namespace.
+
+Otherwise, [ensure that the linode-ccm is installed on your workload cluster via CAAPH](../topics/addons.md#ccm).
+
+### Nodes are in NotReady state
+
+Make sure [a CNI is installed on the workload cluster](../topics/addons.md#cni)
+and that all the pods on the workload cluster are in running state.
+
+If the Cluster is labeled with `cni: cilium`, check that the cilium `HelmChartProxy` is installed in
+the management cluster and that the `HelmChartProxy` is in a `Ready` state:
+
+```bash
+kubectl get cluster $CLUSTER_NAME --show-labels
+```
+
+```bash
+kubectl get helmchartproxies
+```
+
+## Checking CAPI and CAPL resources
+
+To check the progression of all CAPI and CAPL resources on the management cluster you can run:
+
+```bash
+kubectl get cluster-api
+```
+
+## Looking at the CAPL controller logs
+
+To check the CAPL controller logs on the management cluster, run:
+
+```bash
+kubectl logs deploy/cluster-api-provider-linode-controller-manager -n cluster-api-provider-linode-system manager
+```
+
+### Checking cloud-init logs (Debian / Ubuntu)
+
+[Cloud-init](https://www.linode.com/docs/guides/applications/configuration-management/cloud-init/)
+logs can provide more information on any issues that happened when running the bootstrap script.
+
+```admonish warning
+Not all Debian and Ubuntu images available from Linode support cloud-init! Please see the
+[Availability section of the Linode Metadata Service Guide](https://www.linode.com/docs/products/compute/compute-instances/guides/metadata/#availability).
+
+You can also see which images have cloud-init support via the [linode-cli](https://www.linode.com/docs/products/tools/cli/get-started/):
+
+`linode-cli images list | grep cloud-init`
+
+```
+
+Please refer to the [Troubleshoot Metadata and Cloud-Init section of the Linode Metadata Service Guide](https://www.linode.com/docs/products/compute/compute-instances/guides/metadata/?tabs=linode-api%2Cmacos#troubleshoot-metadata-and-cloud-init).
+
diff --git a/docs/book/theme/favicon.png b/docs/book/theme/favicon.png
new file mode 100644
index 000000000..9f0139ba8
Binary files /dev/null and b/docs/book/theme/favicon.png differ
diff --git a/docs/book/theme/mdbook-admonish.css b/docs/book/theme/mdbook-admonish.css
new file mode 100644
index 000000000..45aeff051
--- /dev/null
+++ b/docs/book/theme/mdbook-admonish.css
@@ -0,0 +1,348 @@
+@charset "UTF-8";
+:is(.admonition) {
+ display: flow-root;
+ margin: 1.5625em 0;
+ padding: 0 1.2rem;
+ color: var(--fg);
+ page-break-inside: avoid;
+ background-color: var(--bg);
+ border: 0 solid black;
+ border-inline-start-width: 0.4rem;
+ border-radius: 0.2rem;
+ box-shadow: 0 0.2rem 1rem rgba(0, 0, 0, 0.05), 0 0 0.1rem rgba(0, 0, 0, 0.1);
+}
+@media print {
+ :is(.admonition) {
+ box-shadow: none;
+ }
+}
+:is(.admonition) > * {
+ box-sizing: border-box;
+}
+:is(.admonition) :is(.admonition) {
+ margin-top: 1em;
+ margin-bottom: 1em;
+}
+:is(.admonition) > .tabbed-set:only-child {
+ margin-top: 0;
+}
+html :is(.admonition) > :last-child {
+ margin-bottom: 1.2rem;
+}
+
+a.admonition-anchor-link {
+ display: none;
+ position: absolute;
+ left: -1.2rem;
+ padding-right: 1rem;
+}
+a.admonition-anchor-link:link, a.admonition-anchor-link:visited {
+ color: var(--fg);
+}
+a.admonition-anchor-link:link:hover, a.admonition-anchor-link:visited:hover {
+ text-decoration: none;
+}
+a.admonition-anchor-link::before {
+ content: "ยง";
+}
+
+:is(.admonition-title, summary.admonition-title) {
+ position: relative;
+ min-height: 4rem;
+ margin-block: 0;
+ margin-inline: -1.6rem -1.2rem;
+ padding-block: 0.8rem;
+ padding-inline: 4.4rem 1.2rem;
+ font-weight: 700;
+ background-color: rgba(68, 138, 255, 0.1);
+ print-color-adjust: exact;
+ -webkit-print-color-adjust: exact;
+ display: flex;
+}
+:is(.admonition-title, summary.admonition-title) p {
+ margin: 0;
+}
+html :is(.admonition-title, summary.admonition-title):last-child {
+ margin-bottom: 0;
+}
+:is(.admonition-title, summary.admonition-title)::before {
+ position: absolute;
+ top: 0.625em;
+ inset-inline-start: 1.6rem;
+ width: 2rem;
+ height: 2rem;
+ background-color: #448aff;
+ print-color-adjust: exact;
+ -webkit-print-color-adjust: exact;
+ mask-image: url('data:image/svg+xml;charset=utf-8,');
+ -webkit-mask-image: url('data:image/svg+xml;charset=utf-8,');
+ mask-repeat: no-repeat;
+ -webkit-mask-repeat: no-repeat;
+ mask-size: contain;
+ -webkit-mask-size: contain;
+ content: "";
+}
+:is(.admonition-title, summary.admonition-title):hover a.admonition-anchor-link {
+ display: initial;
+}
+
+details.admonition > summary.admonition-title::after {
+ position: absolute;
+ top: 0.625em;
+ inset-inline-end: 1.6rem;
+ height: 2rem;
+ width: 2rem;
+ background-color: currentcolor;
+ mask-image: var(--md-details-icon);
+ -webkit-mask-image: var(--md-details-icon);
+ mask-repeat: no-repeat;
+ -webkit-mask-repeat: no-repeat;
+ mask-size: contain;
+ -webkit-mask-size: contain;
+ content: "";
+ transform: rotate(0deg);
+ transition: transform 0.25s;
+}
+details[open].admonition > summary.admonition-title::after {
+ transform: rotate(90deg);
+}
+
+:root {
+ --md-details-icon: url("data:image/svg+xml;charset=utf-8,");
+}
+
+:root {
+ --md-admonition-icon--admonish-note: url("data:image/svg+xml;charset=utf-8,");
+ --md-admonition-icon--admonish-abstract: url("data:image/svg+xml;charset=utf-8,");
+ --md-admonition-icon--admonish-info: url("data:image/svg+xml;charset=utf-8,");
+ --md-admonition-icon--admonish-tip: url("data:image/svg+xml;charset=utf-8,");
+ --md-admonition-icon--admonish-success: url("data:image/svg+xml;charset=utf-8,");
+ --md-admonition-icon--admonish-question: url("data:image/svg+xml;charset=utf-8,");
+ --md-admonition-icon--admonish-warning: url("data:image/svg+xml;charset=utf-8,");
+ --md-admonition-icon--admonish-failure: url("data:image/svg+xml;charset=utf-8,");
+ --md-admonition-icon--admonish-danger: url("data:image/svg+xml;charset=utf-8,");
+ --md-admonition-icon--admonish-bug: url("data:image/svg+xml;charset=utf-8,");
+ --md-admonition-icon--admonish-example: url("data:image/svg+xml;charset=utf-8,");
+ --md-admonition-icon--admonish-quote: url("data:image/svg+xml;charset=utf-8,");
+}
+
+:is(.admonition):is(.admonish-note) {
+ border-color: #448aff;
+}
+
+:is(.admonish-note) > :is(.admonition-title, summary.admonition-title) {
+ background-color: rgba(68, 138, 255, 0.1);
+}
+:is(.admonish-note) > :is(.admonition-title, summary.admonition-title)::before {
+ background-color: #448aff;
+ mask-image: var(--md-admonition-icon--admonish-note);
+ -webkit-mask-image: var(--md-admonition-icon--admonish-note);
+ mask-repeat: no-repeat;
+ -webkit-mask-repeat: no-repeat;
+ mask-size: contain;
+ -webkit-mask-repeat: no-repeat;
+}
+
+:is(.admonition):is(.admonish-abstract, .admonish-summary, .admonish-tldr) {
+ border-color: #00b0ff;
+}
+
+:is(.admonish-abstract, .admonish-summary, .admonish-tldr) > :is(.admonition-title, summary.admonition-title) {
+ background-color: rgba(0, 176, 255, 0.1);
+}
+:is(.admonish-abstract, .admonish-summary, .admonish-tldr) > :is(.admonition-title, summary.admonition-title)::before {
+ background-color: #00b0ff;
+ mask-image: var(--md-admonition-icon--admonish-abstract);
+ -webkit-mask-image: var(--md-admonition-icon--admonish-abstract);
+ mask-repeat: no-repeat;
+ -webkit-mask-repeat: no-repeat;
+ mask-size: contain;
+ -webkit-mask-repeat: no-repeat;
+}
+
+:is(.admonition):is(.admonish-info, .admonish-todo) {
+ border-color: #00b8d4;
+}
+
+:is(.admonish-info, .admonish-todo) > :is(.admonition-title, summary.admonition-title) {
+ background-color: rgba(0, 184, 212, 0.1);
+}
+:is(.admonish-info, .admonish-todo) > :is(.admonition-title, summary.admonition-title)::before {
+ background-color: #00b8d4;
+ mask-image: var(--md-admonition-icon--admonish-info);
+ -webkit-mask-image: var(--md-admonition-icon--admonish-info);
+ mask-repeat: no-repeat;
+ -webkit-mask-repeat: no-repeat;
+ mask-size: contain;
+ -webkit-mask-repeat: no-repeat;
+}
+
+:is(.admonition):is(.admonish-tip, .admonish-hint, .admonish-important) {
+ border-color: #00bfa5;
+}
+
+:is(.admonish-tip, .admonish-hint, .admonish-important) > :is(.admonition-title, summary.admonition-title) {
+ background-color: rgba(0, 191, 165, 0.1);
+}
+:is(.admonish-tip, .admonish-hint, .admonish-important) > :is(.admonition-title, summary.admonition-title)::before {
+ background-color: #00bfa5;
+ mask-image: var(--md-admonition-icon--admonish-tip);
+ -webkit-mask-image: var(--md-admonition-icon--admonish-tip);
+ mask-repeat: no-repeat;
+ -webkit-mask-repeat: no-repeat;
+ mask-size: contain;
+ -webkit-mask-repeat: no-repeat;
+}
+
+:is(.admonition):is(.admonish-success, .admonish-check, .admonish-done) {
+ border-color: #00c853;
+}
+
+:is(.admonish-success, .admonish-check, .admonish-done) > :is(.admonition-title, summary.admonition-title) {
+ background-color: rgba(0, 200, 83, 0.1);
+}
+:is(.admonish-success, .admonish-check, .admonish-done) > :is(.admonition-title, summary.admonition-title)::before {
+ background-color: #00c853;
+ mask-image: var(--md-admonition-icon--admonish-success);
+ -webkit-mask-image: var(--md-admonition-icon--admonish-success);
+ mask-repeat: no-repeat;
+ -webkit-mask-repeat: no-repeat;
+ mask-size: contain;
+ -webkit-mask-repeat: no-repeat;
+}
+
+:is(.admonition):is(.admonish-question, .admonish-help, .admonish-faq) {
+ border-color: #64dd17;
+}
+
+:is(.admonish-question, .admonish-help, .admonish-faq) > :is(.admonition-title, summary.admonition-title) {
+ background-color: rgba(100, 221, 23, 0.1);
+}
+:is(.admonish-question, .admonish-help, .admonish-faq) > :is(.admonition-title, summary.admonition-title)::before {
+ background-color: #64dd17;
+ mask-image: var(--md-admonition-icon--admonish-question);
+ -webkit-mask-image: var(--md-admonition-icon--admonish-question);
+ mask-repeat: no-repeat;
+ -webkit-mask-repeat: no-repeat;
+ mask-size: contain;
+ -webkit-mask-repeat: no-repeat;
+}
+
+:is(.admonition):is(.admonish-warning, .admonish-caution, .admonish-attention) {
+ border-color: #ff9100;
+}
+
+:is(.admonish-warning, .admonish-caution, .admonish-attention) > :is(.admonition-title, summary.admonition-title) {
+ background-color: rgba(255, 145, 0, 0.1);
+}
+:is(.admonish-warning, .admonish-caution, .admonish-attention) > :is(.admonition-title, summary.admonition-title)::before {
+ background-color: #ff9100;
+ mask-image: var(--md-admonition-icon--admonish-warning);
+ -webkit-mask-image: var(--md-admonition-icon--admonish-warning);
+ mask-repeat: no-repeat;
+ -webkit-mask-repeat: no-repeat;
+ mask-size: contain;
+ -webkit-mask-repeat: no-repeat;
+}
+
+:is(.admonition):is(.admonish-failure, .admonish-fail, .admonish-missing) {
+ border-color: #ff5252;
+}
+
+:is(.admonish-failure, .admonish-fail, .admonish-missing) > :is(.admonition-title, summary.admonition-title) {
+ background-color: rgba(255, 82, 82, 0.1);
+}
+:is(.admonish-failure, .admonish-fail, .admonish-missing) > :is(.admonition-title, summary.admonition-title)::before {
+ background-color: #ff5252;
+ mask-image: var(--md-admonition-icon--admonish-failure);
+ -webkit-mask-image: var(--md-admonition-icon--admonish-failure);
+ mask-repeat: no-repeat;
+ -webkit-mask-repeat: no-repeat;
+ mask-size: contain;
+ -webkit-mask-repeat: no-repeat;
+}
+
+:is(.admonition):is(.admonish-danger, .admonish-error) {
+ border-color: #ff1744;
+}
+
+:is(.admonish-danger, .admonish-error) > :is(.admonition-title, summary.admonition-title) {
+ background-color: rgba(255, 23, 68, 0.1);
+}
+:is(.admonish-danger, .admonish-error) > :is(.admonition-title, summary.admonition-title)::before {
+ background-color: #ff1744;
+ mask-image: var(--md-admonition-icon--admonish-danger);
+ -webkit-mask-image: var(--md-admonition-icon--admonish-danger);
+ mask-repeat: no-repeat;
+ -webkit-mask-repeat: no-repeat;
+ mask-size: contain;
+ -webkit-mask-repeat: no-repeat;
+}
+
+:is(.admonition):is(.admonish-bug) {
+ border-color: #f50057;
+}
+
+:is(.admonish-bug) > :is(.admonition-title, summary.admonition-title) {
+ background-color: rgba(245, 0, 87, 0.1);
+}
+:is(.admonish-bug) > :is(.admonition-title, summary.admonition-title)::before {
+ background-color: #f50057;
+ mask-image: var(--md-admonition-icon--admonish-bug);
+ -webkit-mask-image: var(--md-admonition-icon--admonish-bug);
+ mask-repeat: no-repeat;
+ -webkit-mask-repeat: no-repeat;
+ mask-size: contain;
+ -webkit-mask-repeat: no-repeat;
+}
+
+:is(.admonition):is(.admonish-example) {
+ border-color: #7c4dff;
+}
+
+:is(.admonish-example) > :is(.admonition-title, summary.admonition-title) {
+ background-color: rgba(124, 77, 255, 0.1);
+}
+:is(.admonish-example) > :is(.admonition-title, summary.admonition-title)::before {
+ background-color: #7c4dff;
+ mask-image: var(--md-admonition-icon--admonish-example);
+ -webkit-mask-image: var(--md-admonition-icon--admonish-example);
+ mask-repeat: no-repeat;
+ -webkit-mask-repeat: no-repeat;
+ mask-size: contain;
+ -webkit-mask-repeat: no-repeat;
+}
+
+:is(.admonition):is(.admonish-quote, .admonish-cite) {
+ border-color: #9e9e9e;
+}
+
+:is(.admonish-quote, .admonish-cite) > :is(.admonition-title, summary.admonition-title) {
+ background-color: rgba(158, 158, 158, 0.1);
+}
+:is(.admonish-quote, .admonish-cite) > :is(.admonition-title, summary.admonition-title)::before {
+ background-color: #9e9e9e;
+ mask-image: var(--md-admonition-icon--admonish-quote);
+ -webkit-mask-image: var(--md-admonition-icon--admonish-quote);
+ mask-repeat: no-repeat;
+ -webkit-mask-repeat: no-repeat;
+ mask-size: contain;
+ -webkit-mask-repeat: no-repeat;
+}
+
+.navy :is(.admonition) {
+ background-color: var(--sidebar-bg);
+}
+
+.ayu :is(.admonition),
+.coal :is(.admonition) {
+ background-color: var(--theme-hover);
+}
+
+.rust :is(.admonition) {
+ background-color: var(--sidebar-bg);
+ color: var(--sidebar-fg);
+}
+.rust .admonition-anchor-link:link, .rust .admonition-anchor-link:visited {
+ color: var(--sidebar-fg);
+}
diff --git a/templates/cluster-template.yaml b/templates/cluster-template.yaml
index 45fa2126d..706bffb92 100644
--- a/templates/cluster-template.yaml
+++ b/templates/cluster-template.yaml
@@ -62,7 +62,7 @@ spec:
key: kubeadm-pre-init.sh
permissions: "0500"
preKubeadmCommands:
- - /kubeadm-pre-init.sh '{{ ds.meta_data.label }}' ${KUBERNETES_VERSION#[vV]}
+ - /kubeadm-pre-init.sh '{{ ds.meta_data.label }}' ${KUBERNETES_VERSION}
clusterConfiguration:
apiServer:
extraArgs:
@@ -91,11 +91,12 @@ metadata:
spec:
template:
spec:
- image: ${LINODE_OS:=""}
+ image: ${LINODE_OS:="linode/ubuntu22.04"}
type: ${LINODE_CONTROL_PLANE_MACHINE_TYPE}
region: ${LINODE_REGION}
authorizedKeys:
- - ${LINODE_SSH_KEY:=""}
+ # uncomment to include your ssh key in linode provisioning
+ # - ${LINODE_SSH_PUBKEY:=""}
---
apiVersion: cluster.x-k8s.io/v1beta1
kind: MachineDeployment
@@ -127,11 +128,12 @@ metadata:
spec:
template:
spec:
- image: ${LINODE_OS:=""}
+ image: ${LINODE_OS:="linode/ubuntu22.04"}
type: ${LINODE_MACHINE_TYPE}
region: ${LINODE_REGION}
authorizedKeys:
- - ${LINODE_SSH_KEY:=""}
+ # uncomment to include your ssh key in linode provisioning
+ # - ${LINODE_SSH_PUBKEY:=""}
---
apiVersion: bootstrap.cluster.x-k8s.io/v1beta1
kind: KubeadmConfigTemplate
@@ -163,7 +165,7 @@ spec:
key: kubeadm-pre-init.sh
permissions: "0500"
preKubeadmCommands:
- - /kubeadm-pre-init.sh '{{ ds.meta_data.label }}' ${KUBERNETES_VERSION#[vV]}
+ - /kubeadm-pre-init.sh '{{ ds.meta_data.label }}' ${KUBERNETES_VERSION}
joinConfiguration:
nodeRegistration:
kubeletExtraArgs:
@@ -199,11 +201,12 @@ stringData:
export DEBIAN_FRONTEND=noninteractive
hostnamectl set-hostname "$1" && hostname -F /etc/hostname
mkdir -p -m 755 /etc/apt/keyrings
- VERSION=$${2%.*}
+ PATCH_VERSION=$${2#[v]}
+ VERSION=$${PATCH_VERSION%.*}
curl -fsSL "https://pkgs.k8s.io/core:/stable:/v$VERSION/deb/Release.key" | sudo gpg --dearmor -o /etc/apt/keyrings/kubernetes-apt-keyring.gpg
echo "deb [signed-by=/etc/apt/keyrings/kubernetes-apt-keyring.gpg] https://pkgs.k8s.io/core:/stable:/v$VERSION/deb/ /" | sudo tee /etc/apt/sources.list.d/kubernetes.list
apt-get update -y
- apt-get install -y kubelet=$2* kubeadm=$2* kubectl=$2* containerd
+ apt-get install -y kubelet=$PATCH_VERSION* kubeadm=$PATCH_VERSION* kubectl=$PATCH_VERSION* containerd
apt-mark hold kubelet kubeadm kubectl containerd
modprobe overlay
modprobe br_netfilter