first commit
This commit is contained in:
21
.gitignore
vendored
Normal file
21
.gitignore
vendored
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
# Secrets - never commit these
|
||||||
|
*.secret.yaml
|
||||||
|
*.secret.yml
|
||||||
|
secrets/
|
||||||
|
*.pem
|
||||||
|
*.key
|
||||||
|
|
||||||
|
# Local overrides
|
||||||
|
values.local.yaml
|
||||||
|
*.local.yaml
|
||||||
|
|
||||||
|
# Editor files
|
||||||
|
*.swp
|
||||||
|
*.swo
|
||||||
|
*~
|
||||||
|
.idea/
|
||||||
|
.vscode/
|
||||||
|
|
||||||
|
# OS files
|
||||||
|
.DS_Store
|
||||||
|
Thumbs.db
|
||||||
58
README.md
Normal file
58
README.md
Normal file
@@ -0,0 +1,58 @@
|
|||||||
|
# Kubernetes Configuration
|
||||||
|
|
||||||
|
Cluster configuration for the roamflow k3s cluster.
|
||||||
|
|
||||||
|
## Structure
|
||||||
|
|
||||||
|
```
|
||||||
|
kube-config/
|
||||||
|
├── apps/ # Application deployments
|
||||||
|
│ ├── headlamp/ # Kubernetes dashboard
|
||||||
|
│ └── ...
|
||||||
|
├── infrastructure/ # Cluster infrastructure
|
||||||
|
│ └── ...
|
||||||
|
└── scripts/ # Deployment scripts
|
||||||
|
└── deploy.sh
|
||||||
|
```
|
||||||
|
|
||||||
|
## Usage
|
||||||
|
|
||||||
|
### Deploy a specific app
|
||||||
|
```bash
|
||||||
|
./scripts/deploy.sh headlamp
|
||||||
|
```
|
||||||
|
|
||||||
|
### Deploy all apps
|
||||||
|
```bash
|
||||||
|
./scripts/deploy.sh --all
|
||||||
|
```
|
||||||
|
|
||||||
|
## Cluster Access
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Start SSH tunnel
|
||||||
|
ssh -f -N -L 6443:127.0.0.1:6443 roamflow-1
|
||||||
|
|
||||||
|
# Use kubectl
|
||||||
|
KUBECONFIG=~/.kube/config-roamflow kubectl get pods -A
|
||||||
|
```
|
||||||
|
|
||||||
|
## Apps
|
||||||
|
|
||||||
|
| App | Namespace | Description | URL |
|
||||||
|
|-----|-----------|-------------|-----|
|
||||||
|
| headlamp | headlamp | Kubernetes dashboard | headlamp.duylai.duckdns.org |
|
||||||
|
| gitea | gitea | Git hosting | gitea.duylai.duckdns.org |
|
||||||
|
| vikunja | vikunja | Task management | tasks.duylai.duckdns.org |
|
||||||
|
|
||||||
|
## Memory Configuration
|
||||||
|
|
||||||
|
The following memory limits have been adjusted to prevent OOM kills:
|
||||||
|
|
||||||
|
| Service | Limit | Request |
|
||||||
|
|---------|-------|---------|
|
||||||
|
| PostgreSQL (per pod) | 768Mi | 512Mi |
|
||||||
|
| Pgpool | 512Mi | 384Mi |
|
||||||
|
| Valkey | 192Mi | 128Mi |
|
||||||
|
|
||||||
|
These are saved in `apps/gitea/values.yaml` for future upgrades.
|
||||||
24
apps/gitea/ingress.yaml
Normal file
24
apps/gitea/ingress.yaml
Normal file
@@ -0,0 +1,24 @@
|
|||||||
|
apiVersion: networking.k8s.io/v1
|
||||||
|
kind: Ingress
|
||||||
|
metadata:
|
||||||
|
name: gitea-ingress
|
||||||
|
namespace: gitea
|
||||||
|
annotations:
|
||||||
|
kubernetes.io/ingress.class: traefik
|
||||||
|
cert-manager.io/cluster-issuer: letsencrypt-prod
|
||||||
|
spec:
|
||||||
|
rules:
|
||||||
|
- host: gitea.duylai.duckdns.org
|
||||||
|
http:
|
||||||
|
paths:
|
||||||
|
- path: /
|
||||||
|
pathType: Prefix
|
||||||
|
backend:
|
||||||
|
service:
|
||||||
|
name: gitea-http
|
||||||
|
port:
|
||||||
|
number: 3000
|
||||||
|
tls:
|
||||||
|
- hosts:
|
||||||
|
- gitea.duylai.duckdns.org
|
||||||
|
secretName: gitea-tls-secret
|
||||||
12
apps/gitea/kustomization.yaml
Normal file
12
apps/gitea/kustomization.yaml
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
apiVersion: kustomize.config.k8s.io/v1beta1
|
||||||
|
kind: Kustomization
|
||||||
|
|
||||||
|
namespace: gitea
|
||||||
|
|
||||||
|
resources:
|
||||||
|
- namespace.yaml
|
||||||
|
- ingress.yaml
|
||||||
|
|
||||||
|
# Helm values are in values.yaml
|
||||||
|
# Deploy with:
|
||||||
|
# helm upgrade --install gitea gitea-charts/gitea -f values.yaml -n gitea --create-namespace
|
||||||
6
apps/gitea/namespace.yaml
Normal file
6
apps/gitea/namespace.yaml
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
apiVersion: v1
|
||||||
|
kind: Namespace
|
||||||
|
metadata:
|
||||||
|
name: gitea
|
||||||
|
labels:
|
||||||
|
name: gitea
|
||||||
83
apps/gitea/values.yaml
Normal file
83
apps/gitea/values.yaml
Normal file
@@ -0,0 +1,83 @@
|
|||||||
|
# Gitea Helm Values
|
||||||
|
# Reference: https://gitea.com/gitea/helm-chart/
|
||||||
|
|
||||||
|
# Gitea server configuration
|
||||||
|
gitea:
|
||||||
|
config:
|
||||||
|
server:
|
||||||
|
DOMAIN: gitea.duylai.duckdns.org
|
||||||
|
ROOT_URL: https://gitea.duylai.duckdns.org/
|
||||||
|
SSH_DOMAIN: gitea.duylai.duckdns.org
|
||||||
|
SSH_LISTEN_PORT: 22
|
||||||
|
SSH_PORT: 30222
|
||||||
|
|
||||||
|
# Service configuration
|
||||||
|
service:
|
||||||
|
http:
|
||||||
|
type: ClusterIP
|
||||||
|
clusterIP: ""
|
||||||
|
ssh:
|
||||||
|
type: NodePort
|
||||||
|
nodePort: 30222
|
||||||
|
|
||||||
|
# Persistence for Git data
|
||||||
|
persistence:
|
||||||
|
enabled: true
|
||||||
|
create: true
|
||||||
|
claimName: gitea-shared-storage
|
||||||
|
size: 10Gi
|
||||||
|
accessModes:
|
||||||
|
- ReadWriteOnce
|
||||||
|
annotations:
|
||||||
|
helm.sh/resource-policy: keep
|
||||||
|
|
||||||
|
# PostgreSQL HA configuration
|
||||||
|
postgresql-ha:
|
||||||
|
enabled: true
|
||||||
|
|
||||||
|
postgresql:
|
||||||
|
# Number of PostgreSQL replicas (minimum 3 for HA)
|
||||||
|
replicaCount: 3
|
||||||
|
|
||||||
|
# Resource limits (fixed for OOM issues)
|
||||||
|
resources:
|
||||||
|
limits:
|
||||||
|
cpu: 375m
|
||||||
|
memory: 768Mi
|
||||||
|
requests:
|
||||||
|
cpu: 250m
|
||||||
|
memory: 512Mi
|
||||||
|
|
||||||
|
persistence:
|
||||||
|
size: 10Gi
|
||||||
|
|
||||||
|
pgpool:
|
||||||
|
enabled: true
|
||||||
|
|
||||||
|
# Resource limits (fixed for OOM issues)
|
||||||
|
resources:
|
||||||
|
limits:
|
||||||
|
cpu: 375m
|
||||||
|
memory: 512Mi
|
||||||
|
requests:
|
||||||
|
cpu: 250m
|
||||||
|
memory: 384Mi
|
||||||
|
|
||||||
|
# Valkey (Redis) cluster configuration
|
||||||
|
valkey-cluster:
|
||||||
|
cluster:
|
||||||
|
# Number of nodes (minimum 3 for cluster)
|
||||||
|
nodes: 3
|
||||||
|
|
||||||
|
# Resource limits
|
||||||
|
resources:
|
||||||
|
limits:
|
||||||
|
cpu: 150m
|
||||||
|
memory: 192Mi
|
||||||
|
requests:
|
||||||
|
cpu: 100m
|
||||||
|
memory: 128Mi
|
||||||
|
|
||||||
|
# Disable single PostgreSQL (using HA version)
|
||||||
|
postgresql:
|
||||||
|
enabled: false
|
||||||
26
apps/headlamp/ingress.yaml
Normal file
26
apps/headlamp/ingress.yaml
Normal file
@@ -0,0 +1,26 @@
|
|||||||
|
apiVersion: networking.k8s.io/v1
|
||||||
|
kind: Ingress
|
||||||
|
metadata:
|
||||||
|
name: headlamp-ingress
|
||||||
|
namespace: headlamp
|
||||||
|
annotations:
|
||||||
|
kubernetes.io/ingress.class: traefik
|
||||||
|
cert-manager.io/cluster-issuer: letsencrypt-prod
|
||||||
|
traefik.ingress.kubernetes.io/router.entrypoints: websecure
|
||||||
|
traefik.ingress.kubernetes.io/router.tls: "true"
|
||||||
|
spec:
|
||||||
|
rules:
|
||||||
|
- host: headlamp.duylai.duckdns.org
|
||||||
|
http:
|
||||||
|
paths:
|
||||||
|
- path: /
|
||||||
|
pathType: Prefix
|
||||||
|
backend:
|
||||||
|
service:
|
||||||
|
name: headlamp
|
||||||
|
port:
|
||||||
|
number: 80
|
||||||
|
tls:
|
||||||
|
- hosts:
|
||||||
|
- headlamp.duylai.duckdns.org
|
||||||
|
secretName: headlamp-tls
|
||||||
11
apps/headlamp/kustomization.yaml
Normal file
11
apps/headlamp/kustomization.yaml
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
apiVersion: kustomize.config.k8s.io/v1beta1
|
||||||
|
kind: Kustomization
|
||||||
|
|
||||||
|
namespace: headlamp
|
||||||
|
|
||||||
|
resources:
|
||||||
|
- namespace.yaml
|
||||||
|
- ingress.yaml
|
||||||
|
|
||||||
|
# Helm values are in values.yaml
|
||||||
|
# Use: helm upgrade --install headlamp headlamp/headlamp -f values.yaml -n headlamp
|
||||||
6
apps/headlamp/namespace.yaml
Normal file
6
apps/headlamp/namespace.yaml
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
apiVersion: v1
|
||||||
|
kind: Namespace
|
||||||
|
metadata:
|
||||||
|
name: headlamp
|
||||||
|
labels:
|
||||||
|
name: headlamp
|
||||||
43
apps/headlamp/values.yaml
Normal file
43
apps/headlamp/values.yaml
Normal file
@@ -0,0 +1,43 @@
|
|||||||
|
# Headlamp Helm Values
|
||||||
|
# Reference: https://artifacthub.io/packages/helm/headlamp/headlamp
|
||||||
|
|
||||||
|
replicaCount: 1
|
||||||
|
|
||||||
|
image:
|
||||||
|
repository: ghcr.io/headlamp-k8s/headlamp
|
||||||
|
tag: ""
|
||||||
|
pullPolicy: IfNotPresent
|
||||||
|
|
||||||
|
# Service configuration
|
||||||
|
service:
|
||||||
|
type: ClusterIP
|
||||||
|
port: 80
|
||||||
|
|
||||||
|
# Ingress managed via kustomize (see ingress.yaml)
|
||||||
|
ingress:
|
||||||
|
enabled: false
|
||||||
|
|
||||||
|
# Resources
|
||||||
|
resources:
|
||||||
|
limits:
|
||||||
|
cpu: 200m
|
||||||
|
memory: 256Mi
|
||||||
|
requests:
|
||||||
|
cpu: 100m
|
||||||
|
memory: 128Mi
|
||||||
|
|
||||||
|
# Persistent volume for plugins
|
||||||
|
persistentVolumeClaim:
|
||||||
|
enabled: false
|
||||||
|
|
||||||
|
# Service account for cluster access
|
||||||
|
serviceAccount:
|
||||||
|
create: true
|
||||||
|
annotations: {}
|
||||||
|
|
||||||
|
# RBAC - give Headlamp full cluster access
|
||||||
|
rbac:
|
||||||
|
create: true
|
||||||
|
clusterRole:
|
||||||
|
create: true
|
||||||
|
name: cluster-admin
|
||||||
122
scripts/deploy.sh
Executable file
122
scripts/deploy.sh
Executable file
@@ -0,0 +1,122 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
# Deploy applications to the Kubernetes cluster
|
||||||
|
|
||||||
|
set -e
|
||||||
|
|
||||||
|
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||||
|
PROJECT_ROOT="$(dirname "$SCRIPT_DIR")"
|
||||||
|
KUBECONFIG="${KUBECONFIG:-$HOME/.kube/config-roamflow}"
|
||||||
|
|
||||||
|
# Colors for output
|
||||||
|
RED='\033[0;31m'
|
||||||
|
GREEN='\033[0;32m'
|
||||||
|
YELLOW='\033[1;33m'
|
||||||
|
NC='\033[0m' # No Color
|
||||||
|
|
||||||
|
log_info() {
|
||||||
|
echo -e "${GREEN}[INFO]${NC} $1"
|
||||||
|
}
|
||||||
|
|
||||||
|
log_warn() {
|
||||||
|
echo -e "${YELLOW}[WARN]${NC} $1"
|
||||||
|
}
|
||||||
|
|
||||||
|
log_error() {
|
||||||
|
echo -e "${RED}[ERROR]${NC} $1"
|
||||||
|
}
|
||||||
|
|
||||||
|
# Ensure SSH tunnel is running
|
||||||
|
ensure_tunnel() {
|
||||||
|
if ! pgrep -f "ssh.*6443.*roamflow-1" > /dev/null; then
|
||||||
|
log_info "Starting SSH tunnel..."
|
||||||
|
ssh -f -N -L 6443:127.0.0.1:6443 roamflow-1
|
||||||
|
sleep 1
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
# Helm chart mappings: app -> (repo_name, repo_url, chart_name)
|
||||||
|
declare -A HELM_CHARTS=(
|
||||||
|
["headlamp"]="headlamp|https://headlamp-k8s.github.io/headlamp/|headlamp"
|
||||||
|
["gitea"]="gitea-charts|https://dl.gitea.com/charts/|gitea"
|
||||||
|
)
|
||||||
|
|
||||||
|
# Add Helm repositories
|
||||||
|
add_repos() {
|
||||||
|
log_info "Adding Helm repositories..."
|
||||||
|
for app in "${!HELM_CHARTS[@]}"; do
|
||||||
|
IFS='|' read -r repo_name repo_url chart_name <<< "${HELM_CHARTS[$app]}"
|
||||||
|
helm repo add "$repo_name" "$repo_url" 2>/dev/null || true
|
||||||
|
done
|
||||||
|
helm repo update
|
||||||
|
}
|
||||||
|
|
||||||
|
# Deploy a specific app
|
||||||
|
deploy_app() {
|
||||||
|
local app=$1
|
||||||
|
local app_dir="$PROJECT_ROOT/apps/$app"
|
||||||
|
|
||||||
|
if [[ ! -d "$app_dir" ]]; then
|
||||||
|
log_error "App '$app' not found in $PROJECT_ROOT/apps/"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
log_info "Deploying $app..."
|
||||||
|
|
||||||
|
# Apply namespace and other kustomize resources first
|
||||||
|
if [[ -f "$app_dir/kustomization.yaml" ]]; then
|
||||||
|
kubectl apply -k "$app_dir" --kubeconfig "$KUBECONFIG"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Deploy with Helm if values.yaml exists
|
||||||
|
if [[ -f "$app_dir/values.yaml" ]]; then
|
||||||
|
if [[ -n "${HELM_CHARTS[$app]}" ]]; then
|
||||||
|
IFS='|' read -r repo_name repo_url chart_name <<< "${HELM_CHARTS[$app]}"
|
||||||
|
helm upgrade --install "$app" "$repo_name/$chart_name" \
|
||||||
|
-f "$app_dir/values.yaml" \
|
||||||
|
-n "$app" \
|
||||||
|
--kubeconfig "$KUBECONFIG" \
|
||||||
|
--create-namespace
|
||||||
|
else
|
||||||
|
log_warn "No Helm chart configured for $app, skipping Helm deployment"
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
log_info "$app deployed successfully!"
|
||||||
|
}
|
||||||
|
|
||||||
|
# List available apps
|
||||||
|
list_apps() {
|
||||||
|
echo "Available apps:"
|
||||||
|
for app_dir in "$PROJECT_ROOT/apps"/*/; do
|
||||||
|
if [[ -d "$app_dir" ]]; then
|
||||||
|
app_name=$(basename "$app_dir")
|
||||||
|
echo " - $app_name"
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
}
|
||||||
|
|
||||||
|
# Main
|
||||||
|
main() {
|
||||||
|
ensure_tunnel
|
||||||
|
add_repos
|
||||||
|
|
||||||
|
if [[ "$1" == "--all" ]]; then
|
||||||
|
log_info "Deploying all apps..."
|
||||||
|
for app_dir in "$PROJECT_ROOT/apps"/*/; do
|
||||||
|
if [[ -d "$app_dir" ]]; then
|
||||||
|
app_name=$(basename "$app_dir")
|
||||||
|
deploy_app "$app_name"
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
elif [[ "$1" == "--list" ]]; then
|
||||||
|
list_apps
|
||||||
|
elif [[ -n "$1" ]]; then
|
||||||
|
deploy_app "$1"
|
||||||
|
else
|
||||||
|
echo "Usage: $0 <app-name|--all|--list>"
|
||||||
|
list_apps
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
main "$@"
|
||||||
Reference in New Issue
Block a user