docs: add Kubernetes deployment guide with overlays structure (#219)

* docs: simplify runtime script usage

Unify to use runtime.sh for all deployment commands, removing the
distinction between "official images" and "Aliyun mirror". The --aliyun
parameter is preserved for users in China to specify the mirror.

Changes:
- Remove runtime-github.sh references, use runtime.sh uniformly
- Default command uses GHCR images
- Add --aliyun parameter for China users
- Update README.md, README_zh.md, and docs/skillhub/ quickstart files

* docs: consolidate documentation links with clear descriptions

Merge the two documentation links into a single "Documentation" section
with clear descriptions of each:
- User Guide: skill publishing, search, CLI usage
- Developer Docs: architecture, API reference, deployment

This makes it easier for users to find the right documentation.

* docs: consolidate documentation links with clear descriptions

Merge the two documentation links into a single "Documentation" section
with clear descriptions of each:
- User Guide: skill publishing, search, CLI usage
- Developer Docs: architecture, API reference, deployment

This makes it easier for users to find the right documentation.

* fix: include --home parameter in shutdown command

When starting with a custom --home directory, the generated shutdown
command now includes the same --home parameter to ensure it can find
the correct compose files.

* docs: add Kubernetes deployment guide with overlays structure

- Restructure k8s configs with base/overlays pattern for flexibility
- Add overlays/with-infra for full deployment (PostgreSQL + Redis)
- Add overlays/external for external database scenarios
- Add comprehensive ConfigMap with bootstrap admin settings
- Fix health check path to /actuator/health (auth issue)
- Add SKILLHUB_API_UPSTREAM env for frontend
- Set SESSION_COOKIE_SECURE=false for HTTP environments
- Add Chinese and English documentation in docs/skillhub/

* docs: update k8s README with complete config reference
This commit is contained in:
XiaoSeS 2026-04-02 21:01:28 +08:00 committed by GitHub
parent 37c25c3f91
commit c0f790079d
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
18 changed files with 1245 additions and 38 deletions

310
deploy/k8s/README.md Normal file
View file

@ -0,0 +1,310 @@
# Kubernetes 部署指南
本文档说明如何在 Kubernetes 集群中部署 SkillHub。
## 前置条件
- Kubernetes 集群 (v1.24+)
- kubectl 已配置并连接到集群
- nginx ingress controller 已安装(可选,用于域名访问)
- 默认 StorageClass 已配置(用于 PVC
## 目录结构
```
deploy/k8s/
├── base/ # 基础配置(所有场景共用)
│ ├── kustomization.yaml
│ ├── configmap.yaml
│ ├── secret.yaml.example
│ ├── services.yaml
│ ├── backend-deployment.yaml
│ ├── frontend-deployment.yaml
│ ├── scanner-deployment.yaml
│ └── ingress.yaml
└── overlays/
├── with-infra/ # 完整部署(包含内置数据库)
│ ├── kustomization.yaml
│ ├── postgres-statefulset.yaml
│ └── redis-statefulset.yaml
└── external/ # 外部数据库
└── kustomization.yaml
```
## 快速开始
### 1. 创建命名空间
```bash
kubectl create namespace skillhub
```
### 2. 配置 Secret
```bash
cd deploy/k8s/base
# 复制示例文件
cp secret.yaml.example secret.yaml
# 编辑 secret.yaml修改敏感配置
```
**Secret 配置项**
| 键 | 说明 | 必填 |
|---|---|---|
| spring-datasource-url | PostgreSQL 连接 URL | 是 |
| spring-datasource-username | 数据库用户名 | 是 |
| spring-datasource-password | 数据库密码 | 是 |
| bootstrap-admin-password | 管理员密码 | 是 |
| oauth2-github-client-id | GitHub OAuth ID | 否 |
| oauth2-github-client-secret | GitHub OAuth 密钥 | 否 |
| skill-scanner-llm-api-key | LLM API 密钥 | 否 |
### 3. 选择部署方式
**方式一:完整部署(包含 PostgreSQL + Redis**
适合全新环境,自动部署数据库:
```bash
kubectl apply -k overlays/with-infra/
```
**方式二:使用外部数据库**
适合已有 PostgreSQL 和 Redis 的环境:
1. 修改 `base/configmap.yaml` 中的 Redis 配置:
```yaml
redis-host: your-redis-host
redis-port: "6379"
```
2. 修改 `base/secret.yaml` 中的数据库连接:
```yaml
spring-datasource-url: jdbc:postgresql://your-postgres-host:5432/skillhub
```
3. 部署:
```bash
kubectl apply -k overlays/external/
```
### 4. 验证部署
```bash
# 检查 Pod 状态
kubectl get pods -n skillhub
# 等待所有 Pod 就绪
kubectl wait --for=condition=ready pod --all -n skillhub --timeout=300s
```
### 5. 访问服务
**方式一:端口转发(推荐本地测试)**
```bash
# 前端
kubectl port-forward svc/skillhub-web -n skillhub 8080:80
# 后端 API
kubectl port-forward svc/skillhub-server -n skillhub 8081:8080
```
访问 http://localhost:8080
**方式二Ingress 域名访问**
修改 `base/ingress.yaml` 中的域名:
```yaml
spec:
rules:
- host: your-domain.com # 修改为你的域名
```
```bash
kubectl apply -k overlays/with-infra/ # 或 overlays/external/
```
## 部署架构
```
┌─────────────────────────────────────────────────────────────┐
│ skillhub namespace │
├─────────────────────────────────────────────────────────────┤
│ ┌─────────────┐ ┌─────────────┐ ┌─────────────────────┐ │
│ │ skillhub-web│ │skillhub- │ │ skillhub-scanner │ │
│ │ (前端) │ │ server │ │ (扫描器) │ │
│ │ :80 │ │ (后端) │ │ :8000 │ │
│ └─────────────┘ │ :8080 │ └─────────────────────┘ │
│ └──────┬──────┘ │
│ │ │
│ ┌────────────────┴────────────────┐ │
│ │ with-infra only │ │
│ │ ┌─────────────┐ ┌───────────┐ │ │
│ │ │ postgres-0 │ │ redis-0 │ │ │
│ │ │ :5432 │ │ :6379 │ │ │
│ │ └─────────────┘ └───────────┘ │ │
│ └─────────────────────────────────┘ │
│ │
│ ┌─────────────────────────────────────────────────────────┐ │
│ │ PersistentVolumeClaims │ │
│ │ - skillhub-storage-pvc (10Gi) │ │
│ │ - postgres-data-0 (10Gi) - with-infra only │ │
│ │ - redis-data-0 (5Gi) - with-infra only │ │
│ └─────────────────────────────────────────────────────────┘ │
└─────────────────────────────────────────────────────────────┘
```
## 配置说明
### ConfigMap 配置项
| 键 | 默认值 | 说明 |
|---|---|---|
| redis-host | redis | Redis 主机地址 |
| redis-port | 6379 | Redis 端口 |
| storage-base-path | /var/lib/skillhub/storage | 技能存储路径 |
| skillhub-storage-provider | local | 存储类型local/s3 |
| skill-scanner-enabled | true | 是否启用扫描器 |
| skill-scanner-url | http://skillhub-scanner:8000 | 扫描器地址 |
| skill-scanner-mode | upload | 扫描模式 |
| bootstrap-admin-enabled | true | 是否创建默认管理员 |
| bootstrap-admin-user-id | docker-admin | 管理员用户 ID |
| bootstrap-admin-username | admin | 管理员用户名 |
| bootstrap-admin-display-name | Platform Admin | 管理员显示名称 |
| bootstrap-admin-email | admin@example.com | 管理员邮箱 |
| session-cookie-secure | false | HTTPS 环境设为 true |
### Secret 配置项
| 键 | 说明 | 必填 |
|---|---|---|
| spring-datasource-url | PostgreSQL 连接 URL | 是 |
| spring-datasource-username | 数据库用户名 | 是 |
| spring-datasource-password | 数据库密码 | 是 |
| bootstrap-admin-password | 管理员密码 | 是 |
| oauth2-github-client-id | GitHub OAuth ID | 否 |
| oauth2-github-client-secret | GitHub OAuth 密钥 | 否 |
| skill-scanner-llm-api-key | LLM API 密钥 | 否 |
| skill-scanner-llm-model | LLM 模型名称 | 否 |
### 存储配置
**本地存储(默认)**
默认使用本地文件存储,数据保存在 PVC `skillhub-storage-pvc` 中。
**S3/OSS 存储**
生产环境建议使用 S3 兼容的对象存储:
1. 修改 ConfigMap
```yaml
skillhub-storage-provider: s3
```
2. 在 Secret 中添加:
```yaml
skillhub-storage-s3-access-key: your-access-key
skillhub-storage-s3-secret-key: your-secret-key
```
3. 在 backend-deployment.yaml 中添加环境变量:
```yaml
- name: SKILLHUB_STORAGE_S3_ENDPOINT
value: https://oss-cn-shanghai.aliyuncs.com
- name: SKILLHUB_STORAGE_S3_BUCKET
value: skillhub-prod
- name: SKILLHUB_STORAGE_S3_REGION
value: cn-shanghai
```
### 持久化存储
| PVC | 大小 | 说明 |
|-----|------|------|
| skillhub-storage-pvc | 10Gi | 技能文件存储 |
| postgres-data-0 | 10Gi | PostgreSQL 数据with-infra only |
| redis-data-0 | 5Gi | Redis 数据with-infra only |
## 镜像说明
| 组件 | 镜像 |
|---|---|
| 后端服务 | ghcr.io/iflytek/skillhub-server:latest |
| 前端服务 | ghcr.io/iflytek/skillhub-web:latest |
| 扫描器 | ghcr.io/iflytek/skillhub-scanner:latest |
| PostgreSQL | postgres:16-alpine |
| Redis | redis:7-alpine |
## 默认管理员
首次启动时,如果 `bootstrap-admin-enabled``true`,系统会自动创建管理员账户:
- 用户名:`admin`
- 密码:在 `secret.yaml``bootstrap-admin-password` 中配置
**安全建议**:首次登录后,请立即修改默认密码。
## 常见问题
### Pod 一直 Pending
```bash
# 检查 PVC 是否绑定
kubectl get pvc -n skillhub
# 检查节点资源
kubectl describe node <node-name>
```
### 镜像拉取失败
如果镜像私有,需要创建拉取凭证:
```bash
kubectl create secret docker-registry ghcr-secret \
--docker-server=ghcr.io \
--docker-username=<GitHub用户名> \
--docker-password=<GitHub Token> \
-n skillhub
```
### 数据库连接失败
```bash
# 检查 PostgreSQL 是否就绪
kubectl logs postgres-0 -n skillhub
# 检查 Secret 配置
kubectl get secret skillhub-secret -n skillhub -o yaml
```
### 查看日志
```bash
# 后端日志
kubectl logs -l app.kubernetes.io/name=skillhub-server -n skillhub -f
# 前端日志
kubectl logs -l app.kubernetes.io/name=skillhub-web -n skillhub -f
# 扫描器日志
kubectl logs -l app.kubernetes.io/name=skillhub-scanner -n skillhub -f
```
## 清理
```bash
# 删除所有资源
kubectl delete -k overlays/with-infra/ # 或 overlays/external/
# 删除命名空间
kubectl delete namespace skillhub
```

View file

@ -24,6 +24,8 @@ spec:
env:
- name: SPRING_PROFILES_ACTIVE
value: docker
# Database
- name: SPRING_DATASOURCE_URL
valueFrom:
secretKeyRef:
@ -39,6 +41,8 @@ spec:
secretKeyRef:
name: skillhub-secret
key: spring-datasource-password
# Redis
- name: SPRING_DATA_REDIS_HOST
valueFrom:
configMapKeyRef:
@ -49,11 +53,20 @@ spec:
configMapKeyRef:
name: skillhub-config
key: redis-port
# Storage
- name: STORAGE_BASE_PATH
valueFrom:
configMapKeyRef:
name: skillhub-config
key: storage-base-path
- name: SKILLHUB_STORAGE_PROVIDER
valueFrom:
configMapKeyRef:
name: skillhub-config
key: skillhub-storage-provider
# Scanner
- name: SKILLHUB_SECURITY_SCANNER_ENABLED
valueFrom:
configMapKeyRef:
@ -69,8 +82,50 @@ spec:
configMapKeyRef:
name: skillhub-config
key: skill-scanner-mode
# Session
- name: SESSION_COOKIE_SECURE
value: "true"
valueFrom:
configMapKeyRef:
name: skillhub-config
key: session-cookie-secure
# Bootstrap Admin (non-sensitive from ConfigMap)
- name: BOOTSTRAP_ADMIN_ENABLED
valueFrom:
configMapKeyRef:
name: skillhub-config
key: bootstrap-admin-enabled
- name: BOOTSTRAP_ADMIN_USER_ID
valueFrom:
configMapKeyRef:
name: skillhub-config
key: bootstrap-admin-user-id
- name: BOOTSTRAP_ADMIN_USERNAME
valueFrom:
configMapKeyRef:
name: skillhub-config
key: bootstrap-admin-username
- name: BOOTSTRAP_ADMIN_DISPLAY_NAME
valueFrom:
configMapKeyRef:
name: skillhub-config
key: bootstrap-admin-display-name
- name: BOOTSTRAP_ADMIN_EMAIL
valueFrom:
configMapKeyRef:
name: skillhub-config
key: bootstrap-admin-email
# Bootstrap Admin Password (sensitive from Secret)
- name: BOOTSTRAP_ADMIN_PASSWORD
valueFrom:
secretKeyRef:
name: skillhub-secret
key: bootstrap-admin-password
optional: true
# OAuth2 GitHub (optional)
- name: OAUTH2_GITHUB_CLIENT_ID
valueFrom:
secretKeyRef:
@ -83,18 +138,19 @@ spec:
name: skillhub-secret
key: oauth2-github-client-secret
optional: true
volumeMounts:
- name: skillhub-storage
mountPath: /var/lib/skillhub/storage
readinessProbe:
httpGet:
path: /actuator/health/readiness
path: /actuator/health
port: http
initialDelaySeconds: 20
periodSeconds: 10
livenessProbe:
httpGet:
path: /actuator/health/liveness
path: /actuator/health
port: http
initialDelaySeconds: 30
periodSeconds: 15

View file

@ -0,0 +1,44 @@
apiVersion: v1
kind: ConfigMap
metadata:
name: skillhub-config
data:
# Redis 配置
# 使用外部 Redis修改为外部主机地址
# 使用内置 Redisoverlays/with-infra保持 redis
redis-host: redis
redis-port: "6379"
# 技能存储路径
storage-base-path: /var/lib/skillhub/storage
# 存储配置
# local: 本地存储(默认), s3: S3/OSS 对象存储
skillhub-storage-provider: local
# 技能扫描器配置
skill-scanner-enabled: "true"
skill-scanner-url: http://skillhub-scanner:8000
skill-scanner-mode: upload
# Bootstrap 管理员配置(非敏感)
bootstrap-admin-enabled: "true"
bootstrap-admin-user-id: docker-admin
bootstrap-admin-username: admin
bootstrap-admin-display-name: Platform Admin
bootstrap-admin-email: admin@example.com
# Session 配置
# HTTP 环境设为 falseHTTPS 环境设为 true
session-cookie-secure: "false"
---
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: skillhub-storage-pvc
spec:
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 10Gi

View file

@ -18,6 +18,9 @@ spec:
- name: web
image: ghcr.io/iflytek/skillhub-web:edge
imagePullPolicy: IfNotPresent
env:
- name: SKILLHUB_API_UPSTREAM
value: http://skillhub-server:8080
ports:
- containerPort: 80
name: http

View file

@ -0,0 +1,26 @@
# 基础配置(所有场景共用)
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
namespace: skillhub
resources:
- configmap.yaml
- services.yaml
- backend-deployment.yaml
- frontend-deployment.yaml
- scanner-deployment.yaml
- ingress.yaml
images:
- name: ghcr.io/iflytek/skillhub-server
newTag: latest
- name: ghcr.io/iflytek/skillhub-web
newTag: latest
- name: ghcr.io/iflytek/skillhub-scanner
newTag: latest
labels:
- pairs:
app.kubernetes.io/part-of: skillhub
app.kubernetes.io/managed-by: kustomize

View file

@ -0,0 +1,31 @@
# SkillHub Secret 配置
# 复制此文件为 secret.yaml 并修改值
# cp secret.yaml.example secret.yaml
apiVersion: v1
kind: Secret
metadata:
name: skillhub-secret
type: Opaque
stringData:
# PostgreSQL 连接配置
# 使用外部数据库:修改主机地址和端口
# 使用内置数据库overlays/with-infra保持 postgres:5432
spring-datasource-url: jdbc:postgresql://postgres:5432/skillhub
spring-datasource-username: skillhub
spring-datasource-password: change-me
# Bootstrap 管理员密码(敏感)
bootstrap-admin-password: ChangeMe!2026
# GitHub OAuth可选用于 GitHub 登录)
oauth2-github-client-id: ""
oauth2-github-client-secret: ""
# LLM 配置(可选,用于技能扫描)
skill-scanner-llm-api-key: ""
skill-scanner-llm-model: ""
# S3 存储配置(可选,使用 S3/OSS 时配置)
skillhub-storage-s3-access-key: ""
skillhub-storage-s3-secret-key: ""

View file

@ -1,22 +0,0 @@
apiVersion: v1
kind: ConfigMap
metadata:
name: skillhub-config
data:
redis-host: redis
redis-port: "6379"
storage-base-path: /var/lib/skillhub/storage
skill-scanner-enabled: "true"
skill-scanner-url: http://skillhub-scanner:8000
skill-scanner-mode: upload
---
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: skillhub-storage-pvc
spec:
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 10Gi

View file

@ -0,0 +1,15 @@
# 外部数据库部署
# 使用方式kubectl apply -k overlays/external/
# 前置条件:修改 base/configmap.yaml 和 secret.yaml 中的数据库连接地址
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
namespace: skillhub
resources:
- ../../base
labels:
- pairs:
app.kubernetes.io/deployment: external-db

View file

@ -0,0 +1,16 @@
# 完整部署(包含内置 PostgreSQL + Redis
# 使用方式kubectl apply -k overlays/with-infra/
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
namespace: skillhub
resources:
- postgres-statefulset.yaml
- redis-statefulset.yaml
- ../../base
labels:
- pairs:
app.kubernetes.io/deployment: with-infra

View file

@ -0,0 +1,86 @@
apiVersion: apps/v1
kind: StatefulSet
metadata:
name: postgres
labels:
app.kubernetes.io/name: postgres
spec:
serviceName: postgres
replicas: 1
selector:
matchLabels:
app.kubernetes.io/name: postgres
template:
metadata:
labels:
app.kubernetes.io/name: postgres
spec:
containers:
- name: postgres
image: postgres:16-alpine
ports:
- containerPort: 5432
name: postgres
env:
- name: POSTGRES_DB
value: skillhub
- name: POSTGRES_USER
valueFrom:
secretKeyRef:
name: skillhub-secret
key: spring-datasource-username
- name: POSTGRES_PASSWORD
valueFrom:
secretKeyRef:
name: skillhub-secret
key: spring-datasource-password
volumeMounts:
- name: postgres-data
mountPath: /var/lib/postgresql/data
readinessProbe:
exec:
command:
- pg_isready
- -U
- skillhub
initialDelaySeconds: 10
periodSeconds: 10
livenessProbe:
exec:
command:
- pg_isready
- -U
- skillhub
initialDelaySeconds: 30
periodSeconds: 15
resources:
requests:
cpu: 100m
memory: 256Mi
limits:
cpu: 500m
memory: 512Mi
volumeClaimTemplates:
- metadata:
name: postgres-data
spec:
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 10Gi
---
apiVersion: v1
kind: Service
metadata:
name: postgres
labels:
app.kubernetes.io/name: postgres
spec:
type: ClusterIP
ports:
- port: 5432
targetPort: postgres
name: postgres
selector:
app.kubernetes.io/name: postgres

View file

@ -0,0 +1,75 @@
apiVersion: apps/v1
kind: StatefulSet
metadata:
name: redis
labels:
app.kubernetes.io/name: redis
spec:
serviceName: redis
replicas: 1
selector:
matchLabels:
app.kubernetes.io/name: redis
template:
metadata:
labels:
app.kubernetes.io/name: redis
spec:
containers:
- name: redis
image: redis:7-alpine
ports:
- containerPort: 6379
name: redis
command:
- redis-server
- --appendonly
- "yes"
volumeMounts:
- name: redis-data
mountPath: /data
readinessProbe:
exec:
command:
- redis-cli
- ping
initialDelaySeconds: 5
periodSeconds: 10
livenessProbe:
exec:
command:
- redis-cli
- ping
initialDelaySeconds: 10
periodSeconds: 15
resources:
requests:
cpu: 50m
memory: 128Mi
limits:
cpu: 200m
memory: 256Mi
volumeClaimTemplates:
- metadata:
name: redis-data
spec:
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 5Gi
---
apiVersion: v1
kind: Service
metadata:
name: redis
labels:
app.kubernetes.io/name: redis
spec:
type: ClusterIP
ports:
- port: 6379
targetPort: redis
name: redis
selector:
app.kubernetes.io/name: redis

View file

@ -1,13 +0,0 @@
apiVersion: v1
kind: Secret
metadata:
name: skillhub-secret
type: Opaque
stringData:
spring-datasource-url: jdbc:postgresql://postgres:5432/skillhub
spring-datasource-username: skillhub
spring-datasource-password: change-me
oauth2-github-client-id: your-client-id
oauth2-github-client-secret: your-client-secret
skill-scanner-llm-api-key: your-llm-api-key
skill-scanner-llm-model: openai/astron-code-latest

View file

@ -43,6 +43,7 @@ export default defineConfig({
{
text: '更多',
items: [
{ text: 'Kubernetes 部署', link: '/guide/kubernetes' },
{ text: '常见问题', link: '/faq' },
],
},
@ -87,6 +88,7 @@ export default defineConfig({
{
text: 'More',
items: [
{ text: 'Kubernetes Deployment', link: '/en/guide/kubernetes' },
{ text: 'FAQ', link: '/en/faq' },
],
},

View file

@ -0,0 +1,289 @@
# Kubernetes Deployment Guide
This document explains how to deploy SkillHub on a Kubernetes cluster.
## Prerequisites
- Kubernetes cluster (v1.24+)
- kubectl configured and connected to the cluster
- nginx ingress controller installed (optional, for domain access)
- Default StorageClass configured (for PVC)
## Directory Structure
```
deploy/k8s/
├── base/ # Base configuration (shared by all scenarios)
│ ├── kustomization.yaml
│ ├── configmap.yaml
│ ├── secret.yaml.example
│ ├── services.yaml
│ ├── backend-deployment.yaml
│ ├── frontend-deployment.yaml
│ ├── scanner-deployment.yaml
│ └── ingress.yaml
└── overlays/
├── with-infra/ # Full deployment (with built-in database)
│ ├── kustomization.yaml
│ ├── postgres-statefulset.yaml
│ └── redis-statefulset.yaml
└── external/ # External database
└── kustomization.yaml
```
## Quick Start
### 1. Create Namespace
```bash
kubectl create namespace skillhub
```
### 2. Configure Secret
```bash
cd deploy/k8s/base
# Copy example file
cp secret.yaml.example secret.yaml
# Edit secret.yaml with your configuration
```
**Secret Configuration Items**:
| Key | Description | Required |
|---|---|---|
| spring-datasource-url | PostgreSQL connection URL | Yes |
| spring-datasource-username | Database username | Yes |
| spring-datasource-password | Database password | Yes |
| bootstrap-admin-password | Admin password | Yes |
| oauth2-github-client-id | GitHub OAuth ID | No |
| oauth2-github-client-secret | GitHub OAuth secret | No |
| skill-scanner-llm-api-key | LLM API key | No |
### 3. Choose Deployment Method
**Option 1: Full Deployment (with PostgreSQL + Redis)**
Suitable for new environments, automatically deploys databases:
```bash
kubectl apply -k overlays/with-infra/
```
**Option 2: Use External Database**
Suitable for environments with existing PostgreSQL and Redis:
1. Modify Redis configuration in `base/configmap.yaml`:
```yaml
redis-host: your-redis-host
redis-port: "6379"
```
2. Modify database connection in `base/secret.yaml`:
```yaml
spring-datasource-url: jdbc:postgresql://your-postgres-host:5432/skillhub
```
3. Deploy:
```bash
kubectl apply -k overlays/external/
```
### 4. Verify Deployment
```bash
# Check Pod status
kubectl get pods -n skillhub
# Wait for all Pods to be ready
kubectl wait --for=condition=ready pod --all -n skillhub --timeout=300s
```
### 5. Access Services
**Option 1: Port Forwarding (recommended for local testing)**
```bash
# Frontend
kubectl port-forward svc/skillhub-web -n skillhub 8080:80
# Backend API
kubectl port-forward svc/skillhub-server -n skillhub 8081:8080
```
Visit http://localhost:8080
**Option 2: Ingress Domain Access**
Modify the domain in `base/ingress.yaml`:
```yaml
spec:
rules:
- host: your-domain.com # Change to your domain
```
```bash
kubectl apply -k overlays/with-infra/ # or overlays/external/
```
## Deployment Architecture
```
┌─────────────────────────────────────────────────────────────┐
│ skillhub namespace │
├─────────────────────────────────────────────────────────────┤
│ ┌─────────────┐ ┌─────────────┐ ┌─────────────────────┐ │
│ │ skillhub-web│ │skillhub- │ │ skillhub-scanner │ │
│ │ (frontend) │ │ server │ │ (scanner) │ │
│ │ :80 │ │ (backend) │ │ :8000 │ │
│ └─────────────┘ │ :8080 │ └─────────────────────┘ │
│ └──────┬──────┘ │
│ │ │
│ ┌────────────────┴────────────────┐ │
│ │ with-infra only │ │
│ │ ┌─────────────┐ ┌───────────┐ │ │
│ │ │ postgres-0 │ │ redis-0 │ │ │
│ │ │ :5432 │ │ :6379 │ │ │
│ │ └─────────────┘ └───────────┘ │ │
│ └─────────────────────────────────┘ │
│ │
│ ┌─────────────────────────────────────────────────────────┐ │
│ │ PersistentVolumeClaims │ │
│ │ - skillhub-storage-pvc (10Gi) │ │
│ │ - postgres-data-0 (10Gi) - with-infra only │ │
│ │ - redis-data-0 (5Gi) - with-infra only │ │
│ └─────────────────────────────────────────────────────────┘ │
└─────────────────────────────────────────────────────────────┘
```
## Configuration Reference
### ConfigMap Items
| Key | Default | Description |
|---|---|---|
| redis-host | redis | Redis host address |
| redis-port | 6379 | Redis port |
| storage-base-path | /var/lib/skillhub/storage | Skill storage path |
| skillhub-storage-provider | local | Storage type (local/s3) |
| skill-scanner-enabled | true | Enable scanner |
| skill-scanner-url | http://skillhub-scanner:8000 | Scanner URL |
| skill-scanner-mode | upload | Scan mode |
| bootstrap-admin-enabled | true | Create default admin |
| bootstrap-admin-user-id | docker-admin | Admin user ID |
| bootstrap-admin-username | admin | Admin username |
| bootstrap-admin-display-name | Platform Admin | Admin display name |
| bootstrap-admin-email | admin@example.com | Admin email |
| session-cookie-secure | false | Set to true for HTTPS |
### Storage Configuration
**Local Storage (Default)**
Uses local file storage by default, data is stored in PVC `skillhub-storage-pvc`.
**S3/OSS Storage**
For production, S3-compatible object storage is recommended:
1. Modify ConfigMap:
```yaml
skillhub-storage-provider: s3
```
2. Add to Secret:
```yaml
skillhub-storage-s3-access-key: your-access-key
skillhub-storage-s3-secret-key: your-secret-key
```
3. Add environment variables to backend-deployment.yaml:
```yaml
- name: SKILLHUB_STORAGE_S3_ENDPOINT
value: https://s3.amazonaws.com
- name: SKILLHUB_STORAGE_S3_BUCKET
value: skillhub-prod
- name: SKILLHUB_STORAGE_S3_REGION
value: us-east-1
```
### Image Reference
| Component | Image |
|---|---|
| Backend | ghcr.io/iflytek/skillhub-server:latest |
| Frontend | ghcr.io/iflytek/skillhub-web:latest |
| Scanner | ghcr.io/iflytek/skillhub-scanner:latest |
| PostgreSQL | postgres:16-alpine |
| Redis | redis:7-alpine |
## Default Admin
On first startup, if `bootstrap-admin-enabled` is `true`, the system will automatically create an admin account:
- Username: `admin`
- Password: Configured in `secret.yaml` as `bootstrap-admin-password`
**Security Note**: Please change the default password immediately after first login.
## Troubleshooting
### Pod Stuck in Pending
```bash
# Check PVC binding
kubectl get pvc -n skillhub
# Check node resources
kubectl describe node <node-name>
```
### Image Pull Failure
If images are private, create pull credentials:
```bash
kubectl create secret docker-registry ghcr-secret \
--docker-server=ghcr.io \
--docker-username=<GitHub-username> \
--docker-password=<GitHub-Token> \
-n skillhub
```
### Database Connection Failure
```bash
# Check PostgreSQL status
kubectl logs postgres-0 -n skillhub
# Check Secret configuration
kubectl get secret skillhub-secret -n skillhub -o yaml
```
### View Logs
```bash
# Backend logs
kubectl logs -l app.kubernetes.io/name=skillhub-server -n skillhub -f
# Frontend logs
kubectl logs -l app.kubernetes.io/name=skillhub-web -n skillhub -f
# Scanner logs
kubectl logs -l app.kubernetes.io/name=skillhub-scanner -n skillhub -f
```
## Cleanup
```bash
# Delete all resources
kubectl delete -k overlays/with-infra/ # or overlays/external/
# Delete namespace
kubectl delete namespace skillhub
```

View file

@ -0,0 +1,289 @@
# Kubernetes 部署指南
本文档说明如何在 Kubernetes 集群中部署 SkillHub。
## 前置条件
- Kubernetes 集群 (v1.24+)
- kubectl 已配置并连接到集群
- nginx ingress controller 已安装(可选,用于域名访问)
- 默认 StorageClass 已配置(用于 PVC
## 目录结构
```
deploy/k8s/
├── base/ # 基础配置(所有场景共用)
│ ├── kustomization.yaml
│ ├── configmap.yaml
│ ├── secret.yaml.example
│ ├── services.yaml
│ ├── backend-deployment.yaml
│ ├── frontend-deployment.yaml
│ ├── scanner-deployment.yaml
│ └── ingress.yaml
└── overlays/
├── with-infra/ # 完整部署(包含内置数据库)
│ ├── kustomization.yaml
│ ├── postgres-statefulset.yaml
│ └── redis-statefulset.yaml
└── external/ # 外部数据库
└── kustomization.yaml
```
## 快速开始
### 1. 创建命名空间
```bash
kubectl create namespace skillhub
```
### 2. 配置 Secret
```bash
cd deploy/k8s/base
# 复制示例文件
cp secret.yaml.example secret.yaml
# 编辑 secret.yaml修改敏感配置
```
**Secret 配置项**
| 键 | 说明 | 必填 |
|---|---|---|
| spring-datasource-url | PostgreSQL 连接 URL | 是 |
| spring-datasource-username | 数据库用户名 | 是 |
| spring-datasource-password | 数据库密码 | 是 |
| bootstrap-admin-password | 管理员密码 | 是 |
| oauth2-github-client-id | GitHub OAuth ID | 否 |
| oauth2-github-client-secret | GitHub OAuth 密钥 | 否 |
| skill-scanner-llm-api-key | LLM API 密钥 | 否 |
### 3. 选择部署方式
**方式一:完整部署(包含 PostgreSQL + Redis**
适合全新环境,自动部署数据库:
```bash
kubectl apply -k overlays/with-infra/
```
**方式二:使用外部数据库**
适合已有 PostgreSQL 和 Redis 的环境:
1. 修改 `base/configmap.yaml` 中的 Redis 配置:
```yaml
redis-host: your-redis-host
redis-port: "6379"
```
2. 修改 `base/secret.yaml` 中的数据库连接:
```yaml
spring-datasource-url: jdbc:postgresql://your-postgres-host:5432/skillhub
```
3. 部署:
```bash
kubectl apply -k overlays/external/
```
### 4. 验证部署
```bash
# 检查 Pod 状态
kubectl get pods -n skillhub
# 等待所有 Pod 就绪
kubectl wait --for=condition=ready pod --all -n skillhub --timeout=300s
```
### 5. 访问服务
**方式一:端口转发(推荐本地测试)**
```bash
# 前端
kubectl port-forward svc/skillhub-web -n skillhub 8080:80
# 后端 API
kubectl port-forward svc/skillhub-server -n skillhub 8081:8080
```
访问 http://localhost:8080
**方式二Ingress 域名访问**
修改 `base/ingress.yaml` 中的域名:
```yaml
spec:
rules:
- host: your-domain.com # 修改为你的域名
```
```bash
kubectl apply -k overlays/with-infra/ # 或 overlays/external/
```
## 部署架构
```
┌─────────────────────────────────────────────────────────────┐
│ skillhub namespace │
├─────────────────────────────────────────────────────────────┤
│ ┌─────────────┐ ┌─────────────┐ ┌─────────────────────┐ │
│ │ skillhub-web│ │skillhub- │ │ skillhub-scanner │ │
│ │ (前端) │ │ server │ │ (扫描器) │ │
│ │ :80 │ │ (后端) │ │ :8000 │ │
│ └─────────────┘ │ :8080 │ └─────────────────────┘ │
│ └──────┬──────┘ │
│ │ │
│ ┌────────────────┴────────────────┐ │
│ │ with-infra only │ │
│ │ ┌─────────────┐ ┌───────────┐ │ │
│ │ │ postgres-0 │ │ redis-0 │ │ │
│ │ │ :5432 │ │ :6379 │ │ │
│ │ └─────────────┘ └───────────┘ │ │
│ └─────────────────────────────────┘ │
│ │
│ ┌─────────────────────────────────────────────────────────┐ │
│ │ PersistentVolumeClaims │ │
│ │ - skillhub-storage-pvc (10Gi) │ │
│ │ - postgres-data-0 (10Gi) - with-infra only │ │
│ │ - redis-data-0 (5Gi) - with-infra only │ │
│ └─────────────────────────────────────────────────────────┘ │
└─────────────────────────────────────────────────────────────┘
```
## 配置说明
### ConfigMap 配置项
| 键 | 默认值 | 说明 |
|---|---|---|
| redis-host | redis | Redis 主机地址 |
| redis-port | 6379 | Redis 端口 |
| storage-base-path | /var/lib/skillhub/storage | 技能存储路径 |
| skillhub-storage-provider | local | 存储类型local/s3 |
| skill-scanner-enabled | true | 是否启用扫描器 |
| skill-scanner-url | http://skillhub-scanner:8000 | 扫描器地址 |
| skill-scanner-mode | upload | 扫描模式 |
| bootstrap-admin-enabled | true | 是否创建默认管理员 |
| bootstrap-admin-user-id | docker-admin | 管理员用户 ID |
| bootstrap-admin-username | admin | 管理员用户名 |
| bootstrap-admin-display-name | Platform Admin | 管理员显示名称 |
| bootstrap-admin-email | admin@example.com | 管理员邮箱 |
| session-cookie-secure | false | HTTPS 环境设为 true |
### 存储配置
**本地存储(默认)**
默认使用本地文件存储,数据保存在 PVC `skillhub-storage-pvc` 中。
**S3/OSS 存储**
生产环境建议使用 S3 兼容的对象存储:
1. 修改 ConfigMap
```yaml
skillhub-storage-provider: s3
```
2. 在 Secret 中添加:
```yaml
skillhub-storage-s3-access-key: your-access-key
skillhub-storage-s3-secret-key: your-secret-key
```
3. 在 backend-deployment.yaml 中添加环境变量:
```yaml
- name: SKILLHUB_STORAGE_S3_ENDPOINT
value: https://oss-cn-shanghai.aliyuncs.com
- name: SKILLHUB_STORAGE_S3_BUCKET
value: skillhub-prod
- name: SKILLHUB_STORAGE_S3_REGION
value: cn-shanghai
```
### 镜像说明
| 组件 | 镜像 |
|---|---|
| 后端服务 | ghcr.io/iflytek/skillhub-server:latest |
| 前端服务 | ghcr.io/iflytek/skillhub-web:latest |
| 扫描器 | ghcr.io/iflytek/skillhub-scanner:latest |
| PostgreSQL | postgres:16-alpine |
| Redis | redis:7-alpine |
## 默认管理员
首次启动时,如果 `bootstrap-admin-enabled``true`,系统会自动创建管理员账户:
- 用户名:`admin`
- 密码:在 `secret.yaml``bootstrap-admin-password` 中配置
**安全建议**:首次登录后,请立即修改默认密码。
## 常见问题
### Pod 一直 Pending
```bash
# 检查 PVC 是否绑定
kubectl get pvc -n skillhub
# 检查节点资源
kubectl describe node <node-name>
```
### 镜像拉取失败
如果镜像私有,需要创建拉取凭证:
```bash
kubectl create secret docker-registry ghcr-secret \
--docker-server=ghcr.io \
--docker-username=<GitHub用户名> \
--docker-password=<GitHub Token> \
-n skillhub
```
### 数据库连接失败
```bash
# 检查 PostgreSQL 是否就绪
kubectl logs postgres-0 -n skillhub
# 检查 Secret 配置
kubectl get secret skillhub-secret -n skillhub -o yaml
```
### 查看日志
```bash
# 后端日志
kubectl logs -l app.kubernetes.io/name=skillhub-server -n skillhub -f
# 前端日志
kubectl logs -l app.kubernetes.io/name=skillhub-web -n skillhub -f
# 扫描器日志
kubectl logs -l app.kubernetes.io/name=skillhub-scanner -n skillhub -f
```
## 清理
```bash
# 删除所有资源
kubectl delete -k overlays/with-infra/ # 或 overlays/external/
# 删除命名空间
kubectl delete namespace skillhub
```