Skip to content

Commit a127d74

Browse files
Merge pull request #42 from SteveLin100132/chore/doks-github-action-deploy
chore(k8s): restructure Kubernetes configurations for DigitalOcean and GKE, add TLS support and update resources
2 parents 428f9e3 + dd7a824 commit a127d74

25 files changed

+588
-17
lines changed

.github/workflows/deploy-doks.yaml

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
name: Deploy to DOKS
2+
3+
on:
4+
push:
5+
branches:
6+
- master
7+
8+
env:
9+
GITHUB_ACTOR: ${{ github.actor }}
10+
APP_VERSION: ${{ vars.APP_VERSION }}
11+
IMAGE_NAME: ${{ vars.IMAGE_NAME }}
12+
IMAGE_REPO: ${GITHUB_ACTOR,,}
13+
14+
jobs:
15+
deploy:
16+
runs-on: ubuntu-latest
17+
18+
steps:
19+
- name: Checkout code
20+
uses: actions/checkout@v4
21+
22+
- name: Set up doctl
23+
uses: digitalocean/action-doctl@v2
24+
with:
25+
token: ${{ secrets.DIGITALOCEAN_ACCESS_TOKEN }}
26+
27+
- name: Save kubeconfig
28+
run: doctl kubernetes cluster kubeconfig save ${{ secrets.DOKS_CLUSTER_ID }}
29+
30+
- name: Set up kubectl
31+
uses: azure/setup-kubectl@v3
32+
with:
33+
version: "latest"
34+
35+
- name: Replace APP_VERSION in kustomization.yaml
36+
run: |
37+
export APP_VERSION=${{ env.APP_VERSION }}
38+
envsubst < ./k8s/kustomization.yaml > ./k8s/kustomization.yaml.tmp
39+
mv ./k8s/kustomization.yaml.tmp ./k8s/kustomization.yaml
40+
41+
- name: Deploy with kustomize
42+
run: |
43+
kustomize build ./k8s | kubectl apply -f -

.github/workflows/deploy.yaml renamed to .github/workflows/deploy-gke.yaml

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ name: Deploy to GKE
33
on:
44
push:
55
branches:
6-
- deploy
6+
- deploy-gke
77

88
env:
99
GITHUB_ACTOR: ${{ github.actor }}
@@ -29,7 +29,7 @@ jobs:
2929
uses: google-github-actions/setup-gcloud@v2
3030
with:
3131
project_id: ${{ secrets.GCP_PROJECT_ID }}
32-
32+
3333
- name: Get GKE credentials
3434
run: |
3535
gcloud container clusters get-credentials ${{ secrets.GKE_CLUSTER }} --zone $GKE_ZONE --project ${{ secrets.GCP_PROJECT_ID }}
@@ -46,4 +46,4 @@ jobs:
4646
4747
- name: Deploy with kustomize
4848
run: |
49-
kustomize build ./k8s | kubectl apply -f -
49+
kustomize build ./k8s | kubectl apply -f -

CHANGELOG.md

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,20 @@
11
# Changelog
22

3+
## [1.1.8] - 2025-08-24
4+
5+
### Added
6+
7+
- **DOKS 自動部署 GitHub Action**
8+
- 新增 `.github/workflows/deploy-doks.yaml`,當 master 分支有 push 時自動部署到 DigitalOcean Kubernetes (DOKS)
9+
- 支援 APP_VERSION 參數自動替換,並整合 doctl/kubectl/kustomize 流程
10+
- **K8s/DOKS 部署教學與 cert-manager HTTPS 範例**
11+
- 新增 `k8s/DOKS/README.md`,詳細記錄 DOKS 連線、nginx ingress controller 安裝、cert-manager 憑證申請與 Ingress TLS 設定教學
12+
- 包含 Let's Encrypt ClusterIssuer、Certificate、Ingress TLS YAML 範例
13+
14+
### Changed
15+
16+
- 部署流程優化,支援 DOKS 自動化,README 文件同步更新
17+
318
## [1.1.7] - 2025-08-10
419

520
### Fixed

k8s/DOKS/README.md

