Add Kubernetes deployment manifests (#3025)

This commit is contained in:
magicJie
2026-06-30 22:24:03 +08:00
committed by GitHub
parent 327c3a317b
commit a1ccd9947d
5 changed files with 195 additions and 1 deletions
+4 -1
View File
@@ -31,4 +31,7 @@ __pycache__
/shell/preload/lang_env.sh
.deepseek/
.claude/
.claude/
# local Kubernetes overlays
/deploy/kubernetes/overlays/local/
+81
View File
@@ -0,0 +1,81 @@
# Kubernetes deployment
This deploys Qinglong as a single-replica `StatefulSet` with persistent data at `/ql/data`.
```bash
kubectl apply -k deploy/kubernetes/overlays/local
kubectl -n qinglong rollout status statefulset/qinglong
```
Open the panel locally:
```bash
kubectl -n qinglong port-forward svc/qinglong 5700:5700
```
Then visit <http://127.0.0.1:5700>.
## Image registry overlays
Use `overlays/example` as the committed template for registry customization:
```yaml
whyour/qinglong:debian -> registry.example.com/whyour/qinglong:debian
```
Create `overlays/local/kustomization.yaml` for the actual cluster image. The `local` overlay is ignored by git so private registry names, digests, and credentials-related references stay local.
## Storage
The manifest creates a 5 GiB `ReadWriteOnce` PVC from the cluster's default `StorageClass`.
If your cluster has no default storage class, add `storageClassName` under:
```yaml
volumeClaimTemplates:
- metadata:
name: data
spec:
storageClassName: your-storage-class
```
Keep `replicas: 1`. Qinglong stores state in the persistent data directory, including SQLite files, so multiple replicas should not share the same data volume.
## Ingress example
If you expose Qinglong through an Ingress path other than `/`, set `QlBaseUrl` to the same path with leading and trailing slashes.
```yaml
env:
- name: QlBaseUrl
value: "/qinglong/"
```
Example Ingress:
```yaml
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: qinglong
namespace: qinglong
spec:
rules:
- host: qinglong.example.com
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: qinglong
port:
number: 5700
```
## Maintenance commands
```bash
kubectl -n qinglong logs -f statefulset/qinglong
kubectl -n qinglong exec -it statefulset/qinglong -- ql check
kubectl -n qinglong exec -it statefulset/qinglong -- ql update
```
@@ -0,0 +1,5 @@
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
resources:
- qinglong.yaml
+95
View File
@@ -0,0 +1,95 @@
apiVersion: v1
kind: Namespace
metadata:
name: qinglong
---
apiVersion: v1
kind: Service
metadata:
name: qinglong
namespace: qinglong
labels:
app.kubernetes.io/name: qinglong
spec:
type: ClusterIP
selector:
app.kubernetes.io/name: qinglong
ports:
- name: http
port: 5700
targetPort: http
---
apiVersion: apps/v1
kind: StatefulSet
metadata:
name: qinglong
namespace: qinglong
labels:
app.kubernetes.io/name: qinglong
spec:
serviceName: qinglong
replicas: 1
selector:
matchLabels:
app.kubernetes.io/name: qinglong
template:
metadata:
labels:
app.kubernetes.io/name: qinglong
spec:
securityContext:
fsGroup: 5432
fsGroupChangePolicy: OnRootMismatch
containers:
- name: qinglong
image: whyour/qinglong:debian
imagePullPolicy: IfNotPresent
env:
- name: QlBaseUrl
value: "/"
- name: TZ
value: Asia/Shanghai
ports:
- name: http
containerPort: 5700
readinessProbe:
httpGet:
path: /api/health
port: http
initialDelaySeconds: 20
periodSeconds: 10
timeoutSeconds: 3
failureThreshold: 6
livenessProbe:
httpGet:
path: /api/health
port: http
initialDelaySeconds: 60
periodSeconds: 20
timeoutSeconds: 3
failureThreshold: 6
startupProbe:
httpGet:
path: /api/health
port: http
periodSeconds: 5
timeoutSeconds: 3
failureThreshold: 60
resources:
requests:
cpu: 100m
memory: 256Mi
limits:
memory: 1Gi
volumeMounts:
- name: data
mountPath: /ql/data
volumeClaimTemplates:
- metadata:
name: data
spec:
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 5Gi
@@ -0,0 +1,10 @@
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
resources:
- ../../base
images:
- name: whyour/qinglong
newName: registry.example.com/whyour/qinglong
newTag: debian