--- apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: name: keydbs.codemowers.io spec: group: codemowers.io names: plural: keydbs singular: keydb kind: KeyDBCluster shortNames: - keydb scope: Namespaced versions: - name: v1alpha1 served: true storage: true schema: openAPIV3Schema: type: object properties: spec: type: object properties: replicas: type: integer description: Replica count required: ["spec"] --- apiVersion: codemowers.io/v1alpha1 kind: ClusterOperator metadata: name: keydb spec: resource: group: codemowers.io version: v1alpha1 plural: keydbs secret: enabled: true name: foobar-secrets structure: - key: REDIS_PASSWORD value: "%s" - key: REDIS_URI value: "redis://:%s@foobar" configmaps: - apiVersion: v1 kind: ConfigMap metadata: name: foobar-scripts labels: app.kubernetes.io/name: foobar data: entrypoint.sh: | #!/bin/bash set -euxo pipefail host="$(hostname)" port="6379" replicas=() for node in {0..2}; do if [ "${host}" != "redis-${node}" ]; then replicas+=("--replicaof redis-${node}.redis-headless ${port}") fi done exec keydb-server /etc/keydb/redis.conf \ --active-replica "yes" \ --multi-master "yes" \ --appendonly "no" \ --bind "0.0.0.0" \ --port "${port}" \ --protected-mode "no" \ --server-threads "2" \ --masterauth "${REDIS_PASSWORD}" \ --requirepass "${REDIS_PASSWORD}" \ "${replicas[@]}" ping_readiness_local.sh: |- #!/bin/bash set -e [[ -n "${REDIS_PASSWORD}" ]] && export REDISCLI_AUTH="${REDIS_PASSWORD}" response="$( timeout -s 3 "${1}" \ keydb-cli \ -h localhost \ -p 6379 \ ping )" if [ "${response}" != "PONG" ]; then echo "${response}" exit 1 fi ping_liveness_local.sh: |- #!/bin/bash set -e [[ -n "${REDIS_PASSWORD}" ]] && export REDISCLI_AUTH="${REDIS_PASSWORD}" response="$( timeout -s 3 "${1}" \ keydb-cli \ -h localhost \ -p 6379 \ ping )" if [ "${response}" != "PONG" ] && [[ ! "${response}" =~ ^.*LOADING.*$ ]]; then echo "${response}" exit 1 fi cleanup_tempfiles.sh: |- #!/bin/bash set -e find /data/ -type f \( -name "temp-*.aof" -o -name "temp-*.rdb" \) -mmin +60 -delete services: - apiVersion: v1 kind: Service metadata: name: foobar-headless labels: app.kubernetes.io/name: foobar spec: type: ClusterIP clusterIP: None ports: - name: redis port: 6379 protocol: TCP targetPort: redis selector: app.kubernetes.io/name: foobar - apiVersion: v1 kind: Service metadata: name: foobar labels: app.kubernetes.io/name: foobar annotations: {} spec: type: ClusterIP ports: - name: redis port: 6379 protocol: TCP targetPort: redis - name: exporter port: 9121 protocol: TCP targetPort: exporter selector: app.kubernetes.io/name: foobar sessionAffinity: ClientIP statefulsets: - apiVersion: apps/v1 kind: StatefulSet metadata: name: foobar labels: app.kubernetes.io/name: foobar spec: replicas: 3 serviceName: foobar-headless selector: matchLabels: app.kubernetes.io/name: foobar template: metadata: labels: app.kubernetes.io/name: foobar spec: affinity: podAntiAffinity: preferredDuringSchedulingIgnoredDuringExecution: - podAffinityTerm: labelSelector: matchExpressions: - key: app.kubernetes.io/name operator: In values: - 'foobar' topologyKey: kubernetes.io/hostname weight: 100 containers: - name: redis image: eqalpha/keydb:x86_64_v6.3.1 imagePullPolicy: Always command: - /scripts/entrypoint.sh ports: - name: redis containerPort: 6379 protocol: TCP livenessProbe: initialDelaySeconds: 20 periodSeconds: 5 # One second longer than command timeout should prevent generation of zombie processes. timeoutSeconds: 6 successThreshold: 1 failureThreshold: 5 exec: command: - sh - -c - /scripts/ping_liveness_local.sh 5 readinessProbe: initialDelaySeconds: 20 periodSeconds: 5 # One second longer than command timeout should prevent generation of zombie processes. timeoutSeconds: 2 successThreshold: 1 failureThreshold: 5 exec: command: - sh - -c - /scripts/ping_readiness_local.sh 1 startupProbe: periodSeconds: 5 # One second longer than command timeout should prevent generation of zombie processes. timeoutSeconds: 2 failureThreshold: 24 exec: command: - sh - -c - /scripts/ping_readiness_local.sh 1 resources: {} securityContext: {} volumeMounts: - name: foobar-scripts mountPath: /scripts - name: foobar-data mountPath: /data envFrom: - secretRef: name: foobar-secrets - name: exporter image: quay.io/oliver006/redis_exporter ports: - name: exporter containerPort: 9121 envFrom: - secretRef: name: foobar-secrets securityContext: {} volumes: - name: foobar-scripts configMap: name: foobar-scripts defaultMode: 0755 - name: foobar-data emptyDir: {}