Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions Chart.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -2,5 +2,5 @@ apiVersion: v2
name: pgdog-control
description: PgDog Control
type: application
version: 0.2.18
appVersion: "84c7c56a"
version: 0.3.0
appVersion: "f477677f"
275 changes: 155 additions & 120 deletions README.md

Large diffs are not rendered by default.

29 changes: 29 additions & 0 deletions templates/_helpers.tpl
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,35 @@ the same cluster don't collide.
{{- printf "%s-redis" .Release.Name | trunc 63 | trimSuffix "-" }}
{{- end }}

{{/* Stable DNS service and token Secret for the Raft members. */}}
{{- define "pgdog-control.raft.fullname" -}}
{{- printf "%s-raft" .Release.Name | trunc 63 | trimSuffix "-" -}}
{{- end }}

{{/*
Reuse the installed token on upgrades. Cache a newly generated token in the
render context so the Secret, ConfigMap, and pod checksum all agree.
*/}}
{{- define "pgdog-control.raft.token" -}}
{{- if .Values.raft.token -}}
{{- if not (regexMatch "^[!-~]+$" .Values.raft.token) -}}
{{- fail "raft.token must contain only non-whitespace printable ASCII characters" -}}
{{- end -}}
{{- .Values.raft.token -}}
{{- else -}}
{{- if not (hasKey .Values.raft "_generatedToken") -}}
{{- $existing := lookup "v1" "Secret" .Release.Namespace (include "pgdog-control.raft.fullname" .) | default dict -}}
{{- $data := $existing.data | default dict -}}
{{- $token := index $data "token" | default "" | b64dec -}}
{{- if not $token -}}
{{- $token = randAlphaNum 64 -}}
{{- end -}}
{{- $_ := set .Values.raft "_generatedToken" $token -}}
{{- end -}}
{{- .Values.raft._generatedToken -}}
{{- end -}}
{{- end }}

