docs: document CI/CD bootstrap, seed images, and troubleshooting
Build and Deploy Platform / build-and-deploy (push) Successful in 8m9s
Build and Deploy Platform / build-and-deploy (push) Successful in 8m9s
Add bootstrap checklist (seed-ci-images, Sealed Secrets, two-repo GitOps), Kaniko BASE_IMAGE/insecure-pull details, platform secret requirements, and updated gitops install order. Link RUNBOOK-CICD from README. Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -13,6 +13,8 @@ custom `wp-content` entrypoint).
|
||||
> 🇮🇷 Production deployment on the `abrban.com` k3s cluster — including all the
|
||||
> Iran-network workarounds — is documented step-by-step in **[RUNBOOK.fa.md](RUNBOOK.fa.md)** (Persian).
|
||||
|
||||
> 🔄 **CI/CD (Gitea Actions → Kaniko → Harbor → Argo CD):** see **[RUNBOOK-CICD.fa.md](RUNBOOK-CICD.fa.md)** (Persian) and **[gitops/README.md](gitops/README.md)** for bootstrap (`seed-ci-images`, Sealed Secrets, two-repo GitOps layout).
|
||||
|
||||
---
|
||||
|
||||
## Architecture Overview
|
||||
|
||||
+73
-2
@@ -32,6 +32,55 @@ flowchart TD
|
||||
|
||||
> **جلوگیری از حلقهٔ CI:** کامیتِ Pipeline به ریپوی جدا (`cloud-host-gitops`) میرود که هیچ Workflowای ندارد؛ بنابراین Build دوباره trigger نمیشود.
|
||||
|
||||
**زمان تقریبی یک Pipeline کامل:** ۱۵–۲۵ دقیقه (backend سنگینتر است؛ شامل دانلود npm، helm و kubectl داخل Dockerfile).
|
||||
|
||||
---
|
||||
|
||||
## Bootstrap — پیشنیازهای یکبار (کلاستر تازه)
|
||||
|
||||
قبل از اولین push به `main`، این موارد باید در کلاستر آماده باشند:
|
||||
|
||||
| # | کار | دستور / فایل |
|
||||
|---|-----|--------------|
|
||||
| 1 | Mirror k3s → Harbor | `./scripts/apply-k3s-registries.sh` |
|
||||
| 2 | Secretهای TLS و registry در nsهای `gitea`, `cloudhost-builds`, `argocd` | [`gitops/README.md`](gitops/README.md) گام ۴ |
|
||||
| 3 | پروکسی egress در `gitea` و `cloudhost-builds` | همان گام ۴ — برای npm/helm/kubectl داخل build و دانلود kubectl توسط Runner |
|
||||
| 4 | **Seed ایمیجهای CI** در Harbor `abrban/` | [`gitops/jobs/seed-ci-images.yaml`](gitops/jobs/seed-ci-images.yaml) |
|
||||
| 5 | Sealed Secrets controller | `helm upgrade --install sealed-secrets ... -f gitops/sealed-secrets/values.yaml` |
|
||||
| 6 | SealedSecretها از ریپوی gitops | `kubectl apply -f` روی `cloud-host-gitops/sealed-secrets/` |
|
||||
| 7 | Gitea Runner + Secret `CI_TOKEN` در ریپو | [`gitops/gitea/act-runner.yaml`](gitops/gitea/act-runner.yaml) |
|
||||
| 8 | ریپوی `cloud-host-gitops` + Argo Application | [`gitops/argocd/application-platform.yaml`](gitops/argocd/application-platform.yaml) |
|
||||
|
||||
### Seed ایمیجهای CI (الزامی)
|
||||
|
||||
kubelet و Kaniko نمیتوانند reliably از proxy-cache هاربر برای همهٔ ایمیجها استفاده کنند. این ایمیجها باید **یکبار** با skopeo در پروژهٔ `abrban/` کپی شوند:
|
||||
|
||||
| ایمیج در Harbor | منبع upstream | مصرف |
|
||||
|-----------------|---------------|------|
|
||||
| `abrban/act-runner:0.2.11` | docker.io/gitea/act_runner | Gitea Actions runner |
|
||||
| `abrban/alpine-git:2.43.0` | docker.io/alpine/git | initContainer کلون در Kaniko Job |
|
||||
| `abrban/node:24-alpine` | docker.io/library/node | **BASE_IMAGE** در Dockerfile (هر stage) |
|
||||
| `abrban/kaniko-executor:v1.27.6-debug` | gcr.io/kaniko-project/executor | Kaniko Job |
|
||||
|
||||
```bash
|
||||
# پیشنیاز: secret registry-egress-proxy و registry-pull-secret در ns cloudhost
|
||||
kubectl apply -f gitops/jobs/seed-ci-images.yaml
|
||||
kubectl -n cloudhost wait --for=condition=complete job/seed-ci-images --timeout=15m
|
||||
kubectl -n cloudhost logs job/seed-ci-images --tail=5
|
||||
# انتظار: SEED_OK
|
||||
```
|
||||
|
||||
بررسی:
|
||||
|
||||
```bash
|
||||
kubectl -n cloudhost run tags --rm -i --restart=Never \
|
||||
--image=registry.abrban.com/abrban/alpine:3 \
|
||||
--overrides='{"spec":{"imagePullSecrets":[{"name":"registry-pull-secret"}]}}' \
|
||||
-- sh -c 'H="harbor_registry_user:$(kubectl -n cloudhost get secret harbor-core -o jsonpath="{.data.REGISTRY_CREDENTIAL_PASSWORD}" | base64 -d)@harbor-registry.cloudhost.svc.cluster.local:5000"; for r in act-runner kaniko-executor alpine-git node; do wget -qO- "http://${H}/v2/abrban/${r}/tags/list"; echo; done'
|
||||
```
|
||||
|
||||
> بعد از bootstrap، Pipeline با push به `main` خودکار اجرا میشود؛ نیازی به `./scripts/trigger-platform-build.sh` برای جریان عادی نیست (فقط برای دیباگ دستی).
|
||||
|
||||
---
|
||||
|
||||
## ساختار Repository (دو ریپو)
|
||||
@@ -105,7 +154,21 @@ kubectl -n cloudhost-builds create secret docker-registry kaniko-harbor-auth \
|
||||
|
||||
نمونهٔ manifest: [`gitops/jobs/kaniko-harbor-auth.example.yaml`](gitops/jobs/kaniko-harbor-auth.example.yaml) — نسخهٔ واقعی بهصورت SealedSecret در ریپوی gitops است.
|
||||
|
||||
ورکفلو این Secret را در مسیر `/kaniko/.docker/config.json` هر دو Kaniko Job مانت میکند. چون push داخلی و بدون TLS است، فلگهای `--insecure --skip-tls-verify` لازماند — این ترافیک از کلاستر خارج نمیشود.
|
||||
ورکفلو این Secret را در مسیر `/kaniko/.docker/config.json` هر دو Kaniko Job مانت میکند. چون push/pull داخلی و بدون TLS است، این فلگها لازماند:
|
||||
|
||||
- `--insecure` / `--skip-tls-verify` — push
|
||||
- `--insecure-pull` / `--insecure-registry=${PUSH_REGISTRY}` — pull ایمیج پایه از `harbor-registry:5000`
|
||||
|
||||
ایمیج پایه (`node:24-alpine`) از endpoint داخلی کشیده میشود، نه از `registry.abrban.com`:
|
||||
|
||||
```yaml
|
||||
# در .gitea/workflows/build-deploy.yaml
|
||||
--build-arg=BASE_IMAGE=harbor-registry.cloudhost.svc.cluster.local:5000/abrban/node:24-alpine
|
||||
```
|
||||
|
||||
Dockerfileها از `ARG BASE_IMAGE=node:24-alpine` استفاده میکنند (build محلی بدون تغییر).
|
||||
|
||||
> **پروکسی egress** (`registry-egress-proxy` در ns `cloudhost-builds`) هنوز لازم است برای `npm ci` و دانلود helm/kubectl **داخل** مراحل RUN در Dockerfile — فقط pull ایمیج پایه از docker.io حذف شده است.
|
||||
|
||||
> **عارضهٔ جانبی push مستقیم به :5000** — Harbor DB از این ایمیجها بیخبر میماند؛ در UI هاربر دیده نمیشوند ولی pull بهدرستی کار میکند. برای دیدن تگها از registry API استفاده کنید (بخش عیبیابی).
|
||||
|
||||
@@ -186,6 +249,9 @@ git push origin main
|
||||
| `gitea-act-runner-token` | `gitea` | توکن ثبت Runner |
|
||||
| `kaniko-harbor-auth` | `cloudhost-builds` | dockerconfig کاربر `harbor_registry_user` |
|
||||
| `gitea-gitops-repo-creds` | `argocd` | repo credential ریپوی gitops (کاربر `ci`) |
|
||||
| `abrban-platform-secrets` | `cloudhost` | postgres-password، jwt-secret، jwt-refresh-secret، **cluster-kubeconfig-key** |
|
||||
|
||||
چارت Helm با `secrets.existingSecret: abrban-platform-secrets` در `platform/values-abrban.yaml` (ریپوی gitops) از Secret ازپیشساخته استفاده میکند — Argo CD با `helm template` نمیتواند Secret تصادفی بسازد (lookup خالی است و هر sync مقادیر JWT را عوض میکند).
|
||||
|
||||
### ساخت/بهروزرسانی یک SealedSecret
|
||||
|
||||
@@ -228,10 +294,15 @@ Secretهایی که هنوز دستیاند (خارج از چرخهٔ CI): `a
|
||||
|-------|-------|
|
||||
| Workflow اجرا نمیشود | `kubectl -n gitea logs deploy/gitea-act-runner` — ثبت Runner و لیبل `abrban-builder` |
|
||||
| Build fail — clone | معتبربودن Secret `CI_TOKEN` در تنظیمات ریپوی `cloud-host` |
|
||||
| Build fail — pull ایمیج پایه (403/timeout از docker.io) | Kaniko نباید مستقیم از docker.io بکشد؛ ایمیج `node:24-alpine` باید در Harbor پروژهٔ `abrban/` seed شده باشد (`gitops/jobs/seed-ci-images.yaml`) و Workflow `--build-arg=BASE_IMAGE=registry.abrban.com/abrban/node:24-alpine` را پاس میدهد |
|
||||
| Build fail — pull ایمیج پایه | `node:24-alpine` باید seed شده باشد؛ Workflow باید `BASE_IMAGE=harbor-registry.../abrban/node:24-alpine` + `--insecure-pull` داشته باشد؛ نه pull مستقیم از docker.io |
|
||||
| Build fail — UNAUTHORIZED روی registry.abrban.com | BASE_IMAGE نباید `registry.abrban.com/...` باشد — credential کانیکو فقط برای `harbor-registry:5000` است |
|
||||
| Build fail — HTTP response to HTTPS client | `--insecure-pull` و `--insecure-registry=harbor-registry.cloudhost.svc.cluster.local:5000` در Kaniko args |
|
||||
| Build fail — timeout npm/helm/kubectl | `registry-egress-proxy` در ns `cloudhost-builds` و سلامت پروکسی egress |
|
||||
| Build fail — push به Harbor | `kubectl -n cloudhost-builds get secret kaniko-harbor-auth`؛ پسورد باید با `REGISTRY_CREDENTIAL_PASSWORD` هاربر یکی باشد |
|
||||
| کامیت values push نمیشود | دسترسی write کاربر `ci` روی `cloud-host-gitops` |
|
||||
| Argo sync نمیکند | `kubectl -n argocd get app abrban-platform`؛ هر دو repo credential (`gitea-repo-creds` و `gitea-gitops-repo-creds`) |
|
||||
| Pod ایمیج را pull نمیکند | `registry-pull-secret` در ns `cloudhost` و mirror k3s (`scripts/apply-k3s-registries.sh`) |
|
||||
| دیدن تگهای موجود در registry | از داخل کلاستر: `wget -qO- "http://harbor_registry_user:<REG_PASS>@harbor-registry.cloudhost.svc.cluster.local:5000/v2/abrban/cloudhost-backend/tags/list"` |
|
||||
| Backend CrashLoop — CLUSTER_KUBECONFIG_KEY | Secret `abrban-platform-secrets` باید کلید `cluster-kubeconfig-key` داشته باشد و در values: `secrets.existingSecret: abrban-platform-secrets` |
|
||||
| Backend CrashLoop — DB auth | پسورد postgres در Secret با DB واقعی همخوان باشد (`ALTER USER ... WITH PASSWORD` در صورت rotate شدن Secret) |
|
||||
| SealedSecret باز نمیشود | `kubectl get sealedsecrets -A` (ستون SYNCED) و لاگ `kubectl -n kube-system logs deploy/sealed-secrets-controller` |
|
||||
|
||||
+17
-13
@@ -46,34 +46,38 @@ helm upgrade --install argocd argo/argo-cd -n argocd --create-namespace \
|
||||
helm upgrade --install gitea gitea-charts/gitea -n gitea --create-namespace \
|
||||
-f gitops/gitea/values.yaml --timeout 15m --wait
|
||||
|
||||
# 4. TLS + registry secrets در namespaceهای argocd/gitea/cloudhost-builds
|
||||
# 4. TLS + registry + egress secrets در namespaceهای argocd/gitea/cloudhost-builds
|
||||
for ns in argocd gitea cloudhost-builds; do
|
||||
kubectl -n cloudhost get secret abrban-wildcard-tls -o yaml | sed "s/namespace: cloudhost/namespace: ${ns}/" | kubectl apply -f -
|
||||
kubectl -n cloudhost get secret registry-pull-secret -o yaml | sed "s/namespace: cloudhost/namespace: ${ns}/" | kubectl apply -f -
|
||||
done
|
||||
|
||||
# پروکسی egress برای act-runner (دانلود kubectl) و Kaniko (pull ایمیج پایه از docker.io)
|
||||
for ns in gitea cloudhost-builds; do
|
||||
kubectl -n cloudhost get secret registry-egress-proxy -o yaml | sed "s/namespace: cloudhost/namespace: ${ns}/" | kubectl apply -f -
|
||||
done
|
||||
|
||||
# 5. git push سورس به Gitea (نه docker push)
|
||||
# 5. Seed ایمیجهای CI در Harbor abrban/ (یکبار — الزامی قبل از Pipeline)
|
||||
kubectl apply -f gitops/jobs/seed-ci-images.yaml
|
||||
kubectl -n cloudhost wait --for=condition=complete job/seed-ci-images --timeout=15m
|
||||
|
||||
# 6. Sealed Secrets controller
|
||||
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 --timeout 10m --wait
|
||||
|
||||
# 7. git push سورس به Gitea
|
||||
# git remote add gitea https://git.abrban.com/abrban/cloud-host.git
|
||||
# git push gitea main
|
||||
|
||||
# 6. اولین build در کلاستر (Kaniko → abrban/)
|
||||
./scripts/trigger-platform-build.sh
|
||||
|
||||
# 7. Deploy
|
||||
./scripts/gitops-deploy.sh
|
||||
# ریپوی GitOps: https://git.abrban.com/abrban/cloud-host-gitops (SealedSecretها + values)
|
||||
|
||||
# 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>'
|
||||
# توکن ثبت: SealedSecret در cloud-host-gitops/sealed-secrets/gitea-act-runner-token.yaml
|
||||
kubectl apply -f gitops/gitea/act-runner.yaml
|
||||
|
||||
# 9. Argo CD Application
|
||||
# 9. Argo CD Application (multi-source: chart از cloud-host، values از cloud-host-gitops)
|
||||
kubectl apply -f gitops/argocd/application-platform.yaml
|
||||
|
||||
# 10. اولین deploy: push به main → Gitea Actions → Argo CD sync (جریان عادی)
|
||||
# برای bootstrap دستی: TAG=... ./scripts/gitops-deploy.sh
|
||||
```
|
||||
|
||||
## CI/CD
|
||||
|
||||
@@ -1,4 +1,13 @@
|
||||
# Bootstrap: copy act_runner + kaniko into abrban/ (kubelet cannot use proxy-cache reliably)
|
||||
# Bootstrap: seed CI/build images into Harbor project abrban/
|
||||
#
|
||||
# kubelet and Kaniko cannot reliably use Harbor proxy-cache for all images.
|
||||
# Run once after Harbor is up and registry-egress-proxy exists in cloudhost:
|
||||
#
|
||||
# kubectl apply -f gitops/jobs/seed-ci-images.yaml
|
||||
# kubectl -n cloudhost wait --for=condition=complete job/seed-ci-images --timeout=15m
|
||||
#
|
||||
# Images copied (see RUNBOOK-CICD.fa.md):
|
||||
# abrban/act-runner, abrban/alpine-git, abrban/node, abrban/kaniko-executor
|
||||
apiVersion: batch/v1
|
||||
kind: Job
|
||||
metadata:
|
||||
@@ -25,6 +34,7 @@ spec:
|
||||
- |
|
||||
set -eux
|
||||
DEST="docker://harbor-registry.cloudhost.svc.cluster.local:5000/abrban"
|
||||
# Must match harbor-core → REGISTRY_CREDENTIAL_PASSWORD (default: harbor_registry_password)
|
||||
CREDS="harbor_registry_user:harbor_registry_password"
|
||||
skopeo copy --dest-tls-verify=false --dest-creds="${CREDS}" \
|
||||
docker://docker.io/gitea/act_runner:0.2.11 \
|
||||
|
||||
Reference in New Issue
Block a user