Skip to content

Commit

Permalink
feat(nomad): improved nomad support (#798)
Browse files Browse the repository at this point in the history
This PR adds better support for our integration with Nomad. Although not
officially supported, we would like to improve the developer experience
and integrate automated e2e tests to avoid breaking Nomad integrations
with future csi-driver releases.

The Terraform module for creating a Nomad (+Consul) cluster on Hetzner
Cloud can be found
[here](https://github.com/hetznercloud/nomad-dev-env).
---------

Co-authored-by: Julian Tölle <[email protected]>
Co-authored-by: Jonas L. <[email protected]>
  • Loading branch information
3 people authored Dec 18, 2024
1 parent d0eba3e commit 4dbea7d
Show file tree
Hide file tree
Showing 17 changed files with 881 additions and 1 deletion.
74 changes: 74 additions & 0 deletions .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -115,3 +115,77 @@ jobs:
if: always()
continue-on-error: true
run: make -C dev down

nomad:
name: nomad ${{ matrix.nomad }}
runs-on: ubuntu-latest

permissions:
id-token: write

concurrency:
group: ${{ github.workflow }}-${{ github.ref }}-${{ matrix.nomad }}
cancel-in-progress: true

strategy:
fail-fast: false
matrix:
include:
- nomad: 1.9.3 # renovate: datasource=github-releases depName=hashicorp/nomad
consul: 1.20.1 # renovate: datasource=github-releases depName=hashicorp/consul

env:
TF_VAR_nomad_version: ${{ matrix.nomad }}
TF_VAR_consul_version: ${{ matrix.consul }}

steps:
- uses: actions/checkout@v4

- uses: actions/setup-go@v5
with:
go-version: "1.23"

- uses: opentofu/setup-opentofu@v1
with:
tofu_version: v1.8.6 # renovate: datasource=github-releases depName=opentofu/opentofu
tofu_wrapper: false

- uses: docker/setup-buildx-action@v3

- uses: yokawasa/[email protected]
with:
setup-tools: |
skaffold
skaffold: v2.13.2 # renovate: datasource=github-releases depName=GoogleContainerTools/skaffold

- uses: hashicorp/setup-nomad@main
id: setup
with:
version: ${{ matrix.nomad }}

# used for generating the certificates
- name: setup consul binary
run: |
curl -o consul.zip https://releases.hashicorp.com/consul/${{ matrix.consul }}/consul_${{ matrix.consul }}_linux_amd64.zip
unzip consul.zip
mv consul /usr/local/bin/
- uses: hetznercloud/tps-action@main

- name: Setup environment
run: make -C nomad/dev up

- name: Run skaffold
run: |
source nomad/dev/files/env.sh
skaffold -f nomad/skaffold.yaml build
- name: Run tests
run: |
source nomad/dev/files/env.sh
go test -v -tags e2e ./test/e2e/nomad/...
- name: Cleanup
if: always()
continue-on-error: true
run: make -C nomad/dev down
2 changes: 1 addition & 1 deletion docs/nomad/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

## Preconditions

- Nomad >= 1.4.x cluster installed following the [Nomad Reference Architecture for production deployments](https://developer.hashicorp.com/nomad/tutorials/enterprise/production-reference-architecture-vm-with-consul). The setup was tested on Nomad Community, version 1.5.x.
- Nomad >= 1.4.x cluster installed following the [Nomad Reference Architecture for production deployments](https://developer.hashicorp.com/nomad/tutorials/enterprise/production-reference-architecture-vm-with-consul). The setup was tested on Nomad Community, version 1.9.3.
- The cluster nodes need to have the `docker` driver installed & configured with [`allow_privileged = true`](https://developer.hashicorp.com/nomad/docs/drivers/docker#allow_privileged).
- The HCL resources are meant to be executed on a machine having nomad installed (with access to the Nomad API).

Expand Down
9 changes: 9 additions & 0 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -31,8 +31,17 @@ require (
github.com/google/go-cmp v0.6.0 // indirect
github.com/google/pprof v0.0.0-20240525223248-4bfdf5a9a2af // indirect
github.com/google/uuid v1.6.0 // indirect
github.com/gorilla/websocket v1.5.0 // indirect
github.com/grpc-ecosystem/go-grpc-middleware/v2 v2.1.0 // indirect
github.com/hashicorp/cronexpr v1.1.2 // indirect
github.com/hashicorp/errwrap v1.1.0 // indirect
github.com/hashicorp/go-cleanhttp v0.5.2 // indirect
github.com/hashicorp/go-multierror v1.1.1 // indirect
github.com/hashicorp/go-rootcerts v1.0.2 // indirect
github.com/hashicorp/nomad/api v0.0.0-20241125123754-1f29a95c2413 // indirect
github.com/klauspost/compress v1.17.11 // indirect
github.com/mitchellh/go-homedir v1.1.0 // indirect
github.com/mitchellh/mapstructure v1.5.0 // indirect
github.com/moby/sys/mountinfo v0.7.2 // indirect
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect
github.com/onsi/ginkgo/v2 v2.19.0 // indirect
Expand Down
19 changes: 19 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -29,10 +29,25 @@ github.com/google/pprof v0.0.0-20240525223248-4bfdf5a9a2af h1:kmjWCqn2qkEml422C2
github.com/google/pprof v0.0.0-20240525223248-4bfdf5a9a2af/go.mod h1:K1liHPHnj73Fdn/EKuT8nrFqBihUSKXoLYU0BuatOYo=
github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0=
github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/gorilla/websocket v1.5.0 h1:PPwGk2jz7EePpoHN/+ClbZu8SPxiqlu12wZP/3sWmnc=
github.com/gorilla/websocket v1.5.0/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE=
github.com/grpc-ecosystem/go-grpc-middleware/providers/prometheus v1.0.1 h1:qnpSQwGEnkcRpTqNOIR6bJbR0gAorgP9CSALpRcKoAA=
github.com/grpc-ecosystem/go-grpc-middleware/providers/prometheus v1.0.1/go.mod h1:lXGCsh6c22WGtjr+qGHj1otzZpV/1kwTMAqkwZsnWRU=
github.com/grpc-ecosystem/go-grpc-middleware/v2 v2.1.0 h1:pRhl55Yx1eC7BZ1N+BBWwnKaMyD8uC+34TLdndZMAKk=
github.com/grpc-ecosystem/go-grpc-middleware/v2 v2.1.0/go.mod h1:XKMd7iuf/RGPSMJ/U4HP0zS2Z9Fh8Ps9a+6X26m/tmI=
github.com/hashicorp/cronexpr v1.1.2 h1:wG/ZYIKT+RT3QkOdgYc+xsKWVRgnxJ1OJtjjy84fJ9A=
github.com/hashicorp/cronexpr v1.1.2/go.mod h1:P4wA0KBl9C5q2hABiMO7cp6jcIg96CDh1Efb3g1PWA4=
github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4=
github.com/hashicorp/errwrap v1.1.0 h1:OxrOeh75EUXMY8TBjag2fzXGZ40LB6IKw45YeGUDY2I=
github.com/hashicorp/errwrap v1.1.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4=
github.com/hashicorp/go-cleanhttp v0.5.2 h1:035FKYIWjmULyFRBKPs8TBQoi0x6d9G4xc9neXJWAZQ=
github.com/hashicorp/go-cleanhttp v0.5.2/go.mod h1:kO/YDlP8L1346E6Sodw+PrpBSV4/SoxCXGY6BqNFT48=
github.com/hashicorp/go-multierror v1.1.1 h1:H5DkEtf6CXdFp0N0Em5UCwQpXMWke8IA0+lD48awMYo=
github.com/hashicorp/go-multierror v1.1.1/go.mod h1:iw975J/qwKPdAO1clOe2L8331t/9/fmwbPZ6JB6eMoM=
github.com/hashicorp/go-rootcerts v1.0.2 h1:jzhAVGtqPKbwpyCPELlgNWhE1znq+qwJtW5Oi2viEzc=
github.com/hashicorp/go-rootcerts v1.0.2/go.mod h1:pqUvnprVnM5bf7AOirdbb01K4ccR319Vf4pU3K5EGc8=
github.com/hashicorp/nomad/api v0.0.0-20241125123754-1f29a95c2413 h1:k0Z3HkPTwMY51/P6gRe20+oCQq6mszc7xJnpM1A+T4w=
github.com/hashicorp/nomad/api v0.0.0-20241125123754-1f29a95c2413/go.mod h1:svtxn6QnrQ69P23VvIWMR34tg3vmwLz4UdUzm1dSCgE=
github.com/hetznercloud/hcloud-go/v2 v2.14.0 h1:WQW72DuOGqT486F0eNp92lDH5cwDTmyn9Mhin93m1To=
github.com/hetznercloud/hcloud-go/v2 v2.14.0/go.mod h1:h8sHav+27Xa+48cVMAvAUMELov5h298Ilg2vflyTHgg=
github.com/hetznercloud/hcloud-go/v2 v2.15.0 h1:6mpMJ/RuX1woZj+MCJdyKNEX9129KDkEIDeeyfr4GD4=
Expand All @@ -55,6 +70,10 @@ github.com/kubernetes-csi/csi-test/v5 v5.3.1 h1:Wiukp1In+kif+BFo6q2ExjgB+MbrAz4j
github.com/kubernetes-csi/csi-test/v5 v5.3.1/go.mod h1:7hA2cSYJ6T8CraEZPA6zqkLZwemjBD54XAnPsPC3VpA=
github.com/kylelemons/godebug v1.1.0 h1:RPNrshWIDI6G2gRW9EHilWtl7Z6Sb1BR0xunSBf0SNc=
github.com/kylelemons/godebug v1.1.0/go.mod h1:9/0rRGxNHcop5bhtWyNeEfOS8JIWk580+fNqagV/RAw=
github.com/mitchellh/go-homedir v1.1.0 h1:lukF9ziXFxDFPkA1vsr5zpc1XuPDn/wFntq5mG+4E0Y=
github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0=
github.com/mitchellh/mapstructure v1.5.0 h1:jeMsZIYE/09sWLaz43PL7Gy6RuMjD2eJVyuac5Z2hdY=
github.com/mitchellh/mapstructure v1.5.0/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo=
github.com/moby/buildkit v0.16.0 h1:wOVBj1o5YNVad/txPQNXUXdelm7Hs/i0PUFjzbK0VKE=
github.com/moby/buildkit v0.16.0/go.mod h1:Xqx/5GlrqE1yIRORk0NSCVDFpQAU1WjlT6KHYZdisIQ=
github.com/moby/buildkit v0.17.0 h1:ZA/4AxwBbve1f3ZaNNJQiCBtTV62R6YweWNwq4A+sTc=
Expand Down
56 changes: 56 additions & 0 deletions nomad/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
# Nomad

Hetzner Cloud does not provide official support for running the CSI driver in Nomad. Nonetheless, we would still like to offer a satisfying developer experience and have automated e2e tests to avoid breaking Nomad accidentally.

## Nomad Development Environment

As a prerequisite for developing Nomad, a setup of the [`nomad-dev-env`](https://github.com/hetznercloud/nomad-dev-env) is necessary, which is located in `nomad/dev`.

1. Setup the `HCLOUD_TOKEN` environment variable
2. Deploy the development cluster:

```bash
make -C nomad/dev up
```

3. Load the generated configuration to access the development cluster:

```bash
source nomad/dev/files/env.sh
```

4. Check that the cluster is healthy:

```bash
nomad node status
```

## Skaffold

Skaffold commands should be executed from the `csi-driver` root directory and use the `-f` flag to point to the Nomad specific `skaffold.yaml`.

```bash
skaffold -f nomad/skaffold.yaml build
```

Skaffold does not offer any native support for Nomad. For this reason we use the Nomad post build hooks to deploy/redeploy the csi plugin. To delete the csi plugin a manual execution of `stop_nomad.sh` is necessary.

```bash
bash ./nomad/stop_nomad.sh
```

## E2E Tests

The nomad e2e tests are located in `test/e2e/nomad` and need a working development environment.

1. Deploy the csi-driver

```bash
skaffold -f nomad/skaffold.yaml build
```

2. Run the e2e tests

```bash
go test -v -tags e2e ./test/e2e/nomad/...
```
6 changes: 6 additions & 0 deletions nomad/dev/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
.terraform/
terraform.tfstate*
.terraform.tfstate*
*.auto.tfvars

files/
76 changes: 76 additions & 0 deletions nomad/dev/.terraform.lock.hcl

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

26 changes: 26 additions & 0 deletions nomad/dev/Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
SHELL = bash

ENV ?= dev

env.auto.tfvars:
@echo 'hcloud_token = "$(HCLOUD_TOKEN)"' >> "$@"

.terraform:
tofu init

validate: .terraform
tofu validate

up: .terraform env.auto.tfvars
tofu apply -auto-approve
$(MAKE) port-forward

down: .terraform env.auto.tfvars
if test -f files/registry-port-forward.sh; then files/registry-port-forward.sh down; fi
tofu destroy -auto-approve

port-forward:
files/registry-port-forward.sh up

clean:
rm -Rf files/ .terraform/ terraform.tfstate* env.auto.tfvars
5 changes: 5 additions & 0 deletions nomad/dev/main.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
module "dev" {
source = "github.com/hetznercloud/nomad-dev-env?ref=v0.1.0" # renovate: datasource=github-releases depName=hetznercloud/nomad-dev-env

hcloud_token = var.hcloud_token
}
3 changes: 3 additions & 0 deletions nomad/dev/variables.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
variable "hcloud_token" {
sensitive = true
}
55 changes: 55 additions & 0 deletions nomad/hcloud-csi-controller.hcl
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
job "hcloud-csi-controller" {
datacenters = ["dc1"]
namespace = "default"
type = "service"

group "controller" {
count = 1

constraint {
distinct_hosts = true
}

update {
max_parallel = 1
canary = 1
min_healthy_time = "10s"
healthy_deadline = "1m"
auto_revert = true
auto_promote = true
}

task "plugin" {
driver = "docker"

config {
image = "$SKAFFOLD_IMAGE"
command = "bin/hcloud-csi-driver-controller"
}

env {
CSI_ENDPOINT = "unix://csi/csi.sock"
ENABLE_METRICS = true
}

template {
data = <<EOH
HCLOUD_TOKEN="{{ with nomadVar "secrets/hcloud" }}{{ .hcloud_token }}{{ end }}"
EOH
destination = "${NOMAD_SECRETS_DIR}/hcloud-token.env"
env = true
}

csi_plugin {
id = "csi.hetzner.cloud"
type = "controller"
mount_dir = "/csi"
}

resources {
cpu = 100
memory = 64
}
}
}
}
Loading

0 comments on commit 4dbea7d

Please sign in to comment.