diff --git a/.github/dependabot.yml b/.github/dependabot.yml index 2dd57525..7f3bf9d2 100644 --- a/.github/dependabot.yml +++ b/.github/dependabot.yml @@ -10,3 +10,7 @@ updates: commit-message: prefix: "chore(deps)" open-pull-requests-limit: 10 + - package-ecosystem: "github-actions" + directory: "/" + schedule: + interval: "weekly" diff --git a/.github/workflows/build-and-push.yaml b/.github/workflows/build-and-push.yaml index 545a18f0..e3bfca2b 100644 --- a/.github/workflows/build-and-push.yaml +++ b/.github/workflows/build-and-push.yaml @@ -2,7 +2,9 @@ name: Build and Push on: push: - branches: + paths: + - '!charts/**.md' + branches: - main tags: - v* diff --git a/.github/workflows/chart-lint-test.yaml b/.github/workflows/chart-lint-test.yaml new file mode 100644 index 00000000..c5a8508c --- /dev/null +++ b/.github/workflows/chart-lint-test.yaml @@ -0,0 +1,50 @@ +name: Lint and Test Charts + +on: + pull_request: + paths: + - charts/** + - '!charts/**.md' +jobs: + lint-test: + runs-on: ubuntu-latest + steps: + - name: Checkout + uses: actions/checkout@v3.1.0 + with: + fetch-depth: 0 + + - name: Set up Helm + uses: azure/setup-helm@v3 + with: + version: v3.8.1 + + # Python is required because `ct lint` runs Yamale (https://github.com/23andMe/Yamale) and + # yamllint (https://github.com/adrienverge/yamllint) which require Python + - name: Set up Python + uses: actions/setup-python@v4.1.0 + with: + python-version: 3.7 + + - name: Set up chart-testing + uses: helm/chart-testing-action@v2.2.1 + with: + version: v3.5.1 + + - name: Run chart-testing (list-changed) + id: list-changed + run: | + changed=$(ct list-changed --config ct.yaml) + if [[ -n "$changed" ]]; then + echo "changed=true" >> $GITHUB_OUTPUT + fi + + - name: Run chart-testing (lint) + run: ct lint --config ct.yaml + + - name: Create kind cluster + uses: helm/kind-action@v1.7.0 + if: steps.list-changed.outputs.changed == 'true' + + - name: Run chart-testing (install) + run: ct install --config ct.yaml diff --git a/.github/workflows/chart-release.yaml b/.github/workflows/chart-release.yaml new file mode 100644 index 00000000..6399d4b4 --- /dev/null +++ b/.github/workflows/chart-release.yaml @@ -0,0 +1,40 @@ +name: Release Charts + +on: + push: + paths: + - charts/** + - '!**.md' + branches: + - main + +jobs: + release: + runs-on: ubuntu-latest + + permissions: + contents: write + + steps: + - name: Checkout + uses: actions/checkout@8ade135a41bc03ea155e62e844d188df1ea18608 # v4.1.0 + with: + fetch-depth: 0 + + - name: Configure Git + run: | + git config user.name "$GITHUB_ACTOR" + git config user.email "$GITHUB_ACTOR@users.noreply.github.com" + + - name: Install Helm + uses: azure/setup-helm@5119fcb9089d432beecbf79bb2c7915207344b78 # v3.5 + with: + version: v3.13.0 + + - name: Run chart-releaser + uses: helm/chart-releaser-action@be16258da8010256c6e82849661221415f031968 # v1.5.0 + with: + charts_dir: charts + config: cr.yaml + env: + CR_TOKEN: "${{ secrets.GITHUB_TOKEN }}" diff --git a/.github/workflows/generate-chart-readme.yaml b/.github/workflows/generate-chart-readme.yaml new file mode 100644 index 00000000..affc40cf --- /dev/null +++ b/.github/workflows/generate-chart-readme.yaml @@ -0,0 +1,48 @@ +name: '[CI/CD] Update README metadata' + +on: + pull_request_target: + branches: + - main + paths: + - 'charts/*/values.yaml' +# Remove all permissions by default +permissions: {} +jobs: + update-readme-metadata: + runs-on: ubuntu-latest + permissions: + contents: write + steps: + - name: Install readme-generator-for-helm + run: npm install -g @bitnami/readme-generator-for-helm + - name: Checkout + uses: actions/checkout@8ade135a41bc03ea155e62e844d188df1ea18608 + with: + path: charts + ref: ${{github.event.pull_request.head.ref}} + repository: ${{github.event.pull_request.head.repo.full_name}} + token: ${{ secrets.GITHUB_TOKEN }} + - name: Execute readme-generator-for-helm + env: + DIFF_URL: "${{github.event.pull_request.diff_url}}" + TEMP_FILE: "${{runner.temp}}/pr-${{github.event.number}}.diff" + run: | + # This request doesn't consume API calls. + curl -Lkso $TEMP_FILE $DIFF_URL + files_changed="$(sed -nr 's/[\-\+]{3} [ab]\/(.*)/\1/p' $TEMP_FILE | sort | uniq)" + # Adding || true to avoid "Process exited with code 1" errors + charts_dirs_changed="$(echo "$files_changed" | xargs dirname | grep -o "pgcat/[^/]*" | sort | uniq || true)" + for chart in ${charts_dirs_changed}; do + echo "Updating README.md for ${chart}" + readme-generator --values "charts/${chart}/values.yaml" --readme "charts/${chart}/README.md" --schema "/tmp/schema.json" + done + - name: Push changes + run: | + # Push all the changes + cd charts + if git status -s | grep pgcat; then + git config user.name "$GITHUB_ACTOR" + git config user.email "$GITHUB_ACTOR@users.noreply.github.com" + git add . && git commit -am "Update README.md with readme-generator-for-helm" --signoff && git push + fi diff --git a/charts/pgcat/.helmignore b/charts/pgcat/.helmignore new file mode 100644 index 00000000..0e8a0eb3 --- /dev/null +++ b/charts/pgcat/.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/charts/pgcat/Chart.yaml b/charts/pgcat/Chart.yaml new file mode 100644 index 00000000..c77d29c0 --- /dev/null +++ b/charts/pgcat/Chart.yaml @@ -0,0 +1,8 @@ +apiVersion: v2 +name: pgcat +description: A Helm chart for PgCat a PostgreSQL pooler and proxy (like PgBouncer) with support for sharding, load balancing, failover and mirroring. +maintainers: + - name: Wildcard + email: support@w6d.io +appVersion: "1.1.1" +version: 0.1.0 diff --git a/charts/pgcat/templates/NOTES.txt b/charts/pgcat/templates/NOTES.txt new file mode 100644 index 00000000..552645b3 --- /dev/null +++ b/charts/pgcat/templates/NOTES.txt @@ -0,0 +1,22 @@ +1. Get the application URL by running these commands: +{{- if .Values.ingress.enabled }} +{{- range $host := .Values.ingress.hosts }} + {{- range .paths }} + http{{ if $.Values.ingress.tls }}s{{ end }}://{{ $host.host }}{{ .path }} + {{- end }} +{{- end }} +{{- else if contains "NodePort" .Values.service.type }} + export NODE_PORT=$(kubectl get --namespace {{ .Release.Namespace }} -o jsonpath="{.spec.ports[0].nodePort}" services {{ include "pgcat.fullname" . }}) + export NODE_IP=$(kubectl get nodes --namespace {{ .Release.Namespace }} -o jsonpath="{.items[0].status.addresses[0].address}") + echo http://$NODE_IP:$NODE_PORT +{{- else if contains "LoadBalancer" .Values.service.type }} + NOTE: It may take a few minutes for the LoadBalancer IP to be available. + You can watch the status of by running 'kubectl get --namespace {{ .Release.Namespace }} svc -w {{ include "pgcat.fullname" . }}' + export SERVICE_IP=$(kubectl get svc --namespace {{ .Release.Namespace }} {{ include "pgcat.fullname" . }} --template "{{"{{ range (index .status.loadBalancer.ingress 0) }}{{.}}{{ end }}"}}") + echo http://$SERVICE_IP:{{ .Values.service.port }} +{{- else if contains "ClusterIP" .Values.service.type }} + export POD_NAME=$(kubectl get pods --namespace {{ .Release.Namespace }} -l "app.kubernetes.io/name={{ include "pgcat.name" . }},app.kubernetes.io/instance={{ .Release.Name }}" -o jsonpath="{.items[0].metadata.name}") + export CONTAINER_PORT=$(kubectl get pod --namespace {{ .Release.Namespace }} $POD_NAME -o jsonpath="{.spec.containers[0].ports[0].containerPort}") + echo "Visit http://127.0.0.1:8080 to use your application" + kubectl --namespace {{ .Release.Namespace }} port-forward $POD_NAME 8080:$CONTAINER_PORT +{{- end }} diff --git a/charts/pgcat/templates/_config.tpl b/charts/pgcat/templates/_config.tpl new file mode 100644 index 00000000..09423a11 --- /dev/null +++ b/charts/pgcat/templates/_config.tpl @@ -0,0 +1,3 @@ +{{/* + Configuration template definition +*/}} diff --git a/charts/pgcat/templates/_helpers.tpl b/charts/pgcat/templates/_helpers.tpl new file mode 100644 index 00000000..07c2d25f --- /dev/null +++ b/charts/pgcat/templates/_helpers.tpl @@ -0,0 +1,62 @@ +{{/* +Expand the name of the chart. +*/}} +{{- define "pgcat.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 "pgcat.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 "pgcat.chart" -}} +{{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" }} +{{- end }} + +{{/* +Common labels +*/}} +{{- define "pgcat.labels" -}} +helm.sh/chart: {{ include "pgcat.chart" . }} +{{ include "pgcat.selectorLabels" . }} +{{- if .Chart.AppVersion }} +app.kubernetes.io/version: {{ .Chart.AppVersion | quote }} +{{- end }} +app.kubernetes.io/managed-by: {{ .Release.Service }} +{{- end }} + +{{/* +Selector labels +*/}} +{{- define "pgcat.selectorLabels" -}} +app.kubernetes.io/name: {{ include "pgcat.name" . }} +app.kubernetes.io/instance: {{ .Release.Name }} +{{- end }} + +{{/* +Create the name of the service account to use +*/}} +{{- define "pgcat.serviceAccountName" -}} +{{- if .Values.serviceAccount.create }} +{{- default (include "pgcat.fullname" .) .Values.serviceAccount.name }} +{{- else }} +{{- default "default" .Values.serviceAccount.name }} +{{- end }} +{{- end }} diff --git a/charts/pgcat/templates/deployment.yaml b/charts/pgcat/templates/deployment.yaml new file mode 100644 index 00000000..84c57f1b --- /dev/null +++ b/charts/pgcat/templates/deployment.yaml @@ -0,0 +1,66 @@ +apiVersion: apps/v1 +kind: Deployment +metadata: + name: {{ include "pgcat.fullname" . }} + labels: + {{- include "pgcat.labels" . | nindent 4 }} +spec: + replicas: {{ .Values.replicaCount }} + selector: + matchLabels: + {{- include "pgcat.selectorLabels" . | nindent 6 }} + template: + metadata: + annotations: + checksum/secret: {{ include (print $.Template.BasePath "/secret.yaml") . | sha256sum }} + {{- with .Values.podAnnotations }} + {{- toYaml . | nindent 8 }} + {{- end }} + labels: + {{- include "pgcat.selectorLabels" . | nindent 8 }} + spec: + {{- with .Values.image.pullSecrets }} + imagePullSecrets: + {{- toYaml . | nindent 8 }} + {{- end }} + serviceAccountName: {{ include "pgcat.serviceAccountName" . }} + securityContext: + {{- toYaml .Values.podSecurityContext | nindent 8 }} + containers: + - name: {{ .Chart.Name }} + securityContext: + {{- toYaml .Values.containerSecurityContext | nindent 12 }} + image: "{{ .Values.image.repository }}:{{ .Values.image.tag | default .Chart.AppVersion }}" + imagePullPolicy: {{ .Values.image.pullPolicy }} + ports: + - name: pgcat + containerPort: {{ .Values.configuration.general.port }} + protocol: TCP + livenessProbe: + tcpSocket: + port: pgcat + readinessProbe: + tcpSocket: + port: pgcat + resources: + {{- toYaml .Values.resources | nindent 12 }} + volumeMounts: + - mountPath: /etc/pgcat + name: config + {{- with .Values.nodeSelector }} + nodeSelector: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.affinity }} + affinity: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.tolerations }} + tolerations: + {{- toYaml . | nindent 8 }} + {{- end }} + volumes: + - secret: + defaultMode: 420 + secretName: {{ include "pgcat.fullname" . }} + name: config diff --git a/charts/pgcat/templates/ingress.yaml b/charts/pgcat/templates/ingress.yaml new file mode 100644 index 00000000..1b1a5b38 --- /dev/null +++ b/charts/pgcat/templates/ingress.yaml @@ -0,0 +1,61 @@ +{{- if .Values.ingress.enabled -}} +{{- $fullName := include "pgcat.fullname" . -}} +{{- $svcPort := .Values.service.port -}} +{{- if and .Values.ingress.className (not (semverCompare ">=1.18-0" .Capabilities.KubeVersion.GitVersion)) }} + {{- if not (hasKey .Values.ingress.annotations "kubernetes.io/ingress.class") }} + {{- $_ := set .Values.ingress.annotations "kubernetes.io/ingress.class" .Values.ingress.className}} + {{- end }} +{{- end }} +{{- if semverCompare ">=1.19-0" .Capabilities.KubeVersion.GitVersion -}} +apiVersion: networking.k8s.io/v1 +{{- else if semverCompare ">=1.14-0" .Capabilities.KubeVersion.GitVersion -}} +apiVersion: networking.k8s.io/v1beta1 +{{- else -}} +apiVersion: extensions/v1beta1 +{{- end }} +kind: Ingress +metadata: + name: {{ $fullName }} + labels: + {{- include "pgcat.labels" . | nindent 4 }} + {{- with .Values.ingress.annotations }} + annotations: + {{- toYaml . | nindent 4 }} + {{- end }} +spec: + {{- if and .Values.ingress.className (semverCompare ">=1.18-0" .Capabilities.KubeVersion.GitVersion) }} + ingressClassName: {{ .Values.ingress.className }} + {{- end }} + {{- if .Values.ingress.tls }} + tls: + {{- range .Values.ingress.tls }} + - hosts: + {{- range .hosts }} + - {{ . | quote }} + {{- end }} + secretName: {{ .secretName }} + {{- end }} + {{- end }} + rules: + {{- range .Values.ingress.hosts }} + - host: {{ .host | quote }} + http: + paths: + {{- range .paths }} + - path: {{ .path }} + {{- if and .pathType (semverCompare ">=1.18-0" $.Capabilities.KubeVersion.GitVersion) }} + pathType: {{ .pathType }} + {{- end }} + backend: + {{- if semverCompare ">=1.19-0" $.Capabilities.KubeVersion.GitVersion }} + service: + name: {{ $fullName }} + port: + number: {{ $svcPort }} + {{- else }} + serviceName: {{ $fullName }} + servicePort: {{ $svcPort }} + {{- end }} + {{- end }} + {{- end }} +{{- end }} diff --git a/charts/pgcat/templates/secret.yaml b/charts/pgcat/templates/secret.yaml new file mode 100644 index 00000000..05711ea9 --- /dev/null +++ b/charts/pgcat/templates/secret.yaml @@ -0,0 +1,86 @@ +apiVersion: v1 +kind: Secret +metadata: + name: {{ include "pgcat.fullname" . }} + labels: + {{- include "pgcat.labels" . | nindent 4 }} +type: Opaque +stringData: + pgcat.toml: | + [general] + host = {{ .Values.configuration.general.host | quote }} + port = {{ .Values.configuration.general.port }} + enable_prometheus_exporter = {{ .Values.configuration.general.enable_prometheus_exporter }} + prometheus_exporter_port = {{ .Values.configuration.general.prometheus_exporter_port }} + connect_timeout = {{ .Values.configuration.general.connect_timeout }} + idle_timeout = {{ .Values.configuration.general.idle_timeout | int }} + server_lifetime = {{ .Values.configuration.general.server_lifetime | int }} + idle_client_in_transaction_timeout = {{ .Values.configuration.general.idle_client_in_transaction_timeout | int }} + healthcheck_timeout = {{ .Values.configuration.general.healthcheck_timeout }} + healthcheck_delay = {{ .Values.configuration.general.healthcheck_delay }} + shutdown_timeout = {{ .Values.configuration.general.shutdown_timeout }} + ban_time = {{ .Values.configuration.general.ban_time }} + log_client_connections = {{ .Values.configuration.general.log_client_connections }} + log_client_disconnections = {{ .Values.configuration.general.log_client_disconnections }} + tcp_keepalives_idle = {{ .Values.configuration.general.tcp_keepalives_idle }} + tcp_keepalives_count = {{ .Values.configuration.general.tcp_keepalives_count }} + tcp_keepalives_interval = {{ .Values.configuration.general.tcp_keepalives_interval }} + {{- if and (ne .Values.configuration.general.tls_certificate "-") (ne .Values.configuration.general.tls_private_key "-") }} + tls_certificate = "{{ .Values.configuration.general.tls_certificate }}" + tls_private_key = "{{ .Values.configuration.general.tls_private_key }}" + {{- end }} + admin_username = {{ .Values.configuration.general.admin_username | quote }} + admin_password = {{ .Values.configuration.general.admin_password | quote }} + {{- if and .Values.configuration.general.auth_query_user .Values.configuration.general.auth_query_password .Values.configuration.general.auth_query }} + auth_query = {{ .Values.configuration.general.auth_query | quote }} + auth_query_user = {{ .Values.configuration.general.auth_query_user | quote }} + auth_query_password = {{ .Values.configuration.general.auth_query_password | quote }} + {{- end }} + + {{- range $pool := .Values.configuration.pools }} + + ## + ## pool for {{ $pool.name }} + ## + [pools.{{ $pool.name | quote }}] + pool_mode = {{ default "transaction" $pool.pool_mode | quote }} + load_balancing_mode = {{ default "random" $pool.load_balancing_mode | quote }} + default_role = {{ default "any" $pool.default_role | quote }} + prepared_statements_cache_size = {{ default 500 $pool.prepared_statements_cache_size }} + query_parser_enabled = {{ default true $pool.query_parser_enabled }} + query_parser_read_write_splitting = {{ default true $pool.query_parser_read_write_splitting }} + primary_reads_enabled = {{ default true $pool.primary_reads_enabled }} + sharding_function = {{ default "pg_bigint_hash" $pool.sharding_function | quote }} + + {{- range $index, $user := $pool.users }} + + ## pool {{ $pool.name }} user {{ $user.username | quote }} + ## + [pools.{{ $pool.name | quote }}.users.{{ $index }}] + username = {{ $user.username | quote }} + password = {{ $user.password | quote }} + pool_size = {{ $user.pool_size }} + statement_timeout = {{ $user.statement_timeout }} + min_pool_size = 3 + server_lifetime = 60000 + {{- if and $user.server_username $user.server_password }} + server_username = {{ $user.server_username | quote }} + server_password = {{ $user.server_password | quote }} + {{- end }} + {{- end }} + + {{- range $index, $shard := $pool.shards }} + + ## pool {{ $pool.name }} database {{ $shard.database }} + ## + [pools.{{ $pool.name | quote }}.shards.{{ $index }}] + {{- if gt (len $shard.servers) 0}} + servers = [ + {{- range $server := $shard.servers }} + [ {{ $server.host | quote }}, {{ $server.port }}, {{ $server.role | quote }} ], + {{- end }} + ] + {{- end }} + database = {{ $shard.database | quote }} + {{- end }} + {{- end }} diff --git a/charts/pgcat/templates/service.yaml b/charts/pgcat/templates/service.yaml new file mode 100644 index 00000000..56c4be71 --- /dev/null +++ b/charts/pgcat/templates/service.yaml @@ -0,0 +1,15 @@ +apiVersion: v1 +kind: Service +metadata: + name: {{ include "pgcat.fullname" . }} + labels: + {{- include "pgcat.labels" . | nindent 4 }} +spec: + type: {{ .Values.service.type }} + ports: + - port: {{ .Values.service.port }} + targetPort: pgcat + protocol: TCP + name: pgcat + selector: + {{- include "pgcat.selectorLabels" . | nindent 4 }} diff --git a/charts/pgcat/templates/serviceaccount.yaml b/charts/pgcat/templates/serviceaccount.yaml new file mode 100644 index 00000000..04ea6161 --- /dev/null +++ b/charts/pgcat/templates/serviceaccount.yaml @@ -0,0 +1,12 @@ +{{- if .Values.serviceAccount.create -}} +apiVersion: v1 +kind: ServiceAccount +metadata: + name: {{ include "pgcat.serviceAccountName" . }} + labels: + {{- include "pgcat.labels" . | nindent 4 }} + {{- with .Values.serviceAccount.annotations }} + annotations: + {{- toYaml . | nindent 4 }} + {{- end }} +{{- end }} diff --git a/charts/pgcat/values.yaml b/charts/pgcat/values.yaml new file mode 100644 index 00000000..86be4104 --- /dev/null +++ b/charts/pgcat/values.yaml @@ -0,0 +1,361 @@ +## String to partially override aspnet-core.fullname template (will maintain the release name) +## @param nameOverride String to partially override common.names.fullname +## +nameOverride: "" + +## String to fully override aspnet-core.fullname template +## @param fullnameOverride String to fully override common.names.fullname +## +fullnameOverride: "" + +## Number of PgCat replicas to deploy +## @param replicaCount Number of PgCat replicas to deploy +replicaCount: 1 + +## Bitnami PgCat image version +## ref: https://hub.docker.com/r/bitnami/kubewatch/tags/ +## +## @param image.registry PgCat image registry +## @param image.repository PgCat image name +## @param image.tag PgCat image tag +## @param image.pullPolicy PgCat image tag +## @param image.pullSecrets Specify docker-registry secret names as an array +image: + repository: ghcr.io/postgresml/pgcat + # Overrides the image tag whose default is the chart appVersion. + tag: "main" + ## Specify a imagePullPolicy + ## Defaults to 'Always' if image tag is 'latest', else set to 'IfNotPresent' + ## ref: http://kubernetes.io/docs/user-guide/images/#pre-pulling-images + ## + pullPolicy: IfNotPresent + ## Optionally specify an array of imagePullSecrets. + ## Secrets must be manually created in the namespace. + ## ref: https://kubernetes.io/docs/tasks/configure-pod-container/pull-image-private-registry/ + ## Example: + ## pullSecrets: + ## - myRegistryKeySecretName + ## + pullSecrets: [] + +## Specifies whether a ServiceAccount should be created +## +## @param serviceAccount.create Enable the creation of a ServiceAccount for PgCat pods +## @param serviceAccount.name Name of the created ServiceAccount +## +serviceAccount: + ## Specifies whether a service account should be created + create: true + ## Annotations to add to the service account + annotations: {} + ## The name of the service account to use. + ## If not set and create is true, a name is generated using the fullname template + name: "" + +## Annotations for server pods. +## ref: https://kubernetes.io/docs/concepts/overview/working-with-objects/annotations/ +## +## @param podAnnotations Annotations for PgCat pods +## +podAnnotations: {} + +## PgCat containers' SecurityContext +## ref: https://kubernetes.io/docs/tasks/configure-pod-container/security-context/#set-the-security-context-for-a-pod +## +## @param podSecurityContext.enabled Enabled PgCat pods' Security Context +## @param podSecurityContext.fsGroup Set PgCat pod's Security Context fsGroup +## +podSecurityContext: {} + # fsGroup: 2000 + +## PgCat pods' Security Context +## ref: https://kubernetes.io/docs/tasks/configure-pod-container/security-context/#set-the-security-context-for-a-container +## +## @param containerSecurityContext.enabled Enabled PgCat containers' Security Context +## @param containerSecurityContext.runAsUser Set PgCat container's Security Context runAsUser +## @param containerSecurityContext.runAsNonRoot Set PgCat container's Security Context runAsNonRoot +## +containerSecurityContext: {} + # capabilities: + # drop: + # - ALL + # readOnlyRootFilesystem: true + # runAsNonRoot: true + # runAsUser: 1000 + +## PgCat service +## +## @param service.type PgCat service type +## @param service.port PgCat service port +service: + type: ClusterIP + port: 6432 + +ingress: + enabled: false + className: "" + annotations: {} + # kubernetes.io/ingress.class: nginx + # kubernetes.io/tls-acme: "true" + hosts: + - host: chart-example.local + paths: + - path: / + pathType: ImplementationSpecific + tls: [] + # - secretName: chart-example-tls + # hosts: + # - chart-example.local + +## PgCat resource requests and limits +## ref: http://kubernetes.io/docs/user-guide/compute-resources/ +## +## @skip resources Optional description +## @disabled-param resources.limits The resources limits for the PgCat container +## @disabled-param resources.requests The requested resources for the PgCat container +## +resources: + # We usually recommend not to specify default resources and to leave this as a conscious + # choice for the user. This also increases chances charts run on environments with little + # resources, such as Minikube. If you do want to specify resources, uncomment the following + # lines, adjust them as necessary, and remove the curly braces after 'resources:'. + limits: {} + # cpu: 100m + # memory: 128Mi + requests: {} + # cpu: 100m + # memory: 128Mi + +## Node labels for pod assignment. Evaluated as a template. +## ref: https://kubernetes.io/docs/user-guide/node-selection/ +## +## @param nodeSelector Node labels for pod assignment +## +nodeSelector: {} + +## Tolerations for pod assignment. Evaluated as a template. +## ref: https://kubernetes.io/docs/concepts/configuration/taint-and-toleration/ +## +## @param tolerations Tolerations for pod assignment +## +tolerations: [] + +## Affinity for pod assignment. Evaluated as a template. +## ref: https://kubernetes.io/docs/concepts/configuration/assign-pod-node/#affinity-and-anti-affinity +## Note: podAffinityPreset, podAntiAffinityPreset, and nodeAffinityPreset will be ignored when it's set +## +## @param affinity Affinity for pod assignment +## +affinity: {} + +## PgCat configuration +## @param configuration [object] +configuration: + ## General pooler settings + ## @param [object] + general: + ## @param configuration.general.host What IP to run on, 0.0.0.0 means accessible from everywhere. + host: "0.0.0.0" + + ## @param configuration.general.port Port to run on, same as PgBouncer used in this example. + port: 6432 + + ## @param configuration.general.enable_prometheus_exporter Whether to enable prometheus exporter or not. + enable_prometheus_exporter: false + + ## @param configuration.general.prometheus_exporter_port Port at which prometheus exporter listens on. + prometheus_exporter_port: 9930 + + # @param configuration.general.connect_timeout How long to wait before aborting a server connection (ms). + connect_timeout: 5000 + + # How long an idle connection with a server is left open (ms). + idle_timeout: 30000 # milliseconds + + # Max connection lifetime before it's closed, even if actively used. + server_lifetime: 86400000 # 24 hours + + # How long a client is allowed to be idle while in a transaction (ms). + idle_client_in_transaction_timeout: 0 # milliseconds + + # @param configuration.general.healthcheck_timeout How much time to give `SELECT 1` health check query to return with a result (ms). + healthcheck_timeout: 1000 + + # @param configuration.general.healthcheck_delay How long to keep connection available for immediate re-use, without running a healthcheck query on it + healthcheck_delay: 30000 + + # @param configuration.general.shutdown_timeout How much time to give clients during shutdown before forcibly killing client connections (ms). + shutdown_timeout: 60000 + + # @param configuration.general.ban_time For how long to ban a server if it fails a health check (seconds). + ban_time: 60 # seconds + + # @param configuration.general.log_client_connections If we should log client connections + log_client_connections: false + + # @param configuration.general.log_client_disconnections If we should log client disconnections + log_client_disconnections: false + + # TLS + # tls_certificate: "server.cert" + # tls_private_key: "server.key" + tls_certificate: "-" + tls_private_key: "-" + + # Credentials to access the virtual administrative database (pgbouncer or pgcat) + # Connecting to that database allows running commands like `SHOW POOLS`, `SHOW DATABASES`, etc.. + admin_username: "postgres" + admin_password: "postgres" + + # Query to be sent to servers to obtain the hash used for md5 authentication. The connection will be + # established using the database configured in the pool. This parameter is inherited by every pool and + # can be redefined in pool configuration. + auth_query: null + + # User to be used for connecting to servers to obtain the hash used for md5 authentication by sending + # the query specified in auth_query_user. The connection will be established using the database configured + # in the pool. This parameter is inherited by every pool and can be redefined in pool configuration. + # + # @param configuration.general.auth_query_user + auth_query_user: null + + # Password to be used for connecting to servers to obtain the hash used for md5 authentication by sending + # the query specified in auth_query_user. The connection will be established using the database configured + # in the pool. This parameter is inherited by every pool and can be redefined in pool configuration. + # + # @param configuration.general.auth_query_password + auth_query_password: null + + # Number of seconds of connection idleness to wait before sending a keepalive packet to the server. + tcp_keepalives_idle: 5 + + # Number of unacknowledged keepalive packets allowed before giving up and closing the connection. + tcp_keepalives_count: 5 + + # Number of seconds between keepalive packets. + tcp_keepalives_interval: 5 + + ## pool + ## configs are structured as pool. + ## the pool_name is what clients use as database name when connecting + ## For the example below a client can connect using "postgres://sharding_user:sharding_user@pgcat_host:pgcat_port/sharded" + ## @param [object] + pools: [] + # - ## default values + # ## + # ## + # ## + # name: "db" + + # ## Pool mode (see PgBouncer docs for more). + # ## session: one server connection per connected client + # ## transaction: one server connection per client transaction + # ## @param configuration.poolsPostgres.pool_mode + # pool_mode: "transaction" + + # ## Load balancing mode + # ## `random` selects the server at random + # ## `loc` selects the server with the least outstanding busy connections + # ## + # ## @param configuration.poolsPostgres.load_balancing_mode + # load_balancing_mode: "random" + + # ## Prepared statements cache size. + # ## TODO: update documentation + # ## + # ## @param configuration.poolsPostgres.prepared_statements_cache_size + # prepared_statements_cache_size: 500 + + # ## If the client doesn't specify, route traffic to + # ## this role by default. + # ## + # ## any: round-robin between primary and replicas, + # ## replica: round-robin between replicas only without touching the primary, + # ## primary: all queries go to the primary unless otherwise specified. + # ## @param configuration.poolsPostgres.default_role + # default_role: "any" + + # ## Query parser. If enabled, we'll attempt to parse + # ## every incoming query to determine if it's a read or a write. + # ## If it's a read query, we'll direct it to a replica. Otherwise, if it's a write, + # ## we'll direct it to the primary. + # ## @param configuration.poolsPostgres.query_parser_enabled + # query_parser_enabled: true + + # ## If the query parser is enabled and this setting is enabled, we'll attempt to + # ## infer the role from the query itself. + # ## @param configuration.poolsPostgres.query_parser_read_write_splitting + # query_parser_read_write_splitting: true + + # ## If the query parser is enabled and this setting is enabled, the primary will be part of the pool of databases used for + # ## load balancing of read queries. Otherwise, the primary will only be used for write + # ## queries. The primary can always be explicitly selected with our custom protocol. + # ## @param configuration.poolsPostgres.primary_reads_enabled + # primary_reads_enabled: true + + # ## So what if you wanted to implement a different hashing function, + # ## or you've already built one and you want this pooler to use it? + # ## + # ## Current options: + # ## + # ## pg_bigint_hash: PARTITION BY HASH (Postgres hashing function) + # ## sha1: A hashing function based on SHA1 + # ## + # ## @param configuration.poolsPostgres.sharding_function + # sharding_function: "pg_bigint_hash" + + # ## Credentials for users that may connect to this cluster + # ## @param users [array] + # ## @param users[0].username Name of the env var (required) + # ## @param users[0].password Value for the env var (required) + # ## @param users[0].pool_size Maximum number of server connections that can be established for this user + # ## @param users[0].statement_timeout Maximum query duration. Dangerous, but protects against DBs that died in a non-obvious way. + # users: [] + # # - username: "user" + # # password: "pass" + # # + # # # The maximum number of connection from a single Pgcat process to any database in the cluster + # # # is the sum of pool_size across all users. + # # pool_size: 9 + # # + # # # Maximum query duration. Dangerous, but protects against DBs that died in a non-obvious way. + # # statement_timeout: 0 + # # + # # # PostgreSQL username used to connect to the server. + # # server_username: "postgres + # # + # # # PostgreSQL password used to connect to the server. + # # server_password: "postgres + + # ## @param shards [array] + # ## @param shards[0].server[0].host Host for this shard + # ## @param shards[0].server[0].port Port for this shard + # ## @param shards[0].server[0].role Role for this shard + # shards: [] + # # [ host, port, role ] + # # - servers: + # # - host: "postgres" + # # port: 5432 + # # role: "primary" + # # - host: "postgres" + # # port: 5432 + # # role: "replica" + # # database: "postgres" + # # # [ host, port, role ] + # # - servers: + # # - host: "postgres" + # # port: 5432 + # # role: "primary" + # # - host: "postgres" + # # port: 5432 + # # role: "replica" + # # database: "postgres" + # # # [ host, port, role ] + # # - servers: + # # - host: "postgres" + # # port: 5432 + # # role: "primary" + # # - host: "postgres" + # # port: 5432 + # # role: "replica" + # # database: "postgres" diff --git a/cr.yaml b/cr.yaml new file mode 100644 index 00000000..0e3201dd --- /dev/null +++ b/cr.yaml @@ -0,0 +1 @@ +sign: false diff --git a/ct.yaml b/ct.yaml new file mode 100644 index 00000000..fe05590a --- /dev/null +++ b/ct.yaml @@ -0,0 +1,5 @@ +remote: origin +target-branch: main +chart-dirs: + - charts +