Initial commit: k8s cluster manifests and scripts

This commit is contained in:
2026-04-01 15:34:02 +08:00
commit 2f04fa4473
49 changed files with 4109 additions and 0 deletions

20
apps/postgres/backup.sh Executable file
View File

@@ -0,0 +1,20 @@
#!/usr/bin/env bash
# 用途:備份 Postgres 到本機(使用 pg_dumpall
set -euo pipefail
BACKUP_DIR="$(cd "$(dirname "$0")" && pwd)/backups"
mkdir -p "$BACKUP_DIR"
POD=$(kubectl get pod -l app=postgres -o jsonpath='{.items[0].metadata.name}')
TS=$(date +%Y%m%d_%H%M%S)
OUT="$BACKUP_DIR/postgres-backup-$TS.sql"
echo "使用 Pod$POD"
echo "開始備份..."
kubectl exec "$POD" -- sh -c 'pg_dumpall -U "$POSTGRES_USER"' > "$OUT"
echo "備份完成:"
echo "$OUT"

View File

@@ -0,0 +1,157 @@
--
-- PostgreSQL database cluster dump
--
\restrict pSRBFv7OawZlldF9mhkwy64jnMZdGanavWk5r24Tn672qcvRL3qpsGkiOe7oPNn
SET default_transaction_read_only = off;
SET client_encoding = 'UTF8';
SET standard_conforming_strings = on;
--
-- Roles
--
CREATE ROLE myuser;
ALTER ROLE myuser WITH SUPERUSER INHERIT CREATEROLE CREATEDB LOGIN REPLICATION BYPASSRLS PASSWORD 'SCRAM-SHA-256$4096:lcasyFLTxsODZ2pTQzSfaQ==$Q9F2EsOXVyUo6hdnr4vPuErS4wNLYQ4aiszK/l4uar0=:ZOUai23wJ0E2uPl9ZVldTF4Kf6IduAMK+smPEs8LcjE=';
--
-- User Configurations
--
\unrestrict pSRBFv7OawZlldF9mhkwy64jnMZdGanavWk5r24Tn672qcvRL3qpsGkiOe7oPNn
--
-- Databases
--
--
-- Database "template1" dump
--
\connect template1
--
-- PostgreSQL database dump
--
\restrict z5l8f0bphx2JQX8DXx5DcxSoJZ8WO1YgETQRPbrS67n6Z3sZTrRi3rkJm5JGwlm
-- Dumped from database version 16.11 (Debian 16.11-1.pgdg13+1)
-- Dumped by pg_dump version 16.11 (Debian 16.11-1.pgdg13+1)
SET statement_timeout = 0;
SET lock_timeout = 0;
SET idle_in_transaction_session_timeout = 0;
SET client_encoding = 'UTF8';
SET standard_conforming_strings = on;
SELECT pg_catalog.set_config('search_path', '', false);
SET check_function_bodies = false;
SET xmloption = content;
SET client_min_messages = warning;
SET row_security = off;
--
-- PostgreSQL database dump complete
--
\unrestrict z5l8f0bphx2JQX8DXx5DcxSoJZ8WO1YgETQRPbrS67n6Z3sZTrRi3rkJm5JGwlm
--
-- Database "mydb" dump
--
--
-- PostgreSQL database dump
--
\restrict gIv4VWnnqhIHCcWxK9Gh9vrZXiMGwbVvmKNa64CtJ60YohCgypC9k0tWmdgClrB
-- Dumped from database version 16.11 (Debian 16.11-1.pgdg13+1)
-- Dumped by pg_dump version 16.11 (Debian 16.11-1.pgdg13+1)
SET statement_timeout = 0;
SET lock_timeout = 0;
SET idle_in_transaction_session_timeout = 0;
SET client_encoding = 'UTF8';
SET standard_conforming_strings = on;
SELECT pg_catalog.set_config('search_path', '', false);
SET check_function_bodies = false;
SET xmloption = content;
SET client_min_messages = warning;
SET row_security = off;
--
-- Name: mydb; Type: DATABASE; Schema: -; Owner: myuser
--
CREATE DATABASE mydb WITH TEMPLATE = template0 ENCODING = 'UTF8' LOCALE_PROVIDER = libc LOCALE = 'en_US.utf8';
ALTER DATABASE mydb OWNER TO myuser;
\unrestrict gIv4VWnnqhIHCcWxK9Gh9vrZXiMGwbVvmKNa64CtJ60YohCgypC9k0tWmdgClrB
\connect mydb
\restrict gIv4VWnnqhIHCcWxK9Gh9vrZXiMGwbVvmKNa64CtJ60YohCgypC9k0tWmdgClrB
SET statement_timeout = 0;
SET lock_timeout = 0;
SET idle_in_transaction_session_timeout = 0;
SET client_encoding = 'UTF8';
SET standard_conforming_strings = on;
SELECT pg_catalog.set_config('search_path', '', false);
SET check_function_bodies = false;
SET xmloption = content;
SET client_min_messages = warning;
SET row_security = off;
--
-- PostgreSQL database dump complete
--
\unrestrict gIv4VWnnqhIHCcWxK9Gh9vrZXiMGwbVvmKNa64CtJ60YohCgypC9k0tWmdgClrB
--
-- Database "postgres" dump
--
\connect postgres
--
-- PostgreSQL database dump
--
\restrict irY5kyT2aM9aY0ej35sQkGD65pdtbEJK5iVUBxrNe906zZsVHZFLUljOIsxjKic
-- Dumped from database version 16.11 (Debian 16.11-1.pgdg13+1)
-- Dumped by pg_dump version 16.11 (Debian 16.11-1.pgdg13+1)
SET statement_timeout = 0;
SET lock_timeout = 0;
SET idle_in_transaction_session_timeout = 0;
SET client_encoding = 'UTF8';
SET standard_conforming_strings = on;
SELECT pg_catalog.set_config('search_path', '', false);
SET check_function_bodies = false;
SET xmloption = content;
SET client_min_messages = warning;
SET row_security = off;
--
-- PostgreSQL database dump complete
--
\unrestrict irY5kyT2aM9aY0ej35sQkGD65pdtbEJK5iVUBxrNe906zZsVHZFLUljOIsxjKic
--
-- PostgreSQL database cluster dump complete
--

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

