kra-new/deploy/k8s/kra.yaml

439 lines
13 KiB
YAML
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# Template variables (rendered by Jenkins `envsubst "$K8S_RENDER_VARS"`):
# KRA_APP application name, derives every resource name
# KRA_NAMESPACE target namespace
# KRA_ENV development | production
# KRA_REPLICAS replicas per deployment
# KRA_FRONTEND_NODEPORT node port for the frontend service
# KRA_BACKEND_NODEPORT node port for the backend debug service
# KRA_MYSQL_IMAGE mysql server image
# KRA_REDIS_IMAGE redis server image
# KRA_BACKEND_IMAGE backend image built by Jenkins
# KRA_FRONTEND_IMAGE frontend image built by Jenkins
# BIN_NAME backend binary name inside the image
apiVersion: v1
kind: Namespace
metadata:
name: ${KRA_NAMESPACE}
labels:
app.kubernetes.io/part-of: ${KRA_APP}
app.kubernetes.io/managed-by: jenkins
---
apiVersion: apps/v1
kind: StatefulSet
metadata:
name: ${KRA_APP}-mysql
namespace: ${KRA_NAMESPACE}
labels:
app.kubernetes.io/name: ${KRA_APP}-mysql
app.kubernetes.io/part-of: ${KRA_APP}
spec:
serviceName: ${KRA_APP}-mysql
replicas: 1
selector:
matchLabels:
app.kubernetes.io/name: ${KRA_APP}-mysql
template:
metadata:
labels:
app.kubernetes.io/name: ${KRA_APP}-mysql
app.kubernetes.io/part-of: ${KRA_APP}
spec:
automountServiceAccountToken: false
containers:
- name: mysql
image: ${KRA_MYSQL_IMAGE}
imagePullPolicy: IfNotPresent
ports:
- name: mysql
containerPort: 3306
env:
- name: MYSQL_DATABASE
value: ${KRA_APP}
- name: MYSQL_ROOT_PASSWORD
valueFrom:
secretKeyRef:
name: ${KRA_APP}-runtime
key: mysql-root-password
volumeMounts:
- name: mysql-data
mountPath: /var/lib/mysql
readinessProbe:
exec:
command: ["sh", "-c", "mysqladmin ping -h 127.0.0.1 -uroot -p\"$MYSQL_ROOT_PASSWORD\" --silent"]
initialDelaySeconds: 20
periodSeconds: 10
timeoutSeconds: 5
failureThreshold: 12
livenessProbe:
exec:
command: ["sh", "-c", "mysqladmin ping -h 127.0.0.1 -uroot -p\"$MYSQL_ROOT_PASSWORD\" --silent"]
initialDelaySeconds: 60
periodSeconds: 20
timeoutSeconds: 5
resources:
requests:
cpu: 250m
memory: 512Mi
limits:
cpu: 1
memory: 2Gi
volumes:
- name: mysql-data
hostPath:
path: /var/lib/${KRA_APP}/mysql
type: DirectoryOrCreate
---
apiVersion: v1
kind: Service
metadata:
name: ${KRA_APP}-mysql
namespace: ${KRA_NAMESPACE}
spec:
clusterIP: None
selector:
app.kubernetes.io/name: ${KRA_APP}-mysql
ports:
- name: mysql
port: 3306
targetPort: mysql
---
apiVersion: v1
kind: Service
metadata:
name: ${KRA_APP}-redis
namespace: ${KRA_NAMESPACE}
spec:
selector:
app.kubernetes.io/name: ${KRA_APP}-redis
ports:
- name: redis
port: 6379
targetPort: redis
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: ${KRA_APP}-redis
namespace: ${KRA_NAMESPACE}
labels:
app.kubernetes.io/name: ${KRA_APP}-redis
app.kubernetes.io/part-of: ${KRA_APP}
spec:
replicas: 1
selector:
matchLabels:
app.kubernetes.io/name: ${KRA_APP}-redis
template:
metadata:
labels:
app.kubernetes.io/name: ${KRA_APP}-redis
app.kubernetes.io/part-of: ${KRA_APP}
spec:
automountServiceAccountToken: false
initContainers:
- name: prepare-redis-storage
image: ${KRA_REDIS_IMAGE}
imagePullPolicy: IfNotPresent
securityContext:
runAsUser: 0
runAsGroup: 0
command: ["sh", "-c"]
args:
- chown -R redis:redis /data
volumeMounts:
- name: redis-data
mountPath: /data
affinity:
podAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
- topologyKey: kubernetes.io/hostname
labelSelector:
matchLabels:
app.kubernetes.io/name: ${KRA_APP}-mysql
containers:
- name: redis
image: ${KRA_REDIS_IMAGE}
imagePullPolicy: IfNotPresent
ports:
- name: redis
containerPort: 6379
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: 15
periodSeconds: 20
resources:
requests:
cpu: 50m
memory: 64Mi
limits:
cpu: 250m
memory: 512Mi
volumes:
- name: redis-data
hostPath:
path: /var/lib/${KRA_APP}/redis
type: DirectoryOrCreate
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: ${KRA_APP}-backend
namespace: ${KRA_NAMESPACE}
labels:
app.kubernetes.io/name: ${KRA_APP}-backend
app.kubernetes.io/part-of: ${KRA_APP}
spec:
replicas: ${KRA_REPLICAS}
revisionHistoryLimit: 3
strategy:
type: RollingUpdate
rollingUpdate:
maxUnavailable: 1
maxSurge: 1
selector:
matchLabels:
app.kubernetes.io/name: ${KRA_APP}-backend
template:
metadata:
labels:
app.kubernetes.io/name: ${KRA_APP}-backend
app.kubernetes.io/part-of: ${KRA_APP}
spec:
securityContext:
fsGroup: 1000
fsGroupChangePolicy: OnRootMismatch
automountServiceAccountToken: false
initContainers:
- name: wait-for-mysql
image: ${KRA_MYSQL_IMAGE}
imagePullPolicy: IfNotPresent
command: ["sh", "-c"]
args:
- >-
until mysqladmin ping -h "${KRA_APP}-mysql" -P 3306
--connect-timeout=2 --silent;
do sleep 2; done
# 这里只等待 MySQL 服务可达,不要求应用数据库已经初始化;首次部署
# 仍需进入 bootstrap 模式完成 /init/initdb 向导。
- name: initialize-shared-storage
image: ${KRA_BACKEND_IMAGE}
imagePullPolicy: Always
securityContext:
runAsUser: 0
runAsGroup: 0
command: ["sh", "-c"]
args:
- >-
mkdir -p /data/conf /app/uploads;
if [ ! -f /data/conf/config.yaml ]; then
cp /bootstrap/config.yaml /data/conf/config.yaml;
fi;
chown 1000:1000 /data/conf /data/conf/config.yaml /app/uploads;
chmod u+rwX,g+rwX /data/conf /data/conf/config.yaml /app/uploads
volumeMounts:
- name: config
mountPath: /data/conf
- name: uploads
mountPath: /app/uploads
- name: config-template
mountPath: /bootstrap
readOnly: true
# /data/conf 由初始化容器从 Secret 初始化到节点共享目录,
# 目录必须可写:初始化向导会把数据库连接写回该文件。
imagePullSecrets:
- name: harbor-registry
affinity:
podAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
- topologyKey: kubernetes.io/hostname
labelSelector:
matchLabels:
app.kubernetes.io/name: ${KRA_APP}-mysql
podAntiAffinity:
preferredDuringSchedulingIgnoredDuringExecution:
- weight: 100
podAffinityTerm:
topologyKey: kubernetes.io/hostname
labelSelector:
matchLabels:
app.kubernetes.io/name: ${KRA_APP}-backend
containers:
- name: backend
image: ${KRA_BACKEND_IMAGE}
imagePullPolicy: Always
command: ["./${BIN_NAME}"]
args: ["-conf", "/data/conf"]
ports:
- name: http
containerPort: 8000
env:
# 数据库连接不在这里注入:应用启动时未配置数据库会进入 bootstrap 模式,
# 首页出现"前往初始化",由 /init/initdb 建表、写入种子数据并持久化连接配置。
# JWT 签名密钥由 /data/conf/config.yaml 唯一管理,避免环境变量覆盖管理页面的配置变更;
# Redis 地址已在下方 config.yaml 中指定。
- name: KRA_ADMIN_SYSTEM_USE_REDIS
value: "true"
volumeMounts:
- name: config
mountPath: /data/conf
- name: uploads
mountPath: /app/uploads
readinessProbe:
httpGet:
path: /health
port: http
initialDelaySeconds: 10
periodSeconds: 10
timeoutSeconds: 3
failureThreshold: 6
livenessProbe:
httpGet:
path: /health
port: http
initialDelaySeconds: 30
periodSeconds: 20
timeoutSeconds: 3
failureThreshold: 3
resources:
requests:
cpu: 100m
memory: 256Mi
limits:
cpu: 500m
memory: 1Gi
volumes:
# 当前是单节点集群required podAffinity 保证所有后端副本落在
# MySQL 所在节点,从而共享同一组 hostPath 目录。它不是真正的 RWX。
# 扩展到多节点前,必须换成 PVC + 真正的共享存储(如 NFS/CephFS
- name: config
hostPath:
path: /var/lib/${KRA_APP}/conf
type: DirectoryOrCreate
- name: uploads
hostPath:
path: /var/lib/${KRA_APP}/uploads
type: DirectoryOrCreate
- name: config-template
secret:
secretName: ${KRA_APP}-config-template
---
apiVersion: v1
kind: Service
metadata:
name: ${KRA_APP}-backend
namespace: ${KRA_NAMESPACE}
labels:
app.kubernetes.io/name: ${KRA_APP}-backend
spec:
type: ClusterIP
selector:
app.kubernetes.io/name: ${KRA_APP}-backend
ports:
- name: http
port: 8000
targetPort: http
---
apiVersion: v1
kind: Service
metadata:
name: ${KRA_APP}-backend-nodeport
namespace: ${KRA_NAMESPACE}
spec:
type: NodePort
selector:
app.kubernetes.io/name: ${KRA_APP}-backend
ports:
- name: http
port: 8000
targetPort: http
nodePort: ${KRA_BACKEND_NODEPORT}
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: ${KRA_APP}-frontend
namespace: ${KRA_NAMESPACE}
labels:
app.kubernetes.io/name: ${KRA_APP}-frontend
app.kubernetes.io/part-of: ${KRA_APP}
spec:
replicas: ${KRA_REPLICAS}
revisionHistoryLimit: 3
strategy:
type: RollingUpdate
rollingUpdate:
maxUnavailable: 1
maxSurge: 1
selector:
matchLabels:
app.kubernetes.io/name: ${KRA_APP}-frontend
template:
metadata:
labels:
app.kubernetes.io/name: ${KRA_APP}-frontend
app.kubernetes.io/part-of: ${KRA_APP}
spec:
automountServiceAccountToken: false
imagePullSecrets:
- name: harbor-registry
affinity:
podAntiAffinity:
preferredDuringSchedulingIgnoredDuringExecution:
- weight: 100
podAffinityTerm:
topologyKey: kubernetes.io/hostname
labelSelector:
matchLabels:
app.kubernetes.io/name: ${KRA_APP}-frontend
containers:
- name: frontend
image: ${KRA_FRONTEND_IMAGE}
imagePullPolicy: Always
ports:
- name: http
containerPort: 80
readinessProbe:
httpGet:
path: /
port: http
initialDelaySeconds: 5
periodSeconds: 10
livenessProbe:
httpGet:
path: /
port: http
initialDelaySeconds: 15
periodSeconds: 20
resources:
requests:
cpu: 50m
memory: 64Mi
limits:
cpu: 250m
memory: 256Mi
---
apiVersion: v1
kind: Service
metadata:
name: ${KRA_APP}-frontend
namespace: ${KRA_NAMESPACE}
spec:
type: NodePort
selector:
app.kubernetes.io/name: ${KRA_APP}-frontend
ports:
- name: http
port: 80
targetPort: http
nodePort: ${KRA_FRONTEND_NODEPORT}