You've already forked helm-gitea
[Breaking] Add HA-support; switch to Deployment
(#437)
# Changes A big shoutout to @luhahn for all his work in #205 which served as the base for this PR. ## Documentation - [x] After thinking for some time about it, I still prefer the distinct option (as started in #350), i.e. having a standalone "HA" doc under `docs/ha-setup.md` to not have a very long README (which is already quite long). Most of the information below should go into it with more details and explanations behind all of the individual components. ## Chart deps ~~- Adds `meilisearch` as a chart dependency for a HA-ready issue indexer. Only works with >= Gitea 1.20~~ ~~- Adds `redis` as a chart dependency for a HA-ready session and queue store.~~ - Adds `redis-cluster` as a chart dependency for a HA-ready session and queue store (alternative to `redis`). Only works with >= Gitea 1.19.2. - Removes `memcached` instead of `redis-cluster` - Add `postgresql-ha` as default DB dep in favor of `postgres` ## Adds smart HA chart logic The goal is to set smart config values that result in a HA-ready Gitea deployment if `replicaCount` > 1. - If `replicaCount` > 1, - `gitea.config.session.PROVIDER` is automatically set to `redis-cluster` - `gitea.config.indexer.REPO_INDEXER_ENABLED` is automatically set to `false` unless the value is `elasticsearch` or `meilisearch` - `redis-cluster` is used for `[queue]` and `[cache]` and `[session]`mode or not Configuration of external instances of `meilisearch` and `minio` are documented in a new markdown doc. ## Deployment vs Statefulset Given all the discussions about this lately (#428), I think we could use both. In the end, we do not have the requirement for a sequential pod scale up/scale down as it would happen in statefulsets. On the other side, we do not have actual stateless pods as we are attaching a RWX to the deployment. Yet I think because we do not have a leader-election requirement, spawning the pods as a deployment makes "Rolling Updates" easier and also signals users that there is no "leader election" logic and each pod can just be "destroyed" at anytime without causing interruption. Hence I think we should be able to switch from a statefulset to a deployment, even in the single-replica case. This change also brought up a templating/linting issue: the definition of `.Values.gitea.config.server.SSH_LISTEN_PORT` in `ssh-svc.yaml` just "luckily" worked so far due to naming-related lint processing. Due to the change from "statefulset" to "deployment", the processing queue changed and caused a failure complaining about `config.server.SSH_LISTEN_PORT` not being defined yet. The only way I could see to fix this was to "properly" define the value in `values.yaml` instead of conditionally definining it in `helpers.tpl`. Maybe there's a better way? ## Chart PVC Creation I've adapted the automated PVC creation from another chart to be able to provide the `storageClassName` as I couldn't get dynamic provisioning for EFS going with the current implementation. In addition the naming and approach within the Gitea chart for PV creation is a bit unusual and aligning it might be beneficial. A semi-unrelated change which will result in a breaking change for existing users but this PR includes a lot of breaking changes already, so including another one might not make it much worse... - New `persistence.mount`: whether to mount an existing PVC (via `persistence.existingClaim` - New `persistence.create`: whether to create a new PVC ## Testing As this PR does a lot of things, we need proper testing. The helm chart can be installed from the Git branch via `helm-git` as follows: ``` helm repo add gitea-charts git+https://gitea.com/gitea/helm-chart@/?ref=deployment helm install gitea --version 0.0.0 ``` It is **highly recommended** to test the chart in a dedicated namespace. I've tested this myself with both `redis` and `redis-cluster` and it seemed to work fine. I just did some basic operations though and we should do more niche testing before merging. Examplary `values.yml` for testing (only needs a valid RWX storage class): <details> <summary>values.yaml</summary> ```yml image: tag: "dev" PullPolicy: "Always" rootless: true replicaCount: 2 persistence: enabled: true accessModes: - ReadWriteMany storageClass: FIXME redis-cluster: enabled: false global: redis: password: gitea gitea: config: indexer: ISSUE_INDEXER_ENABLED: true REPO_INDEXER_ENABLED: false ``` </details> ## Preferred setup The preferred HA setup with respect to performance and stability might currently be as follows: - Repos: RWX (e.g. EFS or Azurefiles NFS) - Issue indexer: Meilisearch (HA) - Session and cache: Redis Cluster (HA) - Attachments/Avatars: Minio (HA) This will result in a ~ 10-pod HA setup overall. All pods have very low resource requests. fix #98 Co-authored-by: pat-s <pat-s@noreply.gitea.io> Reviewed-on: https://gitea.com/gitea/helm-chart/pulls/437 Co-authored-by: pat-s <patrick.schratz@gmail.com> Co-committed-by: pat-s <patrick.schratz@gmail.com>
This commit is contained in:
121
values.yaml
121
values.yaml
@ -20,9 +20,19 @@ global:
|
||||
# hostnames:
|
||||
# - example.com
|
||||
|
||||
## @param replicaCount number of replicas for the statefulset
|
||||
## @param replicaCount number of replicas for the deployment
|
||||
replicaCount: 1
|
||||
|
||||
## @section strategy
|
||||
## @param strategy.type strategy type
|
||||
## @param strategy.rollingUpdate.maxSurge maxSurge
|
||||
## @param strategy.rollingUpdate.maxUnavailable maxUnavailable
|
||||
strategy:
|
||||
type: "RollingUpdate"
|
||||
rollingUpdate:
|
||||
maxSurge: "100%"
|
||||
maxUnavailable: 0
|
||||
|
||||
## @param clusterDomain cluster domain
|
||||
clusterDomain: cluster.local
|
||||
|
||||
@ -74,11 +84,16 @@ containerSecurityContext: {}
|
||||
## @param securityContext Run init and Gitea containers as a specific securityContext
|
||||
securityContext: {}
|
||||
|
||||
## @param podDisruptionBudget Pod disruption budget
|
||||
podDisruptionBudget: {}
|
||||
# maxUnavailable: 1
|
||||
# minAvailable: 1
|
||||
|
||||
## @section Service
|
||||
service:
|
||||
## @param service.http.type Kubernetes service type for web traffic
|
||||
## @param service.http.port Port number for web traffic
|
||||
## @param service.http.clusterIP ClusterIP setting for http autosetup for statefulset is None
|
||||
## @param service.http.clusterIP ClusterIP setting for http autosetup for deployment is None
|
||||
## @param service.http.loadBalancerIP LoadBalancer IP setting
|
||||
## @param service.http.nodePort NodePort for http service
|
||||
## @param service.http.externalTrafficPolicy If `service.http.type` is `NodePort` or `LoadBalancer`, set this to `Local` to enable source IP preservation
|
||||
@ -101,7 +116,7 @@ service:
|
||||
annotations: {}
|
||||
## @param service.ssh.type Kubernetes service type for ssh traffic
|
||||
## @param service.ssh.port Port number for ssh traffic
|
||||
## @param service.ssh.clusterIP ClusterIP setting for ssh autosetup for statefulset is None
|
||||
## @param service.ssh.clusterIP ClusterIP setting for ssh autosetup for deployment is None
|
||||
## @param service.ssh.loadBalancerIP LoadBalancer IP setting
|
||||
## @param service.ssh.nodePort NodePort for ssh service
|
||||
## @param service.ssh.externalTrafficPolicy If `service.ssh.type` is `NodePort` or `LoadBalancer`, set this to `Local` to enable source IP preservation
|
||||
@ -155,7 +170,7 @@ ingress:
|
||||
# If helm doesn't correctly detect your ingress API version you can set it here.
|
||||
# apiVersion: networking.k8s.io/v1
|
||||
|
||||
## @section StatefulSet
|
||||
## @section deployment
|
||||
#
|
||||
## @param resources Kubernetes resources
|
||||
resources:
|
||||
@ -177,26 +192,29 @@ resources:
|
||||
## @param schedulerName Use an alternate scheduler, e.g. "stork"
|
||||
schedulerName: ""
|
||||
|
||||
## @param nodeSelector NodeSelector for the statefulset
|
||||
## @param nodeSelector NodeSelector for the deployment
|
||||
nodeSelector: {}
|
||||
|
||||
## @param tolerations Tolerations for the statefulset
|
||||
## @param tolerations Tolerations for the deployment
|
||||
tolerations: []
|
||||
|
||||
## @param affinity Affinity for the statefulset
|
||||
## @param affinity Affinity for the deployment
|
||||
affinity: {}
|
||||
|
||||
## @param dnsConfig dnsConfig for the statefulset
|
||||
## @param topologySpreadConstraints TopologySpreadConstraints for the deployment
|
||||
topologySpreadConstraints: []
|
||||
|
||||
## @param dnsConfig dnsConfig for the deployment
|
||||
dnsConfig: {}
|
||||
|
||||
## @param priorityClassName priorityClassName for the statefulset
|
||||
## @param priorityClassName priorityClassName for the deployment
|
||||
priorityClassName: ""
|
||||
|
||||
## @param statefulset.env Additional environment variables to pass to containers
|
||||
## @param statefulset.terminationGracePeriodSeconds How long to wait until forcefully kill the pod
|
||||
## @param statefulset.labels Labels for the statefulset
|
||||
## @param statefulset.annotations Annotations for the Gitea StatefulSet to be created
|
||||
statefulset:
|
||||
## @param deployment.env Additional environment variables to pass to containers
|
||||
## @param deployment.terminationGracePeriodSeconds How long to wait until forcefully kill the pod
|
||||
## @param deployment.labels Labels for the deployment
|
||||
## @param deployment.annotations Annotations for the Gitea deployment to be created
|
||||
deployment:
|
||||
env:
|
||||
[]
|
||||
# - name: VARIABLE
|
||||
@ -218,14 +236,16 @@ serviceAccount:
|
||||
name: ""
|
||||
automountServiceAccountToken: false
|
||||
imagePullSecrets: []
|
||||
# - name: private-registry-access
|
||||
# - name: private-registry-access
|
||||
annotations: {}
|
||||
labels: {}
|
||||
|
||||
## @section Persistence
|
||||
#
|
||||
## @param persistence.enabled Enable persistent storage
|
||||
## @param persistence.existingClaim Use an existing claim to store repository information
|
||||
## @param persistence.create Whether to create the persistentVolumeClaim for shared storage
|
||||
## @param persistence.mount Whether the persistentVolumeClaim should be mounted (even if not created)
|
||||
## @param persistence.claimName Use an existing claim to store repository information
|
||||
## @param persistence.size Size for persistence to store repo information
|
||||
## @param persistence.accessModes AccessMode for persistence
|
||||
## @param persistence.labels Labels for the persistence volume claim to be created
|
||||
@ -234,7 +254,9 @@ serviceAccount:
|
||||
## @param persistence.subPath Subdirectory of the volume to mount at
|
||||
persistence:
|
||||
enabled: true
|
||||
existingClaim:
|
||||
create: true
|
||||
mount: true
|
||||
claimName: gitea-shared-storage
|
||||
size: 10Gi
|
||||
accessModes:
|
||||
- ReadWriteOnce
|
||||
@ -243,7 +265,7 @@ persistence:
|
||||
storageClass:
|
||||
subPath:
|
||||
|
||||
## @param extraVolumes Additional volumes to mount to the Gitea statefulset
|
||||
## @param extraVolumes Additional volumes to mount to the Gitea deployment
|
||||
extraVolumes: []
|
||||
# - name: postgres-ssl-vol
|
||||
# secret:
|
||||
@ -358,13 +380,14 @@ gitea:
|
||||
# customProfileUrl:
|
||||
# customEmailUrl:
|
||||
|
||||
## @param gitea.config Configuration for the Gitea server,ref: [config-cheat-sheet](https://docs.gitea.io/en-us/config-cheat-sheet/)
|
||||
config: {}
|
||||
# APP_NAME: "Gitea: Git with a cup of tea"
|
||||
# RUN_MODE: dev
|
||||
#
|
||||
# server:
|
||||
# SSH_PORT: 22
|
||||
## @param gitea.config.server.SSH_PORT SSH port for rootlful Gitea image
|
||||
## @param gitea.config.server.SSH_LISTEN_PORT SSH port for rootless Gitea image
|
||||
config:
|
||||
# APP_NAME: "Gitea: Git with a cup of tea"
|
||||
# RUN_MODE: dev
|
||||
server:
|
||||
SSH_PORT: 22 # rootful image
|
||||
SSH_LISTEN_PORT: 2222 # rootless image
|
||||
#
|
||||
# security:
|
||||
# PASSWORD_COMPLEXITY: spec
|
||||
@ -446,23 +469,37 @@ gitea:
|
||||
successThreshold: 1
|
||||
failureThreshold: 10
|
||||
|
||||
## @section Memcached
|
||||
#
|
||||
## @param memcached.enabled Memcached is loaded as a dependency from [Bitnami](https://github.com/bitnami/charts/tree/master/bitnami/memcached) if enabled in the values. Complete Configuration can be taken from their website.
|
||||
## ref: https://hub.docker.com/r/bitnami/memcached/tags/
|
||||
## @param memcached.service.ports.memcached Port for Memcached
|
||||
memcached:
|
||||
## @section redis-cluster
|
||||
## @param redis-cluster.enabled Enable redis
|
||||
## @param redis-cluster.global.redis.password Password for the "gitea" user (overrides `password`)
|
||||
redis-cluster:
|
||||
enabled: true
|
||||
# image:
|
||||
# registry: docker.io
|
||||
# repository: bitnami/memcached
|
||||
# tag: ""
|
||||
# digest: ""
|
||||
# pullPolicy: IfNotPresent
|
||||
# pullSecrets: []
|
||||
service:
|
||||
ports:
|
||||
memcached: 11211
|
||||
global:
|
||||
redis:
|
||||
password: gitea
|
||||
|
||||
## @section postgresql-ha
|
||||
#
|
||||
## @param postgresql-ha.enabled Enable postgresql-ha
|
||||
## @param postgresql-ha.global.postgresql-ha.auth.password Password for the `gitea` user (overrides `auth.password`)
|
||||
## @param postgresql-ha.global.postgresql-ha.auth.database Name for a custom database to create (overrides `auth.database`)
|
||||
## @param postgresql-ha.global.postgresql-ha.auth.username Name for a custom user to create (overrides `auth.username`)
|
||||
## @param postgresql-ha.global.postgresql-ha.service.ports.postgresql-ha postgresql-ha service port (overrides `service.ports.postgresql-ha`)
|
||||
## @param postgresql-ha.primary.persistence.size PVC Storage Request for postgresql-ha volume
|
||||
postgresql-ha:
|
||||
enabled: true
|
||||
global:
|
||||
postgresql-ha:
|
||||
auth:
|
||||
password: gitea
|
||||
database: gitea
|
||||
username: gitea
|
||||
service:
|
||||
ports:
|
||||
postgresql-ha: 5432
|
||||
primary:
|
||||
persistence:
|
||||
size: 10Gi
|
||||
|
||||
## @section PostgreSQL
|
||||
#
|
||||
@ -473,7 +510,7 @@ memcached:
|
||||
## @param postgresql.global.postgresql.service.ports.postgresql PostgreSQL service port (overrides `service.ports.postgresql`)
|
||||
## @param postgresql.primary.persistence.size PVC Storage Request for PostgreSQL volume
|
||||
postgresql:
|
||||
enabled: true
|
||||
enabled: false
|
||||
global:
|
||||
postgresql:
|
||||
auth:
|
||||
|
Reference in New Issue
Block a user