add infrastructure manifests

This commit is contained in:
stackops
2026-04-09 13:26:46 +03:00
parent f896fa3d3e
commit 7fe1376fe6
10 changed files with 358 additions and 0 deletions

View File

@@ -0,0 +1,16 @@
#!/usr/bin/env bash
set -euo pipefail
# Load credentials
source "$(dirname "$0")/../../.cloudflare"
IP="82.114.226.118"
for name in "@" "app" "git" "grafana" "prom" "*.app"; do
echo "Creating DNS record: $name -> $IP"
curl -s -X POST "https://api.cloudflare.com/client/v4/zones/${CF_ZONE_ID}/dns_records" \
-H "Authorization: Bearer ${CF_API_TOKEN}" \
-H "Content-Type: application/json" \
--data "{\"type\":\"A\",\"name\":\"${name}\",\"content\":\"${IP}\",\"ttl\":1,\"proxied\":false}" \
| python3 -c "import sys,json; r=json.load(sys.stdin); print(' OK' if r['success'] else f' FAIL: {r[\"errors\"]}')"
done

16
01-k3s/install.sh Normal file
View File

@@ -0,0 +1,16 @@
#!/usr/bin/env bash
set -euo pipefail
VPS="root@82.114.226.118"
echo "Installing prerequisites..."
ssh $VPS 'apt-get update -qq && apt-get install -y -qq curl'
echo "Installing k3s (traefik disabled)..."
ssh $VPS 'curl -sfL https://get.k3s.io | INSTALL_K3S_EXEC="--disable=traefik" sh -'
echo "Copying kubeconfig..."
mkdir -p ~/.kube
ssh $VPS 'cat /etc/rancher/k3s/k3s.yaml' | sed 's/127.0.0.1/82.114.226.118/' > ~/.kube/config-nodeup
echo "Done. Use: export KUBECONFIG=~/.kube/config-nodeup"

View File

@@ -0,0 +1,14 @@
apiVersion: cert-manager.io/v1
kind: ClusterIssuer
metadata:
name: letsencrypt-prod
spec:
acme:
server: https://acme-v02.api.letsencrypt.org/directory
email: admin@nodeup.ru
privateKeySecretRef:
name: letsencrypt-prod-key
solvers:
- http01:
ingress:
class: nginx

44
04-gitea/values.yaml Normal file
View File

@@ -0,0 +1,44 @@
gitea:
admin:
username: stackops
password: stackops-admin-2026
config:
server:
DOMAIN: git.nodeup.ru
ROOT_URL: https://git.nodeup.ru
SSH_DOMAIN: git.nodeup.ru
database:
DB_TYPE: sqlite3
session:
PROVIDER: memory
cache:
ADAPTER: memory
queue:
TYPE: level
packages:
ENABLED: true
persistence:
enabled: true
size: 10Gi
storageClass: local-path
ingress:
enabled: true
className: nginx
annotations:
cert-manager.io/cluster-issuer: letsencrypt-prod
hosts:
- host: git.nodeup.ru
paths:
- path: /
pathType: Prefix
tls:
- secretName: gitea-tls
hosts:
- git.nodeup.ru
postgresql-ha:
enabled: false
redis-cluster:
enabled: false

View File

@@ -0,0 +1,11 @@
loki:
persistence:
enabled: true
storageClassName: local-path
size: 10Gi
config:
limits_config:
retention_period: 168h
promtail:
enabled: true

View File

@@ -0,0 +1,34 @@
grafana:
adminPassword: stackops-grafana-2026
ingress:
enabled: true
ingressClassName: nginx
annotations:
cert-manager.io/cluster-issuer: letsencrypt-prod
hosts:
- grafana.nodeup.ru
tls:
- secretName: grafana-tls
hosts:
- grafana.nodeup.ru
prometheus:
prometheusSpec:
retention: 15d
storageSpec:
volumeClaimTemplate:
spec:
storageClassName: local-path
resources:
requests:
storage: 20Gi
resources:
requests:
cpu: 100m
memory: 512Mi
limits:
cpu: 1000m
memory: 1Gi
alertmanager:
enabled: false

View File

@@ -0,0 +1,87 @@
apiVersion: apps/v1
kind: Deployment
metadata:
name: stackops-api
namespace: stackops
spec:
replicas: 1
selector:
matchLabels:
app: stackops-api
template:
metadata:
labels:
app: stackops-api
spec:
serviceAccountName: stackops-api
containers:
- name: api
image: stackops-api:v1
imagePullPolicy: IfNotPresent
ports:
- containerPort: 8080
env:
- name: PORT
value: "8080"
- name: STACKOPS_API_TOKEN
valueFrom:
secretKeyRef:
name: stackops-secrets
key: api-token
- name: DB_PATH
value: /data/stackops.db
volumeMounts:
- name: data
mountPath: /data
livenessProbe:
httpGet:
path: /
port: 8080
initialDelaySeconds: 5
resources:
requests:
cpu: 100m
memory: 128Mi
limits:
cpu: 500m
memory: 256Mi
volumes:
- name: data
persistentVolumeClaim:
claimName: stackops-data
---
apiVersion: v1
kind: Service
metadata:
name: stackops-api
namespace: stackops
spec:
selector:
app: stackops-api
ports:
- port: 8080
targetPort: 8080
---
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: stackops-api
namespace: stackops
annotations:
cert-manager.io/cluster-issuer: letsencrypt-prod
spec:
ingressClassName: nginx
tls:
- hosts: [app.nodeup.ru]
secretName: stackops-tls
rules:
- host: app.nodeup.ru
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: stackops-api
port:
number: 8080

