Add Harbor/Ceph runbooks and align single-node Ceph docs with abr deployment.

Document registry ingress split, image mirroring, loop OSD setup, and platform integration paths.
This commit is contained in:
keyhan
2026-07-01 00:22:06 +03:30
parent 8d1855b89c
commit ee5bd0a291
21 changed files with 2124 additions and 2 deletions
@@ -0,0 +1,23 @@
CloudHost Ceph storage is ready (or still initializing).
Profiles
single-node Directory OSD on /var/lib/rook/osd — for one-node k3s (no HA)
multi-node Raw disk OSDs with replication=3 — production
StorageClasses created by Rook
rook-ceph-block Block volumes (app PVC, DB, registry, …)
rook-ceph-bucket S3-compatible buckets via ObjectBucketClaim
Verify cluster health
kubectl -n rook-ceph exec deploy/rook-ceph-tools -- ceph status
kubectl get storageclass | grep rook-ceph
kubectl -n cloudhost-builds get obc,secret | grep -E 'app-sources|ceph-app-sources'
Platform backend (after bucket sync Job completes)
PLATFORM_STORAGE_CLASS=rook-ceph-block
PLATFORM_CREATE_STORAGE_CLASS=false
PLATFORM_STORAGE_PROVISIONER=rook-ceph.rbd.csi.ceph.com
Mount secret cloudhost-builds/ceph-app-sources-credentials for zip upload S3 settings.
Full guide: backend/helm/cloudhost-ceph/README.md and RUNBOOK-CEPH.fa.md
@@ -0,0 +1,27 @@
{{/*
CloudHost Ceph chart helpers
*/}}
{{- define "cloudhost-ceph.name" -}}
{{- default .Chart.Name .Values.nameOverride | trunc 63 | trimSuffix "-" }}
{{- end }}
{{- define "cloudhost-ceph.fullname" -}}
{{- if .Values.fullnameOverride }}
{{- .Values.fullnameOverride | trunc 63 | trimSuffix "-" }}
{{- else }}
{{- $name := default .Chart.Name .Values.nameOverride }}
{{- if contains $name .Release.Name }}
{{- .Release.Name | trunc 63 | trimSuffix "-" }}
{{- else }}
{{- printf "%s-%s" .Release.Name $name | trunc 63 | trimSuffix "-" }}
{{- end }}
{{- end }}
{{- end }}
{{- define "cloudhost-ceph.labels" -}}
helm.sh/chart: {{ include "cloudhost-ceph.name" . }}-{{ .Chart.Version }}
app.kubernetes.io/name: {{ include "cloudhost-ceph.name" . }}
app.kubernetes.io/instance: {{ .Release.Name }}
app.kubernetes.io/managed-by: {{ .Release.Service }}
app.kubernetes.io/part-of: cloudhost
{{- end }}
@@ -0,0 +1,20 @@
{{- if .Values.integration.createConfigMap }}
apiVersion: v1
kind: ConfigMap
metadata:
name: {{ .Values.integration.configMapName }}
namespace: {{ .Values.namespace }}
labels:
{{- include "cloudhost-ceph.labels" . | nindent 4 }}
data:
PLATFORM_STORAGE_CLASS: rook-ceph-block
PLATFORM_CREATE_STORAGE_CLASS: "false"
PLATFORM_STORAGE_PROVISIONER: rook-ceph.rbd.csi.ceph.com
SOURCE_STORAGE_ENDPOINT: {{ .Values.platform.endpoint | quote }}
SOURCE_STORAGE_REGION: {{ .Values.platform.region | quote }}
SOURCE_STORAGE_CREDENTIALS_SECRET: {{ .Values.platform.credentialsSecretName | quote }}
README: |
Block PVCs: set PLATFORM_STORAGE_CLASS=rook-ceph-block on the backend.
New app PVCs use rook-ceph-block; existing local-path PVCs are NOT auto-migrated.
Object storage credentials: secret {{ .Values.platform.credentialsSecretName }} in {{ .Values.namespace }}.
{{- end }}
@@ -0,0 +1,15 @@
{{- if .Values.objectStore.claimName }}
apiVersion: objectbucket.io/v1alpha1
kind: ObjectBucketClaim
metadata:
name: {{ .Values.objectStore.claimName }}
namespace: {{ .Values.namespace }}
labels:
{{- include "cloudhost-ceph.labels" . | nindent 4 }}
annotations:
helm.sh/hook: post-install,post-upgrade
helm.sh/hook-weight: "5"
spec:
storageClassName: {{ .Values.objectStore.bucketStorageClass | quote }}
generateBucketName: {{ .Values.objectStore.generateBucketName | quote }}
{{- end }}
@@ -0,0 +1,113 @@
{{- if and .Values.platform.createCredentialsSecret .Values.objectStore.claimName }}
# Stable secret name for platform workers. Populated by a post-install Job once the OBC secret exists.
apiVersion: v1
kind: ServiceAccount
metadata:
name: {{ include "cloudhost-ceph.fullname" . }}-bucket-sync
namespace: {{ .Values.namespace }}
labels:
{{- include "cloudhost-ceph.labels" . | nindent 4 }}
annotations:
helm.sh/hook: post-install,post-upgrade
helm.sh/hook-weight: "1"
helm.sh/hook-delete-policy: before-hook-creation
---
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
name: {{ include "cloudhost-ceph.fullname" . }}-bucket-sync
namespace: {{ .Values.namespace }}
annotations:
helm.sh/hook: post-install,post-upgrade
helm.sh/hook-weight: "1"
helm.sh/hook-delete-policy: before-hook-creation
rules:
- apiGroups: [""]
resources: ["secrets"]
verbs: ["get", "list", "create", "patch", "update"]
---
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
name: {{ include "cloudhost-ceph.fullname" . }}-bucket-sync
namespace: {{ .Values.namespace }}
annotations:
helm.sh/hook: post-install,post-upgrade
helm.sh/hook-weight: "1"
helm.sh/hook-delete-policy: before-hook-creation
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: Role
name: {{ include "cloudhost-ceph.fullname" . }}-bucket-sync
subjects:
- kind: ServiceAccount
name: {{ include "cloudhost-ceph.fullname" . }}-bucket-sync
namespace: {{ .Values.namespace }}
---
apiVersion: batch/v1
kind: Job
metadata:
name: {{ include "cloudhost-ceph.fullname" . }}-bucket-sync
namespace: {{ .Values.namespace }}
labels:
{{- include "cloudhost-ceph.labels" . | nindent 4 }}
annotations:
helm.sh/hook: post-install,post-upgrade
helm.sh/hook-weight: "10"
helm.sh/hook-delete-policy: before-hook-creation
spec:
backoffLimit: 30
template:
spec:
serviceAccountName: {{ include "cloudhost-ceph.fullname" . }}-bucket-sync
restartPolicy: OnFailure
containers:
- name: sync
image: registry.abrban.com/proxy-dockerhub/bitnami/kubectl:1.32
imagePullPolicy: IfNotPresent
env:
- name: OBC_SECRET
value: {{ printf "obc-%s-%s" .Values.namespace .Values.objectStore.claimName | quote }}
- name: TARGET_SECRET
value: {{ .Values.platform.credentialsSecretName | quote }}
- name: NAMESPACE
value: {{ .Values.namespace | quote }}
- name: ENDPOINT
value: {{ .Values.platform.endpoint | quote }}
- name: REGION
value: {{ .Values.platform.region | quote }}
command:
- /bin/bash
- -ec
- |
echo "Waiting for OBC secret ${OBC_SECRET} in ${NAMESPACE}..."
for i in $(seq 1 120); do
if kubectl get secret -n "${NAMESPACE}" "${OBC_SECRET}" >/dev/null 2>&1; then
break
fi
sleep 10
done
kubectl get secret -n "${NAMESPACE}" "${OBC_SECRET}" >/dev/null
BUCKET=$(kubectl get secret -n "${NAMESPACE}" "${OBC_SECRET}" -o jsonpath='{.data.BUCKET_NAME}' | base64 -d)
ACCESS=$(kubectl get secret -n "${NAMESPACE}" "${OBC_SECRET}" -o jsonpath='{.data.AWS_ACCESS_KEY_ID}' | base64 -d)
SECRET=$(kubectl get secret -n "${NAMESPACE}" "${OBC_SECRET}" -o jsonpath='{.data.AWS_SECRET_ACCESS_KEY}' | base64 -d)
cat <<EOF | kubectl apply -f -
apiVersion: v1
kind: Secret
metadata:
name: ${TARGET_SECRET}
namespace: ${NAMESPACE}
labels:
app.kubernetes.io/part-of: cloudhost
type: Opaque
stringData:
SOURCE_STORAGE_ENDPOINT: "${ENDPOINT}"
SOURCE_STORAGE_REGION: "${REGION}"
SOURCE_STORAGE_BUCKET: "${BUCKET}"
SOURCE_STORAGE_ACCESS_KEY: "${ACCESS}"
SOURCE_STORAGE_SECRET_KEY: "${SECRET}"
EOF
echo "Synced bucket credentials to secret ${TARGET_SECRET} (bucket=${BUCKET})"
{{- end }}