diff --git a/deploy/k3s/README.md b/deploy/k3s/README.md index 561bcbf..7ec19a9 100644 --- a/deploy/k3s/README.md +++ b/deploy/k3s/README.md @@ -5,7 +5,7 @@ - infra: `postgres`, `monitoring-postgres`, `pgbouncer`, `monitoring-pgbouncer`, `rabbitmq`, `redis`, `qdrant`, `minio` - jobs: `migrate`, `minio-init` - apps: `tenant-api`, `browser-fetch`, `worker-generate`, `kol-assist-worker`, `scheduler`, `ops-api`, `frontend`, `ops-web` -- ingress: `geo-rankly.local` -> `frontend`, `ops.geo-rankly.local` -> `ops-web` +- ingress: `saas.shengxintui.com` -> `frontend`, `ops.shengxintui.com` -> `ops-web`, `api.shengxintui.com` -> `tenant-api` 对象存储部署跟随 `deploy/config.yaml` / `deploy/config.yml` 里的 `object_storage.provider`,并允许 `deploy/config.local.yaml` / `deploy/config.local.yml` 覆盖: @@ -134,12 +134,13 @@ k3s 默认同时支持两种访问方式。 ### 4.1 直接用节点 IP + 端口 -`frontend` 和 `ops-web` 已固定为 NodePort: +`frontend`、`ops-web` 和 `tenant-api` 已固定为 NodePort: - tenant admin: `http://:30080` - ops admin: `http://:30081` +- tenant api: `http://:30083` -这两个 NodePort Service 使用 `externalTrafficPolicy: Local`,用于保留客户端源 IP,后端日志和登录审计会读取规范化后的 `X-Forwarded-For` / `X-Real-IP`。 +这些 NodePort Service 使用 `externalTrafficPolicy: Local`,用于保留客户端源 IP,后端日志和登录审计会读取规范化后的 `X-Forwarded-For` / `X-Real-IP`。 如果通过 k3s 内置 Traefik Ingress 对外提供服务,也需要把 Traefik Service 调整为保留源地址: @@ -153,20 +154,59 @@ kubectl -n kube-system patch svc traefik -p '{"spec":{"externalTrafficPolicy":"L - tenant admin: `http://192.168.100.19:30080` - ops admin: `http://192.168.100.19:30081` +- tenant api: `http://192.168.100.19:30083` -### 4.2 用域名 Ingress +### 4.2 用域名 Ingress + HTTPS -k3s 默认 Traefik 会接管 Ingress。先把域名指到 k3s 节点 IP: +k3s 默认 Traefik 会接管 Ingress。先把域名指到 k3s 节点公网 IP。如果 `www.shengxintui.com` 已经解析到了这个节点,可以把 `saas`、`ops`、`api` 做 CNAME 指向 `www.shengxintui.com`: ```text - geo-rankly.local - ops.geo-rankly.local +saas.shengxintui.com CNAME www.shengxintui.com +ops.shengxintui.com CNAME www.shengxintui.com +api.shengxintui.com CNAME www.shengxintui.com ``` -然后访问: +也可以直接添加 A 记录: -- tenant admin: `http://geo-rankly.local` -- ops admin: `http://ops.geo-rankly.local` +```text +saas.shengxintui.com A +ops.shengxintui.com A +api.shengxintui.com A +``` + +HTTPS 使用 cert-manager + Let's Encrypt 自动签发和续期证书。签发前需要保证公网可以访问 k3s 节点的 80/443 端口;证书签发成功后,cert-manager 会在过期前自动续期。 + +先安装 cert-manager: + +```bash +kubectl apply -f https://github.com/cert-manager/cert-manager/releases/download/v1.20.2/cert-manager.yaml +kubectl -n cert-manager get pods -w +``` + +确认 cert-manager Pod 正常后,安装 Let's Encrypt ClusterIssuer: + +```bash +kubectl apply -f deploy/k3s/addons/letsencrypt-clusterissuer.yaml +``` + +然后部署或更新业务清单: + +```bash +kubectl apply -k deploy/k3s +``` + +访问: + +- tenant admin: `https://saas.shengxintui.com` +- ops admin: `https://ops.shengxintui.com` +- tenant api: `https://api.shengxintui.com` + +检查证书状态: + +```bash +kubectl -n geo-rankly get certificate,challenge,order +kubectl -n geo-rankly describe certificate shengxintui-com-tls +``` 临时调试时也可用端口转发: diff --git a/deploy/k3s/addons/letsencrypt-clusterissuer.yaml b/deploy/k3s/addons/letsencrypt-clusterissuer.yaml new file mode 100644 index 0000000..eaa9c1d --- /dev/null +++ b/deploy/k3s/addons/letsencrypt-clusterissuer.yaml @@ -0,0 +1,30 @@ +# Requires cert-manager to be installed before applying this file. +apiVersion: cert-manager.io/v1 +kind: ClusterIssuer +metadata: + name: letsencrypt-staging +spec: + acme: + email: admin@shengxintui.com + server: https://acme-staging-v02.api.letsencrypt.org/directory + privateKeySecretRef: + name: letsencrypt-staging-account-key + solvers: + - http01: + ingress: + ingressClassName: traefik +--- +apiVersion: cert-manager.io/v1 +kind: ClusterIssuer +metadata: + name: letsencrypt-prod +spec: + acme: + email: admin@shengxintui.com + server: https://acme-v02.api.letsencrypt.org/directory + privateKeySecretRef: + name: letsencrypt-prod-account-key + solvers: + - http01: + ingress: + ingressClassName: traefik diff --git a/deploy/k3s/ingress.yaml b/deploy/k3s/ingress.yaml index fbae74d..170ffee 100644 --- a/deploy/k3s/ingress.yaml +++ b/deploy/k3s/ingress.yaml @@ -3,7 +3,8 @@ kind: Ingress metadata: name: geo-rankly-web annotations: - traefik.ingress.kubernetes.io/router.entrypoints: web + cert-manager.io/cluster-issuer: letsencrypt-prod + traefik.ingress.kubernetes.io/router.entrypoints: websecure spec: ingressClassName: traefik rules: @@ -37,3 +38,9 @@ spec: name: tenant-api port: number: 8080 + tls: + - hosts: + - saas.shengxintui.com + - ops.shengxintui.com + - api.shengxintui.com + secretName: shengxintui-com-tls