From 90fd37101b092e93c07836d85fb2937b492b3eaf Mon Sep 17 00:00:00 2001 From: bootstrap Date: Wed, 6 May 2026 17:35:56 +0300 Subject: [PATCH] Initial Gitea chart with smoke CI --- .gitea/workflows/trash-ci.yaml | 19 + .helm/.helmignore | 23 + .helm/Chart.lock | 9 + .helm/Chart.yaml | 14 + .helm/charts/postgresql-preprod-16.4.8.tgz | Bin 0 -> 83308 bytes .helm/charts/universal-chart-0.1.9.tgz | Bin 0 -> 21341 bytes .helm/restore-values.example.yaml | 42 ++ .helm/templates/_helpers.tpl | 45 ++ .helm/templates/backup-cronjobs.yaml | 170 +++++++ .helm/templates/gitea-deployment.yaml | 211 ++++++++ .helm/templates/gitea-service.yaml | 18 + .helm/templates/pvc.yaml | 45 ++ .helm/templates/restore-job.yaml | 182 +++++++ .helm/templates/restore-rbac.yaml | 73 +++ .helm/templates/restore-scale-down-job.yaml | 38 ++ .helm/templates/restore-scale-up-job.yaml | 42 ++ .helm/templates/runner-configmap.yaml | 43 ++ .helm/templates/secret.yaml | 31 ++ .helm/templates/ssh-service.yaml | 24 + .helm/values.yaml | 521 ++++++++++++++++++++ README.md | 80 +++ 21 files changed, 1630 insertions(+) create mode 100644 .gitea/workflows/trash-ci.yaml create mode 100755 .helm/.helmignore create mode 100644 .helm/Chart.lock create mode 100644 .helm/Chart.yaml create mode 100644 .helm/charts/postgresql-preprod-16.4.8.tgz create mode 100644 .helm/charts/universal-chart-0.1.9.tgz create mode 100644 .helm/restore-values.example.yaml create mode 100644 .helm/templates/_helpers.tpl create mode 100644 .helm/templates/backup-cronjobs.yaml create mode 100644 .helm/templates/gitea-deployment.yaml create mode 100644 .helm/templates/gitea-service.yaml create mode 100644 .helm/templates/pvc.yaml create mode 100644 .helm/templates/restore-job.yaml create mode 100644 .helm/templates/restore-rbac.yaml create mode 100644 .helm/templates/restore-scale-down-job.yaml create mode 100644 .helm/templates/restore-scale-up-job.yaml create mode 100644 .helm/templates/runner-configmap.yaml create mode 100644 .helm/templates/secret.yaml create mode 100644 .helm/templates/ssh-service.yaml create mode 100644 .helm/values.yaml create mode 100644 README.md diff --git a/.gitea/workflows/trash-ci.yaml b/.gitea/workflows/trash-ci.yaml new file mode 100644 index 0000000..be937ec --- /dev/null +++ b/.gitea/workflows/trash-ci.yaml @@ -0,0 +1,19 @@ +name: trash-ci + +on: + push: + branches: + - main + workflow_dispatch: + +jobs: + smoke: + runs-on: linux-shell + steps: + - name: Checkout + uses: actions/checkout@v4 + - name: Smoke + run: | + echo "runner-ok" + pwd + ls -la diff --git a/.helm/.helmignore b/.helm/.helmignore new file mode 100755 index 0000000..0e8a0eb --- /dev/null +++ b/.helm/.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/.helm/Chart.lock b/.helm/Chart.lock new file mode 100644 index 0000000..a085f4d --- /dev/null +++ b/.helm/Chart.lock @@ -0,0 +1,9 @@ +dependencies: +- name: universal-chart + repository: oci://cr.yandex/crp3ccidau046kdj8g9q/charts + version: 0.1.9 +- name: postgresql-preprod + repository: oci://cr.yandex/crp3ccidau046kdj8g9q/charts + version: 16.4.8 +digest: sha256:2fff848510e52c012ae7d941e38fbed2a017c94011e4b3dbca294e672f45a686 +generated: "2026-05-06T12:00:56.461784+03:00" diff --git a/.helm/Chart.yaml b/.helm/Chart.yaml new file mode 100644 index 0000000..7a5b48d --- /dev/null +++ b/.helm/Chart.yaml @@ -0,0 +1,14 @@ +apiVersion: v2 +name: gitea +description: Gitea with act_runner, PostgreSQL, S3 backups, and restore jobs. +type: application +version: 1.0.0 +appVersion: "1.22.6" +dependencies: + - name: universal-chart + repository: oci://cr.yandex/crp3ccidau046kdj8g9q/charts + version: 0.1.9 + - name: postgresql-preprod + alias: postgresql + repository: oci://cr.yandex/crp3ccidau046kdj8g9q/charts + version: 16.4.8 diff --git a/.helm/charts/postgresql-preprod-16.4.8.tgz b/.helm/charts/postgresql-preprod-16.4.8.tgz new file mode 100644 index 0000000000000000000000000000000000000000..6a2ad710df6307c94594659c955e844f849d754d GIT binary patch literal 83308 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

