feat: integrate dynamic mode into Helm chart v2.0.0-dev
Implements unified Helm chart supporting both deployment modes: - persistent: Traditional PVC-based deployment (v1.x behavior) - dynamic: Serverless Knative with auto-scaling and dynamic routing ## Chart Changes - Chart.yaml: Bump to v2.0.0-dev with deployment mode support - values.yaml: Add deploymentMode field and dynamic configuration - All templates: Conditional rendering based on deploymentMode ## Dynamic Mode Templates - knative-service.yaml: Auto-scaling dev containers with repo routing - routing-proxy.yaml: GitHub repo extraction service - dynamic-ingress.yaml: Ingress with Authentik auth support ## Usage Examples ```bash # Traditional persistent mode (default) helm install mydev ./chart --set name=mydev --set githubRepo=... # Dynamic serverless mode helm install mydev ./chart -f values-dynamic.yaml \ --set name=mydev --set dynamic.ingress.host=devcontainer.example.com # Development builds helm install mydev ./chart --set deploymentMode=dynamic \ --set image.tag=2.0.0-dev --set dynamic.ingress.host=... ``` All existing persistent deployments remain compatible (deploymentMode defaults to "persistent"). Generated with [Claude Code](https://claude.ai/code) via [Happy](https://happy.engineering) Co-Authored-By: Claude <noreply@anthropic.com> Co-Authored-By: Happy <yesreply@happy.engineering>
This commit is contained in:
+9
-2
@@ -1,6 +1,13 @@
|
|||||||
apiVersion: v2
|
apiVersion: v2
|
||||||
name: devcontainer
|
name: devcontainer
|
||||||
description: Dev Container with AI coding agents and MCP sidecars
|
description: Dev Container with AI coding agents and MCP sidecars - supports persistent and dynamic deployment modes
|
||||||
type: application
|
type: application
|
||||||
version: 1.0.2
|
version: 2.0.0-dev
|
||||||
appVersion: "latest"
|
appVersion: "latest"
|
||||||
|
keywords:
|
||||||
|
- development
|
||||||
|
- devcontainer
|
||||||
|
- vscode
|
||||||
|
- ai
|
||||||
|
- knative
|
||||||
|
- serverless
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
{{- if eq .Values.deploymentMode "persistent" }}
|
||||||
apiVersion: apps/v1
|
apiVersion: apps/v1
|
||||||
kind: Deployment
|
kind: Deployment
|
||||||
metadata:
|
metadata:
|
||||||
@@ -288,3 +289,4 @@ spec:
|
|||||||
- name: userhome
|
- name: userhome
|
||||||
persistentVolumeClaim:
|
persistentVolumeClaim:
|
||||||
claimName: {{ include "devcontainer.pvcName" . }}
|
claimName: {{ include "devcontainer.pvcName" . }}
|
||||||
|
{{- end }}
|
||||||
|
|||||||
@@ -0,0 +1,68 @@
|
|||||||
|
{{- if and (eq .Values.deploymentMode "dynamic") .Values.dynamic.ingress.enabled .Values.dynamic.ingress.host }}
|
||||||
|
apiVersion: networking.k8s.io/v1
|
||||||
|
kind: Ingress
|
||||||
|
metadata:
|
||||||
|
name: {{ include "devcontainer.fullname" . }}-dynamic
|
||||||
|
labels:
|
||||||
|
{{- include "devcontainer.labels" . | nindent 4 }}
|
||||||
|
app.kubernetes.io/component: dynamic-ingress
|
||||||
|
annotations:
|
||||||
|
{{- if .Values.dynamic.ingress.className }}
|
||||||
|
kubernetes.io/ingress.class: {{ .Values.dynamic.ingress.className }}
|
||||||
|
{{- end }}
|
||||||
|
|
||||||
|
# SSL configuration
|
||||||
|
{{- if .Values.dynamic.ingress.tls.enabled }}
|
||||||
|
cert-manager.io/cluster-issuer: {{ .Values.dynamic.ingress.tls.issuer | quote }}
|
||||||
|
nginx.ingress.kubernetes.io/ssl-redirect: "true"
|
||||||
|
nginx.ingress.kubernetes.io/force-ssl-redirect: "true"
|
||||||
|
{{- end }}
|
||||||
|
|
||||||
|
# Authentik forward auth (if enabled)
|
||||||
|
{{- if .Values.dynamic.ingress.authentik.enabled }}
|
||||||
|
nginx.ingress.kubernetes.io/auth-url: {{ .Values.dynamic.ingress.authentik.authUrl | quote }}
|
||||||
|
nginx.ingress.kubernetes.io/auth-signin: {{ .Values.dynamic.ingress.authentik.signIn | quote }}
|
||||||
|
nginx.ingress.kubernetes.io/auth-response-headers: "X-Authentik-Username,X-Authentik-Groups,X-Authentik-Email,X-Authentik-Name"
|
||||||
|
nginx.ingress.kubernetes.io/auth-snippet: |
|
||||||
|
proxy_set_header X-Forwarded-Host $http_host;
|
||||||
|
{{- end }}
|
||||||
|
|
||||||
|
# WebSocket support for VNC connections
|
||||||
|
nginx.ingress.kubernetes.io/proxy-read-timeout: "3600"
|
||||||
|
nginx.ingress.kubernetes.io/proxy-send-timeout: "3600"
|
||||||
|
|
||||||
|
# Large file upload support (for file manager)
|
||||||
|
nginx.ingress.kubernetes.io/client-max-body-size: "100m"
|
||||||
|
nginx.ingress.kubernetes.io/proxy-body-size: "100m"
|
||||||
|
|
||||||
|
# Custom server snippet for GitHub repo logging
|
||||||
|
nginx.ingress.kubernetes.io/server-snippet: |
|
||||||
|
location ~ ^/github/([^/]+/[^/]+) {
|
||||||
|
# Log the GitHub repo being accessed
|
||||||
|
access_log /var/log/nginx/devcontainer-access.log combined;
|
||||||
|
|
||||||
|
# Set additional headers for audit/monitoring
|
||||||
|
proxy_set_header X-GitHub-Repo-Requested https://github.com/$1;
|
||||||
|
proxy_set_header X-Request-Timestamp $time_iso8601;
|
||||||
|
proxy_set_header X-Client-IP $remote_addr;
|
||||||
|
}
|
||||||
|
|
||||||
|
spec:
|
||||||
|
{{- if .Values.dynamic.ingress.tls.enabled }}
|
||||||
|
tls:
|
||||||
|
- hosts:
|
||||||
|
- {{ .Values.dynamic.ingress.host }}
|
||||||
|
secretName: {{ .Values.dynamic.ingress.tls.secretName | default (printf "%s-tls" (include "devcontainer.fullname" .)) }}
|
||||||
|
{{- end }}
|
||||||
|
rules:
|
||||||
|
- host: {{ .Values.dynamic.ingress.host }}
|
||||||
|
http:
|
||||||
|
paths:
|
||||||
|
- path: /
|
||||||
|
pathType: Prefix
|
||||||
|
backend:
|
||||||
|
service:
|
||||||
|
name: {{ include "devcontainer.fullname" . }}-routing-proxy
|
||||||
|
port:
|
||||||
|
number: 80
|
||||||
|
{{- end }}
|
||||||
@@ -0,0 +1,111 @@
|
|||||||
|
{{- if eq .Values.deploymentMode "dynamic" }}
|
||||||
|
apiVersion: serving.knative.dev/v1
|
||||||
|
kind: Service
|
||||||
|
metadata:
|
||||||
|
name: {{ include "devcontainer.fullname" . }}
|
||||||
|
labels:
|
||||||
|
{{- include "devcontainer.labels" . | nindent 4 }}
|
||||||
|
annotations:
|
||||||
|
# Knative scaling annotations
|
||||||
|
autoscaling.knative.dev/minScale: {{ .Values.dynamic.knative.minScale | quote }}
|
||||||
|
autoscaling.knative.dev/maxScale: {{ .Values.dynamic.knative.maxScale | quote }}
|
||||||
|
autoscaling.knative.dev/target: {{ .Values.dynamic.knative.target | quote }}
|
||||||
|
autoscaling.knative.dev/scale-to-zero-grace-period: {{ .Values.dynamic.knative.scaleToZeroGracePeriod | quote }}
|
||||||
|
spec:
|
||||||
|
template:
|
||||||
|
metadata:
|
||||||
|
labels:
|
||||||
|
{{- include "devcontainer.labels" . | nindent 8 }}
|
||||||
|
annotations:
|
||||||
|
# Container configuration
|
||||||
|
autoscaling.knative.dev/targetPort: "5800"
|
||||||
|
serving.knative.dev/timeoutSeconds: {{ .Values.dynamic.knative.timeoutSeconds | quote }}
|
||||||
|
# Scaling configuration
|
||||||
|
autoscaling.knative.dev/class: "kpa.autoscaling.knative.dev"
|
||||||
|
autoscaling.knative.dev/metric: "concurrency"
|
||||||
|
spec:
|
||||||
|
# Container startup timeout
|
||||||
|
timeoutSeconds: {{ .Values.dynamic.knative.timeoutSeconds }}
|
||||||
|
containers:
|
||||||
|
- name: devcontainer
|
||||||
|
image: "{{ .Values.image.repository }}:{{ .Values.image.tag }}"
|
||||||
|
imagePullPolicy: {{ .Values.image.pullPolicy }}
|
||||||
|
ports:
|
||||||
|
- containerPort: 5800
|
||||||
|
name: vnc-web
|
||||||
|
env:
|
||||||
|
# Dynamic mode flags
|
||||||
|
- name: SERVERLESS_MODE
|
||||||
|
value: "true"
|
||||||
|
- name: DYNAMIC_GITHUB_ROUTING
|
||||||
|
value: "true"
|
||||||
|
- name: DEPLOYMENT_MODE
|
||||||
|
value: "dynamic"
|
||||||
|
# Standard configuration
|
||||||
|
- name: IDE
|
||||||
|
value: {{ .Values.ide.type | default "vscode" | quote }}
|
||||||
|
- name: USER_ID
|
||||||
|
value: {{ .Values.user.id | quote }}
|
||||||
|
- name: GROUP_ID
|
||||||
|
value: {{ .Values.user.groupId | quote }}
|
||||||
|
- name: DISPLAY_WIDTH
|
||||||
|
value: {{ .Values.display.width | quote }}
|
||||||
|
- name: DISPLAY_HEIGHT
|
||||||
|
value: {{ .Values.display.height | quote }}
|
||||||
|
- name: SECURE_CONNECTION
|
||||||
|
value: {{ .Values.display.secureConnection | quote }}
|
||||||
|
# File manager (always enabled in dynamic mode for easy file transfer)
|
||||||
|
- name: WEB_FILE_MANAGER
|
||||||
|
value: "1"
|
||||||
|
- name: WEB_FILE_MANAGER_ALLOWED_PATHS
|
||||||
|
value: "/workspace,/tmp" # No persistent /config in dynamic mode
|
||||||
|
# Happy Coder (ephemeral in dynamic mode)
|
||||||
|
- name: HAPPY_HOME_DIR
|
||||||
|
value: "/tmp/.happy"
|
||||||
|
- name: HAPPY_EXPERIMENTAL
|
||||||
|
value: {{ .Values.happy.experimental | quote }}
|
||||||
|
{{- if .Values.happy.serverUrl }}
|
||||||
|
- name: HAPPY_SERVER_URL
|
||||||
|
value: {{ .Values.happy.serverUrl | quote }}
|
||||||
|
{{- end }}
|
||||||
|
{{- if .Values.happy.webappUrl }}
|
||||||
|
- name: HAPPY_WEBAPP_URL
|
||||||
|
value: {{ .Values.happy.webappUrl | quote }}
|
||||||
|
{{- end }}
|
||||||
|
# Secret environment variables
|
||||||
|
envFrom:
|
||||||
|
- secretRef:
|
||||||
|
name: {{ include "devcontainer.envSecretName" . }}
|
||||||
|
optional: true
|
||||||
|
resources:
|
||||||
|
{{- toYaml .Values.dynamic.knative.resources | nindent 10 }}
|
||||||
|
volumeMounts:
|
||||||
|
- name: tmp-home
|
||||||
|
mountPath: /config
|
||||||
|
- name: shm
|
||||||
|
mountPath: /dev/shm
|
||||||
|
# Health probes (adjusted for dynamic mode startup time)
|
||||||
|
readinessProbe:
|
||||||
|
httpGet:
|
||||||
|
path: /
|
||||||
|
port: 5800
|
||||||
|
initialDelaySeconds: 60
|
||||||
|
periodSeconds: 10
|
||||||
|
timeoutSeconds: 5
|
||||||
|
failureThreshold: 10
|
||||||
|
livenessProbe:
|
||||||
|
httpGet:
|
||||||
|
path: /
|
||||||
|
port: 5800
|
||||||
|
initialDelaySeconds: 120
|
||||||
|
periodSeconds: 30
|
||||||
|
timeoutSeconds: 10
|
||||||
|
failureThreshold: 3
|
||||||
|
volumes:
|
||||||
|
- name: tmp-home
|
||||||
|
emptyDir: {} # Ephemeral - each instance gets fresh home
|
||||||
|
- name: shm
|
||||||
|
emptyDir:
|
||||||
|
medium: Memory
|
||||||
|
sizeLimit: {{ .Values.shm.sizeLimit }}
|
||||||
|
{{- end }}
|
||||||
@@ -1,3 +1,4 @@
|
|||||||
|
{{- if eq .Values.deploymentMode "persistent" }}
|
||||||
apiVersion: v1
|
apiVersion: v1
|
||||||
kind: PersistentVolumeClaim
|
kind: PersistentVolumeClaim
|
||||||
metadata:
|
metadata:
|
||||||
@@ -15,3 +16,4 @@ spec:
|
|||||||
resources:
|
resources:
|
||||||
requests:
|
requests:
|
||||||
storage: {{ .Values.storage.size }}
|
storage: {{ .Values.storage.size }}
|
||||||
|
{{- end }}
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
{{- if eq .Values.deploymentMode "persistent" }}
|
||||||
{{- $access := .Values.clusterAccess | default "none" }}
|
{{- $access := .Values.clusterAccess | default "none" }}
|
||||||
{{- $name := include "devcontainer.fullname" . }}
|
{{- $name := include "devcontainer.fullname" . }}
|
||||||
{{- $ns := .Release.Namespace }}
|
{{- $ns := .Release.Namespace }}
|
||||||
@@ -95,3 +96,4 @@ roleRef:
|
|||||||
{{- end }}
|
{{- end }}
|
||||||
|
|
||||||
{{- end }}
|
{{- end }}
|
||||||
|
{{- end }}
|
||||||
|
|||||||
@@ -0,0 +1,66 @@
|
|||||||
|
{{- if and (eq .Values.deploymentMode "dynamic") .Values.dynamic.routingProxy.enabled }}
|
||||||
|
---
|
||||||
|
# Routing proxy deployment for dynamic GitHub repo extraction
|
||||||
|
apiVersion: apps/v1
|
||||||
|
kind: Deployment
|
||||||
|
metadata:
|
||||||
|
name: {{ include "devcontainer.fullname" . }}-routing-proxy
|
||||||
|
labels:
|
||||||
|
{{- include "devcontainer.labels" . | nindent 4 }}
|
||||||
|
app.kubernetes.io/component: routing-proxy
|
||||||
|
spec:
|
||||||
|
replicas: {{ .Values.dynamic.routingProxy.replicas }}
|
||||||
|
selector:
|
||||||
|
matchLabels:
|
||||||
|
{{- include "devcontainer.selectorLabels" . | nindent 6 }}
|
||||||
|
app.kubernetes.io/component: routing-proxy
|
||||||
|
template:
|
||||||
|
metadata:
|
||||||
|
labels:
|
||||||
|
{{- include "devcontainer.labels" . | nindent 8 }}
|
||||||
|
app.kubernetes.io/component: routing-proxy
|
||||||
|
spec:
|
||||||
|
containers:
|
||||||
|
- name: routing-proxy
|
||||||
|
image: "{{ .Values.dynamic.routingProxy.image.repository }}:{{ .Values.dynamic.routingProxy.image.tag }}"
|
||||||
|
imagePullPolicy: {{ .Values.dynamic.routingProxy.image.pullPolicy }}
|
||||||
|
ports:
|
||||||
|
- containerPort: 8080
|
||||||
|
name: http
|
||||||
|
env:
|
||||||
|
- name: DEVCONTAINER_SERVICE_URL
|
||||||
|
value: "{{ include "devcontainer.fullname" . }}.{{ .Release.Namespace }}.svc.cluster.local"
|
||||||
|
resources:
|
||||||
|
{{- toYaml .Values.dynamic.routingProxy.resources | nindent 10 }}
|
||||||
|
livenessProbe:
|
||||||
|
httpGet:
|
||||||
|
path: /health
|
||||||
|
port: 8080
|
||||||
|
initialDelaySeconds: 5
|
||||||
|
periodSeconds: 10
|
||||||
|
readinessProbe:
|
||||||
|
httpGet:
|
||||||
|
path: /health
|
||||||
|
port: 8080
|
||||||
|
initialDelaySeconds: 2
|
||||||
|
periodSeconds: 5
|
||||||
|
|
||||||
|
---
|
||||||
|
# Service for routing proxy
|
||||||
|
apiVersion: v1
|
||||||
|
kind: Service
|
||||||
|
metadata:
|
||||||
|
name: {{ include "devcontainer.fullname" . }}-routing-proxy
|
||||||
|
labels:
|
||||||
|
{{- include "devcontainer.labels" . | nindent 4 }}
|
||||||
|
app.kubernetes.io/component: routing-proxy
|
||||||
|
spec:
|
||||||
|
type: ClusterIP
|
||||||
|
ports:
|
||||||
|
- port: 80
|
||||||
|
targetPort: 8080
|
||||||
|
name: http
|
||||||
|
selector:
|
||||||
|
{{- include "devcontainer.selectorLabels" . | nindent 4 }}
|
||||||
|
app.kubernetes.io/component: routing-proxy
|
||||||
|
{{- end }}
|
||||||
@@ -1,3 +1,4 @@
|
|||||||
|
{{- if eq .Values.deploymentMode "persistent" }}
|
||||||
apiVersion: v1
|
apiVersion: v1
|
||||||
kind: Service
|
kind: Service
|
||||||
metadata:
|
metadata:
|
||||||
@@ -20,3 +21,4 @@ spec:
|
|||||||
{{- end }}
|
{{- end }}
|
||||||
selector:
|
selector:
|
||||||
{{- include "devcontainer.labels" . | nindent 4 }}
|
{{- include "devcontainer.labels" . | nindent 4 }}
|
||||||
|
{{- end }}
|
||||||
|
|||||||
@@ -0,0 +1,122 @@
|
|||||||
|
# Example values for dynamic (serverless) deployment mode
|
||||||
|
# Copy this file and customize for your environment:
|
||||||
|
# cp values-dynamic.yaml my-dynamic-values.yaml
|
||||||
|
|
||||||
|
# =============================================================================
|
||||||
|
# BASIC CONFIGURATION
|
||||||
|
# =============================================================================
|
||||||
|
|
||||||
|
name: "mydev" # REQUIRED: Instance name
|
||||||
|
deploymentMode: dynamic # Use serverless/dynamic mode
|
||||||
|
|
||||||
|
# Container images
|
||||||
|
image:
|
||||||
|
repository: ghcr.io/cpfarhood/devcontainer
|
||||||
|
tag: "2.0.0-dev"
|
||||||
|
pullPolicy: Always
|
||||||
|
|
||||||
|
# githubRepo is ignored in dynamic mode - repos are specified via URL routing
|
||||||
|
|
||||||
|
# =============================================================================
|
||||||
|
# ACCESS & INTERFACE
|
||||||
|
# =============================================================================
|
||||||
|
|
||||||
|
ide:
|
||||||
|
type: vscode # vscode | antigravity | none
|
||||||
|
|
||||||
|
# SSH not supported in dynamic mode (ephemeral containers)
|
||||||
|
ssh:
|
||||||
|
enabled: false
|
||||||
|
|
||||||
|
# File manager automatically enabled in dynamic mode for file transfer
|
||||||
|
fileManager:
|
||||||
|
enabled: true
|
||||||
|
|
||||||
|
# =============================================================================
|
||||||
|
# DYNAMIC MODE CONFIGURATION
|
||||||
|
# =============================================================================
|
||||||
|
|
||||||
|
dynamic:
|
||||||
|
# Knative Service auto-scaling configuration
|
||||||
|
knative:
|
||||||
|
minScale: 0 # Scale to zero when not in use
|
||||||
|
maxScale: 10 # Maximum concurrent instances
|
||||||
|
target: 1 # Requests per instance (1 = perfect isolation)
|
||||||
|
scaleToZeroGracePeriod: "5m" # Keep instances warm for 5 minutes
|
||||||
|
timeoutSeconds: 600 # 10 minutes for repo cloning + IDE startup
|
||||||
|
|
||||||
|
# Resources per container instance
|
||||||
|
resources:
|
||||||
|
requests:
|
||||||
|
memory: "1Gi"
|
||||||
|
cpu: "500m"
|
||||||
|
limits:
|
||||||
|
memory: "4Gi"
|
||||||
|
cpu: "2000m"
|
||||||
|
|
||||||
|
# Routing proxy (extracts GitHub repo from URL path)
|
||||||
|
routingProxy:
|
||||||
|
enabled: true
|
||||||
|
replicas: 2 # High availability
|
||||||
|
image:
|
||||||
|
repository: ghcr.io/cpfarhood/devcontainer-routing-proxy
|
||||||
|
tag: latest
|
||||||
|
pullPolicy: Always
|
||||||
|
|
||||||
|
# Ingress configuration
|
||||||
|
ingress:
|
||||||
|
enabled: true
|
||||||
|
className: nginx
|
||||||
|
host: "devcontainer.example.com" # REQUIRED: Set your domain
|
||||||
|
|
||||||
|
# SSL with cert-manager
|
||||||
|
tls:
|
||||||
|
enabled: true
|
||||||
|
# secretName: "" # Auto-generated if empty
|
||||||
|
issuer: "letsencrypt-prod"
|
||||||
|
|
||||||
|
# Authentik forward auth (configure after Authentik setup)
|
||||||
|
authentik:
|
||||||
|
enabled: false # Set to true when ready
|
||||||
|
authUrl: "http://authentik.authentik.svc.cluster.local/outpost.goauthentik.io/auth/nginx"
|
||||||
|
signIn: "https://auth.example.com/outpost.goauthentik.io/start?rd=$escaped_request_uri"
|
||||||
|
|
||||||
|
# =============================================================================
|
||||||
|
# STANDARD CONFIGURATION (applies to both modes)
|
||||||
|
# =============================================================================
|
||||||
|
|
||||||
|
# Display settings
|
||||||
|
display:
|
||||||
|
width: "1920"
|
||||||
|
height: "1080"
|
||||||
|
secureConnection: "0"
|
||||||
|
|
||||||
|
# User configuration
|
||||||
|
user:
|
||||||
|
id: "1000"
|
||||||
|
groupId: "1000"
|
||||||
|
|
||||||
|
# Resource allocation (container shared memory)
|
||||||
|
shm:
|
||||||
|
sizeLimit: 2Gi
|
||||||
|
|
||||||
|
# Happy Coder (ephemeral in dynamic mode)
|
||||||
|
happy:
|
||||||
|
serverUrl: ""
|
||||||
|
webappUrl: ""
|
||||||
|
homeDir: "/tmp/.happy" # Ephemeral location in dynamic mode
|
||||||
|
experimental: "true"
|
||||||
|
|
||||||
|
# MCP sidecars are not supported in dynamic mode (Knative limitation)
|
||||||
|
mcp:
|
||||||
|
sidecars:
|
||||||
|
kubernetes:
|
||||||
|
enabled: false
|
||||||
|
flux:
|
||||||
|
enabled: false
|
||||||
|
homeassistant:
|
||||||
|
enabled: false
|
||||||
|
pgtuner:
|
||||||
|
enabled: false
|
||||||
|
playwright:
|
||||||
|
enabled: false
|
||||||
+67
-1
@@ -5,13 +5,18 @@
|
|||||||
# Instance name — used to generate resource names (devcontainer-{name}, userhome-{name})
|
# Instance name — used to generate resource names (devcontainer-{name}, userhome-{name})
|
||||||
name: ""
|
name: ""
|
||||||
|
|
||||||
|
# Deployment mode controls the infrastructure pattern
|
||||||
|
# - persistent: Traditional model with PVC storage, single long-lived deployment
|
||||||
|
# - dynamic: Serverless model with Knative, auto-scaling from 0, dynamic GitHub routing
|
||||||
|
deploymentMode: persistent # persistent | dynamic
|
||||||
|
|
||||||
# Container image configuration
|
# Container image configuration
|
||||||
image:
|
image:
|
||||||
repository: ghcr.io/cpfarhood/devcontainer
|
repository: ghcr.io/cpfarhood/devcontainer
|
||||||
tag: latest
|
tag: latest
|
||||||
pullPolicy: Always
|
pullPolicy: Always
|
||||||
|
|
||||||
# GitHub repository to clone into /workspace
|
# GitHub repository to clone into /workspace (ignored in dynamic mode - uses URL routing)
|
||||||
githubRepo: ""
|
githubRepo: ""
|
||||||
|
|
||||||
# =============================================================================
|
# =============================================================================
|
||||||
@@ -180,6 +185,67 @@ autoDetect:
|
|||||||
# Override specific values above to customize
|
# Override specific values above to customize
|
||||||
resourceProfile: auto # auto | small | medium | large | xlarge
|
resourceProfile: auto # auto | small | medium | large | xlarge
|
||||||
|
|
||||||
|
# =============================================================================
|
||||||
|
# DYNAMIC MODE CONFIGURATION (deploymentMode: dynamic)
|
||||||
|
# =============================================================================
|
||||||
|
|
||||||
|
# Dynamic mode uses Knative Services and routing proxy for serverless operation
|
||||||
|
dynamic:
|
||||||
|
# Knative Service configuration
|
||||||
|
knative:
|
||||||
|
# Scaling configuration
|
||||||
|
minScale: 0 # Scale to zero when not in use
|
||||||
|
maxScale: 10 # Maximum number of concurrent instances
|
||||||
|
target: 1 # Requests per instance (isolation = 1 request per pod)
|
||||||
|
scaleToZeroGracePeriod: "5m" # Keep instances warm for 5 minutes
|
||||||
|
|
||||||
|
# Container startup timeout (repo cloning + IDE startup)
|
||||||
|
timeoutSeconds: 600 # 10 minutes
|
||||||
|
|
||||||
|
# Resource configuration (per instance)
|
||||||
|
resources:
|
||||||
|
requests:
|
||||||
|
memory: "1Gi"
|
||||||
|
cpu: "500m"
|
||||||
|
limits:
|
||||||
|
memory: "4Gi"
|
||||||
|
cpu: "2000m"
|
||||||
|
|
||||||
|
# Routing proxy configuration (extracts GitHub repo from URL)
|
||||||
|
routingProxy:
|
||||||
|
enabled: true
|
||||||
|
replicas: 2 # High availability
|
||||||
|
image:
|
||||||
|
repository: ghcr.io/cpfarhood/devcontainer-routing-proxy
|
||||||
|
tag: latest
|
||||||
|
pullPolicy: Always
|
||||||
|
|
||||||
|
resources:
|
||||||
|
requests:
|
||||||
|
memory: "64Mi"
|
||||||
|
cpu: "100m"
|
||||||
|
limits:
|
||||||
|
memory: "256Mi"
|
||||||
|
cpu: "500m"
|
||||||
|
|
||||||
|
# Ingress configuration for dynamic mode
|
||||||
|
ingress:
|
||||||
|
enabled: true
|
||||||
|
className: nginx
|
||||||
|
host: "" # Set this to your domain (e.g., devcontainer.farh.net)
|
||||||
|
|
||||||
|
# TLS configuration
|
||||||
|
tls:
|
||||||
|
enabled: true
|
||||||
|
secretName: "" # Auto-generated if empty
|
||||||
|
issuer: "letsencrypt-prod" # cert-manager ClusterIssuer
|
||||||
|
|
||||||
|
# Authentik forward auth configuration
|
||||||
|
authentik:
|
||||||
|
enabled: false # Set to true when Authentik is configured
|
||||||
|
authUrl: "http://authentik.authentik.svc.cluster.local/outpost.goauthentik.io/auth/nginx"
|
||||||
|
signIn: "https://auth.example.com/outpost.goauthentik.io/start?rd=$escaped_request_uri"
|
||||||
|
|
||||||
# =============================================================================
|
# =============================================================================
|
||||||
# ADVANCED CONFIGURATION
|
# ADVANCED CONFIGURATION
|
||||||
# =============================================================================
|
# =============================================================================
|
||||||
|
|||||||
Reference in New Issue
Block a user