beecommerce gitops workflow
npx skills add https://github.com/gacabartosz/agent-skills --skill 'BeeCommerce GitOps Workflow'
Skill 文档
BeeCommerce GitOps Workflow
Autor: Bartosz Gaca | BeeCommerce Serwer K8s: kube.beecommerce.pl Harbor: harbor.kube.beecommerce.pl GitOps repo: github.com/gacabartosz/gitops-manifests Wersja: 1.0.0
â ï¸ ZASADA NADRZÄDNA
Nikt nie dotyka klastra rÄcznie. Co jest w main branch = co jest na K8s. Każda zmiana przez Pull Request.
ArgoCD z selfHeal: true automatycznie cofa każdÄ
rÄcznÄ
zmianÄ do stanu z Git.
ðï¸ Architektura
Developer â git push â GitHub â Jenkins CI â Harbor Registry
â
gitops-manifests repo
â
ArgoCD (auto-deploy)
â
Kubernetes (OVH)
Trzy typy repozytoriów
| Typ | Repo | ZawartoÅÄ |
|---|---|---|
| Template | beecommerce/project-template |
Dockerfile, Jenkinsfile, Helm values szablon |
| App repos | beecommerce/{app-name} |
Kod aplikacji + CI |
| GitOps manifests | beecommerce/gitops-manifests |
Helm values per projekt, Sealed Secrets |
ð OPERACJA: Nowy projekt
Krok 1: Utwórz repo z template
gh repo create gacabartosz/nowy-projekt \
--template gacabartosz/project-template \
--private --clone
cd nowy-projekt
Krok 2: Dodaj do gitops-manifests
git clone git@github.com:gacabartosz/gitops-manifests.git
cd gitops-manifests
cp -r apps/_template apps/nowy-projekt
Edytuj apps/nowy-projekt/values.yaml:
name: nowy-projekt
replicaCount: 1
image:
repository: harbor.kube.beecommerce.pl/library/nowy-projekt
tag: latest
imagePullPolicy: Always
service:
enabled: true
port: 80
targetPort: 3000
ingress:
enabled: true
annotations:
cert-manager.io/cluster-issuer: cluster-issuer-letsencrypt
hosts:
- host: nowy-projekt.ai.beecommerce.pl
paths: [/]
tls:
- secretName: nowy-projekt-tls
hosts: [nowy-projekt.ai.beecommerce.pl]
autoscaling:
enabled: false
Krok 3: Commit i push
git add apps/nowy-projekt/
git commit -m "feat: add nowy-projekt to gitops"
git push
ArgoCD automatycznie wykryje nowy projekt (App-of-Apps pattern) i wdroży go.
ð OPERACJA: Deploy na produkcjÄ
Normalny flow (automatyczny):
- Developer pushuje do
mainw app repo - Jenkins CI automatycznie buduje i pushuje obraz do Harbor
- Jenkins aktualizuje
tagwgitops-manifests/apps/{app}/values.yaml - ArgoCD wykrywa zmianÄ â rolling update
Manualny trigger Jenkins:
# Przez GitHub Actions webhook lub bezpoÅrednio
curl -X POST https://jenkins.kube.beecommerce.pl/job/{app-name}/build \
--user "user:token"
Sprawdź status deploy:
# Status ArgoCD sync
kubectl -n argocd get app {app-name}
kubectl -n argocd describe app {app-name}
# Krótka forma (ArgoCD CLI)
argocd app get {app-name}
argocd app sync {app-name} # force sync jeÅli auto nie zadziaÅaÅo
ð OPERACJA: Dodaj Secret (Sealed Secrets)
Zasada
Nigdy nie commituj plaintext secrets! Używaj kubeseal do szyfrowania.
Workflow
# 1. Utwórz zwykÅy Secret (dry-run, nie aplikuj do klastra!)
kubectl create secret generic {app-name}-secrets \
--dry-run=client -o yaml \
--from-literal=API_KEY=twoja-wartosc \
--from-literal=DB_PASSWORD=haslo \
-n {namespace} \
> /tmp/secret.yaml
# 2. Zaszyfruj kluczem publicznym klastra
kubeseal --format yaml \
--controller-name=sealed-secrets \
--controller-namespace=kube-system \
< /tmp/secret.yaml \
> gitops-manifests/apps/{app-name}/sealed-secret.yaml
# 3. UsuÅ plaintext plik!
rm /tmp/secret.yaml
# 4. Commituj zaszyfrowany plik (bezpieczny do Git)
cd gitops-manifests
git add apps/{app-name}/sealed-secret.yaml
git commit -m "feat: add secrets for {app-name}"
git push
Weryfikacja
# Sprawdź czy Secret zostaŠodszyfrowany przez kontroler
kubectl get secret {app-name}-secrets -n {namespace}
kubectl get sealedsecret {app-name}-secrets -n {namespace}
ð OPERACJA: Debug deploy
KolejnoÅÄ sprawdzania
# 1. Stan aplikacji w ArgoCD
argocd app get {app-name}
# Szukaj: Health Status, Sync Status
# 2. Pod status
kubectl get pods -n {namespace} -l app={app-name}
kubectl describe pod {pod-name} -n {namespace}
# 3. Logi poda
kubectl logs -n {namespace} -l app={app-name} --tail=100
kubectl logs -n {namespace} {pod-name} --previous # jeÅli crashuje
# 4. Events w namespace
kubectl get events -n {namespace} --sort-by='.lastTimestamp' | tail -20
# 5. Ingress i certyfikat
kubectl get ingress -n {namespace}
kubectl describe ingress {app-name} -n {namespace}
kubectl get certificate -n {namespace}
# 6. Harbor - czy obraz istnieje?
# Sprawdź: https://harbor.kube.beecommerce.pl
NajczÄstsze problemy
| Problem | Przyczyna | RozwiÄ zanie |
|---|---|---|
ImagePullBackOff |
ZÅy tag lub brak dostÄpu do Harbor | Sprawdź credentials imagePullSecret |
CrashLoopBackOff |
BÅÄ d aplikacji przy starcie | kubectl logs --previous |
| ArgoCD OutOfSync | Konflikt miÄdzy Git a klastrem | argocd app sync --force |
| Cert-manager pending | DNS nie propaguje | Sprawdź kubectl describe certificate |
| 502 Bad Gateway | Pod nie odpowiada | Sprawdź healthcheck i port |
âï¸ OPERACJA: Skalowanie
# Przez Git (rekomendowane!)
# Edytuj: gitops-manifests/apps/{app-name}/values.yaml
replicaCount: 3 # zmieÅ liczbÄ
git commit -am "scale: {app-name} to 3 replicas"
git push
# ArgoCD automatycznie zastosuje zmianÄ
# Sprawdź
kubectl get pods -n {namespace} -l app={app-name}
ð Struktura gitops-manifests
gitops-manifests/
âââ apps/
â âââ _template/ # szablon dla nowych projektów
â â âââ values.yaml
â â âââ sealed-secret.yaml
â â âââ kustomization.yaml
â âââ karlik-crm/
â â âââ values.yaml
â â âââ sealed-secret.yaml
â âââ felu-generator/
â â âââ values.yaml
â â âââ sealed-secret.yaml
â âââ .../
âââ base/
â âââ helm-chart/ # Universal Helm Chart
âââ argocd/
â âââ app-of-apps.yaml # master Application
â âââ project.yaml
âââ README.md
ð§ Jenkinsfile (szablon)
pipeline {
agent any
environment {
REGISTRY = 'harbor.kube.beecommerce.pl'
PROJECT = 'library'
APP_NAME = env.JOB_BASE_NAME
TAG = "${env.GIT_COMMIT?.take(8) ?: 'latest'}"
}
stages {
stage('Build') {
steps {
sh 'docker build -t ${REGISTRY}/${PROJECT}/${APP_NAME}:${TAG} .'
}
}
stage('Push to Harbor') {
steps {
withCredentials([usernamePassword(
credentialsId: 'harbor-robot',
usernameVariable: 'USER',
passwordVariable: 'PASS'
)]) {
sh 'docker login ${REGISTRY} -u ${USER} -p ${PASS}'
sh 'docker push ${REGISTRY}/${PROJECT}/${APP_NAME}:${TAG}'
}
}
}
stage('Update GitOps Manifest') {
steps {
withCredentials([sshUserPrivateKey(
credentialsId: 'github-deploy-key',
keyFileVariable: 'SSH_KEY'
)]) {
sh '''
git clone git@github.com:gacabartosz/gitops-manifests.git /tmp/gitops
cd /tmp/gitops
sed -i "s|tag:.*|tag: ${TAG}|" apps/${APP_NAME}/values.yaml
git commit -am "deploy: ${APP_NAME}:${TAG}"
git push
'''
}
}
}
}
}
ð¯ ArgoCD App-of-Apps
# argocd/app-of-apps.yaml
apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
name: beecommerce-apps
namespace: argocd
spec:
project: default
source:
repoURL: git@github.com:gacabartosz/gitops-manifests.git
targetRevision: main
path: apps
directory:
recurse: true
destination:
server: https://kubernetes.default.svc
syncPolicy:
automated:
prune: true # usuwa zasoby nieistniejÄ
ce w repo
selfHeal: true # cofa rÄczne zmiany do stanu z Git
ð¡ï¸ Gwarancje niezmiennoÅci
| Mechanizm | DziaÅanie |
|---|---|
ArgoCD selfHeal |
Cofa każdÄ rÄcznÄ zmianÄ w klastrze do stanu z Git |
ArgoCD prune |
Usuwa zasoby które nie istniejÄ w repo |
Branch protection |
main wymaga PR + review |
Image tags = commit SHA |
Brak latest, każdy deploy jest unikalny |
Harbor immutable tags |
Nie można nadpisaÄ istniejÄ cego tagu |
Git audit trail |
PeÅna historia: kto, co, kiedy |
ð Quick Reference
# === STATUS ===
argocd app list # wszystkie aplikacje
argocd app get {app} # szczegóÅy aplikacji
kubectl get pods -n {ns} # pody
kubectl get ingress -n {ns} # ingress
# === SYNC ===
argocd app sync {app} # force sync
argocd app sync {app} --force # override conflicts
# === LOGI ===
kubectl logs -n {ns} -l app={app} -f # live logs
kubectl logs -n {ns} {pod} --previous # crash logi
# === SECRETS ===
kubeseal --fetch-cert > pub-cert.pem # pobierz klucz publiczny
kubectl get sealedsecrets -n {ns} # lista sealed secrets
# === HARBOR ===
docker login harbor.kube.beecommerce.pl # logowanie
docker push harbor.kube.beecommerce.pl/library/{app}:{tag}
# === CERTYFIKATY ===
kubectl get certificate -n {ns}
kubectl describe certificaterequest -n {ns}
ðºï¸ Plan wdrożenia (fazy)
| Faza | Co | Czas |
|---|---|---|
| 0 | ArgoCD + Sealed Secrets na K8s, Harbor credentials w Jenkins | 1 dzieÅ |
| 1 | Template repo, Jenkinsfile, Helm values.yaml | 1 dzieÅ |
| 2 | Pilot: migracja felu-generator (najprostszy) |
1 dzieÅ |
| 3 | gitops-manifests repo, ArgoCD App-of-Apps, sealed secrets | 1 dzieÅ |
| 4 | Migracja: karlik-crm, porownanie-ai, ralph | 2-3 dni |
| 5 | Claude Code Skills: new-project, deploy, add-secret, debug | 2 dni |
Zacznij od fazy 2 (pilot) – waliduje caÅy flow na jednym projekcie.
Opracowanie: Bartosz Gaca | BeeCommerce | kontakt@bartoszgaca.pl Wersja 1.0.0 | Luty 2026