TemplatesModules
Back to Templates
Envbox (Kubernetes) Icon

Envbox (Kubernetes)

By:
Provision envbox pods as Coder workspaces
Source
README
Resources (2)
Variables (8)

Copy and paste the following into main.tf and run coder template push:

1terraform {
2  required_providers {
3    coder = {
4      source = "coder/coder"
5    }
6    kubernetes = {
7      source = "hashicorp/kubernetes"
8    }
9  }
10}
11
12data "coder_parameter" "home_disk" {
13  name        = "Disk Size"
14  description = "How large should the disk storing the home directory be?"
15  icon        = "https://cdn-icons-png.flaticon.com/512/2344/2344147.png"
16  type        = "number"
17  default     = 10
18  mutable     = true
19  validation {
20    min = 10
21    max = 100
22  }
23}
24
25variable "use_kubeconfig" {
26  type        = bool
27  sensitive   = true
28  default     = true
29  description = <<-EOF
30  Use host kubeconfig? (true/false)
31  Set this to false if the Coder host is itself running as a Pod on the same
32  Kubernetes cluster as you are deploying workspaces to.
33  Set this to true if the Coder host is running outside the Kubernetes cluster
34  for workspaces.  A valid "~/.kube/config" must be present on the Coder host.
35  EOF
36}
37
38provider "coder" {
39}
40
41variable "namespace" {
42  type        = string
43  sensitive   = true
44  description = "The namespace to create workspaces in (must exist prior to creating workspaces)"
45}
46
47variable "create_tun" {
48  type        = bool
49  sensitive   = true
50  description = "Add a TUN device to the workspace."
51  default     = false
52}
53
54variable "create_fuse" {
55  type        = bool
56  description = "Add a FUSE device to the workspace."
57  sensitive   = true
58  default     = false
59}
60
61variable "max_cpus" {
62  type        = string
63  sensitive   = true
64  description = "Max number of CPUs the workspace may use (e.g. 2)."
65}
66
67variable "min_cpus" {
68  type        = string
69  sensitive   = true
70  description = "Minimum number of CPUs the workspace may use (e.g. .1)."
71}
72
73variable "max_memory" {
74  type        = string
75  description = "Maximum amount of memory to allocate the workspace (in GB)."
76  sensitive   = true
77}
78
79variable "min_memory" {
80  type        = string
81  description = "Minimum amount of memory to allocate the workspace (in GB)."
82  sensitive   = true
83}
84
85provider "kubernetes" {
86  # Authenticate via ~/.kube/config or a Coder-specific ServiceAccount, depending on admin preferences
87  config_path = var.use_kubeconfig == true ? "~/.kube/config" : null
88}
89
90data "coder_workspace" "me" {}
91data "coder_workspace_owner" "me" {}
92
93resource "coder_agent" "main" {
94  os             = "linux"
95  arch           = "amd64"
96  startup_script = <<EOT
97    #!/bin/bash
98    # home folder can be empty, so copying default bash settings
99    if [ ! -f ~/.profile ]; then
100      cp /etc/skel/.profile $HOME
101    fi
102    if [ ! -f ~/.bashrc ]; then
103      cp /etc/skel/.bashrc $HOME
104    fi
105    # install and start code-server
106    curl -fsSL https://code-server.dev/install.sh | sh -s -- --version 4.8.3 | tee code-server-install.log
107    code-server --auth none --port 13337 | tee code-server-install.log &
108  EOT
109}
110
111# code-server
112resource "coder_app" "code-server" {
113  agent_id     = coder_agent.main.id
114  slug         = "code-server"
115  display_name = "code-server"
116  icon         = "/icon/code.svg"
117  url          = "http://localhost:13337?folder=/home/coder"
118  subdomain    = false
119  share        = "owner"
120
121  healthcheck {
122    url       = "http://localhost:13337/healthz"
123    interval  = 3
124    threshold = 10
125  }
126}
127
128resource "kubernetes_persistent_volume_claim" "home" {
129  metadata {
130    name      = "coder-${lower(data.coder_workspace_owner.me.name)}-${lower(data.coder_workspace.me.name)}-home"
131    namespace = var.namespace
132  }
133  wait_until_bound = false
134  spec {
135    access_modes = ["ReadWriteOnce"]
136    resources {
137      requests = {
138        storage = "${data.coder_parameter.home_disk.value}Gi"
139      }
140    }
141  }
142}
143
144resource "kubernetes_pod" "main" {
145  count = data.coder_workspace.me.start_count
146
147  metadata {
148    name      = "coder-${lower(data.coder_workspace_owner.me.name)}-${lower(data.coder_workspace.me.name)}"
149    namespace = var.namespace
150  }
151
152  spec {
153    restart_policy = "Never"
154
155    container {
156      name = "dev"
157      # We highly recommend pinning this to a specific release of envbox, as the latest tag may change.
158      image             = "ghcr.io/coder/envbox:latest"
159      image_pull_policy = "Always"
160      command           = ["/envbox", "docker"]
161
162      security_context {
163        privileged = true
164      }
165
166      resources {
167        requests = {
168          "cpu" : "${var.min_cpus}"
169          "memory" : "${var.min_memory}G"
170        }
171
172        limits = {
173          "cpu" : "${var.max_cpus}"
174          "memory" : "${var.max_memory}G"
175        }
176      }
177
178      env {
179        name  = "CODER_AGENT_TOKEN"
180        value = coder_agent.main.token
181      }
182
183      env {
184        name  = "CODER_AGENT_URL"
185        value = data.coder_workspace.me.access_url
186      }
187
188      env {
189        name  = "CODER_INNER_IMAGE"
190        value = "index.docker.io/codercom/enterprise-base@sha256:069e84783d134841cbb5007a16d9025b6aed67bc5b95eecc118eb96dccd6de68"
191      }
192
193      env {
194        name  = "CODER_INNER_USERNAME"
195        value = "coder"
196      }
197
198      env {
199        name  = "CODER_BOOTSTRAP_SCRIPT"
200        value = coder_agent.main.init_script
201      }
202
203      env {
204        name  = "CODER_MOUNTS"
205        value = "/home/coder:/home/coder"
206      }
207
208      env {
209        name  = "CODER_ADD_FUSE"
210        value = var.create_fuse
211      }
212
213      env {
214        name  = "CODER_INNER_HOSTNAME"
215        value = data.coder_workspace.me.name
216      }
217
218      env {
219        name  = "CODER_ADD_TUN"
220        value = var.create_tun
221      }
222
223      env {
224        name = "CODER_CPUS"
225        value_from {
226          resource_field_ref {
227            resource = "limits.cpu"
228          }
229        }
230      }
231
232      env {
233        name = "CODER_MEMORY"
234        value_from {
235          resource_field_ref {
236            resource = "limits.memory"
237          }
238        }
239      }
240
241      volume_mount {
242        mount_path = "/home/coder"
243        name       = "home"
244        read_only  = false
245        sub_path   = "home"
246      }
247
248      volume_mount {
249        mount_path = "/var/lib/coder/docker"
250        name       = "home"
251        sub_path   = "cache/docker"
252      }
253
254      volume_mount {
255        mount_path = "/var/lib/coder/containers"
256        name       = "home"
257        sub_path   = "cache/containers"
258      }
259
260      volume_mount {
261        mount_path = "/var/lib/sysbox"
262        name       = "sysbox"
263      }
264
265      volume_mount {
266        mount_path = "/var/lib/containers"
267        name       = "home"
268        sub_path   = "envbox/containers"
269      }
270
271      volume_mount {
272        mount_path = "/var/lib/docker"
273        name       = "home"
274        sub_path   = "envbox/docker"
275      }
276
277      volume_mount {
278        mount_path = "/usr/src"
279        name       = "usr-src"
280      }
281
282      volume_mount {
283        mount_path = "/lib/modules"
284        name       = "lib-modules"
285      }
286    }
287
288    volume {
289      name = "home"
290      persistent_volume_claim {
291        claim_name = kubernetes_persistent_volume_claim.home.metadata.0.name
292        read_only  = false
293      }
294    }
295
296    volume {
297      name = "sysbox"
298      empty_dir {}
299    }
300
301    volume {
302      name = "usr-src"
303      host_path {
304        path = "/usr/src"
305        type = ""
306      }
307    }
308
309    volume {
310      name = "lib-modules"
311      host_path {
312        path = "/lib/modules"
313        type = ""
314      }
315    }
316  }
317}
318