feat: SOPS + age encrypted secrets structure

- .sops.yaml with 3 age keys (admin, dev, prod)
- infra/gitea/values/*.enc.yaml — per-env encrypted Helm values
- infra/kargo/values/*.enc.yaml — per-env encrypted Kargo admin secrets
- kargo/credentials/*.enc.yaml — per-env encrypted git credentials (ksops)
- infra/kargo-credentials/ — ArgoCD app for deploying Kargo creds via ksops
- All repoURLs point to deploy-app-kargo-private

Structure from deploy-app-kargo (reference), adapted for SOPS workflow
This commit is contained in:
XoR
2026-03-11 10:01:26 +03:00
parent 720748be50
commit 4dd68859d8
60 changed files with 1444 additions and 1 deletions

View File

@@ -0,0 +1,12 @@
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
resources:
- namespace.yaml
- project.yaml
- warehouse.yaml
- stages/dev.yaml
- stages/test.yaml
- stages/prod.yaml
- verification/rbac.yaml
- verification/dev-health-check.yaml
- verification/prod-health-check.yaml

View File

@@ -0,0 +1,6 @@
apiVersion: v1
kind: Namespace
metadata:
name: infra
labels:
kargo.akuity.io/project: "true"

18
kargo/infra/project.yaml Normal file
View File

@@ -0,0 +1,18 @@
apiVersion: kargo.akuity.io/v1alpha1
kind: Project
metadata:
name: infra
---
apiVersion: kargo.akuity.io/v1alpha1
kind: ProjectConfig
metadata:
name: infra
namespace: infra
spec:
promotionPolicies:
- stageSelector: { name: dev }
autoPromotionEnabled: true
- stageSelector: { name: test }
autoPromotionEnabled: true
- stageSelector: { name: prod }
autoPromotionEnabled: true # creates PR, not direct push

View File

@@ -0,0 +1,69 @@
apiVersion: kargo.akuity.io/v1alpha1
kind: Stage
metadata:
name: dev
namespace: infra
spec:
requestedFreight:
- origin:
kind: Warehouse
name: infra-charts
sources:
direct: true
promotionTemplate:
spec:
vars:
- name: gitopsRepo
value: https://github.com/Kargones/deploy-app-kargo-private.git
- name: targetBranch
value: infra/stage/${{ ctx.stage }}
steps:
- uses: git-clone
config:
repoURL: ${{ vars.gitopsRepo }}
checkout:
- branch: main
path: ./src
- branch: ${{ vars.targetBranch }}
create: true
path: ./out
- uses: git-clear
config:
path: ./out
- uses: yaml-update
as: update-cert-manager
config:
path: ./src/infra/cert-manager/config.yaml
updates:
- key: source.targetRevision
value: ${{ chartFrom("https://charts.jetstack.io", "cert-manager").Version }}
- uses: yaml-update
as: update-argo-rollouts
config:
path: ./src/infra/argo-rollouts/config.yaml
updates:
- key: source.targetRevision
value: ${{ chartFrom("https://argoproj.github.io/argo-helm", "argo-rollouts").Version }}
- uses: yaml-update
as: update-gitea
config:
path: ./src/infra/gitea/config.yaml
updates:
- key: source.targetRevision
value: ${{ chartFrom("https://dl.gitea.com/charts", "gitea").Version }}
- uses: copy
config:
inPath: ./src/infra
outPath: ./out/infra
- uses: git-commit
as: commit
config:
path: ./out
message: "promote(infra/${{ ctx.stage }}): freight ${{ ctx.targetFreight.name }}"
- uses: git-push
config:
path: ./out
targetBranch: ${{ vars.targetBranch }}
verification:
analysisTemplates:
- name: dev-health-check

View File

@@ -0,0 +1,76 @@
apiVersion: kargo.akuity.io/v1alpha1
kind: Stage
metadata:
name: prod
namespace: infra
spec:
requestedFreight:
- origin:
kind: Warehouse
name: infra-charts
sources:
stages:
- test
promotionTemplate:
spec:
vars:
- name: gitopsRepo
value: https://github.com/Kargones/deploy-app-kargo-private.git
- name: sourceBranch
value: infra/stage/test
- name: targetBranch
value: infra/stage/prod
steps:
- uses: git-clone
config:
repoURL: ${{ vars.gitopsRepo }}
checkout:
- branch: ${{ vars.sourceBranch }}
path: ./src
- branch: ${{ vars.targetBranch }}
create: true
path: ./out
- uses: git-clear
config:
path: ./out
- uses: copy
config:
inPath: ./src/infra
outPath: ./out/infra
- uses: git-commit
as: commit
config:
path: ./out
message: "promote(infra/prod): freight ${{ ctx.targetFreight.name }}"
- uses: git-push
as: push
config:
path: ./out
generateTargetBranch: true
- uses: git-open-pr
as: open-pr
config:
repoURL: ${{ vars.gitopsRepo }}
sourceBranch: ${{ outputs.push.branch }}
targetBranch: ${{ vars.targetBranch }}
title: "promote(infra/prod): ${{ ctx.targetFreight.name }}"
description: |
## Kargo Promotion
**Freight:** ${{ ctx.targetFreight.name }}
**Project:** infra
**Stage:** prod
## Verified in
- ✅ dev (pod-health)
- ✅ test (pod-health)
## Review
Check the diff below for version changes.
Verify changelogs before merging.
- uses: git-wait-for-pr
config:
repoURL: ${{ vars.gitopsRepo }}
prNumber: ${{ outputs['open-pr'].pr.id }}
verification:
analysisTemplates:
- name: prod-health-check

View File

@@ -0,0 +1,51 @@
apiVersion: kargo.akuity.io/v1alpha1
kind: Stage
metadata:
name: test
namespace: infra
spec:
requestedFreight:
- origin:
kind: Warehouse
name: infra-charts
sources:
stages:
- dev
promotionTemplate:
spec:
vars:
- name: gitopsRepo
value: https://github.com/Kargones/deploy-app-kargo-private.git
- name: sourceBranch
value: infra/stage/dev
- name: targetBranch
value: infra/stage/${{ ctx.stage }}
steps:
- uses: git-clone
config:
repoURL: ${{ vars.gitopsRepo }}
checkout:
- branch: ${{ vars.sourceBranch }}
path: ./src
- branch: ${{ vars.targetBranch }}
create: true
path: ./out
- uses: git-clear
config:
path: ./out
- uses: copy
config:
inPath: ./src/infra
outPath: ./out/infra
- uses: git-commit
as: commit
config:
path: ./out
message: "promote(infra/${{ ctx.stage }}): freight ${{ ctx.targetFreight.name }}"
- uses: git-push
config:
path: ./out
targetBranch: ${{ vars.targetBranch }}
verification:
analysisTemplates:
- name: dev-health-check

View File

@@ -0,0 +1,37 @@
apiVersion: argoproj.io/v1alpha1
kind: AnalysisTemplate
metadata:
name: dev-health-check
namespace: infra
spec:
metrics:
- name: pod-health
successCondition: result == "healthy"
provider:
job:
spec:
template:
spec:
serviceAccountName: kargo-verifier
containers:
- name: check
image: alpine/k8s:1.35.1
command: [sh, -c]
args:
- |
set -e
echo "Checking pod health..."
cm=$(kubectl get pods -n cert-manager --no-headers 2>/dev/null | grep -c Running || echo 0)
echo "cert-manager running pods: $cm"
ar=$(kubectl get pods -n argo-rollouts --no-headers 2>/dev/null | grep -c Running || echo 0)
echo "argo-rollouts running pods: $ar"
gt=$(kubectl get pods -n gitea --no-headers 2>/dev/null | grep -c Running || echo 0)
echo "gitea running pods: $gt"
if [ "$cm" -ge 1 ] && [ "$ar" -ge 1 ] && [ "$gt" -ge 1 ]; then
echo "healthy"
else
echo "unhealthy"
exit 1
fi
restartPolicy: Never
backoffLimit: 2

View File

@@ -0,0 +1,37 @@
apiVersion: argoproj.io/v1alpha1
kind: AnalysisTemplate
metadata:
name: prod-health-check
namespace: infra
spec:
metrics:
- name: pod-health
successCondition: result == "healthy"
provider:
job:
spec:
template:
spec:
serviceAccountName: kargo-verifier
containers:
- name: check
image: alpine/k8s:1.35.1
command: [sh, -c]
args:
- |
set -e
echo "Checking pod health..."
cm=$(kubectl get pods -n cert-manager --no-headers 2>/dev/null | grep -c Running || echo 0)
echo "cert-manager running pods: $cm"
ar=$(kubectl get pods -n argo-rollouts --no-headers 2>/dev/null | grep -c Running || echo 0)
echo "argo-rollouts running pods: $ar"
gt=$(kubectl get pods -n gitea --no-headers 2>/dev/null | grep -c Running || echo 0)
echo "gitea running pods: $gt"
if [ "$cm" -ge 1 ] && [ "$ar" -ge 1 ] && [ "$gt" -ge 1 ]; then
echo "healthy"
else
echo "unhealthy"
exit 1
fi
restartPolicy: Never
backoffLimit: 2

View File

@@ -0,0 +1,27 @@
apiVersion: v1
kind: ServiceAccount
metadata:
name: kargo-verifier
namespace: infra
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
name: kargo-verifier-infra
rules:
- apiGroups: [""]
resources: ["pods"]
verbs: ["get", "list"]
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
name: kargo-verifier-infra
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
name: kargo-verifier-infra
subjects:
- kind: ServiceAccount
name: kargo-verifier
namespace: infra

View File

@@ -0,0 +1,22 @@
apiVersion: kargo.akuity.io/v1alpha1
kind: Warehouse
metadata:
name: infra-charts
namespace: infra
spec:
subscriptions:
- chart:
repoURL: https://charts.jetstack.io
name: cert-manager
semverConstraint: ">=1.17.0"
discoveryLimit: 5
- chart:
repoURL: https://argoproj.github.io/argo-helm
name: argo-rollouts
semverConstraint: ">=2.39.0"
discoveryLimit: 5
- chart:
repoURL: https://dl.gitea.com/charts
name: gitea
semverConstraint: ">=10.6.0"
discoveryLimit: 5