feat: add adminer and vaultwarden apps, integrated from k8s-manifests

This commit is contained in:
2026-04-01 16:46:33 +08:00
parent 19342c6821
commit b86255e81f
17 changed files with 397 additions and 48 deletions

View File

@@ -19,8 +19,9 @@ sudo -i # 切換 root
cd /root/k8s # K3s 工作目錄
```
- **主機**: 192.168.42.120
- **主機**: 192.168.42.120 (vm120 master + vm121/vm122 workers)
- **K3s 目錄**: `/root/k8s`
- **舊 manifests**: `/root/k8s-manifests` (備份保留)
- **本地目錄**: `/Users/timmy/42_120/k8s`
- **Git Repo**: http://192.168.42.124:31337/timmy/k3s.git
@@ -32,6 +33,8 @@ cd /root/k8s # K3s 工作目錄
|------|------|----------|
| [CodiMD](apps/codimd/) | Markdown 協作筆記 | `./apps/codimd/status.sh` |
| [Opengist](apps/opengist/) | Git Snippets 管理 | `./apps/opengist/status.sh` |
| [Vaultwarden](apps/vaultwarden/) | 密碼管理器 | `./apps/vaultwarden/status.sh` |
| [Adminer](apps/adminer/) | 資料庫管理工具 | `./apps/adminer/status.sh` |
| [PostgreSQL](apps/postgres/) | 通用資料庫 | `./apps/postgres/status.sh` |
---
@@ -41,9 +44,12 @@ cd /root/k8s # K3s 工作目錄
```
k8s/
├── apps/
│ ├── adminer/ # 資料庫管理工具
│ ├── codimd/ # 筆記應用
│ ├── opengist/ # Git Snippets
── postgres/ # 資料庫
── postgres/ # 資料庫
│ ├── template/ # 新 App 範本
│ └── vaultwarden/ # 密碼管理器
└── cluster/ # 叢集工具
```
@@ -53,7 +59,7 @@ k8s/
- `deploy.sh` - 部署腳本
- `stop.sh` - 停止腳本(保留資料)
- `status.sh` - 狀態檢查
- `backup.sh` - 備份腳本
- `backup.sh` - 備份腳本(如有)
---
@@ -79,7 +85,7 @@ kubectl get ingress -A
1. **本地修改** → 在此目錄編輯 manifests 或腳本
2. **Git 提交**`git add -A && git commit -m "描述" && git push`
3. **同步遠端**`rsync -avz --rsync-path="sudo rsync" . ubuntu@192.168.42.120:/root/k8s/`
3. **遠端更新**`git -C /root/k8s pull`
4. **套用變更**`kubectl apply -f manifests/`
---
@@ -89,16 +95,15 @@ kubectl get ingress -A
```
┌─────────────────────────────────────┐
│ Traefik Ingress │
(note.xxx.com / git.xxx.com)
(codimd / opengist / vw / adminer)
└─────────────────┬───────────────────┘
┌─────────────┼─────────────┐
│ │ │
┌───▼───┐ ┌───▼───┐ ┌───▼───┐
CodiMD│ │Opengist│ │PostgreSQL
+ │ │ │ │ (獨立)
│ PG │ │ │ │
└───────┘ └────────┘ └───────┘
┌─────────────┼─────────────┬─────────
│ │ │
┌───▼───┐ ┌───▼───┐ ┌───▼───┐ ┌──▼────┐
│CodiMD │ │Opengist│ │Vault │ │Adminer│
+PG │ │ │ │warden │ │ │
└───────┘ └────────┘ └───────┘ └───────┘
│ │ │
└───▼─────────────▼─────────────▼───┘
Longhorn Storage

View File

