modified: README.md

This commit is contained in:
sakim 2024-03-29 07:17:54 +00:00
parent 97b7a2ba47
commit 534efcff12
3 changed files with 348 additions and 1 deletions

View File

@ -1,2 +1,65 @@
# coder-template
## Terminology
- **[code-server](https://github.com/coder/code-server)** : Open Source Visual Studio Code + web browser remote access
- **[coder](https://github.com/coder/coder)** : Development Environments (i.e. code-server, JupyterLab, JetBrains, and etc) management software
- **API-server** : LMS can call the endpoints of this API-server to manage **coder**.
## What is this?
You can use this template when you create a new lab and deploy it to **coder**. Lab users will get clients that include web IDE and software/tools (e.g. **[akamai CLI](https://github.com/akamai/cli)**).
- **build** : sample **API-server**
- **docker-compose.yaml** : installs **coder** and **API-server**
## Sample Workflow
- [ ] **Alice** : Content Creator
- [ ] **Bob** : Lab Administrator
**1. Servers vs Clients**
```
Alice ->> Bob: I'd like to create a new lab for ION.
Bob ->> Alice: Do you want servers or clients?
Alice ->> Bob: I'm not sure. It is a DevOps lab. Learners will run python, terraform, and httpie.
Bob ->> Alice: I suggest clients. Each learner can run codes or tools in his/her own isolated environment.
```
> Bob can create diverse types of servers (**Linux only!**) such as, web servers, application servers, and database servers.
Sample server: https://origin-akashop.akamai-lab.com/
>
> Bob can create one type of clients based on **Visual Studio Code**. Clients can be assigned to learners one to one or one to many.
Sample client: https://training.akamai.com/ewp
**2. Software**
```
Bob ->> Alice: Do you need any software or tools other than python, terraform, and httpie?
```
> Bob can install other softwares or tools such as **akamai cli**, based on the lab scenario.
**3. Infrastructure**
> Bob runs *docker-compose.yaml* file to create a default **coder** and **API-server**.
```
git clone https://gitea-ptl.akamai-lab.com/akamai/coder-template.git
cd coder-template
docker compose up -d
```
**4. code-server Template**
> Bob builds a code-server template by customizing **main.tf**.
>
> **/samples/main.tf** file can be a good starting point if you don't want to use persistant volume.
**5. Staging**
> Bob deploys a code-server to kubernetes staging environment and Alice validates it iteratively until they finalize code-server template.
>
> Bob should customize API-server codes, if Alice wants to integrate **coder** with **LMS** (for example, click a button on LMS to create a new code-server and get its URL).
**6. Production**
> Bob deploys a code-server to kubernetes production environment.
>
> Alice validates the client by end-to-end test.

View File

@ -11,7 +11,6 @@ services:
volumes:
- ./build/python:/home/python
coder:
# This MUST be stable for our documentation and
# other automations.
@ -37,6 +36,7 @@ services:
depends_on:
database:
condition: service_healthy
database:
image: "postgres:14.2"
ports:

284
samples/main.tf Normal file
View File

@ -0,0 +1,284 @@
terraform {
required_providers {
coder = {
source = "coder/coder"
}
kubernetes = {
source = "hashicorp/kubernetes"
}
}
}
provider "coder" {
}
variable "use_kubeconfig" {
type = bool
description = <<-EOF
Use host kubeconfig? (true/false)
Set this to false if the Coder host is itself running as a Pod on the same
Kubernetes cluster as you are deploying workspaces to.
Set this to true if the Coder host is running outside the Kubernetes cluster
for workspaces. A valid "~/.kube/config" must be present on the Coder host.
EOF
default = true
}
variable "namespace" {
type = string
description = "The Kubernetes namespace to create workspaces in (must exist prior to creating workspaces). If the Coder host is itself running as a Pod on the same Kubernetes cluster as you are deploying workspaces to, set this to the same namespace."
}
data "coder_parameter" "cpu" {
name = "cpu"
display_name = "CPU"
description = "The number of CPU cores"
default = "2"
icon = "/icon/memory.svg"
mutable = true
option {
name = "2 Cores"
value = "2"
}
option {
name = "4 Cores"
value = "4"
}
option {
name = "6 Cores"
value = "6"
}
option {
name = "8 Cores"
value = "8"
}
}
data "coder_parameter" "memory" {
name = "memory"
display_name = "Memory"
description = "The amount of memory in GB"
default = "2"
icon = "/icon/memory.svg"
mutable = true
option {
name = "2 GB"
value = "2"
}
option {
name = "4 GB"
value = "4"
}
option {
name = "6 GB"
value = "6"
}
option {
name = "8 GB"
value = "8"
}
}
data "coder_parameter" "home_disk_size" {
name = "home_disk_size"
display_name = "Home disk size"
description = "The size of the home disk in GB"
default = "10"
type = "number"
icon = "/emojis/1f4be.png"
mutable = false
validation {
min = 1
max = 99999
}
}
provider "kubernetes" {
# Authenticate via ~/.kube/config or a Coder-specific ServiceAccount, depending on admin preferences
config_path = var.use_kubeconfig == true ? "~/.kube/config" : null
}
data "coder_workspace" "me" {}
resource "coder_agent" "main" {
os = "linux"
arch = "amd64"
startup_script = <<-EOT
set -e
# install and start code-server
curl -fsSL https://code-server.dev/install.sh | sh -s -- --method=standalone --prefix=/tmp/code-server --version 4.11.0
/tmp/code-server/bin/code-server --auth none --port 13337 >/tmp/code-server.log 2>&1 &
EOT
# The following metadata blocks are optional. They are used to display
# information about your workspace in the dashboard. You can remove them
# if you don't want to display any information.
# For basic resources, you can use the `coder stat` command.
# If you need more control, you can write your own script.
metadata {
display_name = "CPU Usage"
key = "0_cpu_usage"
script = "coder stat cpu"
interval = 10
timeout = 1
}
metadata {
display_name = "RAM Usage"
key = "1_ram_usage"
script = "coder stat mem"
interval = 10
timeout = 1
}
metadata {
display_name = "Home Disk"
key = "3_home_disk"
script = "coder stat disk --path $${HOME}"
interval = 60
timeout = 1
}
metadata {
display_name = "CPU Usage (Host)"
key = "4_cpu_usage_host"
script = "coder stat cpu --host"
interval = 10
timeout = 1
}
metadata {
display_name = "Memory Usage (Host)"
key = "5_mem_usage_host"
script = "coder stat mem --host"
interval = 10
timeout = 1
}
metadata {
display_name = "Load Average (Host)"
key = "6_load_host"
# get load avg scaled by number of cores
script = <<EOT
echo "`cat /proc/loadavg | awk '{ print $1 }'` `nproc`" | awk '{ printf "%0.2f", $1/$2 }'
EOT
interval = 60
timeout = 1
}
}
# code-server
resource "coder_app" "code-server" {
agent_id = coder_agent.main.id
slug = "code-server"
display_name = "code-server"
icon = "/icon/code.svg"
url = "http://localhost:13337?folder=/home/coder"
subdomain = false
share = "owner"
healthcheck {
url = "http://localhost:13337/healthz"
interval = 3
threshold = 10
}
}
resource "kubernetes_deployment" "main" {
count = data.coder_workspace.me.start_count
wait_for_rollout = false
metadata {
name = "coder-${lower(data.coder_workspace.me.owner)}-${lower(data.coder_workspace.me.name)}"
namespace = var.namespace
labels = {
"app.kubernetes.io/name" = "coder-workspace"
"app.kubernetes.io/instance" = "coder-workspace-${lower(data.coder_workspace.me.owner)}-${lower(data.coder_workspace.me.name)}"
"app.kubernetes.io/part-of" = "coder"
"com.coder.resource" = "true"
"com.coder.workspace.id" = data.coder_workspace.me.id
"com.coder.workspace.name" = data.coder_workspace.me.name
"com.coder.user.id" = data.coder_workspace.me.owner_id
"com.coder.user.username" = data.coder_workspace.me.owner
}
annotations = {
"com.coder.user.email" = data.coder_workspace.me.owner_email
}
}
spec {
replicas = 1
selector {
match_labels = {
"app.kubernetes.io/name" = "coder-workspace"
}
}
strategy {
type = "Recreate"
}
template {
metadata {
labels = {
"app.kubernetes.io/name" = "coder-workspace"
}
}
spec {
security_context {
run_as_user = 1000
fs_group = 1000
}
container {
name = "dev"
image = "codercom/enterprise-base:ubuntu"
image_pull_policy = "Always"
command = ["sh", "-c", coder_agent.main.init_script]
security_context {
run_as_user = "1000"
}
env {
name = "CODER_AGENT_TOKEN"
value = coder_agent.main.token
}
resources {
requests = {
"cpu" = "250m"
"memory" = "512Mi"
}
limits = {
"cpu" = "${data.coder_parameter.cpu.value}"
"memory" = "${data.coder_parameter.memory.value}Gi"
}
}
}
affinity {
// This affinity attempts to spread out all workspace pods evenly across
// nodes.
pod_anti_affinity {
preferred_during_scheduling_ignored_during_execution {
weight = 1
pod_affinity_term {
topology_key = "kubernetes.io/hostname"
label_selector {
match_expressions {
key = "app.kubernetes.io/name"
operator = "In"
values = ["coder-workspace"]
}
}
}
}
}
}
}
}
}
}