ci: split GitOps state into cloud-host-gitops repo, add Sealed Secrets, fix pipeline auth
Build and Deploy Platform / build-and-deploy (push) Failing after 20m1s

- Workflow now pushes image tags to the separate cloud-host-gitops repo
  (no more CI loop risk) and authenticates via CI_TOKEN secret
- Fix undefined ${REGISTRY} in Kaniko jobs, add concurrency group,
  targeted tag update, and mounted kaniko-harbor-auth docker config
- Argo CD Application is now multi-source (chart from cloud-host,
  values from cloud-host-gitops)
- Remove plaintext runner token and proxy credentials from manifests;
  secrets are now SealedSecrets in the gitops repo

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
keyhan
2026-07-02 14:10:46 +03:30
parent d4559920d1
commit 7e66d1edf3
10 changed files with 390 additions and 97 deletions
+10 -1
View File
@@ -52,6 +52,9 @@ for ns in argocd gitea cloudhost-builds; do
kubectl -n cloudhost get secret registry-pull-secret -o yaml | sed "s/namespace: cloudhost/namespace: ${ns}/" | kubectl apply -f -
done
# پروکسی egress برای act-runner (دانلود kubectl در initContainer)
kubectl -n cloudhost get secret registry-egress-proxy -o yaml | sed 's/namespace: cloudhost/namespace: gitea/' | kubectl apply -f -
# 5. git push سورس به Gitea (نه docker push)
# git remote add gitea https://git.abrban.com/abrban/cloud-host.git
# git push gitea main
@@ -63,6 +66,8 @@ done
./scripts/gitops-deploy.sh
# 8. Gitea Actions runner
# توکن ثبت: SealedSecret در ریپوی cloud-host-gitops (sealed-secrets/gitea-act-runner-token.yaml)
# یا دستی: kubectl -n gitea create secret generic gitea-act-runner-token --from-literal=token='<TOKEN>'
kubectl apply -f gitops/gitea/act-runner.yaml
# 9. Argo CD Application
@@ -73,4 +78,8 @@ kubectl apply -f gitops/argocd/application-platform.yaml
Gitea Actions: [.gitea/workflows/build-deploy.yaml](../.gitea/workflows/build-deploy.yaml)
Push به `main` → Kaniko (از Harbor proxy) → push به `abrban/` → ArgoCD sync.
Push به `main` → Kaniko → push به `abrban/` کامیت tag در ریپوی [cloud-host-gitops](https://git.abrban.com/abrban/cloud-host-gitops) → ArgoCD sync.
- مقادیر Production در ریپوی جدا `abrban/cloud-host-gitops` است (`platform/values-abrban.yaml`)؛ Application به‌صورت multi-source تعریف شده.
- Secretهای CI به‌صورت SealedSecret در همان ریپو هستند (کنترلر در `kube-system`، values در `gitops/sealed-secrets/values.yaml`).
- مستند کامل: [RUNBOOK-CICD.fa.md](../RUNBOOK-CICD.fa.md)
+13 -9
View File
@@ -1,19 +1,23 @@
# Source of truth for this file: cloud-host-gitops repo (argocd/application-platform.yaml).
# Kept here as a mirror for bootstrap convenience.
apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
name: abrban-platform
namespace: argocd
finalizers:
- resources-finalizer.argocd.argoproj.io
spec:
project: default
source:
repoURL: https://git.abrban.com/abrban/cloud-host.git
targetRevision: main
path: backend/helm/cloudhost-platform
helm:
valueFiles:
- ../../../gitops/platform/values-abrban.yaml
# Multi-source: chart lives in the app repo, values (GitOps state) live in cloud-host-gitops.
sources:
- repoURL: https://git.abrban.com/abrban/cloud-host.git
targetRevision: main
path: backend/helm/cloudhost-platform
helm:
valueFiles:
- $values/platform/values-abrban.yaml
- repoURL: https://git.abrban.com/abrban/cloud-host-gitops.git
targetRevision: main
ref: values
destination:
server: https://kubernetes.default.svc
namespace: cloudhost
+16 -9
View File
@@ -1,13 +1,17 @@
# Gitea Actions runner — host mode (no docker.sock; k3s uses containerd)
# Runner creates Kaniko Jobs in cloudhost-builds for image builds.
apiVersion: v1
kind: Secret
metadata:
name: gitea-act-runner-token
namespace: gitea
type: Opaque
stringData:
token: "nL63VkZEyqpCNFdF3AMM9wzQLdLlATUvXSe5Tj0R"
#
# Secrets (never commit real values):
#
# # Registration token: managed as SealedSecret in the cloud-host-gitops repo
# # (sealed-secrets/gitea-act-runner-token.yaml). To rotate manually:
# # token from Gitea UI → Site Administration → Actions → Runners, then:
# kubectl -n gitea create secret generic gitea-act-runner-token \
# --from-literal=token='<RUNNER_REGISTRATION_TOKEN>'
#
# # Egress proxy (copied from cloudhost namespace, needed by the kubectl download):
# kubectl -n cloudhost get secret registry-egress-proxy -o yaml \
# | sed 's/namespace: cloudhost/namespace: gitea/' | kubectl apply -f -
---
apiVersion: v1
kind: ServiceAccount
@@ -64,7 +68,10 @@ spec:
imagePullPolicy: IfNotPresent
env:
- name: HTTPS_PROXY
value: "http://builder:BeeldiOr!12009@45.129.38.203:9911"
valueFrom:
secretKeyRef:
name: registry-egress-proxy
key: HTTPS_PROXY
command:
- sh
- -c
@@ -0,0 +1,36 @@
# Example only — DO NOT commit real credentials.
# The real secret is managed as a SealedSecret in the cloud-host-gitops repo
# (sealed-secrets/kaniko-harbor-auth.yaml).
#
# Kaniko pushes directly to the internal registry endpoint
# (harbor-registry.cloudhost.svc.cluster.local:5000), which bypasses harbor-core.
# That endpoint only accepts the internal registry credential — Harbor robot
# accounts do NOT work there (their tokens are issued by harbor-core's token
# service). Use the harbor_registry_user credential from the harbor-core secret:
#
# REG_PASS="$(kubectl -n cloudhost get secret harbor-core \
# -o jsonpath='{.data.REGISTRY_CREDENTIAL_PASSWORD}' | base64 -d)"
# kubectl -n cloudhost-builds create secret docker-registry kaniko-harbor-auth \
# --docker-server=harbor-registry.cloudhost.svc.cluster.local:5000 \
# --docker-username=harbor_registry_user \
# --docker-password="${REG_PASS}"
#
# The build-deploy workflow mounts this secret at /kaniko/.docker/config.json
# inside every Kaniko Job. See RUNBOOK-CICD.fa.md for the full procedure.
apiVersion: v1
kind: Secret
metadata:
name: kaniko-harbor-auth
namespace: cloudhost-builds
type: kubernetes.io/dockerconfigjson
stringData:
.dockerconfigjson: |
{
"auths": {
"harbor-registry.cloudhost.svc.cluster.local:5000": {
"username": "harbor_registry_user",
"password": "<REGISTRY_CREDENTIAL_PASSWORD>",
"auth": "<base64 of username:password>"
}
}
}
-56
View File
@@ -1,56 +0,0 @@
# Production values for abrban.com — used by ArgoCD / Gitea Actions GitOps
namespace: cloudhost
createNamespace: false
global:
storageClass: local-path
images:
backend:
repository: registry.abrban.com/abrban/cloudhost-backend
tag: "1.0.0"
pullPolicy: Always
frontend:
repository: registry.abrban.com/abrban/cloudhost-frontend
tag: "1.0.0"
pullPolicy: Always
backend:
imagePullSecrets:
- name: registry-pull-secret
sourceStorage:
enabled: true
existingSecret: ceph-app-sources-credentials
env:
NODE_ENV: production
PORT: "4000"
PLATFORM_DOMAIN: apps.abrban.com
REGISTRY_URL: registry.abrban.com
REGISTRY_PULL_URL: registry.abrban.com
BUILD_NAMESPACE: cloudhost-builds
BUILD_SERVICE_ACCOUNT: kaniko-builder
UPLOAD_DIR: /app/uploads
PLATFORM_CREATE_STORAGE_CLASS: "false"
PLATFORM_STORAGE_CLASS: rook-ceph-block
PLATFORM_STORAGE_PROVISIONER: rook-ceph.rbd.csi.ceph.com
ELASTICSEARCH_HOST: elasticsearch.logging.svc.cluster.local
ELASTICSEARCH_AUTO_PORT_FORWARD: "false"
frontend:
imagePullSecrets:
- name: registry-pull-secret
ingress:
enabled: true
className: traefik
annotations:
traefik.ingress.kubernetes.io/router.entrypoints: websecure
frontend:
host: abrban.com
panel:
host: panel.abrban.com
api:
host: api.abrban.com
tls:
enabled: true
secretName: abrban-wildcard-tls
+15
View File
@@ -0,0 +1,15 @@
# Sealed Secrets controller — encrypts secrets so they can live in Git.
# Install:
# helm repo add sealed-secrets https://bitnami.github.io/sealed-secrets
# helm upgrade --install sealed-secrets sealed-secrets/sealed-secrets \
# -n kube-system -f gitops/sealed-secrets/values.yaml
#
# fullnameOverride matches the default the kubeseal CLI expects
# (sealed-secrets-controller in kube-system), so kubeseal works without flags.
fullnameOverride: sealed-secrets-controller
image:
# Seeded into Harbor abrban/ project from ghcr.io/bitnami (proxy-ghcr returned 401
# for kubelet pulls; see seed job pattern in gitops/jobs/seed-ci-images.yaml).
registry: registry.abrban.com
repository: abrban/sealed-secrets-controller