diff --git a/servers/legion/apps/gitea.yaml b/servers/legion/apps/gitea.yaml new file mode 100644 index 0000000..5c6ad3f --- /dev/null +++ b/servers/legion/apps/gitea.yaml @@ -0,0 +1,102 @@ +apiVersion: apps/v1 +kind: Deployment +metadata: + name: gitea + namespace: git + labels: + app: gitea +spec: + replicas: 1 + strategy: + type: Recreate + selector: + matchLabels: + app: gitea + template: + metadata: + labels: + app: gitea + spec: + containers: + - name: gitea + image: gitea/gitea:1.22 + ports: + - name: http + containerPort: 3000 + - name: ssh + containerPort: 22 + env: + - name: GITEA__database__DB_TYPE + value: postgres + - name: GITEA__database__HOST + value: postgres-postgresql.platform.svc.cluster.local:5432 + - name: GITEA__database__NAME + value: gitea + - name: GITEA__database__USER + value: gitea + - name: GITEA__database__PASSWD + valueFrom: + secretKeyRef: + name: gitea-db + key: password + - name: GITEA__server__DOMAIN + value: git.neuralplatform.dev + - name: GITEA__server__ROOT_URL + value: https://git.neuralplatform.dev + - name: GITEA__server__SSH_DOMAIN + value: git.neuralplatform.dev + - name: GITEA__server__SSH_PORT + value: "30022" + - name: GITEA__server__START_SSH_SERVER + value: "false" + - name: GITEA__service__DISABLE_REGISTRATION + value: "true" + - name: GITEA__service__REQUIRE_SIGNIN_VIEW + value: "true" + - name: GITEA__security__INSTALL_LOCK + value: "true" + - name: GITEA__packages__ENABLED + value: "true" + - name: GITEA__webhook__ALLOWED_HOST_LIST + value: 192.168.0.0/24,10.0.0.0/8 + volumeMounts: + - name: data + mountPath: /data + - name: custom-css + mountPath: /data/gitea/custom/public/assets/css/custom.css + subPath: custom.css + - name: custom-css + mountPath: /data/gitea/custom/templates/custom/header.tmpl + subPath: header.tmpl + resources: + requests: + memory: 256Mi + cpu: 100m + limits: + memory: 512Mi + cpu: 500m + volumes: + - name: data + persistentVolumeClaim: + claimName: gitea-data + - name: custom-css + configMap: + name: gitea-custom-css +--- +apiVersion: v1 +kind: Service +metadata: + name: gitea + namespace: git +spec: + selector: + app: gitea + ports: + - name: http + port: 3000 + targetPort: 3000 + - name: ssh + port: 22 + targetPort: 22 + nodePort: 30022 + type: NodePort diff --git a/servers/legion/apps/github-runner.yaml b/servers/legion/apps/github-runner.yaml new file mode 100644 index 0000000..3eac1e4 --- /dev/null +++ b/servers/legion/apps/github-runner.yaml @@ -0,0 +1,53 @@ +apiVersion: apps/v1 +kind: Deployment +metadata: + name: github-runner + namespace: ci + labels: + app: github-runner +spec: + replicas: 1 + selector: + matchLabels: + app: github-runner + template: + metadata: + labels: + app: github-runner + spec: + containers: + - name: runner + image: myoung34/github-runner:latest + env: + - name: ACCESS_TOKEN + valueFrom: + secretKeyRef: + name: github-runner-secret + key: ACCESS_TOKEN + - name: RUNNER_SCOPE + value: org + - name: ORG_NAME + value: harmonic-framework + - name: RUNNER_NAME + value: legion + - name: RUNNER_WORKDIR + value: /tmp/runner + - name: LABELS + value: self-hosted,linux,x64,legion + - name: DISABLE_AUTO_UPDATE + value: "true" + volumeMounts: + - name: docker-sock + mountPath: /var/run/docker.sock + resources: + requests: + memory: 512Mi + cpu: 250m + limits: + memory: 4Gi + cpu: "4" + volumes: + - name: docker-sock + hostPath: + path: /var/run/docker.sock + type: Socket diff --git a/servers/legion/apps/neuron.yaml b/servers/legion/apps/neuron.yaml new file mode 100644 index 0000000..c9cbd99 --- /dev/null +++ b/servers/legion/apps/neuron.yaml @@ -0,0 +1,132 @@ +apiVersion: apps/v1 +kind: Deployment +metadata: + name: neuron + namespace: neuron + labels: + app: neuron +spec: + replicas: 1 + strategy: + type: Recreate + selector: + matchLabels: + app: neuron + template: + metadata: + labels: + app: neuron + spec: + containers: + - name: neuron + image: registry.nook.family/neural-platform/neuron:latest + imagePullPolicy: Always + command: + - bash + - -c + - mkdir -p /root/.neuron && ln -sf /data/neuron.db /root/.neuron/neuron.db && python -m synapse platform serve --mcp-host 0.0.0.0 --mcp-port 8001 --webhook-port 3847 + ports: + - name: mcp + containerPort: 8001 + - name: webhook + containerPort: 3847 + envFrom: + - configMapRef: + name: neuron-config + - secretRef: + name: neuron-secrets + volumeMounts: + - name: data + mountPath: /data + - name: app-config + mountPath: /app/config/default.yaml + subPath: default.yaml + resources: + requests: + memory: 256Mi + cpu: 100m + limits: + memory: 1Gi + cpu: 500m + livenessProbe: + httpGet: + path: /health + port: mcp + initialDelaySeconds: 10 + periodSeconds: 30 + readinessProbe: + httpGet: + path: /health + port: mcp + initialDelaySeconds: 5 + periodSeconds: 10 + volumes: + - name: data + persistentVolumeClaim: + claimName: neuron-data + - name: app-config + configMap: + name: neuron-config + items: + - key: default.yaml + path: default.yaml +--- +apiVersion: v1 +kind: Service +metadata: + name: neuron + namespace: neuron +spec: + selector: + app: neuron + ports: + - name: mcp + port: 8001 + targetPort: 8001 + - name: webhook + port: 3847 + targetPort: 3847 + type: ClusterIP +--- +# cloudflared — Cloudflare tunnel for external Axon webhook access +# Routes: axon.neuralplatform.ai → neuron:3847 +apiVersion: apps/v1 +kind: Deployment +metadata: + name: cloudflared + namespace: neuron + labels: + app: cloudflared +spec: + replicas: 1 + selector: + matchLabels: + app: cloudflared + template: + metadata: + labels: + app: cloudflared + spec: + containers: + - name: cloudflared + image: cloudflare/cloudflared:latest + args: ["tunnel", "--no-autoupdate", "run"] + env: + - name: TUNNEL_TOKEN + valueFrom: + secretKeyRef: + name: cloudflared-secret + key: TUNNEL_TOKEN + resources: + requests: + memory: 64Mi + cpu: 50m + limits: + memory: 128Mi + cpu: 200m + livenessProbe: + httpGet: + path: /ready + port: 20241 + initialDelaySeconds: 10 + periodSeconds: 30 diff --git a/servers/legion/apps/ollama.yaml b/servers/legion/apps/ollama.yaml new file mode 100644 index 0000000..6618fb8 --- /dev/null +++ b/servers/legion/apps/ollama.yaml @@ -0,0 +1,55 @@ +apiVersion: apps/v1 +kind: Deployment +metadata: + name: ollama + namespace: ollama + labels: + app: ollama +spec: + replicas: 1 + strategy: + type: Recreate + selector: + matchLabels: + app: ollama + template: + metadata: + labels: + app: ollama + spec: + containers: + - name: ollama + image: ollama/ollama:latest + ports: + - containerPort: 11434 + env: + - name: NVIDIA_VISIBLE_DEVICES + value: all + volumeMounts: + - name: models + mountPath: /root/.ollama + resources: + requests: + memory: 2Gi + cpu: 500m + limits: + memory: 8Gi + cpu: "4" + volumes: + - name: models + persistentVolumeClaim: + claimName: ollama-models +--- +apiVersion: v1 +kind: Service +metadata: + name: ollama + namespace: ollama +spec: + selector: + app: ollama + ports: + - port: 11434 + targetPort: 11434 + nodePort: 31434 + type: NodePort diff --git a/servers/legion/apps/packages.yaml b/servers/legion/apps/packages.yaml new file mode 100644 index 0000000..653aa63 --- /dev/null +++ b/servers/legion/apps/packages.yaml @@ -0,0 +1,118 @@ +# Verdaccio — npm proxy/cache +apiVersion: apps/v1 +kind: Deployment +metadata: + name: verdaccio + namespace: packages +spec: + replicas: 1 + selector: + matchLabels: + app: verdaccio + template: + metadata: + labels: + app: verdaccio + spec: + securityContext: + fsGroup: 101 + containers: + - name: verdaccio + image: verdaccio/verdaccio:5 + ports: + - containerPort: 4873 + env: + - name: VERDACCIO_PORT + value: "4873" + volumeMounts: + - name: config + mountPath: /verdaccio/conf/config.yaml + subPath: config.yaml + - name: data + mountPath: /verdaccio/storage + resources: + requests: + memory: 128Mi + cpu: 50m + limits: + memory: 512Mi + volumes: + - name: config + configMap: + name: verdaccio-config + - name: data + persistentVolumeClaim: + claimName: verdaccio-data +--- +apiVersion: v1 +kind: Service +metadata: + name: verdaccio + namespace: packages +spec: + selector: + app: verdaccio + ports: + - port: 4873 + targetPort: 4873 +--- +# devpi — PyPI proxy/cache +apiVersion: apps/v1 +kind: Deployment +metadata: + name: devpi + namespace: packages +spec: + replicas: 1 + selector: + matchLabels: + app: devpi + template: + metadata: + labels: + app: devpi + spec: + initContainers: + - name: devpi-init + image: python:3.12-slim + command: + - sh + - -c + - pip install -q devpi-server devpi-web && if [ ! -f /data/.serverversion ]; then devpi-init --serverdir /data; fi && chmod 600 /data/.secret 2>/dev/null || true + volumeMounts: + - name: data + mountPath: /data + containers: + - name: devpi + image: python:3.12-slim + command: + - sh + - -c + - pip install -q devpi-server devpi-web && exec devpi-server --serverdir /data --host 0.0.0.0 --port 3141 --outside-url https://pypi.neuralplatform.ai + ports: + - containerPort: 3141 + volumeMounts: + - name: data + mountPath: /data + resources: + requests: + memory: 512Mi + cpu: 100m + limits: + memory: 2Gi + volumes: + - name: data + persistentVolumeClaim: + claimName: devpi-data +--- +apiVersion: v1 +kind: Service +metadata: + name: devpi + namespace: packages +spec: + selector: + app: devpi + ports: + - port: 3141 + targetPort: 3141 diff --git a/servers/legion/apps/registry.yaml b/servers/legion/apps/registry.yaml new file mode 100644 index 0000000..642a85a --- /dev/null +++ b/servers/legion/apps/registry.yaml @@ -0,0 +1,103 @@ +apiVersion: apps/v1 +kind: Deployment +metadata: + name: registry + namespace: registry + labels: + app: registry +spec: + replicas: 1 + selector: + matchLabels: + app: registry + template: + metadata: + labels: + app: registry + spec: + containers: + - name: registry + image: registry:2 + ports: + - containerPort: 5000 + volumeMounts: + - name: data + mountPath: /var/lib/registry + resources: + requests: + memory: 64Mi + cpu: 50m + limits: + memory: 256Mi + cpu: 200m + volumes: + - name: data + persistentVolumeClaim: + claimName: registry-data +--- +apiVersion: v1 +kind: Service +metadata: + name: registry + namespace: registry +spec: + selector: + app: registry + ports: + - port: 5000 + targetPort: 5000 + type: ClusterIP +--- +apiVersion: apps/v1 +kind: Deployment +metadata: + name: registry-ui + namespace: registry + labels: + app: registry-ui +spec: + replicas: 1 + selector: + matchLabels: + app: registry-ui + template: + metadata: + labels: + app: registry-ui + spec: + containers: + - name: registry-ui + image: joxit/docker-registry-ui:latest + ports: + - containerPort: 80 + env: + - name: REGISTRY_TITLE + value: Nook Registry + - name: NGINX_PROXY_PASS_URL + value: http://registry:5000 + - name: SINGLE_REGISTRY + value: "true" + - name: SHOW_CONTENT_DIGEST + value: "true" + - name: DELETE_IMAGES + value: "true" + resources: + requests: + memory: 32Mi + cpu: 20m + limits: + memory: 64Mi + cpu: 100m +--- +apiVersion: v1 +kind: Service +metadata: + name: registry-ui + namespace: registry +spec: + selector: + app: registry-ui + ports: + - port: 80 + targetPort: 80 + type: ClusterIP diff --git a/servers/legion/gitea.tf b/servers/legion/gitea.tf index 56dd1a6..4256659 100644 --- a/servers/legion/gitea.tf +++ b/servers/legion/gitea.tf @@ -149,181 +149,7 @@ resource "kubernetes_secret" "gitea_db_secret" { } } -resource "kubernetes_deployment" "gitea" { - metadata { - name = "gitea" - namespace = kubernetes_namespace.git.metadata[0].name - labels = { app = "gitea" } - } - - spec { - replicas = 1 - strategy { type = "Recreate" } - - selector { - match_labels = { app = "gitea" } - } - - template { - metadata { - labels = { app = "gitea" } - } - - spec { - container { - name = "gitea" - image = "gitea/gitea:1.22" - - port { - name = "http" - container_port = 3000 - } - port { - name = "ssh" - container_port = 22 - } - - env { - name = "GITEA__database__DB_TYPE" - value = "postgres" - } - env { - name = "GITEA__database__HOST" - value = "postgres-postgresql.platform.svc.cluster.local:5432" - } - env { - name = "GITEA__database__NAME" - value = "gitea" - } - env { - name = "GITEA__database__USER" - value = "gitea" - } - env { - name = "GITEA__database__PASSWD" - value_from { - secret_key_ref { - name = kubernetes_secret.gitea_db_secret.metadata[0].name - key = "password" - } - } - } - env { - name = "GITEA__server__DOMAIN" - value = var.gitea_domain - } - env { - name = "GITEA__server__ROOT_URL" - value = "https://${var.gitea_domain}" - } - env { - name = "GITEA__server__SSH_DOMAIN" - value = var.gitea_domain - } - env { - name = "GITEA__server__SSH_PORT" - value = "30022" - } - env { - name = "GITEA__server__START_SSH_SERVER" - value = "false" - } - env { - name = "GITEA__service__DISABLE_REGISTRATION" - value = "true" - } - env { - name = "GITEA__service__REQUIRE_SIGNIN_VIEW" - value = "true" - } - env { - name = "GITEA__security__INSTALL_LOCK" - value = "true" - } - env { - name = "GITEA__packages__ENABLED" - value = "true" - } - - env { - name = "GITEA__webhook__ALLOWED_HOST_LIST" - value = "192.168.0.0/24,10.0.0.0/8" - } - - volume_mount { - name = "data" - mount_path = "/data" - } - - volume_mount { - name = "custom-css" - mount_path = "/data/gitea/custom/public/assets/css/custom.css" - sub_path = "custom.css" - } - - volume_mount { - name = "custom-css" - mount_path = "/data/gitea/custom/templates/custom/header.tmpl" - sub_path = "header.tmpl" - } - - resources { - requests = { - memory = "256Mi" - cpu = "100m" - } - limits = { - memory = "512Mi" - cpu = "500m" - } - } - } - - volume { - name = "data" - persistent_volume_claim { - claim_name = kubernetes_persistent_volume_claim.gitea_data.metadata[0].name - } - } - - volume { - name = "custom-css" - config_map { - name = kubernetes_config_map.gitea_custom_css.metadata[0].name - } - } - } - } - } - - depends_on = [helm_release.postgres] -} - -resource "kubernetes_service" "gitea" { - metadata { - name = "gitea" - namespace = kubernetes_namespace.git.metadata[0].name - } - - spec { - selector = { app = "gitea" } - - port { - name = "http" - port = 3000 - target_port = 3000 - } - - port { - name = "ssh" - port = 22 - target_port = 22 - node_port = 30022 - } - - type = "NodePort" - } -} +# Deployment + Service managed by Argo CD — see servers/legion/apps/gitea.yaml resource "kubernetes_ingress_v1" "gitea" { metadata { @@ -348,7 +174,7 @@ resource "kubernetes_ingress_v1" "gitea" { path_type = "Prefix" backend { service { - name = kubernetes_service.gitea.metadata[0].name + name = "gitea" port { number = 3000 } } } diff --git a/servers/legion/github-runner.tf b/servers/legion/github-runner.tf index d59faa9..1a85d40 100644 --- a/servers/legion/github-runner.tf +++ b/servers/legion/github-runner.tf @@ -1,94 +1,12 @@ # GitHub Actions Self-Hosted Runner — org-level, serves all repos -resource "kubernetes_deployment" "github_runner" { +# Deployment managed by Argo CD — see servers/legion/apps/github-runner.yaml + +resource "kubernetes_secret" "github_runner_secret" { metadata { - name = "github-runner" + name = "github-runner-secret" namespace = kubernetes_namespace.ci.metadata[0].name - labels = { - app = "github-runner" - } } - - spec { - replicas = 1 - - selector { - match_labels = { - app = "github-runner" - } - } - - template { - metadata { - labels = { - app = "github-runner" - } - } - - spec { - container { - name = "runner" - image = "myoung34/github-runner:latest" - - env { - name = "ACCESS_TOKEN" - value = var.github_classic_pat - } - - env { - name = "RUNNER_SCOPE" - value = "org" - } - - env { - name = "ORG_NAME" - value = "harmonic-framework" - } - - env { - name = "RUNNER_NAME" - value = "legion" - } - - env { - name = "RUNNER_WORKDIR" - value = "/tmp/runner" - } - - env { - name = "LABELS" - value = "self-hosted,linux,x64,legion" - } - - env { - name = "DISABLE_AUTO_UPDATE" - value = "true" - } - - volume_mount { - name = "docker-sock" - mount_path = "/var/run/docker.sock" - } - - resources { - requests = { - memory = "512Mi" - cpu = "250m" - } - limits = { - memory = "4Gi" - cpu = "4" - } - } - } - - volume { - name = "docker-sock" - host_path { - path = "/var/run/docker.sock" - type = "Socket" - } - } - } - } + data = { + ACCESS_TOKEN = var.github_classic_pat } } diff --git a/servers/legion/ingress.tf b/servers/legion/ingress.tf index 7de99ea..065131c 100644 --- a/servers/legion/ingress.tf +++ b/servers/legion/ingress.tf @@ -24,7 +24,7 @@ resource "kubernetes_ingress_v1" "ollama" { path_type = "Prefix" backend { service { - name = kubernetes_service.ollama.metadata[0].name + name = "ollama" port { number = 11434 } } } @@ -60,7 +60,7 @@ resource "kubernetes_ingress_v1" "registry" { path_type = "Prefix" backend { service { - name = kubernetes_service.registry.metadata[0].name + name = "registry" port { number = 5000 } } } @@ -95,7 +95,7 @@ resource "kubernetes_ingress_v1" "registry_ui" { path_type = "Prefix" backend { service { - name = kubernetes_service.registry_ui.metadata[0].name + name = "registry-ui" port { number = 80 } } } @@ -131,7 +131,7 @@ resource "kubernetes_ingress_v1" "npm_registry" { path_type = "Prefix" backend { service { - name = kubernetes_service.verdaccio.metadata[0].name + name = "verdaccio" port { number = 4873 } } } @@ -140,7 +140,7 @@ resource "kubernetes_ingress_v1" "npm_registry" { } } - depends_on = [helm_release.cert_manager, kubernetes_deployment.verdaccio] + depends_on = [helm_release.cert_manager] } # PyPI registry — devpi (proxies pypi.org, caches locally) @@ -167,7 +167,7 @@ resource "kubernetes_ingress_v1" "pypi_registry" { path_type = "Prefix" backend { service { - name = kubernetes_service.devpi.metadata[0].name + name = "devpi" port { number = 3141 } } } @@ -176,5 +176,5 @@ resource "kubernetes_ingress_v1" "pypi_registry" { } } - depends_on = [helm_release.cert_manager, kubernetes_deployment.devpi] + depends_on = [helm_release.cert_manager] } diff --git a/servers/legion/neuron.tf b/servers/legion/neuron.tf index d48a717..6369a07 100644 --- a/servers/legion/neuron.tf +++ b/servers/legion/neuron.tf @@ -81,157 +81,15 @@ resource "kubernetes_secret" "neuron_secrets" { } } -resource "kubernetes_deployment" "neuron" { +# Deployment + Service + cloudflared managed by Argo CD — see servers/legion/apps/neuron.yaml + +resource "kubernetes_secret" "cloudflared_secret" { metadata { - name = "neuron" - namespace = kubernetes_namespace.neuron.metadata[0].name - labels = { - app = "neuron" - } - } - - spec { - replicas = 1 - - strategy { - type = "Recreate" # SQLite cannot handle concurrent writers - } - - selector { - match_labels = { - app = "neuron" - } - } - - template { - metadata { - labels = { - app = "neuron" - } - } - - spec { - container { - name = "neuron" - image = "registry.nook.family/neural-platform/neuron:latest" - image_pull_policy = "Always" - - command = [ - "bash", "-c", - "mkdir -p /root/.neuron && ln -sf /data/neuron.db /root/.neuron/neuron.db && python -m synapse platform serve --mcp-host 0.0.0.0 --mcp-port 8001 --webhook-port 3847" - ] - - port { - name = "mcp" - container_port = 8001 - } - - port { - name = "webhook" - container_port = 3847 - } - - env_from { - config_map_ref { - name = kubernetes_config_map.neuron_config.metadata[0].name - } - } - - env_from { - secret_ref { - name = kubernetes_secret.neuron_secrets.metadata[0].name - } - } - - volume_mount { - name = "data" - mount_path = "/data" - } - - volume_mount { - name = "app-config" - mount_path = "/app/config/default.yaml" - sub_path = "default.yaml" - } - - resources { - requests = { - memory = "256Mi" - cpu = "100m" - } - limits = { - memory = "1Gi" - cpu = "500m" - } - } - - liveness_probe { - http_get { - path = "/health" - port = "mcp" - } - initial_delay_seconds = 10 - period_seconds = 30 - } - - readiness_probe { - http_get { - path = "/health" - port = "mcp" - } - initial_delay_seconds = 5 - period_seconds = 10 - } - } - - volume { - name = "data" - persistent_volume_claim { - claim_name = kubernetes_persistent_volume_claim.neuron_data.metadata[0].name - } - } - - volume { - name = "app-config" - config_map { - name = kubernetes_config_map.neuron_config.metadata[0].name - items { - key = "default.yaml" - path = "default.yaml" - } - } - } - } - } - } - - depends_on = [kubernetes_persistent_volume_claim.neuron_data] -} - -resource "kubernetes_service" "neuron" { - metadata { - name = "neuron" + name = "cloudflared-secret" namespace = kubernetes_namespace.neuron.metadata[0].name } - - spec { - selector = { - app = "neuron" - } - - port { - name = "mcp" - port = 8001 - target_port = 8001 - } - - port { - name = "webhook" - port = 3847 - target_port = 3847 - } - - type = "ClusterIP" + data = { + TUNNEL_TOKEN = var.cloudflared_tunnel_token } } @@ -262,7 +120,7 @@ resource "kubernetes_ingress_v1" "neuron" { path_type = "Prefix" backend { service { - name = kubernetes_service.neuron.metadata[0].name + name = "neuron" port { number = 8001 } @@ -276,68 +134,3 @@ resource "kubernetes_ingress_v1" "neuron" { depends_on = [helm_release.cert_manager] } -# cloudflared — Cloudflare tunnel for external access to Axon webhooks -# Routes: axon.neuralplatform.ai → neuron:3847 -# webhooks.neuralplatform.ai → neuron:3847 -resource "kubernetes_deployment" "cloudflared" { - metadata { - name = "cloudflared" - namespace = kubernetes_namespace.neuron.metadata[0].name - labels = { - app = "cloudflared" - } - } - - spec { - replicas = 1 - - selector { - match_labels = { - app = "cloudflared" - } - } - - template { - metadata { - labels = { - app = "cloudflared" - } - } - - spec { - container { - name = "cloudflared" - image = "cloudflare/cloudflared:latest" - args = ["tunnel", "--no-autoupdate", "run"] - - env { - name = "TUNNEL_TOKEN" - value = var.cloudflared_tunnel_token - } - - resources { - requests = { - memory = "64Mi" - cpu = "50m" - } - limits = { - memory = "128Mi" - cpu = "200m" - } - } - - liveness_probe { - http_get { - path = "/ready" - port = 20241 - } - initial_delay_seconds = 10 - period_seconds = 30 - } - } - } - } - } - - depends_on = [kubernetes_deployment.neuron] -} diff --git a/servers/legion/ollama.tf b/servers/legion/ollama.tf index 31f2e3f..16bc408 100644 --- a/servers/legion/ollama.tf +++ b/servers/legion/ollama.tf @@ -25,94 +25,4 @@ resource "kubernetes_persistent_volume_claim" "ollama_models" { } } -resource "kubernetes_deployment" "ollama" { - metadata { - name = "ollama" - namespace = kubernetes_namespace.ollama.metadata[0].name - labels = { - app = "ollama" - } - } - - spec { - replicas = 1 - - strategy { - type = "Recreate" - } - - selector { - match_labels = { - app = "ollama" - } - } - - template { - metadata { - labels = { - app = "ollama" - } - } - - spec { - container { - name = "ollama" - image = "ollama/ollama:latest" - - port { - container_port = 11434 - } - - env { - name = "NVIDIA_VISIBLE_DEVICES" - value = "all" - } - - volume_mount { - name = "models" - mount_path = "/root/.ollama" - } - - resources { - requests = { - memory = "2Gi" - cpu = "500m" - } - limits = { - memory = "8Gi" - cpu = "4" - } - } - } - - volume { - name = "models" - persistent_volume_claim { - claim_name = kubernetes_persistent_volume_claim.ollama_models.metadata[0].name - } - } - } - } - } -} - -resource "kubernetes_service" "ollama" { - metadata { - name = "ollama" - namespace = kubernetes_namespace.ollama.metadata[0].name - } - - spec { - selector = { - app = "ollama" - } - - port { - port = 11434 - target_port = 11434 - node_port = 31434 - } - - type = "NodePort" - } -} +# Deployment + Service managed by Argo CD — see servers/legion/apps/ollama.yaml diff --git a/servers/legion/packages.tf b/servers/legion/packages.tf index d20d5df..715d4e1 100644 --- a/servers/legion/packages.tf +++ b/servers/legion/packages.tf @@ -75,156 +75,4 @@ resource "kubernetes_config_map" "verdaccio_config" { } } -resource "kubernetes_deployment" "verdaccio" { - metadata { - name = "verdaccio" - namespace = kubernetes_namespace.packages.metadata[0].name - } - - spec { - replicas = 1 - selector { - match_labels = { app = "verdaccio" } - } - template { - metadata { - labels = { app = "verdaccio" } - } - spec { - security_context { - fs_group = 101 - } - container { - name = "verdaccio" - image = "verdaccio/verdaccio:5" - - port { - container_port = 4873 - } - - # Override k8s service env injection which conflicts with Verdaccio's port detection - env { - name = "VERDACCIO_PORT" - value = "4873" - } - - volume_mount { - name = "config" - mount_path = "/verdaccio/conf/config.yaml" - sub_path = "config.yaml" - } - - volume_mount { - name = "data" - mount_path = "/verdaccio/storage" - } - - resources { - requests = { memory = "128Mi", cpu = "50m" } - limits = { memory = "512Mi" } - } - } - - volume { - name = "config" - config_map { - name = kubernetes_config_map.verdaccio_config.metadata[0].name - } - } - - volume { - name = "data" - persistent_volume_claim { - claim_name = kubernetes_persistent_volume_claim.verdaccio_data.metadata[0].name - } - } - } - } - } -} - -resource "kubernetes_service" "verdaccio" { - metadata { - name = "verdaccio" - namespace = kubernetes_namespace.packages.metadata[0].name - } - spec { - selector = { app = "verdaccio" } - port { - port = 4873 - target_port = 4873 - } - } -} - -# devpi — PyPI proxy/cache -resource "kubernetes_deployment" "devpi" { - metadata { - name = "devpi" - namespace = kubernetes_namespace.packages.metadata[0].name - } - - spec { - replicas = 1 - selector { - match_labels = { app = "devpi" } - } - template { - metadata { - labels = { app = "devpi" } - } - spec { - init_container { - name = "devpi-init" - image = "python:3.12-slim" - command = ["sh", "-c", "pip install -q devpi-server devpi-web && if [ ! -f /data/.serverversion ]; then devpi-init --serverdir /data; fi && chmod 600 /data/.secret 2>/dev/null || true"] - volume_mount { - name = "data" - mount_path = "/data" - } - } - - container { - name = "devpi" - image = "python:3.12-slim" - command = ["sh", "-c", "pip install -q devpi-server devpi-web && exec devpi-server --serverdir /data --host 0.0.0.0 --port 3141 --outside-url https://pypi.neuralplatform.ai"] - - port { - container_port = 3141 - } - - volume_mount { - name = "data" - mount_path = "/data" - } - - resources { - requests = { memory = "512Mi", cpu = "100m" } - limits = { memory = "2Gi" } - } - } - - volume { - name = "data" - persistent_volume_claim { - claim_name = kubernetes_persistent_volume_claim.devpi_data.metadata[0].name - } - } - } - } - } -} - -resource "kubernetes_service" "devpi" { - metadata { - name = "devpi" - namespace = kubernetes_namespace.packages.metadata[0].name - } - spec { - selector = { app = "devpi" } - port { - port = 3141 - target_port = 3141 - } - } -} +# Deployments + Services managed by Argo CD — see servers/legion/apps/packages.yaml diff --git a/servers/legion/registry.tf b/servers/legion/registry.tf index 522fbce..c812c50 100644 --- a/servers/legion/registry.tf +++ b/servers/legion/registry.tf @@ -25,159 +25,4 @@ resource "kubernetes_persistent_volume_claim" "registry_data" { } } -resource "kubernetes_deployment" "registry" { - metadata { - name = "registry" - namespace = kubernetes_namespace.registry.metadata[0].name - labels = { - app = "registry" - } - } - - spec { - replicas = 1 - - selector { - match_labels = { - app = "registry" - } - } - - template { - metadata { - labels = { - app = "registry" - } - } - - spec { - container { - name = "registry" - image = "registry:2" - - port { - container_port = 5000 - } - - volume_mount { - name = "data" - mount_path = "/var/lib/registry" - } - - resources { - requests = { - memory = "64Mi" - cpu = "50m" - } - limits = { - memory = "256Mi" - cpu = "200m" - } - } - } - - volume { - name = "data" - persistent_volume_claim { - claim_name = kubernetes_persistent_volume_claim.registry_data.metadata[0].name - } - } - } - } - } -} - -resource "kubernetes_service" "registry" { - metadata { - name = "registry" - namespace = kubernetes_namespace.registry.metadata[0].name - } - - spec { - selector = { app = "registry" } - port { - port = 5000 - target_port = 5000 - } - type = "ClusterIP" - } -} - -# Docker Registry UI — browse images and tags visually -resource "kubernetes_deployment" "registry_ui" { - metadata { - name = "registry-ui" - namespace = kubernetes_namespace.registry.metadata[0].name - labels = { app = "registry-ui" } - } - - spec { - replicas = 1 - selector { - match_labels = { app = "registry-ui" } - } - template { - metadata { - labels = { app = "registry-ui" } - } - spec { - container { - name = "registry-ui" - image = "joxit/docker-registry-ui:latest" - - port { - container_port = 80 - } - - env { - name = "REGISTRY_TITLE" - value = "Nook Registry" - } - env { - name = "NGINX_PROXY_PASS_URL" - value = "http://registry:5000" - } - env { - name = "SINGLE_REGISTRY" - value = "true" - } - env { - name = "SHOW_CONTENT_DIGEST" - value = "true" - } - env { - name = "DELETE_IMAGES" - value = "true" - } - - resources { - requests = { - memory = "32Mi" - cpu = "20m" - } - limits = { - memory = "64Mi" - cpu = "100m" - } - } - } - } - } - } -} - -resource "kubernetes_service" "registry_ui" { - metadata { - name = "registry-ui" - namespace = kubernetes_namespace.registry.metadata[0].name - } - - spec { - selector = { app = "registry-ui" } - port { - port = 80 - target_port = 80 - } - type = "ClusterIP" - } -} +# Deployments + Services managed by Argo CD — see servers/legion/apps/registry.yaml