Skip to content

Commit 91a74f0

Browse files
johnstcnmafredri
andauthored
chore(examples): update kubernetes devcontainer template with envbuilder provider (coder#14267)
* chore(examples): update kubernetes devcontainer template with envbuilder provider * make insecure a template variable * Update examples/templates/devcontainer-kubernetes/README.md Co-authored-by: Mathias Fredriksson <mafredri@gmail.com> --------- Co-authored-by: Mathias Fredriksson <mafredri@gmail.com>
1 parent 4db8fa6 commit 91a74f0

File tree

2 files changed

+80
-15
lines changed

2 files changed

+80
-15
lines changed

examples/templates/devcontainer-kubernetes/README.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,8 @@ Provision Devcontainers as [Coder workspaces](https://coder.com/docs/workspaces)
1919

2020
**Container Image**: This template uses the [envbuilder image](https://github.com/coder/envbuilder) to build a Devcontainer from a `devcontainer.json`.
2121

22+
**(Optional) Cache Registry**: Envbuilder can utilize a Docker registry as a cache to speed up workspace builds. The [envbuilder Terraform provider](https://github.com/coder/terraform-provider-envbuilder) will check the contents of the cache to determine if a prebuilt image exists. In the case of some missing layers in the registry (partial cache miss), Envbuilder can still utilize some of the build cache from the registry.
23+
2224
### Authentication
2325

2426
This template authenticates using a `~/.kube/config`, if present on the server, or via built-in authentication if the Coder provisioner is running on Kubernetes with an authorized ServiceAccount. To use another [authentication method](https://registry.terraform.io/providers/hashicorp/kubernetes/latest/docs#authentication), edit the template.
@@ -31,6 +33,7 @@ This template provisions the following resources:
3133

3234
- Kubernetes deployment (ephemeral)
3335
- Kubernetes persistent volume claim (persistent on `/workspaces`)
36+
- Envbuilder cached image (optional, persistent).
3437

3538
This template will fetch a Git repo containing a `devcontainer.json` specified by the `repo` parameter, and builds it
3639
with [`envbuilder`](https://github.com/coder/envbuilder).
@@ -47,6 +50,8 @@ Edit the `devcontainer.json` instead!
4750
To speed up your builds, you can use a container registry as a cache.
4851
When creating the template, set the parameter `cache_repo`.
4952

53+
See the [Envbuilder Terraform Provider Examples](https://github.com/coder/terraform-provider-envbuilder/blob/main/examples/resources/envbuilder_cached_image/envbuilder_cached_image_resource.tf/) for a more complete example of how the provider works.
54+
5055
> [!NOTE] We recommend using a registry cache with authentication enabled.
5156
> To allow Envbuilder to authenticate with the registry cache, specify the variable `cache_repo_dockerconfig_secret`
5257
> with the name of a Kubernetes secret in the same namespace as Coder. The secret must contain the key `.dockerconfigjson`.

examples/templates/devcontainer-kubernetes/main.tf

Lines changed: 75 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,9 @@ terraform {
77
kubernetes = {
88
source = "hashicorp/kubernetes"
99
}
10+
envbuilder = {
11+
source = "coder/envbuilder"
12+
}
1013
}
1114
}
1215

@@ -15,6 +18,7 @@ provider "kubernetes" {
1518
# Authenticate via ~/.kube/config or a Coder-specific ServiceAccount, depending on admin preferences
1619
config_path = var.use_kubeconfig == true ? "~/.kube/config" : null
1720
}
21+
provider "envbuilder" {}
1822

1923
data "coder_provisioner" "me" {}
2024
data "coder_workspace" "me" {}
@@ -43,10 +47,15 @@ variable "namespace" {
4347
variable "cache_repo" {
4448
default = ""
4549
description = "Use a container registry as a cache to speed up builds."
46-
sensitive = true
4750
type = string
4851
}
4952

53+
variable "insecure_cache_repo" {
54+
default = false
55+
description = "Enable this option if your cache registry does not serve HTTPS."
56+
type = bool
57+
}
58+
5059
data "coder_parameter" "cpu" {
5160
type = "number"
5261
name = "cpu"
@@ -139,20 +148,45 @@ data "kubernetes_secret" "cache_repo_dockerconfig_secret" {
139148
}
140149

141150
locals {
142-
deployment_name = "coder-${data.coder_workspace_owner.me.name}-${lower(data.coder_workspace.me.name)}"
151+
deployment_name = "coder-${lower(data.coder_workspace.me.id)}"
143152
devcontainer_builder_image = data.coder_parameter.devcontainer_builder.value
144153
git_author_name = coalesce(data.coder_workspace_owner.me.full_name, data.coder_workspace_owner.me.name)
145154
git_author_email = data.coder_workspace_owner.me.email
146155
repo_url = data.coder_parameter.repo.value
156+
# The envbuilder provider requires a key-value map of environment variables.
157+
envbuilder_env = {
158+
"CODER_AGENT_TOKEN" : coder_agent.main.token,
159+
# Use the docker gateway if the access URL is 127.0.0.1
160+
"CODER_AGENT_URL" : replace(data.coder_workspace.me.access_url, "/localhost|127\\.0\\.0\\.1/", "host.docker.internal"),
161+
"ENVBUILDER_GIT_URL" : local.repo_url,
162+
# Use the docker gateway if the access URL is 127.0.0.1
163+
"ENVBUILDER_INIT_SCRIPT" : replace(coder_agent.main.init_script, "/localhost|127\\.0\\.0\\.1/", "host.docker.internal"),
164+
"ENVBUILDER_FALLBACK_IMAGE" : data.coder_parameter.fallback_image.value,
165+
"ENVBUILDER_CACHE_REPO" : var.cache_repo,
166+
"ENVBUILDER_DOCKER_CONFIG_BASE64" : try(data.kubernetes_secret.cache_repo_dockerconfig_secret[0].data[".dockerconfigjson"], ""),
167+
"ENVBUILDER_PUSH_IMAGE" : var.cache_repo == "" ? "" : "true",
168+
"ENVBUILDER_INSECURE" : "${var.insecure_cache_repo}",
169+
}
170+
}
171+
172+
# Check for the presence of a prebuilt image in the cache repo
173+
# that we can use instead.
174+
resource "envbuilder_cached_image" "cached" {
175+
count = var.cache_repo == "" ? 0 : data.coder_workspace.me.start_count
176+
builder_image = local.devcontainer_builder_image
177+
git_url = local.repo_url
178+
cache_repo = var.cache_repo
179+
extra_env = local.envbuilder_env
180+
insecure = var.insecure_cache_repo
147181
}
148182

149-
resource "kubernetes_persistent_volume_claim" "home" {
183+
resource "kubernetes_persistent_volume_claim" "workspaces" {
150184
metadata {
151-
name = "coder-${lower(data.coder_workspace_owner.me.name)}-${lower(data.coder_workspace.me.name)}-home"
185+
name = "coder-${lower(data.coder_workspace.me.id)}-workspaces"
152186
namespace = var.namespace
153187
labels = {
154-
"app.kubernetes.io/name" = "coder-pvc"
155-
"app.kubernetes.io/instance" = "coder-pvc-${lower(data.coder_workspace_owner.me.name)}-${lower(data.coder_workspace.me.name)}"
188+
"app.kubernetes.io/name" = "coder-${lower(data.coder_workspace.me.id)}-workspaces"
189+
"app.kubernetes.io/instance" = "coder-${lower(data.coder_workspace.me.id)}-workspaces"
156190
"app.kubernetes.io/part-of" = "coder"
157191
//Coder-specific labels.
158192
"com.coder.resource" = "true"
@@ -173,13 +207,14 @@ resource "kubernetes_persistent_volume_claim" "home" {
173207
storage = "${data.coder_parameter.workspaces_volume_size.value}Gi"
174208
}
175209
}
210+
# storage_class_name = "local-path" # Configure the StorageClass to use here, if required.
176211
}
177212
}
178213

179214
resource "kubernetes_deployment" "main" {
180215
count = data.coder_workspace.me.start_count
181216
depends_on = [
182-
kubernetes_persistent_volume_claim.home
217+
kubernetes_persistent_volume_claim.workspaces
183218
]
184219
wait_for_rollout = false
185220
metadata {
@@ -222,7 +257,7 @@ resource "kubernetes_deployment" "main" {
222257

223258
container {
224259
name = "dev"
225-
image = local.devcontainer_builder_image
260+
image = var.cache_repo == "" ? local.devcontainer_builder_image : envbuilder_cached_image.cached.0.image
226261
image_pull_policy = "Always"
227262
security_context {}
228263
env {
@@ -249,6 +284,14 @@ resource "kubernetes_deployment" "main" {
249284
name = "ENVBUILDER_CACHE_REPO"
250285
value = var.cache_repo
251286
}
287+
env {
288+
name = "ENVBUILDER_PUSH_IMAGE"
289+
value = var.cache_repo == "" ? "" : "true"
290+
}
291+
env {
292+
name = "ENVBUILDER_INSECURE"
293+
value = var.insecure_cache_repo
294+
}
252295
env {
253296
name = "ENVBUILDER_DOCKER_CONFIG_BASE64"
254297
value = try(data.kubernetes_secret.cache_repo_dockerconfig_secret[0].data[".dockerconfigjson"], "")
@@ -271,16 +314,16 @@ resource "kubernetes_deployment" "main" {
271314
}
272315
}
273316
volume_mount {
274-
mount_path = "/home/coder"
275-
name = "home"
317+
mount_path = "/workspaces"
318+
name = "workspaces"
276319
read_only = false
277320
}
278321
}
279322

280323
volume {
281-
name = "home"
324+
name = "workspaces"
282325
persistent_volume_claim {
283-
claim_name = kubernetes_persistent_volume_claim.home.metadata.0.name
326+
claim_name = kubernetes_persistent_volume_claim.workspaces.metadata.0.name
284327
read_only = false
285328
}
286329
}
@@ -357,9 +400,9 @@ resource "coder_agent" "main" {
357400
}
358401

359402
metadata {
360-
display_name = "Home Disk"
361-
key = "3_home_disk"
362-
script = "coder stat disk --path $HOME"
403+
display_name = "Workspaces Disk"
404+
key = "3_workspaces_disk"
405+
script = "coder stat disk --path /workspaces"
363406
interval = 60
364407
timeout = 1
365408
}
@@ -417,3 +460,20 @@ resource "coder_app" "code-server" {
417460
threshold = 6
418461
}
419462
}
463+
464+
resource "coder_metadata" "container_info" {
465+
count = data.coder_workspace.me.start_count
466+
resource_id = coder_agent.main.id
467+
item {
468+
key = "workspace image"
469+
value = var.cache_repo == "" ? local.devcontainer_builder_image : envbuilder_cached_image.cached.0.image
470+
}
471+
item {
472+
key = "git url"
473+
value = local.repo_url
474+
}
475+
item {
476+
key = "cache repo"
477+
value = var.cache_repo == "" ? "not enabled" : var.cache_repo
478+
}
479+
}

0 commit comments

Comments
 (0)