Lines changed: 158 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,158 @@
1+
# DigitalOcean Kubernetes (DOKS) 操作指南
2+
3+
## 1. 連線到 DOKS Cluster
4+
5+
1. 安裝 doctl CLI 工具
6+
[官方下載頁](https://docs.digitalocean.com/reference/doctl/how-to/install/)
7+
2. 登入 doctl(用 DigitalOcean API Token)
8+
```sh
9+
doctl auth init
10+
```
11+
3. 取得 cluster 列表,找到你的 cluster 名稱或 ID
12+
```sh
13+
doctl kubernetes cluster list
14+
```
15+
4. 儲存 kubeconfig(用 cluster 名稱或 ID)
16+
```sh
17+
doctl kubernetes cluster kubeconfig save <your-cluster-name-or-id>
18+
```
19+
5. 驗證連線
20+
```sh
21+
kubectl get nodes
22+
```
23+
24+
## 2. 安裝 nginx ingress controller
25+
26+
1. 執行以下指令安裝 nginx ingress controller:
27+
```sh
28+
kubectl apply -f https://raw.githubusercontent.com/kubernetes/ingress-nginx/controller-v1.10.1/deploy/static/provider/cloud/deploy.yaml
29+
```
30+
2. 等待安裝完成,確認 controller 已啟動:
31+
```sh
32+
kubectl get pods -n ingress-nginx
33+
```
34+
3. 取得 EXTERNAL-IP:
35+
```sh
36+
kubectl get svc -n ingress-nginx
37+
```
38+
39+
## 3. 設定 Ingress 資源
40+
41+
1. 在 Ingress YAML 設定 ingress class:
42+
```yaml
43+
apiVersion: networking.k8s.io/v1
44+
kind: Ingress
45+
metadata:
46+
name: your-app-ingress
47+
labels:
48+
app: your-app
49+
spec:
50+
ingressClassName: nginx
51+
rules:
52+
- host: your-domain.com
53+
http:
54+
paths:
55+
- path: /
56+
pathType: Prefix
57+
backend:
58+
service:
59+
name: your-app-service
60+
port:
61+
number: 80
62+
```
63+
2. 套用 Ingress 資源:
64+
```sh
65+
kubectl apply -f <your-ingress.yaml>
66+
```
67+
3. 驗證 Ingress 是否分配外部 IP:
68+
```sh
69+
kubectl get ingress
70+
```
71+
72+
---
73+
74+
## 4. 安裝 cert-manager 並自動申請 HTTPS 憑證
75+
76+
### 安裝 cert-manager
77+
78+
```sh
79+
kubectl apply -f https://github.com/cert-manager/cert-manager/releases/download/v1.14.2/cert-manager.yaml
80+
```
81+
82+
### 建立 ClusterIssuer(Let's Encrypt)
83+
84+
建立一個 `cluster-issuer.yaml`
85+
86+
```yaml
87+
apiVersion: cert-manager.io/v1
88+
kind: ClusterIssuer
89+
metadata:
90+
name: letsencrypt-prod
91+
spec:
92+
acme:
93+
server: https://acme-v02.api.letsencrypt.org/directory
94+
email: your-email@example.com
95+
privateKeySecretRef:
96+
name: letsencrypt-prod
97+
solvers:
98+
- http01:
99+
ingress:
100+
class: nginx
101+
```
102+
103+
套用:
104+
105+
```sh
106+
kubectl apply -f cluster-issuer.yaml
107+
```
108+
109+
### 建立 Certificate 資源
110+
111+
建立一個 `certificate.yaml`
112+
113+
```yaml
114+
apiVersion: cert-manager.io/v1
115+
kind: Certificate
116+
metadata:
117+
name: notion-chart-generator-cert
118+
namespace: default
119+
spec:
120+
secretName: notion-chart-generator-tls
121+
issuerRef:
122+
name: letsencrypt-prod
123+
kind: ClusterIssuer
124+
commonName: your-domain.com
125+
dnsNames:
126+
- your-domain.com
127+
```
128+
129+
套用:
130+
131+
```sh
132+
kubectl apply -f certificate.yaml
133+
```
134+
135+
### 修改 Ingress 讓其使用 TLS
136+
137+
在 Ingress YAML 加入 TLS 設定:
138+
139+
```yaml
140+
spec:
141+
tls:
142+
- hosts:
143+
- 188-166-204-94.nip.io
144+
secretName: notion-chart-generator-tls
145+
rules:
146+
- host: 188-166-204-94.nip.io
147+
http:
148+
paths:
149+
# ...existing paths...
150+
```
151+
152+
---
153+
154+
**注意事項:**
155+
156+
- 請將 `your-email@example.com` 改為你自己的 email。
157+
- DNS 必須能指向你的 Ingress EXTERNAL-IP(nip.io 會自動處理)。
158+
- cert-manager 會自動申請、續期憑證,無需手動操作。

k8s/DOKS/certificate.yaml

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
apiVersion: cert-manager.io/v1
2+
kind: Certificate
3+
metadata:
4+
name: notion-chart-generator-cert
5+
namespace: default
6+
spec:
7+
secretName: notion-chart-generator-tls
8+
issuerRef:
9+
name: letsencrypt-prod
10+
kind: ClusterIssuer
11+
commonName: 188-166-204-94.nip.io
12+
dnsNames:
13+
- 188-166-204-94.nip.io

k8s/DOKS/cluster-issuer.yaml

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
apiVersion: cert-manager.io/v1
2+
kind: ClusterIssuer
3+
metadata:
4+
name: letsencrypt-prod
5+
spec:
6+
acme:
7+
server: https://acme-v02.api.letsencrypt.org/directory
8+
email: jojo404032@gmail.com
9+
privateKeySecretRef:
10+
name: letsencrypt-prod
11+
solvers:
12+
- http01:
13+
ingress:
14+
class: nginx

k8s/DOKS/configmap.yaml

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
apiVersion: v1
2+
kind: ConfigMap
3+
metadata:
4+
name: notion-chart-generator-config
5+
data:
6+
APP_VER: "1.0.0"
7+
NODE_ENV: "production"
8+
PORT: "3000"
9+
BACKEND_PORT: "3001"

k8s/DOKS/deployment.yaml

Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
1+
apiVersion: apps/v1
2+
kind: Deployment
3+
metadata:
4+
name: notion-chart-generator
5+
labels:
6+
app: notion-chart-generator
7+
version: "1.0.0"
8+
spec:
9+
replicas: 1
10+
selector:
11+
matchLabels:
12+
app: notion-chart-generator
13+
template:
14+
metadata:
15+
labels:
16+
app: notion-chart-generator
17+
spec:
18+
automountServiceAccountToken: false
19+
securityContext:
20+
fsGroup: 1001
21+
runAsUser: 1001
22+
runAsGroup: 65533
23+
containers:
24+
- name: notion-chart-generator
25+
image: ghcr.io/stevelin100132/notion-chart-generator # Use the image from the kustomization.yaml
26+
ports:
27+
- containerPort: 3000
28+
name: frontend
29+
- containerPort: 3001
30+
name: backend
31+
envFrom:
32+
- configMapRef:
33+
name: notion-chart-generator-config
34+
env:
35+
- name: NODE_ENV
36+
value: "production"
37+
- name: PORT
38+
value: "3000"
39+
- name: BACKEND_PORT
40+
value: "3001"
41+
resources:
42+
requests:
43+
cpu: 100m
44+
memory: 256Mi
45+
ephemeral-storage: 128Mi
46+
limits:
47+
cpu: 500m
48+
memory: 512Mi
49+
ephemeral-storage: 256Mi
50+
livenessProbe:
51+
httpGet:
52+
path: /
53+
port: 3000
54+
initialDelaySeconds: 30
55+
periodSeconds: 10
56+
timeoutSeconds: 5
57+
failureThreshold: 3
58+
readinessProbe:
59+
httpGet:
60+
path: /api/health
61+
port: 3001
62+
initialDelaySeconds: 10
63+
periodSeconds: 10
64+
timeoutSeconds: 5
65+
failureThreshold: 3
66+
volumeMounts:
67+
- name: snapshots-storage
68+
mountPath: /app/backend/snapshots
69+
volumes:
70+
- name: snapshots-storage
71+
persistentVolumeClaim:
72+
claimName: notion-chart-snapshots-pvc
73+
# imagePullSecrets:
74+
# - name: ghcr-secret

k8s/DOKS/ingress.yaml

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
apiVersion: networking.k8s.io/v1
2+
kind: Ingress
3+
metadata:
4+
name: notion-chart-generator-ingress
5+
labels:
6+
app: notion-chart-generator
7+
spec:
8+
ingressClassName: nginx
9+
tls:
10+
- hosts:
11+
- 188-166-204-94.nip.io
12+
secretName: notion-chart-generator-tls
13+
rules:
14+
- host: 188-166-204-94.nip.io
15+
http:
16+
paths:
17+
- path: /api
18+
pathType: Prefix
19+
backend:
20+
service:
21+
name: notion-chart-generator-service
22+
port:
23+
number: 3001
24+
- path: /
25+
pathType: Prefix
26+
backend:
27+
service:
28+
name: notion-chart-generator-service
29+
port:
30+
number: 80

0 commit comments

Comments
 (0)