diff --git a/kafka/.gitignore b/kafka/.gitignore new file mode 100644 index 00000000..bae75352 --- /dev/null +++ b/kafka/.gitignore @@ -0,0 +1,6 @@ + +# ./unhelm.sh output that we don't need +helm +redpanda/ystack/kustomization.yaml +redpanda/ystack/redpanda/templates/poddisruptionbudget.yaml +redpanda/ystack/redpanda/templates/tests diff --git a/kafka/redpanda.ystack.values.yaml b/kafka/redpanda.ystack.values.yaml new file mode 100644 index 00000000..dadd43d6 --- /dev/null +++ b/kafka/redpanda.ystack.values.yaml @@ -0,0 +1,50 @@ +# yaml-language-server: $schema=https://github.com/redpanda-data/helm-charts/raw/redpanda-4.0.32/charts/redpanda/values.schema.json +# unhelm-template-repo: https://charts.redpanda.com +# unhelm-namespace: kafka + +# this is an attempt to disable as much as possible from the chart, except the actual broker +statefulset: + replicas: 1 + additionalRedpandaCmdFlags: + - --overprovisioned + sideCars: + configWatcher: + enabled: false +tls: + enabled: false +config: + cluster: + auto_create_topics_enabled: false + tunable: {} + node: {} +external: + enabled: false +rbac: + enabled: false +post_install_job: + enabled: false +post_upgrade_job: + enabled: false +console: + enabled: false +logging: + logLevel: info + usageStats: + enabled: false +tuning: + tune_aio_events: false +# See forwarded ports in ../k3s/ystack.yaml +# See also https://github.com/redpanda-data/helm-charts/issues/285 +listeners: + kafka: + port: 9092 + external: + default: + advertisedPorts: + - 31712 + http: + port: 8082 + external: + default: + advertisedPorts: + - 31713 diff --git a/kafka/redpanda/ystack/redpanda/templates/configmap.yaml b/kafka/redpanda/ystack/redpanda/templates/configmap.yaml new file mode 100644 index 00000000..931cef08 --- /dev/null +++ b/kafka/redpanda/ystack/redpanda/templates/configmap.yaml @@ -0,0 +1,92 @@ +--- +# Source: redpanda/templates/configmap.yaml +apiVersion: v1 +kind: ConfigMap +metadata: + name: redpanda + namespace: "kafka" + labels: + app.kubernetes.io/component: redpanda + app.kubernetes.io/instance: redpanda + app.kubernetes.io/managed-by: Helm + app.kubernetes.io/name: redpanda + helm.sh/chart: redpanda-4.0.47 +data: + bootstrap.yaml: | + kafka_enable_authorization: false + enable_sasl: false + auto_create_topics_enabled: false + compacted_log_segment_size: 67108864 + group_topic_partitions: 16 + kafka_batch_max_bytes: 1048576 + kafka_connection_rate_limit: 1000 + log_segment_size: 134217728 + log_segment_size_max: 268435456 + log_segment_size_min: 16777216 + max_compacted_log_segment_size: 536870912 + topic_partitions_per_shard: 1000 + storage_min_free_bytes: 1073741824 + redpanda.yaml: | + config_file: /etc/redpanda/redpanda.yaml + redpanda: + empty_seed_starts_cluster: false + kafka_enable_authorization: false + enable_sasl: false + auto_create_topics_enabled: false + compacted_log_segment_size: 67108864 + group_topic_partitions: 16 + kafka_batch_max_bytes: 1048576 + kafka_connection_rate_limit: 1000 + log_segment_size: 134217728 + log_segment_size_max: 268435456 + log_segment_size_min: 16777216 + max_compacted_log_segment_size: 536870912 + topic_partitions_per_shard: 1000 + storage_min_free_bytes: 1073741824 + admin: + - name: internal + address: 0.0.0.0 + port: 9644 + - name: default + address: 0.0.0.0 + port: 9645 + admin_api_tls: + kafka_api: + - name: internal + address: 0.0.0.0 + port: 9092 + - name: default + address: 0.0.0.0 + port: 9094 + kafka_api_tls: + rpc_server: + address: 0.0.0.0 + port: 33145 + seed_servers: + - host: + address: redpanda-0.redpanda.kafka.svc.cluster.local. + port: 33145 + schema_registry: + schema_registry_api: + - name: internal + address: 0.0.0.0 + port: 8081 + - name: default + address: 0.0.0.0 + port: 8084 + schema_registry_api_tls: + pandaproxy: + pandaproxy_api: + - name: internal + address: 0.0.0.0 + port: 8082 + - name: default + address: 0.0.0.0 + port: 8083 + pandaproxy_api_tls: + + rpk: + enable_usage_stats: false + overprovisioned: false + enable_memory_locking: false + tune_aio_events: false diff --git a/kafka/redpanda/ystack/redpanda/templates/secrets.yaml b/kafka/redpanda/ystack/redpanda/templates/secrets.yaml new file mode 100644 index 00000000..8e5b28cf --- /dev/null +++ b/kafka/redpanda/ystack/redpanda/templates/secrets.yaml @@ -0,0 +1,45 @@ +--- +# Source: redpanda/templates/secrets.yaml +apiVersion: v1 +kind: Secret +metadata: + name: redpanda-sts-lifecycle + namespace: "kafka" + labels: + app.kubernetes.io/component: redpanda + app.kubernetes.io/instance: redpanda + app.kubernetes.io/managed-by: Helm + app.kubernetes.io/name: redpanda + helm.sh/chart: redpanda-4.0.47 +type: Opaque +stringData: + common.sh: |- + #!/usr/bin/env bash + + # the SERVICE_NAME comes from the metadata.name of the pod, essentially the POD_NAME + CURL_URL="http://${SERVICE_NAME}.redpanda.kafka.svc.cluster.local:9644" + + # commands used throughout + CURL_NODE_ID_CMD="curl --silent --fail ${CURL_URL}/v1/node_config" + + CURL_MAINTENANCE_DELETE_CMD_PREFIX='curl -X DELETE --silent -o /dev/null -w "%{http_code}"' + CURL_MAINTENANCE_PUT_CMD_PREFIX='curl -X PUT --silent -o /dev/null -w "%{http_code}"' + CURL_MAINTENANCE_GET_CMD="curl -X GET --silent ${CURL_URL}/v1/maintenance" + + postStart.sh: |- + #!/usr/bin/env bash + # This code should be similar if not exactly the same as that found in the panda-operator, see + # https://github.com/redpanda-data/redpanda/blob/e51d5b7f2ef76d5160ca01b8c7a8cf07593d29b6/src/go/k8s/pkg/resources/secret.go + + # path below should match the path defined on the statefulset + source /var/lifecycle/common.sh + + preStop.sh: |- + #!/usr/bin/env bash + # This code should be similar if not exactly the same as that found in the panda-operator, see + # https://github.com/redpanda-data/redpanda/blob/e51d5b7f2ef76d5160ca01b8c7a8cf07593d29b6/src/go/k8s/pkg/resources/secret.go + + # path below should match the path defined on the statefulset + source /var/lifecycle/common.sh + + set -x diff --git a/kafka/redpanda/ystack/redpanda/templates/service.internal.yaml b/kafka/redpanda/ystack/redpanda/templates/service.internal.yaml new file mode 100644 index 00000000..d32fbac2 --- /dev/null +++ b/kafka/redpanda/ystack/redpanda/templates/service.internal.yaml @@ -0,0 +1,29 @@ +--- +# Source: redpanda/templates/service.internal.yaml +# This service is only used to create the DNS enteries for each pod in +# the stateful set and allow the serviceMonitor to target the pods. +# This service should not be used by any client application +apiVersion: v1 +kind: Service +metadata: + name: redpanda + namespace: "kafka" + labels: + monitoring.redpanda.com/enabled: "false" + app.kubernetes.io/component: redpanda + app.kubernetes.io/instance: redpanda + app.kubernetes.io/managed-by: Helm + app.kubernetes.io/name: redpanda + helm.sh/chart: redpanda-4.0.47 +spec: + type: ClusterIP + publishNotReadyAddresses: true + clusterIP: None + selector: + app.kubernetes.io/name: redpanda + app.kubernetes.io/instance: "redpanda" + ports: + - name: admin + protocol: TCP + targetPort: 9644 + port: 9644 diff --git a/kafka/redpanda/ystack/redpanda/templates/statefulset.yaml b/kafka/redpanda/ystack/redpanda/templates/statefulset.yaml new file mode 100644 index 00000000..7aef1250 --- /dev/null +++ b/kafka/redpanda/ystack/redpanda/templates/statefulset.yaml @@ -0,0 +1,250 @@ +--- +# Source: redpanda/templates/statefulset.yaml +apiVersion: apps/v1 +kind: StatefulSet +metadata: + name: redpanda + labels: + app.kubernetes.io/component: redpanda + app.kubernetes.io/instance: redpanda + app.kubernetes.io/managed-by: Helm + app.kubernetes.io/name: redpanda + helm.sh/chart: redpanda-4.0.47 +spec: + selector: + matchLabels: + app.kubernetes.io/name: redpanda + app.kubernetes.io/instance: "redpanda" + app.kubernetes.io/component: redpanda-statefulset + serviceName: redpanda + replicas: 1 + updateStrategy: + type: RollingUpdate + podManagementPolicy: "Parallel" + template: + metadata: + labels: + app.kubernetes.io/name: redpanda + app.kubernetes.io/instance: "redpanda" + app.kubernetes.io/component: redpanda-statefulset + redpanda.com/poddisruptionbudget: redpanda + annotations: + checksum/config: d03b9a360350a848b9cfeac23a8c7514fd02b280efe0ec9c1f4682202ccf62f9 + spec: + terminationGracePeriodSeconds: 90 + securityContext: + fsGroup: 101 + fsGroupChangePolicy: OnRootMismatch + serviceAccountName: default + initContainers: + - name: redpanda-configurator + image: docker.redpanda.com/redpandadata/redpanda:v23.1.12 + command: ["/bin/bash", "-c"] + env: + - name: SERVICE_NAME + valueFrom: + fieldRef: + fieldPath: metadata.name + - name: ADVERTISED_KAFKA_ADDRESSES + value: '{"address":"$(SERVICE_NAME).redpanda.kafka.svc.cluster.local.","name":"internal","port":9092};{"address":"$(SERVICE_NAME)","name":"default","port":31712}' + - name: ADVERTISED_HTTP_ADDRESSES + value: '{"address":"$(SERVICE_NAME).redpanda.kafka.svc.cluster.local.","name":"internal","port":8082};{"address":"$(SERVICE_NAME)","name":"default","port":31713}' + - name: KUBERNETES_NODE_NAME + valueFrom: + fieldRef: + fieldPath: spec.nodeName + args: + - | + set -xe + CONFIG=/etc/redpanda/redpanda.yaml + POD_ORDINAL=${SERVICE_NAME##*-} + + # Setup config files + cp /tmp/base-config/redpanda.yaml "${CONFIG}" + cp /tmp/base-config/bootstrap.yaml /etc/redpanda/.bootstrap.yaml + + NODE_INDEX=`expr $POD_ORDINAL + 1` + + LISTENER_INDEX=1 + LISTENER=`echo $ADVERTISED_KAFKA_ADDRESSES | cut -d ' ' -f $NODE_INDEX | cut -d ';' -f $LISTENER_INDEX` + until [ "$LISTENER" == "" ]; do + rpk redpanda config --config "$CONFIG" set redpanda.advertised_kafka_api[$(($LISTENER_INDEX-1))] "$LISTENER" + let "LISTENER_INDEX+=1" + LISTENER=`echo $ADVERTISED_KAFKA_ADDRESSES | cut -d ' ' -f $NODE_INDEX | cut -d ';' -f $LISTENER_INDEX` + done + + LISTENER_INDEX=1 + LISTENER=`echo $ADVERTISED_HTTP_ADDRESSES | cut -d ' ' -f $NODE_INDEX | cut -d ';' -f $LISTENER_INDEX` + until [ "$LISTENER" == "" ]; do + rpk redpanda config --config "$CONFIG" set pandaproxy.advertised_pandaproxy_api[$(($LISTENER_INDEX-1))] "$LISTENER" + let "LISTENER_INDEX+=1" + LISTENER=`echo $ADVERTISED_HTTP_ADDRESSES | cut -d ' ' -f $NODE_INDEX | cut -d ';' -f $LISTENER_INDEX` + done + securityContext: + runAsUser: 101 + runAsGroup: 101 + volumeMounts: + - name: redpanda + mountPath: /tmp/base-config + - name: config + mountPath: /etc/redpanda + containers: + - name: redpanda + image: docker.redpanda.com/redpandadata/redpanda:v23.1.12 + env: + - name: SERVICE_NAME + valueFrom: + fieldRef: + fieldPath: metadata.name + - name: POD_IP + valueFrom: + fieldRef: + fieldPath: status.podIP + - name: HOST_IP + valueFrom: + fieldRef: + fieldPath: status.hostIP + lifecycle: + postStart: + exec: + command: ["/bin/bash", "-c", "./var/lifecycle/postStart.sh"] + preStop: + exec: + command: ["/bin/bash", "-c", "./var/lifecycle/preStop.sh"] + # the startupProbe checks to see that the admin api is listening and that the broker has a node_id assigned. This + # check is only used to delay the start of the liveness and readiness probes until it passes. + startupProbe: + exec: + command: + - /bin/sh + - -c + - | + set -e + RESULT=$(curl --silent --fail -k "http://${SERVICE_NAME}.redpanda.kafka.svc.cluster.local.:9644/v1/status/ready") + echo $RESULT + echo $RESULT | grep ready + initialDelaySeconds: 1 + failureThreshold: 120 + periodSeconds: 10 + # the livenessProbe just checks to see that the admin api is listening and returning 200s. + livenessProbe: + exec: + command: + - /bin/sh + - -c + - curl --silent --fail -k "http://${SERVICE_NAME}.redpanda.kafka.svc.cluster.local.:9644/v1/status/ready" + initialDelaySeconds: 10 + failureThreshold: 3 + periodSeconds: 10 + # the readiness probe just checks that the cluster is healthy according to rpk cluster health. + # It's ok that this cluster-wide check affects all the pods as it's only used for the + # PodDisruptionBudget and we don't want to roll any pods if the Redpanda cluster isn't healthy. + # https://kubernetes.io/docs/concepts/workloads/pods/disruptions/#pod-disruption-budgets + readinessProbe: + exec: + command: + - /bin/sh + - -c + - | + set -x + rpk cluster health --api-urls ${SERVICE_NAME}.redpanda.kafka.svc.cluster.local.:9644 + rpk cluster health --api-urls ${SERVICE_NAME}.redpanda.kafka.svc.cluster.local.:9644 | grep 'Healthy:.*true' + initialDelaySeconds: 1 + failureThreshold: 3 + periodSeconds: 10 + successThreshold: 1 + command: + - rpk + - redpanda + - start + - --smp=1 + - --memory=2048M + - --reserve-memory=205M + - --default-log-level=info + - --advertise-rpc-addr=$(SERVICE_NAME).redpanda.kafka.svc.cluster.local.:33145 + - --overprovisioned + ports: + - name: admin + containerPort: 9644 + - name: admin-default + containerPort: 9645 + - name: http + containerPort: 8082 + - name: http-default + containerPort: 8083 + - name: kafka + containerPort: 9092 + - name: kafka-default + containerPort: 9094 + - name: rpc + containerPort: 33145 + - name: schemaregistry + containerPort: 8081 + - name: schema-default + containerPort: 8084 + securityContext: + runAsUser: 101 + runAsGroup: 101 + volumeMounts: + - name: lifecycle-scripts + mountPath: /var/lifecycle + - name: datadir + mountPath: /var/lib/redpanda/data + - name: config + mountPath: /etc/redpanda + resources: + limits: + cpu: 1 + memory: 2.5Gi + volumes: + - name: lifecycle-scripts + secret: + secretName: redpanda-sts-lifecycle + defaultMode: 0774 + - name: datadir + persistentVolumeClaim: + claimName: datadir + - name: redpanda + configMap: + name: redpanda + - name: config + emptyDir: {} + - name: redpanda-config-watcher + secret: + secretName: redpanda-config-watcher + optional: false + defaultMode: 0774 + affinity: + podAntiAffinity: + requiredDuringSchedulingIgnoredDuringExecution: + - topologyKey: kubernetes.io/hostname + labelSelector: + matchLabels: + app.kubernetes.io/name: redpanda + app.kubernetes.io/instance: "redpanda" + app.kubernetes.io/component: redpanda-statefulset + topologySpreadConstraints: + - maxSkew: 1 + topologyKey: topology.kubernetes.io/zone + whenUnsatisfiable: ScheduleAnyway + labelSelector: + matchLabels: + app.kubernetes.io/name: redpanda + app.kubernetes.io/instance: "redpanda" + app.kubernetes.io/component: redpanda-statefulset + nodeSelector: + {} + tolerations: + [] + volumeClaimTemplates: + - metadata: + name: datadir + labels: + app.kubernetes.io/name: redpanda + app.kubernetes.io/instance: "redpanda" + app.kubernetes.io/component: redpanda + spec: + accessModes: ["ReadWriteOnce"] + resources: + requests: + storage: "20Gi" diff --git a/kafka/unhelm.sh b/kafka/unhelm.sh new file mode 100755 index 00000000..3a6e67bb --- /dev/null +++ b/kafka/unhelm.sh @@ -0,0 +1,7 @@ +#!/usr/bin/env bash +[ -z "$DEBUG" ] || set -x +set -eo pipefail + +UNHELM_REF=a3addefaa4a1213342b7d499e7b801ecf23189d2 + +curl -sLS "https://raw.githubusercontent.com/Yolean/unhelm/$UNHELM_REF/unhelm.sh" | bash -s -- $@