From 19342c68219064f9512642c565b6b627039f9169 Mon Sep 17 00:00:00 2001 From: Timmy Date: Wed, 1 Apr 2026 16:32:59 +0800 Subject: [PATCH] feat: add .gitignore and apps/template for new apps --- .gitignore | 30 +++++++++++ apps/template/README.md | 55 +++++++++++++++++++++ apps/template/backup.sh | 30 +++++++++++ apps/template/deploy.sh | 18 +++++++ apps/template/manifests/app-deployment.yaml | 55 +++++++++++++++++++++ apps/template/manifests/app-ingress.yaml | 24 +++++++++ apps/template/manifests/app-pvc.yaml | 16 ++++++ apps/template/manifests/app-service.yaml | 18 +++++++ apps/template/status.sh | 31 ++++++++++++ apps/template/stop.sh | 15 ++++++ 10 files changed, 292 insertions(+) create mode 100644 .gitignore create mode 100644 apps/template/README.md create mode 100755 apps/template/backup.sh create mode 100755 apps/template/deploy.sh create mode 100644 apps/template/manifests/app-deployment.yaml create mode 100644 apps/template/manifests/app-ingress.yaml create mode 100644 apps/template/manifests/app-pvc.yaml create mode 100644 apps/template/manifests/app-service.yaml create mode 100755 apps/template/status.sh create mode 100755 apps/template/stop.sh diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..4c48744 --- /dev/null +++ b/.gitignore @@ -0,0 +1,30 @@ +# 備份檔案(太大且不應進版控) +**/backup/ +**/backups/ +**/*.sql +**/*.sql.gz +**/*.tar.gz +**/*.dump + +# 暫存目錄 +**/tmpdir/ +**/tmp/ +**/*.tmp + +# K8s 產生的檔案 +**/.kubectl* +**/kubeconfig* + +# 編輯器 +*.swp +*.swo +*~ +.idea/ +.vscode/ + +# 作業系統 +.DS_Store +Thumbs.db + +# 日誌 +**/*.log diff --git a/apps/template/README.md b/apps/template/README.md new file mode 100644 index 0000000..7bd9751 --- /dev/null +++ b/apps/template/README.md @@ -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` diff --git a/apps/template/backup.sh b/apps/template/backup.sh new file mode 100755 index 0000000..bd32477 --- /dev/null +++ b/apps/template/backup.sh @@ -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" diff --git a/apps/template/deploy.sh b/apps/template/deploy.sh new file mode 100755 index 0000000..bd95b18 --- /dev/null +++ b/apps/template/deploy.sh @@ -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 部署完成" diff --git a/apps/template/manifests/app-deployment.yaml b/apps/template/manifests/app-deployment.yaml new file mode 100644 index 0000000..57c611d --- /dev/null +++ b/apps/template/manifests/app-deployment.yaml @@ -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 diff --git a/apps/template/manifests/app-ingress.yaml b/apps/template/manifests/app-ingress.yaml new file mode 100644 index 0000000..31d8856 --- /dev/null +++ b/apps/template/manifests/app-ingress.yaml @@ -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}} diff --git a/apps/template/manifests/app-pvc.yaml b/apps/template/manifests/app-pvc.yaml new file mode 100644 index 0000000..5239327 --- /dev/null +++ b/apps/template/manifests/app-pvc.yaml @@ -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}} diff --git a/apps/template/manifests/app-service.yaml b/apps/template/manifests/app-service.yaml new file mode 100644 index 0000000..3a577b4 --- /dev/null +++ b/apps/template/manifests/app-service.yaml @@ -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} diff --git a/apps/template/status.sh b/apps/template/status.sh new file mode 100755 index 0000000..3837374 --- /dev/null +++ b/apps/template/status.sh @@ -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 diff --git a/apps/template/stop.sh b/apps/template/stop.sh new file mode 100755 index 0000000..99005bc --- /dev/null +++ b/apps/template/stop.sh @@ -0,0 +1,15 @@ +#!/usr/bin/env bash +# 用途:停止 {{APP_NAME}}(保留資料) + +set -euo pipefail + +APP_NAME="{{APP_NAME}}" + +echo "🛑 停止 $APP_NAME(保留 PVC 資料)..." + +# 只刪除 Deployment 和 Service,PVC 會保留 +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 已停止,資料安全保留"