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