y$D>whYaVVid>FJ>D69 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 literal 0 HcmV?d00001 diff --git a/.helm/restore-values.example.yaml b/.helm/restore-values.example.yaml new file mode 100644 index 0000000..20a3655 --- /dev/null +++ b/.helm/restore-values.example.yaml @@ -0,0 +1,42 @@ +restore: + enabled: true + name: gitea-restore + files: + enabled: true + postgresql: + enabled: true + host: postgresql + s3: + bucket: gitops-gitea + endpointUrl: https://storage.yandexcloud.net + region: ru-central1 + giteaFilesKey: gitops-backups/gitea-files/gitea-files-2026-05-06-141255.tar.gz + postgresqlDumpKey: gitops-backups/postgresql/gitea-postgresql-2026-05-06-111204.sql.gz + scaleGitea: + enabled: true + serviceAccountName: gitea-restore + deploymentName: gitea + waitTimeoutSeconds: 300 + scaleUp: + enabled: true + replicas: 1 + waitForRestoreTimeoutSeconds: 1800 + images: + kubectl: + repository: bitnamilegacy/kubectl + tag: "1.30.6" + pullPolicy: IfNotPresent + awsCli: + repository: amazon/aws-cli + tag: "2.15.57" + pullPolicy: IfNotPresent + postgres: + repository: postgres + tag: "17" + pullPolicy: IfNotPresent + busybox: + repository: busybox + tag: "1.36" + pullPolicy: IfNotPresent + verify: + enabled: true diff --git a/.helm/templates/_helpers.tpl b/.helm/templates/_helpers.tpl new file mode 100644 index 0000000..834936a --- /dev/null +++ b/.helm/templates/_helpers.tpl @@ -0,0 +1,45 @@ +{{- define "gitea.name" -}} +{{- default .Chart.Name .Values.global.nameOverride | trunc 63 | trimSuffix "-" -}} +{{- end -}} + +{{- define "gitea.fullname" -}} +{{- if .Values.global.fullnameOverride -}} +{{- .Values.global.fullnameOverride | trunc 63 | trimSuffix "-" -}} +{{- else -}} +{{- include "gitea.name" . -}} +{{- end -}} +{{- end -}} + +{{- define "gitea.chart" -}} +{{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" -}} +{{- end -}} + +{{- define "gitea.labels" -}} +helm.sh/chart: {{ include "gitea.chart" . }} +app.kubernetes.io/name: {{ include "gitea.name" . }} +app.kubernetes.io/instance: {{ .Release.Name }} +app.kubernetes.io/managed-by: {{ .Release.Service }} +{{- with .Values.global.labels }} +{{ toYaml . }} +{{- end }} +{{- end -}} + +{{- define "gitea.secretName" -}} +{{- default "gitea-secret" .Values.giteaSecret.name -}} +{{- end -}} + +{{- define "gitea.giteaPvcName" -}} +{{- if .Values.persistence.gitea.existingClaim -}} +{{- .Values.persistence.gitea.existingClaim -}} +{{- else -}} +{{- default "gitea-data" .Values.persistence.gitea.name -}} +{{- end -}} +{{- end -}} + +{{- define "gitea.runnerPvcName" -}} +{{- if .Values.persistence.runner.existingClaim -}} +{{- .Values.persistence.runner.existingClaim -}} +{{- else -}} +{{- default "gitea-runner-data" .Values.persistence.runner.name -}} +{{- end -}} +{{- end -}} diff --git a/.helm/templates/backup-cronjobs.yaml b/.helm/templates/backup-cronjobs.yaml new file mode 100644 index 0000000..373c6d8 --- /dev/null +++ b/.helm/templates/backup-cronjobs.yaml @@ -0,0 +1,170 @@ +{{- if and .Values.backup.enabled .Values.backup.giteaFiles.enabled (eq (default "sidecar" .Values.backup.giteaFiles.mode) "cronjob") }} +apiVersion: batch/v1 +kind: CronJob +metadata: + name: gitea-files-backup + namespace: {{ .Release.Namespace | quote }} + labels: + {{- include "gitea.labels" . | nindent 4 }} +spec: + schedule: {{ .Values.backup.giteaFiles.schedule | quote }} + {{- with .Values.backup.timeZone }} + timeZone: {{ . | quote }} + {{- end }} + concurrencyPolicy: Forbid + successfulJobsHistoryLimit: {{ .Values.backup.giteaFiles.successfulJobsHistoryLimit }} + failedJobsHistoryLimit: {{ .Values.backup.giteaFiles.failedJobsHistoryLimit }} + jobTemplate: + spec: + {{- with .Values.backup.giteaFiles.ttlSecondsAfterFinished }} + ttlSecondsAfterFinished: {{ . }} + {{- end }} + template: + spec: + restartPolicy: OnFailure + containers: + - name: backup + image: "{{ .Values.backup.giteaFiles.image.repository }}:{{ .Values.backup.giteaFiles.image.tag }}" + imagePullPolicy: {{ .Values.backup.giteaFiles.image.pullPolicy }} + command: + - /bin/sh + - -ec + - | + case "${AWS_ACCESS_KEY_ID:-}" in ""|GENERATED_*) echo "AWS_ACCESS_KEY_ID is not configured" >&2; exit 1;; esac + case "${AWS_SECRET_ACCESS_KEY:-}" in ""|GENERATED_*) echo "AWS_SECRET_ACCESS_KEY is not configured" >&2; exit 1;; esac + test -n "${S3_BUCKET:-}" || { echo "S3_BUCKET is not configured" >&2; exit 1; } + + timestamp="$(date +%F-%H%M%S)" + archive_name="gitea-files-${timestamp}.tar.gz" + tar -C /data -czf "/tmp/${archive_name}" . + aws --endpoint-url "${AWS_ENDPOINT_URL}" \ + s3 cp "/tmp/${archive_name}" "s3://${S3_BUCKET}/${S3_PREFIX}/gitea-files/${archive_name}" + env: + - name: S3_BUCKET + value: {{ .Values.backup.s3.bucket | quote }} + - name: S3_PREFIX + value: {{ .Values.backup.s3.prefix | quote }} + - name: AWS_DEFAULT_REGION + value: {{ .Values.backup.s3.region | quote }} + - name: AWS_ENDPOINT_URL + value: {{ .Values.backup.s3.endpointUrl | quote }} + - name: AWS_ACCESS_KEY_ID + valueFrom: + secretKeyRef: + name: {{ include "gitea.secretName" . | quote }} + key: aws-access-key-id + - name: AWS_SECRET_ACCESS_KEY + valueFrom: + secretKeyRef: + name: {{ include "gitea.secretName" . | quote }} + key: aws-secret-access-key + volumeMounts: + - name: gitea-data + mountPath: /data + readOnly: true + resources: + {{- toYaml .Values.backup.giteaFiles.resources | nindent 16 }} + volumes: + - name: gitea-data + persistentVolumeClaim: + claimName: {{ include "gitea.giteaPvcName" . | quote }} + readOnly: true +{{- end }} +{{- if and .Values.backup.enabled .Values.backup.postgresql.enabled }} +--- +apiVersion: batch/v1 +kind: CronJob +metadata: + name: gitea-postgresql-backup + namespace: {{ .Release.Namespace | quote }} + labels: + {{- include "gitea.labels" . | nindent 4 }} +spec: + schedule: {{ .Values.backup.postgresql.schedule | quote }} + {{- with .Values.backup.timeZone }} + timeZone: {{ . | quote }} + {{- end }} + concurrencyPolicy: Forbid + successfulJobsHistoryLimit: {{ .Values.backup.postgresql.successfulJobsHistoryLimit }} + failedJobsHistoryLimit: {{ .Values.backup.postgresql.failedJobsHistoryLimit }} + jobTemplate: + spec: + {{- with .Values.backup.postgresql.ttlSecondsAfterFinished }} + ttlSecondsAfterFinished: {{ . }} + {{- end }} + template: + spec: + restartPolicy: OnFailure + initContainers: + - name: dump + image: "{{ .Values.backup.postgresql.dumpImage.repository }}:{{ .Values.backup.postgresql.dumpImage.tag }}" + imagePullPolicy: {{ .Values.backup.postgresql.dumpImage.pullPolicy }} + command: + - /bin/sh + - -ec + - | + timestamp="$(date +%F-%H%M%S)" + dump_name="gitea-postgresql-${timestamp}.sql.gz" + until pg_isready -h "${POSTGRES_HOST}" -U "${POSTGRES_USER}" -d "${POSTGRES_DB}"; do + sleep 5 + done + pg_dump -h "${POSTGRES_HOST}" -U "${POSTGRES_USER}" "${POSTGRES_DB}" | gzip -9 > "/backup/${dump_name}" + printf "%s" "${dump_name}" > /backup/dump-name + env: + - name: POSTGRES_HOST + value: {{ .Values.backup.postgresql.host | quote }} + - name: POSTGRES_DB + value: {{ .Values.postgresql.auth.database | quote }} + - name: POSTGRES_USER + value: {{ .Values.postgresql.auth.username | quote }} + - name: PGPASSWORD + valueFrom: + secretKeyRef: + name: {{ .Values.databaseSecret.name | quote }} + key: {{ .Values.databaseSecret.passwordKey | quote }} + volumeMounts: + - name: backup + mountPath: /backup + containers: + - name: upload + image: "{{ .Values.backup.postgresql.uploadImage.repository }}:{{ .Values.backup.postgresql.uploadImage.tag }}" + imagePullPolicy: {{ .Values.backup.postgresql.uploadImage.pullPolicy }} + command: + - /bin/sh + - -ec + - | + case "${AWS_ACCESS_KEY_ID:-}" in ""|GENERATED_*) echo "AWS_ACCESS_KEY_ID is not configured" >&2; exit 1;; esac + case "${AWS_SECRET_ACCESS_KEY:-}" in ""|GENERATED_*) echo "AWS_SECRET_ACCESS_KEY is not configured" >&2; exit 1;; esac + test -n "${S3_BUCKET:-}" || { echo "S3_BUCKET is not configured" >&2; exit 1; } + + dump_name="$(cat /backup/dump-name)" + aws --endpoint-url "${AWS_ENDPOINT_URL}" \ + s3 cp "/backup/${dump_name}" "s3://${S3_BUCKET}/${S3_PREFIX}/postgresql/${dump_name}" + env: + - name: S3_BUCKET + value: {{ .Values.backup.s3.bucket | quote }} + - name: S3_PREFIX + value: {{ .Values.backup.s3.prefix | quote }} + - name: AWS_DEFAULT_REGION + value: {{ .Values.backup.s3.region | quote }} + - name: AWS_ENDPOINT_URL + value: {{ .Values.backup.s3.endpointUrl | quote }} + - name: AWS_ACCESS_KEY_ID + valueFrom: + secretKeyRef: + name: {{ include "gitea.secretName" . | quote }} + key: aws-access-key-id + - name: AWS_SECRET_ACCESS_KEY + valueFrom: + secretKeyRef: + name: {{ include "gitea.secretName" . | quote }} + key: aws-secret-access-key + volumeMounts: + - name: backup + mountPath: /backup + resources: + {{- toYaml .Values.backup.postgresql.resources | nindent 16 }} + volumes: + - name: backup + emptyDir: {} +{{- end }} diff --git a/.helm/templates/gitea-deployment.yaml b/.helm/templates/gitea-deployment.yaml new file mode 100644 index 0000000..ce1c054 --- /dev/null +++ b/.helm/templates/gitea-deployment.yaml @@ -0,0 +1,211 @@ +apiVersion: apps/v1 +kind: Deployment +metadata: + name: gitea + namespace: {{ .Release.Namespace | quote }} + labels: + {{- include "gitea.labels" . | nindent 4 }} + app: gitea + service: gitea + annotations: + owner: "platform" +spec: + replicas: {{ .Values.gitea.replicaCount }} + revisionHistoryLimit: 10 + strategy: + type: Recreate + selector: + matchLabels: + app: gitea + template: + metadata: + labels: + {{- include "gitea.labels" . | nindent 8 }} + app: gitea + service: gitea + annotations: + traffic.sidecar.istio.io/excludeOutboundPorts: "4317,4318,9411" + spec: + containers: + - name: gitea + image: "{{ .Values.gitea.image.repository }}:{{ .Values.gitea.image.tag }}" + imagePullPolicy: {{ .Values.gitea.image.pullPolicy }} + ports: + - name: http + containerPort: {{ .Values.gitea.service.targetPort }} + protocol: TCP + - name: ssh + containerPort: 22 + protocol: TCP + env: + - name: USER_UID + value: {{ .Values.gitea.uid | quote }} + - name: USER_GID + value: {{ .Values.gitea.gid | quote }} + - name: GITEA__database__DB_TYPE + value: postgres + - name: GITEA__database__HOST + value: postgresql:5432 + - name: GITEA__database__NAME + value: {{ .Values.postgresql.auth.database | quote }} + - name: GITEA__database__USER + value: {{ .Values.postgresql.auth.username | quote }} + - name: GITEA__database__PASSWD + valueFrom: + secretKeyRef: + name: {{ .Values.databaseSecret.name | quote }} + key: {{ .Values.databaseSecret.passwordKey | quote }} + - name: GITEA__server__DOMAIN + value: {{ .Values.gitea.domain | quote }} + - name: GITEA__server__SSH_DOMAIN + value: {{ .Values.gitea.sshDomain | quote }} + - name: GITEA__server__ROOT_URL + value: {{ .Values.gitea.rootUrl | quote }} + - name: GITEA__server__HTTP_PORT + value: {{ .Values.gitea.httpPort | quote }} + - name: GITEA__server__SSH_PORT + value: {{ .Values.gitea.sshPort | quote }} + - name: GITEA__server__SSH_LISTEN_PORT + value: {{ .Values.gitea.sshListenPort | quote }} + - name: GITEA__security__INSTALL_LOCK + value: "true" + - name: GITEA__actions__ENABLED + value: "true" + - name: TZ + value: {{ .Values.gitea.timezone | quote }} + startupProbe: + tcpSocket: + port: http + initialDelaySeconds: {{ .Values.gitea.probes.startup.initialDelaySeconds }} + periodSeconds: {{ .Values.gitea.probes.startup.periodSeconds }} + timeoutSeconds: {{ .Values.gitea.probes.startup.timeoutSeconds }} + failureThreshold: {{ .Values.gitea.probes.startup.failureThreshold }} + readinessProbe: + tcpSocket: + port: http + initialDelaySeconds: {{ .Values.gitea.probes.readiness.initialDelaySeconds }} + periodSeconds: {{ .Values.gitea.probes.readiness.periodSeconds }} + livenessProbe: + tcpSocket: + port: http + initialDelaySeconds: {{ .Values.gitea.probes.liveness.initialDelaySeconds }} + periodSeconds: {{ .Values.gitea.probes.liveness.periodSeconds }} + volumeMounts: + - name: gitea-data + mountPath: /data + resources: + {{- toYaml .Values.gitea.resources | nindent 12 }} + {{- if and .Values.backup.enabled .Values.backup.giteaFiles.enabled (eq (default "sidecar" .Values.backup.giteaFiles.mode) "sidecar") }} + - name: gitea-files-archive + image: "{{ .Values.backup.giteaFiles.archiveImage.repository }}:{{ .Values.backup.giteaFiles.archiveImage.tag }}" + imagePullPolicy: {{ .Values.backup.giteaFiles.archiveImage.pullPolicy }} + command: + - /bin/sh + - -ec + - | + run_archive() { + timestamp="$(date +%F-%H%M%S)" + archive_name="gitea-files-${timestamp}.tar.gz" + tmp_path="/backup/${archive_name}.tmp" + archive_path="/backup/${archive_name}" + marker_path="/backup/${archive_name}.ready" + tar -C /data -czf "${tmp_path}" . + mv "${tmp_path}" "${archive_path}" + printf "%s" "${archive_name}" > "${marker_path}" + } + + last_run_file="/backup/.gitea-files-backup-last-run" + if [ "${RUN_ON_START}" = "true" ]; then + run_archive || true + date +%F > "${last_run_file}" + fi + + while true; do + current_time="$(date +%H:%M)" + current_day="$(date +%F)" + last_run="$(cat "${last_run_file}" 2>/dev/null || true)" + if [ "${current_time}" = "${BACKUP_TIME}" ] && [ "${last_run}" != "${current_day}" ]; then + if run_archive; then + echo "${current_day}" > "${last_run_file}" + fi + fi + sleep 60 + done + env: + - name: BACKUP_TIME + value: {{ .Values.backup.giteaFiles.time | quote }} + - name: RUN_ON_START + value: {{ ternary "true" "false" .Values.backup.giteaFiles.runOnStart | quote }} + - name: TZ + value: {{ .Values.backup.timeZone | quote }} + volumeMounts: + - name: gitea-data + mountPath: /data + readOnly: true + - name: gitea-files-backup + mountPath: /backup + resources: + {{- toYaml .Values.backup.giteaFiles.resources | nindent 12 }} + - name: gitea-files-upload + image: "{{ .Values.backup.giteaFiles.uploadImage.repository }}:{{ .Values.backup.giteaFiles.uploadImage.tag }}" + imagePullPolicy: {{ .Values.backup.giteaFiles.uploadImage.pullPolicy }} + command: + - /bin/sh + - -ec + - | + credentials_ready() { + case "${AWS_ACCESS_KEY_ID:-}" in ""|GENERATED_*) echo "AWS_ACCESS_KEY_ID is not configured" >&2; return 1;; esac + case "${AWS_SECRET_ACCESS_KEY:-}" in ""|GENERATED_*) echo "AWS_SECRET_ACCESS_KEY is not configured" >&2; return 1;; esac + test -n "${S3_BUCKET:-}" || { echo "S3_BUCKET is not configured" >&2; return 1; } + } + + while true; do + for marker_path in /backup/*.ready; do + [ -e "${marker_path}" ] || continue + archive_name="$(cat "${marker_path}")" + archive_path="/backup/${archive_name}" + [ -f "${archive_path}" ] || continue + + if credentials_ready; then + aws --endpoint-url "${AWS_ENDPOINT_URL}" \ + s3 cp "${archive_path}" "s3://${S3_BUCKET}/${S3_PREFIX}/gitea-files/${archive_name}" + rm -f "${archive_path}" "${marker_path}" + else + sleep 300 + fi + done + sleep 60 + done + env: + - name: S3_BUCKET + value: {{ .Values.backup.s3.bucket | quote }} + - name: S3_PREFIX + value: {{ .Values.backup.s3.prefix | quote }} + - name: AWS_DEFAULT_REGION + value: {{ .Values.backup.s3.region | quote }} + - name: AWS_ENDPOINT_URL + value: {{ .Values.backup.s3.endpointUrl | quote }} + - name: AWS_ACCESS_KEY_ID + valueFrom: + secretKeyRef: + name: {{ include "gitea.secretName" . | quote }} + key: aws-access-key-id + - name: AWS_SECRET_ACCESS_KEY + valueFrom: + secretKeyRef: + name: {{ include "gitea.secretName" . | quote }} + key: aws-secret-access-key + volumeMounts: + - name: gitea-files-backup + mountPath: /backup + resources: + {{- toYaml .Values.backup.giteaFiles.resources | nindent 12 }} + {{- end }} + volumes: + - name: gitea-data + persistentVolumeClaim: + claimName: {{ include "gitea.giteaPvcName" . | quote }} + {{- if and .Values.backup.enabled .Values.backup.giteaFiles.enabled (eq (default "sidecar" .Values.backup.giteaFiles.mode) "sidecar") }} + - name: gitea-files-backup + emptyDir: {} + {{- end }} diff --git a/.helm/templates/gitea-service.yaml b/.helm/templates/gitea-service.yaml new file mode 100644 index 0000000..bb74c1e --- /dev/null +++ b/.helm/templates/gitea-service.yaml @@ -0,0 +1,18 @@ +apiVersion: v1 +kind: Service +metadata: + name: gitea + namespace: {{ .Release.Namespace | quote }} + labels: + {{- include "gitea.labels" . | nindent 4 }} + app: gitea + service: gitea +spec: + type: {{ .Values.gitea.service.type }} + selector: + app: gitea + ports: + - name: http + port: {{ .Values.gitea.service.port }} + targetPort: http + protocol: TCP diff --git a/.helm/templates/pvc.yaml b/.helm/templates/pvc.yaml new file mode 100644 index 0000000..9f8f8d5 --- /dev/null +++ b/.helm/templates/pvc.yaml @@ -0,0 +1,45 @@ +{{- if and .Values.persistence.gitea.create (not .Values.persistence.gitea.existingClaim) }} +apiVersion: v1 +kind: PersistentVolumeClaim +metadata: + name: {{ include "gitea.giteaPvcName" . }} + namespace: {{ .Release.Namespace | quote }} + labels: + {{- include "gitea.labels" . | nindent 4 }} + {{- with .Values.persistence.gitea.annotations }} + annotations: + {{- toYaml . | nindent 4 }} + {{- end }} +spec: + accessModes: + {{- toYaml .Values.persistence.gitea.accessModes | nindent 4 }} + {{- with .Values.persistence.gitea.storageClass }} + storageClassName: {{ . | quote }} + {{- end }} + resources: + requests: + storage: {{ .Values.persistence.gitea.size }} +{{- end }} +{{- if and .Values.persistence.runner.create (not .Values.persistence.runner.existingClaim) }} +--- +apiVersion: v1 +kind: PersistentVolumeClaim +metadata: + name: {{ include "gitea.runnerPvcName" . }} + namespace: {{ .Release.Namespace | quote }} + labels: + {{- include "gitea.labels" . | nindent 4 }} + {{- with .Values.persistence.runner.annotations }} + annotations: + {{- toYaml . | nindent 4 }} + {{- end }} +spec: + accessModes: + {{- toYaml .Values.persistence.runner.accessModes | nindent 4 }} + {{- with .Values.persistence.runner.storageClass }} + storageClassName: {{ . | quote }} + {{- end }} + resources: + requests: + storage: {{ .Values.persistence.runner.size }} +{{- end }} diff --git a/.helm/templates/restore-job.yaml b/.helm/templates/restore-job.yaml new file mode 100644 index 0000000..d67f8a2 --- /dev/null +++ b/.helm/templates/restore-job.yaml @@ -0,0 +1,182 @@ +{{- if and .Values.restore .Values.restore.enabled }} +{{- $restoreFiles := default false .Values.restore.files.enabled }} +{{- $restorePostgresql := default false .Values.restore.postgresql.enabled }} +{{- if not (or $restoreFiles $restorePostgresql) }} +{{- fail "restore.enabled=true requires restore.files.enabled=true or restore.postgresql.enabled=true" }} +{{- end }} +apiVersion: batch/v1 +kind: Job +metadata: + name: {{ .Values.restore.name | quote }} + namespace: {{ .Release.Namespace | quote }} + labels: + {{- include "gitea.labels" . | nindent 4 }} + annotations: + helm.sh/hook: pre-install,pre-upgrade + helm.sh/hook-weight: "0" + helm.sh/hook-delete-policy: before-hook-creation +spec: + backoffLimit: 1 + template: + spec: + restartPolicy: Never + initContainers: + - name: download + image: "{{ .Values.restore.images.awsCli.repository }}:{{ .Values.restore.images.awsCli.tag }}" + imagePullPolicy: {{ .Values.restore.images.awsCli.pullPolicy }} + command: + - /bin/sh + - -ec + - | + case "${AWS_ACCESS_KEY_ID:-}" in ""|GENERATED_*) echo "AWS_ACCESS_KEY_ID is not configured" >&2; exit 1;; esac + case "${AWS_SECRET_ACCESS_KEY:-}" in ""|GENERATED_*) echo "AWS_SECRET_ACCESS_KEY is not configured" >&2; exit 1;; esac + test -n "${S3_BUCKET:-}" || { echo "S3_BUCKET is not configured" >&2; exit 1; } + {{- if $restoreFiles }} + test -n "${GITEA_FILES_KEY}" + aws --endpoint-url "${AWS_ENDPOINT_URL}" s3 cp "s3://${S3_BUCKET}/${GITEA_FILES_KEY}" /restore/gitea-files.tar.gz + {{- end }} + {{- if $restorePostgresql }} + test -n "${POSTGRESQL_DUMP_KEY}" + aws --endpoint-url "${AWS_ENDPOINT_URL}" s3 cp "s3://${S3_BUCKET}/${POSTGRESQL_DUMP_KEY}" /restore/postgresql.sql.gz + {{- end }} + env: + - name: S3_BUCKET + value: {{ .Values.restore.s3.bucket | quote }} + - name: GITEA_FILES_KEY + value: {{ default "" .Values.restore.s3.giteaFilesKey | quote }} + - name: POSTGRESQL_DUMP_KEY + value: {{ default "" .Values.restore.s3.postgresqlDumpKey | quote }} + - name: AWS_DEFAULT_REGION + value: {{ .Values.restore.s3.region | quote }} + - name: AWS_ENDPOINT_URL + value: {{ .Values.restore.s3.endpointUrl | quote }} + - name: AWS_ACCESS_KEY_ID + valueFrom: + secretKeyRef: + name: {{ include "gitea.secretName" . | quote }} + key: aws-access-key-id + - name: AWS_SECRET_ACCESS_KEY + valueFrom: + secretKeyRef: + name: {{ include "gitea.secretName" . | quote }} + key: aws-secret-access-key + volumeMounts: + - name: restore + mountPath: /restore + {{- if $restoreFiles }} + - name: restore-files + image: "{{ .Values.restore.images.busybox.repository }}:{{ .Values.restore.images.busybox.tag }}" + imagePullPolicy: {{ .Values.restore.images.busybox.pullPolicy }} + command: + - /bin/sh + - -ec + - | + rm -rf /data/* /data/.[!.]* /data/..?* + tar -C /data -xzf /restore/gitea-files.tar.gz + volumeMounts: + - name: restore + mountPath: /restore + - name: gitea-data + mountPath: /data + {{- end }} + {{- if $restorePostgresql }} + - name: restore-postgresql + image: "{{ .Values.restore.images.postgres.repository }}:{{ .Values.restore.images.postgres.tag }}" + imagePullPolicy: {{ .Values.restore.images.postgres.pullPolicy }} + command: + - /bin/sh + - -ec + - | + export PGPASSWORD="${POSTGRES_PASSWORD}" + until pg_isready -h "${POSTGRES_HOST}" -U "${POSTGRES_USER}" -d postgres; do + sleep 5 + done + + escaped_user="$(printf "%s" "${POSTGRES_USER}" | sed 's/"/""/g')" + escaped_db="$(printf "%s" "${POSTGRES_DB}" | sed 's/"/""/g')" + + if ! psql -h "${POSTGRES_HOST}" -U "${POSTGRES_USER}" -d postgres -tAc "select 1 from pg_database where datname = '${POSTGRES_DB}'" | grep -q 1; then + createdb -h "${POSTGRES_HOST}" -U "${POSTGRES_USER}" -O "${POSTGRES_USER}" "${POSTGRES_DB}" + fi + + psql -h "${POSTGRES_HOST}" -U "${POSTGRES_USER}" -d postgres -v ON_ERROR_STOP=1 \ + -c "ALTER DATABASE \"${escaped_db}\" OWNER TO \"${escaped_user}\";" + + psql -h "${POSTGRES_HOST}" -U "${POSTGRES_USER}" -d "${POSTGRES_DB}" -v ON_ERROR_STOP=1 \ + -c "DROP SCHEMA IF EXISTS public CASCADE; CREATE SCHEMA public AUTHORIZATION \"${POSTGRES_USER}\"; GRANT ALL ON SCHEMA public TO \"${POSTGRES_USER}\";" + + gunzip -c /restore/postgresql.sql.gz | psql -h "${POSTGRES_HOST}" -U "${POSTGRES_USER}" -d "${POSTGRES_DB}" -v ON_ERROR_STOP=1 + env: + - name: POSTGRES_HOST + value: {{ .Values.restore.postgresql.host | quote }} + - name: POSTGRES_DB + value: {{ .Values.postgresql.auth.database | quote }} + - name: POSTGRES_USER + value: {{ .Values.postgresql.auth.username | quote }} + - name: POSTGRES_PASSWORD + valueFrom: + secretKeyRef: + name: {{ .Values.databaseSecret.name | quote }} + key: {{ .Values.databaseSecret.passwordKey | quote }} + volumeMounts: + - name: restore + mountPath: /restore + {{- end }} + containers: + {{- if .Values.restore.verify.enabled }} + - name: verify + image: "{{ .Values.restore.images.postgres.repository }}:{{ .Values.restore.images.postgres.tag }}" + imagePullPolicy: {{ .Values.restore.images.postgres.pullPolicy }} + command: + - /bin/sh + - -ec + - | + {{- if $restoreFiles }} + test -d /data + objects="$(find /data -mindepth 1 -maxdepth 2 | head -n 1)" + test -n "${objects}" + {{- end }} + {{- if $restorePostgresql }} + tables="$(psql -h "${POSTGRES_HOST}" -U "${POSTGRES_USER}" -d "${POSTGRES_DB}" -tAc "select count(*) from information_schema.tables where table_schema = 'public'")" + test "${tables}" -gt 0 + core_tables="$(psql -h "${POSTGRES_HOST}" -U "${POSTGRES_USER}" -d "${POSTGRES_DB}" -tAc "select count(*) from information_schema.tables where table_schema = 'public' and table_name in ('user', 'repository', 'version')")" + test "${core_tables}" -gt 0 + echo "Gitea database restore verification passed: ${tables} public tables, ${core_tables} core tables" + {{- end }} + echo "Gitea restore verification passed" + env: + - name: POSTGRES_HOST + value: {{ .Values.restore.postgresql.host | quote }} + - name: POSTGRES_DB + value: {{ .Values.postgresql.auth.database | quote }} + - name: POSTGRES_USER + value: {{ .Values.postgresql.auth.username | quote }} + - name: PGPASSWORD + valueFrom: + secretKeyRef: + name: {{ .Values.databaseSecret.name | quote }} + key: {{ .Values.databaseSecret.passwordKey | quote }} + {{- if $restoreFiles }} + volumeMounts: + - name: gitea-data + mountPath: /data + readOnly: true + {{- end }} + {{- else }} + - name: done + image: "{{ .Values.restore.images.busybox.repository }}:{{ .Values.restore.images.busybox.tag }}" + imagePullPolicy: {{ .Values.restore.images.busybox.pullPolicy }} + command: + - /bin/sh + - -ec + - echo "Gitea restore completed" + {{- end }} + volumes: + - name: restore + emptyDir: {} + {{- if $restoreFiles }} + - name: gitea-data + persistentVolumeClaim: + claimName: {{ include "gitea.giteaPvcName" . | quote }} + {{- end }} +{{- end }} diff --git a/.helm/templates/restore-rbac.yaml b/.helm/templates/restore-rbac.yaml new file mode 100644 index 0000000..9f23896 --- /dev/null +++ b/.helm/templates/restore-rbac.yaml @@ -0,0 +1,73 @@ +{{- if and .Values.restore .Values.restore.enabled .Values.restore.scaleGitea.enabled }} +apiVersion: v1 +kind: ServiceAccount +metadata: + name: {{ default .Values.restore.name .Values.restore.scaleGitea.serviceAccountName | quote }} + namespace: {{ .Release.Namespace | quote }} + labels: + {{- include "gitea.labels" . | nindent 4 }} + annotations: + helm.sh/hook: pre-install,pre-upgrade + helm.sh/hook-weight: "-30" + helm.sh/hook-delete-policy: before-hook-creation +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: Role +metadata: + name: {{ default .Values.restore.name .Values.restore.scaleGitea.serviceAccountName | quote }} + namespace: {{ .Release.Namespace | quote }} + labels: + {{- include "gitea.labels" . | nindent 4 }} + annotations: + helm.sh/hook: pre-install,pre-upgrade + helm.sh/hook-weight: "-30" + helm.sh/hook-delete-policy: before-hook-creation +rules: + - apiGroups: + - apps + resources: + - deployments + - deployments/scale + verbs: + - get + - list + - watch + - patch + - update + - apiGroups: + - "" + resources: + - pods + verbs: + - get + - list + - watch + - apiGroups: + - batch + resources: + - jobs + verbs: + - get + - list + - watch +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: RoleBinding +metadata: + name: {{ default .Values.restore.name .Values.restore.scaleGitea.serviceAccountName | quote }} + namespace: {{ .Release.Namespace | quote }} + labels: + {{- include "gitea.labels" . | nindent 4 }} + annotations: + helm.sh/hook: pre-install,pre-upgrade + helm.sh/hook-weight: "-30" + helm.sh/hook-delete-policy: before-hook-creation +subjects: + - kind: ServiceAccount + name: {{ default .Values.restore.name .Values.restore.scaleGitea.serviceAccountName | quote }} + namespace: {{ .Release.Namespace | quote }} +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: Role + name: {{ default .Values.restore.name .Values.restore.scaleGitea.serviceAccountName | quote }} +{{- end }} diff --git a/.helm/templates/restore-scale-down-job.yaml b/.helm/templates/restore-scale-down-job.yaml new file mode 100644 index 0000000..13f6956 --- /dev/null +++ b/.helm/templates/restore-scale-down-job.yaml @@ -0,0 +1,38 @@ +{{- if and .Values.restore .Values.restore.enabled .Values.restore.scaleGitea.enabled }} +apiVersion: batch/v1 +kind: Job +metadata: + name: {{ printf "%s-scale-down" .Values.restore.name | quote }} + namespace: {{ .Release.Namespace | quote }} + labels: + {{- include "gitea.labels" . | nindent 4 }} + annotations: + helm.sh/hook: pre-install,pre-upgrade + helm.sh/hook-weight: "-10" + helm.sh/hook-delete-policy: before-hook-creation +spec: + backoffLimit: 1 + template: + spec: + restartPolicy: Never + serviceAccountName: {{ default .Values.restore.name .Values.restore.scaleGitea.serviceAccountName | quote }} + containers: + - name: scale-down-gitea + image: "{{ .Values.restore.images.kubectl.repository }}:{{ .Values.restore.images.kubectl.tag }}" + imagePullPolicy: {{ .Values.restore.images.kubectl.pullPolicy }} + command: + - /bin/sh + - -ec + - | + kubectl -n "${K8S_NAMESPACE}" scale deployment "${GITEA_DEPLOYMENT_NAME}" --replicas=0 + kubectl -n "${K8S_NAMESPACE}" wait --for=delete pod -l app=gitea --timeout="${WAIT_TIMEOUT_SECONDS}s" || true + env: + - name: K8S_NAMESPACE + valueFrom: + fieldRef: + fieldPath: metadata.namespace + - name: GITEA_DEPLOYMENT_NAME + value: {{ .Values.restore.scaleGitea.deploymentName | quote }} + - name: WAIT_TIMEOUT_SECONDS + value: {{ .Values.restore.scaleGitea.waitTimeoutSeconds | quote }} +{{- end }} diff --git a/.helm/templates/restore-scale-up-job.yaml b/.helm/templates/restore-scale-up-job.yaml new file mode 100644 index 0000000..6c4cd24 --- /dev/null +++ b/.helm/templates/restore-scale-up-job.yaml @@ -0,0 +1,42 @@ +{{- if and .Values.restore .Values.restore.enabled .Values.restore.scaleGitea.enabled .Values.restore.scaleGitea.scaleUp.enabled }} +apiVersion: batch/v1 +kind: Job +metadata: + name: {{ printf "%s-scale-up" .Values.restore.name | quote }} + namespace: {{ .Release.Namespace | quote }} + labels: + {{- include "gitea.labels" . | nindent 4 }} + annotations: + helm.sh/hook: pre-install,pre-upgrade + helm.sh/hook-weight: "10" + helm.sh/hook-delete-policy: before-hook-creation +spec: + backoffLimit: 1 + template: + spec: + restartPolicy: Never + serviceAccountName: {{ default .Values.restore.name .Values.restore.scaleGitea.serviceAccountName | quote }} + containers: + - name: scale-up-gitea + image: "{{ .Values.restore.images.kubectl.repository }}:{{ .Values.restore.images.kubectl.tag }}" + imagePullPolicy: {{ .Values.restore.images.kubectl.pullPolicy }} + command: + - /bin/sh + - -ec + - | + kubectl -n "${K8S_NAMESPACE}" wait --for=condition=complete "job/${RESTORE_JOB_NAME}" --timeout="${RESTORE_WAIT_TIMEOUT_SECONDS}s" + kubectl -n "${K8S_NAMESPACE}" scale deployment "${GITEA_DEPLOYMENT_NAME}" --replicas="${REPLICAS_AFTER_RESTORE}" + env: + - name: K8S_NAMESPACE + valueFrom: + fieldRef: + fieldPath: metadata.namespace + - name: RESTORE_JOB_NAME + value: {{ .Values.restore.name | quote }} + - name: GITEA_DEPLOYMENT_NAME + value: {{ .Values.restore.scaleGitea.deploymentName | quote }} + - name: REPLICAS_AFTER_RESTORE + value: {{ .Values.restore.scaleGitea.scaleUp.replicas | quote }} + - name: RESTORE_WAIT_TIMEOUT_SECONDS + value: {{ .Values.restore.scaleGitea.scaleUp.waitForRestoreTimeoutSeconds | quote }} +{{- end }} diff --git a/.helm/templates/runner-configmap.yaml b/.helm/templates/runner-configmap.yaml new file mode 100644 index 0000000..af111d1 --- /dev/null +++ b/.helm/templates/runner-configmap.yaml @@ -0,0 +1,43 @@ +apiVersion: v1 +kind: ConfigMap +metadata: + name: gitea-runner-config + namespace: {{ .Release.Namespace | quote }} + labels: + {{- include "gitea.labels" . | nindent 4 }} +data: + config.yaml: |- +{{ toYaml .Values.runner.config | nindent 4 }} +--- +apiVersion: v1 +kind: ConfigMap +metadata: + name: gitea-runner-entrypoint + namespace: {{ .Release.Namespace | quote }} + labels: + {{- include "gitea.labels" . | nindent 4 }} +data: + runner-entrypoint.sh: |- + #!/bin/sh + set -eu + + case "${GITEA_RUNNER_REGISTRATION_TOKEN:-}" in + ""|GENERATED_*) + echo "GITEA_RUNNER_REGISTRATION_TOKEN is not configured in Kubernetes secret" + echo "Patch secret gitea-secret key runner-registration-token and restart this pod" + exec tail -f /dev/null + ;; + esac + + if [ ! -f /data/.runner ]; then + echo "Registering Gitea runner ${GITEA_RUNNER_NAME} ..." + act_runner register --no-interactive \ + --instance "${GITEA_INSTANCE_URL}" \ + --token "${GITEA_RUNNER_REGISTRATION_TOKEN}" \ + --name "${GITEA_RUNNER_NAME}" \ + --labels "${GITEA_RUNNER_LABELS}" \ + --config /config.yaml + fi + + echo "Starting Gitea runner daemon" + exec act_runner daemon --config /config.yaml diff --git a/.helm/templates/secret.yaml b/.helm/templates/secret.yaml new file mode 100644 index 0000000..764515f --- /dev/null +++ b/.helm/templates/secret.yaml @@ -0,0 +1,31 @@ +{{- if .Values.giteaSecret.create }} +{{- $secretName := include "gitea.secretName" . }} +{{- $existingSecret := lookup "v1" "Secret" .Release.Namespace $secretName }} +{{- if not $existingSecret }} +{{- $runnerToken := printf "GENERATED_%s" (randAlphaNum 48) }} +{{- $awsAccessKeyId := printf "GENERATED_%s" (randAlphaNum 32) }} +{{- $awsSecretAccessKey := printf "GENERATED_%s" (randAlphaNum 64) }} +{{- $kubeconfig := "apiVersion: v1\nclusters: []\ncontexts: []\ncurrent-context: \"\"\nkind: Config\npreferences: {}\nusers: []" }} +{{- $dockerConfigJson := "{\"auths\":{}}" }} +apiVersion: v1 +kind: Secret +metadata: + name: {{ $secretName }} + namespace: {{ .Release.Namespace | quote }} + labels: + {{- include "gitea.labels" . | nindent 4 }} + {{- if .Values.giteaSecret.keep }} + annotations: + helm.sh/resource-policy: keep + {{- end }} +type: Opaque +stringData: + runner-registration-token: {{ $runnerToken | quote }} + aws-access-key-id: {{ $awsAccessKeyId | quote }} + aws-secret-access-key: {{ $awsSecretAccessKey | quote }} + kubeconfig: |- +{{ $kubeconfig | nindent 4 }} + docker-config.json: |- +{{ $dockerConfigJson | nindent 4 }} +{{- end }} +{{- end }} diff --git a/.helm/templates/ssh-service.yaml b/.helm/templates/ssh-service.yaml new file mode 100644 index 0000000..6ea2bbd --- /dev/null +++ b/.helm/templates/ssh-service.yaml @@ -0,0 +1,24 @@ +{{- if .Values.sshService.enabled }} +apiVersion: v1 +kind: Service +metadata: + name: {{ .Values.sshService.name | quote }} + namespace: {{ .Release.Namespace | quote }} + labels: + {{- include "gitea.labels" . | nindent 4 }} +spec: + type: {{ .Values.sshService.type }} + {{- if and .Values.sshService.externalTrafficPolicy (or (eq .Values.sshService.type "NodePort") (eq .Values.sshService.type "LoadBalancer")) }} + externalTrafficPolicy: {{ .Values.sshService.externalTrafficPolicy }} + {{- end }} + selector: + app: gitea + ports: + - name: ssh + port: {{ .Values.sshService.port }} + targetPort: {{ .Values.sshService.targetPort }} + protocol: TCP + {{- if and (eq .Values.sshService.type "NodePort") .Values.sshService.nodePort }} + nodePort: {{ .Values.sshService.nodePort }} + {{- end }} +{{- end }} diff --git a/.helm/values.yaml b/.helm/values.yaml new file mode 100644 index 0000000..4c5cca9 --- /dev/null +++ b/.helm/values.yaml @@ -0,0 +1,521 @@ +global: + nameOverride: "" + fullnameOverride: "" + imagePullSecrets: [] + labels: {} + +giteaSecret: + create: true + name: gitea-secret + keep: true + +databaseSecret: + name: postgresql-secret + adminPasswordKey: admin-password + passwordKey: user-password + +persistence: + gitea: + create: true + name: gitea-data + existingClaim: "" + accessModes: + - ReadWriteOnce + storageClass: "" + size: 50Gi + annotations: {} + runner: + create: true + name: gitea-runner-data + existingClaim: "" + accessModes: + - ReadWriteOnce + storageClass: "" + size: 10Gi + annotations: {} + +postgresql: + enabled: true + fullnameOverride: postgresql + global: + imagePullSecrets: [] + security: + allowInsecureImages: true + postgresql: + auth: + username: gitea + database: gitea + existingSecret: postgresql-secret + secretKeys: + adminPasswordKey: admin-password + userPasswordKey: user-password + replicationPasswordKey: replication-password + auth: + username: gitea + database: gitea + existingSecret: postgresql-secret + secretKeys: + adminPasswordKey: admin-password + userPasswordKey: user-password + replicationPasswordKey: replication-password + image: + repository: contour/postgresql + pullSecrets: [] + primary: + podAntiAffinityPreset: "" + networkPolicy: + enabled: false + podSecurityContext: + enabled: false + containerSecurityContext: + enabled: false + persistence: + storageClass: "" + size: 20Gi + resources: + requests: + cpu: 100m + memory: 256Mi + limits: + cpu: 1000m + memory: 1Gi + metrics: + enabled: false + image: + pullSecrets: [] + serviceMonitor: + enabled: false + prometheusRule: + enabled: false + volumePermissions: + image: + pullSecrets: [] + +sshService: + enabled: true + name: gitea-ssh + type: NodePort + port: 22 + targetPort: 22 + nodePort: 30222 + externalTrafficPolicy: Cluster + +runner: + config: + log: + level: info + runner: + file: /data/.runner + capacity: 2 + insecure: false + timeout: 3h + cache: + enabled: true + dir: /data/cache + container: + network: "" + privileged: false + +gitea: + replicaCount: 1 + image: + repository: gitea/gitea + tag: "1.22.6" + pullPolicy: IfNotPresent + service: + type: ClusterIP + port: 3000 + targetPort: 3000 + uid: "1000" + gid: "1000" + domain: 158-160-253-227.nip.io + sshDomain: 158-160-253-227.nip.io + rootUrl: https://158-160-253-227.nip.io/ + httpPort: "3000" + sshPort: "30222" + sshListenPort: "22" + timezone: Europe/Moscow + resources: + requests: + cpu: 200m + memory: 512Mi + limits: + cpu: 2000m + memory: 2Gi + probes: + startup: + initialDelaySeconds: 10 + periodSeconds: 10 + timeoutSeconds: 2 + failureThreshold: 60 + readiness: + initialDelaySeconds: 10 + periodSeconds: 10 + liveness: + initialDelaySeconds: 30 + periodSeconds: 30 + +backup: + enabled: true + timeZone: Europe/Moscow + s3: + bucket: gitops-gitea + region: ru-central1 + endpointUrl: https://storage.yandexcloud.net + prefix: gitops-backups + giteaFiles: + enabled: true + mode: sidecar + schedule: "30 2 * * *" + time: "02:30" + runOnStart: false + archiveImage: + repository: busybox + tag: "1.36" + pullPolicy: IfNotPresent + uploadImage: + repository: amazon/aws-cli + tag: "2.15.57" + pullPolicy: IfNotPresent + successfulJobsHistoryLimit: 3 + failedJobsHistoryLimit: 3 + ttlSecondsAfterFinished: 86400 + resources: + requests: + cpu: 100m + memory: 128Mi + limits: + cpu: 1000m + memory: 1Gi + postgresql: + enabled: true + schedule: "45 2 * * *" + host: postgresql + dumpImage: + repository: postgres + tag: "17" + pullPolicy: IfNotPresent + uploadImage: + repository: amazon/aws-cli + tag: "2.15.57" + pullPolicy: IfNotPresent + successfulJobsHistoryLimit: 3 + failedJobsHistoryLimit: 3 + ttlSecondsAfterFinished: 86400 + resources: + requests: + cpu: 100m + memory: 128Mi + limits: + cpu: 1000m + memory: 1Gi + +universal-chart: + global: + env: _default + + services: + gitea: + enabled: false + deployment: + enabled: true + name: + _default: gitea + replicaCount: + _default: 1 + port: + _default: 3000 + revisionHistoryLimit: + _default: 10 + resources: + requests: + cpu: + _default: 200m + memory: + _default: 512Mi + limits: + cpu: + _default: 2000m + memory: + _default: 2Gi + probes: + startup: + enabled: + _default: true + type: + _default: tcpSocket + tcpSocket: + port: + _default: 3000 + initialDelaySeconds: + _default: 10 + periodSeconds: + _default: 10 + timeoutSeconds: + _default: 2 + failureThreshold: + _default: 60 + liveness: + enabled: + _default: true + type: + _default: tcpSocket + tcpSocket: + port: + _default: 3000 + initialDelaySeconds: + _default: 30 + periodSeconds: + _default: 30 + readiness: + enabled: + _default: true + type: + _default: tcpSocket + tcpSocket: + port: + _default: 3000 + initialDelaySeconds: + _default: 10 + periodSeconds: + _default: 10 + image: + name: + _default: gitea/gitea:1.22.6 + pullPolicy: + _default: IfNotPresent + imagePullSecrets: + enabled: + _default: false + name: + _default: dockerhub + service: + enabled: true + name: + _default: gitea + type: + _default: ClusterIP + portName: + _default: http + port: + _default: 3000 + targetPort: + _default: http + envs: + - name: USER_UID + value: + _default: "1000" + - name: USER_GID + value: + _default: "1000" + - name: GITEA__database__DB_TYPE + value: + _default: postgres + - name: GITEA__database__HOST + value: + _default: postgresql:5432 + - name: GITEA__database__NAME + value: + _default: gitea + - name: GITEA__database__USER + value: + _default: gitea + - name: GITEA__server__DOMAIN + value: + _default: 158-160-253-227.nip.io + - name: GITEA__server__SSH_DOMAIN + value: + _default: 158-160-253-227.nip.io + - name: GITEA__server__ROOT_URL + value: + _default: https://158-160-253-227.nip.io/ + - name: GITEA__server__HTTP_PORT + value: + _default: "3000" + - name: GITEA__server__SSH_PORT + value: + _default: "30222" + - name: GITEA__server__SSH_LISTEN_PORT + value: + _default: "22" + - name: GITEA__security__INSTALL_LOCK + value: + _default: "true" + - name: GITEA__actions__ENABLED + value: + _default: "true" + - name: TZ + value: + _default: Europe/Moscow + secretEnvs: + - name: GITEA__database__PASSWD + secretName: + _default: postgresql-secret + secretKey: + _default: user-password + volumes: + _default: + - name: gitea-data + mountPath: /data + persistentVolumeClaim: + claimName: + _default: gitea-data + commitSha: "" + gitlabUri: "" + gitlabJobUrl: "" + owner: platform + + gitea-ci-worker: + enabled: true + deployment: + enabled: true + name: + _default: gitea-ci-worker + replicaCount: + _default: 1 + port: + _default: 8088 + command: + _default: + - /bin/sh + - /runner-entrypoint.sh + revisionHistoryLimit: + _default: 10 + resources: + requests: + cpu: + _default: 200m + memory: + _default: 256Mi + limits: + cpu: + _default: 2000m + memory: + _default: 2Gi + probes: + liveness: + enabled: false + readiness: + enabled: false + image: + name: + _default: gitea/act_runner:0.2.11 + pullPolicy: + _default: IfNotPresent + imagePullSecrets: + enabled: + _default: false + name: + _default: dockerhub + service: + enabled: false + name: + _default: gitea-ci-worker + type: + _default: ClusterIP + portName: + _default: http + port: + _default: 8088 + targetPort: + _default: http + envs: + - name: GITEA_INSTANCE_URL + value: + _default: http://gitea:3000/ + - name: GITEA_RUNNER_NAME + value: + _default: registry01-runner + - name: GITEA_RUNNER_LABELS + value: + _default: linux-amd64:docker://node:20-bookworm,linux-shell:host + - name: DOCKER_HOST + value: + _default: unix:///var/run/docker.sock + - name: KUBECONFIG + value: + _default: /data/.kube/config + - name: KUBE_CONTEXT + value: + _default: yc-k8s-test + - name: AWS_DEFAULT_REGION + value: + _default: ru-central1 + - name: AWS_ENDPOINT_URL + value: + _default: https://storage.yandexcloud.net + - name: S3_BUCKET + value: + _default: gitops-gitea + - name: S3_PREFIX + value: + _default: gitops-backups + secretEnvs: + - name: GITEA_RUNNER_REGISTRATION_TOKEN + secretName: + _default: gitea-secret + secretKey: + _default: runner-registration-token + - name: AWS_ACCESS_KEY_ID + secretName: + _default: gitea-secret + secretKey: + _default: aws-access-key-id + - name: AWS_SECRET_ACCESS_KEY + secretName: + _default: gitea-secret + secretKey: + _default: aws-secret-access-key + volumes: + _default: + - name: runner-data + mountPath: /data + persistentVolumeClaim: + claimName: + _default: gitea-runner-data + - name: runner-config + mountPath: /config.yaml + subPath: config.yaml + readOnly: true + configMap: + name: gitea-runner-config + items: + - key: config.yaml + path: config.yaml + - name: runner-entrypoint + mountPath: /runner-entrypoint.sh + subPath: runner-entrypoint.sh + readOnly: true + configMap: + name: gitea-runner-entrypoint + defaultMode: 493 + items: + - key: runner-entrypoint.sh + path: runner-entrypoint.sh + - name: docker-config + mountPath: /root/.docker/config.json + subPath: config.json + readOnly: true + secret: + secretName: gitea-secret + items: + - key: docker-config.json + path: config.json + - name: kubeconfig + mountPath: /data/.kube/config + subPath: config + readOnly: true + secret: + secretName: gitea-secret + items: + - key: kubeconfig + path: config + - name: docker-sock + mountPath: /var/run/docker.sock + hostPath: + path: /var/run/docker.sock + type: Socket + commitSha: "" + gitlabUri: "" + gitlabJobUrl: "" + owner: platform diff --git a/README.md b/README.md new file mode 100644 index 0000000..fd8e570 --- /dev/null +++ b/README.md @@ -0,0 +1,80 @@ +# Gitea Helm chart + +Чарт лежит в `.helm`. + +Зависимости: + +- `universal-chart` `0.1.9` для `gitea-ci-worker` +- статический `Deployment` для `gitea`, потому что файловый backup должен жить sidecar-ом в том же pod-е, где смонтирован RWO PVC +- `postgresql-preprod` `16.4.8` из `oci://cr.yandex/crp3ccidau046kdj8g9q/charts` + +HTTP-маршрутизации здесь нет: ни `Ingress`, ни `VirtualService`. VS управляется отдельным чартом. + +## Секреты + +В `values.yaml` нет чувствительных значений. Чарт создает `gitea-secret` через `lookup`: если Secret уже существует, значения сохраняются; если нет, создаются сгенерированные заглушки. С заглушками runner и S3 backup не заработают, пока Secret не будет заполнен реальными данными. + +Перед установкой можно создать Secret отдельно: + +```bash +kubectl create namespace gitea --dry-run=client -o yaml | kubectl apply -f - + +kubectl -n gitea create secret generic gitea-secret \ + --from-literal=runner-registration-token="$GITEA_RUNNER_REGISTRATION_TOKEN" \ + --from-literal=aws-access-key-id="$AWS_ACCESS_KEY_ID" \ + --from-literal=aws-secret-access-key="$AWS_SECRET_ACCESS_KEY" \ + --from-file=kubeconfig=./runner/kubeconfig/config \ + --from-file=docker-config.json=./runner/docker-config/config.json \ + --dry-run=client -o yaml | kubectl apply -f - +``` + +PostgreSQL пароль живет в `postgresql-secret`, который создает PostgreSQL chart и сохраняет через `helm.sh/resource-policy: keep`. Gitea читает ключ `user-password`. + +## Установка + +```bash +helm dependency update .helm +helm upgrade --install gitea .helm -n gitea --create-namespace +``` + +Если Secret создан уже после установки, перезапустить runner: + +```bash +kubectl -n gitea rollout restart deploy/gitea-ci-worker +``` + +## Backup + +Backup включен по умолчанию: + +- `gitea-files-backup`: sidecar внутри pod `gitea`, каждый день в `02:30` архивирует `/data` и кладет в `s3://gitops-gitea/gitops-backups/gitea-files/`. Отдельного pod-а с mount PVC нет, поэтому не возникает second attach/Multi-Attach для `gitea-data`. +- `gitea-postgresql-backup`: каждый день в `02:45`, делает `pg_dump | gzip` и кладет в `s3://gitops-gitea/gitops-backups/postgresql/` + +Оба backup-процесса используют S3-ключи из `gitea-secret`. Если там сгенерированные заглушки, backup завершится с понятной ошибкой и ничего не загрузит. + +## Restore + +Restore не включен в обычную установку. Это разовый Job, который включается отдельным values-файлом. + +1. Взять имена объектов из S3: + +```bash +aws --endpoint-url "$AWS_ENDPOINT_URL" s3 ls s3://gitops-gitea/gitops-backups/gitea-files/ +aws --endpoint-url "$AWS_ENDPOINT_URL" s3 ls s3://gitops-gitea/gitops-backups/postgresql/ +``` + +2. Скопировать `.helm/restore-values.example.yaml`, указать реальные `giteaFilesKey` и/или `postgresqlDumpKey`. + +3. Запустить restore: + +```bash +helm upgrade --install gitea .helm -n gitea -f restore-values.yaml +``` + +Режимы restore: + +- полный restore: `restore.files.enabled=true` и `restore.postgresql.enabled=true` +- только файлы: `restore.files.enabled=true`, `restore.postgresql.enabled=false` +- только база: `restore.files.enabled=false`, `restore.postgresql.enabled=true` + +Restore Job при `restore.scaleGitea.enabled=true` сначала масштабирует deployment `gitea` в `0` и ждёт удаления pod-а. Это нужно, чтобы restore файлов не монтировал RWO PVC одновременно с Gitea. После успешного completion отдельный `gitea-restore-scale-up` Job возвращает replicas обратно.