20
apps/postgres/deploy.sh Executable file
View File

@@ -0,0 +1,20 @@
#!/usr/bin/env bash
# 用途:部署或更新 PostgresSecret / PVC / Deployment / Service
set -euo pipefail
BASE_DIR="$(cd "$(dirname "$0")" && pwd)"
MANIFESTS="$BASE_DIR/manifests"
echo "部署 Postgres 中..."
kubectl apply -f "$MANIFESTS/postgres-secret.yaml"
kubectl apply -f "$MANIFESTS/postgres-pvc.yaml"
kubectl apply -f "$MANIFESTS/postgres-deployment.yaml"
kubectl apply -f "$MANIFESTS/postgres-service.yaml"
echo "完成,等待 Pod 就緒..."
kubectl wait --for=condition=ready pod -l app=postgres --timeout=120s
echo "Postgres 已啟動"

View File

@@ -0,0 +1,65 @@
apiVersion: apps/v1
kind: Deployment
metadata:
name: postgres
labels:
app: postgres
spec:
replicas: 1
selector:
matchLabels:
app: postgres
template:
metadata:
labels:
app: postgres
spec:
containers:
- name: postgres
image: postgres:16
imagePullPolicy: IfNotPresent
ports:
- containerPort: 5432
# 🔑 關鍵:避免 lost+found 問題
env:
- name: PGDATA
value: /var/lib/postgresql/data/pgdata
envFrom:
- secretRef:
name: postgres-secret
volumeMounts:
- name: postgres-data
mountPath: /var/lib/postgresql/data
# 官方建議的健康檢查方式
livenessProbe:
exec:
command:
- sh
- -c
- pg_isready -d "$POSTGRES_DB" -U "$POSTGRES_USER"
initialDelaySeconds: 30
periodSeconds: 10
timeoutSeconds: 5
failureThreshold: 3
readinessProbe:
exec:
command:
- sh
- -c
- pg_isready -d "$POSTGRES_DB" -U "$POSTGRES_USER"
initialDelaySeconds: 5
periodSeconds: 10
timeoutSeconds: 5
failureThreshold: 3
volumes:
- name: postgres-data
persistentVolumeClaim:
claimName: postgres-pvc

View File

@@ -0,0 +1,11 @@
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: postgres-pvc
spec:
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 5Gi

View File

@@ -0,0 +1,10 @@
apiVersion: v1
kind: Secret
metadata:
name: postgres-secret
type: Opaque
stringData:
POSTGRES_DB: mydb
POSTGRES_USER: myuser
POSTGRES_PASSWORD: mypassword

View File

@@ -0,0 +1,13 @@
apiVersion: v1
kind: Service
metadata:
name: postgres
spec:
type: NodePort
selector:
app: postgres
ports:
- port: 5432
targetPort: 5432
nodePort: 31532

26
apps/postgres/status.sh Executable file
View File

@@ -0,0 +1,26 @@
#!/usr/bin/env bash
# 用途:查看 Postgres 狀態與連線資訊
set -euo pipefail
echo
echo "=== Pod ==="
kubectl get pod -l app=postgres -o wide
echo
echo "=== Service ==="
kubectl get svc postgres
echo
echo "=== PVC ==="
kubectl get pvc postgres-pvc
echo
echo "=== NodePort 連線 ==="
NODE_IPS=$(kubectl get nodes -o jsonpath='{range .items[*]}{.status.addresses[?(@.type=="InternalIP")].address}{" "}{end}')
PORT=$(kubectl get svc postgres -o jsonpath='{.spec.ports[0].nodePort}')
for ip in $NODE_IPS; do
echo "- $ip:$PORT"
done

13
apps/postgres/stop.sh Executable file
View File

@@ -0,0 +1,13 @@
#!/usr/bin/env bash
# 用途:停止 Postgres不刪 PVC 與 Secret
set -euo pipefail
echo "停止 Postgres 中..."
kubectl delete deployment postgres --ignore-not-found
kubectl wait --for=delete pod -l app=postgres --timeout=60s || true
kubectl delete service postgres --ignore-not-found
echo "Postgres 已停止(資料仍保留)"