From 2fa5f0cb1166b97b1952a1442d88eb320462c23c Mon Sep 17 00:00:00 2001 From: sirius0xdev Date: Sat, 18 Apr 2026 02:56:18 +0000 Subject: [PATCH] add openclaw to cluster. --- apps/base/customer1/openclaw/configmap.yaml | 39 +++++ apps/base/customer1/openclaw/deployment.yaml | 147 ++++++++++++++++++ .../customer1/openclaw/kustomization.yaml | 8 + .../customer1/openclaw/openclaw-secrets.yaml | 23 +++ apps/base/customer1/openclaw/pvc.yaml | 12 ++ apps/base/customer1/openclaw/service.yaml | 15 ++ modules/pro6000-nodepool.tf | 55 +++++++ 7 files changed, 299 insertions(+) create mode 100644 apps/base/customer1/openclaw/configmap.yaml create mode 100644 apps/base/customer1/openclaw/deployment.yaml create mode 100644 apps/base/customer1/openclaw/kustomization.yaml create mode 100644 apps/base/customer1/openclaw/openclaw-secrets.yaml create mode 100644 apps/base/customer1/openclaw/pvc.yaml create mode 100644 apps/base/customer1/openclaw/service.yaml create mode 100644 modules/pro6000-nodepool.tf diff --git a/apps/base/customer1/openclaw/configmap.yaml b/apps/base/customer1/openclaw/configmap.yaml new file mode 100644 index 0000000..9b41b74 --- /dev/null +++ b/apps/base/customer1/openclaw/configmap.yaml @@ -0,0 +1,39 @@ +apiVersion: v1 +kind: ConfigMap +metadata: + name: openclaw-config + namespace: customer1 + labels: + app: openclaw +data: + openclaw.json: | + { + "gateway": { + "mode": "local", + "bind": "loopback", + "port": 18789, + "auth": { + "mode": "token" + }, + "controlUi": { + "enabled": true + } + }, + "agents": { + "defaults": { + "workspace": "~/.openclaw/workspace" + }, + "list": [ + { + "id": "default", + "name": "OpenClaw Assistant", + "workspace": "~/.openclaw/workspace" + } + ] + }, + "cron": { "enabled": false } + } + AGENTS.md: | + # OpenClaw Assistant + + You are a helpful AI assistant running in Kubernetes. diff --git a/apps/base/customer1/openclaw/deployment.yaml b/apps/base/customer1/openclaw/deployment.yaml new file mode 100644 index 0000000..7531844 --- /dev/null +++ b/apps/base/customer1/openclaw/deployment.yaml @@ -0,0 +1,147 @@ +apiVersion: apps/v1 +kind: Deployment +metadata: + namespace: customer1 + name: openclaw + labels: + app: openclaw +spec: + replicas: 1 + selector: + matchLabels: + app: openclaw + strategy: + type: Recreate + template: + metadata: + labels: + app: openclaw + spec: + automountServiceAccountToken: false + securityContext: + fsGroup: 1000 + seccompProfile: + type: RuntimeDefault + initContainers: + - name: init-config + image: busybox:1.37 + imagePullPolicy: IfNotPresent + command: + - sh + - -c + - | + cp /config/openclaw.json /home/node/.openclaw/openclaw.json + mkdir -p /home/node/.openclaw/workspace + cp /config/AGENTS.md /home/node/.openclaw/workspace/AGENTS.md + securityContext: + runAsUser: 1000 + runAsGroup: 1000 + resources: + requests: + memory: 32Mi + cpu: 50m + limits: + memory: 64Mi + cpu: 100m + volumeMounts: + - name: openclaw-home + mountPath: /home/node/.openclaw + - name: config + mountPath: /config + containers: + - name: gateway + image: ghcr.io/openclaw/openclaw:slim + imagePullPolicy: IfNotPresent + command: + - node + - /app/dist/index.js + - gateway + - run + ports: + - name: gateway + containerPort: 18789 + protocol: TCP + env: + - name: HOME + value: /home/node + - name: OPENCLAW_CONFIG_DIR + value: /home/node/.openclaw + - name: NODE_ENV + value: production + - name: OPENCLAW_GATEWAY_TOKEN + valueFrom: + secretKeyRef: + name: openclaw-secrets + key: OPENCLAW_GATEWAY_TOKEN + - name: ANTHROPIC_API_KEY + valueFrom: + secretKeyRef: + name: openclaw-secrets + key: ANTHROPIC_API_KEY + optional: true + - name: OPENAI_API_KEY + valueFrom: + secretKeyRef: + name: openclaw-secrets + key: OPENAI_API_KEY + optional: true + - name: GEMINI_API_KEY + valueFrom: + secretKeyRef: + name: openclaw-secrets + key: GEMINI_API_KEY + optional: true + - name: OPENROUTER_API_KEY + valueFrom: + secretKeyRef: + name: openclaw-secrets + key: OPENROUTER_API_KEY + optional: true + resources: + requests: + memory: 512Mi + cpu: 250m + limits: + memory: 4Gi + cpu: "1" + livenessProbe: + exec: + command: + - node + - -e + - "require('http').get('http://127.0.0.1:18789/healthz', r => process.exit(r.statusCode < 400 ? 0 : 1)).on('error', () => process.exit(1))" + initialDelaySeconds: 60 + periodSeconds: 30 + timeoutSeconds: 10 + readinessProbe: + exec: + command: + - node + - -e + - "require('http').get('http://127.0.0.1:18789/readyz', r => process.exit(r.statusCode < 400 ? 0 : 1)).on('error', () => process.exit(1))" + initialDelaySeconds: 15 + periodSeconds: 10 + timeoutSeconds: 5 + volumeMounts: + - name: openclaw-home + mountPath: /home/node/.openclaw + - name: tmp-volume + mountPath: /tmp + securityContext: + runAsNonRoot: true + runAsUser: 1000 + runAsGroup: 1000 + allowPrivilegeEscalation: false + readOnlyRootFilesystem: true + capabilities: + drop: + - ALL + volumes: + - name: openclaw-home + persistentVolumeClaim: + claimName: openclaw-home-pvc + - name: config + configMap: + name: openclaw-config + - name: tmp-volume + emptyDir: {} diff --git a/apps/base/customer1/openclaw/kustomization.yaml b/apps/base/customer1/openclaw/kustomization.yaml new file mode 100644 index 0000000..147e03d --- /dev/null +++ b/apps/base/customer1/openclaw/kustomization.yaml @@ -0,0 +1,8 @@ +apiVersion: kustomize.config.k8s.io/v1beta1 +kind: Kustomization +resources: + - pvc.yaml + - configmap.yaml + - deployment.yaml + - service.yaml + - openclaw-secrets.yaml diff --git a/apps/base/customer1/openclaw/openclaw-secrets.yaml b/apps/base/customer1/openclaw/openclaw-secrets.yaml new file mode 100644 index 0000000..a21e5ca --- /dev/null +++ b/apps/base/customer1/openclaw/openclaw-secrets.yaml @@ -0,0 +1,23 @@ +apiVersion: v1 +data: + GEMINI_API_KEY: ENC[AES256_GCM,data:Db+wQ97LH83AyIlnDR9G2/G1KxFrGOBCe4r/oF5ha6fU7mptMhBwlkpYahI/uBlZrCKRCD8TSjePE34r+IqbkADxW6/3RRqw,iv:EtAb3/Hrd6uFCkI/ilEPrISCXQqg7EHvr9ZEHwhJ0PM=,tag:y8BRHHszENNB27V30DTNNw==,type:str] +kind: Secret +metadata: + creationTimestamp: null + name: openclaw-secrets + namespace: customer1 +sops: + age: + - recipient: age1uuxf066xuuqgvjppxfcmqkwfcufnwp3wcwnl9h20g9k4l8nkw9jsaungf7 + enc: | + -----BEGIN AGE ENCRYPTED FILE----- + YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBSUmk5VGVMeko4WjhtMHJ2 + MmF5bzRGMEd4S3UyNTl5elo4ejZjeWo5RjBJCnhKeG1maWxpQzhFNUQ5dVpnK3VU + Sm1qVVBheXZYazNwNytlMTZHcDZYUTAKLS0tIGlOWGNBTWJlUlVpV0ovTGF1dXBI + U3VEeExXOHVNMG15RjNZb0NyWEFWUVkKCJE8UyglijNTBLrMZ3ggxwnYpAGVTFXr + 2i5vqb8byppiAkMNwLzvz06XYhwFt8JSdxym3DMQJQS7ALtA5mCkYg== + -----END AGE ENCRYPTED FILE----- + lastmodified: "2026-04-18T02:54:32Z" + mac: ENC[AES256_GCM,data:sFV9JunMLa9b8Pdc8abAt6p357pdqkgAuwIjAsvwVX15DewJhX8e1Kt/WAV21+Fkn4kqiIYZSUVPsGgUlEMXw7kVcxssKYmTr1ioDVyBMOH867E/x6fDIbd4OJN75WYsL5QAgbxMyzCCoVQHV5CSLmwIEAzN94UZkfg87S4yHKQ=,iv:TcqHHQzmr1FyUbcCVlkzk9yHMGZwHPMGRLZjrIOjpl0=,tag:8sKGweCmhh6DLuVKVnnVJA==,type:str] + encrypted_regex: ^(data|stringData)$ + version: 3.11.0 diff --git a/apps/base/customer1/openclaw/pvc.yaml b/apps/base/customer1/openclaw/pvc.yaml new file mode 100644 index 0000000..e834e78 --- /dev/null +++ b/apps/base/customer1/openclaw/pvc.yaml @@ -0,0 +1,12 @@ +apiVersion: v1 +kind: PersistentVolumeClaim +metadata: + name: openclaw-home-pvc + labels: + app: openclaw +spec: + accessModes: + - ReadWriteOnce + resources: + requests: + storage: 10Gi diff --git a/apps/base/customer1/openclaw/service.yaml b/apps/base/customer1/openclaw/service.yaml new file mode 100644 index 0000000..41df621 --- /dev/null +++ b/apps/base/customer1/openclaw/service.yaml @@ -0,0 +1,15 @@ +apiVersion: v1 +kind: Service +metadata: + name: openclaw + labels: + app: openclaw +spec: + type: ClusterIP + selector: + app: openclaw + ports: + - name: gateway + port: 18789 + targetPort: 18789 + protocol: TCP diff --git a/modules/pro6000-nodepool.tf b/modules/pro6000-nodepool.tf new file mode 100644 index 0000000..077ab44 --- /dev/null +++ b/modules/pro6000-nodepool.tf @@ -0,0 +1,55 @@ +resource "google_container_node_pool" "pro6000_pool" { + name = "pro600-pool" + location = "us-central1-a" + cluster = google_container_cluster.primary.name + + node_locations = [ + "us-central1-b" , + "us-central1-f" + ] + + initial_node_count = 0 + autoscaling { + min_node_count = 0 + max_node_count = 1 + } + + node_config { + # pro6000 gpu requires a g4-standard-48 machine type + machine_type = "g4-standard-48" + + guest_accelerator { + type = "nvidia-rtx-pro-6000" + count = 1 + + gpu_driver_installation_config { + gpu_driver_version = "LATEST" + } + } + + # SPOT is the modern equivalent of Preemptible + spot = false + + # Specific labels to help the Autoscaler find this pool + labels = { + "accelerator" = "pro6000-gpu" + } + + # Taint to keep other pods off this expensive node + taint { + key = "nvidia.com/gpu-nvidia-rtx-pro-6000" + value = "present" + effect = "NO_SCHEDULE" + } + + disk_size_gb = 100 + disk_type = "hyperdisk-balanced" + + oauth_scopes = ["https://www.googleapis.com/auth/cloud-platform"] + } + + management { + auto_repair = true + auto_upgrade = true + } +}