@@ -9,9 +9,12 @@
| 主機 | 192.168.42.120 |
| 連線 | `ssh ubuntu@192.168.42.120``sudo -i` |
| K8s 目錄 | `/root/k8s` |
| 舊 manifests | `/root/k8s-manifests` (備份) |
| 本地目錄 | `/Users/timmy/42_120/k8s` |
| Git Repo | http://192.168.42.124:31337/timmy/k3s.git |
**節點**: vm120 (master) + vm121 + vm122 (3 節點 HA)
---
## 🚀 已部署服務
@@ -21,15 +24,10 @@
| 項目 | 值 |
|------|-----|
| 用途 | Markdown 協作筆記、團隊知識庫 |
| Ingress | `note.yourdomain.com` |
| Ingress | `codimd.lotimmy.com` |
| 命名空間 | `default` |
| 資料庫 | PostgreSQL (內建) |
**組件:**
- `codimd-app` - 應用程式
- `codimd-db` - PostgreSQL 資料庫
- Longhorn PVC - 資料持久化
**腳本:** `apps/codimd/{deploy,stop,status,backup,restore}.sh`
---
@@ -39,18 +37,37 @@
| 項目 | 值 |
|------|-----|
| 用途 | 自架 Git snippets、程式碼片段分享 |
| SSH Port | `2222` (Traefik TCP) |
| Web Port | `80`/`443` (Ingress) |
| Ingress | `opengist.lotimmy.com` |
| 命名空間 | `default` |
**組件:**
- `opengist` - 應用程式
- Longhorn PVC - 資料持久化
**腳本:** `apps/opengist/{deploy,stop,status,backup,restore}.sh`
---
### Vaultwarden - 密碼管理器
| 項目 | 值 |
|------|-----|
| 用途 | 自架 Bitwarden 密碼管理 |
| Ingress | `vaultwarden.lotimmy.com` |
| 儲存 | 5Gi Longhorn PVC |
**腳本:** `apps/vaultwarden/{deploy,stop,status,backup,restore}.sh`
---
### Adminer - 資料庫管理
| 項目 | 值 |
|------|-----|
| 用途 | Web 資料庫管理工具 |
| Ingress | `adminer.lotimmy.com` |
| 連接目標 | 叢集內 PostgreSQL |
**腳本:** `apps/adminer/{deploy,stop,status}.sh`
---
### PostgreSQL - 獨立資料庫
| 項目 | 值 |
@@ -68,23 +85,19 @@
```
k8s/
├── apps/
│ ├── adminer/ # 資料庫管理工具
│ ├── codimd/ # CodiMD 筆記應用
│ │ ├── manifests/ # K8s YAML 檔案
│ │ ├── backup/ # 備份檔案
│ │ ├── tmpdir/ # 暫存/舊檔案
│ │ └── *.sh # 管理腳本
│ ├── opengist/ # Opengist Git Snippets
│ ├── manifests/
│ ├── backup/
│ └── *.sh
│ └── postgres/ # 獨立 PostgreSQL
├── manifests/
├── backups/ # SQL 備份
└── *.sh
── cluster/ # 叢集檢查工具
├── check_access.sh # 檢查存取權限
├── check_nodes.sh # 檢查節點狀態
└── check_storage.sh # 檢查儲存空間
│ ├── postgres/ # 獨立 PostgreSQL
│ ├── template/ # 新 App 範本
│ └── vaultwarden/ # 密碼管理器
├── cluster/ # 叢集檢查工具
├── check_access.sh
├── check_nodes.sh
└── check_storage.sh
── README.md
├── QUICKSTART.md
└── SUMMARY.md
```
---
@@ -120,10 +133,11 @@ kubectl logs -f <pod-name>
## 🔄 維護工作流程
1. **本地修改** → 編輯 manifests 或腳本
2. **同步遠端**`rsync``git push`
3. **部署**執行 `deploy.sh`
4. **驗證** → 執行 `status.sh`
5. **備份** → 執行 `backup.sh`
2. **Git 提交**`git add -A && git commit && git push`
3. **遠端更新**`git -C /root/k8s pull`
4. **部署** → 執行 `deploy.sh`
5. **驗證** → 執行 `status.sh`
6. **備份** → 執行 `backup.sh`
---

14
apps/adminer/deploy.sh Executable file
View File

@@ -0,0 +1,14 @@
#!/usr/bin/env bash
set -euo pipefail
BASE_DIR="$(cd "$(dirname "$0")" && pwd)"
MANIFESTS="$BASE_DIR/manifests"
echo "🚀 部署 Adminer..."
kubectl apply -f "$MANIFESTS/"
echo "⏳ 等待 Pod 就緒..."
kubectl rollout status deployment/adminer --timeout=120s
echo "✅ Adminer 部署完成"

View File

