Initial OpenClaw GitOps skeleton
This commit is contained in:
17
README.md
Normal file
17
README.md
Normal file
@@ -0,0 +1,17 @@
|
|||||||
|
# openclaw (OpenShift)
|
||||||
|
|
||||||
|
GitOps repo for deploying **OpenClaw** into the `openclaw` namespace.
|
||||||
|
|
||||||
|
Layout:
|
||||||
|
- `bootstrap/` – ArgoCD `Application` (apply manually once)
|
||||||
|
- `manifests/` – Namespace + workload resources (ArgoCD-managed)
|
||||||
|
|
||||||
|
Target:
|
||||||
|
- Namespace: `openclaw`
|
||||||
|
- Route host: `openclaw.apps.lab.apilab.us`
|
||||||
|
- Image: `default-route-openshift-image-registry.apps.lab.apilab.us/openclaw/openclaw:latest`
|
||||||
|
- Gateway port: `18789`
|
||||||
|
|
||||||
|
Notes:
|
||||||
|
- This repo intentionally does **not** deploy TEI; it assumes the existing service:
|
||||||
|
`http://text-embeddings.tei.svc.cluster.local:8080/v1/`
|
||||||
21
bootstrap/argocd-application.yaml
Normal file
21
bootstrap/argocd-application.yaml
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
apiVersion: argoproj.io/v1alpha1
|
||||||
|
kind: Application
|
||||||
|
metadata:
|
||||||
|
name: openclaw
|
||||||
|
namespace: openshift-gitops
|
||||||
|
spec:
|
||||||
|
project: default
|
||||||
|
source:
|
||||||
|
repoURL: https://gitea.apilab.us/cscott/openclaw.git
|
||||||
|
targetRevision: main
|
||||||
|
path: manifests
|
||||||
|
destination:
|
||||||
|
server: https://kubernetes.default.svc
|
||||||
|
namespace: openclaw
|
||||||
|
syncPolicy:
|
||||||
|
automated:
|
||||||
|
prune: true
|
||||||
|
selfHeal: true
|
||||||
|
syncOptions:
|
||||||
|
- CreateNamespace=true
|
||||||
|
- ApplyOutOfSyncOnly=true
|
||||||
26
manifests/config-secret.yaml
Normal file
26
manifests/config-secret.yaml
Normal file
@@ -0,0 +1,26 @@
|
|||||||
|
apiVersion: v1
|
||||||
|
kind: Secret
|
||||||
|
metadata:
|
||||||
|
name: openclaw-config
|
||||||
|
namespace: openclaw
|
||||||
|
type: Opaque
|
||||||
|
stringData:
|
||||||
|
# IMPORTANT: Fill this in with the OpenClaw gateway config JSON (or whatever the new format is).
|
||||||
|
# This is a placeholder so Argo has a resource to manage.
|
||||||
|
openclaw.json: |
|
||||||
|
{
|
||||||
|
"agents": {
|
||||||
|
"defaults": {
|
||||||
|
"memorySearch": {
|
||||||
|
"enabled": true,
|
||||||
|
"provider": "openai",
|
||||||
|
"model": "BAAI/bge-base-en-v1.5",
|
||||||
|
"remote": {
|
||||||
|
"baseUrl": "http://text-embeddings.tei.svc.cluster.local:8080/v1/",
|
||||||
|
"apiKey": "not-needed",
|
||||||
|
"batch": {"enabled": false}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
51
manifests/deployment.yaml
Normal file
51
manifests/deployment.yaml
Normal file
@@ -0,0 +1,51 @@
|
|||||||
|
apiVersion: apps/v1
|
||||||
|
kind: Deployment
|
||||||
|
metadata:
|
||||||
|
name: openclaw
|
||||||
|
namespace: openclaw
|
||||||
|
labels:
|
||||||
|
app.kubernetes.io/name: openclaw
|
||||||
|
spec:
|
||||||
|
replicas: 1
|
||||||
|
selector:
|
||||||
|
matchLabels:
|
||||||
|
app.kubernetes.io/name: openclaw
|
||||||
|
template:
|
||||||
|
metadata:
|
||||||
|
labels:
|
||||||
|
app.kubernetes.io/name: openclaw
|
||||||
|
spec:
|
||||||
|
serviceAccountName: openclaw
|
||||||
|
containers:
|
||||||
|
- name: openclaw
|
||||||
|
image: default-route-openshift-image-registry.apps.lab.apilab.us/openclaw/openclaw:latest
|
||||||
|
imagePullPolicy: Always
|
||||||
|
ports:
|
||||||
|
- name: http
|
||||||
|
containerPort: 18789
|
||||||
|
env:
|
||||||
|
# Keep caches out of $HOME under restricted SCC
|
||||||
|
- name: NPM_CONFIG_CACHE
|
||||||
|
value: /tmp/npm-cache
|
||||||
|
- name: XDG_CACHE_HOME
|
||||||
|
value: /tmp
|
||||||
|
# If OpenClaw uses HOME for state, keep it in the PVC-backed /home/clawd
|
||||||
|
- name: HOME
|
||||||
|
value: /home/clawd
|
||||||
|
volumeMounts:
|
||||||
|
- name: config
|
||||||
|
mountPath: /home/clawd/.openclaw
|
||||||
|
- name: tmp
|
||||||
|
mountPath: /tmp
|
||||||
|
- name: config-secret
|
||||||
|
mountPath: /clawd-init
|
||||||
|
readOnly: true
|
||||||
|
volumes:
|
||||||
|
- name: config
|
||||||
|
persistentVolumeClaim:
|
||||||
|
claimName: openclaw-config
|
||||||
|
- name: tmp
|
||||||
|
emptyDir: {}
|
||||||
|
- name: config-secret
|
||||||
|
secret:
|
||||||
|
secretName: openclaw-config
|
||||||
9
manifests/maintenance/README.md
Normal file
9
manifests/maintenance/README.md
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
Maintenance notes
|
||||||
|
|
||||||
|
We intentionally avoid assumptions about UID/GID/FSGroup under OpenShift restricted SCC.
|
||||||
|
|
||||||
|
If PVC permissions ever wedge, prefer:
|
||||||
|
- designing the container entrypoint to `umask 0002` and create needed dirs/files with group-writable perms, OR
|
||||||
|
- use an initContainer that only does `chmod -R g+rwX` (no chown) if your cluster policy allows.
|
||||||
|
|
||||||
|
Avoid hardcoding specific numeric UIDs/GIDs.
|
||||||
33
manifests/maintenance/fix-openclaw-pvc-perms-job.yaml
Normal file
33
manifests/maintenance/fix-openclaw-pvc-perms-job.yaml
Normal file
@@ -0,0 +1,33 @@
|
|||||||
|
apiVersion: batch/v1
|
||||||
|
kind: Job
|
||||||
|
metadata:
|
||||||
|
name: openclaw-fix-pvc-perms
|
||||||
|
namespace: openclaw
|
||||||
|
spec:
|
||||||
|
template:
|
||||||
|
spec:
|
||||||
|
restartPolicy: Never
|
||||||
|
serviceAccountName: openclaw
|
||||||
|
containers:
|
||||||
|
- name: fix
|
||||||
|
image: registry.access.redhat.com/ubi9/ubi-minimal:9.5
|
||||||
|
command:
|
||||||
|
- /bin/sh
|
||||||
|
- -lc
|
||||||
|
- |
|
||||||
|
set -eu
|
||||||
|
echo "Fixing group permissions under /data (PVC)"
|
||||||
|
echo "NOTE: This job intentionally avoids chown or any hardcoded UID/GID assumptions."
|
||||||
|
|
||||||
|
chmod -R g+rwX /data
|
||||||
|
find /data -type d -exec chmod 2775 {} \;
|
||||||
|
|
||||||
|
echo "Done"
|
||||||
|
ls -la /data | head -n 100 || true
|
||||||
|
volumeMounts:
|
||||||
|
- name: config
|
||||||
|
mountPath: /data
|
||||||
|
volumes:
|
||||||
|
- name: config
|
||||||
|
persistentVolumeClaim:
|
||||||
|
claimName: openclaw-config
|
||||||
9
manifests/namespace.yaml
Normal file
9
manifests/namespace.yaml
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
apiVersion: v1
|
||||||
|
kind: Namespace
|
||||||
|
metadata:
|
||||||
|
name: openclaw
|
||||||
|
labels:
|
||||||
|
app.kubernetes.io/name: openclaw
|
||||||
|
app.kubernetes.io/part-of: openclaw
|
||||||
|
# Uncomment if you want autonomous ephemeral diagnostics allowed here
|
||||||
|
# mcp.demo/ephemeral: "true"
|
||||||
12
manifests/pvc.yaml
Normal file
12
manifests/pvc.yaml
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
apiVersion: v1
|
||||||
|
kind: PersistentVolumeClaim
|
||||||
|
metadata:
|
||||||
|
name: openclaw-config
|
||||||
|
namespace: openclaw
|
||||||
|
spec:
|
||||||
|
accessModes:
|
||||||
|
- ReadWriteOnce
|
||||||
|
resources:
|
||||||
|
requests:
|
||||||
|
storage: 2Gi
|
||||||
|
# storageClassName: <set if you want to pin it>
|
||||||
17
manifests/route.yaml
Normal file
17
manifests/route.yaml
Normal file
@@ -0,0 +1,17 @@
|
|||||||
|
apiVersion: route.openshift.io/v1
|
||||||
|
kind: Route
|
||||||
|
metadata:
|
||||||
|
name: openclaw
|
||||||
|
namespace: openclaw
|
||||||
|
spec:
|
||||||
|
host: openclaw.apps.lab.apilab.us
|
||||||
|
to:
|
||||||
|
kind: Service
|
||||||
|
name: openclaw
|
||||||
|
weight: 100
|
||||||
|
port:
|
||||||
|
targetPort: http
|
||||||
|
tls:
|
||||||
|
termination: edge
|
||||||
|
insecureEdgeTerminationPolicy: Redirect
|
||||||
|
wildcardPolicy: None
|
||||||
12
manifests/service.yaml
Normal file
12
manifests/service.yaml
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
apiVersion: v1
|
||||||
|
kind: Service
|
||||||
|
metadata:
|
||||||
|
name: openclaw
|
||||||
|
namespace: openclaw
|
||||||
|
spec:
|
||||||
|
selector:
|
||||||
|
app.kubernetes.io/name: openclaw
|
||||||
|
ports:
|
||||||
|
- name: http
|
||||||
|
port: 80
|
||||||
|
targetPort: 18789
|
||||||
30
manifests/serviceaccount-rbac.yaml
Normal file
30
manifests/serviceaccount-rbac.yaml
Normal file
@@ -0,0 +1,30 @@
|
|||||||
|
apiVersion: v1
|
||||||
|
kind: ServiceAccount
|
||||||
|
metadata:
|
||||||
|
name: openclaw
|
||||||
|
namespace: openclaw
|
||||||
|
---
|
||||||
|
# Minimal Role/RoleBinding placeholder.
|
||||||
|
# Adjust permissions once we know what OpenClaw needs (MCP, secrets read, etc.)
|
||||||
|
apiVersion: rbac.authorization.k8s.io/v1
|
||||||
|
kind: Role
|
||||||
|
metadata:
|
||||||
|
name: openclaw-basic
|
||||||
|
namespace: openclaw
|
||||||
|
rules:
|
||||||
|
- apiGroups: [""]
|
||||||
|
resources: ["pods", "pods/log"]
|
||||||
|
verbs: ["get", "list", "watch"]
|
||||||
|
---
|
||||||
|
apiVersion: rbac.authorization.k8s.io/v1
|
||||||
|
kind: RoleBinding
|
||||||
|
metadata:
|
||||||
|
name: openclaw-basic
|
||||||
|
namespace: openclaw
|
||||||
|
subjects:
|
||||||
|
- kind: ServiceAccount
|
||||||
|
name: openclaw
|
||||||
|
roleRef:
|
||||||
|
apiGroup: rbac.authorization.k8s.io
|
||||||
|
kind: Role
|
||||||
|
name: openclaw-basic
|
||||||
Reference in New Issue
Block a user