44
06-stackops/rbac.yaml Normal file
View File

@@ -0,0 +1,44 @@
apiVersion: v1
kind: Namespace
metadata:
name: stackops
---
apiVersion: v1
kind: ServiceAccount
metadata:
name: stackops-api
namespace: stackops
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
name: stackops-deployer
rules:
- apiGroups: ["*"]
resources: ["*"]
verbs: ["*"]
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
name: stackops-deployer
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
name: stackops-deployer
subjects:
- kind: ServiceAccount
name: stackops-api
namespace: stackops
---
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: stackops-data
namespace: stackops
spec:
accessModes: [ReadWriteOnce]
storageClassName: local-path
resources:
requests:
storage: 1Gi

View File

@@ -0,0 +1,14 @@
[app]
name = "whoami"
image = "traefik/whoami:latest"
replicas = 1
port = 80
[ingress]
host = "whoami.app.nodeup.ru"
path = "/"
tls = true
[dependencies.postgres]
version = "15"
storage = "1Gi"

78
Makefile Normal file
View File

@@ -0,0 +1,78 @@
KUBECONFIG ?= $(HOME)/.kube/config-nodeup
export KUBECONFIG
.PHONY: all dns k3s core kubevela gitea monitoring stackops test-app
all: dns k3s core kubevela gitea monitoring stackops test-app
dns:
bash 00-dns/cloudflare-records.sh
k3s:
bash 01-k3s/install.sh
core: nginx-ingress cert-manager clusterissuer
nginx-ingress:
helm upgrade --install ingress-nginx ingress-nginx/ingress-nginx \
--namespace ingress-nginx --create-namespace \
--set controller.service.type=LoadBalancer \
--set controller.kind=DaemonSet \
--set controller.hostPort.enabled=true \
--set controller.service.externalTrafficPolicy=Local \
--timeout 10m --wait
cert-manager:
helm upgrade --install cert-manager jetstack/cert-manager \
--namespace cert-manager --create-namespace \
--set crds.enabled=true \
--timeout 10m --wait
clusterissuer:
@source ../../.cloudflare && \
sed "s|\$${CF_API_TOKEN}|$$CF_API_TOKEN|g" 02-core/clusterissuer.yaml | \
kubectl apply -f -
kubevela:
helm upgrade --install kubevela kubevela/vela-core \
--namespace vela-system --create-namespace \
--timeout 8m --wait
kubectl apply --server-side \
-f https://raw.githubusercontent.com/cloudnative-pg/cloudnative-pg/release-1.23/releases/cnpg-1.23.0.yaml
helm upgrade --install redis-operator ot-helm/redis-operator \
--namespace redis-operator --create-namespace --wait
kubectl apply -f ../kubevela/components/
gitea:
helm repo add gitea-charts https://dl.gitea.com/charts/ || true
helm repo update gitea-charts
helm upgrade --install gitea gitea-charts/gitea \
--namespace gitea --create-namespace \
-f 04-gitea/values.yaml \
--timeout 10m --wait
monitoring:
helm repo add prometheus-community https://prometheus-community.github.io/helm-charts || true
helm repo add grafana https://grafana.github.io/helm-charts || true
helm repo update prometheus-community grafana
helm upgrade --install monitoring prometheus-community/kube-prometheus-stack \
--namespace monitoring --create-namespace \
-f 05-monitoring/values-prometheus.yaml \
--timeout 10m --wait
helm upgrade --install loki grafana/loki-stack \
--namespace monitoring \
-f 05-monitoring/values-loki.yaml \
--timeout 5m --wait
stackops:
kubectl apply -f 06-stackops/rbac.yaml
kubectl create secret generic stackops-secrets \
--namespace stackops \
--from-literal=api-token=dev-secret-token \
--dry-run=client -o yaml | kubectl apply -f -
kubectl apply -f 06-stackops/deployment.yaml
test-app:
@echo "Deploy test app via StackOps API or manually:"
@echo " cd ../toml-converter && go run ./cmd/main.go -f ../infra/07-test-app/stackfile.toml -o /tmp/whoami.yaml"
@echo " kubectl create namespace whoami && kubectl apply -f /tmp/whoami.yaml -n whoami"