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