diff --git a/chart/.helmignore b/chart/.helmignore new file mode 100644 index 0000000..0e8a0eb --- /dev/null +++ b/chart/.helmignore @@ -0,0 +1,23 @@ +# Patterns to ignore when building packages. +# This supports shell glob matching, relative path matching, and +# negation (prefixed with !). Only one pattern per line. +.DS_Store +# Common VCS dirs +.git/ +.gitignore +.bzr/ +.bzrignore +.hg/ +.hgignore +.svn/ +# Common backup files +*.swp +*.bak +*.tmp +*.orig +*~ +# Various IDEs +.project +.idea/ +*.tmproj +.vscode/ diff --git a/chart/Chart.yaml b/chart/Chart.yaml new file mode 100644 index 0000000..743310e --- /dev/null +++ b/chart/Chart.yaml @@ -0,0 +1,24 @@ +apiVersion: v2 +name: neo-blog +description: A Helm chart for Kubernetes + +# A chart can be either an 'application' or a 'library' chart. +# +# Application charts are a collection of templates that can be packaged into versioned archives +# to be deployed. +# +# Library charts provide useful utilities or functions for the chart developer. They're included as +# a dependency of application charts to inject those utilities and functions into the rendering +# pipeline. Library charts do not define any templates and therefore cannot be deployed. +type: application + +# This is the chart version. This version number should be incremented each time you make changes +# to the chart and its templates, including the app version. +# Versions are expected to follow Semantic Versioning (https://semver.org/) +version: 0.1.0 + +# This is the version number of the application being deployed. This version number should be +# incremented each time you make changes to the application. Versions are not expected to +# follow Semantic Versioning. They should reflect the version the application is using. +# It is recommended to use it with quotes. +appVersion: "latest" diff --git a/chart/templates/_helpers.tpl b/chart/templates/_helpers.tpl new file mode 100644 index 0000000..f8089bb --- /dev/null +++ b/chart/templates/_helpers.tpl @@ -0,0 +1,77 @@ +{{/* +Expand the name of the chart. +*/}} +{{- define "neo-blog.name" -}} +{{- default .Chart.Name .Values.nameOverride | trunc 63 | trimSuffix "-" }} +{{- end }} + +{{/* +Create a default fully qualified app name. +We truncate at 63 chars because some Kubernetes name fields are limited to this (by the DNS naming spec). +If release name contains chart name it will be used as a full name. +*/}} +{{- define "neo-blog.fullname" -}} +{{- if .Values.fullnameOverride }} +{{- .Values.fullnameOverride | trunc 63 | trimSuffix "-" }} +{{- else }} +{{- $name := default .Chart.Name .Values.nameOverride }} +{{- if contains $name .Release.Name }} +{{- .Release.Name | trunc 63 | trimSuffix "-" }} +{{- else }} +{{- printf "%s-%s" .Release.Name $name | trunc 63 | trimSuffix "-" }} +{{- end }} +{{- end }} +{{- end }} + +{{/* +Create chart name and version as used by the chart label. +*/}} +{{- define "neo-blog.chart" -}} +{{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" }} +{{- end }} + +{{/* +Common labels +*/}} +{{- define "neo-blog.labels" -}} +helm.sh/chart: {{ include "neo-blog.chart" . }} +{{ include "neo-blog.selectorLabels" . }} +{{- if .Chart.AppVersion }} +app.kubernetes.io/version: {{ .Chart.AppVersion | quote }} +{{- end }} +app.kubernetes.io/managed-by: {{ .Release.Service }} +{{- end }} + +{{/* +Selector labels +*/}} +{{- define "neo-blog.selectorLabels" -}} +app.kubernetes.io/name: {{ include "neo-blog.name" . }} +app.kubernetes.io/instance: {{ .Release.Name }} +{{- end }} + +{{/* +Selector labels for Frontend +*/}} +{{- define "neo-blog.frontend.selectorLabels" -}} +{{- include "neo-blog.selectorLabels" . }} +app.kubernetes.io/component: frontend +{{- end }} + +{{/* +Selector labels for Backend +*/}} +{{- define "neo-blog.backend.selectorLabels" -}} +{{- include "neo-blog.selectorLabels" . }} +app.kubernetes.io/component: backend +{{- end }} +{{/* +Create the name of the service account to use +*/}} +{{- define "neo-blog.serviceAccountName" -}} +{{- if .Values.serviceAccount.create }} +{{- default (include "neo-blog.fullname" .) .Values.serviceAccount.name }} +{{- else }} +{{- default "default" .Values.serviceAccount.name }} +{{- end }} +{{- end }} diff --git a/chart/templates/backend-deployment.yaml b/chart/templates/backend-deployment.yaml new file mode 100644 index 0000000..4df1d86 --- /dev/null +++ b/chart/templates/backend-deployment.yaml @@ -0,0 +1,83 @@ +apiVersion: apps/v1 +kind: Deployment +metadata: + name: {{ include "neo-blog.fullname" . }}-backend + labels: + {{- include "neo-blog.backend.selectorLabels" . | nindent 4 }} +spec: + {{- if not .Values.autoscaling.enabled }} + replicas: {{ .Values.replicaCount }} + {{- end }} + selector: + matchLabels: + {{- include "neo-blog.backend.selectorLabels" . | nindent 6 }} + template: + metadata: + {{- with .Values.podAnnotations }} + annotations: + {{- toYaml . | nindent 8 }} + {{- end }} + labels: + {{- include "neo-blog.backend.selectorLabels" . | nindent 8 }} + {{- with .Values.podLabels }} + {{- toYaml . | nindent 8 }} + {{- end }} + spec: + {{- with .Values.imagePullSecrets }} + imagePullSecrets: + {{- toYaml . | nindent 8 }} + {{- end }} + serviceAccountName: {{ include "neo-blog.serviceAccountName" . }} + {{- with .Values.podSecurityContext }} + securityContext: + {{- toYaml . | nindent 8 }} + {{- end }} + containers: + - name: {{ .Chart.Name }}-backend + {{- with .Values.securityContext }} + securityContext: + {{- toYaml . | nindent 12 }} + {{- end }} + image: "{{ .Values.image.registry }}/{{ .Values.image.backend }}:{{ .Values.image.backendTag | default .Chart.AppVersion }}" + imagePullPolicy: {{ .Values.image.pullPolicy }} + env: + {{- range $key, $val := .Values.backend.env }} + - name: {{ $key | quote }} + value: {{ $val | quote }} + {{- end }} + ports: + - name: http + containerPort: {{ .Values.service.port }} + protocol: TCP + livenessProbe: + httpGet: + path: /api/v1/post/list + port: http + readinessProbe: + httpGet: + path: /api/v1/post/list + port: http + {{- with .Values.resources.backend }} + resources: + {{- toYaml . | nindent 12 }} + {{- end }} + {{- with .Values.volumeMounts }} + volumeMounts: + {{- toYaml . | nindent 12 }} + {{- end }} + {{- with .Values.volumes }} + volumes: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.nodeSelector }} + nodeSelector: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.affinity }} + affinity: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.tolerations }} + tolerations: + {{- toYaml . | nindent 8 }} + {{- end }} diff --git a/chart/templates/backend-service.yaml b/chart/templates/backend-service.yaml new file mode 100644 index 0000000..9ceb762 --- /dev/null +++ b/chart/templates/backend-service.yaml @@ -0,0 +1,15 @@ +apiVersion: v1 +kind: Service +metadata: + name: {{ include "neo-blog.fullname" . }}-backend + labels: + {{- include "neo-blog.backend.selectorLabels" . | nindent 4 }} +spec: + type: {{ .Values.service.type }} + ports: + - port: {{ .Values.service.port }} + targetPort: http + protocol: TCP + name: http + selector: + {{- include "neo-blog.backend.selectorLabels" . | nindent 4 }} diff --git a/chart/templates/frontend-deployment.yaml b/chart/templates/frontend-deployment.yaml new file mode 100644 index 0000000..03bdd8e --- /dev/null +++ b/chart/templates/frontend-deployment.yaml @@ -0,0 +1,86 @@ +{{- if .Values.frontend.enabled -}} +apiVersion: apps/v1 +kind: Deployment +metadata: + name: {{ include "neo-blog.fullname" . }}-frontend + labels: + {{- include "neo-blog.frontend.selectorLabels" . | nindent 4 }} +spec: + {{- if not .Values.autoscaling.enabled }} + replicas: {{ .Values.replicaCount }} + {{- end }} + selector: + matchLabels: + {{- include "neo-blog.frontend.selectorLabels" . | nindent 6 }} + template: + metadata: + {{- with .Values.podAnnotations }} + annotations: + {{- toYaml . | nindent 8 }} + {{- end }} + labels: + {{- include "neo-blog.frontend.selectorLabels" . | nindent 8 }} + {{- with .Values.podLabels }} + {{- toYaml . | nindent 8 }} + {{- end }} + spec: + {{- with .Values.imagePullSecrets }} + imagePullSecrets: + {{- toYaml . | nindent 8 }} + {{- end }} + serviceAccountName: {{ include "neo-blog.serviceAccountName" . }} + {{- with .Values.podSecurityContext }} + securityContext: + {{- toYaml . | nindent 8 }} + {{- end }} + containers: + - name: {{ .Chart.Name }}-frontend + {{- with .Values.securityContext }} + securityContext: + {{- toYaml . | nindent 12 }} + {{- end }} + image: "{{ .Values.image.registry }}/{{ .Values.image.frontend }}:{{ .Values.image.frontendTag | default .Chart.AppVersion }}" + imagePullPolicy: {{ .Values.image.pullPolicy }} + ports: + - name: http + containerPort: {{ .Values.service.port }} + protocol: TCP + env: + - name: BACKEND_URL + value: "http://{{(include "neo-blog.fullname" .)}}-backend:{{ .Values.service.port }}" + - name: PORT + value: "{{ .Values.service.port }}" + livenessProbe: + httpGet: + path: / + port: http + readinessProbe: + httpGet: + path: / + port: http + {{- with .Values.resources.frontend }} + resources: + {{- toYaml . | nindent 12}} + {{- end }} + {{- with .Values.volumeMounts }} + volumeMounts: + {{- toYaml . | nindent 12 }} + {{- end }} + {{- with .Values.volumes }} + volumes: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.nodeSelector }} + nodeSelector: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.affinity }} + affinity: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.tolerations }} + tolerations: + {{- toYaml . | nindent 8 }} + {{- end }} + +{{- end -}} \ No newline at end of file diff --git a/chart/templates/frontend-service.yaml b/chart/templates/frontend-service.yaml new file mode 100644 index 0000000..3d0bb7c --- /dev/null +++ b/chart/templates/frontend-service.yaml @@ -0,0 +1,17 @@ +{{- if .Values.frontend.enabled -}} +apiVersion: v1 +kind: Service +metadata: + name: {{ include "neo-blog.fullname" . }}-frontend + labels: + {{- include "neo-blog.frontend.selectorLabels" . | nindent 4 }} +spec: + type: {{ .Values.service.type }} + ports: + - port: {{ .Values.service.port }} + targetPort: http + protocol: TCP + name: http + selector: + {{- include "neo-blog.frontend.selectorLabels" . | nindent 4 }} +{{- end -}} \ No newline at end of file diff --git a/chart/templates/hpa.yaml b/chart/templates/hpa.yaml new file mode 100644 index 0000000..8575e50 --- /dev/null +++ b/chart/templates/hpa.yaml @@ -0,0 +1,63 @@ +{{- if .Values.autoscaling.enabled }} +apiVersion: autoscaling/v2 +kind: HorizontalPodAutoscaler +metadata: + name: {{ include "neo-blog.fullname" . }}-backend + labels: + {{- include "neo-blog.backend.selectorLabels" . | nindent 4 }} +spec: + scaleTargetRef: + apiVersion: apps/v1 + kind: Deployment + name: {{ include "neo-blog.fullname" . }}-backend + minReplicas: {{ .Values.autoscaling.minReplicas }} + maxReplicas: {{ .Values.autoscaling.maxReplicas }} + metrics: + {{- if .Values.autoscaling.targetCPUUtilizationPercentage }} + - type: Resource + resource: + name: cpu + target: + type: Utilization + averageUtilization: {{ .Values.autoscaling.targetCPUUtilizationPercentage }} + {{- end }} + {{- if .Values.autoscaling.targetMemoryUtilizationPercentage }} + - type: Resource + resource: + name: memory + target: + type: Utilization + averageUtilization: {{ .Values.autoscaling.targetMemoryUtilizationPercentage }} + {{- end }} +--- +apiVersion: autoscaling/v2 +kind: HorizontalPodAutoscaler +metadata: + name: {{ include "neo-blog.fullname" . }}-frontend + labels: + {{- include "neo-blog.frontend.selectorLabels" . | nindent 4 }} +spec: + scaleTargetRef: + apiVersion: apps/v1 + kind: Deployment + name: {{ include "neo-blog.fullname" . }}-frontend + minReplicas: {{ .Values.autoscaling.minReplicas }} + maxReplicas: {{ .Values.autoscaling.maxReplicas }} + metrics: + {{- if .Values.autoscaling.targetCPUUtilizationPercentage }} + - type: Resource + resource: + name: cpu + target: + type: Utilization + averageUtilization: {{ .Values.autoscaling.targetCPUUtilizationPercentage }} + {{- end }} + {{- if .Values.autoscaling.targetMemoryUtilizationPercentage }} + - type: Resource + resource: + name: memory + target: + type: Utilization + averageUtilization: {{ .Values.autoscaling.targetMemoryUtilizationPercentage }} + {{- end }} +{{- end }} diff --git a/chart/templates/ingress.yaml b/chart/templates/ingress.yaml new file mode 100644 index 0000000..1fe30cd --- /dev/null +++ b/chart/templates/ingress.yaml @@ -0,0 +1,61 @@ +{{- if .Values.ingress.enabled -}} +apiVersion: networking.k8s.io/v1 +kind: Ingress +metadata: + name: {{ include "neo-blog.fullname" . }}-frontend + labels: + {{- include "neo-blog.labels" . | nindent 4 }} + {{- with .Values.ingress.annotations }} + annotations: + {{- toYaml . | nindent 4 }} + {{- end }} +spec: + {{- with .Values.ingress.className }} + ingressClassName: {{ . }} + {{- end }} + {{- if .Values.ingress.tls }} + tls: + {{- range .Values.ingress.tls }} + - hosts: + {{- range .hosts }} + - {{ . | quote }} + {{- end }} + secretName: {{ .secretName }} + {{- end }} + {{- end }} + rules: + {{- range .Values.ingress.hosts.frontend }} + - host: {{ .host | quote }} + http: + paths: + {{- range .paths }} + - path: {{ .path }} + {{- with .pathType }} + pathType: {{ . }} + {{- end }} + backend: + service: + name: {{ include "neo-blog.fullname" $ }}-frontend + port: + number: {{ $.Values.service.port }} + {{- end }} + {{- end }} + {{- if .Values.backend.expose -}} + {{- range .Values.ingress.hosts.backend }} + - host: {{ .host | quote }} + http: + paths: + {{- range .paths }} + - path: {{ .path }} + {{- with .pathType }} + pathType: {{ . }} + {{- end }} + backend: + service: + name: {{ include "neo-blog.fullname" $ }}-backend + port: + number: {{ $.Values.service.port }} + {{- end }} + {{- end }} + {{- end }} +{{- end }} \ No newline at end of file diff --git a/chart/templates/serviceaccount.yaml b/chart/templates/serviceaccount.yaml new file mode 100644 index 0000000..7064e3e --- /dev/null +++ b/chart/templates/serviceaccount.yaml @@ -0,0 +1,13 @@ +{{- if .Values.serviceAccount.create -}} +apiVersion: v1 +kind: ServiceAccount +metadata: + name: {{ include "neo-blog.serviceAccountName" . }} + labels: + {{- include "neo-blog.labels" . | nindent 4 }} + {{- with .Values.serviceAccount.annotations }} + annotations: + {{- toYaml . | nindent 4 }} + {{- end }} +automountServiceAccountToken: {{ .Values.serviceAccount.automount }} +{{- end }} diff --git a/chart/values.yaml b/chart/values.yaml new file mode 100644 index 0000000..74afd6b --- /dev/null +++ b/chart/values.yaml @@ -0,0 +1,174 @@ +# 初始副本数 +replicaCount: 1 + +# 镜像设置 +image: + registry: docker.linkos.org + backend: snowykami/neo-blog-backend + backendTag: latest + frontend: snowykami/neo-blog-frontend + frontendTag: latest + pullPolicy: IfNotPresent + +# 是否启用前端 +frontend: + enabled: true + +backend: + # 是否暴露后端 + expose: false + + # 后端环境变量 + env: + # Captcha settings 机器人挑战配置 + # 开发模式下的直接通过验证码 + CAPTCHA_DEV_PASSCODE: "114514" + # captcha类型,支持turnstile recaptcha hcaptcha,disable为禁用验证码 + CAPTCHA_TYPE: turnstile + # captcha设置 + CAPTCHA_SITE_SECRET: 89dh29djha28dh + CAPTCHA_SECRET_KEY: 89dh28912dh1289dh128d9d + + # Database settings 数据库配置 + # 数据库驱动,支持sqlite postgres + DB_DRIVER: sqlite + DB_NAME: blog + DB_PATH: ./data/data.db + DB_HOST: postgres + DB_PORT: 5432 + DB_USER: blog + DB_PASSWORD: blog + # postgres数据库SSL模式 + DB_SSLMODE: disable + + # Email settings 邮件配置 + EMAIL_ENABLED: false + EMAIL_USERNAME: xxx@bbb.com + EMAIL_PASSWORD: xxx + EMAIL_ADDRESS: xxx@bbb.com + EMAIL_HOST: smtp.xxx.com + EMAIL_PORT: "465" + EMAIL_SSL: true + + # App settings 应用程序配置 + LOG_LEVEL: debug + BASE_URL: https://blog.shenyu.moe + MAX_REQUEST_BODY_SIZE: "1000000" + MODE: prod + + # 后端端口,无需替换 + PORT: "80" + PASSWORD_SALT: "1234567890" + JWT_SECRET: "1234567890" + TOKEN_DURATION: "3600" + REFRESH_TOKEN_DURATION: "604800" + +## 镜像拉取密钥 +imagePullSecrets: [] + +# 覆盖ChartName +nameOverride: "" +fullnameOverride: "" + +# 服务账号 +serviceAccount: + # 是否创建 + create: true + # 是否自动挂载 + automount: true + # 自定义声明 + annotations: {} + # 服务账号名 + # 若未设置将自动生成 + name: "" + +# This is for setting Kubernetes Annotations to a Pod. +# For more information checkout: https://kubernetes.io/docs/concepts/overview/working-with-objects/annotations/ +podAnnotations: {} +# This is for setting Kubernetes Labels to a Pod. +# For more information checkout: https://kubernetes.io/docs/concepts/overview/working-with-objects/labels/ +podLabels: {} + +podSecurityContext: {} + # fsGroup: 2000 + +securityContext: {} + # capabilities: + # drop: + # - ALL + # readOnlyRootFilesystem: true + # runAsNonRoot: true + # runAsUser: 1000 + +# 服务配置 +service: + type: ClusterIP + # 服务端口,非必要无需更改 + port: 80 + +# ingress 配置 +ingress: + enabled: true + className: "nginx" + annotations: {} + # kubernetes.io/ingress.class: nginx + # kubernetes.io/tls-acme: "true" + hosts: + frontend: + - host: neo-blog.local + paths: + - path: / + pathType: ImplementationSpecific + backend: + - host: api.neo-blog.local + paths: + - path: / + pathType: ImplementationSpecific + tls: [] + # - secretName: chart-example-tls + # hosts: + # - chart-example.local + +# 资源配置 +resources: + backend: + limits: + cpu: 2 + memory: 2Gi + requests: + cpu: 2 + memory: 2Gi + frontend: + limits: + cpu: 64 + memory: 64Gi + requests: + cpu: 64 + memory: 64Gi + + +# 自动扩缩容 +autoscaling: + enabled: false + minReplicas: 1 + maxReplicas: 100 + targetCPUUtilizationPercentage: 80 + targetMemoryUtilizationPercentage: 80 + +# 存储卷 +volumes: [] +# - name: foo +# secret: +# secretName: mysecret +# optional: false + +volumeMounts: [] +# - name: foo +# mountPath: "/etc/foo" +# readOnly: true + +nodeSelector: {} + +tolerations: [] + +affinity: {}