@@ -0,0 +1,28 @@
apiVersion: apps/v1
kind: Deployment
metadata:
name: adminer
labels:
app: adminer
spec:
replicas: 1
selector:
matchLabels:
app: adminer
template:
metadata:
labels:
app: adminer
spec:
containers:
- name: adminer
image: adminer:latest
ports:
- containerPort: 8080
resources:
requests:
cpu: "10m"
memory: "32Mi"
limits:
cpu: "200m"
memory: "256Mi"

View File

@@ -0,0 +1,35 @@
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: adminer-ingress
labels:
app: adminer
annotations:
traefik.ingress.kubernetes.io/router.entrypoints: web,websecure
spec:
ingressClassName: traefik
tls:
- hosts:
- adminer.192.168.42.120.nip.io
secretName: nip-io-cert
rules:
- host: adminer.lotimmy.com
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: adminer-service
port:
number: 80
- host: adminer.192.168.42.120.nip.io
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: adminer-service
port:
number: 80

View File

@@ -0,0 +1,15 @@
apiVersion: v1
kind: Service
metadata:
name: adminer-service
labels:
app: adminer
spec:
selector:
app: adminer
type: ClusterIP
ports:
- protocol: TCP
name: http
port: 80
targetPort: 8080

20
apps/adminer/status.sh Executable file
View File

@@ -0,0 +1,20 @@
#!/usr/bin/env bash
set -euo pipefail
APP_NAME="adminer"
echo "=== [ $APP_NAME 資源狀態 ] ==="
echo ""
echo "--- Pods ---"
kubectl get pods -l "app=$APP_NAME" -o wide
echo ""
echo "--- Services ---"
kubectl get svc -l "app=$APP_NAME"
echo ""
echo "--- Access (Ingress) ---"
kubectl get ingress -l "app=$APP_NAME" -o custom-columns=NAME:.metadata.name,HOSTS:.spec.rules[*].host

10
apps/adminer/stop.sh Executable file
View File

@@ -0,0 +1,10 @@
#!/usr/bin/env bash
set -euo pipefail
echo "🛑 停止 Adminer..."
kubectl delete deployment/adminer --ignore-not-found
kubectl delete service/adminer-service --ignore-not-found
kubectl delete ingress/adminer-ingress --ignore-not-found
echo "✅ Adminer 已停止"

25
apps/vaultwarden/backup.sh Executable file
View File

@@ -0,0 +1,25 @@
#!/usr/bin/env bash
set -euo pipefail
APP_NAME="vaultwarden"
BASE_DIR="$(cd "$(dirname "$0")" && pwd)"
BACKUP_DIR="$BASE_DIR/backup"
TIMESTAMP=$(date +%Y%m%d-%H%M)
echo "📦 備份 $APP_NAME..."
mkdir -p "$BACKUP_DIR"
POD=$(kubectl get pod -l "app=$APP_NAME" -o jsonpath="{.items[0].metadata.name}")
if [ -z "$POD" ]; then
echo "❌ 找不到 $APP_NAME 的 Pod"
exit 1
fi
echo "備份資料..."
kubectl exec $POD -- tar czf /tmp/backup.tar.gz /data
kubectl cp $POD:/tmp/backup.tar.gz "$BACKUP_DIR/$APP_NAME-$TIMESTAMP.tar.gz"
kubectl exec $POD -- rm /tmp/backup.tar.gz
echo "✅ 備份完成: $BACKUP_DIR/$APP_NAME-$TIMESTAMP.tar.gz"

14
apps/vaultwarden/deploy.sh Executable file
View File

@@ -0,0 +1,14 @@
#!/usr/bin/env bash
set -euo pipefail
BASE_DIR="$(cd "$(dirname "$0")" && pwd)"
MANIFESTS="$BASE_DIR/manifests"
echo "🚀 部署 Vaultwarden..."
kubectl apply -f "$MANIFESTS/"
echo "⏳ 等待 Pod 就緒..."
kubectl rollout status deployment/vaultwarden --timeout=120s
echo "✅ Vaultwarden 部署完成"

View File

