Compare commits
6 Commits
feature/ho
...
a471f11740
| Author | SHA1 | Date | |
|---|---|---|---|
| a471f11740 | |||
| 333acdea26 | |||
| 458f7b23ad | |||
| 41c8b85bf8 | |||
| 4e6a84785a | |||
| e0bdaab422 |
@@ -34,6 +34,7 @@ jobs:
|
||||
with:
|
||||
submodules: true
|
||||
fetch-depth: 0
|
||||
token: ${{ secrets.AI_REVIEW_TOKEN }}
|
||||
|
||||
- name: Run inline review
|
||||
uses: docker://nikitafilonov/ai-review:v0.64.0
|
||||
|
||||
32
_app-of-apps-aks-dev.yaml
Normal file
32
_app-of-apps-aks-dev.yaml
Normal file
@@ -0,0 +1,32 @@
|
||||
apiVersion: v1
|
||||
kind: Namespace
|
||||
metadata:
|
||||
name: monitoring
|
||||
annotations:
|
||||
argocd.argoproj.io/sync-wave: "-1"
|
||||
---
|
||||
apiVersion: argoproj.io/v1alpha1
|
||||
kind: Application
|
||||
metadata:
|
||||
name: infrastructure-apps
|
||||
namespace: argocd
|
||||
labels:
|
||||
app.kubernetes.io/name: infrastructure-apps
|
||||
app.kubernetes.io/part-of: platform
|
||||
finalizers:
|
||||
- resources-finalizer.argocd.argoproj.io
|
||||
spec:
|
||||
project: default
|
||||
source:
|
||||
repoURL: ssh://git@git.forteapps.net:2222/Forte/launchpad.git
|
||||
targetRevision: HEAD
|
||||
path: infra/overlays/aks-dev
|
||||
destination:
|
||||
server: https://kubernetes.default.svc
|
||||
namespace: default
|
||||
syncPolicy:
|
||||
automated:
|
||||
prune: true
|
||||
selfHeal: true
|
||||
syncOptions:
|
||||
- CreateNamespace=true
|
||||
32
_app-of-apps-aks-prod.yaml
Normal file
32
_app-of-apps-aks-prod.yaml
Normal file
@@ -0,0 +1,32 @@
|
||||
apiVersion: v1
|
||||
kind: Namespace
|
||||
metadata:
|
||||
name: monitoring
|
||||
annotations:
|
||||
argocd.argoproj.io/sync-wave: "-1"
|
||||
---
|
||||
apiVersion: argoproj.io/v1alpha1
|
||||
kind: Application
|
||||
metadata:
|
||||
name: infrastructure-apps
|
||||
namespace: argocd
|
||||
labels:
|
||||
app.kubernetes.io/name: infrastructure-apps
|
||||
app.kubernetes.io/part-of: platform
|
||||
finalizers:
|
||||
- resources-finalizer.argocd.argoproj.io
|
||||
spec:
|
||||
project: default
|
||||
source:
|
||||
repoURL: ssh://git@git.forteapps.net:2222/Forte/launchpad.git
|
||||
targetRevision: HEAD
|
||||
path: infra/overlays/aks-prod
|
||||
destination:
|
||||
server: https://kubernetes.default.svc
|
||||
namespace: default
|
||||
syncPolicy:
|
||||
automated:
|
||||
prune: true
|
||||
selfHeal: true
|
||||
syncOptions:
|
||||
- CreateNamespace=true
|
||||
32
_app-of-apps-eks-dev.yaml
Normal file
32
_app-of-apps-eks-dev.yaml
Normal file
@@ -0,0 +1,32 @@
|
||||
apiVersion: v1
|
||||
kind: Namespace
|
||||
metadata:
|
||||
name: monitoring
|
||||
annotations:
|
||||
argocd.argoproj.io/sync-wave: "-1"
|
||||
---
|
||||
apiVersion: argoproj.io/v1alpha1
|
||||
kind: Application
|
||||
metadata:
|
||||
name: infrastructure-apps
|
||||
namespace: argocd
|
||||
labels:
|
||||
app.kubernetes.io/name: infrastructure-apps
|
||||
app.kubernetes.io/part-of: platform
|
||||
finalizers:
|
||||
- resources-finalizer.argocd.argoproj.io
|
||||
spec:
|
||||
project: default
|
||||
source:
|
||||
repoURL: ssh://git@git.forteapps.net:2222/Forte/launchpad.git
|
||||
targetRevision: HEAD
|
||||
path: infra/overlays/eks-dev
|
||||
destination:
|
||||
server: https://kubernetes.default.svc
|
||||
namespace: default
|
||||
syncPolicy:
|
||||
automated:
|
||||
prune: true
|
||||
selfHeal: true
|
||||
syncOptions:
|
||||
- CreateNamespace=true
|
||||
32
_app-of-apps-eks-prod.yaml
Normal file
32
_app-of-apps-eks-prod.yaml
Normal file
@@ -0,0 +1,32 @@
|
||||
apiVersion: v1
|
||||
kind: Namespace
|
||||
metadata:
|
||||
name: monitoring
|
||||
annotations:
|
||||
argocd.argoproj.io/sync-wave: "-1"
|
||||
---
|
||||
apiVersion: argoproj.io/v1alpha1
|
||||
kind: Application
|
||||
metadata:
|
||||
name: infrastructure-apps
|
||||
namespace: argocd
|
||||
labels:
|
||||
app.kubernetes.io/name: infrastructure-apps
|
||||
app.kubernetes.io/part-of: platform
|
||||
finalizers:
|
||||
- resources-finalizer.argocd.argoproj.io
|
||||
spec:
|
||||
project: default
|
||||
source:
|
||||
repoURL: ssh://git@git.forteapps.net:2222/Forte/launchpad.git
|
||||
targetRevision: HEAD
|
||||
path: infra/overlays/eks-prod
|
||||
destination:
|
||||
server: https://kubernetes.default.svc
|
||||
namespace: default
|
||||
syncPolicy:
|
||||
automated:
|
||||
prune: true
|
||||
selfHeal: true
|
||||
syncOptions:
|
||||
- CreateNamespace=true
|
||||
32
_app-of-apps-gke-dev.yaml
Normal file
32
_app-of-apps-gke-dev.yaml
Normal file
@@ -0,0 +1,32 @@
|
||||
apiVersion: v1
|
||||
kind: Namespace
|
||||
metadata:
|
||||
name: monitoring
|
||||
annotations:
|
||||
argocd.argoproj.io/sync-wave: "-1"
|
||||
---
|
||||
apiVersion: argoproj.io/v1alpha1
|
||||
kind: Application
|
||||
metadata:
|
||||
name: infrastructure-apps
|
||||
namespace: argocd
|
||||
labels:
|
||||
app.kubernetes.io/name: infrastructure-apps
|
||||
app.kubernetes.io/part-of: platform
|
||||
finalizers:
|
||||
- resources-finalizer.argocd.argoproj.io
|
||||
spec:
|
||||
project: default
|
||||
source:
|
||||
repoURL: ssh://git@git.forteapps.net:2222/Forte/launchpad.git
|
||||
targetRevision: HEAD
|
||||
path: infra/overlays/gke-dev
|
||||
destination:
|
||||
server: https://kubernetes.default.svc
|
||||
namespace: default
|
||||
syncPolicy:
|
||||
automated:
|
||||
prune: true
|
||||
selfHeal: true
|
||||
syncOptions:
|
||||
- CreateNamespace=true
|
||||
32
_app-of-apps-gke-prod.yaml
Normal file
32
_app-of-apps-gke-prod.yaml
Normal file
@@ -0,0 +1,32 @@
|
||||
apiVersion: v1
|
||||
kind: Namespace
|
||||
metadata:
|
||||
name: monitoring
|
||||
annotations:
|
||||
argocd.argoproj.io/sync-wave: "-1"
|
||||
---
|
||||
apiVersion: argoproj.io/v1alpha1
|
||||
kind: Application
|
||||
metadata:
|
||||
name: infrastructure-apps
|
||||
namespace: argocd
|
||||
labels:
|
||||
app.kubernetes.io/name: infrastructure-apps
|
||||
app.kubernetes.io/part-of: platform
|
||||
finalizers:
|
||||
- resources-finalizer.argocd.argoproj.io
|
||||
spec:
|
||||
project: default
|
||||
source:
|
||||
repoURL: ssh://git@git.forteapps.net:2222/Forte/launchpad.git
|
||||
targetRevision: HEAD
|
||||
path: infra/overlays/gke-prod
|
||||
destination:
|
||||
server: https://kubernetes.default.svc
|
||||
namespace: default
|
||||
syncPolicy:
|
||||
automated:
|
||||
prune: true
|
||||
selfHeal: true
|
||||
syncOptions:
|
||||
- CreateNamespace=true
|
||||
@@ -18,7 +18,7 @@ metadata:
|
||||
spec:
|
||||
project: default
|
||||
source:
|
||||
repoURL: git@github.com:fortedigital/sturdy-adventure.git
|
||||
repoURL: ssh://git@git.forteapps.net:2222/Forte/launchpad.git
|
||||
targetRevision: HEAD
|
||||
path: infra/overlays/upc-prod
|
||||
destination:
|
||||
|
||||
@@ -37,7 +37,7 @@ spec:
|
||||
- $values/infra/values/base/dot-ai-stack-values.yaml
|
||||
- $values/infra/values/upc-dev/dot-ai-stack-values.yaml
|
||||
|
||||
- repoURL: git@github.com:fortedigital/sturdy-adventure.git
|
||||
- repoURL: ssh://git@git.forteapps.net:2222/Forte/launchpad.git
|
||||
targetRevision: HEAD
|
||||
ref: values
|
||||
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
# in case of $'\r': command not found error, run command below first
|
||||
# sed -i 's/\r$//' ./bootstrap.sh
|
||||
|
||||
CLUSTER="${1:?Usage: ./bootstrap.sh <cluster> (upc-dev|upc-prod)}"
|
||||
CLUSTER="${1:?Usage: ./bootstrap.sh <cluster> (upc-dev|upc-prod|aks-dev|aks-prod|eks-dev|eks-prod|gke-dev|gke-prod)}"
|
||||
|
||||
echo "running $0 for cluster: ${CLUSTER}..."
|
||||
|
||||
|
||||
@@ -57,17 +57,17 @@ spec:
|
||||
- sh
|
||||
- -c
|
||||
- |
|
||||
mc alias set upcloud "${S3_ENDPOINT}" "${AWS_ACCESS_KEY_ID}" "${AWS_SECRET_ACCESS_KEY}"
|
||||
mc alias set s3 "${S3_ENDPOINT}" "${AWS_ACCESS_KEY_ID}" "${AWS_SECRET_ACCESS_KEY}"
|
||||
|
||||
TIMESTAMP=$(date +%Y%m%d-%H%M%S)
|
||||
KEY="gitea-dump-${TIMESTAMP}.zip"
|
||||
echo "Uploading ${KEY}..."
|
||||
mc cp /backup/gitea-dump.zip "upcloud/${S3_BUCKET}/${KEY}" && \
|
||||
mc cp /backup/gitea-dump.zip "s3/${S3_BUCKET}/${KEY}" && \
|
||||
echo "Upload complete."
|
||||
|
||||
# Prune backups older than 7 days
|
||||
echo "Pruning backups older than 7 days..."
|
||||
mc rm --older-than 7d --force "upcloud/${S3_BUCKET}/" 2>&1 || true
|
||||
mc rm --older-than 7d --force "s3/${S3_BUCKET}/" 2>&1 || true
|
||||
echo "Pruning complete."
|
||||
envFrom:
|
||||
- secretRef:
|
||||
|
||||
10
clusters/aks-dev.yaml
Normal file
10
clusters/aks-dev.yaml
Normal file
@@ -0,0 +1,10 @@
|
||||
clusterName: dev-fd-aks
|
||||
domain: forteapps.net
|
||||
argocdDomain: argocd.127.0.0.1.nip.io
|
||||
grafanaDomain: grafana.forteapps.net
|
||||
keycloakDomain: id.forteapps.net
|
||||
dotaiDomain: kubemcp.forteapps.net
|
||||
dotaiUiDomain: kubemcpui.forteapps.net
|
||||
letsencryptEmail: danijels@gmail.com
|
||||
trustedIPs: "10.0.0.0/8"
|
||||
cloudProvider: azure
|
||||
10
clusters/aks-prod.yaml
Normal file
10
clusters/aks-prod.yaml
Normal file
@@ -0,0 +1,10 @@
|
||||
clusterName: prod-fd-aks
|
||||
domain: fortedigital.com
|
||||
argocdDomain: argocd.127.0.0.1.nip.io
|
||||
grafanaDomain: grafana.fortedigital.com
|
||||
keycloakDomain: id.fortedigital.com
|
||||
dotaiDomain: kubemcp.fortedigital.com
|
||||
dotaiUiDomain: kubemcpui.fortedigital.com
|
||||
letsencryptEmail: danijel.simeunovic@fortedigital.com
|
||||
trustedIPs: "10.0.0.0/8"
|
||||
cloudProvider: azure
|
||||
10
clusters/eks-dev.yaml
Normal file
10
clusters/eks-dev.yaml
Normal file
@@ -0,0 +1,10 @@
|
||||
clusterName: dev-fd-eks
|
||||
domain: forteapps.net
|
||||
argocdDomain: argocd.127.0.0.1.nip.io
|
||||
grafanaDomain: grafana.forteapps.net
|
||||
keycloakDomain: id.forteapps.net
|
||||
dotaiDomain: kubemcp.forteapps.net
|
||||
dotaiUiDomain: kubemcpui.forteapps.net
|
||||
letsencryptEmail: danijels@gmail.com
|
||||
trustedIPs: "10.0.0.0/8"
|
||||
cloudProvider: aws
|
||||
10
clusters/eks-prod.yaml
Normal file
10
clusters/eks-prod.yaml
Normal file
@@ -0,0 +1,10 @@
|
||||
clusterName: prod-fd-eks
|
||||
domain: fortedigital.com
|
||||
argocdDomain: argocd.127.0.0.1.nip.io
|
||||
grafanaDomain: grafana.fortedigital.com
|
||||
keycloakDomain: id.fortedigital.com
|
||||
dotaiDomain: kubemcp.fortedigital.com
|
||||
dotaiUiDomain: kubemcpui.fortedigital.com
|
||||
letsencryptEmail: danijel.simeunovic@fortedigital.com
|
||||
trustedIPs: "10.0.0.0/8"
|
||||
cloudProvider: aws
|
||||
10
clusters/gke-dev.yaml
Normal file
10
clusters/gke-dev.yaml
Normal file
@@ -0,0 +1,10 @@
|
||||
clusterName: dev-fd-gke
|
||||
domain: forteapps.net
|
||||
argocdDomain: argocd.127.0.0.1.nip.io
|
||||
grafanaDomain: grafana.forteapps.net
|
||||
keycloakDomain: id.forteapps.net
|
||||
dotaiDomain: kubemcp.forteapps.net
|
||||
dotaiUiDomain: kubemcpui.forteapps.net
|
||||
letsencryptEmail: danijels@gmail.com
|
||||
trustedIPs: "10.0.0.0/8"
|
||||
cloudProvider: gcp
|
||||
10
clusters/gke-prod.yaml
Normal file
10
clusters/gke-prod.yaml
Normal file
@@ -0,0 +1,10 @@
|
||||
clusterName: prod-fd-gke
|
||||
domain: fortedigital.com
|
||||
argocdDomain: argocd.127.0.0.1.nip.io
|
||||
grafanaDomain: grafana.fortedigital.com
|
||||
keycloakDomain: id.fortedigital.com
|
||||
dotaiDomain: kubemcp.fortedigital.com
|
||||
dotaiUiDomain: kubemcpui.fortedigital.com
|
||||
letsencryptEmail: danijel.simeunovic@fortedigital.com
|
||||
trustedIPs: "10.0.0.0/8"
|
||||
cloudProvider: gcp
|
||||
@@ -9,6 +9,7 @@
|
||||
- [Kyverno Policies](#kyverno-policies)
|
||||
- [Configuration Reference](#configuration-reference)
|
||||
- [API Endpoints](#api-endpoints)
|
||||
- [Cloud Overlay Pattern](#cloud-overlay-pattern)
|
||||
- [Glossary](#glossary)
|
||||
|
||||
---
|
||||
@@ -19,9 +20,9 @@
|
||||
|
||||
| Component | Value |
|
||||
|-----------|-------|
|
||||
| **Provider** | UpCloud Managed Kubernetes |
|
||||
| **Environment** | Production (internal use) |
|
||||
| **Cluster Count** | Multi-cluster (upc-dev, upc-prod) |
|
||||
| **Provider** | Multi-cloud (UpCloud, AKS, EKS, GKE) |
|
||||
| **Environment** | Dev + Production per cloud |
|
||||
| **Cluster Count** | Multi-cluster (upc-dev/prod, aks-dev/prod, eks-dev/prod, gke-dev/prod) |
|
||||
| **GitOps Tool** | ArgoCD |
|
||||
| **Ingress Controller** | Traefik v2 |
|
||||
| **Certificate Management** | Cert-Manager + Let's Encrypt |
|
||||
@@ -92,16 +93,34 @@ launchpad/
|
||||
│ ├── sealedsecrets.yaml
|
||||
│ ├── secrets.yaml
|
||||
│ ├── renovate.yaml
|
||||
│ ├── base/ # ArgoCD Application manifests (Kustomize base)
|
||||
│ │ ├── gitea.yaml
|
||||
│ │ ├── opencost.yaml
|
||||
│ │ ├── traefik-application.yaml
|
||||
│ │ ├── keycloak.yaml
|
||||
│ │ ├── grafana.yaml
|
||||
│ │ └── ...
|
||||
│ ├── overlays/
|
||||
│ │ └── upc-prod/
|
||||
│ │ └── kustomization.yaml # Patches upc-dev → upc-prod valueFile paths
|
||||
│ └── values/
|
||||
│ ├── argocd-values.yaml
|
||||
│ ├── prometheus-values.yaml
|
||||
│ ├── grafana-values.yaml
|
||||
│ ├── loki-values.yaml
|
||||
│ ├── tempo-values.yaml
|
||||
│ ├── gitea-values.yaml
|
||||
│ ├── gitea-actions-values.yaml
|
||||
│ ├── fluent-bit-values.yaml
|
||||
│ └── renovate-values.yaml
|
||||
│ ├── base/ # Cloud-agnostic Helm values
|
||||
│ │ ├── gitea-values.yaml
|
||||
│ │ ├── opencost-values.yaml
|
||||
│ │ ├── prometheus-values.yaml
|
||||
│ │ └── ...
|
||||
│ ├── upc-dev/ # UpCloud dev overlay values
|
||||
│ │ ├── traefik-values.yaml
|
||||
│ │ ├── keycloak-values.yaml
|
||||
│ │ ├── grafana-values.yaml
|
||||
│ │ ├── gitea-values.yaml
|
||||
│ │ └── opencost-values.yaml
|
||||
│ └── upc-prod/ # UpCloud prod overlay values
|
||||
│ ├── traefik-values.yaml
|
||||
│ ├── keycloak-values.yaml
|
||||
│ ├── grafana-values.yaml
|
||||
│ ├── gitea-values.yaml
|
||||
│ └── opencost-values.yaml
|
||||
│
|
||||
├── apps/ # Business applications
|
||||
│ ├── mcp10x.yaml
|
||||
@@ -135,6 +154,15 @@ launchpad/
|
||||
│ ├── mcp10x-credentials-sealed.yaml
|
||||
│ └── musicman-credentials.yaml
|
||||
│
|
||||
├── scripts/ # Operational helper scripts
|
||||
│ ├── gitea-backup.sh # S3 backup helper (list/download)
|
||||
│ ├── gitea-restore.sh
|
||||
│ └── backup/ # Per-cloud backup reference scripts
|
||||
│ ├── s3-minio.sh # S3-compatible (UpCloud, MinIO, Wasabi)
|
||||
│ ├── aws-s3.sh # Native AWS S3
|
||||
│ ├── azure-blob.sh # Azure Blob Storage
|
||||
│ └── gcp-gcs.sh # GCP Cloud Storage
|
||||
│
|
||||
├── private/ # Local-only (Git-ignored)
|
||||
│ ├── *.yaml
|
||||
│ └── *.sh
|
||||
@@ -1621,6 +1649,87 @@ POST /loki/api/v1/push
|
||||
|
||||
---
|
||||
|
||||
## Cloud Overlay Pattern
|
||||
|
||||
### Overview
|
||||
|
||||
Cloud-specific configuration (StorageClass, LoadBalancer annotations, pricing models, etc.) lives in per-cloud overlay value files, **not** in `base/`. Adding a new cloud provider only requires a new overlay directory — no base changes.
|
||||
|
||||
### Supported Clouds
|
||||
|
||||
| Cloud | Dev overlay | Prod overlay | StorageClass | LB type |
|
||||
|-------|-----------|-------------|-------------|---------|
|
||||
| **UpCloud** | `upc-dev` | `upc-prod` | `upcloud-block-storage-maxiops` | UpCloud LB (proxy protocol v2) |
|
||||
| **Azure AKS** | `aks-dev` | `aks-prod` | `managed-csi-premium` | Azure LB |
|
||||
| **AWS EKS** | `eks-dev` | `eks-prod` | `gp3` | AWS NLB (proxy protocol) |
|
||||
| **GCP GKE** | `gke-dev` | `gke-prod` | `premium-rwo` | GCP NEG |
|
||||
|
||||
Bootstrap any cluster with: `./bootstrap.sh <cluster>` (e.g., `./bootstrap.sh aks-dev`)
|
||||
|
||||
### How It Works
|
||||
|
||||
Each ArgoCD Application uses **multi-source Helm values** with two value files:
|
||||
|
||||
```yaml
|
||||
# infra/base/gitea.yaml (example)
|
||||
helm:
|
||||
valueFiles:
|
||||
- $values/infra/values/base/gitea-values.yaml # [0] cloud-agnostic
|
||||
- $values/infra/values/upc-dev/gitea-values.yaml # [1] cloud-specific (default: upc-dev)
|
||||
```
|
||||
|
||||
The `upc-prod` Kustomize overlay patches index `[1]` to swap the cloud-specific file:
|
||||
|
||||
```yaml
|
||||
# infra/overlays/upc-prod/kustomization.yaml
|
||||
- target:
|
||||
kind: Application
|
||||
name: gitea
|
||||
patch: |
|
||||
- op: replace
|
||||
path: /spec/sources/0/helm/valueFiles/1
|
||||
value: $values/infra/values/upc-prod/gitea-values.yaml
|
||||
```
|
||||
|
||||
### Components Using Cloud Overlays
|
||||
|
||||
| Component | Cloud-specific config | Overlay value file |
|
||||
|-----------|----------------------|-------------------|
|
||||
| **Traefik** | LB annotations, proxy protocol IPs | `traefik-values.yaml` |
|
||||
| **Keycloak** | Hostname, TLS settings | `keycloak-values.yaml` |
|
||||
| **Grafana** | Hostname, datasource URLs | `grafana-values.yaml` |
|
||||
| **Gitea** | StorageClass (persistence + PostgreSQL) | `gitea-values.yaml` |
|
||||
| **OpenCost** | Custom pricing model (CPU/RAM/storage rates) | `opencost-values.yaml` |
|
||||
|
||||
### Backup CronJob
|
||||
|
||||
The `gitea-backup` CronJob uses a generic `s3` alias for `minio/mc`. The actual endpoint and credentials come from the `gitea-backup-s3` Sealed Secret, which is per-cloud. Reference scripts for different cloud providers are in `scripts/backup/`:
|
||||
|
||||
| Script | Provider | Tool |
|
||||
|--------|----------|------|
|
||||
| `s3-minio.sh` | S3-compatible (UpCloud, MinIO, Wasabi) | `minio/mc` |
|
||||
| `aws-s3.sh` | AWS S3 | `aws` CLI |
|
||||
| `azure-blob.sh` | Azure Blob Storage | `az` CLI |
|
||||
| `gcp-gcs.sh` | GCP Cloud Storage | `gsutil` |
|
||||
|
||||
### Adding a New Cloud Provider
|
||||
|
||||
To add support for a new cloud (e.g., `oci-dev` for Oracle Cloud):
|
||||
|
||||
1. **Cluster config**: `clusters/oci-dev.yaml` — clusterName, domain, trustedIPs, cloudProvider
|
||||
2. **Overlay value files** in `infra/values/oci-dev/`:
|
||||
- `traefik-values.yaml` — LB annotations, proxy protocol config
|
||||
- `keycloak-values.yaml` — hostname
|
||||
- `grafana-values.yaml` — hostname
|
||||
- `gitea-values.yaml` — `storageClass` for persistence + PostgreSQL
|
||||
- `opencost-values.yaml` — pricing model or cloud billing integration
|
||||
3. **Kustomize overlay**: `infra/overlays/oci-dev/kustomization.yaml` — patch `valueFiles[1]` for each Application
|
||||
4. **App-of-apps**: `_app-of-apps-oci-dev.yaml` — points to `infra/overlays/oci-dev`
|
||||
5. **Sealed Secrets**: `secrets/oci-dev/` — TLS certs, credentials, backup S3 config
|
||||
6. **Bootstrap**: `./bootstrap.sh oci-dev`
|
||||
|
||||
---
|
||||
|
||||
## Glossary
|
||||
|
||||
### Terms
|
||||
|
||||
@@ -22,6 +22,7 @@ spec:
|
||||
releaseName: gitea
|
||||
valueFiles:
|
||||
- $values/infra/values/base/gitea-values.yaml
|
||||
- $values/infra/values/upc-dev/gitea-values.yaml
|
||||
|
||||
- repoURL: ssh://git@git.forteapps.net:2222/Forte/launchpad.git
|
||||
targetRevision: HEAD
|
||||
|
||||
@@ -22,8 +22,9 @@ spec:
|
||||
releaseName: opencost
|
||||
valueFiles:
|
||||
- $values/infra/values/base/opencost-values.yaml
|
||||
- $values/infra/values/upc-dev/opencost-values.yaml
|
||||
|
||||
- repoURL: git@github.com:fortedigital/sturdy-adventure.git
|
||||
- repoURL: ssh://git@git.forteapps.net:2222/Forte/launchpad.git
|
||||
targetRevision: HEAD
|
||||
ref: values
|
||||
|
||||
|
||||
@@ -31,7 +31,7 @@ spec:
|
||||
- $values/infra/values/base/traefik-values.yaml
|
||||
- $values/infra/values/upc-dev/traefik-values.yaml
|
||||
|
||||
- repoURL: git@github.com:fortedigital/sturdy-adventure.git
|
||||
- repoURL: ssh://git@git.forteapps.net:2222/Forte/launchpad.git
|
||||
targetRevision: HEAD
|
||||
ref: values
|
||||
|
||||
|
||||
68
infra/overlays/aks-dev/kustomization.yaml
Normal file
68
infra/overlays/aks-dev/kustomization.yaml
Normal file
@@ -0,0 +1,68 @@
|
||||
apiVersion: kustomize.config.k8s.io/v1beta1
|
||||
kind: Kustomization
|
||||
resources:
|
||||
- ../../base
|
||||
|
||||
patches:
|
||||
# Traefik: swap upc-dev → aks-dev
|
||||
- target:
|
||||
kind: Application
|
||||
name: traefik
|
||||
patch: |
|
||||
- op: replace
|
||||
path: /spec/sources/0/helm/valueFiles/1
|
||||
value: $values/infra/values/aks-dev/traefik-values.yaml
|
||||
|
||||
# Keycloak: swap upc-dev → aks-dev
|
||||
- target:
|
||||
kind: Application
|
||||
name: keycloak
|
||||
patch: |
|
||||
- op: replace
|
||||
path: /spec/sources/0/helm/valueFiles/1
|
||||
value: $values/infra/values/aks-dev/keycloak-values.yaml
|
||||
|
||||
# Grafana: swap upc-dev → aks-dev
|
||||
- target:
|
||||
kind: Application
|
||||
name: grafana
|
||||
patch: |
|
||||
- op: replace
|
||||
path: /spec/sources/0/helm/valueFiles/1
|
||||
value: $values/infra/values/aks-dev/grafana-values.yaml
|
||||
|
||||
# Gitea: swap upc-dev → aks-dev
|
||||
- target:
|
||||
kind: Application
|
||||
name: gitea
|
||||
patch: |
|
||||
- op: replace
|
||||
path: /spec/sources/0/helm/valueFiles/1
|
||||
value: $values/infra/values/aks-dev/gitea-values.yaml
|
||||
|
||||
# OpenCost: swap upc-dev → aks-dev
|
||||
- target:
|
||||
kind: Application
|
||||
name: opencost
|
||||
patch: |
|
||||
- op: replace
|
||||
path: /spec/sources/0/helm/valueFiles/1
|
||||
value: $values/infra/values/aks-dev/opencost-values.yaml
|
||||
|
||||
# Secrets: change path to aks-dev
|
||||
- target:
|
||||
kind: Application
|
||||
name: secrets
|
||||
patch: |
|
||||
- op: replace
|
||||
path: /spec/source/path
|
||||
value: secrets/aks-dev
|
||||
|
||||
# Enterprise-apps: point to aks-dev overlay
|
||||
- target:
|
||||
kind: Application
|
||||
name: enterprise-apps
|
||||
patch: |
|
||||
- op: replace
|
||||
path: /spec/source/path
|
||||
value: apps/overlays/aks-dev
|
||||
68
infra/overlays/aks-prod/kustomization.yaml
Normal file
68
infra/overlays/aks-prod/kustomization.yaml
Normal file
@@ -0,0 +1,68 @@
|
||||
apiVersion: kustomize.config.k8s.io/v1beta1
|
||||
kind: Kustomization
|
||||
resources:
|
||||
- ../../base
|
||||
|
||||
patches:
|
||||
# Traefik: swap upc-dev → aks-prod
|
||||
- target:
|
||||
kind: Application
|
||||
name: traefik
|
||||
patch: |
|
||||
- op: replace
|
||||
path: /spec/sources/0/helm/valueFiles/1
|
||||
value: $values/infra/values/aks-prod/traefik-values.yaml
|
||||
|
||||
# Keycloak: swap upc-dev → aks-prod
|
||||
- target:
|
||||
kind: Application
|
||||
name: keycloak
|
||||
patch: |
|
||||
- op: replace
|
||||
path: /spec/sources/0/helm/valueFiles/1
|
||||
value: $values/infra/values/aks-prod/keycloak-values.yaml
|
||||
|
||||
# Grafana: swap upc-dev → aks-prod
|
||||
- target:
|
||||
kind: Application
|
||||
name: grafana
|
||||
patch: |
|
||||
- op: replace
|
||||
path: /spec/sources/0/helm/valueFiles/1
|
||||
value: $values/infra/values/aks-prod/grafana-values.yaml
|
||||
|
||||
# Gitea: swap upc-dev → aks-prod
|
||||
- target:
|
||||
kind: Application
|
||||
name: gitea
|
||||
patch: |
|
||||
- op: replace
|
||||
path: /spec/sources/0/helm/valueFiles/1
|
||||
value: $values/infra/values/aks-prod/gitea-values.yaml
|
||||
|
||||
# OpenCost: swap upc-dev → aks-prod
|
||||
- target:
|
||||
kind: Application
|
||||
name: opencost
|
||||
patch: |
|
||||
- op: replace
|
||||
path: /spec/sources/0/helm/valueFiles/1
|
||||
value: $values/infra/values/aks-prod/opencost-values.yaml
|
||||
|
||||
# Secrets: change path to aks-prod
|
||||
- target:
|
||||
kind: Application
|
||||
name: secrets
|
||||
patch: |
|
||||
- op: replace
|
||||
path: /spec/source/path
|
||||
value: secrets/aks-prod
|
||||
|
||||
# Enterprise-apps: point to aks-prod overlay
|
||||
- target:
|
||||
kind: Application
|
||||
name: enterprise-apps
|
||||
patch: |
|
||||
- op: replace
|
||||
path: /spec/source/path
|
||||
value: apps/overlays/aks-prod
|
||||
68
infra/overlays/eks-dev/kustomization.yaml
Normal file
68
infra/overlays/eks-dev/kustomization.yaml
Normal file
@@ -0,0 +1,68 @@
|
||||
apiVersion: kustomize.config.k8s.io/v1beta1
|
||||
kind: Kustomization
|
||||
resources:
|
||||
- ../../base
|
||||
|
||||
patches:
|
||||
# Traefik: swap upc-dev → eks-dev
|
||||
- target:
|
||||
kind: Application
|
||||
name: traefik
|
||||
patch: |
|
||||
- op: replace
|
||||
path: /spec/sources/0/helm/valueFiles/1
|
||||
value: $values/infra/values/eks-dev/traefik-values.yaml
|
||||
|
||||
# Keycloak: swap upc-dev → eks-dev
|
||||
- target:
|
||||
kind: Application
|
||||
name: keycloak
|
||||
patch: |
|
||||
- op: replace
|
||||
path: /spec/sources/0/helm/valueFiles/1
|
||||
value: $values/infra/values/eks-dev/keycloak-values.yaml
|
||||
|
||||
# Grafana: swap upc-dev → eks-dev
|
||||
- target:
|
||||
kind: Application
|
||||
name: grafana
|
||||
patch: |
|
||||
- op: replace
|
||||
path: /spec/sources/0/helm/valueFiles/1
|
||||
value: $values/infra/values/eks-dev/grafana-values.yaml
|
||||
|
||||
# Gitea: swap upc-dev → eks-dev
|
||||
- target:
|
||||
kind: Application
|
||||
name: gitea
|
||||
patch: |
|
||||
- op: replace
|
||||
path: /spec/sources/0/helm/valueFiles/1
|
||||
value: $values/infra/values/eks-dev/gitea-values.yaml
|
||||
|
||||
# OpenCost: swap upc-dev → eks-dev
|
||||
- target:
|
||||
kind: Application
|
||||
name: opencost
|
||||
patch: |
|
||||
- op: replace
|
||||
path: /spec/sources/0/helm/valueFiles/1
|
||||
value: $values/infra/values/eks-dev/opencost-values.yaml
|
||||
|
||||
# Secrets: change path to eks-dev
|
||||
- target:
|
||||
kind: Application
|
||||
name: secrets
|
||||
patch: |
|
||||
- op: replace
|
||||
path: /spec/source/path
|
||||
value: secrets/eks-dev
|
||||
|
||||
# Enterprise-apps: point to eks-dev overlay
|
||||
- target:
|
||||
kind: Application
|
||||
name: enterprise-apps
|
||||
patch: |
|
||||
- op: replace
|
||||
path: /spec/source/path
|
||||
value: apps/overlays/eks-dev
|
||||
68
infra/overlays/eks-prod/kustomization.yaml
Normal file
68
infra/overlays/eks-prod/kustomization.yaml
Normal file
@@ -0,0 +1,68 @@
|
||||
apiVersion: kustomize.config.k8s.io/v1beta1
|
||||
kind: Kustomization
|
||||
resources:
|
||||
- ../../base
|
||||
|
||||
patches:
|
||||
# Traefik: swap upc-dev → eks-prod
|
||||
- target:
|
||||
kind: Application
|
||||
name: traefik
|
||||
patch: |
|
||||
- op: replace
|
||||
path: /spec/sources/0/helm/valueFiles/1
|
||||
value: $values/infra/values/eks-prod/traefik-values.yaml
|
||||
|
||||
# Keycloak: swap upc-dev → eks-prod
|
||||
- target:
|
||||
kind: Application
|
||||
name: keycloak
|
||||
patch: |
|
||||
- op: replace
|
||||
path: /spec/sources/0/helm/valueFiles/1
|
||||
value: $values/infra/values/eks-prod/keycloak-values.yaml
|
||||
|
||||
# Grafana: swap upc-dev → eks-prod
|
||||
- target:
|
||||
kind: Application
|
||||
name: grafana
|
||||
patch: |
|
||||
- op: replace
|
||||
path: /spec/sources/0/helm/valueFiles/1
|
||||
value: $values/infra/values/eks-prod/grafana-values.yaml
|
||||
|
||||
# Gitea: swap upc-dev → eks-prod
|
||||
- target:
|
||||
kind: Application
|
||||
name: gitea
|
||||
patch: |
|
||||
- op: replace
|
||||
path: /spec/sources/0/helm/valueFiles/1
|
||||
value: $values/infra/values/eks-prod/gitea-values.yaml
|
||||
|
||||
# OpenCost: swap upc-dev → eks-prod
|
||||
- target:
|
||||
kind: Application
|
||||
name: opencost
|
||||
patch: |
|
||||
- op: replace
|
||||
path: /spec/sources/0/helm/valueFiles/1
|
||||
value: $values/infra/values/eks-prod/opencost-values.yaml
|
||||
|
||||
# Secrets: change path to eks-prod
|
||||
- target:
|
||||
kind: Application
|
||||
name: secrets
|
||||
patch: |
|
||||
- op: replace
|
||||
path: /spec/source/path
|
||||
value: secrets/eks-prod
|
||||
|
||||
# Enterprise-apps: point to eks-prod overlay
|
||||
- target:
|
||||
kind: Application
|
||||
name: enterprise-apps
|
||||
patch: |
|
||||
- op: replace
|
||||
path: /spec/source/path
|
||||
value: apps/overlays/eks-prod
|
||||
68
infra/overlays/gke-dev/kustomization.yaml
Normal file
68
infra/overlays/gke-dev/kustomization.yaml
Normal file
@@ -0,0 +1,68 @@
|
||||
apiVersion: kustomize.config.k8s.io/v1beta1
|
||||
kind: Kustomization
|
||||
resources:
|
||||
- ../../base
|
||||
|
||||
patches:
|
||||
# Traefik: swap upc-dev → gke-dev
|
||||
- target:
|
||||
kind: Application
|
||||
name: traefik
|
||||
patch: |
|
||||
- op: replace
|
||||
path: /spec/sources/0/helm/valueFiles/1
|
||||
value: $values/infra/values/gke-dev/traefik-values.yaml
|
||||
|
||||
# Keycloak: swap upc-dev → gke-dev
|
||||
- target:
|
||||
kind: Application
|
||||
name: keycloak
|
||||
patch: |
|
||||
- op: replace
|
||||
path: /spec/sources/0/helm/valueFiles/1
|
||||
value: $values/infra/values/gke-dev/keycloak-values.yaml
|
||||
|
||||
# Grafana: swap upc-dev → gke-dev
|
||||
- target:
|
||||
kind: Application
|
||||
name: grafana
|
||||
patch: |
|
||||
- op: replace
|
||||
path: /spec/sources/0/helm/valueFiles/1
|
||||
value: $values/infra/values/gke-dev/grafana-values.yaml
|
||||
|
||||
# Gitea: swap upc-dev → gke-dev
|
||||
- target:
|
||||
kind: Application
|
||||
name: gitea
|
||||
patch: |
|
||||
- op: replace
|
||||
path: /spec/sources/0/helm/valueFiles/1
|
||||
value: $values/infra/values/gke-dev/gitea-values.yaml
|
||||
|
||||
# OpenCost: swap upc-dev → gke-dev
|
||||
- target:
|
||||
kind: Application
|
||||
name: opencost
|
||||
patch: |
|
||||
- op: replace
|
||||
path: /spec/sources/0/helm/valueFiles/1
|
||||
value: $values/infra/values/gke-dev/opencost-values.yaml
|
||||
|
||||
# Secrets: change path to gke-dev
|
||||
- target:
|
||||
kind: Application
|
||||
name: secrets
|
||||
patch: |
|
||||
- op: replace
|
||||
path: /spec/source/path
|
||||
value: secrets/gke-dev
|
||||
|
||||
# Enterprise-apps: point to gke-dev overlay
|
||||
- target:
|
||||
kind: Application
|
||||
name: enterprise-apps
|
||||
patch: |
|
||||
- op: replace
|
||||
path: /spec/source/path
|
||||
value: apps/overlays/gke-dev
|
||||
68
infra/overlays/gke-prod/kustomization.yaml
Normal file
68
infra/overlays/gke-prod/kustomization.yaml
Normal file
@@ -0,0 +1,68 @@
|
||||
apiVersion: kustomize.config.k8s.io/v1beta1
|
||||
kind: Kustomization
|
||||
resources:
|
||||
- ../../base
|
||||
|
||||
patches:
|
||||
# Traefik: swap upc-dev → gke-prod
|
||||
- target:
|
||||
kind: Application
|
||||
name: traefik
|
||||
patch: |
|
||||
- op: replace
|
||||
path: /spec/sources/0/helm/valueFiles/1
|
||||
value: $values/infra/values/gke-prod/traefik-values.yaml
|
||||
|
||||
# Keycloak: swap upc-dev → gke-prod
|
||||
- target:
|
||||
kind: Application
|
||||
name: keycloak
|
||||
patch: |
|
||||
- op: replace
|
||||
path: /spec/sources/0/helm/valueFiles/1
|
||||
value: $values/infra/values/gke-prod/keycloak-values.yaml
|
||||
|
||||
# Grafana: swap upc-dev → gke-prod
|
||||
- target:
|
||||
kind: Application
|
||||
name: grafana
|
||||
patch: |
|
||||
- op: replace
|
||||
path: /spec/sources/0/helm/valueFiles/1
|
||||
value: $values/infra/values/gke-prod/grafana-values.yaml
|
||||
|
||||
# Gitea: swap upc-dev → gke-prod
|
||||
- target:
|
||||
kind: Application
|
||||
name: gitea
|
||||
patch: |
|
||||
- op: replace
|
||||
path: /spec/sources/0/helm/valueFiles/1
|
||||
value: $values/infra/values/gke-prod/gitea-values.yaml
|
||||
|
||||
# OpenCost: swap upc-dev → gke-prod
|
||||
- target:
|
||||
kind: Application
|
||||
name: opencost
|
||||
patch: |
|
||||
- op: replace
|
||||
path: /spec/sources/0/helm/valueFiles/1
|
||||
value: $values/infra/values/gke-prod/opencost-values.yaml
|
||||
|
||||
# Secrets: change path to gke-prod
|
||||
- target:
|
||||
kind: Application
|
||||
name: secrets
|
||||
patch: |
|
||||
- op: replace
|
||||
path: /spec/source/path
|
||||
value: secrets/gke-prod
|
||||
|
||||
# Enterprise-apps: point to gke-prod overlay
|
||||
- target:
|
||||
kind: Application
|
||||
name: enterprise-apps
|
||||
patch: |
|
||||
- op: replace
|
||||
path: /spec/source/path
|
||||
value: apps/overlays/gke-prod
|
||||
@@ -31,6 +31,24 @@ patches:
|
||||
path: /spec/sources/0/helm/valueFiles/1
|
||||
value: $values/infra/values/upc-prod/grafana-values.yaml
|
||||
|
||||
# Gitea: swap upc-dev → upc-prod
|
||||
- target:
|
||||
kind: Application
|
||||
name: gitea
|
||||
patch: |
|
||||
- op: replace
|
||||
path: /spec/sources/0/helm/valueFiles/1
|
||||
value: $values/infra/values/upc-prod/gitea-values.yaml
|
||||
|
||||
# OpenCost: swap upc-dev → upc-prod
|
||||
- target:
|
||||
kind: Application
|
||||
name: opencost
|
||||
patch: |
|
||||
- op: replace
|
||||
path: /spec/sources/0/helm/valueFiles/1
|
||||
value: $values/infra/values/upc-prod/opencost-values.yaml
|
||||
|
||||
# Secrets: change path to upc-prod
|
||||
- target:
|
||||
kind: Application
|
||||
|
||||
7
infra/values/aks-dev/gitea-values.yaml
Normal file
7
infra/values/aks-dev/gitea-values.yaml
Normal file
@@ -0,0 +1,7 @@
|
||||
# AKS-specific: Azure managed disk storage class
|
||||
persistence:
|
||||
storageClass: managed-csi-premium
|
||||
postgresql:
|
||||
primary:
|
||||
persistence:
|
||||
storageClass: managed-csi-premium
|
||||
4
infra/values/aks-dev/grafana-values.yaml
Normal file
4
infra/values/aks-dev/grafana-values.yaml
Normal file
@@ -0,0 +1,4 @@
|
||||
# AKS-specific: Grafana hostname
|
||||
ingress:
|
||||
hosts:
|
||||
- grafana.forteapps.net
|
||||
3
infra/values/aks-dev/keycloak-values.yaml
Normal file
3
infra/values/aks-dev/keycloak-values.yaml
Normal file
@@ -0,0 +1,3 @@
|
||||
# AKS-specific: Keycloak hostname
|
||||
ingress:
|
||||
hostname: id.forteapps.net
|
||||
8
infra/values/aks-dev/opencost-values.yaml
Normal file
8
infra/values/aks-dev/opencost-values.yaml
Normal file
@@ -0,0 +1,8 @@
|
||||
# AKS-specific: Azure pricing via Cloud Billing API
|
||||
opencost:
|
||||
exporter:
|
||||
cloudProviderApiKey: ""
|
||||
customPricing:
|
||||
enabled: false
|
||||
azure:
|
||||
secretName: opencost-azure-billing
|
||||
11
infra/values/aks-dev/traefik-values.yaml
Normal file
11
infra/values/aks-dev/traefik-values.yaml
Normal file
@@ -0,0 +1,11 @@
|
||||
# AKS-specific: Azure Load Balancer for Traefik
|
||||
service:
|
||||
annotations:
|
||||
service.beta.kubernetes.io/azure-load-balancer-health-probe-request-path: /ping
|
||||
ports:
|
||||
web:
|
||||
forwardedHeaders:
|
||||
trustedIPs: "10.0.0.0/8"
|
||||
websecure:
|
||||
forwardedHeaders:
|
||||
trustedIPs: "10.0.0.0/8"
|
||||
7
infra/values/aks-prod/gitea-values.yaml
Normal file
7
infra/values/aks-prod/gitea-values.yaml
Normal file
@@ -0,0 +1,7 @@
|
||||
# AKS-specific: Azure managed disk storage class (prod)
|
||||
persistence:
|
||||
storageClass: managed-csi-premium
|
||||
postgresql:
|
||||
primary:
|
||||
persistence:
|
||||
storageClass: managed-csi-premium
|
||||
4
infra/values/aks-prod/grafana-values.yaml
Normal file
4
infra/values/aks-prod/grafana-values.yaml
Normal file
@@ -0,0 +1,4 @@
|
||||
# AKS-specific: Grafana hostname (prod)
|
||||
ingress:
|
||||
hosts:
|
||||
- grafana.fortedigital.com
|
||||
3
infra/values/aks-prod/keycloak-values.yaml
Normal file
3
infra/values/aks-prod/keycloak-values.yaml
Normal file
@@ -0,0 +1,3 @@
|
||||
# AKS-specific: Keycloak hostname (prod)
|
||||
ingress:
|
||||
hostname: id.fortedigital.com
|
||||
8
infra/values/aks-prod/opencost-values.yaml
Normal file
8
infra/values/aks-prod/opencost-values.yaml
Normal file
@@ -0,0 +1,8 @@
|
||||
# AKS-specific: Azure pricing via Cloud Billing API (prod)
|
||||
opencost:
|
||||
exporter:
|
||||
cloudProviderApiKey: ""
|
||||
customPricing:
|
||||
enabled: false
|
||||
azure:
|
||||
secretName: opencost-azure-billing
|
||||
12
infra/values/aks-prod/traefik-values.yaml
Normal file
12
infra/values/aks-prod/traefik-values.yaml
Normal file
@@ -0,0 +1,12 @@
|
||||
# AKS-specific: Azure Load Balancer for Traefik (prod)
|
||||
service:
|
||||
annotations:
|
||||
service.beta.kubernetes.io/azure-load-balancer-health-probe-request-path: /ping
|
||||
service.beta.kubernetes.io/azure-load-balancer-internal: "false"
|
||||
ports:
|
||||
web:
|
||||
forwardedHeaders:
|
||||
trustedIPs: "10.0.0.0/8"
|
||||
websecure:
|
||||
forwardedHeaders:
|
||||
trustedIPs: "10.0.0.0/8"
|
||||
@@ -130,7 +130,6 @@ persistence:
|
||||
size: 10Gi
|
||||
accessModes:
|
||||
- ReadWriteOnce
|
||||
storageClass: upcloud-block-storage-maxiops
|
||||
|
||||
# -- Recreate strategy to avoid Multi-Attach errors with RWO volumes
|
||||
strategy:
|
||||
@@ -156,7 +155,6 @@ postgresql:
|
||||
persistence:
|
||||
enabled: true
|
||||
size: 8Gi
|
||||
storageClass: upcloud-block-storage-maxiops
|
||||
resources:
|
||||
requests:
|
||||
cpu: 100m
|
||||
|
||||
@@ -10,18 +10,6 @@ opencost:
|
||||
serviceName: prometheus-server
|
||||
namespaceName: monitoring
|
||||
port: 80
|
||||
customPricing:
|
||||
enabled: true
|
||||
provider: custom
|
||||
costModel:
|
||||
description: "UpCloud 4-node cluster pricing"
|
||||
CPU: "5.86"
|
||||
RAM: "1.46"
|
||||
GPU: "0"
|
||||
storage: "0.34"
|
||||
zoneNetworkEgress: "0"
|
||||
regionNetworkEgress: "0"
|
||||
internetNetworkEgress: "0"
|
||||
ui:
|
||||
enabled: false
|
||||
service:
|
||||
|
||||
7
infra/values/eks-dev/gitea-values.yaml
Normal file
7
infra/values/eks-dev/gitea-values.yaml
Normal file
@@ -0,0 +1,7 @@
|
||||
# EKS-specific: gp3 storage class
|
||||
persistence:
|
||||
storageClass: gp3
|
||||
postgresql:
|
||||
primary:
|
||||
persistence:
|
||||
storageClass: gp3
|
||||
4
infra/values/eks-dev/grafana-values.yaml
Normal file
4
infra/values/eks-dev/grafana-values.yaml
Normal file
@@ -0,0 +1,4 @@
|
||||
# EKS-specific: Grafana hostname
|
||||
ingress:
|
||||
hosts:
|
||||
- grafana.forteapps.net
|
||||
3
infra/values/eks-dev/keycloak-values.yaml
Normal file
3
infra/values/eks-dev/keycloak-values.yaml
Normal file
@@ -0,0 +1,3 @@
|
||||
# EKS-specific: Keycloak hostname
|
||||
ingress:
|
||||
hostname: id.forteapps.net
|
||||
11
infra/values/eks-dev/opencost-values.yaml
Normal file
11
infra/values/eks-dev/opencost-values.yaml
Normal file
@@ -0,0 +1,11 @@
|
||||
# EKS-specific: AWS pricing via Cost and Usage Report
|
||||
opencost:
|
||||
exporter:
|
||||
cloudProviderApiKey: ""
|
||||
customPricing:
|
||||
enabled: false
|
||||
aws:
|
||||
spot_data_region: ""
|
||||
spot_data_bucket: ""
|
||||
spot_data_prefix: ""
|
||||
account_id: ""
|
||||
17
infra/values/eks-dev/traefik-values.yaml
Normal file
17
infra/values/eks-dev/traefik-values.yaml
Normal file
@@ -0,0 +1,17 @@
|
||||
# EKS-specific: AWS NLB for Traefik
|
||||
service:
|
||||
annotations:
|
||||
service.beta.kubernetes.io/aws-load-balancer-type: nlb
|
||||
service.beta.kubernetes.io/aws-load-balancer-scheme: internet-facing
|
||||
service.beta.kubernetes.io/aws-load-balancer-proxy-protocol: "*"
|
||||
ports:
|
||||
web:
|
||||
proxyProtocol:
|
||||
trustedIPs: "10.0.0.0/8"
|
||||
forwardedHeaders:
|
||||
trustedIPs: "10.0.0.0/8"
|
||||
websecure:
|
||||
proxyProtocol:
|
||||
trustedIPs: "10.0.0.0/8"
|
||||
forwardedHeaders:
|
||||
trustedIPs: "10.0.0.0/8"
|
||||
7
infra/values/eks-prod/gitea-values.yaml
Normal file
7
infra/values/eks-prod/gitea-values.yaml
Normal file
@@ -0,0 +1,7 @@
|
||||
# EKS-specific: gp3 storage class (prod)
|
||||
persistence:
|
||||
storageClass: gp3
|
||||
postgresql:
|
||||
primary:
|
||||
persistence:
|
||||
storageClass: gp3
|
||||
4
infra/values/eks-prod/grafana-values.yaml
Normal file
4
infra/values/eks-prod/grafana-values.yaml
Normal file
@@ -0,0 +1,4 @@
|
||||
# EKS-specific: Grafana hostname (prod)
|
||||
ingress:
|
||||
hosts:
|
||||
- grafana.fortedigital.com
|
||||
3
infra/values/eks-prod/keycloak-values.yaml
Normal file
3
infra/values/eks-prod/keycloak-values.yaml
Normal file
@@ -0,0 +1,3 @@
|
||||
# EKS-specific: Keycloak hostname (prod)
|
||||
ingress:
|
||||
hostname: id.fortedigital.com
|
||||
11
infra/values/eks-prod/opencost-values.yaml
Normal file
11
infra/values/eks-prod/opencost-values.yaml
Normal file
@@ -0,0 +1,11 @@
|
||||
# EKS-specific: AWS pricing via Cost and Usage Report (prod)
|
||||
opencost:
|
||||
exporter:
|
||||
cloudProviderApiKey: ""
|
||||
customPricing:
|
||||
enabled: false
|
||||
aws:
|
||||
spot_data_region: ""
|
||||
spot_data_bucket: ""
|
||||
spot_data_prefix: ""
|
||||
account_id: ""
|
||||
18
infra/values/eks-prod/traefik-values.yaml
Normal file
18
infra/values/eks-prod/traefik-values.yaml
Normal file
@@ -0,0 +1,18 @@
|
||||
# EKS-specific: AWS NLB for Traefik (prod)
|
||||
service:
|
||||
annotations:
|
||||
service.beta.kubernetes.io/aws-load-balancer-type: nlb
|
||||
service.beta.kubernetes.io/aws-load-balancer-scheme: internet-facing
|
||||
service.beta.kubernetes.io/aws-load-balancer-proxy-protocol: "*"
|
||||
service.beta.kubernetes.io/aws-load-balancer-cross-zone-load-balancing-enabled: "true"
|
||||
ports:
|
||||
web:
|
||||
proxyProtocol:
|
||||
trustedIPs: "10.0.0.0/8"
|
||||
forwardedHeaders:
|
||||
trustedIPs: "10.0.0.0/8"
|
||||
websecure:
|
||||
proxyProtocol:
|
||||
trustedIPs: "10.0.0.0/8"
|
||||
forwardedHeaders:
|
||||
trustedIPs: "10.0.0.0/8"
|
||||
7
infra/values/gke-dev/gitea-values.yaml
Normal file
7
infra/values/gke-dev/gitea-values.yaml
Normal file
@@ -0,0 +1,7 @@
|
||||
# GKE-specific: SSD persistent disk storage class
|
||||
persistence:
|
||||
storageClass: premium-rwo
|
||||
postgresql:
|
||||
primary:
|
||||
persistence:
|
||||
storageClass: premium-rwo
|
||||
4
infra/values/gke-dev/grafana-values.yaml
Normal file
4
infra/values/gke-dev/grafana-values.yaml
Normal file
@@ -0,0 +1,4 @@
|
||||
# GKE-specific: Grafana hostname
|
||||
ingress:
|
||||
hosts:
|
||||
- grafana.forteapps.net
|
||||
3
infra/values/gke-dev/keycloak-values.yaml
Normal file
3
infra/values/gke-dev/keycloak-values.yaml
Normal file
@@ -0,0 +1,3 @@
|
||||
# GKE-specific: Keycloak hostname
|
||||
ingress:
|
||||
hostname: id.forteapps.net
|
||||
10
infra/values/gke-dev/opencost-values.yaml
Normal file
10
infra/values/gke-dev/opencost-values.yaml
Normal file
@@ -0,0 +1,10 @@
|
||||
# GKE-specific: GCP pricing via BigQuery billing export
|
||||
opencost:
|
||||
exporter:
|
||||
cloudProviderApiKey: ""
|
||||
customPricing:
|
||||
enabled: false
|
||||
google:
|
||||
key: ""
|
||||
project_id: ""
|
||||
billing_account: ""
|
||||
12
infra/values/gke-dev/traefik-values.yaml
Normal file
12
infra/values/gke-dev/traefik-values.yaml
Normal file
@@ -0,0 +1,12 @@
|
||||
# GKE-specific: Google Cloud Load Balancer for Traefik
|
||||
service:
|
||||
annotations:
|
||||
cloud.google.com/neg: '{"ingress":true}'
|
||||
networking.gke.io/load-balancer-type: External
|
||||
ports:
|
||||
web:
|
||||
forwardedHeaders:
|
||||
trustedIPs: "10.0.0.0/8"
|
||||
websecure:
|
||||
forwardedHeaders:
|
||||
trustedIPs: "10.0.0.0/8"
|
||||
7
infra/values/gke-prod/gitea-values.yaml
Normal file
7
infra/values/gke-prod/gitea-values.yaml
Normal file
@@ -0,0 +1,7 @@
|
||||
# GKE-specific: SSD persistent disk storage class (prod)
|
||||
persistence:
|
||||
storageClass: premium-rwo
|
||||
postgresql:
|
||||
primary:
|
||||
persistence:
|
||||
storageClass: premium-rwo
|
||||
4
infra/values/gke-prod/grafana-values.yaml
Normal file
4
infra/values/gke-prod/grafana-values.yaml
Normal file
@@ -0,0 +1,4 @@
|
||||
# GKE-specific: Grafana hostname (prod)
|
||||
ingress:
|
||||
hosts:
|
||||
- grafana.fortedigital.com
|
||||
3
infra/values/gke-prod/keycloak-values.yaml
Normal file
3
infra/values/gke-prod/keycloak-values.yaml
Normal file
@@ -0,0 +1,3 @@
|
||||
# GKE-specific: Keycloak hostname (prod)
|
||||
ingress:
|
||||
hostname: id.fortedigital.com
|
||||
10
infra/values/gke-prod/opencost-values.yaml
Normal file
10
infra/values/gke-prod/opencost-values.yaml
Normal file
@@ -0,0 +1,10 @@
|
||||
# GKE-specific: GCP pricing via BigQuery billing export (prod)
|
||||
opencost:
|
||||
exporter:
|
||||
cloudProviderApiKey: ""
|
||||
customPricing:
|
||||
enabled: false
|
||||
google:
|
||||
key: ""
|
||||
project_id: ""
|
||||
billing_account: ""
|
||||
12
infra/values/gke-prod/traefik-values.yaml
Normal file
12
infra/values/gke-prod/traefik-values.yaml
Normal file
@@ -0,0 +1,12 @@
|
||||
# GKE-specific: Google Cloud Load Balancer for Traefik (prod)
|
||||
service:
|
||||
annotations:
|
||||
cloud.google.com/neg: '{"ingress":true}'
|
||||
networking.gke.io/load-balancer-type: External
|
||||
ports:
|
||||
web:
|
||||
forwardedHeaders:
|
||||
trustedIPs: "10.0.0.0/8"
|
||||
websecure:
|
||||
forwardedHeaders:
|
||||
trustedIPs: "10.0.0.0/8"
|
||||
7
infra/values/upc-dev/gitea-values.yaml
Normal file
7
infra/values/upc-dev/gitea-values.yaml
Normal file
@@ -0,0 +1,7 @@
|
||||
# UpCloud-specific: block storage class for Gitea + PostgreSQL
|
||||
persistence:
|
||||
storageClass: upcloud-block-storage-maxiops
|
||||
postgresql:
|
||||
primary:
|
||||
persistence:
|
||||
storageClass: upcloud-block-storage-maxiops
|
||||
15
infra/values/upc-dev/opencost-values.yaml
Normal file
15
infra/values/upc-dev/opencost-values.yaml
Normal file
@@ -0,0 +1,15 @@
|
||||
# UpCloud-specific: custom pricing model
|
||||
opencost:
|
||||
exporter:
|
||||
customPricing:
|
||||
enabled: true
|
||||
provider: custom
|
||||
costModel:
|
||||
description: "UpCloud 4-node cluster pricing"
|
||||
CPU: "5.86"
|
||||
RAM: "1.46"
|
||||
GPU: "0"
|
||||
storage: "0.34"
|
||||
zoneNetworkEgress: "0"
|
||||
regionNetworkEgress: "0"
|
||||
internetNetworkEgress: "0"
|
||||
7
infra/values/upc-prod/gitea-values.yaml
Normal file
7
infra/values/upc-prod/gitea-values.yaml
Normal file
@@ -0,0 +1,7 @@
|
||||
# UpCloud-specific: block storage class for Gitea + PostgreSQL
|
||||
persistence:
|
||||
storageClass: upcloud-block-storage-maxiops
|
||||
postgresql:
|
||||
primary:
|
||||
persistence:
|
||||
storageClass: upcloud-block-storage-maxiops
|
||||
15
infra/values/upc-prod/opencost-values.yaml
Normal file
15
infra/values/upc-prod/opencost-values.yaml
Normal file
@@ -0,0 +1,15 @@
|
||||
# UpCloud-specific: custom pricing model
|
||||
opencost:
|
||||
exporter:
|
||||
customPricing:
|
||||
enabled: true
|
||||
provider: custom
|
||||
costModel:
|
||||
description: "UpCloud 4-node cluster pricing"
|
||||
CPU: "5.86"
|
||||
RAM: "1.46"
|
||||
GPU: "0"
|
||||
storage: "0.34"
|
||||
zoneNetworkEgress: "0"
|
||||
regionNetworkEgress: "0"
|
||||
internetNetworkEgress: "0"
|
||||
23
scripts/backup/aws-s3.sh
Normal file
23
scripts/backup/aws-s3.sh
Normal file
@@ -0,0 +1,23 @@
|
||||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
# AWS S3 backup upload (native AWS CLI)
|
||||
# Uses: aws cli v2
|
||||
# Env: AWS_ACCESS_KEY_ID, AWS_SECRET_ACCESS_KEY, AWS_DEFAULT_REGION, S3_BUCKET
|
||||
|
||||
BACKUP_FILE="${1:?Usage: $0 <backup-file>}"
|
||||
TIMESTAMP=$(date +%Y%m%d-%H%M%S)
|
||||
KEY="gitea-dump-${TIMESTAMP}.zip"
|
||||
|
||||
echo "Uploading ${KEY}..."
|
||||
aws s3 cp "$BACKUP_FILE" "s3://${S3_BUCKET}/${KEY}"
|
||||
echo "Upload complete."
|
||||
|
||||
# Prune backups older than 7 days
|
||||
echo "Pruning backups older than 7 days..."
|
||||
CUTOFF=$(date -d '7 days ago' +%Y-%m-%dT%H:%M:%S 2>/dev/null || date -v-7d +%Y-%m-%dT%H:%M:%S)
|
||||
aws s3api list-objects-v2 --bucket "${S3_BUCKET}" --query "Contents[?LastModified<'${CUTOFF}'].Key" --output text \
|
||||
| tr '\t' '\n' \
|
||||
| while read -r key; do
|
||||
[ -n "$key" ] && aws s3 rm "s3://${S3_BUCKET}/${key}" && echo "Deleted: ${key}"
|
||||
done
|
||||
echo "Pruning complete."
|
||||
36
scripts/backup/azure-blob.sh
Normal file
36
scripts/backup/azure-blob.sh
Normal file
@@ -0,0 +1,36 @@
|
||||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
# Azure Blob Storage backup upload
|
||||
# Uses: az cli
|
||||
# Env: AZURE_STORAGE_ACCOUNT, AZURE_STORAGE_KEY, AZURE_CONTAINER
|
||||
|
||||
BACKUP_FILE="${1:?Usage: $0 <backup-file>}"
|
||||
TIMESTAMP=$(date +%Y%m%d-%H%M%S)
|
||||
KEY="gitea-dump-${TIMESTAMP}.zip"
|
||||
|
||||
echo "Uploading ${KEY}..."
|
||||
az storage blob upload \
|
||||
--account-name "${AZURE_STORAGE_ACCOUNT}" \
|
||||
--account-key "${AZURE_STORAGE_KEY}" \
|
||||
--container-name "${AZURE_CONTAINER}" \
|
||||
--name "${KEY}" \
|
||||
--file "$BACKUP_FILE" \
|
||||
--overwrite
|
||||
echo "Upload complete."
|
||||
|
||||
# Prune backups older than 7 days
|
||||
echo "Pruning backups older than 7 days..."
|
||||
CUTOFF=$(date -d '7 days ago' +%Y-%m-%dT%H:%M:%SZ 2>/dev/null || date -v-7d +%Y-%m-%dT%H:%M:%SZ)
|
||||
az storage blob list \
|
||||
--account-name "${AZURE_STORAGE_ACCOUNT}" \
|
||||
--account-key "${AZURE_STORAGE_KEY}" \
|
||||
--container-name "${AZURE_CONTAINER}" \
|
||||
--query "[?properties.lastModified<'${CUTOFF}'].name" -o tsv \
|
||||
| while read -r name; do
|
||||
[ -n "$name" ] && az storage blob delete \
|
||||
--account-name "${AZURE_STORAGE_ACCOUNT}" \
|
||||
--account-key "${AZURE_STORAGE_KEY}" \
|
||||
--container-name "${AZURE_CONTAINER}" \
|
||||
--name "$name" && echo "Deleted: ${name}"
|
||||
done
|
||||
echo "Pruning complete."
|
||||
26
scripts/backup/gcp-gcs.sh
Normal file
26
scripts/backup/gcp-gcs.sh
Normal file
@@ -0,0 +1,26 @@
|
||||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
# GCP Cloud Storage backup upload
|
||||
# Uses: gsutil (gcloud SDK)
|
||||
# Env: GCS_BUCKET (e.g. gs://my-bucket)
|
||||
|
||||
BACKUP_FILE="${1:?Usage: $0 <backup-file>}"
|
||||
TIMESTAMP=$(date +%Y%m%d-%H%M%S)
|
||||
KEY="gitea-dump-${TIMESTAMP}.zip"
|
||||
|
||||
echo "Uploading ${KEY}..."
|
||||
gsutil cp "$BACKUP_FILE" "${GCS_BUCKET}/${KEY}"
|
||||
echo "Upload complete."
|
||||
|
||||
# Prune backups older than 7 days — GCS lifecycle rules are preferred,
|
||||
# but this works as a manual fallback
|
||||
echo "Pruning backups older than 7 days..."
|
||||
CUTOFF=$(date -d '7 days ago' +%Y-%m-%dT%H:%M:%SZ 2>/dev/null || date -v-7d +%Y-%m-%dT%H:%M:%SZ)
|
||||
gsutil ls -l "${GCS_BUCKET}/" \
|
||||
| grep 'gitea-dump-' \
|
||||
| while read -r size date name; do
|
||||
if [[ "$date" < "$CUTOFF" ]]; then
|
||||
gsutil rm "$name" && echo "Deleted: ${name}"
|
||||
fi
|
||||
done
|
||||
echo "Pruning complete."
|
||||
20
scripts/backup/s3-minio.sh
Normal file
20
scripts/backup/s3-minio.sh
Normal file
@@ -0,0 +1,20 @@
|
||||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
# S3-compatible backup upload (UpCloud Objects, MinIO, Wasabi, etc.)
|
||||
# Uses: minio/mc
|
||||
# Env: S3_ENDPOINT, AWS_ACCESS_KEY_ID, AWS_SECRET_ACCESS_KEY, S3_BUCKET
|
||||
|
||||
BACKUP_FILE="${1:?Usage: $0 <backup-file>}"
|
||||
TIMESTAMP=$(date +%Y%m%d-%H%M%S)
|
||||
KEY="gitea-dump-${TIMESTAMP}.zip"
|
||||
|
||||
mc alias set s3 "${S3_ENDPOINT}" "${AWS_ACCESS_KEY_ID}" "${AWS_SECRET_ACCESS_KEY}"
|
||||
|
||||
echo "Uploading ${KEY}..."
|
||||
mc cp "$BACKUP_FILE" "s3/${S3_BUCKET}/${KEY}"
|
||||
echo "Upload complete."
|
||||
|
||||
# Prune backups older than 7 days
|
||||
echo "Pruning backups older than 7 days..."
|
||||
mc rm --older-than 7d --force "s3/${S3_BUCKET}/" 2>&1 || true
|
||||
echo "Pruning complete."
|
||||
@@ -13,7 +13,7 @@ NAMESPACE="gitea"
|
||||
SECRET="gitea-backup-s3"
|
||||
IMAGE="minio/mc:latest"
|
||||
POD_NAME="gitea-backup-helper"
|
||||
ALIAS_CMD='mc alias set upcloud ${S3_ENDPOINT} ${AWS_ACCESS_KEY_ID} ${AWS_SECRET_ACCESS_KEY} > /dev/null'
|
||||
ALIAS_CMD='mc alias set s3 ${S3_ENDPOINT} ${AWS_ACCESS_KEY_ID} ${AWS_SECRET_ACCESS_KEY} > /dev/null'
|
||||
|
||||
cleanup() {
|
||||
kubectl -n "$NAMESPACE" delete pod "$POD_NAME" --ignore-not-found --grace-period=0 > /dev/null 2>&1 || true
|
||||
@@ -41,7 +41,7 @@ mc_run() {
|
||||
case "${1:-help}" in
|
||||
list)
|
||||
echo "Listing backups..."
|
||||
mc_run 'mc ls upcloud/${S3_BUCKET}/'
|
||||
mc_run 'mc ls s3/${S3_BUCKET}/'
|
||||
;;
|
||||
|
||||
download)
|
||||
@@ -49,7 +49,7 @@ case "${1:-help}" in
|
||||
|
||||
if [ "$FILE" = "latest" ]; then
|
||||
echo "Finding latest backup..."
|
||||
FILE=$(mc_run 'mc ls upcloud/${S3_BUCKET}/' | sort | tail -1 | awk '{print $NF}' | tr -d '[:space:]')
|
||||
FILE=$(mc_run 'mc ls s3/${S3_BUCKET}/' | sort | tail -1 | awk '{print $NF}' | tr -d '[:space:]')
|
||||
if [ -z "$FILE" ]; then
|
||||
echo "No backups found."
|
||||
exit 1
|
||||
@@ -74,7 +74,7 @@ case "${1:-help}" in
|
||||
kubectl -n "$NAMESPACE" wait --for=condition=Ready "pod/$POD_NAME" --timeout=60s > /dev/null 2>&1
|
||||
|
||||
echo "Saving to ./$FILE ..."
|
||||
kubectl -n "$NAMESPACE" exec "$POD_NAME" -- sh -c "${ALIAS_CMD} && mc cat upcloud/\${S3_BUCKET}/$FILE" > "./$FILE"
|
||||
kubectl -n "$NAMESPACE" exec "$POD_NAME" -- sh -c "${ALIAS_CMD} && mc cat s3/\${S3_BUCKET}/$FILE" > "./$FILE"
|
||||
cleanup
|
||||
|
||||
echo "Downloaded: ./$FILE"
|
||||
|
||||
Reference in New Issue
Block a user