feat: add .gitignore and apps/template for new apps

This commit is contained in:
2026-04-01 16:32:59 +08:00
parent 98cd6b71cb
commit 19342c6821
10 changed files with 292 additions and 0 deletions

55
apps/template/README.md Normal file
View File

@@ -0,0 +1,55 @@
# 新增應用範本
## 使用步驟
1. **複製範本**
```bash
cp -r apps/template apps/your-app
```
2. **替換佔位符**
- `{{APP_NAME}}` → 應用名稱(如 `myapp`
- `{{IMAGE}}` → Docker 映像(如 `nginx`
- `{{TAG}}` → 版本標籤(如 `1.25`
- `{{PORT}}` → 容器端口(如 `80`
- `{{HOST}}` → 網域名稱(如 `app.example.com`
- `{{SIZE}}` → 儲存大小(如 `10Gi`
- `{{DATA_MOUNT_PATH}}` → 資料掛載路徑
3. **權限設定**
```bash
chmod +x apps/your-app/*.sh
```
4. **部署**
```bash
cd apps/your-app
./deploy.sh
```
## 目錄結構
```
apps/your-app/
├── manifests/ # K8s YAML 檔案
│ ├── app-deployment.yaml
│ ├── app-pvc.yaml
│ ├── app-ingress.yaml
│ └── app-service.yaml
├── deploy.sh # 部署腳本
├── stop.sh # 停止腳本
├── status.sh # 狀態檢查
├── backup.sh # 備份腳本
└── backup/ # 備份檔案目錄
```
## 常見調整
### 有資料庫的應用
在 `manifests/` 新增 `db-deployment.yaml`、`db-service.yaml`
### 需要密碼/金鑰
在 `manifests/` 新增 `secret.yaml`(參考 `apps/codimd/manifests/01-codimd-secrets.yaml`
### 需要特殊設定
在 `manifests/` 新增 `configmap.yaml`

30
apps/template/backup.sh Executable file
View File

@@ -0,0 +1,30 @@
#!/usr/bin/env bash
# 用途:備份 {{APP_NAME}} 資料
set -euo pipefail
APP_NAME="{{APP_NAME}}"
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 名稱
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
# 備份 PVC 資料(範例:假設是檔案資料)
echo "備份 PVC 資料..."
kubectl exec $POD -- tar czf /tmp/backup.tar.gz {{DATA_MOUNT_PATH|/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"

18
apps/template/deploy.sh Executable file
View File

@@ -0,0 +1,18 @@
#!/usr/bin/env bash
# 用途:部署 {{APP_NAME}} 到 K3s
set -euo pipefail
BASE_DIR="$(cd "$(dirname "$0")" && pwd)"
MANIFESTS="$BASE_DIR/manifests"
APP_NAME="{{APP_NAME}}"
echo "🚀 部署 $APP_NAME..."
# 依序套用 manifests按檔名排序
kubectl apply -f "$MANIFESTS/"
echo "⏳ 等待 Pod 就緒..."
kubectl rollout status deployment/$APP_NAME --timeout=120s
echo "$APP_NAME 部署完成"

View File

@@ -0,0 +1,55 @@
# Deployment 範本
# 使用方式:複製此檔案,將 {{APP_NAME}} 替換為你的應用名稱
apiVersion: apps/v1
kind: Deployment
metadata:
name: {{APP_NAME}}
namespace: default
labels:
app: {{APP_NAME}}
spec:
replicas: 1
selector:
matchLabels:
app: {{APP_NAME}}
template:
metadata:
labels:
app: {{APP_NAME}}
spec:
containers:
- name: {{APP_NAME}}
image: {{IMAGE}}:{{TAG|latest}}
imagePullPolicy: IfNotPresent
ports:
- name: http
containerPort: {{PORT|8080}}
# 資源限制(建議設定)
resources:
limits:
memory: "512Mi"
cpu: "500m"
requests:
memory: "256Mi"
cpu: "250m"
# 健康檢查(可選)
livenessProbe:
httpGet:
path: /
port: http
initialDelaySeconds: 30
periodSeconds: 10
readinessProbe:
httpGet:
path: /
port: http
initialDelaySeconds: 5
periodSeconds: 10
volumeMounts:
- name: data-vol
mountPath: {{DATA_MOUNT_PATH|/data}}
volumes:
- name: data-vol
persistentVolumeClaim:
claimName: {{APP_NAME}}-pvc

View File

@@ -0,0 +1,24 @@
# Ingress 範本 - Traefik
# 使用方式:將 {{APP_NAME}}、{{HOST}} 替換為實際值
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: {{APP_NAME}}-ingress
labels:
app: {{APP_NAME}}
annotations:
traefik.ingress.kubernetes.io/router.entrypoints: web, websecure
spec:
ingressClassName: traefik
rules:
- host: {{HOST}}
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: {{APP_NAME}}-service
port:
number: {{PORT|8080}}

View File

@@ -0,0 +1,16 @@
# PVC 範本 - Longhorn 儲存
# 使用方式:將 {{APP_NAME}} 替換為你的應用名稱
# 儲存大小可調整1Gi, 5Gi, 10Gi...
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: {{APP_NAME}}-pvc
namespace: default
spec:
accessModes:
- ReadWriteOnce
storageClassName: longhorn
resources:
requests:
storage: {{SIZE|5Gi}}

View File

@@ -0,0 +1,18 @@
# Service 範本
# 使用方式:將 {{APP_NAME}}、{{PORT}} 替換為實際值
apiVersion: v1
kind: Service
metadata:
name: {{APP_NAME}}-service
namespace: default
labels:
app: {{APP_NAME}}
spec:
type: ClusterIP
selector:
app: {{APP_NAME}}
ports:
- name: http
port: 80
targetPort: {{PORT|8080}

31
apps/template/status.sh Executable file
View File

@@ -0,0 +1,31 @@
#!/usr/bin/env bash
# 用途:檢查 {{APP_NAME}} 狀態
set -euo pipefail
APP_NAME="{{APP_NAME}}"
echo "=== [ $APP_NAME 資源狀態 ] ==="
echo ""
# 1. Pods
echo "--- Pods ---"
kubectl get pods -l "app=$APP_NAME" -o wide
echo ""
# 2. Services
echo "--- Services ---"
kubectl get svc -l "app=$APP_NAME"
echo ""
# 3. PVC
echo "--- Storage (PVC) ---"
kubectl get pvc | grep "$APP_NAME" || echo "無 PVC"
echo ""
# 4. Ingress
echo "--- Access (Ingress) ---"
kubectl get ingress -l "app=$APP_NAME" -o custom-columns=NAME:.metadata.name,HOSTS:.spec.rules[*].host,ADDRESS:.status.loadBalancer.ingress[*].ip

15
apps/template/stop.sh Executable file
View File

@@ -0,0 +1,15 @@
#!/usr/bin/env bash
# 用途:停止 {{APP_NAME}}(保留資料)
set -euo pipefail
APP_NAME="{{APP_NAME}}"
echo "🛑 停止 $APP_NAME(保留 PVC 資料)..."
# 只刪除 Deployment 和 ServicePVC 會保留
kubectl delete deployment/$APP_NAME --ignore-not-found
kubectl delete service/$APP_NAME-service --ignore-not-found
kubectl delete ingress/$APP_NAME-ingress --ignore-not-found
echo "$APP_NAME 已停止,資料安全保留"