diff --git a/.github/workflows/release.yaml b/.github/workflows/release.yaml index ab27aa12d117c..4314a41f985e1 100644 --- a/.github/workflows/release.yaml +++ b/.github/workflows/release.yaml @@ -141,7 +141,8 @@ jobs: build/coder_"$version"_linux_{amd64,armv7,arm64}.{tar.gz,apk,deb,rpm} \ build/coder_"$version"_{darwin,windows}_{amd64,arm64}.zip \ build/coder_"$version"_windows_amd64_installer.exe \ - build/coder_helm_"$version".tgz + build/coder_helm_"$version".tgz \ + build/provisioner_helm_"$version".tgz env: CODER_SIGN_DARWIN: "1" AC_CERTIFICATE_FILE: /tmp/apple_cert.p12 @@ -295,9 +296,11 @@ jobs: version="$(./scripts/version.sh)" mkdir -p build/helm cp "build/coder_helm_${version}.tgz" build/helm + cp "build/provisioner_helm_${version}.tgz" build/helm gsutil cp gs://helm.coder.com/v2/index.yaml build/helm/index.yaml helm repo index build/helm --url https://helm.coder.com/v2 --merge build/helm/index.yaml gsutil -h "Cache-Control:no-cache,max-age=0" cp build/helm/coder_helm_${version}.tgz gs://helm.coder.com/v2 + gsutil -h "Cache-Control:no-cache,max-age=0" cp build/helm/provisioner_helm_${version}.tgz gs://helm.coder.com/v2 gsutil -h "Cache-Control:no-cache,max-age=0" cp build/helm/index.yaml gs://helm.coder.com/v2 gsutil -h "Cache-Control:no-cache,max-age=0" cp helm/artifacthub-repo.yml gs://helm.coder.com/v2 diff --git a/Makefile b/Makefile index 8bb681c9d4020..4ec4157cd79ff 100644 --- a/Makefile +++ b/Makefile @@ -344,15 +344,19 @@ push/$(CODER_MAIN_IMAGE): $(CODER_MAIN_IMAGE) docker manifest push "$$image_tag" .PHONY: push/$(CODER_MAIN_IMAGE) +# Helm charts that are available +charts = coder provisioner + # Shortcut for Helm chart package. -build/coder_helm.tgz: build/coder_helm_$(VERSION).tgz +$(foreach chart,$(charts),build/$(chart)_helm.tgz): build/%_helm.tgz: build/%_helm_$(VERSION).tgz rm -f "$@" ln "$<" "$@" # Helm chart package. -build/coder_helm_$(VERSION).tgz: +$(foreach chart,$(charts),build/$(chart)_helm_$(VERSION).tgz): build/%_helm_$(VERSION).tgz: ./scripts/helm.sh \ --version "$(VERSION)" \ + --chart $* \ --output "$@" site/out/index.html: site/package.json $(shell find ./site $(FIND_EXCLUSIONS) -type f \( -name '*.ts' -o -name '*.tsx' \)) diff --git a/docs/admin/provisioners.md b/docs/admin/provisioners.md index 6843a4e3efaad..ac0e17078c0bb 100644 --- a/docs/admin/provisioners.md +++ b/docs/admin/provisioners.md @@ -10,22 +10,23 @@ By default, the Coder server runs [built-in provisioner daemons](../cli/server.m - **Reduce server load**: External provisioners reduce load and build queue times from the Coder server. See [Scaling Coder](./scale.md#concurrent-workspace-builds) for more details. -> External provisioners are in an [alpha state](../contributing/feature-stages.md#alpha-features) and the behavior is subject to change. Use [GitHub issues](https://github.com/coder/coder) to leave feedback. - -## Running external provisioners - Each provisioner can run a single [concurrent workspace build](./scale.md#concurrent-workspace-builds). For example, running 30 provisioner containers will allow 30 users to start workspaces at the same time. Provisioners are started with the [coder provisionerd start](../cli/provisionerd_start.md) command. -### Authentication +## Authentication + +The provisioner daemon must authenticate with your Coder deployment. -The provisioner server must authenticate with your Coder deployment. There are two authentication methods: +Set a [provisioner daemon pre-shared key (PSK)](../cli/server.md#--provisioner-daemon-psk) on the Coder server and start the provisioner with +`coder provisionerd start --psk `. If you are [installing with Helm](../install/kubernetes#install-coder-with-helm), +see the [Helm example](#example-running-an-external-provisioner-with-helm) below. -- PSK: Set a [provisioner daemon PSK](../cli/server#--provisioner-daemon-psk) on the Coder server and start the provisioner with `coder provisionerd start --psk ` -- User token: [Authenticate](../cli.md#--token) the Coder CLI as a user with the Template Admin or Owner role. +> Coder still supports authenticating the provisioner daemon with a [token](../cli.md#--token) from a user with the +> Template Admin or Owner role. This method is deprecated in favor of the PSK, which only has permission to access +> provisioner daemon APIs. We recommend migrating to the PSK as soon as practical. -### Types of provisioners +## Types of provisioners - **Generic provisioners** can pick up any build job from templates without provisioner tags. @@ -65,7 +66,68 @@ The provisioner server must authenticate with your Coder deployment. There are t --provisioner-tag scope=user ``` -### Example: Running an external provisioner on a VM +## Example: Running an external provisioner with Helm + +Coder provides a Helm chart for running external provisioner daemons, which you will use in concert with the Helm chart +for deploying the Coder server. + +1. Create a long, random pre-shared key (PSK) and store it in a Kubernetes secret + + ```shell + kubectl create secret generic coder-provisioner-psk --from-literal=psk=`head /dev/urandom | tr -dc A-Za-z0-9 | head -c 26` + ``` + +1. Modify your Coder `values.yaml` to include + + ```yaml + provisionerDaemon: + pskSecretName: "coder-provisioner-psk" + ``` + +1. Redeploy Coder with the new `values.yaml` to roll out the PSK. You can omit `--version ` to also upgrade + Coder to the latest version. + + ```shell + helm upgrade coder coder-v2/coder \ + --namespace coder \ + --version \ + --values values.yaml + ``` + +1. Create a `provisioner-values.yaml` file for the provisioner daemons Helm chart. For example + + ```yaml + coder: + env: + - name: CODER_URL + value: "https://coder.example.com" + replicaCount: 10 + provisionerDaemon: + pskSecretName: "coder-provisioner-psk" + tags: + location: auh + kind: k8s + ``` + + This example creates a deployment of 10 provisioner daemons (for 10 concurrent builds) with the listed tags. For + generic provisioners, remove the tags. + + > Refer to the [values.yaml](https://github.com/coder/coder/blob/main/helm/provisioner/values.yaml) file for the + > coder-provisioner chart for information on what values can be specified. + +1. Install the provisioner daemon chart + + ```shell + helm install coder-provisioner coder-v2/coder-provisioner \ + --namespace coder \ + --version \ + --values provisioner-values.yaml + ``` + + You can verify that your provisioner daemons have successfully connected to Coderd by looking for a log with message + `provisionerd successfully connected to coderd` from each Pod. + +## Example: Running an external provisioner on a VM ```sh curl -L https://coder.com/install.sh | sh @@ -74,7 +136,7 @@ export CODER_SESSION_TOKEN=your_token coder provisionerd start ``` -### Example: Running an external provisioner via Docker +## Example: Running an external provisioner via Docker ```sh docker run --rm -it \ diff --git a/helm/coder/charts/libcoder-0.1.0.tgz b/helm/coder/charts/libcoder-0.1.0.tgz index b799de7d00819..baae560bb8310 100644 Binary files a/helm/coder/charts/libcoder-0.1.0.tgz and b/helm/coder/charts/libcoder-0.1.0.tgz differ diff --git a/helm/provisioner/README.md b/helm/provisioner/README.md new file mode 100644 index 0000000000000..d1f8b6727fa11 --- /dev/null +++ b/helm/provisioner/README.md @@ -0,0 +1,36 @@ +# Coder Helm Chart + +This directory contains the Helm chart used to deploy Coder provisioner daemons onto a Kubernetes +cluster. + +External provisioner daemons are an Enterprise feature. Contact sales@coder.com. + +## Getting Started + +> **Warning**: The main branch in this repository does not represent the +> latest release of Coder. Please reference our installation docs for +> instructions on a tagged release. + +View +[our docs](https://coder.com/docs/v2/latest/admin/provisioners) +for detailed installation instructions. + +## Values + +Please refer to [values.yaml](values.yaml) for available Helm values and their +defaults. + +A good starting point for your values file is: + +```yaml +coder: + env: + - name: CODER_URL + value: "https://coder.example.com" + # This env enables the Prometheus metrics endpoint. + - name: CODER_PROMETHEUS_ADDRESS + value: "0.0.0.0:2112" + replicaCount: 10 +provisionerDaemon: + pskSecretName: "coder-provisioner-psk" +``` diff --git a/helm/provisioner/charts/libcoder-0.1.0.tgz b/helm/provisioner/charts/libcoder-0.1.0.tgz index 638d50f976a7e..094e3f64207ad 100644 Binary files a/helm/provisioner/charts/libcoder-0.1.0.tgz and b/helm/provisioner/charts/libcoder-0.1.0.tgz differ diff --git a/scripts/helm.sh b/scripts/helm.sh index 67edad0e149fc..1397281c7e3c4 100755 --- a/scripts/helm.sh +++ b/scripts/helm.sh @@ -4,15 +4,14 @@ # .tgz file at the specified path, and may optionally push it to the Coder OSS # repo. # -# ./helm.sh [--version 1.2.3] [--output path/to/coder.tgz] [--push] +# ./helm.sh [--version 1.2.3] [--chart coder|provisioner] [--output path/to/coder.tgz] # # If no version is specified, defaults to the version from ./version.sh. # -# If no output path is specified, defaults to -# "$repo_root/build/coder_helm_$version.tgz". +# If no chart is specified, defaults to 'coder' # -# If the --push parameter is specified, the resulting artifact will be published -# to the Coder OSS repo. This requires `gsutil` to be installed and configured. +# If no output path is specified, defaults to +# "$repo_root/build/$chart_helm_$version.tgz". set -euo pipefail # shellcheck source=scripts/lib.sh @@ -20,9 +19,9 @@ source "$(dirname "${BASH_SOURCE[0]}")/lib.sh" version="" output_path="" -push=0 +chart="" -args="$(getopt -o "" -l version:,output:,push -- "$@")" +args="$(getopt -o "" -l version:,chart:,output:,push -- "$@")" eval set -- "$args" while true; do case "$1" in @@ -30,14 +29,14 @@ while true; do version="$2" shift 2 ;; + --chart) + chart="$2" + shift 2 + ;; --output) output_path="$(realpath "$2")" shift 2 ;; - --push) - push="1" - shift - ;; --) shift break @@ -54,10 +53,17 @@ if [[ "$version" == "" ]]; then version="$(execrelative ./version.sh)" fi +if [[ "$chart" == "" ]]; then + chart="coder" +fi +if ! [[ "$chart" =~ ^(coder|provisioner)$ ]]; then + error "--chart value must be one of (coder, provisioner)" +fi + if [[ "$output_path" == "" ]]; then cdroot mkdir -p build - output_path="$(realpath "build/coder_helm_$version.tgz")" + output_path="$(realpath "build/${chart}_helm_${version}.tgz")" fi # Check dependencies @@ -69,10 +75,10 @@ cdroot temp_dir="$(mktemp -d)" cdroot -cd ./helm/coder +cd ./helm/$chart log "--- Updating dependencies" helm dependency update . -log "--- Packaging helm chart for version $version ($output_path)" +log "--- Packaging helm chart $chart for version $version ($output_path)" helm package \ --version "$version" \ --app-version "$version" \ @@ -82,8 +88,3 @@ helm package \ log "Moving helm chart to $output_path" cp "$temp_dir"/*.tgz "$output_path" rm -rf "$temp_dir" - -if [[ "$push" == 1 ]]; then - log "--- Publishing helm chart..." - # TODO: figure out how/where we want to publish the helm chart -fi