{{/*
Redis URL used by the control plane. redis.url is the public chart setting;
control.config.redis.url remains supported for backwards compatibility.
Expand Down
29 changes: 12 additions & 17 deletions templates/configmap.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -112,23 +112,18 @@ data:
{{- end }}
{{- end }}

{{- with $config.leader }}

[leader]
{{- if hasKey . "enabled" }}
enabled = {{ .enabled }}
{{- end }}
{{- with .lease_name }}
lease_name = {{ . | quote }}
{{- end }}
{{- with .lease_duration_secs }}
lease_duration_secs = {{ . }}
{{- end }}
{{- with .renew_interval_secs }}
renew_interval_secs = {{ . }}
{{- end }}
{{- with .release_timeout_secs }}
release_timeout_secs = {{ . }}
{{- if .Values.raft.enabled }}

[raft]
token = {{ include "pgdog-control.raft.token" . | quote }}
storage_path = {{ printf "%s/raft.redb" (trimSuffix "/" .Values.raft.persistence.mountPath) | quote }}
cluster_name = {{ .Values.raft.cluster_name | default .Release.Name | quote }}
sequence_cache_size = {{ .Values.raft.sequence_cache_size }}
{{- range $id := until 3 }}

[[raft.members]]
id = {{ $id }}
address = {{ printf "http://%s-%d.%s.%s.svc:%v" (include "pgdog-control.control.fullname" $) $id (include "pgdog-control.raft.fullname" $) $.Release.Namespace $.Values.control.port | quote }}
{{- end }}
{{- end }}

Expand Down
57 changes: 47 additions & 10 deletions templates/deployment.yaml
Original file line number Diff line number Diff line change
@@ -1,31 +1,47 @@
apiVersion: apps/v1
kind: Deployment
kind: {{ ternary "StatefulSet" "Deployment" .Values.raft.enabled }}
metadata:
name: {{ include "pgdog-control.control.fullname" . }}
labels:
{{- include "pgdog-control.labels" . | nindent 4 }}
spec:
replicas: {{ .Values.control.replicas | default 1 }}
replicas: {{ ternary 3 (int (.Values.control.replicas | default 1)) .Values.raft.enabled }}
{{- if .Values.raft.enabled }}
serviceName: {{ include "pgdog-control.raft.fullname" . }}
# Start all members without waiting for an initial quorum to become ready.
podManagementPolicy: Parallel
updateStrategy:
type: RollingUpdate
volumeClaimTemplates:
- metadata:
name: raft
spec:
accessModes: ["ReadWriteOnce"]
{{- if eq .Values.raft.persistence.storageClass "-" }}
storageClassName: ""
{{- else if .Values.raft.persistence.storageClass }}
storageClassName: {{ .Values.raft.persistence.storageClass | quote }}
{{- end }}
resources:
requests:
storage: {{ .Values.raft.persistence.size | quote }}
{{- end }}
selector:
matchLabels:
{{- include "pgdog-control.selectorLabels" . | nindent 6 }}
# Readiness is leader-aware so only the elected control pod receives
# Service traffic. New pods normally start as followers, so they do not
# become Ready while the old leader still holds the Lease. Allowing the
# whole old ReplicaSet to be unavailable lets Kubernetes terminate the
# old leader, release the Lease, and promote a new-version pod instead
# of waiting forever for a follower to become Ready.
{{- if not .Values.raft.enabled }}
strategy:
type: RollingUpdate
rollingUpdate:
maxSurge: 0
maxUnavailable: 100%
{{- end }}
template:
metadata:
annotations:
meta.helm.sh/release-name: {{ .Release.Name | quote }}
meta.helm.sh/release-namespace: {{ .Release.Namespace | quote }}
# Roll the deployment when any rendered config / secret content
# Roll the workload when any rendered config / secret content
# changes. Each annotation hashes the *template output*, not
# values directly, so transformations applied inside the
# template (defaults, lookups, randAlphaNum on first install)
Expand All @@ -46,7 +62,17 @@ spec:
labels:
{{- include "pgdog-control.selectorLabels" . | nindent 8 }}
spec:
{{- if gt (int (.Values.control.replicas | default 1)) 1 }}
{{- if .Values.raft.enabled }}
affinity:
podAntiAffinity:
preferredDuringSchedulingIgnoredDuringExecution:
- weight: 100
podAffinityTerm:
topologyKey: kubernetes.io/hostname
labelSelector:
matchLabels:
{{- include "pgdog-control.selectorLabels" . | nindent 18 }}
{{- else if gt (int (.Values.control.replicas | default 1)) 1 }}
topologySpreadConstraints:
- maxSkew: 1
topologyKey: kubernetes.io/hostname
Expand Down Expand Up @@ -88,6 +114,13 @@ spec:
env:
- name: CONTROL_CONFIG
value: /etc/pgdog-control/control.toml
{{- if .Values.raft.enabled }}
# control2 extracts the StatefulSet ordinal from the pod name.
- name: RAFT_NODE_ID
valueFrom:
fieldRef:
fieldPath: metadata.name
{{- end }}
- name: HOME
value: /var/lib/pgdog-control
- name: XDG_CACHE_HOME
Expand Down Expand Up @@ -168,6 +201,10 @@ spec:
readOnly: true
- name: runtime
mountPath: /var/lib/pgdog-control
{{- if .Values.raft.enabled }}
- name: raft
mountPath: {{ .Values.raft.persistence.mountPath | quote }}
{{- end }}
- name: tmp
mountPath: /tmp
ports:
Expand Down
18 changes: 18 additions & 0 deletions templates/networkpolicy.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,15 @@ spec:
- Ingress
- Egress
ingress:
{{- if .Values.raft.enabled }}
- from:
- podSelector:
matchLabels:
{{- include "pgdog-control.selectorLabels" . | nindent 10 }}
ports:
- protocol: TCP
port: {{ .Values.control.port }}
{{- end }}
- from:
- namespaceSelector:
matchLabels:
Expand All @@ -24,6 +33,15 @@ spec:
{{- toYaml . | nindent 2 }}
{{- end }}
egress:
{{- if .Values.raft.enabled }}
- to:
- podSelector:
matchLabels:
{{- include "pgdog-control.selectorLabels" . | nindent 10 }}
ports:
- protocol: TCP
port: {{ .Values.control.port }}
{{- end }}
{{- if .Values.redis.enabled }}
- to:
- podSelector:
Expand Down
11 changes: 11 additions & 0 deletions templates/raft-secret.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
{{- if .Values.raft.enabled }}
apiVersion: v1
kind: Secret
metadata:
name: {{ include "pgdog-control.raft.fullname" . }}
labels:
{{- include "pgdog-control.labels" . | nindent 4 }}
type: Opaque
data:
token: {{ include "pgdog-control.raft.token" . | b64enc | quote }}
{{- end }}
19 changes: 19 additions & 0 deletions templates/raft-service.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
{{- if .Values.raft.enabled }}
apiVersion: v1
kind: Service
metadata:
name: {{ include "pgdog-control.raft.fullname" . }}
labels:
{{- include "pgdog-control.labels" . | nindent 4 }}
spec:
clusterIP: None
# Peers must be discoverable while the cluster is starting or recovering.
publishNotReadyAddresses: true
ports:
- port: {{ .Values.control.port }}
targetPort: http
protocol: TCP
name: http
selector:
{{- include "pgdog-control.selectorLabels" . | nindent 4 }}
{{- end }}
29 changes: 0 additions & 29 deletions templates/rbac.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -54,35 +54,6 @@ subjects:
- kind: ServiceAccount
name: {{ include "pgdog-control.control.serviceAccountName" . }}
namespace: {{ .Release.Namespace }}
---
# Namespace-scoped access for control-plane leader election.
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
name: {{ include "pgdog-control.control.clusterFullname" . }}-leader
namespace: {{ .Release.Namespace }}
labels:
{{- include "pgdog-control.labels" . | nindent 4 }}
rules:
- apiGroups: ["coordination.k8s.io"]
resources: ["leases"]
verbs: ["get", "list", "watch", "create", "update", "patch", "delete"]
---
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
name: {{ include "pgdog-control.control.clusterFullname" . }}-leader
namespace: {{ .Release.Namespace }}
labels:
{{- include "pgdog-control.labels" . | nindent 4 }}
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: Role
name: {{ include "pgdog-control.control.clusterFullname" . }}-leader
subjects:
- kind: ServiceAccount
name: {{ include "pgdog-control.control.serviceAccountName" . }}
namespace: {{ .Release.Namespace }}
{{- range $ns := .Values.control.rbac.writeNamespaces }}
---
# Namespace-scoped write access for workloads the control plane manages.
Expand Down
6 changes: 0 additions & 6 deletions test/values-full.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -37,12 +37,6 @@ control:
autoreload: "immediately"
autoscaling:
pool_size: true
leader:
enabled: true
lease_name: pgdog-control-leader
lease_duration_secs: 20
renew_interval_secs: 7
release_timeout_secs: 4
helm:
chart: pgdog
repo: pgdogdev
Expand Down
2 changes: 2 additions & 0 deletions test/values-raft.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
raft:
enabled: true
21 changes: 15 additions & 6 deletions values.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,21 @@ nodeSelector: {}
# tolerations allows pods to be scheduled on nodes with matching taints
tolerations: []

raft:
# Run three control pods with stable identities and durable Raft storage.
# Prefer separate machines, but allow pods to share a node when needed.
enabled: false
# Shared peer token. Empty generates a token retained in a Kubernetes Secret.
token: ""
# Empty defaults to the Helm release name.
cluster_name: ""
sequence_cache_size: 1000
persistence:
size: 1Gi
# Empty uses the cluster's default StorageClass; "-" disables dynamic provisioning.
storageClass: ""
mountPath: /var/lib/pgdog-control/raft

control:
port: 8080
aws:
Expand Down Expand Up @@ -115,12 +130,6 @@ control:
# autoreload: off
autoscaling: {}
# pool_size: false
leader: {}
# enabled: true
# lease_name: "" # Empty means derive from Helm release.
# lease_duration_secs: 15
# renew_interval_secs: 5
# release_timeout_secs: 3
helm: {}
# chart: pgdog
# repo: pgdogdev
Expand Down
Loading