@@ -0,0 +1,39 @@
apiVersion: apps/v1
kind: Deployment
metadata:
name: vaultwarden
labels:
app: vaultwarden
spec:
replicas: 1
selector:
matchLabels:
app: vaultwarden
template:
metadata:
labels:
app: vaultwarden
spec:
containers:
- name: vaultwarden
image: vaultwarden/server:latest
resources:
limits:
memory: "512Mi"
cpu: "500m"
ports:
- containerPort: 80
env:
- name: WEBSOCKET_ENABLED
value: "true"
- name: DOMAIN
value: "https://vaultwarden.lotimmy.com"
- name: ADMIN_TOKEN
value: "$$argon2id$$v=19$$m=65540,t=3,p=4$$EVIbGzNlkQUK5b0r7aMgKoUWV98aqrpPevU+8Bbv0EE$$JB51q0ih0LGmw6rp7ZVBgT+PNnCepy+bNYyaChD+VMc"
volumeMounts:
- mountPath: "/data"
name: data-vol
volumes:
- name: data-vol
persistentVolumeClaim:
claimName: vaultwarden-pvc

View File

@@ -0,0 +1,35 @@
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: vaultwarden-ingress
labels:
app: vaultwarden
annotations:
traefik.ingress.kubernetes.io/router.entrypoints: web,websecure
spec:
ingressClassName: traefik
tls:
- hosts:
- vaultwarden.192.168.42.120.nip.io
secretName: nip-io-cert
rules:
- host: vaultwarden.lotimmy.com
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: vaultwarden-service
port:
number: 80
- host: vaultwarden.192.168.42.120.nip.io
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: vaultwarden-service
port:
number: 80

View File

@@ -0,0 +1,13 @@
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: vaultwarden-pvc
labels:
app: vaultwarden
spec:
storageClassName: longhorn
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 5Gi

View File

@@ -0,0 +1,15 @@
apiVersion: v1
kind: Service
metadata:
name: vaultwarden-service
labels:
app: vaultwarden
spec:
selector:
app: vaultwarden
ports:
- protocol: TCP
name: http
port: 80
targetPort: 80
type: ClusterIP

32
apps/vaultwarden/restore.sh Executable file
View File

@@ -0,0 +1,32 @@
#!/usr/bin/env bash
set -euo pipefail
APP_NAME="vaultwarden"
BASE_DIR="$(cd "$(dirname "$0")" && pwd)"
BACKUP_DIR="$BASE_DIR/backup"
if [ $# -eq 0 ]; then
echo "用法: $0 <backup-file>"
echo ""
echo "可用備份:"
ls -lh "$BACKUP_DIR/"*.tar.gz 2>/dev/null || echo "無備份檔案"
exit 1
fi
BACKUP_FILE="$1"
if [ ! -f "$BACKUP_FILE" ]; then
echo "❌ 備份檔案不存在: $BACKUP_FILE"
exit 1
fi
POD=$(kubectl get pod -l "app=$APP_NAME" -o jsonpath="{.items[0].metadata.name}")
echo "📥 還原 $APP_NAME$BACKUP_FILE..."
kubectl cp "$BACKUP_FILE" $POD:/tmp/restore.tar.gz
kubectl exec $POD -- tar xzf /tmp/restore.tar.gz -C /
kubectl exec $POD -- rm /tmp/restore.tar.gz
echo "✅ 還原完成,請重啟 Pod"
kubectl rollout restart deployment/$APP_NAME

25
apps/vaultwarden/status.sh Executable file
View File

@@ -0,0 +1,25 @@
#!/usr/bin/env bash
set -euo pipefail
APP_NAME="vaultwarden"
echo "=== [ $APP_NAME 資源狀態 ] ==="
echo ""
echo "--- Pods ---"
kubectl get pods -l "app=$APP_NAME" -o wide
echo ""
echo "--- Services ---"
kubectl get svc -l "app=$APP_NAME"
echo ""
echo "--- Storage (PVC) ---"
kubectl get pvc -l "app=$APP_NAME"
echo ""
echo "--- Access (Ingress) ---"
kubectl get ingress -l "app=$APP_NAME" -o custom_columns=NAME:.metadata.name,HOSTS:.spec.rules[*].host

10
apps/vaultwarden/stop.sh Executable file
View File

@@ -0,0 +1,10 @@
#!/usr/bin/env bash
set -euo pipefail
echo "🛑 停止 Vaultwarden保留資料..."
kubectl delete deployment/vaultwarden --ignore-not-found
kubectl delete service/vaultwarden-service --ignore-not-found
kubectl delete ingress/vaultwarden-ingress --ignore-not-found
echo "✅ Vaultwarden 已停止PVC 資料保留"