diff --git a/servers/legion/apps/neuron-swarm.yaml b/servers/legion/apps/neuron-swarm.yaml new file mode 100644 index 0000000..ff0eb46 --- /dev/null +++ b/servers/legion/apps/neuron-swarm.yaml @@ -0,0 +1,52 @@ +apiVersion: argoproj.io/v1alpha1 +kind: Application +metadata: + name: neuron-swarm + namespace: argocd +spec: + project: default + source: + repoURL: http://10.43.1.53:3000/will/infrastructure.git + targetRevision: main + path: servers/legion/k8s/neuron-technologies/swarm + destination: + server: https://kubernetes.default.svc + # No single namespace — resources span swarm-alpha/beta/gamma. + # Each resource declares its own namespace. + namespace: swarm-alpha + syncPolicy: + automated: + prune: true + selfHeal: true + syncOptions: + - CreateNamespace=true + # Don't track Jobs created dynamically by swarm.sh + ignoreDifferences: + - group: batch + kind: Job + namespace: swarm-alpha + jsonPointers: [""] + - group: batch + kind: Job + namespace: swarm-beta + jsonPointers: [""] + - group: batch + kind: Job + namespace: swarm-gamma + jsonPointers: [""] + # Session ConfigMaps are created/deleted by swarm.sh — ignore drift + - group: "" + kind: ConfigMap + name: swarm-alpha-session + namespace: swarm-alpha + jsonPointers: [""] + - group: "" + kind: ConfigMap + name: swarm-beta-session + namespace: swarm-beta + jsonPointers: [""] + - group: "" + kind: ConfigMap + name: swarm-gamma-session + namespace: swarm-gamma + jsonPointers: [""] diff --git a/servers/legion/k8s/neuron-technologies/swarm/configmaps.yaml b/servers/legion/k8s/neuron-technologies/swarm/configmaps.yaml new file mode 100644 index 0000000..93d2d95 --- /dev/null +++ b/servers/legion/k8s/neuron-technologies/swarm/configmaps.yaml @@ -0,0 +1,48 @@ +# Swarm variant ConfigMaps — base config per variant +# The swarm-{variant}-session ConfigMap is created dynamically by swarm.sh +# at session start and deleted at session end. +--- +apiVersion: v1 +kind: ConfigMap +metadata: + name: swarm-alpha-config + namespace: swarm-alpha +data: + SPRING_PROFILES_ACTIVE: "swarm" + NEURON_DATA_DIR: "/data" + NEURON_DB_PATH: "/data/neuron.db" + NEURON_STORAGE_PATH: "/data" + SERVER_TOMCAT_ACCESSLOG_ENABLED: "true" + MANAGEMENT_ENDPOINTS_WEB_EXPOSURE_INCLUDE: "health,info,metrics" + MANAGEMENT_ENDPOINT_HEALTH_SHOW_DETAILS: "always" + MANAGEMENT_OTLP_METRICS_EXPORT_ENABLED: "false" +--- +apiVersion: v1 +kind: ConfigMap +metadata: + name: swarm-beta-config + namespace: swarm-beta +data: + SPRING_PROFILES_ACTIVE: "swarm" + NEURON_DATA_DIR: "/data" + NEURON_DB_PATH: "/data/neuron.db" + NEURON_STORAGE_PATH: "/data" + SERVER_TOMCAT_ACCESSLOG_ENABLED: "true" + MANAGEMENT_ENDPOINTS_WEB_EXPOSURE_INCLUDE: "health,info,metrics" + MANAGEMENT_ENDPOINT_HEALTH_SHOW_DETAILS: "always" + MANAGEMENT_OTLP_METRICS_EXPORT_ENABLED: "false" +--- +apiVersion: v1 +kind: ConfigMap +metadata: + name: swarm-gamma-config + namespace: swarm-gamma +data: + SPRING_PROFILES_ACTIVE: "swarm" + NEURON_DATA_DIR: "/data" + NEURON_DB_PATH: "/data/neuron.db" + NEURON_STORAGE_PATH: "/data" + SERVER_TOMCAT_ACCESSLOG_ENABLED: "true" + MANAGEMENT_ENDPOINTS_WEB_EXPOSURE_INCLUDE: "health,info,metrics" + MANAGEMENT_ENDPOINT_HEALTH_SHOW_DETAILS: "always" + MANAGEMENT_OTLP_METRICS_EXPORT_ENABLED: "false" diff --git a/servers/legion/k8s/neuron-technologies/swarm/externalsecrets.yaml b/servers/legion/k8s/neuron-technologies/swarm/externalsecrets.yaml new file mode 100644 index 0000000..2e396af --- /dev/null +++ b/servers/legion/k8s/neuron-technologies/swarm/externalsecrets.yaml @@ -0,0 +1,155 @@ +# Swarm variants share the same secrets as prod. +# Each variant gets its own ExternalSecret object pointing at the same Vault paths. +--- +apiVersion: external-secrets.io/v1beta1 +kind: ExternalSecret +metadata: + name: swarm-alpha-secrets + namespace: swarm-alpha +spec: + refreshInterval: 1h + secretStoreRef: + name: vault + kind: ClusterSecretStore + target: + name: swarm-alpha-secrets + creationPolicy: Owner + data: + - secretKey: NEURON_API_KEY + remoteRef: + key: secret/data/neuron-technologies/prod + property: api_key + - secretKey: NEURON_WEBHOOK_SECRET + remoteRef: + key: secret/data/neuron-technologies/prod + property: gitea_webhook_secret + - secretKey: NEURON_LICENSE_ADMIN_TOKEN + remoteRef: + key: secret/data/neuron-technologies/license + property: admin_token + - secretKey: UNKEY_ROOT_KEY + remoteRef: + key: secret/data/neuron-technologies/unkey + property: root_key + - secretKey: UNKEY_API_ID + remoteRef: + key: secret/data/neuron-technologies/unkey + property: api_id + - secretKey: NEURON_R2_ENDPOINT + remoteRef: + key: secret/data/r2 + property: endpoint + - secretKey: NEURON_R2_ACCESS_KEY + remoteRef: + key: secret/data/r2 + property: access_key_id + - secretKey: NEURON_R2_SECRET_KEY + remoteRef: + key: secret/data/r2 + property: secret_access_key + - secretKey: NEURON_R2_BUCKET + remoteRef: + key: secret/data/r2 + property: neuron_bucket +--- +apiVersion: external-secrets.io/v1beta1 +kind: ExternalSecret +metadata: + name: swarm-beta-secrets + namespace: swarm-beta +spec: + refreshInterval: 1h + secretStoreRef: + name: vault + kind: ClusterSecretStore + target: + name: swarm-beta-secrets + creationPolicy: Owner + data: + - secretKey: NEURON_API_KEY + remoteRef: + key: secret/data/neuron-technologies/prod + property: api_key + - secretKey: NEURON_WEBHOOK_SECRET + remoteRef: + key: secret/data/neuron-technologies/prod + property: gitea_webhook_secret + - secretKey: NEURON_LICENSE_ADMIN_TOKEN + remoteRef: + key: secret/data/neuron-technologies/license + property: admin_token + - secretKey: UNKEY_ROOT_KEY + remoteRef: + key: secret/data/neuron-technologies/unkey + property: root_key + - secretKey: UNKEY_API_ID + remoteRef: + key: secret/data/neuron-technologies/unkey + property: api_id + - secretKey: NEURON_R2_ENDPOINT + remoteRef: + key: secret/data/r2 + property: endpoint + - secretKey: NEURON_R2_ACCESS_KEY + remoteRef: + key: secret/data/r2 + property: access_key_id + - secretKey: NEURON_R2_SECRET_KEY + remoteRef: + key: secret/data/r2 + property: secret_access_key + - secretKey: NEURON_R2_BUCKET + remoteRef: + key: secret/data/r2 + property: neuron_bucket +--- +apiVersion: external-secrets.io/v1beta1 +kind: ExternalSecret +metadata: + name: swarm-gamma-secrets + namespace: swarm-gamma +spec: + refreshInterval: 1h + secretStoreRef: + name: vault + kind: ClusterSecretStore + target: + name: swarm-gamma-secrets + creationPolicy: Owner + data: + - secretKey: NEURON_API_KEY + remoteRef: + key: secret/data/neuron-technologies/prod + property: api_key + - secretKey: NEURON_WEBHOOK_SECRET + remoteRef: + key: secret/data/neuron-technologies/prod + property: gitea_webhook_secret + - secretKey: NEURON_LICENSE_ADMIN_TOKEN + remoteRef: + key: secret/data/neuron-technologies/license + property: admin_token + - secretKey: UNKEY_ROOT_KEY + remoteRef: + key: secret/data/neuron-technologies/unkey + property: root_key + - secretKey: UNKEY_API_ID + remoteRef: + key: secret/data/neuron-technologies/unkey + property: api_id + - secretKey: NEURON_R2_ENDPOINT + remoteRef: + key: secret/data/r2 + property: endpoint + - secretKey: NEURON_R2_ACCESS_KEY + remoteRef: + key: secret/data/r2 + property: access_key_id + - secretKey: NEURON_R2_SECRET_KEY + remoteRef: + key: secret/data/r2 + property: secret_access_key + - secretKey: NEURON_R2_BUCKET + remoteRef: + key: secret/data/r2 + property: neuron_bucket diff --git a/servers/legion/k8s/neuron-technologies/swarm/kustomization.yaml b/servers/legion/k8s/neuron-technologies/swarm/kustomization.yaml new file mode 100644 index 0000000..06056e9 --- /dev/null +++ b/servers/legion/k8s/neuron-technologies/swarm/kustomization.yaml @@ -0,0 +1,30 @@ +apiVersion: kustomize.config.k8s.io/v1beta1 +kind: Kustomization +resources: + # Namespaces + - namespace-alpha.yaml + - namespace-beta.yaml + - namespace-gamma.yaml + # Persistent volumes + - pvc-alpha.yaml + - pvc-beta.yaml + - pvc-gamma.yaml + # Base config + - configmaps.yaml + # Shared secrets from Vault + - externalsecrets.yaml + # MCP deployments + - mcp-deployment-alpha.yaml + - mcp-deployment-beta.yaml + - mcp-deployment-gamma.yaml + # REST deployments + - rest-deployment-alpha.yaml + - rest-deployment-beta.yaml + - rest-deployment-gamma.yaml + # Services + - services.yaml + # RBAC for CI runner + - rbac.yaml + # SQLite clone Jobs (applied by swarm.sh at session start, not auto-synced by ArgoCD) + # These are listed here for reference but excluded from ArgoCD automated sync + # via the ignoreDifferences config in the ArgoCD app. diff --git a/servers/legion/k8s/neuron-technologies/swarm/mcp-deployment-alpha.yaml b/servers/legion/k8s/neuron-technologies/swarm/mcp-deployment-alpha.yaml new file mode 100644 index 0000000..7fd8263 --- /dev/null +++ b/servers/legion/k8s/neuron-technologies/swarm/mcp-deployment-alpha.yaml @@ -0,0 +1,121 @@ +apiVersion: apps/v1 +kind: Deployment +metadata: + name: neuron-mcp + namespace: swarm-alpha + labels: + app: neuron-mcp + env: swarm + variant: alpha +spec: + replicas: 1 + strategy: + type: Recreate + selector: + matchLabels: + app: neuron-mcp + template: + metadata: + labels: + app: neuron-mcp + env: swarm + variant: alpha + spec: + terminationGracePeriodSeconds: 30 + securityContext: + runAsNonRoot: true + seccompProfile: + type: RuntimeDefault + initContainers: + - name: wait-for-sqlite-clone + image: busybox:1.36 + command: ["sh", "-c", "until [ -f /data/neuron.db ]; do echo 'waiting for SQLite clone...'; sleep 2; done; echo 'SQLite ready'"] + volumeMounts: + - name: data + mountPath: /data + securityContext: + runAsNonRoot: true + allowPrivilegeEscalation: false + capabilities: + drop: ["ALL"] + containers: + - name: neuron-mcp + # Image is updated by swarm CI on each loop iteration + image: registry.neuralplatform.ai/neuron-technologies/neuron-mcp:v0.15.3 + imagePullPolicy: Always + ports: + - name: http + containerPort: 8080 + securityContext: + allowPrivilegeEscalation: false + readOnlyRootFilesystem: false + runAsNonRoot: true + capabilities: + drop: ["ALL"] + env: + - name: NEURON_SWARM_VARIANT + value: "alpha" + - name: NEURON_SWARM_SESSION + valueFrom: + configMapKeyRef: + name: swarm-alpha-session + key: session_id + optional: true + - name: NEURON_SWARM_GOAL + valueFrom: + configMapKeyRef: + name: swarm-alpha-session + key: goal + optional: true + - name: NEURON_SWARM_LOOP_MAX + valueFrom: + configMapKeyRef: + name: swarm-alpha-session + key: loop_max + optional: true + - name: OTEL_EXPORTER_OTLP_ENDPOINT + value: "http://alloy-otlp.monitoring.svc.cluster.local:4318" + - name: JAVA_TOOL_OPTIONS + value: "-XX:+UseContainerSupport -XX:MaxRAMPercentage=75.0 -XX:+ExitOnOutOfMemoryError" + envFrom: + - configMapRef: + name: swarm-alpha-config + - secretRef: + name: swarm-alpha-secrets + volumeMounts: + - name: data + mountPath: /data + resources: + requests: + cpu: 250m + memory: 512Mi + limits: + cpu: 1500m + memory: 1536Mi + lifecycle: + preStop: + exec: + command: ["sh", "-c", "sleep 5"] + startupProbe: + httpGet: + path: /actuator/health/liveness + port: http + failureThreshold: 30 + periodSeconds: 5 + livenessProbe: + httpGet: + path: /actuator/health/liveness + port: http + periodSeconds: 30 + failureThreshold: 3 + readinessProbe: + httpGet: + path: /actuator/health/readiness + port: http + initialDelaySeconds: 5 + periodSeconds: 10 + failureThreshold: 3 + volumes: + - name: data + persistentVolumeClaim: + claimName: swarm-alpha-data diff --git a/servers/legion/k8s/neuron-technologies/swarm/mcp-deployment-beta.yaml b/servers/legion/k8s/neuron-technologies/swarm/mcp-deployment-beta.yaml new file mode 100644 index 0000000..c6d6cca --- /dev/null +++ b/servers/legion/k8s/neuron-technologies/swarm/mcp-deployment-beta.yaml @@ -0,0 +1,120 @@ +apiVersion: apps/v1 +kind: Deployment +metadata: + name: neuron-mcp + namespace: swarm-beta + labels: + app: neuron-mcp + env: swarm + variant: beta +spec: + replicas: 1 + strategy: + type: Recreate + selector: + matchLabels: + app: neuron-mcp + template: + metadata: + labels: + app: neuron-mcp + env: swarm + variant: beta + spec: + terminationGracePeriodSeconds: 30 + securityContext: + runAsNonRoot: true + seccompProfile: + type: RuntimeDefault + initContainers: + - name: wait-for-sqlite-clone + image: busybox:1.36 + command: ["sh", "-c", "until [ -f /data/neuron.db ]; do echo 'waiting for SQLite clone...'; sleep 2; done; echo 'SQLite ready'"] + volumeMounts: + - name: data + mountPath: /data + securityContext: + runAsNonRoot: true + allowPrivilegeEscalation: false + capabilities: + drop: ["ALL"] + containers: + - name: neuron-mcp + image: registry.neuralplatform.ai/neuron-technologies/neuron-mcp:v0.15.3 + imagePullPolicy: Always + ports: + - name: http + containerPort: 8080 + securityContext: + allowPrivilegeEscalation: false + readOnlyRootFilesystem: false + runAsNonRoot: true + capabilities: + drop: ["ALL"] + env: + - name: NEURON_SWARM_VARIANT + value: "beta" + - name: NEURON_SWARM_SESSION + valueFrom: + configMapKeyRef: + name: swarm-beta-session + key: session_id + optional: true + - name: NEURON_SWARM_GOAL + valueFrom: + configMapKeyRef: + name: swarm-beta-session + key: goal + optional: true + - name: NEURON_SWARM_LOOP_MAX + valueFrom: + configMapKeyRef: + name: swarm-beta-session + key: loop_max + optional: true + - name: OTEL_EXPORTER_OTLP_ENDPOINT + value: "http://alloy-otlp.monitoring.svc.cluster.local:4318" + - name: JAVA_TOOL_OPTIONS + value: "-XX:+UseContainerSupport -XX:MaxRAMPercentage=75.0 -XX:+ExitOnOutOfMemoryError" + envFrom: + - configMapRef: + name: swarm-beta-config + - secretRef: + name: swarm-beta-secrets + volumeMounts: + - name: data + mountPath: /data + resources: + requests: + cpu: 250m + memory: 512Mi + limits: + cpu: 1500m + memory: 1536Mi + lifecycle: + preStop: + exec: + command: ["sh", "-c", "sleep 5"] + startupProbe: + httpGet: + path: /actuator/health/liveness + port: http + failureThreshold: 30 + periodSeconds: 5 + livenessProbe: + httpGet: + path: /actuator/health/liveness + port: http + periodSeconds: 30 + failureThreshold: 3 + readinessProbe: + httpGet: + path: /actuator/health/readiness + port: http + initialDelaySeconds: 5 + periodSeconds: 10 + failureThreshold: 3 + volumes: + - name: data + persistentVolumeClaim: + claimName: swarm-beta-data diff --git a/servers/legion/k8s/neuron-technologies/swarm/mcp-deployment-gamma.yaml b/servers/legion/k8s/neuron-technologies/swarm/mcp-deployment-gamma.yaml new file mode 100644 index 0000000..5c452ec --- /dev/null +++ b/servers/legion/k8s/neuron-technologies/swarm/mcp-deployment-gamma.yaml @@ -0,0 +1,120 @@ +apiVersion: apps/v1 +kind: Deployment +metadata: + name: neuron-mcp + namespace: swarm-gamma + labels: + app: neuron-mcp + env: swarm + variant: gamma +spec: + replicas: 1 + strategy: + type: Recreate + selector: + matchLabels: + app: neuron-mcp + template: + metadata: + labels: + app: neuron-mcp + env: swarm + variant: gamma + spec: + terminationGracePeriodSeconds: 30 + securityContext: + runAsNonRoot: true + seccompProfile: + type: RuntimeDefault + initContainers: + - name: wait-for-sqlite-clone + image: busybox:1.36 + command: ["sh", "-c", "until [ -f /data/neuron.db ]; do echo 'waiting for SQLite clone...'; sleep 2; done; echo 'SQLite ready'"] + volumeMounts: + - name: data + mountPath: /data + securityContext: + runAsNonRoot: true + allowPrivilegeEscalation: false + capabilities: + drop: ["ALL"] + containers: + - name: neuron-mcp + image: registry.neuralplatform.ai/neuron-technologies/neuron-mcp:v0.15.3 + imagePullPolicy: Always + ports: + - name: http + containerPort: 8080 + securityContext: + allowPrivilegeEscalation: false + readOnlyRootFilesystem: false + runAsNonRoot: true + capabilities: + drop: ["ALL"] + env: + - name: NEURON_SWARM_VARIANT + value: "gamma" + - name: NEURON_SWARM_SESSION + valueFrom: + configMapKeyRef: + name: swarm-gamma-session + key: session_id + optional: true + - name: NEURON_SWARM_GOAL + valueFrom: + configMapKeyRef: + name: swarm-gamma-session + key: goal + optional: true + - name: NEURON_SWARM_LOOP_MAX + valueFrom: + configMapKeyRef: + name: swarm-gamma-session + key: loop_max + optional: true + - name: OTEL_EXPORTER_OTLP_ENDPOINT + value: "http://alloy-otlp.monitoring.svc.cluster.local:4318" + - name: JAVA_TOOL_OPTIONS + value: "-XX:+UseContainerSupport -XX:MaxRAMPercentage=75.0 -XX:+ExitOnOutOfMemoryError" + envFrom: + - configMapRef: + name: swarm-gamma-config + - secretRef: + name: swarm-gamma-secrets + volumeMounts: + - name: data + mountPath: /data + resources: + requests: + cpu: 250m + memory: 512Mi + limits: + cpu: 1500m + memory: 1536Mi + lifecycle: + preStop: + exec: + command: ["sh", "-c", "sleep 5"] + startupProbe: + httpGet: + path: /actuator/health/liveness + port: http + failureThreshold: 30 + periodSeconds: 5 + livenessProbe: + httpGet: + path: /actuator/health/liveness + port: http + periodSeconds: 30 + failureThreshold: 3 + readinessProbe: + httpGet: + path: /actuator/health/readiness + port: http + initialDelaySeconds: 5 + periodSeconds: 10 + failureThreshold: 3 + volumes: + - name: data + persistentVolumeClaim: + claimName: swarm-gamma-data diff --git a/servers/legion/k8s/neuron-technologies/swarm/namespace-alpha.yaml b/servers/legion/k8s/neuron-technologies/swarm/namespace-alpha.yaml new file mode 100644 index 0000000..4dcd487 --- /dev/null +++ b/servers/legion/k8s/neuron-technologies/swarm/namespace-alpha.yaml @@ -0,0 +1,9 @@ +apiVersion: v1 +kind: Namespace +metadata: + name: swarm-alpha + labels: + app: neuron-technologies + tier: swarm + variant: alpha + managed-by: argocd diff --git a/servers/legion/k8s/neuron-technologies/swarm/namespace-beta.yaml b/servers/legion/k8s/neuron-technologies/swarm/namespace-beta.yaml new file mode 100644 index 0000000..8cba811 --- /dev/null +++ b/servers/legion/k8s/neuron-technologies/swarm/namespace-beta.yaml @@ -0,0 +1,9 @@ +apiVersion: v1 +kind: Namespace +metadata: + name: swarm-beta + labels: + app: neuron-technologies + tier: swarm + variant: beta + managed-by: argocd diff --git a/servers/legion/k8s/neuron-technologies/swarm/namespace-gamma.yaml b/servers/legion/k8s/neuron-technologies/swarm/namespace-gamma.yaml new file mode 100644 index 0000000..0fe1c27 --- /dev/null +++ b/servers/legion/k8s/neuron-technologies/swarm/namespace-gamma.yaml @@ -0,0 +1,9 @@ +apiVersion: v1 +kind: Namespace +metadata: + name: swarm-gamma + labels: + app: neuron-technologies + tier: swarm + variant: gamma + managed-by: argocd diff --git a/servers/legion/k8s/neuron-technologies/swarm/pvc-alpha.yaml b/servers/legion/k8s/neuron-technologies/swarm/pvc-alpha.yaml new file mode 100644 index 0000000..9188a3e --- /dev/null +++ b/servers/legion/k8s/neuron-technologies/swarm/pvc-alpha.yaml @@ -0,0 +1,12 @@ +apiVersion: v1 +kind: PersistentVolumeClaim +metadata: + name: swarm-alpha-data + namespace: swarm-alpha +spec: + storageClassName: local-path + accessModes: + - ReadWriteOnce + resources: + requests: + storage: 20Gi diff --git a/servers/legion/k8s/neuron-technologies/swarm/pvc-beta.yaml b/servers/legion/k8s/neuron-technologies/swarm/pvc-beta.yaml new file mode 100644 index 0000000..51a6697 --- /dev/null +++ b/servers/legion/k8s/neuron-technologies/swarm/pvc-beta.yaml @@ -0,0 +1,12 @@ +apiVersion: v1 +kind: PersistentVolumeClaim +metadata: + name: swarm-beta-data + namespace: swarm-beta +spec: + storageClassName: local-path + accessModes: + - ReadWriteOnce + resources: + requests: + storage: 20Gi diff --git a/servers/legion/k8s/neuron-technologies/swarm/pvc-gamma.yaml b/servers/legion/k8s/neuron-technologies/swarm/pvc-gamma.yaml new file mode 100644 index 0000000..a134c20 --- /dev/null +++ b/servers/legion/k8s/neuron-technologies/swarm/pvc-gamma.yaml @@ -0,0 +1,12 @@ +apiVersion: v1 +kind: PersistentVolumeClaim +metadata: + name: swarm-gamma-data + namespace: swarm-gamma +spec: + storageClassName: local-path + accessModes: + - ReadWriteOnce + resources: + requests: + storage: 20Gi diff --git a/servers/legion/k8s/neuron-technologies/swarm/rbac.yaml b/servers/legion/k8s/neuron-technologies/swarm/rbac.yaml new file mode 100644 index 0000000..4a89fc6 --- /dev/null +++ b/servers/legion/k8s/neuron-technologies/swarm/rbac.yaml @@ -0,0 +1,97 @@ +# RBAC for swarm variant namespaces +# Grants the CI runner ServiceAccount permission to deploy to swarm-* namespaces. +# Mirrors the pattern used for neuron-dev/stage deployments. +# The CI runner runs in the `ci` namespace as the `default` ServiceAccount. +--- +# swarm-alpha +apiVersion: rbac.authorization.k8s.io/v1 +kind: Role +metadata: + name: swarm-deployer + namespace: swarm-alpha +rules: + - apiGroups: ["apps"] + resources: ["deployments"] + verbs: ["get", "list", "watch", "create", "update", "patch"] + - apiGroups: [""] + resources: ["configmaps", "services", "pods", "pods/log"] + verbs: ["get", "list", "watch", "create", "update", "patch", "delete"] + - apiGroups: ["batch"] + resources: ["jobs"] + verbs: ["get", "list", "watch", "create", "update", "patch", "delete"] +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: RoleBinding +metadata: + name: ci-runner-swarm-alpha + namespace: swarm-alpha +subjects: + - kind: ServiceAccount + name: default + namespace: ci +roleRef: + kind: Role + name: swarm-deployer + apiGroup: rbac.authorization.k8s.io +--- +# swarm-beta +apiVersion: rbac.authorization.k8s.io/v1 +kind: Role +metadata: + name: swarm-deployer + namespace: swarm-beta +rules: + - apiGroups: ["apps"] + resources: ["deployments"] + verbs: ["get", "list", "watch", "create", "update", "patch"] + - apiGroups: [""] + resources: ["configmaps", "services", "pods", "pods/log"] + verbs: ["get", "list", "watch", "create", "update", "patch", "delete"] + - apiGroups: ["batch"] + resources: ["jobs"] + verbs: ["get", "list", "watch", "create", "update", "patch", "delete"] +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: RoleBinding +metadata: + name: ci-runner-swarm-beta + namespace: swarm-beta +subjects: + - kind: ServiceAccount + name: default + namespace: ci +roleRef: + kind: Role + name: swarm-deployer + apiGroup: rbac.authorization.k8s.io +--- +# swarm-gamma +apiVersion: rbac.authorization.k8s.io/v1 +kind: Role +metadata: + name: swarm-deployer + namespace: swarm-gamma +rules: + - apiGroups: ["apps"] + resources: ["deployments"] + verbs: ["get", "list", "watch", "create", "update", "patch"] + - apiGroups: [""] + resources: ["configmaps", "services", "pods", "pods/log"] + verbs: ["get", "list", "watch", "create", "update", "patch", "delete"] + - apiGroups: ["batch"] + resources: ["jobs"] + verbs: ["get", "list", "watch", "create", "update", "patch", "delete"] +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: RoleBinding +metadata: + name: ci-runner-swarm-gamma + namespace: swarm-gamma +subjects: + - kind: ServiceAccount + name: default + namespace: ci +roleRef: + kind: Role + name: swarm-deployer + apiGroup: rbac.authorization.k8s.io diff --git a/servers/legion/k8s/neuron-technologies/swarm/rest-deployment-alpha.yaml b/servers/legion/k8s/neuron-technologies/swarm/rest-deployment-alpha.yaml new file mode 100644 index 0000000..5377a68 --- /dev/null +++ b/servers/legion/k8s/neuron-technologies/swarm/rest-deployment-alpha.yaml @@ -0,0 +1,99 @@ +apiVersion: apps/v1 +kind: Deployment +metadata: + name: neuron-rest + namespace: swarm-alpha + labels: + app: neuron-rest + env: swarm + variant: alpha +spec: + replicas: 1 + strategy: + type: Recreate + selector: + matchLabels: + app: neuron-rest + template: + metadata: + labels: + app: neuron-rest + env: swarm + variant: alpha + spec: + securityContext: + runAsNonRoot: true + seccompProfile: + type: RuntimeDefault + containers: + - name: neuron-rest + image: registry.neuralplatform.ai/neuron-technologies/neuron-rest:v0.15.3 + imagePullPolicy: Always + ports: + - name: http + containerPort: 8081 + securityContext: + allowPrivilegeEscalation: false + readOnlyRootFilesystem: false + runAsNonRoot: true + capabilities: + drop: ["ALL"] + env: + - name: NEURON_SWARM_VARIANT + value: "alpha" + - name: NEURON_SWARM_SESSION + valueFrom: + configMapKeyRef: + name: swarm-alpha-session + key: session_id + optional: true + - name: NEURON_SWARM_GOAL + valueFrom: + configMapKeyRef: + name: swarm-alpha-session + key: goal + optional: true + - name: NEURON_SWARM_LOOP_MAX + valueFrom: + configMapKeyRef: + name: swarm-alpha-session + key: loop_max + optional: true + envFrom: + - configMapRef: + name: swarm-alpha-config + - secretRef: + name: swarm-alpha-secrets + volumeMounts: + - name: data + mountPath: /data + resources: + requests: + cpu: 250m + memory: 512Mi + limits: + cpu: 1000m + memory: 1Gi + startupProbe: + httpGet: + path: /actuator/health/liveness + port: http + failureThreshold: 30 + periodSeconds: 5 + livenessProbe: + httpGet: + path: /actuator/health/liveness + port: http + periodSeconds: 30 + failureThreshold: 3 + readinessProbe: + httpGet: + path: /actuator/health/readiness + port: http + initialDelaySeconds: 5 + periodSeconds: 10 + failureThreshold: 3 + volumes: + - name: data + persistentVolumeClaim: + claimName: swarm-alpha-data diff --git a/servers/legion/k8s/neuron-technologies/swarm/rest-deployment-beta.yaml b/servers/legion/k8s/neuron-technologies/swarm/rest-deployment-beta.yaml new file mode 100644 index 0000000..bed4bcf --- /dev/null +++ b/servers/legion/k8s/neuron-technologies/swarm/rest-deployment-beta.yaml @@ -0,0 +1,99 @@ +apiVersion: apps/v1 +kind: Deployment +metadata: + name: neuron-rest + namespace: swarm-beta + labels: + app: neuron-rest + env: swarm + variant: beta +spec: + replicas: 1 + strategy: + type: Recreate + selector: + matchLabels: + app: neuron-rest + template: + metadata: + labels: + app: neuron-rest + env: swarm + variant: beta + spec: + securityContext: + runAsNonRoot: true + seccompProfile: + type: RuntimeDefault + containers: + - name: neuron-rest + image: registry.neuralplatform.ai/neuron-technologies/neuron-rest:v0.15.3 + imagePullPolicy: Always + ports: + - name: http + containerPort: 8081 + securityContext: + allowPrivilegeEscalation: false + readOnlyRootFilesystem: false + runAsNonRoot: true + capabilities: + drop: ["ALL"] + env: + - name: NEURON_SWARM_VARIANT + value: "beta" + - name: NEURON_SWARM_SESSION + valueFrom: + configMapKeyRef: + name: swarm-beta-session + key: session_id + optional: true + - name: NEURON_SWARM_GOAL + valueFrom: + configMapKeyRef: + name: swarm-beta-session + key: goal + optional: true + - name: NEURON_SWARM_LOOP_MAX + valueFrom: + configMapKeyRef: + name: swarm-beta-session + key: loop_max + optional: true + envFrom: + - configMapRef: + name: swarm-beta-config + - secretRef: + name: swarm-beta-secrets + volumeMounts: + - name: data + mountPath: /data + resources: + requests: + cpu: 250m + memory: 512Mi + limits: + cpu: 1000m + memory: 1Gi + startupProbe: + httpGet: + path: /actuator/health/liveness + port: http + failureThreshold: 30 + periodSeconds: 5 + livenessProbe: + httpGet: + path: /actuator/health/liveness + port: http + periodSeconds: 30 + failureThreshold: 3 + readinessProbe: + httpGet: + path: /actuator/health/readiness + port: http + initialDelaySeconds: 5 + periodSeconds: 10 + failureThreshold: 3 + volumes: + - name: data + persistentVolumeClaim: + claimName: swarm-beta-data diff --git a/servers/legion/k8s/neuron-technologies/swarm/rest-deployment-gamma.yaml b/servers/legion/k8s/neuron-technologies/swarm/rest-deployment-gamma.yaml new file mode 100644 index 0000000..e512a64 --- /dev/null +++ b/servers/legion/k8s/neuron-technologies/swarm/rest-deployment-gamma.yaml @@ -0,0 +1,99 @@ +apiVersion: apps/v1 +kind: Deployment +metadata: + name: neuron-rest + namespace: swarm-gamma + labels: + app: neuron-rest + env: swarm + variant: gamma +spec: + replicas: 1 + strategy: + type: Recreate + selector: + matchLabels: + app: neuron-rest + template: + metadata: + labels: + app: neuron-rest + env: swarm + variant: gamma + spec: + securityContext: + runAsNonRoot: true + seccompProfile: + type: RuntimeDefault + containers: + - name: neuron-rest + image: registry.neuralplatform.ai/neuron-technologies/neuron-rest:v0.15.3 + imagePullPolicy: Always + ports: + - name: http + containerPort: 8081 + securityContext: + allowPrivilegeEscalation: false + readOnlyRootFilesystem: false + runAsNonRoot: true + capabilities: + drop: ["ALL"] + env: + - name: NEURON_SWARM_VARIANT + value: "gamma" + - name: NEURON_SWARM_SESSION + valueFrom: + configMapKeyRef: + name: swarm-gamma-session + key: session_id + optional: true + - name: NEURON_SWARM_GOAL + valueFrom: + configMapKeyRef: + name: swarm-gamma-session + key: goal + optional: true + - name: NEURON_SWARM_LOOP_MAX + valueFrom: + configMapKeyRef: + name: swarm-gamma-session + key: loop_max + optional: true + envFrom: + - configMapRef: + name: swarm-gamma-config + - secretRef: + name: swarm-gamma-secrets + volumeMounts: + - name: data + mountPath: /data + resources: + requests: + cpu: 250m + memory: 512Mi + limits: + cpu: 1000m + memory: 1Gi + startupProbe: + httpGet: + path: /actuator/health/liveness + port: http + failureThreshold: 30 + periodSeconds: 5 + livenessProbe: + httpGet: + path: /actuator/health/liveness + port: http + periodSeconds: 30 + failureThreshold: 3 + readinessProbe: + httpGet: + path: /actuator/health/readiness + port: http + initialDelaySeconds: 5 + periodSeconds: 10 + failureThreshold: 3 + volumes: + - name: data + persistentVolumeClaim: + claimName: swarm-gamma-data diff --git a/servers/legion/k8s/neuron-technologies/swarm/services.yaml b/servers/legion/k8s/neuron-technologies/swarm/services.yaml new file mode 100644 index 0000000..3ab65ec --- /dev/null +++ b/servers/legion/k8s/neuron-technologies/swarm/services.yaml @@ -0,0 +1,103 @@ +# Services for swarm variants — ClusterIP only, no external exposure needed +--- +apiVersion: v1 +kind: Service +metadata: + name: neuron-mcp + namespace: swarm-alpha + labels: + app: neuron-mcp + variant: alpha +spec: + selector: + app: neuron-mcp + ports: + - name: http + port: 8080 + targetPort: 8080 + type: ClusterIP +--- +apiVersion: v1 +kind: Service +metadata: + name: neuron-rest + namespace: swarm-alpha + labels: + app: neuron-rest + variant: alpha +spec: + selector: + app: neuron-rest + ports: + - name: http + port: 8081 + targetPort: 8081 + type: ClusterIP +--- +apiVersion: v1 +kind: Service +metadata: + name: neuron-mcp + namespace: swarm-beta + labels: + app: neuron-mcp + variant: beta +spec: + selector: + app: neuron-mcp + ports: + - name: http + port: 8080 + targetPort: 8080 + type: ClusterIP +--- +apiVersion: v1 +kind: Service +metadata: + name: neuron-rest + namespace: swarm-beta + labels: + app: neuron-rest + variant: beta +spec: + selector: + app: neuron-rest + ports: + - name: http + port: 8081 + targetPort: 8081 + type: ClusterIP +--- +apiVersion: v1 +kind: Service +metadata: + name: neuron-mcp + namespace: swarm-gamma + labels: + app: neuron-mcp + variant: gamma +spec: + selector: + app: neuron-mcp + ports: + - name: http + port: 8080 + targetPort: 8080 + type: ClusterIP +--- +apiVersion: v1 +kind: Service +metadata: + name: neuron-rest + namespace: swarm-gamma + labels: + app: neuron-rest + variant: gamma +spec: + selector: + app: neuron-rest + ports: + - name: http + port: 8081 + targetPort: 8081 + type: ClusterIP diff --git a/servers/legion/k8s/neuron-technologies/swarm/sqlite-clone-job-alpha.yaml b/servers/legion/k8s/neuron-technologies/swarm/sqlite-clone-job-alpha.yaml new file mode 100644 index 0000000..a00d33f --- /dev/null +++ b/servers/legion/k8s/neuron-technologies/swarm/sqlite-clone-job-alpha.yaml @@ -0,0 +1,66 @@ +# SQLite clone Job for swarm-alpha +# Creates a snapshot of the prod neuron.db into swarm-alpha's PVC. +# This Job is created by swarm.sh at session start; it is NOT static. +# This file is the template — swarm.sh applies it via kubectl after substituting SESSION_ID. +# +# The Job mounts both the prod PVC (read-only) and the variant PVC (read-write). +# It uses a simple cp to snapshot the database before the variant MCP starts. +# +# NOTE: The prod MCP must be scaled down to 0 OR the Job must use SQLite's backup API +# (via sqlite3 .backup command) to ensure consistency. swarm.sh handles the hot-backup +# approach using the sqlite3 CLI, so the prod pod does NOT need to stop. +apiVersion: batch/v1 +kind: Job +metadata: + name: sqlite-clone-alpha + namespace: swarm-alpha + labels: + app: swarm-clone + variant: alpha +spec: + ttlSecondsAfterFinished: 3600 + backoffLimit: 3 + template: + metadata: + labels: + app: swarm-clone + variant: alpha + spec: + restartPolicy: OnFailure + securityContext: + runAsNonRoot: false # sqlite3 needs to run as root to access both PVCs + containers: + - name: sqlite-clone + image: keinos/sqlite3:latest + command: + - sh + - -c + - | + set -e + echo "Starting SQLite hot-backup from prod to swarm-alpha..." + # Use SQLite's .backup command for a consistent online backup + sqlite3 /prod-data/neuron.db ".backup /variant-data/neuron.db" + echo "Backup complete. Verifying..." + sqlite3 /variant-data/neuron.db "PRAGMA integrity_check;" + echo "SQLite clone complete for swarm-alpha." + volumeMounts: + - name: prod-data + mountPath: /prod-data + readOnly: true + - name: variant-data + mountPath: /variant-data + resources: + requests: + cpu: 100m + memory: 128Mi + limits: + cpu: 500m + memory: 512Mi + volumes: + - name: prod-data + persistentVolumeClaim: + claimName: neuron-prod-data + readOnly: true + - name: variant-data + persistentVolumeClaim: + claimName: swarm-alpha-data diff --git a/servers/legion/k8s/neuron-technologies/swarm/sqlite-clone-job-beta.yaml b/servers/legion/k8s/neuron-technologies/swarm/sqlite-clone-job-beta.yaml new file mode 100644 index 0000000..832fa71 --- /dev/null +++ b/servers/legion/k8s/neuron-technologies/swarm/sqlite-clone-job-beta.yaml @@ -0,0 +1,54 @@ +apiVersion: batch/v1 +kind: Job +metadata: + name: sqlite-clone-beta + namespace: swarm-beta + labels: + app: swarm-clone + variant: beta +spec: + ttlSecondsAfterFinished: 3600 + backoffLimit: 3 + template: + metadata: + labels: + app: swarm-clone + variant: beta + spec: + restartPolicy: OnFailure + securityContext: + runAsNonRoot: false + containers: + - name: sqlite-clone + image: keinos/sqlite3:latest + command: + - sh + - -c + - | + set -e + echo "Starting SQLite hot-backup from prod to swarm-beta..." + sqlite3 /prod-data/neuron.db ".backup /variant-data/neuron.db" + echo "Backup complete. Verifying..." + sqlite3 /variant-data/neuron.db "PRAGMA integrity_check;" + echo "SQLite clone complete for swarm-beta." + volumeMounts: + - name: prod-data + mountPath: /prod-data + readOnly: true + - name: variant-data + mountPath: /variant-data + resources: + requests: + cpu: 100m + memory: 128Mi + limits: + cpu: 500m + memory: 512Mi + volumes: + - name: prod-data + persistentVolumeClaim: + claimName: neuron-prod-data + readOnly: true + - name: variant-data + persistentVolumeClaim: + claimName: swarm-beta-data diff --git a/servers/legion/k8s/neuron-technologies/swarm/sqlite-clone-job-gamma.yaml b/servers/legion/k8s/neuron-technologies/swarm/sqlite-clone-job-gamma.yaml new file mode 100644 index 0000000..0a0a76e --- /dev/null +++ b/servers/legion/k8s/neuron-technologies/swarm/sqlite-clone-job-gamma.yaml @@ -0,0 +1,54 @@ +apiVersion: batch/v1 +kind: Job +metadata: + name: sqlite-clone-gamma + namespace: swarm-gamma + labels: + app: swarm-clone + variant: gamma +spec: + ttlSecondsAfterFinished: 3600 + backoffLimit: 3 + template: + metadata: + labels: + app: swarm-clone + variant: gamma + spec: + restartPolicy: OnFailure + securityContext: + runAsNonRoot: false + containers: + - name: sqlite-clone + image: keinos/sqlite3:latest + command: + - sh + - -c + - | + set -e + echo "Starting SQLite hot-backup from prod to swarm-gamma..." + sqlite3 /prod-data/neuron.db ".backup /variant-data/neuron.db" + echo "Backup complete. Verifying..." + sqlite3 /variant-data/neuron.db "PRAGMA integrity_check;" + echo "SQLite clone complete for swarm-gamma." + volumeMounts: + - name: prod-data + mountPath: /prod-data + readOnly: true + - name: variant-data + mountPath: /variant-data + resources: + requests: + cpu: 100m + memory: 128Mi + limits: + cpu: 500m + memory: 512Mi + volumes: + - name: prod-data + persistentVolumeClaim: + claimName: neuron-prod-data + readOnly: true + - name: variant-data + persistentVolumeClaim: + claimName: swarm-gamma-data diff --git a/servers/legion/neuron-technologies.tf b/servers/legion/neuron-technologies.tf index 0587ad8..42deefc 100644 --- a/servers/legion/neuron-technologies.tf +++ b/servers/legion/neuron-technologies.tf @@ -50,3 +50,43 @@ resource "kubernetes_namespace" "neuron_tim" { } } } + +# Swarm variant namespaces — isolated execution environments for swarm self-improvement loops +resource "kubernetes_namespace" "swarm_alpha" { + metadata { + name = "swarm-alpha" + labels = { + managed-by = "terraform" + tier = "swarm" + environment = "swarm" + app = "neuron-technologies" + variant = "alpha" + } + } +} + +resource "kubernetes_namespace" "swarm_beta" { + metadata { + name = "swarm-beta" + labels = { + managed-by = "terraform" + tier = "swarm" + environment = "swarm" + app = "neuron-technologies" + variant = "beta" + } + } +} + +resource "kubernetes_namespace" "swarm_gamma" { + metadata { + name = "swarm-gamma" + labels = { + managed-by = "terraform" + tier = "swarm" + environment = "swarm" + app = "neuron-technologies" + variant = "gamma" + } + } +}