From 7b0d3f61681a26495cdacebdfcfe4337ef8cbdd0 Mon Sep 17 00:00:00 2001 From: chandra sekahr Date: Sat, 20 Jun 2026 22:08:14 +0530 Subject: [PATCH 1/6] docs: add proposal for drunix deployment support --- docs/proposals/drunix-deployment-support.md | 100 ++++++++++++++++++++ 1 file changed, 100 insertions(+) create mode 100644 docs/proposals/drunix-deployment-support.md diff --git a/docs/proposals/drunix-deployment-support.md b/docs/proposals/drunix-deployment-support.md new file mode 100644 index 0000000..1da7d82 --- /dev/null +++ b/docs/proposals/drunix-deployment-support.md @@ -0,0 +1,100 @@ +# Proposal: Drunix Deployment Support in Falcon + +## Background + +Falcon currently provides deployment automation and lifecycle management for Hyperledger Fabric based blockchain networks. + +Drunix introduces a new blockchain architecture with components such as Validation Service, Committer Service, Endorser Service and supporting infrastructure components. Existing Falcon deployment capabilities are focused on traditional Hyperledger Fabric topology and do not support deployment of Drunix networks. + +## Objective + +Enable Falcon to deploy and manage Drunix blockchain networks using Kubernetes and Helm based deployment automation. + +## Problem Statement + +Currently there is no standardized deployment mechanism within Falcon for Drunix components. + +Users intending to deploy Drunix networks must manually create Kubernetes manifests and deployment configurations, leading to: + +* Increased deployment effort +* Configuration inconsistencies +* Longer onboarding time +* Higher operational complexity + +## Proposed Solution + +Extend Falcon deployment capabilities to support Drunix network deployment. + +The implementation will introduce Helm charts and deployment automation for Drunix components. + +Initial scope includes: + +* Validation Service deployment +* Endorser Service deployment +* Committer Service deployment +* Gateway deployment +* Configuration management +* Secrets management +* Service discovery +* Health monitoring configuration + +## Deployment Architecture + +Falcon will manage deployment of Drunix components through Helm charts. + +Deployment artifacts: + +* Helm Charts +* values.yaml configuration +* Kubernetes Deployments +* StatefulSets (if required) +* Services +* ConfigMaps +* Secrets +* PVC definitions + +## Deliverables + +Phase 1 + +* Base Helm chart structure +* Validation Service deployment +* Endorser deployment +* Committer deployment + +Phase 2 + +* Gateway deployment +* Configuration automation +* Resource management + +Phase 3 + +* Production hardening +* Upgrade strategy +* Documentation + +## Benefits + +* Standardized Drunix deployment +* Faster environment provisioning +* Reusable deployment templates +* Improved operational consistency +* Easier onboarding for institutions adopting Drunix + +## Risks + +* Drunix architecture may evolve during development +* Additional deployment dependencies may be identified during implementation + +## Testing Plan + +* Local validation using Kind cluster +* Multi-node Kubernetes deployment testing +* Component health verification +* Upgrade testing +* Rollback testing + +## Approval Requested + +Approval is requested to proceed with design and implementation of Drunix deployment support within Falcon. From 0d3ce63cba95abbc313c5ddb4ccf990a1630a88a Mon Sep 17 00:00:00 2001 From: chandra sekahr Date: Sat, 20 Jun 2026 23:24:46 +0530 Subject: [PATCH 2/6] docs: Updated proposal as per addtiaonal requiremnt --- docs/proposals/drunix-deployment-support.md | 104 +++++++++++++++----- 1 file changed, 81 insertions(+), 23 deletions(-) diff --git a/docs/proposals/drunix-deployment-support.md b/docs/proposals/drunix-deployment-support.md index 1da7d82..1805bf1 100644 --- a/docs/proposals/drunix-deployment-support.md +++ b/docs/proposals/drunix-deployment-support.md @@ -2,13 +2,13 @@ ## Background -Falcon currently provides deployment automation and lifecycle management for Hyperledger Fabric based blockchain networks. +Falcon currently provides deployment automation and lifecycle management for Hyperledger Fabric (HLF) based blockchain networks. -Drunix introduces a new blockchain architecture with components such as Validation Service, Committer Service, Endorser Service and supporting infrastructure components. Existing Falcon deployment capabilities are focused on traditional Hyperledger Fabric topology and do not support deployment of Drunix networks. +Drunix introduces an enhanced blockchain architecture with components such as Validation Service, Committer Service, Endorser Service and supporting infrastructure components including YugabyteDB. Existing Falcon deployment capabilities are focused on traditional Hyperledger Fabric topology and do not currently support deployment and lifecycle management of Drunix based networks. ## Objective -Enable Falcon to deploy and manage Drunix blockchain networks using Kubernetes and Helm based deployment automation. +Extend Falcon to support deployment and lifecycle management of Drunix networks while maintaining full compatibility with existing Hyperledger Fabric deployments. ## Problem Statement @@ -20,12 +20,25 @@ Users intending to deploy Drunix networks must manually create Kubernetes manife * Configuration inconsistencies * Longer onboarding time * Higher operational complexity +* Lack of standardized upgrade and deployment workflows + +Additionally, there is currently no mechanism to onboard Drunix components into an existing HLF-based network through Falcon. + +## Design Principles + +The proposed implementation will follow the following principles: + +* Reuse existing Falcon deployment charts and templates wherever possible. +* Extend deployment capabilities through configurable values and conditional templates instead of duplicating charts. +* Maintain backward compatibility with all existing HLF deployment workflows. +* Support both standalone Drunix deployments and hybrid HLF-Drunix deployments. +* Ensure deployment dependencies are provisioned as part of the automation workflow. ## Proposed Solution Extend Falcon deployment capabilities to support Drunix network deployment. -The implementation will introduce Helm charts and deployment automation for Drunix components. +The implementation will introduce deployment automation for Drunix components by leveraging and extending existing Falcon Helm charts. Initial scope includes: @@ -37,64 +50,109 @@ Initial scope includes: * Secrets management * Service discovery * Health monitoring configuration +* YugabyteDB deployment and configuration +* Version compatibility management + +## Supported Deployment Scenarios + +### Scenario 1: Existing HLF Deployment + +Current Falcon deployment workflow remains unchanged. + +### Scenario 2: New Drunix Deployment + +Falcon provisions all required Drunix components and supporting infrastructure. + +### Scenario 3: Hybrid Deployment + +Falcon enables onboarding of Drunix peers and services into an existing HLF based network while maintaining interoperability and operational consistency. ## Deployment Architecture -Falcon will manage deployment of Drunix components through Helm charts. +Falcon will manage deployment of Drunix components through reusable Helm charts and deployment templates. -Deployment artifacts: +Deployment artifacts include: -* Helm Charts -* values.yaml configuration +* Reusable Helm Charts +* values.yaml driven configurations * Kubernetes Deployments -* StatefulSets (if required) +* StatefulSets (where required) * Services * ConfigMaps * Secrets * PVC definitions +* YugabyteDB deployment components + +The implementation will maximize reuse of existing Falcon deployment assets and introduce Drunix specific behavior through configuration driven extensions. ## Deliverables -Phase 1 +### Phase 1 -* Base Helm chart structure +* Architecture assessment +* Reusable chart identification +* Base deployment framework * Validation Service deployment * Endorser deployment * Committer deployment -Phase 2 +### Phase 2 * Gateway deployment +* Hybrid HLF-Drunix deployment support * Configuration automation * Resource management -Phase 3 +### Phase 3 -* Production hardening -* Upgrade strategy +* YugabyteDB integration and deployment automation +* Version compatibility validation +* Upgrade strategy implementation * Documentation +### Phase 4 + +* Production hardening +* End-to-end deployment validation +* Upgrade and rollback validation + +## Version Compatibility + +As part of the implementation, existing component versions will be reviewed and upgraded where necessary to ensure compatibility between: + +* Falcon +* Hyperledger Fabric +* Drunix components +* YugabyteDB +* Helm chart dependencies + ## Benefits -* Standardized Drunix deployment -* Faster environment provisioning -* Reusable deployment templates -* Improved operational consistency -* Easier onboarding for institutions adopting Drunix +* Standardized Drunix deployment workflow +* Reuse of existing Falcon deployment capabilities +* Support for both HLF and Drunix ecosystems +* Hybrid deployment support +* Reduced operational effort +* Consistent deployment and upgrade process +* Faster onboarding for organizations adopting Drunix ## Risks -* Drunix architecture may evolve during development -* Additional deployment dependencies may be identified during implementation +* Drunix architecture may evolve during implementation. +* Additional deployment dependencies may be identified during development. +* Hybrid deployment scenarios may introduce integration complexities. ## Testing Plan * Local validation using Kind cluster * Multi-node Kubernetes deployment testing +* HLF deployment regression testing +* Drunix deployment validation +* Hybrid deployment validation * Component health verification * Upgrade testing * Rollback testing ## Approval Requested -Approval is requested to proceed with design and implementation of Drunix deployment support within Falcon. +Approval is requested to proceed with design and implementation of Drunix deployment support within Falcon, including support for standalone Drunix deployments, hybrid HLF-Drunix deployments, deployment dependency automation and version compatibility enhancements. From 196c6a8571c3453ff41553d98257a5ed06b9208a Mon Sep 17 00:00:00 2001 From: bandigesaikiran Date: Sun, 21 Jun 2026 12:46:42 +0530 Subject: [PATCH 3/6] feat: add Yugabyte deployment support --- examples/yugabyte/values.yaml | 974 +++++++++++++++++ helm-charts/yugabyte/.helmignore | 1 + helm-charts/yugabyte/Chart.yaml | 17 + helm-charts/yugabyte/README.md | 1 + helm-charts/yugabyte/app-readme.md | 1 + helm-charts/yugabyte/expose-all-shared.yaml | 21 + helm-charts/yugabyte/expose-all.yaml | 31 + helm-charts/yugabyte/generate_kubeconfig.py | 220 ++++ helm-charts/yugabyte/openshift.values.yaml | 4 + helm-charts/yugabyte/questions.yaml | 200 ++++ helm-charts/yugabyte/templates/NOTES.txt | 29 + helm-charts/yugabyte/templates/_helpers.tpl | 801 ++++++++++++++ .../yugabyte/templates/certificates.yaml | 190 ++++ .../templates/controller-gflags-secret.yaml | 40 + .../yugabyte/templates/debug_config_map.yaml | 46 + .../hooks/setup-credentials-job.yaml | 101 ++ .../templates/master-gflags-secret.yaml | 73 ++ .../templates/master-servicemonitor.yaml | 46 + .../multicluster/common-tserver-service.yaml | 23 + .../multicluster/mcs-service-export.yaml | 21 + .../multicluster/service-per-pod.yaml | 45 + .../yugabyte/templates/otel-collector.yaml | 174 ++++ helm-charts/yugabyte/templates/secrets.yaml | 7 + .../yugabyte/templates/service-endpoints.yaml | 93 ++ helm-charts/yugabyte/templates/service.yaml | 977 ++++++++++++++++++ .../setup-credentials-configmap.yaml | 264 +++++ .../templates/tserver-gflags-secret.yaml | 88 ++ .../templates/tserver-servicemonitor.yaml | 110 ++ helm-charts/yugabyte/test-labels.sh | 230 +++++ helm-charts/yugabyte/tests/README.md | 19 + .../yugabyte/tests/test_affinity_merges.yaml | 243 +++++ helm-charts/yugabyte/tests/test_labels.yaml | 646 ++++++++++++ .../tests/test_priority_class_name.yaml | 127 +++ .../tests/test_setup_credentials.yaml | 53 + .../yugabyte/tests/values_affinity_merge.yaml | 66 ++ .../tests/values_priority_class_name.yaml | 11 + .../values_priority_class_name_global.yaml | 6 + helm-charts/yugabyte/values.yaml | 974 +++++++++++++++++ helm-charts/yugabyte/yugabyte-rbac.yaml | 19 + 39 files changed, 6992 insertions(+) create mode 100644 examples/yugabyte/values.yaml create mode 100644 helm-charts/yugabyte/.helmignore create mode 100644 helm-charts/yugabyte/Chart.yaml create mode 100644 helm-charts/yugabyte/README.md create mode 100644 helm-charts/yugabyte/app-readme.md create mode 100644 helm-charts/yugabyte/expose-all-shared.yaml create mode 100644 helm-charts/yugabyte/expose-all.yaml create mode 100644 helm-charts/yugabyte/generate_kubeconfig.py create mode 100644 helm-charts/yugabyte/openshift.values.yaml create mode 100644 helm-charts/yugabyte/questions.yaml create mode 100644 helm-charts/yugabyte/templates/NOTES.txt create mode 100644 helm-charts/yugabyte/templates/_helpers.tpl create mode 100644 helm-charts/yugabyte/templates/certificates.yaml create mode 100644 helm-charts/yugabyte/templates/controller-gflags-secret.yaml create mode 100644 helm-charts/yugabyte/templates/debug_config_map.yaml create mode 100644 helm-charts/yugabyte/templates/hooks/setup-credentials-job.yaml create mode 100644 helm-charts/yugabyte/templates/master-gflags-secret.yaml create mode 100644 helm-charts/yugabyte/templates/master-servicemonitor.yaml create mode 100644 helm-charts/yugabyte/templates/multicluster/common-tserver-service.yaml create mode 100644 helm-charts/yugabyte/templates/multicluster/mcs-service-export.yaml create mode 100644 helm-charts/yugabyte/templates/multicluster/service-per-pod.yaml create mode 100644 helm-charts/yugabyte/templates/otel-collector.yaml create mode 100644 helm-charts/yugabyte/templates/secrets.yaml create mode 100644 helm-charts/yugabyte/templates/service-endpoints.yaml create mode 100644 helm-charts/yugabyte/templates/service.yaml create mode 100644 helm-charts/yugabyte/templates/setup-credentials-configmap.yaml create mode 100644 helm-charts/yugabyte/templates/tserver-gflags-secret.yaml create mode 100644 helm-charts/yugabyte/templates/tserver-servicemonitor.yaml create mode 100644 helm-charts/yugabyte/test-labels.sh create mode 100644 helm-charts/yugabyte/tests/README.md create mode 100644 helm-charts/yugabyte/tests/test_affinity_merges.yaml create mode 100644 helm-charts/yugabyte/tests/test_labels.yaml create mode 100644 helm-charts/yugabyte/tests/test_priority_class_name.yaml create mode 100644 helm-charts/yugabyte/tests/test_setup_credentials.yaml create mode 100644 helm-charts/yugabyte/tests/values_affinity_merge.yaml create mode 100644 helm-charts/yugabyte/tests/values_priority_class_name.yaml create mode 100644 helm-charts/yugabyte/tests/values_priority_class_name_global.yaml create mode 100644 helm-charts/yugabyte/values.yaml create mode 100644 helm-charts/yugabyte/yugabyte-rbac.yaml diff --git a/examples/yugabyte/values.yaml b/examples/yugabyte/values.yaml new file mode 100644 index 0000000..eef5160 --- /dev/null +++ b/examples/yugabyte/values.yaml @@ -0,0 +1,974 @@ +# Default values for yugabyte. +# This is a YAML-formatted file. +# Declare variables to be passed into your templates. +Component: "yugabytedb" + +fullnameOverride: "" +nameOverride: "" + +Image: + repository: "yugabytedb/yugabyte" + tag: 2025.2.3.2-b1 + pullPolicy: IfNotPresent + pullSecretName: "" + +storage: + ephemeral: false # will not allocate PVs when true + master: + count: 2 + size: 10Gi + storageClass: "" + tserver: + count: 2 + size: 10Gi + storageClass: "" + +resource: + master: + requests: + cpu: "2" + memory: 2Gi + limits: + cpu: "2" + ## Ensure the 'memory' value is strictly in 'Gi' or 'G' format. Deviating from these formats + ## may result in setting an incorrect value for the 'memory_limit_hard_bytes' flag. + ## Avoid using floating numbers for the numeric part of 'memory'. Doing so may lead to + ## the 'memory_limit_hard_bytes' being set to 0, as the function expects integer values. + memory: 2Gi + tserver: + requests: + cpu: "2" + memory: 4Gi + limits: + cpu: "2" + ## Ensure the 'memory' value is strictly in 'Gi' or 'G' format. Deviating from these formats + ## may result in setting an incorrect value for the 'memory_limit_hard_bytes' flag. + ## Avoid using floating numbers for the numeric part of 'memory'. Doing so may lead to + ## the 'memory_limit_hard_bytes' being set to 0, as the function expects integer values. + memory: 4Gi + +replicas: + master: 3 + tserver: 3 + ## Used to set replication factor when isMultiAz is set to true + totalMasters: 3 + +partition: + master: 0 + tserver: 0 + +# Used to decide if a move operation is in progress. +# This defines the range of StatefulSet indices that are part of a move operation. +# +# Rules: +# - start == end: No move operation in progress. All StatefulSets use standard values. +# - start != end: Move operation in progress. The StatefulSet with index 'end' uses values from moveOp. +# - end can only be 1 more than start (end = start + 1). This ensures only one StatefulSet +# is being migrated at a time. +# - Wraparound case: When start is at the 9, end will be 0 +# instead of start+1. This is the only exception to the "end = start + 1" rule. +# +# Example progression for 2 replicas (indices 0, 1): +# - Initial: start=0, end=0 (no migration) +# - Step 1: start=0, end=1 (migrating index 1, end = start + 1) +# - Complete: start=1, end=1 (migration complete) +stsIndex: + tserver: + start: 0 + end: 0 + master: + start: 0 + end: 0 + +# Used during move operation to define temporary configuration values. +# +# When a move operation is in progress (stsIndex.start != stsIndex.end), the StatefulSet +# with index equal to stsIndex.end will use the values defined here instead of the standard +# values (storage, replicas, partition, etc.) from the main configuration. +# +# This allows you to migrate a StatefulSet to new storage class, storage counts, or other settings +# without affecting the rest of the cluster. Once the migration is complete and stsIndex.start +# equals stsIndex.end, all StatefulSets will revert to using the standard values. +# +# Only used when stsIndex.start != stsIndex.end for the corresponding server type (master/tserver). +moveOp: + storage: + ephemeral: false # will not allocate PVs when true + master: + count: 2 + size: 10Gi + storageClass: "" + tserver: + count: 2 + size: 10Gi + storageClass: "" + + replicas: + master: 3 + tserver: 3 + + partition: + master: 0 + tserver: 0 + +updateStrategy: + type: RollingUpdate + +# Used in Multi-AZ setup +masterAddresses: "" + +isMultiAz: false +AZ: "" + +# Disable the YSQL +disableYsql: false + +tls: + # Set to true to enable the TLS. + enabled: false + nodeToNode: true + clientToServer: true + # Set to false to disallow any service with unencrypted communication from joining this cluster + insecure: false + # Set enabled to true to use cert-manager instead of providing your own node certs + certManager: + enabled: false + # Will create own ca certificate and issuer when set to true + bootstrapSelfsigned: true + # Use ClusterIssuer when set to true, otherwise use Issuer + useClusterIssuer: false + # Name of ClusterIssuer to use when useClusterIssuer is true + clusterIssuer: cluster-ca + # Name of Issuer to use when useClusterIssuer is false + issuer: yugabyte-ca + + # Set the below value to true for using custom issuer like AWSPCAClusterIssuer + useCustomIssuer: false + # if customIssuer is set to true, then below issuer values will get applied + customIssuer: + kind: Issuer + name: yugabyte-ca + group: cert-manager.io + + # Set to true to use existing server certificate. + # Useful during online certificate rotation. + useExistingServerCertificate: false + + certificates: + # The lifetime before cert-manager will issue a new certificate. + # The re-issued certificates will not be automatically reloaded by the service. + # It is necessary to provide some external means of restarting the pods. + duration: 2160h # 90d + renewBefore: 360h # 15d + algorithm: RSA # ECDSA or RSA + # Can be 2048, 4096 or 8192 for RSA + # Or 256, 384 or 521 for ECDSA + keySize: 2048 + # Enable this option to include a commonName in the Certificate. + # Certain custom Certificate Authorities (CAs), such as AWS PCA, require the commonName + # field to be present in the certificate for successful issuance. + # If set to true, the commonName of certs will automatically be set to the service name. + commonNameRequired: false + # If commonNameSuffix is specified, it will be used as the suffix for the commonName for the certificate. + commonNameSuffix: "" + + ## When certManager.enabled=false, rootCA.cert and rootCA.key are used to generate TLS certs. + ## When certManager.enabled=true and boostrapSelfsigned=true, rootCA is ignored. + ## When certManager.enabled=true and bootstrapSelfsigned=false, only rootCA.cert is used + ## to verify TLS certs generated and signed by the external provider. + rootCA: + cert: "LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSUM2VENDQWRHZ0F3SUJBZ0lCQVRBTkJna3Foa2lHOXcwQkFRc0ZBREFXTVJRd0VnWURWUVFERXd0WmRXZGgKWW5sMFpTQkVRakFlRncweE9UQXlNRGd3TURRd01qSmFGdzB5T1RBeU1EVXdNRFF3TWpKYU1CWXhGREFTQmdOVgpCQU1UQzFsMVoyRmllWFJsSUVSQ01JSUJJakFOQmdrcWhraUc5dzBCQVFFRkFBT0NBUThBTUlJQkNnS0NBUUVBCnVOMWF1aWc4b2pVMHM0OXF3QXhrT2FCaHkwcTlyaVg2akVyZWJyTHJOWDJOeHdWQmNVcWJkUlhVc3VZNS96RUQKUC9CZTNkcTFuMm9EQ2ZGVEwweGkyNFdNZExRcnJBMndCdzFtNHM1WmQzcEJ1U04yWHJkVVhkeUx6dUxlczJNbgovckJxcWRscXp6LzAyTk9TOE9SVFZCUVRTQTBSOFNMQ1RjSGxMQmRkMmdxZ1ZmemVXRlVObXhWQ2EwcHA5UENuCmpUamJJRzhJWkh5dnBkTyt3aURQM1Y1a1ZEaTkvbEtUaGUzcTFOeDg5VUNFcnRJa1pjSkYvWEs3aE90MU1sOXMKWDYzb2lVMTE1Q2svbGFGRjR6dWgrZk9VenpOVXRXeTc2RE92cm5pVGlaU0tQZDBBODNNa2l2N2VHaDVkV3owWgpsKzJ2a3dkZHJaRzVlaHhvbGhGS3pRSURBUUFCbzBJd1FEQU9CZ05WSFE4QkFmOEVCQU1DQXFRd0hRWURWUjBsCkJCWXdGQVlJS3dZQkJRVUhBd0VHQ0NzR0FRVUZCd01DTUE4R0ExVWRFd0VCL3dRRk1BTUJBZjh3RFFZSktvWkkKaHZjTkFRRUxCUUFEZ2dFQkFEQjVRbmlYd1ptdk52eG5VbS9sTTVFbms3VmhTUzRUZldIMHY4Q0srZWZMSVBTbwpVTkdLNXU5UzNEUWlvaU9SN1Vmc2YrRnk1QXljMmNUY1M2UXBxTCt0V1QrU1VITXNJNk9oQ05pQ1gvQjNKWERPCkd2R0RIQzBVOHo3aWJTcW5zQ2Rid05kajAyM0lwMHVqNE9DVHJ3azZjd0RBeXlwVWkwN2tkd28xYWJIWExqTnAKamVQMkwrY0hkc2dKM1N4WWpkK1kvei9IdmFrZG1RZDJTL1l2V0R3aU1SRDkrYmZXWkJVRHo3Y0QyQkxEVmU0aAp1bkFaK3NyelR2Sjd5dkVodzlHSDFyajd4Qm9VNjB5SUUrYSszK2xWSEs4WnBSV0NXMnh2eWNrYXJSKytPS2NKClFsL04wWExqNWJRUDVoUzdhOTdhQktTamNqY3E5VzNGcnhJa2tKST0KLS0tLS1FTkQgQ0VSVElGSUNBVEUtLS0tLQo=" + key: "LS0tLS1CRUdJTiBSU0EgUFJJVkFURSBLRVktLS0tLQpNSUlFcEFJQkFBS0NBUUVBdU4xYXVpZzhvalUwczQ5cXdBeGtPYUJoeTBxOXJpWDZqRXJlYnJMck5YMk54d1ZCCmNVcWJkUlhVc3VZNS96RURQL0JlM2RxMW4yb0RDZkZUTDB4aTI0V01kTFFyckEyd0J3MW00czVaZDNwQnVTTjIKWHJkVVhkeUx6dUxlczJNbi9yQnFxZGxxenovMDJOT1M4T1JUVkJRVFNBMFI4U0xDVGNIbExCZGQyZ3FnVmZ6ZQpXRlVObXhWQ2EwcHA5UENualRqYklHOElaSHl2cGRPK3dpRFAzVjVrVkRpOS9sS1RoZTNxMU54ODlVQ0VydElrClpjSkYvWEs3aE90MU1sOXNYNjNvaVUxMTVDay9sYUZGNHp1aCtmT1V6ek5VdFd5NzZET3ZybmlUaVpTS1BkMEEKODNNa2l2N2VHaDVkV3owWmwrMnZrd2RkclpHNWVoeG9saEZLelFJREFRQUJBb0lCQUJsdW1tU3gxR1djWER1Mwpwei8wZEhWWkV4c2NsU3U0SGRmZkZPcTF3cFlCUjlmeGFTZGsxQzR2YXF1UjhMaWl6WWVtVWViRGgraitkSnlSCmpwZ2JNaDV4S1BtRkw5empwU3ZUTkN4UHB3OUF5bm5sM3dyNHZhcU1CTS9aZGpuSGttRC9kQzBadEEvL0JIZ3YKNHk4d3VpWCsvUWdVaER0Z1JNcmR1ZUZ1OVlKaFo5UE9jYXkzSkkzMFhEYjdJSS9vNFNhYnhTcFI3bTg5WjY0NwpUb3hsOEhTSzl0SUQxbkl1bHVpTmx1dHI1RzdDdE93WTBSc2N5dmZ2elg4a1d2akpLZVJVbmhMSCtXVFZOaExICjdZc0tMNmlLa1NkckMzeWVPWnV4R0pEbVdrZVgxTzNPRUVGYkc4TjVEaGNqL0lXbDh1dGt3LzYwTEthNHBCS2cKTXhtNEx3RUNnWUVBNnlPRkhNY2pncHYxLzlHZC8yb3c2YmZKcTFjM1dqQkV2cnM2ZXNyMzgrU3UvdVFneXJNcAo5V01oZElpb2dYZjVlNjV5ZlIzYVBXcjJJdWMxZ0RUNlYycDZFR2h0NysyQkF1YkIzczloZisycVNRY1lkS3pmCnJOTDdKalE4ZEVGZWdYd041cHhKOTRTTVFZNEI4Qm9hOHNJWTd3TzU4dHpVMjZoclVnanFXQ1VDZ1lFQXlVUUIKNzViWlh6MGJ5cEc5NjNwYVp0bGlJY0cvUk1XMnVPOE9rVFNYSGdDSjBob25uRm5IMGZOc1pGTHdFWEtnTTRORworU3ZNbWtUekE5eVVSMHpIMFJ4UW44L1YzVWZLT2k5RktFeWx6NzNiRkV6ZW1QSEppQm12NWQ4ZTlOenZmU0E0CkdpRTYrYnFyV3VVWWRoRWlYTnY1SFNPZ3I4bUx1TzJDbGlmNTg0a0NnWUFlZzlDTmlJWmlOODAzOHNNWFYzZWIKalI5ZDNnYXY3SjJ2UnVyeTdvNDVGNDlpUXNiQ3AzZWxnY1RnczY5eWhkaFpwYXp6OGNEVndhREpyTW16cHF4cQpWY1liaFFIblppSWM5MGRubS9BaVF2eWJWNUZqNnQ5b05VVWtreGpaV1haalJXOGtZMW55QmtDUmJWVnhER0k4CjZOV0ZoeTFGaUVVVGNJcms3WVZFQlFLQmdRREpHTVIrYWRFamtlRlUwNjVadkZUYmN0VFVPY3dzb1Foalc2akkKZVMyTThxakNYeE80NnhQMnVTeFNTWFJKV3FpckQ3NDRkUVRvRjRCaEdXS21veGI3M3pqSGxWaHcwcXhDMnJ4VQorZENxODE0VXVJR3BlOTBMdWU3QTFlRU9kRHB1WVdUczVzc1FmdTE3MG5CUWQrcEhzaHNFZkhhdmJjZkhyTGpQCjQzMmhVUUtCZ1FDZ3hMZG5Pd2JMaHZLVkhhdTdPVXQxbGpUT240SnB5bHpnb3hFRXpzaDhDK0ZKUUQ1bkFxZXEKZUpWSkNCd2VkallBSDR6MUV3cHJjWnJIN3IyUTBqT2ZFallwU1dkZGxXaWh4OTNYODZ0aG83UzJuUlYrN1hNcQpPVW9ZcVZ1WGlGMWdMM1NGeHZqMHhxV3l0d0NPTW5DZGFCb0M0Tkw3enJtL0lZOEUwSkw2MkE9PQotLS0tLUVORCBSU0EgUFJJVkFURSBLRVktLS0tLQo=" + ## When tls.certManager.enabled=false + ## nodeCert and clientCert will be used only when rootCA.key is empty. + ## Will be ignored and genSignedCert will be used to generate + ## node and client certs if rootCA.key is provided. + ## cert and key are base64 encoded content of certificate and key. + nodeCert: + cert: "" + key: "" + clientCert: + cert: "" + key: "" + ## Checksum for CA certificate. If set to empty, statefulset + ## will calculate new checksum value and decide whether to restart pods + ## based on the result of comparing previous checksum value and new value. + ## If previous value is provided again, there will be no Pod restart + ## for CA certificate changes. + rootCAChecksum: "" + +gflags: + master: + default_memory_limit_to_ram_ratio: 0.85 + tserver: {} +# use_cassandra_authentication: false + ybc: {} + +yugabytedUi: + enabled: true + # If recoverWithoutFailure is true, yugabyted-ui will automatically try to restart itself + # instead of failing and causing the pod to restart + recoverWithoutFailure: true + recoveryInterval: 30s + # metricsSnapshotter must be enabled for yugabytedUi to properly display metrics + metricsSnapshotter: + enabled: true + # time between each metric snapshot in ms + interval: 11000 + whitelist: + - handler_latency_yb_tserver_TabletServerService_Read_count + - handler_latency_yb_tserver_TabletServerService_Write_count + - handler_latency_yb_tserver_TabletServerService_Read_sum + - handler_latency_yb_tserver_TabletServerService_Write_sum + - disk_usage + - cpu_usage + - node_up + +PodManagementPolicy: Parallel + +enableLoadBalancer: true + +ybc: + enabled: false + # Use inbuilt YB-Controller executable + useYBDBImage: false + ## https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/#resource-requests-and-limits-of-pod-and-container + ## Use the above link to learn more about Kubernetes resources configuration. + resources: + requests: + cpu: "1" + memory: 1Gi + limits: + cpu: "1" + memory: 1Gi + ## Checksum for controller gflags secret. If set to empty, statefulset + ## will calculate new checksum value and decide whether to restart pods + ## based on the result of comparing previous checksum value and new value. + ## If previous value is provided again, there will be no Pod restart + ## for gflags changes. + gflagsChecksum: "" + +ybCleanup: + ## https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/#resource-requests-and-limits-of-pod-and-container + ## Use the above link to learn more about Kubernetes resources configuration. + resources: + requests: + cpu: "0.25" + memory: 250Mi + limits: + cpu: "0.25" + memory: 250Mi + +domainName: "cluster.local" + +# ## Enable global service endpoints for tserver/master services across +# ## zones. Requires common label "app.kubernetes.io/part-of" on resources. +# globalServiceEndpoints: +# tserverGlobalService: +# enabled: false +# # Will use LoadBalancer only if 'enableLoadBalancer' is true. +# # Otherwise, ClusterIP service is created. +# type: LoadBalancer +# annotations: {} +# ## Sets the Service's externalTrafficPolicy +# externalTrafficPolicy: "" +# app: "yb-tserver" +# loadBalancerIP: "" +# name: "tserver-global-service" +# ports: +# tcp-yql-port: "9042" +# tcp-yedis-port: "6379" +# tcp-ysql-port: "5433" + +# masterGlobalService: +# enabled: false +# # Will use LoadBalancer only if 'enableLoadBalancer' is true. +# # Otherwise, ClusterIP service is created. +# type: LoadBalancer +# annotations: {} +# ## Sets the Service's externalTrafficPolicy +# externalTrafficPolicy: "" +# app: "yb-master" +# loadBalancerIP: "" +# name: "master-global-service" +# ports: +# http-ui: "7000" + +## If you would like to define which IP family to use for single stack or define +## the order of IP families for dual-stack, you can choose the address families by +## setting the ipFamilies. It can be any of these values: +## ["IPv4"] +## ["IPv6"] +## ["IPv4","IPv6"] (dual stack) +## ["IPv6","IPv4"] (dual stack) +## Docs: https://kubernetes.io/docs/concepts/services-networking/dual-stack/#dual-stack-service-configuration-scenarios +ipFamilies: [] + +## ipFamilyPolicy can be set to the following values: +## SingleStack +## PreferDualStack +## RequireDualStack +## Selects the .spec.clusterIP from the list of .spec.clusterIPs based on the address +## family of the first element in the .spec.ipFamilies array. +## Docs: https://kubernetes.io/docs/concepts/services-networking/dual-stack/#dual-stack-service-configuration-scenarios +ipFamilyPolicy: "" + +## Default service scope to use if not defined in service endpoint definition. +## Can be "Namespaced"/"AZ" +defaultServiceScope: "AZ" + +serviceEndpoints: + - name: "yb-master-ui" + type: LoadBalancer + # Can be AZ/Namespaced + scope: "AZ" + annotations: {} + clusterIP: "" + ## Sets the Service's externalTrafficPolicy + externalTrafficPolicy: "" + app: "yb-master" + loadBalancerIP: "" + ports: + http-ui: "7000" + extraArgs: {} + + - name: "yb-tserver-service" + type: LoadBalancer + # Can be AZ/Namespaced + scope: "AZ" + annotations: {} + clusterIP: "" + ## Sets the Service's externalTrafficPolicy + externalTrafficPolicy: "" + app: "yb-tserver" + loadBalancerIP: "" + ports: + tcp-yql-port: "9042" + tcp-yedis-port: "6379" + tcp-ysql-port: "5433" + extraArgs: {} + + - name: "yugabyted-ui-service" + type: LoadBalancer + # Can be AZ/Namespaced + scope: "AZ" + annotations: {} + clusterIP: "" + ## Sets the Service's externalTrafficPolicy + externalTrafficPolicy: "" + app: "yb-master" + loadBalancerIP: "" + sessionAffinity: ClientIP + ports: + yugabyted-ui: "15433" + extraArgs: {} + +Services: + - name: "yb-masters" + label: "yb-master" + skipHealthChecks: false + memory_limit_to_ram_ratio: 0.85 + ports: + http-ui: "7000" + tcp-rpc-port: "7100" + yugabyted-ui: "15433" + + - name: "yb-tservers" + label: "yb-tserver" + skipHealthChecks: false + ports: + http-ui: "9000" + tcp-rpc-port: "9100" + tcp-yql-port: "9042" + tcp-yedis-port: "6379" + tcp-ysql-port: "5433" + http-ycql-met: "12000" + http-yedis-met: "11000" + http-ysql-met: "13000" + tcp-ybc-port: "18018" + yugabyted-ui: "15433" + + +## Should be set to true only if Istio is being used. This also adds +## the Istio sidecar injection labels to the pods. +## TODO: remove this once +## https://github.com/yugabyte/yugabyte-db/issues/5641 is fixed. +## +istioCompatibility: + enabled: false + +## Settings required when using multicluster environment. +multicluster: + ## Creates a ClusterIP service for each yb-master and yb-tserver + ## pod. + createServicePerPod: false + ## creates a ClusterIP service whos name does not have release name + ## in it. A common service across different clusters for automatic + ## failover. Useful when using new naming style. + createCommonTserverService: false + + ## Enable it to deploy YugabyteDB in a multi-cluster services enabled + ## Kubernetes cluster (KEP-1645). This will create ServiceExport. + ## GKE Ref - https://cloud.google.com/kubernetes-engine/docs/how-to/multi-cluster-services#registering_a_service_for_export + ## You can use this gist for the reference to deploy the YugabyteDB in a multi-cluster scenario. + ## Gist - https://gist.github.com/baba230896/78cc9bb6f4ba0b3d0e611cd49ed201bf + createServiceExports: false + + ## Mandatory variable when createServiceExports is set to true. + ## Use: In case of GKE, you need to pass GKE Hub Membership Name. + ## GKE Ref - https://cloud.google.com/kubernetes-engine/docs/how-to/multi-cluster-services#enabling + kubernetesClusterId: "" + + ## mcsApiVersion is used for the MCS resources created by the + ## chart. Set to net.gke.io/v1 when using GKE MCS. + mcsApiVersion: "multicluster.x-k8s.io/v1alpha1" + +serviceMonitor: + ## If true, two ServiceMonitor CRs are created. One for yb-master + ## and one for yb-tserver + ## https://github.com/coreos/prometheus-operator/blob/master/Documentation/api.md#servicemonitor + ## + enabled: false + ## interval is the default scrape_interval for all the endpoints + interval: 30s + ## extraLabels can be used to add labels to the ServiceMonitors + ## being created + extraLabels: {} + # release: prom + + ## Configurations of ServiceMonitor for yb-master + master: + enabled: true + port: "http-ui" + interval: "" + path: "/prometheus-metrics" + + ## Configurations of ServiceMonitor for yb-tserver + tserver: + enabled: true + port: "http-ui" + interval: "" + path: "/prometheus-metrics" + ycql: + enabled: true + port: "http-ycql-met" + interval: "" + path: "/prometheus-metrics" + ysql: + enabled: true + port: "http-ysql-met" + interval: "" + path: "/prometheus-metrics" + yedis: + enabled: true + port: "http-yedis-met" + interval: "" + path: "/prometheus-metrics" + + commonMetricRelabelings: + # https://git.io/JJW5p + # Save the name of the metric so we can group_by since we cannot by __name__ directly... + - sourceLabels: ["__name__"] + regex: "(.*)" + targetLabel: "saved_name" + replacement: "$1" + # The following basically retrofit the handler_latency_* metrics to label format. + - sourceLabels: ["__name__"] + regex: "handler_latency_(yb_[^_]*)_([^_]*)_([^_]*)(.*)" + targetLabel: "server_type" + replacement: "$1" + - sourceLabels: ["__name__"] + regex: "handler_latency_(yb_[^_]*)_([^_]*)_([^_]*)(.*)" + targetLabel: "service_type" + replacement: "$2" + - sourceLabels: ["__name__"] + regex: "handler_latency_(yb_[^_]*)_([^_]*)_([^_]*)(_sum|_count)?" + targetLabel: "service_method" + replacement: "$3" + - sourceLabels: ["__name__"] + regex: "handler_latency_(yb_[^_]*)_([^_]*)_([^_]*)(_sum|_count)?" + targetLabel: "__name__" + replacement: "rpc_latency$4" + +resources: {} + +nodeSelector: {} + +## PriorityClassName for the StatefulSet pod template (sts.spec.template.spec.priorityClassName). +## Default for both master and tserver; override per component with master.priorityClassName / tserver.priorityClassName. +## See https://kubernetes.io/docs/concepts/scheduling-eviction/pod-priority-preemption/ +priorityClassName: "" + +affinity: {} + +statefulSetAnnotations: {} + +networkAnnotation: {} + +commonLabels: {} + +## @param dnsPolicy DNS Policy for pod +## ref: https://kubernetes.io/docs/concepts/services-networking/dns-pod-service/ +## E.g. +## dnsPolicy: ClusterFirst +dnsPolicy: "" +## @param dnsConfig DNS Configuration pod +## ref: https://kubernetes.io/docs/concepts/services-networking/dns-pod-service/ +## E.g. +## dnsConfig: +## options: +## - name: ndots +## value: "4" +dnsConfig: {} + + +master: + ## Ref: https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.22/#affinity-v1-core + ## This might override the default affinity from service.yaml + # To successfully merge, we need to follow rules for merging nodeSelectorTerms that kubernentes + # has. Each new node selector term is ORed together, and each match expression or match field in + # a single selector is ANDed together. + # This means, if a pod needs to be scheduled on a label 'custom_label_1' with a value + # 'custom_value_1', we need to add this 'subterm' to each of our pre-defined node affinity + # terms. + # + # Pod anti affinity is a simpler merge. Each term is applied separately, and the weight is tracked. + # The pod that achieves the highest weight is selected. + ## Example. + # affinity: + # podAntiAffinity: + # requiredDuringSchedulingIgnoredDuringExecution: + # - labelSelector: + # matchExpressions: + # - key: app + # operator: In + # values: + # - "yb-master" + # topologyKey: kubernetes.io/hostname + # + # For further examples, see examples/yugabyte/affinity_overrides.yaml + affinity: {} + + ## Extra environment variables passed to the Master pods. + ## Ref: https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.22/#envvar-v1-core + ## Example: + # extraEnv: + # - name: NODE_IP + # valueFrom: + # fieldRef: + # fieldPath: status.hostIP + extraEnv: [] + + # secretEnv variables are used to expose secrets data as env variables in the master pod. + # TODO Add namespace also to support copying secrets from other namespace. + # secretEnv: + # - name: MYSQL_LDAP_PASSWORD + # valueFrom: + # secretKeyRef: + # name: secretName + # key: password + secretEnv: [] + + ## Annotations to be added to the Master pods. + podAnnotations: {} + + ## Labels to be added to the Master pods. + podLabels: {} + + ## Tolerations to be added to the Master pods. + ## Ref: https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.22/#toleration-v1-core + ## Example: + # tolerations: + # - key: dedicated + # operator: Equal + # value: experimental + # effect: NoSchedule + tolerations: [] + + ## Extra volumes + ## extraVolumesMounts are mandatory for each extraVolumes. + ## Ref: https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.22/#volume-v1-core + ## Example: + # extraVolumes: + # - name: custom-nfs-vol + # persistentVolumeClaim: + # claimName: some-nfs-claim + extraVolumes: [] + + ## Extra volume mounts + ## Ref: https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.22/#volumemount-v1-core + ## Example: + # extraVolumeMounts: + # - name: custom-nfs-vol + # mountPath: /home/yugabyte/nfs-backup + extraVolumeMounts: [] + + ## Set service account for master DB pods. The service account + ## should exist in the namespace where the master DB pods are brought up. + serviceAccount: "" + + ## PriorityClassName for master pods (sts.spec.template.spec.priorityClassName). + ## Falls back to top-level priorityClassName if unset. + priorityClassName: "" + + ## Memory limit hard % (between 1-100) of the memory limit. + memoryLimitHardPercentage: 85 + + ## Readiness Probe + readinessProbe: + enabled: false + initialDelaySeconds: 30 + periodSeconds: 20 + timeoutSeconds: 10 + failureThreshold: 3 + successThreshold: 1 + + ## Custom readinessProbe that overrides the default one + ## Example: HTTP based Master readinessProbe + # customReadinessProbe: + # initialDelaySeconds: 30 + # periodSeconds: 20 + # timeoutSeconds: 10 + # failureThreshold: 3 + # successThreshold: 1 + # httpGet: + # path: / + # port: 7000 + ## Ref: https://kubernetes.io/docs/tasks/configure-pod-container/configure-liveness-readiness-startup-probes/#define-readiness-probes + customReadinessProbe: {} + + ## Startup probe + startupProbe: + enabled: false + initialDelaySeconds: 10 + periodSeconds: 10 + timeoutSeconds: 5 + failureThreshold: 30 + successThreshold: 1 + + ## Custom startupProbe that overrides the default one + ## Enabling it will overrides the tserver.startupProbe + ## Example: HTTP based Master startupProbe + # customStartupProbe: + # initialDelaySeconds: 30 + # periodSeconds: 10 + # timeoutSeconds: 5 + # failureThreshold: 3 + # successThreshold: 1 + # httpGet: + # path: / + # port: 7000 + ## Ref: https://kubernetes.io/docs/tasks/configure-pod-container/configure-liveness-readiness-startup-probes/#define-startup-probes + customStartupProbe: {} + + ## Checksum for master gflags secret. If set to empty, statefulset + ## will calculate new checksum value and decide whether to restart pods + ## based on the result of comparing previous checksum value and new value. + ## If previous value is provided again, there will be no Pod restart + ## for gflags changes. + gflagsChecksum: "" + + advanced: + ## Bash commands to run before the start of the master service + ## WARNING: This is an advanced feature. Incorrect use may cause startup failures, + ## security issues, or unexpected behavior. Use with caution and at your own risk. + preCommands: "" + + +tserver: + ## Ref: https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.22/#affinity-v1-core + ## This might override the default affinity from service.yaml + # To successfully merge, we need to follow rules for merging nodeSelectorTerms that kubernentes + # has. Each new node selector term is ORed together, and each match expression or match field in + # a single selector is ANDed together. + # This means, if a pod needs to be scheduled on a label 'custom_label_1' with a value + # 'custom_value_1', we need to add this 'subterm' to each of our pre-defined node affinity + # terms. + # + # Pod anti affinity is a simpler merge. Each term is applied separately, and the weight is tracked. + # The pod that achieves the highest weight is selected. + ## Example. + # affinity: + # podAntiAffinity: + # requiredDuringSchedulingIgnoredDuringExecution: + # - labelSelector: + # matchExpressions: + # - key: app + # operator: In + # values: + # - "yb-tserver" + # topologyKey: kubernetes.io/hostname + # For further examples, see examples/yugabyte/affinity_overrides.yaml + affinity: {} + + ## Extra environment variables passed to the TServer pods. + ## Ref: https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.22/#envvar-v1-core + ## Example: + # extraEnv: + # - name: NODE_IP + # valueFrom: + # fieldRef: + # fieldPath: status.hostIP + extraEnv: [] + + ## secretEnv variables are used to expose secrets data as env variables in the tserver pods. + ## If namespace field is not specified we assume that user already + ## created the secret in the same namespace as DB pods. + ## Example + # secretEnv: + # - name: MYSQL_LDAP_PASSWORD + # valueFrom: + # secretKeyRef: + # name: secretName + # namespace: my-other-namespace-with-ldap-secret + # key: password + secretEnv: [] + + ## Annotations to be added to the TServer pods. + podAnnotations: {} + + ## Labels to be added to the TServer pods. + podLabels: {} + + ## Tolerations to be added to the TServer pods. + ## Ref: https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.22/#toleration-v1-core + ## Example: + # tolerations: + # - key: dedicated + # operator: Equal + # value: experimental + # effect: NoSchedule + tolerations: [] + + ## PriorityClassName for tserver pods (sts.spec.template.spec.priorityClassName). + ## Falls back to top-level priorityClassName if unset. + priorityClassName: "" + + ## Sets the --server_broadcast_addresses flag on the TServer, no + ## preflight checks are done for this address. You might need to add + ## `use_private_ip: cloud` to the gflags.master and gflags.tserver. + serverBroadcastAddress: "" + + ## Extra volumes + ## extraVolumesMounts are mandatory for each extraVolumes. + ## Ref: https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.22/#volume-v1-core + ## Example: + # extraVolumes: + # - name: custom-nfs-vol + # persistentVolumeClaim: + # claimName: some-nfs-claim + extraVolumes: [] + + ## Extra volume mounts + ## Ref: https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.22/#volumemount-v1-core + ## Example: + # extraVolumeMounts: + # - name: custom-nfs-vol + # path: /home/yugabyte/nfs-backup + extraVolumeMounts: [] + + ## Set service account for tserver DB pods. The service account + ## should exist in the namespace where the tserver DB pods are brought up. + serviceAccount: "" + + ## Memory limit hard % (between 1-100) of the memory limit. + memoryLimitHardPercentage: 85 + + ## Readiness Probe + readinessProbe: + enabled: false + initialDelaySeconds: 30 + periodSeconds: 20 + timeoutSeconds: 10 + failureThreshold: 3 + successThreshold: 1 + + ## Custom readinessProbe that overrides the default one + ## Enabling it will overrides the tserver.readinessProbe + ## Example: HTTP based Tserver readinessProbe + # customReadinessProbe: + # initialDelaySeconds: 30 + # periodSeconds: 20 + # timeoutSeconds: 10 + # httpGet: + # path: / + # port: 9000 + ## Ref: https://kubernetes.io/docs/tasks/configure-pod-container/configure-liveness-readiness-startup-probes/#define-readiness-probes + customReadinessProbe: {} + + ## Startup probe + startupProbe: + enabled: false + initialDelaySeconds: 10 + periodSeconds: 10 + timeoutSeconds: 5 + failureThreshold: 30 + successThreshold: 1 + + ## Custom startupProbe that overrides the default one + ## Enabling it will overrides the tserver.startupProbe + ## Example: HTTP based Tserver startupProbe + # customStartupProbe: + # initialDelaySeconds: 30 + # periodSeconds: 10 + # timeoutSeconds: 5 + # failureThreshold: 3 + # successThreshold: 1 + # httpGet: + # path: / + # port: 9000 + ## Ref: https://kubernetes.io/docs/tasks/configure-pod-container/configure-liveness-readiness-startup-probes/#define-startup-probes + customStartupProbe: {} + + ## Checksum for tserver gflags secret. If set to empty, statefulset + ## will calculate new checksum value and decide whether to restart pods + ## based on the result of comparing previous checksum value and new value. + ## If previous value is provided again, there will be no Pod restart + ## for gflags changes. + gflagsChecksum: "" + + advanced: + ## Bash commands to run before the start of the tserver service + ## WARNING: This is an advanced feature. Incorrect use may cause startup failures, + ## security issues, or unexpected behavior. Use with caution and at your own risk. + preCommands: "" + +helm2Legacy: false + +ip_version_support: "v4_only" # v4_only, v6_only are the only supported values at the moment + +# For more https://docs.yugabyte.com/latest/reference/configuration/yugabyted/#environment-variables +authCredentials: + ysql: + user: "" + password: "" + database: "" + # Must contain the key ysqlPassword + passwordSecretName: "" + ycql: + user: "" + password: "" + keyspace: "" + # Must contain the key ycqlPassword + passwordSecretName: "" + +oldNamingStyle: true + +preflight: + # Set to true to skip disk IO check, DNS address resolution, and + # port bind checks + skipAll: false + # Set to true to skip port bind checks + skipBind: false + + ## Set to true to skip ulimit verification + ## SkipAll has higher priority + skipUlimit: false + +## Liveness Probe configuration for both master and tserver pods +livenessProbe: + enabled: true + failureThreshold: 3 + periodSeconds: 10 + successThreshold: 1 + timeoutSeconds: 1 + +## Custom livenessProbe that overrides the default one +## Example: +# customLivenessProbe: +# failureThreshold: 3 +# periodSeconds: 10 +# timeoutSeconds: 1 +# successThreshold: 1 +# exec: +# command: +# - /custom/health/check +customLivenessProbe: {} + +## Pod securityContext +## Ref: https://kubernetes.io/docs/reference/kubernetes-api/workload-resources/pod-v1/#security-context +## The following configuration runs YB-Master and YB-TServer as a non-root user +## Applied at the pod level; settings inherit to all containers in the pod +## unless overridden via containerSecurityContext below. +podSecurityContext: + enabled: false + ## Mark it false, if you want to stop the non root user validation + runAsNonRoot: true + fsGroup: 10001 + runAsUser: 10001 + runAsGroup: 10001 + additionalSettings: {} + +## Container securityContext +## Applied at the container level for each container in the yugabyte pods. +## When enabled, this overrides the values inherited from the pod-level +## podSecurityContext on a per-container basis. +## Ref: https://kubernetes.io/docs/tasks/configure-pod-container/security-context/ +containerSecurityContext: + enabled: false + ## Expected to have runAsUser values != 0 when + ## runAsNonRoot is set to true, otherwise container creation fails. + runAsUser: 10001 + runAsGroup: 10001 + runAsNonRoot: true + additionalSettings: {} + +## Added to handle old universe which has volume annotations +## K8s universe <= 2.5 to >= 2.6 +legacyVolumeClaimAnnotations: false + +useOldPodDisruptionBudget: true + +## Set to true to enable OCP compatibility mode. +ocpCompatibility: + enabled: false + +## Set to true to run OTEL collector as a sidecar in tserver pods +otelCollector: + enabled: false + image: "" + exporters: {} # Add exporters here + # exporters: + # datadog: + # api: + # key: + # site: datadoghq.com + # retry_on_failure: + # enabled: true + # sending_queue: + # enabled: true + # storage: file_storage/queue + + recievers: + ysql: + # Set ysql receiver params here, based on log_line_prefix set in ysql_pg.conf + lineStartPattern: "(?P\\d{4}-\\d{2}-\\d{2} \\d{2}:\\d{2}:\\d{2}[.]\\d{3} \\w{3})[ ][[](?P\\d+)[]][ ]" + regex: "(?P\\d{4}-\\d{2}-\\d{2} \\d{2}:\\d{2}:\\d{2}[.]\\d{3} \\w{3})[ ][[](?P\\d+)[]][ ](?P\\w+): AUDIT: (?P\\w+),(?P\\d+),(?P\\d+),(?P\\w+),(?P[^,]+),(?P[^,]*),(?P[^,]*),(?P(.|\\n|\\r|\\s)*)" + timestamp: + layout: '%Y-%m-%d %H:%M:%S.%L %Z' + parse_from: 'attributes.timestamp_with_ms' + resources: {} + # resources: + # requests: + # cpu: "100m" + # memory: "256Mi" + # limits: + # cpu: "200m" + # memory: "512Mi" + + # Add secret environment variables here if using AWS CloudWatch or GCP Log Explorer. + secretEnv: [] + # secretEnv: + # - envName: AWS_ACCESS_KEY_ID + # envValue: + # - envName: AWS_SECRET_ACCESS_KEY + # envValue: + # - envName: GOOGLE_APPLICATION_CREDENTIALS_CONTENT + # envValue: + + # Alternatively, set `tserver.serviceAccount` to a service account with the necessary permissions + # to utilize IAM roles for access instead of embedding credentials directly. + # Additionally, ensure that the appropriate nodeSelector is added to enable the metadata server + # for example: for IAM authentication in GKE. + # nodeSelector: + # iam.gke.io/gke-metadata-server-enabled: "true" diff --git a/helm-charts/yugabyte/.helmignore b/helm-charts/yugabyte/.helmignore new file mode 100644 index 0000000..3598c30 --- /dev/null +++ b/helm-charts/yugabyte/.helmignore @@ -0,0 +1 @@ +tests \ No newline at end of file diff --git a/helm-charts/yugabyte/Chart.yaml b/helm-charts/yugabyte/Chart.yaml new file mode 100644 index 0000000..e896e52 --- /dev/null +++ b/helm-charts/yugabyte/Chart.yaml @@ -0,0 +1,17 @@ +apiVersion: v2 +name: yugabyte +version: 2025.2.3 +appVersion: 2025.2.3.2-b1 +kubeVersion: ">=1.17.0-0" +home: https://www.yugabyte.com +description: YugabyteDB is the high-performance distributed SQL database for building global, internet-scale apps. +icon: https://avatars0.githubusercontent.com/u/17074854?s=200&v=4 +sources: +- https://github.com/yugabyte/yugabyte-db +maintainers: +- name: Sanketh Indarapu + email: sanketh@yugabyte.com +- name: Govardhan Reddy Jalla + email: gjalla@yugabyte.com +annotations: + charts.openshift.io/name: yugabyte diff --git a/helm-charts/yugabyte/README.md b/helm-charts/yugabyte/README.md new file mode 100644 index 0000000..9528cff --- /dev/null +++ b/helm-charts/yugabyte/README.md @@ -0,0 +1 @@ +YugabyteDB can be deployed in various Kubernetes configurations (including single zone, multi-zone and multi-cluster) using this Helm Chart. Detailed documentation is available in [YugabyteDB Docs for Kubernetes Deployments](https://docs.yugabyte.com/latest/deploy/kubernetes/). diff --git a/helm-charts/yugabyte/app-readme.md b/helm-charts/yugabyte/app-readme.md new file mode 100644 index 0000000..ea01c6c --- /dev/null +++ b/helm-charts/yugabyte/app-readme.md @@ -0,0 +1 @@ +This chart bootstraps an RF3 YugabyteDB version 2025.2.3.2-b1 cluster using the Helm Package Manager. diff --git a/helm-charts/yugabyte/expose-all-shared.yaml b/helm-charts/yugabyte/expose-all-shared.yaml new file mode 100644 index 0000000..fae0234 --- /dev/null +++ b/helm-charts/yugabyte/expose-all-shared.yaml @@ -0,0 +1,21 @@ +serviceEndpoints: + - name: "yb-master-service" + type: LoadBalancer + app: "yb-master" + ports: + ui: "7000" + + - name: "yb-tserver-service" + type: LoadBalancer + app: "yb-tserver" + ports: + yql-port: "9042" + yedis-port: "6379" + ysql-port: "5433" + + - name: "yugabyted-ui-service" + type: LoadBalancer + app: "yb-master" + sessionAffinity: ClientIP + ports: + yugabyted-ui: "15433" diff --git a/helm-charts/yugabyte/expose-all.yaml b/helm-charts/yugabyte/expose-all.yaml new file mode 100644 index 0000000..ac3edf5 --- /dev/null +++ b/helm-charts/yugabyte/expose-all.yaml @@ -0,0 +1,31 @@ +serviceEndpoints: + - name: "yb-master-ui" + type: LoadBalancer + app: "yb-master" + ports: + ui: "7000" + + - name: "yql-service" + type: LoadBalancer + app: "yb-tserver" + ports: + yql-port: "9042" + + - name: "yedis-service" + type: LoadBalancer + app: "yb-tserver" + ports: + yedis-port: "6379" + + - name: "ysql-service" + type: LoadBalancer + app: "yb-tserver" + ports: + ysql-port: "5433" + + - name: "yugabyted-ui-service" + type: LoadBalancer + app: "yb-master" + sessionAffinity: ClientIP + ports: + yugabyted-ui: "15433" diff --git a/helm-charts/yugabyte/generate_kubeconfig.py b/helm-charts/yugabyte/generate_kubeconfig.py new file mode 100644 index 0000000..0d91739 --- /dev/null +++ b/helm-charts/yugabyte/generate_kubeconfig.py @@ -0,0 +1,220 @@ +#!/usr/bin/python +# Copyright (c) YugaByte, Inc. + +# This script would generate a kubeconfig for the given servie account +# by fetching the cluster information and also add the service account +# token for the authentication purpose. + +import argparse +from subprocess import check_output +from sys import exit +import json +import base64 +import tempfile +import time +import os.path + + +def run_command(command_args, namespace=None, as_json=True, log_command=True): + command = ["kubectl"] + if namespace: + command.extend(["--namespace", namespace]) + command.extend(command_args) + if as_json: + command.extend(["-o", "json"]) + if log_command: + print("Running command: {}".format(" ".join(command))) + output = check_output(command) + if as_json: + return json.loads(output) + else: + return output.decode("utf8") + + +def create_sa_token_secret(directory, sa_name, namespace): + """Creates a service account token secret for sa_name in + namespace. Returns the name of the secret created. + + Ref: + https://k8s.io/docs/concepts/configuration/secret/#service-account-token-secrets + + """ + token_secret = { + "apiVersion": "v1", + "data": { + "do-not-delete-used-for-yugabyte-anywhere": "MQ==", + }, + "kind": "Secret", + "metadata": { + "annotations": { + "kubernetes.io/service-account.name": sa_name, + }, + "name": sa_name, + }, + "type": "kubernetes.io/service-account-token", + } + token_secret_file_name = os.path.join(directory, "token_secret.yaml") + with open(token_secret_file_name, "w") as token_secret_file: + json.dump(token_secret, token_secret_file) + run_command(["apply", "-f", token_secret_file_name], namespace) + return sa_name + + +def get_secret_data(secret, namespace): + """Returns the secret in JSON format if it has ca.crt and token in + it, else returns None. It retries 3 times with 1 second timeout + for the secret to be populated with this data. + + """ + secret_data = None + num_retries = 5 + timeout = 2 + while True: + secret_json = run_command(["get", "secret", secret], namespace) + if "ca.crt" in secret_json["data"] and "token" in secret_json["data"]: + secret_data = secret_json + break + + num_retries -= 1 + if num_retries == 0: + break + print( + "Secret '{}' is not populated. Sleep {}s, ({} retries left)".format( + secret, timeout, num_retries + ) + ) + time.sleep(timeout) + return secret_data + + +def get_secrets_for_sa(sa_name, namespace): + """Returns a list of all service account token secrets associated + with the given sa_name in the namespace. + + """ + secrets = run_command( + [ + "get", + "secret", + "--field-selector", + "type=kubernetes.io/service-account-token", + "-o", + 'jsonpath="{.items[?(@.metadata.annotations.kubernetes\.io/service-account\.name == "' + + sa_name + + '")].metadata.name}"', + ], + namespace, + as_json=False, + ) + return secrets.strip('"').split() + + +parser = argparse.ArgumentParser(description="Generate KubeConfig with Token") +parser.add_argument("-s", "--service_account", help="Service Account name", required=True) +parser.add_argument("-n", "--namespace", help="Kubernetes namespace", default="kube-system") +parser.add_argument("-c", "--context", help="kubectl context") +parser.add_argument("-o", "--output_file", help="output file path") +args = vars(parser.parse_args()) + +# if the context is not provided we use the current-context +context = args["context"] +if context is None: + context = run_command(["config", "current-context"], args["namespace"], as_json=False) + +cluster_attrs = run_command( + ["config", "get-contexts", context.strip(), "--no-headers"], args["namespace"], as_json=False +) + +cluster_name = cluster_attrs.strip().split()[2] +endpoint = run_command( + [ + "config", + "view", + "-o", + 'jsonpath="{.clusters[?(@.name =="' + cluster_name + '")].cluster.server}"', + ], + args["namespace"], + as_json=False, +) +service_account_info = run_command(["get", "sa", args["service_account"]], args["namespace"]) + +tmpdir = tempfile.TemporaryDirectory() + +# Get the token and ca.crt from service account secret. +sa_secrets = list() + +# Get secrets specified in the service account, there can be multiple +# of them, and not all are service account token secrets. +if "secrets" in service_account_info: + sa_secrets = [secret["name"] for secret in service_account_info["secrets"]] + +# Find the existing additional service account token secrets +sa_secrets.extend(get_secrets_for_sa(args["service_account"], args["namespace"])) + +secret_data = None +for secret in sa_secrets: + secret_data = get_secret_data(secret, args["namespace"]) + if secret_data is not None: + break + +# Kubernetes 1.22+ doesn't create the service account token secret by +# default, we have to create one. +if secret_data is None: + print("No usable secret found for '{}', creating one.".format(args["service_account"])) + token_secret = create_sa_token_secret(tmpdir.name, args["service_account"], args["namespace"]) + secret_data = get_secret_data(token_secret, args["namespace"]) + if secret_data is None: + exit( + "Failed to generate kubeconfig: No usable credentials found for '{}'.".format( + args["service_account"] + ) + ) + + +context_name = "{}-{}".format(args["service_account"], cluster_name) +kube_config = args["output_file"] +if not kube_config: + kube_config = "/tmp/{}.conf".format(args["service_account"]) + + +ca_crt_file_name = os.path.join(tmpdir.name, "ca.crt") +ca_crt_file = open(ca_crt_file_name, "wb") +ca_crt_file.write(base64.b64decode(secret_data["data"]["ca.crt"])) +ca_crt_file.close() + +# create kubeconfig entry +set_cluster_cmd = [ + "config", + "set-cluster", + cluster_name, + "--kubeconfig={}".format(kube_config), + "--server={}".format(endpoint.strip('"')), + "--embed-certs=true", + "--certificate-authority={}".format(ca_crt_file_name), +] +run_command(set_cluster_cmd, as_json=False) + +user_token = base64.b64decode(secret_data["data"]["token"]).decode("utf-8") +set_credentials_cmd = [ + "config", + "set-credentials", + context_name, + "--token={}".format(user_token), + "--kubeconfig={}".format(kube_config), +] +run_command(set_credentials_cmd, as_json=False, log_command=False) + +set_context_cmd = [ + "config", + "set-context", + context_name, + "--cluster={}".format(cluster_name), + "--user={}".format(context_name), + "--kubeconfig={}".format(kube_config), +] +run_command(set_context_cmd, as_json=False) + +use_context_cmd = ["config", "use-context", context_name, "--kubeconfig={}".format(kube_config)] +run_command(use_context_cmd, as_json=False) + +print("Generated the kubeconfig file: {}".format(kube_config)) diff --git a/helm-charts/yugabyte/openshift.values.yaml b/helm-charts/yugabyte/openshift.values.yaml new file mode 100644 index 0000000..d2784b2 --- /dev/null +++ b/helm-charts/yugabyte/openshift.values.yaml @@ -0,0 +1,4 @@ +# OCP compatible values for yugabyte + +Image: + repository: "quay.io/yugabyte/yugabyte-ubi" diff --git a/helm-charts/yugabyte/questions.yaml b/helm-charts/yugabyte/questions.yaml new file mode 100644 index 0000000..7df1875 --- /dev/null +++ b/helm-charts/yugabyte/questions.yaml @@ -0,0 +1,200 @@ +--- +questions: + ## Default images for yugabyte + - variable: questions.defaultYugabyteDB + default: true + description: "Use default settings for YugabyteDB" + label: Use default + type: boolean + show_subquestion_if: false + group: "YugabyteDB" + subquestions: + - variable: Image.repository + default: "yugabytedb/yugabyte" + required: true + type: string + label: YugabyteDB image repository + description: "YugabyteDB image repository" + - variable: Image.tag + default: "2.5.1.0-b153" + required: true + type: string + label: YugabyteDB image tag + description: "YugabyteDB image tag" + - variable: Image.pullPolicy + default: "IfNotPresent" + required: false + type: enum + options: + - "Always" + - "IfNotPresent" + label: YugabyteDB image pull policy + description: "YugabyteDB image pull policy" + - variable: storage.ephemeral + default: false + required: false + type: boolean + label: YugabyteDB ephemeral storage + description: "Won't allocate PVs when true" + - variable: replicas.master + default: 3 + description: "Number of replicas for Master" + type: int + required: true + label: Replication Factor Master + - variable: replicas.tserver + default: 3 + description: "Number of replicas for TServer" + type: int + required: true + label: Replication Factor TServer + - variable: statefulSetAnnotations + description: Annotations for the StatefulSet + type: dict + required: false + label: "Annotations for the StatefulSet" + - variable: questions.defaultMasterStorage + default: true + description: "Use default storage configurations for YugabyteDB Master" + label: Use default storage configurations + type: boolean + show_subquestion_if: false + group: "Master Storage" + subquestions: + - variable: storage.master.count + default: 2 + required: true + type: int + label: YugabyteDB master storage disk count + description: "YugabyteDB master storage disk count" + - variable: storage.master.size + default: "10Gi" + required: true + type: string + label: YugabyteDB master storage size + description: "YugabyteDB master storage size" + - variable: storage.master.storageClass + default: "" + required: false + type: storageclass + label: YugabyteDB master storage class + description: "YugabyteDB master storage class" + - variable: questions.defaultTServerStorage + default: true + description: "Use default storage configurations for YugabyteDB TServer" + label: Use default storage configuration + type: boolean + show_subquestion_if: false + group: "TServer Storage" + subquestions: + - variable: storage.tserver.count + default: 2 + required: true + type: int + label: YugabyteDB TServer storage disk count + description: "YugabyteDB TServer storage disk count" + - variable: storage.tserver.size + default: "10Gi" + required: true + type: string + label: YugabyteDB TServer storage size + description: "YugabyteDB TServer storage size" + - variable: storage.tserver.storageClass + default: "" + required: false + type: storageclass + label: YugabyteDB TServer storage class + description: "YugabyteDB TServer storage class" + ## Default resources + - variable: questions.defaultResources + default: true + description: "Use default resources for YugabyteDB" + label: Use default resources + type: boolean + show_subquestion_if: false + group: "Resources" + subquestions: + - variable: resource.master.requests.cpu + default: "2" + description: "Master vcpu allocation for YugabyteDB" + type: string + required: true + label: vcpu allocation for master + - variable: resource.master.requests.memory + default: "2Gi" + description: "Master RAM allocation for YugabyteDB" + type: string + required: true + label: RAM allocation for master + - variable: resource.tserver.requests.cpu + default: "2" + description: "TServer vcpu allocation for YugabyteDB" + type: string + required: true + label: vcpu allocation for tserver + - variable: resource.tserver.requests.memory + default: "4Gi" + description: "TServer RAM allocation for YugabyteDB" + type: string + required: true + label: RAM allocation for tserver + ## TLS + - variable: tls.enabled + default: false + description: "Enable TLS - TLS disabled by default" + label: Enable TLS + type: boolean + show_subquestion_if: true + group: "TLS" + subquestions: + - variable: tls.nodeToNode + default: true + description: "Node to Node" + type: boolean + required: false + label: Node to Node + - variable: tls.clientToServer + default: true + description: "Client to server" + type: boolean + required: false + label: Client to server + - variable: tls.insecure + default: false + description: "Insecure - no service will connect on unencrypted connection" + type: boolean + required: false + label: Insecure communication + - variable: tls.certManager.enabled + default: false + description: "Use cert-manager to provide cluster certificates" + type: boolean + required: false + label: Cert-Manager Support + - variable: containerSecurityContext.enabled + default: false + description: "Enable Container Security Context" + label: Enable Container Security Context + type: boolean + show_subquestion_if: true + group: "Security Context" + subquestions: + - variable: containerSecurityContext.runAsUser + default: 10001 + required: false + type: int + label: runAsUser + description: "runAsUser" + - variable: containerSecurityContext.runAsGroup + default: 10001 + required: false + type: int + label: runAsGroup + description: "runAsGroup" + - variable: containerSecurityContext.runAsNonRoot + default: true + required: false + type: boolean + label: runAsNonRoot + description: "runAsNonRoot" + diff --git a/helm-charts/yugabyte/templates/NOTES.txt b/helm-charts/yugabyte/templates/NOTES.txt new file mode 100644 index 0000000..2f90d74 --- /dev/null +++ b/helm-charts/yugabyte/templates/NOTES.txt @@ -0,0 +1,29 @@ +1. Get YugabyteDB Pods by running this command: + kubectl --namespace {{ .Release.Namespace }} get pods + +2. Get list of YugabyteDB services that are running: + kubectl --namespace {{ .Release.Namespace }} get services + +3. Get information about the load balancer services: + kubectl get svc --namespace {{ .Release.Namespace }} + +4. Connect to one of the tablet server: + kubectl exec --namespace {{ .Release.Namespace }} -it yb-tserver-0 bash + +5. Run YSQL shell from inside of a tablet server: + kubectl exec --namespace {{ .Release.Namespace }} -it yb-tserver-0 -- /home/yugabyte/bin/ysqlsh -h yb-tserver-0.yb-tservers.{{ .Release.Namespace }} + +6. Cleanup YugabyteDB Pods + For helm 2: + helm delete {{ .Release.Name }} --purge + For helm 3: + helm delete {{ .Release.Name }} -n {{ .Release.Namespace }} + NOTE: You need to manually delete the persistent volume + {{- $root := . -}} + {{- range .Values.Services }} + kubectl delete pvc --namespace {{ $root.Release.Namespace }} -l app={{.label}} + {{- end }} +{{ if $root.Values.yugabytedUi.enabled }} +NOTE: The yugabyted UI is now available and is enabled by default. It requires version 2.21.0 or greater. +If you are using a custom image of YugabyteDB that is older than 2.21.0, please disable the UI by setting yugabytedUi.enabled to false. +{{- end }} diff --git a/helm-charts/yugabyte/templates/_helpers.tpl b/helm-charts/yugabyte/templates/_helpers.tpl new file mode 100644 index 0000000..3aa798c --- /dev/null +++ b/helm-charts/yugabyte/templates/_helpers.tpl @@ -0,0 +1,801 @@ +{{/* vim: set filetype=mustache: */}} + +{{/* +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. +The components in this chart create additional resources that expand the longest created name strings. +The longest name that gets created of 20 characters, so truncation should be 63-20=43. +*/}} +{{- define "yugabyte.fullname" -}} + {{- if .Values.fullnameOverride -}} + {{- .Values.fullnameOverride | trunc 43 | trimSuffix "-" -}} + {{- else -}} + {{- $name := default .Chart.Name .Values.nameOverride -}} + {{- if contains $name .Release.Name -}} + {{- .Release.Name | trunc 43 | trimSuffix "-" -}} + {{- else -}} + {{- printf "%s-%s" .Release.Name $name | trunc 43 | trimSuffix "-" -}} + {{- end -}} + {{- end -}} +{{- end -}} + +{{/* +Generate common labels. +Excludes chart-managed labels from commonLabels to prevent overriding them. +Chart-managed labels include: heritage, release (used in selectors), chart, component, app, app.kubernetes.io/name +*/}} +{{- define "yugabyte.labels" }} +heritage: {{ .Values.helm2Legacy | ternary "Tiller" (.Release.Service | quote) }} +release: {{ .Release.Name | quote }} +chart: {{ .Chart.Name | quote }} +component: {{ .Values.Component | quote }} +{{- if .Values.commonLabels}} +{{- $filteredLabels := .Values.commonLabels }} +{{- if .Values.oldNamingStyle }} +{{- $filteredLabels = omit $filteredLabels "heritage" "release" "chart" "component" "app" }} +{{- else }} +{{- $filteredLabels = omit $filteredLabels "heritage" "release" "chart" "component" "app" "app.kubernetes.io/name" }} +{{- end }} +{{ toYaml $filteredLabels }} +{{- end }} +{{- end }} + +{{/* +Generate app label. +*/}} +{{- define "yugabyte.applabel" }} +{{- if .root.Values.oldNamingStyle }} +app: "{{ .label }}" +{{- else }} +app.kubernetes.io/name: "{{ .label }}" +{{- end }} +{{- end }} + +{{/* +Generate app selector. +*/}} +{{- define "yugabyte.appselector" }} +{{- if .root.Values.oldNamingStyle }} +app: "{{ .label }}" +{{- else }} +app.kubernetes.io/name: "{{ .label }}" +{{- end }} +release: {{ .root.Release.Name | quote }} +{{- end }} + +{{/* +Generate service name. +*/}} +{{- define "yugabyte.servicename" }} + {{- if eq .scope "Namespaced" }} + {{- $prefix := (get (.root.Values.commonLabels | default dict) "app.kubernetes.io/part-of" | default "namespaced") | trunc 43 | trimSuffix "-" }} + {{- if $prefix }} + {{- printf "%s-%s" $prefix .endpoint.name }} + {{- else }} + {{- .endpoint.name }} + {{- end }} + {{- else }} + {{- .root.Values.oldNamingStyle | ternary .endpoint.name (printf "%s-%s" (include "yugabyte.fullname" $.root) .endpoint.name) }} + {{- end }} +{{- end }} + +{{/* +Get service scope +*/}} +{{- define "yugabyte.servicescope" }} + {{- if .endpoint.scope }} + {{- .endpoint.scope }} + {{- else }} + {{- .defaultScope }} + {{- end }} +{{- end }} + +{{/* +Generate namespaced service selector. +*/}} +{{- define "yugabyte.namespacedserviceselector" }} +app.kubernetes.io/name: "{{ .label }}" +{{- $partof := (get (.root.Values.commonLabels | default dict) "app.kubernetes.io/part-of" | default "")}} +{{- if $partof }} +app.kubernetes.io/part-of: "{{ $partof }}" +{{- end }} +{{- end }} + +{{/* +Checks if a service is required to be installed/upgraded +*/}} +{{- define "yugabyte.should_render_service" -}} + {{- if eq .scope "AZ" }} + {{- "true" }} + {{- else }} + {{- $namespacedService := (lookup "v1" "Service" .root.Release.Namespace .serviceName) }} + {{- if not $namespacedService }} + {{- "true" }} + {{- else }} + {{- $ownerRelease := (get $namespacedService.metadata.annotations "meta.helm.sh/release-name") | default "" }} + {{- if eq $ownerRelease .root.Release.Name }} + {{- "true" }} + {{- else }} + {{- "false" }} + {{- end }} + {{- end }} + {{- end }} +{{- end }} + +{{/* +Create secrets in DBNamespace from other namespaces by iterating over envSecrets. +*/}} +{{- define "yugabyte.envsecrets" -}} +{{- range $v := .secretenv }} +{{- if $v.valueFrom.secretKeyRef.namespace }} +{{- $secretObj := (lookup +"v1" +"Secret" +$v.valueFrom.secretKeyRef.namespace +$v.valueFrom.secretKeyRef.name) +| default dict }} +{{- $secretData := (get $secretObj "data") | default dict }} +{{- $secretValue := (get $secretData $v.valueFrom.secretKeyRef.key) | default "" }} +{{- if (and (not $secretValue) (not $v.valueFrom.secretKeyRef.optional)) }} +{{- required (printf "Secret or key missing for %s/%s in namespace: %s" +$v.valueFrom.secretKeyRef.name +$v.valueFrom.secretKeyRef.key +$v.valueFrom.secretKeyRef.namespace) +nil }} +{{- end }} +{{- if $secretValue }} +apiVersion: v1 +kind: Secret +metadata: + {{- $secretfullname := printf "%s-%s-%s-%s" + $.root.Release.Name + $v.valueFrom.secretKeyRef.namespace + $v.valueFrom.secretKeyRef.name + $v.valueFrom.secretKeyRef.key + }} + name: {{ printf "%s-%s-%s-%s-%s-%s" + $.root.Release.Name + ($v.valueFrom.secretKeyRef.namespace | substr 0 5) + ($v.valueFrom.secretKeyRef.name | substr 0 5) + ( $v.valueFrom.secretKeyRef.key | substr 0 5) + (sha256sum $secretfullname | substr 0 4) + ($.suffix) + | lower | replace "." "" | replace "_" "" + }} + namespace: "{{ $.root.Release.Namespace }}" + labels: + {{- include "yugabyte.labels" $.root | indent 4 }} +type: Opaque # should it be an Opaque secret? +data: + {{ $v.valueFrom.secretKeyRef.key }}: {{ $secretValue | quote }} +{{- end }} +{{- end }} +--- +{{- end }} +{{- end }} + +{{/* +Add env secrets to DB statefulset. +*/}} +{{- define "yugabyte.addenvsecrets" -}} +{{- range $v := .secretenv }} +- name: {{ $v.name }} + valueFrom: + secretKeyRef: + {{- if $v.valueFrom.secretKeyRef.namespace }} + {{- $secretfullname := printf "%s-%s-%s-%s" + $.root.Release.Name + $v.valueFrom.secretKeyRef.namespace + $v.valueFrom.secretKeyRef.name + $v.valueFrom.secretKeyRef.key + }} + name: {{ printf "%s-%s-%s-%s-%s-%s" + $.root.Release.Name + ($v.valueFrom.secretKeyRef.namespace | substr 0 5) + ($v.valueFrom.secretKeyRef.name | substr 0 5) + ($v.valueFrom.secretKeyRef.key | substr 0 5) + (sha256sum $secretfullname | substr 0 4) + ($.suffix) + | lower | replace "." "" | replace "_" "" + }} + {{- else }} + name: {{ $v.valueFrom.secretKeyRef.name }} + {{- end }} + key: {{ $v.valueFrom.secretKeyRef.key }} + optional: {{ $v.valueFrom.secretKeyRef.optional | default "false" }} +{{- end }} +{{- end }} +{{/* +Create Volume name. +*/}} +{{- define "yugabyte.volume_name" -}} + {{- printf "%s-datadir" (include "yugabyte.fullname" .) -}} +{{- end -}} + +{{/* +Derive the memory hard limit in bytes for Master and Tserver components based on +a given memory size and a limit percentage. + +The function expects two parameters: +1. 'size': Specifies memory in 'G' or 'Gi' format (e.g., "2Gi"). +2. 'limitPercent': An integer representing the percentage of the memory limit (e.g., 85 for 85%). + +It uses a base multiplier of 1000 for 'G' units and 1024 for 'Gi' units. +*/}} +{{- define "yugabyte.memory_hard_limit" -}} + {{- $baseMultiplier := 1000 -}} + {{- if .size | toString | hasSuffix "Gi" -}} + {{- $baseMultiplier = 1024 -}} + {{- end -}} + {{- $limit_percent := .limitPercent -}} + {{- $multiplier := int (div (mul $limit_percent $baseMultiplier) 100) -}} + {{- printf "%d" .size | regexFind "\\d+" | mul $baseMultiplier | mul $baseMultiplier | mul $multiplier -}} +{{- end -}} + +{{/* +Create chart name and version as used by the chart label. +*/}} +{{- define "yugabyte.chart" -}} + {{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" -}} +{{- end -}} + +{{/* +Generate a preflight check script invocation. +*/}} +{{- define "yugabyte.preflight_check" -}} +{{- if not .Values.preflight.skipAll -}} +{{- $port := .Preflight.Port -}} +{{- range $addr := split "," .Preflight.Addr -}} +if [ -f /home/yugabyte/tools/k8s_preflight.py ]; then + PYTHONUNBUFFERED="true" /home/yugabyte/tools/k8s_preflight.py \ + dnscheck \ + --addr="{{ $addr }}" \ +{{- if not $.Values.preflight.skipBind }} + --port="{{ $port }}" +{{- else }} + --skip_bind +{{- end }} +fi && \ +{{ end }} +{{- end }} +{{- end }} + +{{/* +Get YugaByte fs data directories. +*/}} +{{- define "yugabyte.fs_data_dirs" -}} + {{- range $index := until (int (.count)) -}} + {{- if ne $index 0 }},{{ end }}/mnt/disk{{ $index -}} + {{- end -}} +{{- end -}} + +{{/* +Get files from fs data directories for readiness / liveness probes. +*/}} +{{- define "yugabyte.fs_data_dirs_probe_files" -}} + {{- range $index := until (int (.count)) -}} + {{- if ne $index 0 }} {{ end }}"/mnt/disk{{ $index -}}/disk.check" + {{- end -}} +{{- end -}} + + +{{/* +Command to do a disk write and sync for liveness probes. +*/}} +{{- define "yugabyte.fs_data_dirs_probe" -}} +echo "disk check at: $(date)" \ + | tee {{ template "yugabyte.fs_data_dirs_probe_files" . }} \ + && sync {{ template "yugabyte.fs_data_dirs_probe_files" . }} +{{- end -}} + + +{{/* +Generate server FQDN. +*/}} +{{- define "yugabyte.server_fqdn" -}} + {{- if .Values.multicluster.createServicePerPod -}} + {{- printf "${HOSTNAME}.${NAMESPACE}.svc.%s" .Values.domainName -}} + {{- else if (and .Values.oldNamingStyle .Values.multicluster.createServiceExports) -}} + {{ $membershipName := required "A valid membership name is required! Please set multicluster.kubernetesClusterId" .Values.multicluster.kubernetesClusterId }} + {{- printf "${HOSTNAME}.%s.%s.${NAMESPACE}.svc.clusterset.local" $membershipName .Service.name -}} + {{- else if .Values.oldNamingStyle -}} + {{- printf "${HOSTNAME}.%s.${NAMESPACE}.svc.%s" .Service.name .Values.domainName -}} + {{- else -}} + {{- if .Values.multicluster.createServiceExports -}} + {{ $membershipName := required "A valid membership name is required! Please set multicluster.kubernetesClusterId" .Values.multicluster.kubernetesClusterId }} + {{- printf "${HOSTNAME}.%s.%s-%s.${NAMESPACE}.svc.clusterset.local" $membershipName (include "yugabyte.fullname" .) .Service.name -}} + {{- else -}} + {{- printf "${HOSTNAME}.%s-%s.${NAMESPACE}.svc.%s" (include "yugabyte.fullname" .) .Service.name .Values.domainName -}} + {{- end -}} + {{- end -}} +{{- end -}} + +{{/* +Generate server broadcast address. +*/}} +{{- define "yugabyte.server_broadcast_address" -}} + {{- include "yugabyte.server_fqdn" . }}:{{ index .Service.ports "tcp-rpc-port" -}} +{{- end -}} + +{{/* +Generate server RPC bind address. + +In case of multi-cluster services (MCS), we set it to ${POD_IP} to +ensure YCQL uses a resolvable address. +See https://github.com/yugabyte/yugabyte-db/issues/16155 + +We use a workaround for above in case of Istio by setting it to +${POD_IP} and localhost. Master doesn't support that combination, so +we stick to 0.0.0.0, which works for master. +*/}} +{{- define "yugabyte.rpc_bind_address" -}} + {{- $port := index .Service.ports "tcp-rpc-port" -}} + {{- if .Values.istioCompatibility.enabled -}} + {{- if (eq .Service.name "yb-masters") -}} + 0.0.0.0:{{ $port }} + {{- else -}} + ${POD_IP}:{{ $port }},127.0.0.1:{{ $port }} + {{- end -}} + {{- else if (or .Values.multicluster.createServiceExports .Values.multicluster.createServicePerPod) -}} + ${POD_IP}:{{ $port }} + {{- else -}} + {{- include "yugabyte.server_fqdn" . -}} + {{- end -}} +{{- end -}} + +{{/* +Generate server web interface. +*/}} +{{- define "yugabyte.webserver_interface" -}} + {{- eq .Values.ip_version_support "v6_only" | ternary "[::]" "0.0.0.0" -}} +{{- end -}} + +{{/* +Generate server CQL proxy bind address. +*/}} +{{- define "yugabyte.cql_proxy_bind_address" -}} + {{- eq .Values.ip_version_support "v6_only" | ternary "[::]" "0.0.0.0" -}}:{{ index .Service.ports "tcp-yql-port" -}} +{{- end -}} + +{{/* +Generate server PGSQL proxy bind address. +*/}} +{{- define "yugabyte.pgsql_proxy_bind_address" -}} + {{- eq .Values.ip_version_support "v6_only" | ternary "[::]" "0.0.0.0" -}}:{{ index .Service.ports "tcp-ysql-port" -}} +{{- end -}} + +{{/* +Get YugaByte master addresses. +Usage: {{ include "yugabyte.master_addresses" (dict "root" $root "vars" $masterStsVars) }} + - root: the chart root context (.) + - vars: the result of "yugabyte.stsIndexVars" for the "yb-masters" service +*/}} +{{- define "yugabyte.master_addresses" -}} + {{- $root := .root -}} + {{- $vars := .vars -}} + {{- $domain_name := $root.Values.domainName -}} + {{- $newNamingStylePrefix := printf "%s-" (include "yugabyte.fullname" $root) -}} + {{- $prefix := ternary "" $newNamingStylePrefix $root.Values.oldNamingStyle -}} + {{- $addrs := list -}} + {{- range $stsIdx := until (int $vars.stsCount) -}} + {{- $loopVars := include "yugabyte.stsIndexLoopVars" (dict "stsIdx" $stsIdx "stsStart" $vars.stsStart "stsEnd" $vars.stsEnd "replicas" $vars.replicas "moveOpReplicas" $vars.moveOpReplicas) | fromYaml -}} + {{- $stsIndexSuffix := $loopVars.stsIndexSuffix -}} + {{- $currentReplicas := $loopVars.currentReplicas | int -}} + {{- range $index := until $currentReplicas -}} + {{- $addr := "" -}} + {{- if eq $root.Values.multicluster.kubernetesClusterId "" -}} + {{- $addr = printf "%syb-master%s-%d.%syb-masters.${NAMESPACE}.svc.%s:7100" $prefix $stsIndexSuffix $index $prefix $domain_name -}} + {{- else -}} + {{- $addr = printf "%syb-master%s-%d.%s.%syb-masters.${NAMESPACE}.svc.%s:7100" $prefix $stsIndexSuffix $index $root.Values.multicluster.kubernetesClusterId $prefix $domain_name -}} + {{- end -}} + {{- $addrs = append $addrs $addr -}} + {{- end -}} + {{- end -}} + {{- join "," $addrs -}} +{{- end -}} + +{{/* +Compute the maximum number of unavailable pods based on the number of master replicas +*/}} +{{- define "yugabyte.max_unavailable_for_quorum" -}} + {{- $master_replicas_100x := .Values.replicas.master | int | mul 100 -}} + {{- $max_unavailable_master_replicas := 100 | div (100 | sub (2 | div ($master_replicas_100x | add 100))) -}} + {{- printf "%d" $max_unavailable_master_replicas -}} +{{- end -}} + +{{/* +Set consistent issuer name. +*/}} +{{- define "yugabyte.tls_cm_issuer" -}} + {{- if .Values.tls.certManager.bootstrapSelfsigned -}} + {{ .Values.oldNamingStyle | ternary "yugabyte-selfsigned" (printf "%s-selfsigned" (include "yugabyte.fullname" .)) }} + {{- else -}} + {{- if .Values.tls.certManager.useCustomIssuer -}} + {{ .Values.tls.certManager.customIssuer.name }} + {{- else -}} + {{ .Values.tls.certManager.useClusterIssuer | ternary .Values.tls.certManager.clusterIssuer .Values.tls.certManager.issuer }} + {{- end -}} + {{- end -}} +{{- end -}} + +{{/* +Set issuer kind. +*/}} +{{- define "yugabyte.tls_issuer_kind" -}} + {{- if .Values.tls.certManager.useCustomIssuer -}} + {{ .Values.tls.certManager.customIssuer.kind }} + {{- else -}} + {{ .Values.tls.certManager.useClusterIssuer | ternary "ClusterIssuer" "Issuer" }} + {{- end -}} +{{- end -}} + +{{/* +Set issuer group. +*/}} +{{- define "yugabyte.tls_issuer_group" -}} + {{- if .Values.tls.certManager.useCustomIssuer -}} + {{ .Values.tls.certManager.customIssuer.group | default "cert-manager.io" }} + {{- else -}} + {{ "" }} + {{- end -}} +{{- end -}} + +{{/* + Verify the extraVolumes and extraVolumeMounts mappings. + Every extraVolumes should have extraVolumeMounts +*/}} +{{- define "yugabyte.isExtraVolumesMappingExists" -}} + {{- $lenExtraVolumes := len .extraVolumes -}} + {{- $lenExtraVolumeMounts := len .extraVolumeMounts -}} + + {{- if and (eq $lenExtraVolumeMounts 0) (gt $lenExtraVolumes 0) -}} + {{- fail "You have not provided the extraVolumeMounts for extraVolumes." -}} + {{- else if and (eq $lenExtraVolumes 0) (gt $lenExtraVolumeMounts 0) -}} + {{- fail "You have not provided the extraVolumes for extraVolumeMounts." -}} + {{- else if and (gt $lenExtraVolumes 0) (gt $lenExtraVolumeMounts 0) -}} + {{- $volumeMountsList := list -}} + {{- range .extraVolumeMounts -}} + {{- $volumeMountsList = append $volumeMountsList .name -}} + {{- end -}} + + {{- $volumesList := list -}} + {{- range .extraVolumes -}} + {{- $volumesList = append $volumesList .name -}} + {{- end -}} + + {{- range $volumesList -}} + {{- if not (has . $volumeMountsList) -}} + {{- fail (printf "You have not provided the extraVolumeMounts for extraVolume %s" .) -}} + {{- end -}} + {{- end -}} + + {{- range $volumeMountsList -}} + {{- if not (has . $volumesList) -}} + {{- fail (printf "You have not provided the extraVolumes for extraVolumeMounts %s" .) -}} + {{- end -}} + {{- end -}} + {{- end -}} +{{- end -}} + +{{/* + Default nodeAffinity for multi-az deployments +*/}} +{{- define "yugabyte.multiAZNodeAffinity" -}} +requiredDuringSchedulingIgnoredDuringExecution: + nodeSelectorTerms: + - matchExpressions: + - key: failure-domain.beta.kubernetes.io/zone + operator: In + values: + - {{ quote .Values.AZ }} + - matchExpressions: + - key: topology.kubernetes.io/zone + operator: In + values: + - {{ quote .Values.AZ }} +{{- end -}} + +{{/* + Default podAntiAffinity for master and tserver + + This requires "appLabelArgs" to be passed in - defined in service.yaml + we have a .root and a .label in appLabelArgs +*/}} +{{- define "yugabyte.podAntiAffinity" -}} +preferredDuringSchedulingIgnoredDuringExecution: +- weight: 100 + podAffinityTerm: + labelSelector: + matchExpressions: + {{- if .root.Values.oldNamingStyle }} + - key: app + operator: In + values: + - "{{ .label }}" + {{- else }} + - key: app.kubernetes.io/name + operator: In + values: + - "{{ .label }}" + - key: release + operator: In + values: + - {{ .root.Release.Name | quote }} + {{- end }} + topologyKey: kubernetes.io/hostname +{{- end -}} + +{{/* + YB Master ports +*/}} +{{- define "yugabyte.yb_masters.ports" -}} +{{- $masterPorts := dict -}} +{{- range .Values.Services -}} + {{- if eq .name "yb-masters" -}} + {{- range $key, $value := .ports -}} + {{- $masterPorts = set $masterPorts $key $value -}} + {{- end -}} + {{- end -}} +{{- end -}} +{{- toYaml $masterPorts -}} +{{- end -}} + +{{/* + Readiness Probe for Master +*/}} +{{- define "yugabyte.master.readinessProbe" -}} +{{- if .Values.master.customReadinessProbe -}} +{{- toYaml .Values.master.customReadinessProbe }} +{{- else if .Values.master.readinessProbe.enabled -}} +{{- toYaml (omit .Values.master.readinessProbe "enabled") }} +httpGet: + path: / + port: {{ index (include "yugabyte.yb_masters.ports" .| fromYaml) "http-ui" }} +{{- end -}} +{{- end -}} + +{{/* + YB Tservers ports +*/}} +{{- define "yugabyte.yb_tservers.ports" -}} +{{- $tserverPorts := dict -}} +{{- range .Values.Services }} + {{- if eq .name "yb-tservers" }} + {{- range $key, $value := .ports }} + {{- $tserverPorts = set $tserverPorts $key $value }} + {{- end }} + {{- end }} +{{- end }} +{{- toYaml $tserverPorts -}} +{{- end -}} + +{{/* + Readiness Probe for Tserver + Use ".Values.authCredentials.ysql.password" while setting ysql credentials through YB DB values.yaml + Use ".Values.gflags.tserver.ysql_enable_auth" while setting ysql credentials through YBA +*/}} +{{- define "yugabyte.tserver.readinessProbe" -}} +{{- if .Values.tserver.customReadinessProbe -}} +{{- toYaml .Values.tserver.customReadinessProbe }} +{{- else if .Values.tserver.readinessProbe.enabled -}} +{{- toYaml (omit .Values.tserver.readinessProbe "enabled") }} +exec: + command: + - bash + - -v + - -c + - | + {{- if not .Values.disableYsql }} + {{- if (or .Values.authCredentials.ysql.password (eq .Values.gflags.tserver.ysql_enable_auth "true") .Values.authCredentials.ysql.passwordSecretName) }} + unix_socket=$(find /tmp -name ".yb.*"); + ysqlsh_output=$(ysqlsh -U yugabyte -h "${unix_socket}" -d system_platform -c "\\conninfo"); + exit_code="$?"; + {{- else }} + ysqlsh_output=$(ysqlsh -U yugabyte -h 127.0.0.1 -p {{ index (include "yugabyte.yb_tservers.ports" . | fromYaml) "tcp-ysql-port" }} -d system_platform -c "\\conninfo"); + exit_code="$?"; + {{- end }} + + if [[ $exit_code -ne 0 ]]; then + echo "Error while executing ysqlsh command. Exit code: ${exit_code}"; + echo "Error: ${ysqlsh_output}"; + exit "${exit_code}" + fi + {{- end }} + + {{- if not (eq .Values.gflags.tserver.start_cql_proxy "false") }} + {{- if (and .Values.tls.enabled .Values.tls.clientToServer) }} + ycqlsh_output=$(ycqlsh --debug --ssl -e "SHOW HOST" "$HOSTNAME" {{ index (include "yugabyte.yb_tservers.ports" . | fromYaml) "tcp-yql-port" }} 2>&1); + {{- else }} + ycqlsh_output=$(ycqlsh --debug -e "SHOW HOST" "$HOSTNAME" {{ index (include "yugabyte.yb_tservers.ports" . | fromYaml) "tcp-yql-port" }} 2>&1); + {{- end }} + exit_code="$?"; + + if [[ $exit_code -ne 0 && "${ycqlsh_output}" != *"Remote end requires authentication"* ]]; then + echo "Error while executing ycqlsh command. Exit code: ${exit_code}"; + echo "Error: ${ycqlsh_output}"; + exit "${exit_code}" + fi + {{- end }} + + exit 0 +{{- end -}} +{{- end -}} + +{{/* + Startup Probe for Master +*/}} +{{- define "yugabyte.master.startupProbe" -}} +{{- if .Values.master.customStartupProbe -}} +{{- toYaml .Values.master.customStartupProbe }} +{{- else if .Values.master.startupProbe.enabled -}} +{{- toYaml (omit .Values.master.startupProbe "enabled") }} +tcpSocket: + port: {{ index (include "yugabyte.yb_masters.ports" .| fromYaml) "tcp-rpc-port" }} +{{- end -}} +{{- end -}} + +{{/* + Startup Probe for Tserver +*/}} +{{- define "yugabyte.tserver.startupProbe" -}} +{{- if .Values.tserver.customStartupProbe -}} +{{- toYaml .Values.tserver.customStartupProbe }} +{{- else if .Values.tserver.startupProbe.enabled -}} +{{- toYaml (omit .Values.tserver.startupProbe "enabled") }} +tcpSocket: + port: {{ index (include "yugabyte.yb_tservers.ports" .| fromYaml) "tcp-rpc-port" }} +{{- end -}} +{{- end -}} + +{{/* + Get Security Context. +*/}} +{{- define "getSecurityContext" }} +securityContext: + runAsUser: {{ required "runAsUser cannot be empty" .Values.containerSecurityContext.runAsUser }} + {{- if ne .Values.containerSecurityContext.runAsGroup nil }} + runAsGroup: {{ .Values.containerSecurityContext.runAsGroup }} + {{- else }} + runAsGroup: {{ .Values.containerSecurityContext.runAsUser }} + {{- end }} + runAsNonRoot: {{ .Values.containerSecurityContext.runAsNonRoot }} + {{- if .Values.containerSecurityContext.additionalSettings }} +{{ toYaml .Values.containerSecurityContext.additionalSettings | indent 2}} + {{- end }} +{{- end -}} + +{{/* +Get ipFamily and ipFamilyPolicy settings. +*/}} +{{- define "yugabyte.ipFamilyConfig" }} +{{- if .Values.ipFamilies }} +ipFamilies: + {{- range .Values.ipFamilies }} + - {{ . }} + {{- end }} +{{- end }} +{{- if .Values.ipFamilyPolicy }} +ipFamilyPolicy: {{ .Values.ipFamilyPolicy }} +{{- end }} +{{- end -}} + +{{/* + Append commonNameSuffix to commonName while ensuring total length doesn't exceed 63 characters. +*/}} +{{- define "yugabyte.commonNameWithSuffix" -}} + {{- $commonName := .commonName -}} + {{- $suffix := .root.Values.tls.certManager.certificates.commonNameSuffix | default "" -}} + {{- if $suffix -}} + {{- $combined := printf "%s-%s" $commonName $suffix -}} + {{- if gt (len $combined) 63 -}} + {{- $maxCommonNameLength := sub 63 (add 1 (len $suffix)) -}} + {{- printf "%s-%s" ($commonName | trunc $maxCommonNameLength | trimSuffix "-") $suffix -}} + {{- else -}} + {{- $combined -}} + {{- end -}} + {{- else -}} + {{- $commonName -}} + {{- end -}} +{{- end -}} + +{{/* + Validate stsIndex start and end values for master and tserver. + Rules: + 1. end must be >= start (except for the wrap-around case: start=9, end=0) + 2. If start != end (move operation in progress), end - start must be exactly 1, except for the wrap-around case + 3. start == end is valid (no move operation) + + Usage: + {{- include "yugabyte.validateStsIndex" (dict "start" ($root.Values.stsIndex.master.start | int) "end" ($root.Values.stsIndex.master.end | int) "component" "master") -}} + {{- include "yugabyte.validateStsIndex" (dict "start" ($root.Values.stsIndex.tserver.start | int) "end" ($root.Values.stsIndex.tserver.end | int) "component" "tserver") -}} +*/}} +{{- define "yugabyte.validateStsIndex" -}} + {{- $start := .start | int -}} + {{- $end := .end | int -}} + {{- $component := .component -}} + + {{- $isWrapAround := and (eq $start 9) (eq $end 0) -}} + {{- $diff := sub $end $start -}} + {{- $isMoveOp := ne $start $end -}} + + {{- /* Check: end >= start (except wrap-around case) */ -}} + {{- if and (not $isWrapAround) (lt $end $start) -}} + {{- fail (printf "stsIndex.%s: end (%d) must be >= start (%d), except for the wrap-around case (start=9, end=0)" $component $end $start) -}} + {{- end -}} + + {{- /* Check: if move operation (start != end), end - start must be exactly 1 (except wrap-around case) */ -}} + {{- if and $isMoveOp (not $isWrapAround) (ne $diff 1) -}} + {{- fail (printf "stsIndex.%s: end (%d) and start (%d) must differ by exactly one when start != end, except for the wrap-around case (start=9, end=0)" $component $end $start) -}} + {{- end -}} +{{- end -}} + +{{/* +Get storage info based on service type and move operation state. +Returns the storage dict object as YAML. +Usage: + {{- $storageInfo := include "yugabyte.storageInfo" (dict "serviceName" $service.name "useMoveOp" $useMoveOp "root" $root) | fromYaml -}} +*/}} +{{- define "yugabyte.storageInfo" -}} + {{- $serviceName := .serviceName -}} + {{- $useMoveOp := .useMoveOp -}} + {{- $root := .root -}} + {{- if eq $serviceName "yb-masters" -}} + {{- if $useMoveOp -}} + {{- $root.Values.moveOp.storage.master | toYaml -}} + {{- else -}} + {{- $root.Values.storage.master | toYaml -}} + {{- end -}} + {{- else -}} + {{- if $useMoveOp -}} + {{- $root.Values.moveOp.storage.tserver | toYaml -}} + {{- else -}} + {{- $root.Values.storage.tserver | toYaml -}} + {{- end -}} + {{- end -}} +{{- end -}} + +{{/* +Get stsIndex variables for a service (master or tserver). +Returns a YAML dict with: stsStart, stsEnd, stsCount, replicas, moveOpReplicas, hasMoveOp +Usage: {{- $vars := include "yugabyte.stsIndexVars" (dict "serviceName" "yb-masters" "root" $root) | fromYaml -}} +*/}} +{{- define "yugabyte.stsIndexVars" -}} + {{- $serviceName := .serviceName -}} + {{- $root := .root -}} + {{- $isMaster := eq $serviceName "yb-masters" -}} + {{- $stsStart := ($isMaster | ternary $root.Values.stsIndex.master.start $root.Values.stsIndex.tserver.start) | int -}} + {{- $stsEnd := ($isMaster | ternary $root.Values.stsIndex.master.end $root.Values.stsIndex.tserver.end) | int -}} + {{- $stsCount := (add (mod (add (sub $stsEnd $stsStart) 10) 10) 1 | int) -}} + {{- $replicas := ($isMaster | ternary $root.Values.replicas.master $root.Values.replicas.tserver) | int -}} + {{- $moveOpReplicas := ($isMaster | ternary $root.Values.moveOp.replicas.master $root.Values.moveOp.replicas.tserver) | int -}} + {{- $hasMoveOp := ne $stsStart $stsEnd -}} +stsStart: {{ $stsStart }} +stsEnd: {{ $stsEnd }} +stsCount: {{ $stsCount }} +replicas: {{ $replicas }} +moveOpReplicas: {{ $moveOpReplicas }} +hasMoveOp: {{ $hasMoveOp }} +{{- end -}} + +{{/* +Get stsIndex loop variables for a specific iteration. +Returns a YAML dict with: currentStsIndex, useMoveOp, stsIndexSuffix, currentReplicas +Usage: {{- $loopVars := include "yugabyte.stsIndexLoopVars" (dict "stsIdx" $stsIdx "stsStart" $vars.stsStart "stsEnd" $vars.stsEnd "replicas" $vars.replicas "moveOpReplicas" $vars.moveOpReplicas) | fromYaml -}} +Note: The helper function casts all input values to int internally, so no casting is needed when passing values. +*/}} +{{- define "yugabyte.stsIndexLoopVars" -}} + {{- $stsIdx := .stsIdx | int -}} + {{- $stsStart := .stsStart | int -}} + {{- $stsEnd := .stsEnd | int -}} + {{- $replicas := .replicas | int -}} + {{- $moveOpReplicas := .moveOpReplicas | int -}} + {{- $currentStsIndex := mod (add $stsStart $stsIdx) 10 | int -}} + {{- $useMoveOp := and (ne $stsStart $stsEnd) (eq $currentStsIndex $stsEnd) -}} + {{- $stsIndexSuffix := eq $currentStsIndex 0 | ternary "" (printf "-%d" $currentStsIndex) -}} + {{- $currentReplicas := $useMoveOp | ternary $moveOpReplicas $replicas | int -}} +currentStsIndex: {{ $currentStsIndex }} +useMoveOp: {{ $useMoveOp }} +stsIndexSuffix: {{ $stsIndexSuffix | quote }} +currentReplicas: {{ $currentReplicas }} +{{- end -}} diff --git a/helm-charts/yugabyte/templates/certificates.yaml b/helm-charts/yugabyte/templates/certificates.yaml new file mode 100644 index 0000000..602b619 --- /dev/null +++ b/helm-charts/yugabyte/templates/certificates.yaml @@ -0,0 +1,190 @@ +{{- $root := . -}} +--- +{{- if $root.Values.tls.certManager.enabled }} +{{- if $root.Values.tls.certManager.bootstrapSelfsigned }} +--- +{{ $appLabelArgs := dict "label" "yugabyte" "root" $root }} +apiVersion: cert-manager.io/v1 +kind: Issuer +metadata: + name: {{ (printf "%s-bootstrap" (include "yugabyte.tls_cm_issuer" $root)) | quote }} + namespace: "{{ $root.Release.Namespace }}" + labels: + {{- include "yugabyte.applabel" ($appLabelArgs) | indent 4 }} + {{- include "yugabyte.labels" $root | indent 4 }} +spec: + selfSigned: {} +--- +{{ $appLabelArgs := dict "label" "yugabyte" "root" $root }} +apiVersion: cert-manager.io/v1 +kind: Certificate +metadata: + name: {{ $root.Values.oldNamingStyle | ternary "yugabyte-ca" (printf "%s-ca" (include "yugabyte.fullname" $root)) }} + namespace: "{{ $root.Release.Namespace }}" + labels: + {{- include "yugabyte.applabel" ($appLabelArgs) | indent 4 }} + {{- include "yugabyte.labels" $root | indent 4 }} +spec: + isCA: true + privateKey: + algorithm: {{ $root.Values.tls.certManager.certificates.algorithm | quote }} + encoding: PKCS8 + size: {{ $root.Values.tls.certManager.certificates.keySize }} + commonName: Yugabyte Selfsigned CA + secretName: {{ $root.Values.oldNamingStyle | ternary "yugabyte-ca" (printf "%s-ca" (include "yugabyte.fullname" $root)) }} + issuerRef: + name: {{ (printf "%s-bootstrap" (include "yugabyte.tls_cm_issuer" $root)) | quote }} + kind: Issuer +--- +{{ $appLabelArgs := dict "label" "yugabyte" "root" $root }} +apiVersion: cert-manager.io/v1 +kind: Issuer +metadata: + name: {{ include "yugabyte.tls_cm_issuer" $root | quote }} + namespace: "{{ $root.Release.Namespace }}" + labels: + {{- include "yugabyte.applabel" ($appLabelArgs) | indent 4 }} + {{- include "yugabyte.labels" $root | indent 4 }} +spec: + ca: + secretName: {{ $root.Values.oldNamingStyle | ternary "yugabyte-ca" (printf "%s-ca" (include "yugabyte.fullname" $root)) }} +--- +{{- else }} +{{/* when bootstrapSelfsigned = false, ie. when using an external CA. +Create a Secret with just the rootCA.cert value and mount into master/tserver pods. +This will be used as a fall back in case the Secret generated by cert-manager does not +have a root ca.crt. This can happen for certain certificate issuers like LetsEncrypt. +*/}} +--- +{{ $appLabelArgs := dict "label" "yugabyte" "root" $root }} +apiVersion: v1 +kind: Secret +metadata: + name: {{ printf "%s-root-ca" (include "yugabyte.fullname" $root) }} + namespace: "{{ $root.Release.Namespace }}" + labels: + {{- include "yugabyte.applabel" ($appLabelArgs) | indent 4 }} + {{- include "yugabyte.labels" $root | indent 4 }} +type: Opaque +data: + ca.crt: {{ $root.Values.tls.rootCA.cert }} + {{/* if useExistingServerCertificate is true, then tls.crt and tls.key will not be set */}} + {{if $root.Values.tls.certManager.useExistingServerCertificate -}} + tls.crt: "" + tls.key: "" + {{- end }} +--- +{{- end }} + + +{{/* +The below Certificate resource will trigger cert-manager to issue crt/key into Secrets. +These secrets are mounted into master/tserver pods. +*/}} +{{- range .Values.Services }} +{{- $service := . -}} +{{- $appLabelArgs := dict "label" .label "root" $root -}} +{{- $serviceValues := (dict "Service" $service "Values" $root.Values "Chart" $root.Chart "Release" $root.Release) -}} +{{- $vars := include "yugabyte.stsIndexVars" (dict "serviceName" .name "root" $root) | fromYaml -}} +{{- range $stsIdx := until (int $vars.stsCount) }} +{{- $loopVars := include "yugabyte.stsIndexLoopVars" (dict "stsIdx" $stsIdx "stsStart" $vars.stsStart "stsEnd" $vars.stsEnd "replicas" $vars.replicas "moveOpReplicas" $vars.moveOpReplicas) | fromYaml -}} +{{- $currentStsIndex := $loopVars.currentStsIndex -}} +{{- $useMoveOp := $loopVars.useMoveOp -}} +{{- $stsIndexSuffix := $loopVars.stsIndexSuffix -}} +{{- $currentReplicas := $loopVars.currentReplicas }} +{{- if gt (int $currentReplicas) 0 }} +--- +apiVersion: cert-manager.io/v1 +kind: Certificate +metadata: + name: {{ $root.Values.oldNamingStyle | ternary (printf "%s%s-yugabyte-tls-cert" $service.label $stsIndexSuffix) (printf "%s-%s%s-tls-cert" (include "yugabyte.fullname" $root) $service.label $stsIndexSuffix) }} + namespace: "{{ $root.Release.Namespace }}" + labels: + {{- include "yugabyte.applabel" ($appLabelArgs) | indent 4 }} + {{- include "yugabyte.labels" $root | indent 4 }} +spec: + secretTemplate: + labels: + {{- include "yugabyte.applabel" ($appLabelArgs) | indent 6 }} + {{- include "yugabyte.labels" $root | indent 6 }} + issuerRef: + name: {{ include "yugabyte.tls_cm_issuer" $root | quote }} + kind: {{ include "yugabyte.tls_issuer_kind" $root }} + group: {{ include "yugabyte.tls_issuer_group" $root }} + secretName: {{ $root.Values.oldNamingStyle | ternary (printf "%s%s-yugabyte-tls-cert" $service.label $stsIndexSuffix) (printf "%s-%s%s-tls-cert" (include "yugabyte.fullname" $root) $service.label $stsIndexSuffix) }} + duration: {{ $root.Values.tls.certManager.certificates.duration | quote }} + renewBefore: {{ $root.Values.tls.certManager.certificates.renewBefore | quote }} + isCA: false + privateKey: + algorithm: {{ $root.Values.tls.certManager.certificates.algorithm | quote }} + encoding: PKCS8 + size: {{ $root.Values.tls.certManager.certificates.keySize }} + rotationPolicy: Always + usages: + - server auth + - client auth + # At least one of a DNS Name, URI, or IP address is required. + dnsNames: + {{- range $index := until ( int ( $currentReplicas ) ) }} + {{- $nodeOldStyle := printf "%s%s-%d.%s.%s.svc.%s" $service.label $stsIndexSuffix $index $service.name $root.Release.Namespace $root.Values.domainName }} + {{- $nodeNewStyle := printf "%s-%s%s-%d.%s-%s.%s.svc.%s" (include "yugabyte.fullname" $root) $service.label $stsIndexSuffix $index (include "yugabyte.fullname" $root) $service.name $root.Release.Namespace $root.Values.domainName }} + + {{- if $root.Values.multicluster.createServiceExports -}} + {{- $nodeOldStyle = printf "%s%s-%d.%s.%s.%s.svc.clusterset.local" $service.label $stsIndexSuffix $index $root.Values.multicluster.kubernetesClusterId $service.name $root.Release.Namespace }} + {{- $nodeNewStyle = printf "%s-%s%s-%d.%s.%s-%s.%s.svc.clusterset.local" (include "yugabyte.fullname" $root) $service.label $stsIndexSuffix $index $root.Values.multicluster.kubernetesClusterId (include "yugabyte.fullname" $root) $service.name $root.Release.Namespace }} + {{- end -}} + + {{- if $root.Values.multicluster.createServicePerPod -}} + {{- $nodeOldStyle = printf "%s%s-%d.%s.svc.%s" $service.label $stsIndexSuffix $index $root.Release.Namespace $root.Values.domainName }} + {{- $nodeNewStyle = printf "%s-%s%s-%d.%s.svc.%s" (include "yugabyte.fullname" $root) $service.label $stsIndexSuffix $index $root.Release.Namespace $root.Values.domainName }} + {{- end -}} + {{- $node := $root.Values.oldNamingStyle | ternary $nodeOldStyle $nodeNewStyle }} + - {{$node}} + {{- end }} + - {{ printf "%s-%s%s.%s.svc.%s" (include "yugabyte.fullname" $root) $service.name $stsIndexSuffix $root.Release.Namespace $root.Values.domainName }} + uris: [] + ipAddresses: [] + {{- if $root.Values.tls.certManager.certificates.commonNameRequired }} + commonName: {{ include "yugabyte.commonNameWithSuffix" (dict "commonName" ($root.Values.oldNamingStyle | ternary $service.name (printf "%s-%s" (include "yugabyte.fullname" $root) $service.name)) "root" $root) | quote }} + {{- end }} +--- +{{- end }} +{{- end }} +{{- end }} + +--- +{{ $appLabelArgs := dict "label" "yugabyte" "root" $root }} +apiVersion: cert-manager.io/v1 +kind: Certificate +metadata: + name: {{ $root.Values.oldNamingStyle | ternary "yugabyte-tls-client-cert" (printf "%s-client-tls" (include "yugabyte.fullname" $root)) }} + namespace: "{{ $root.Release.Namespace }}" + labels: + {{- include "yugabyte.applabel" ($appLabelArgs) | indent 4 }} + {{- include "yugabyte.labels" $root | indent 4 }} +spec: + secretTemplate: + labels: + {{- include "yugabyte.applabel" ($appLabelArgs) | indent 6 }} + {{- include "yugabyte.labels" $root | indent 6 }} + issuerRef: + name: {{ include "yugabyte.tls_cm_issuer" $root | quote }} + kind: {{ include "yugabyte.tls_issuer_kind" $root }} + group: {{ include "yugabyte.tls_issuer_group" $root }} + secretName: {{ $root.Values.oldNamingStyle | ternary "yugabyte-tls-client-cert" (printf "%s-client-tls" (include "yugabyte.fullname" $root)) }} + duration: {{ $root.Values.tls.certManager.certificates.duration | quote }} + renewBefore: {{ $root.Values.tls.certManager.certificates.renewBefore | quote }} + commonName: {{ include "yugabyte.commonNameWithSuffix" (dict "commonName" "yugabyte" "root" $root) | quote }} + isCA: false + privateKey: + algorithm: {{ $root.Values.tls.certManager.certificates.algorithm | quote }} + encoding: PKCS8 + size: {{ $root.Values.tls.certManager.certificates.keySize }} + rotationPolicy: Always + usages: + - client auth + dnsNames: [] + uris: [] + ipAddresses: [] +--- +{{- end }} diff --git a/helm-charts/yugabyte/templates/controller-gflags-secret.yaml b/helm-charts/yugabyte/templates/controller-gflags-secret.yaml new file mode 100644 index 0000000..afbc6c5 --- /dev/null +++ b/helm-charts/yugabyte/templates/controller-gflags-secret.yaml @@ -0,0 +1,40 @@ +{{- $root := . -}} +{{- range $service := $root.Values.Services }} +{{- if and (eq $service.name "yb-tservers") (and ($root.Values.ybc.enabled) ($root.Values.ybc.useYBDBImage)) }} +{{- $serviceValues := (dict "Service" $service "Values" $root.Values "Chart" $root.Chart "Release" $root.Release) -}} +{{- $appLabelArgs := dict "label" $service.label "root" $root -}} +--- +apiVersion: v1 +kind: Secret +metadata: + name: {{ include "yugabyte.fullname" $root }}-controller-gflags + namespace: "{{ $root.Release.Namespace }}" + labels: + {{- include "yugabyte.applabel" ($appLabelArgs) | indent 4 }} + {{- include "yugabyte.labels" $root | indent 4 }} +type: Opaque +stringData: + server.conf.template: | + --v=1 + --server_address={{ (eq $root.Values.ip_version_support "v6_only") | ternary "[::]" "0.0.0.0" }} + --server_port={{ index $service.ports "tcp-ybc-port" }} + --log_dir=/mnt/disk0/ybc-data/controller/logs + --yb_tserver_address={{ include "yugabyte.rpc_bind_address" $serviceValues }} + --yb_tserver_webserver_port={{ index $service.ports "http-ui" }} + --yb_admin=/home/yugabyte/tserver/bin/yb-admin + --ysql_dump=/home/yugabyte/tserver/postgres/bin/ysql_dump + --ysql_dumpall=/home/yugabyte/tserver/postgres/bin/ysql_dumpall + --ysqlsh=/home/yugabyte/tserver/postgres/bin/ysqlsh + --ycqlsh=/home/yugabyte/tserver/bin/ycqlsh + --log_filename=yb-controller-server + --log_utc_time=true +{{- if and $root.Values.tls.enabled $root.Values.tls.nodeToNode }} + --certs_dir_name=/opt/certs/yugabyte + --cert_node_filename={{ $root.Values.tserver.serverBroadcastAddress | default (include "yugabyte.server_fqdn" $serviceValues) }} +{{- end }} +{{- range $flag, $override := $root.Values.gflags.ybc }} + --{{ $flag }}={{ $override }} +{{- end }} +--- +{{- end }} +{{- end }} diff --git a/helm-charts/yugabyte/templates/debug_config_map.yaml b/helm-charts/yugabyte/templates/debug_config_map.yaml new file mode 100644 index 0000000..03812cc --- /dev/null +++ b/helm-charts/yugabyte/templates/debug_config_map.yaml @@ -0,0 +1,46 @@ +{{- $root := . -}} +{{- $stsTsStart := int $root.Values.stsIndex.tserver.start -}} +{{- $stsTsEnd := int $root.Values.stsIndex.tserver.end -}} +{{- $stsMasterStart := int $root.Values.stsIndex.master.start -}} +{{- $stsMasterEnd := int $root.Values.stsIndex.master.end -}} +{{- $hasMoveOpMaster := ne $stsMasterStart $stsMasterEnd -}} +{{- $hasMoveOpTserver := ne $stsTsStart $stsTsEnd -}} +{{- $masterReplicas := $root.Values.replicas.master -}} +{{- $masterMoveOpReplicas := $root.Values.moveOp.replicas.master -}} +{{- $tserverReplicas := $root.Values.replicas.tserver -}} +{{- $tserverMoveOpReplicas := $root.Values.moveOp.replicas.tserver -}} +{{- $maxMasterReplicas := ($hasMoveOpMaster | ternary (max (int $masterReplicas) (int $masterMoveOpReplicas)) (int $masterReplicas)) | int }} +{{- $maxTserverReplicas := ($hasMoveOpTserver | ternary (max (int $tserverReplicas) (int $tserverMoveOpReplicas)) (int $tserverReplicas)) | int }} + +--- +{{ $appLabelArgs := dict "label" "yb-master" "root" $root }} +apiVersion: v1 +kind: ConfigMap +metadata: + name: {{ include "yugabyte.fullname" $root }}-master-hooks + namespace: "{{ $root.Release.Namespace }}" + labels: + {{- include "yugabyte.applabel" ($appLabelArgs) | indent 4 }} + {{- include "yugabyte.labels" $root | indent 4 }} +data: +{{- range $index := until $maxMasterReplicas }} + yb-master-{{.}}-pre_debug_hook.sh: "echo 'hello-from-pre' " + yb-master-{{.}}-post_debug_hook.sh: "echo 'hello-from-post' " +{{- end }} + +--- +{{ $appLabelArgs := dict "label" "yb-tserver" "root" $root }} +apiVersion: v1 +kind: ConfigMap +metadata: + name: {{ include "yugabyte.fullname" $root }}-tserver-hooks + namespace: "{{ $root.Release.Namespace }}" + labels: + {{- include "yugabyte.applabel" ($appLabelArgs) | indent 4 }} + {{- include "yugabyte.labels" $root | indent 4 }} +data: +{{- range $index := until $maxTserverReplicas }} + yb-tserver-{{.}}-pre_debug_hook.sh: "echo 'hello-from-pre' " + yb-tserver-{{.}}-post_debug_hook.sh: "echo 'hello-from-post' " +{{- end }} +--- diff --git a/helm-charts/yugabyte/templates/hooks/setup-credentials-job.yaml b/helm-charts/yugabyte/templates/hooks/setup-credentials-job.yaml new file mode 100644 index 0000000..a12e581 --- /dev/null +++ b/helm-charts/yugabyte/templates/hooks/setup-credentials-job.yaml @@ -0,0 +1,101 @@ +{{- if or .Values.authCredentials.ycql.user .Values.authCredentials.ycql.password .Values.authCredentials.ycql.keyspace .Values.authCredentials.ysql.password .Values.authCredentials.ysql.user .Values.authCredentials.ysql.database .Values.authCredentials.ycql.passwordSecretName .Values.authCredentials.ysql.passwordSecretName .Values.authCredentials.ycql.passwordSecretName .Values.authCredentials.ysql.passwordSecretName .Values.authCredentials.ycql.passwordSecretName .Values.authCredentials.ysql.passwordSecretName}} +{{- $appLabelArgs := dict "label" "yugabyte" "root" . -}} +apiVersion: batch/v1 +kind: Job +metadata: + name: {{ include "yugabyte.fullname" . }}-setup-credentials + namespace: "{{ .Release.Namespace }}" + labels: + {{- include "yugabyte.applabel" ($appLabelArgs) | indent 4 }} + {{- include "yugabyte.labels" . | indent 4 }} + annotations: + "helm.sh/hook": post-install + "helm.sh/hook-weight": "0" + "helm.sh/hook-delete-policy": hook-succeeded,before-hook-creation +spec: + backoffLimit: 2 + template: + metadata: + name: "setup-credentials" + labels: + {{- include "yugabyte.applabel" ($appLabelArgs) | indent 8 }} + {{- include "yugabyte.labels" . | indent 8 }} + spec: + {{- if .Values.Image.pullSecretName }} + imagePullSecrets: + - name: {{ .Values.Image.pullSecretName }} + {{ end }} + {{- if .Values.nodeSelector }} + nodeSelector: {{ toYaml .Values.nodeSelector | nindent 8 }} + {{- end }} + {{- if .Values.tserver.tolerations }} + tolerations: {{ toYaml .Values.tserver.tolerations | nindent 8 }} + {{- end }} + restartPolicy: Never + containers: + - name: setup-credentials + image: "{{ .Values.Image.repository }}:{{ .Values.Image.tag }}" + env: + {{- if .Values.authCredentials.ysql.user }} + - name: YSQL_USER + value: "{{ .Values.authCredentials.ysql.user }}" + {{- end }} + {{- if or .Values.authCredentials.ysql.password .Values.authCredentials.ysql.passwordSecretName }} + - name: YSQL_PASSWORD + {{- if .Values.authCredentials.ysql.passwordSecretName }} + valueFrom: + secretKeyRef: + name: {{ .Values.authCredentials.ysql.passwordSecretName }} + key: ysqlPassword + {{- else }} + value: "{{ .Values.authCredentials.ysql.password }}" + {{- end -}} + {{- end }} + {{- if .Values.authCredentials.ysql.database }} + - name: YSQL_DB + value: "{{ .Values.authCredentials.ysql.database }}" + {{- end }} + {{- if .Values.authCredentials.ycql.user }} + - name: YCQL_USER + value: "{{ .Values.authCredentials.ycql.user }}" + {{- end }} + {{- if or (.Values.authCredentials.ycql.password) (.Values.authCredentials.ycql.passwordSecretName) }} + - name: YCQL_PASSWORD + {{- if .Values.authCredentials.ycql.passwordSecretName }} + valueFrom: + secretKeyRef: + name: {{ .Values.authCredentials.ycql.passwordSecretName }} + key: ycqlPassword + {{- else }} + value: "{{ .Values.authCredentials.ycql.password }}" + {{- end -}} + {{- end }} + {{- if .Values.authCredentials.ycql.keyspace }} + - name: YCQL_KEYSPACE + value: "{{ .Values.authCredentials.ycql.keyspace }}" + {{- end }} + {{- if .Values.tls.enabled }} + - name: SSL_CERTFILE + value: "/root/.yugabytedb/root.crt" + {{- end }} + command: + - 'bash' + - '/home/yugabyte/bin/setup-credentials/setup-credentials.sh' + volumeMounts: + - name: setup-credentials-script + mountPath: "/home/yugabyte/bin/setup-credentials" + {{- if .Values.tls.enabled }} + - name: yugabyte-tls-client-cert + mountPath: "/root/.yugabytedb/" + {{- end }} + volumes: + - name: setup-credentials-script + configMap: + name: {{ include "yugabyte.fullname" . }}-setup-credentials-script + {{- if .Values.tls.enabled }} + - name: yugabyte-tls-client-cert + secret: + secretName: {{ .Values.oldNamingStyle | ternary "yugabyte-tls-client-cert" (printf "%s-client-tls" (include "yugabyte.fullname" . )) }} + defaultMode: 256 + {{- end }} +{{- end }} diff --git a/helm-charts/yugabyte/templates/master-gflags-secret.yaml b/helm-charts/yugabyte/templates/master-gflags-secret.yaml new file mode 100644 index 0000000..31cc97a --- /dev/null +++ b/helm-charts/yugabyte/templates/master-gflags-secret.yaml @@ -0,0 +1,73 @@ +{{- $root := . -}} +{{- range $service := $root.Values.Services }} +{{- if eq $service.name "yb-masters" }} +{{- $serviceValues := (dict "Service" $service "Values" $root.Values "Chart" $root.Chart "Release" $root.Release) -}} +{{- $appLabelArgs := dict "label" $service.label "root" $root -}} +{{- $vars := include "yugabyte.stsIndexVars" (dict "serviceName" $service.name "root" $root) | fromYaml -}} + +{{- range $stsIdx := until (int $vars.stsCount) }} +{{- $loopVars := include "yugabyte.stsIndexLoopVars" (dict "stsIdx" $stsIdx "stsStart" $vars.stsStart "stsEnd" $vars.stsEnd "replicas" $vars.replicas "moveOpReplicas" $vars.moveOpReplicas) | fromYaml -}} +{{- $currentStsIndex := $loopVars.currentStsIndex -}} +{{- $useMoveOp := $loopVars.useMoveOp -}} +{{- $stsIndexSuffix := $loopVars.stsIndexSuffix -}} +{{- $storageInfo := $useMoveOp | ternary $root.Values.moveOp.storage.master $root.Values.storage.master -}} +{{- $storageEphemeral := $useMoveOp | ternary $root.Values.moveOp.storage.ephemeral $root.Values.storage.ephemeral -}} +{{- $currentReplicas := $loopVars.currentReplicas }} +--- +apiVersion: v1 +kind: Secret +metadata: + name: {{ printf "%s%s-master-gflags" (include "yugabyte.fullname" $root) $stsIndexSuffix }} + namespace: "{{ $root.Release.Namespace }}" + labels: + {{- include "yugabyte.applabel" ($appLabelArgs) | indent 4 }} + {{- include "yugabyte.labels" $root | indent 4 }} +type: Opaque +stringData: + server.conf.template: | +{{- if not $storageEphemeral }} + --fs_data_dirs={{ template "yugabyte.fs_data_dirs" $storageInfo }} +{{- else }} + --fs_data_dirs=/var/yugabyte +{{- end }} +{{- if eq $root.Values.ip_version_support "v6_only" }} + --net_address_filter=ipv6_external,ipv6_non_link_local,ipv6_all,ipv4_external,ipv4_all +{{- end }} +{{- $masterCount := ternary $root.Values.replicas.totalMasters $currentReplicas $root.Values.isMultiAz }} + --replication_factor={{ $masterCount }} +{{- if $root.Values.masterAddresses }} + --master_addresses={{ $root.Values.masterAddresses }} +{{- else }} + --master_addresses={{ include "yugabyte.master_addresses" (dict "root" $root "vars" $vars) }} +{{- end }} +{{- if not $root.Values.disableYsql }} + --enable_ysql=true +{{- else }} + --enable_ysql=false +{{- end }} +{{- if $root.Values.tls.enabled }} + --certs_dir=/opt/certs/yugabyte + --use_node_to_node_encryption={{ $root.Values.tls.nodeToNode }} + --allow_insecure_connections={{ $root.Values.tls.insecure }} +{{- end }} +{{- if $root.Values.yugabytedUi.enabled }} + --master_enable_metrics_snapshotter={{ $root.Values.yugabytedUi.metricsSnapshotter.enabled }} + --metrics_snapshotter_tserver_metrics_whitelist={{ join "," $root.Values.yugabytedUi.metricsSnapshotter.whitelist }} +{{- end }} + --metric_node_name=${EXPORTED_INSTANCE} + --memory_limit_hard_bytes={{ template "yugabyte.memory_hard_limit" dict "size" $root.Values.resource.master.limits.memory "limitPercent" $root.Values.master.memoryLimitHardPercentage }} + --stderrthreshold=0 + --num_cpus={{ ceil $root.Values.resource.master.requests.cpu }} + --max_log_size=256 + --undefok=num_cpus,enable_ysql + --use_node_hostname_for_local_tserver=true + --rpc_bind_addresses={{ include "yugabyte.rpc_bind_address" $serviceValues }} + --server_broadcast_addresses={{ include "yugabyte.server_broadcast_address" $serviceValues }} + --webserver_interface={{ include "yugabyte.webserver_interface" $serviceValues }} +{{- range $flag, $override := $root.Values.gflags.master }} + --{{ $flag }}={{ $override }} +{{- end }} +{{- end }} +{{- end }} +{{- end }} +--- diff --git a/helm-charts/yugabyte/templates/master-servicemonitor.yaml b/helm-charts/yugabyte/templates/master-servicemonitor.yaml new file mode 100644 index 0000000..b6050d8 --- /dev/null +++ b/helm-charts/yugabyte/templates/master-servicemonitor.yaml @@ -0,0 +1,46 @@ +{{- if and .Values.serviceMonitor.enabled .Values.serviceMonitor.master.enabled }} +{{- $appLabelArgs := dict "label" "yb-master" "root" . -}} +apiVersion: monitoring.coreos.com/v1 +kind: ServiceMonitor +metadata: + name: {{ include "yugabyte.fullname" . }}-yb-master + labels: + {{- include "yugabyte.applabel" ($appLabelArgs) | indent 4 }} + {{- include "yugabyte.labels" . | indent 4 }} + {{- with .Values.serviceMonitor.extraLabels }} + {{- toYaml . | nindent 4 }} + {{- end }} +spec: + jobLabel: "release" + selector: + matchLabels: + {{- if .Values.oldNamingStyle }} + app: "yb-master" + {{- else }} + app.kubernetes.io/name: "yb-master" + {{- end }} + release: {{ .Release.Name | quote }} + service-type: "headless" + endpoints: + + {{- with .Values.serviceMonitor.master }} + {{- if .enabled }} + - port: {{ .port }} + path: {{ .path }} + {{- if .interval }} + interval: {{ .interval }} + {{- else }} + interval: {{ $.Values.serviceMonitor.interval }} + {{- end }} + relabelings: + - targetLabel: "group" + replacement: "yb-master" + - targetLabel: "export_type" + replacement: "master_export" + - targetLabel: "node_prefix" + replacement: {{ $.Release.Name | quote }} + metricRelabelings: + {{- toYaml $.Values.serviceMonitor.commonMetricRelabelings | nindent 4 }} + {{- end }} + {{- end }} +{{- end }} diff --git a/helm-charts/yugabyte/templates/multicluster/common-tserver-service.yaml b/helm-charts/yugabyte/templates/multicluster/common-tserver-service.yaml new file mode 100644 index 0000000..68f250d --- /dev/null +++ b/helm-charts/yugabyte/templates/multicluster/common-tserver-service.yaml @@ -0,0 +1,23 @@ +{{- if (and .Values.multicluster.createCommonTserverService (not .Values.oldNamingStyle)) }} +{{- range $service := .Values.serviceEndpoints }} +{{- if eq $service.name "yb-tserver-service" }} +{{- $appLabelArgs := dict "label" $service.app "root" $ -}} +apiVersion: v1 +kind: Service +metadata: + name: "yb-tserver-common" + labels: + {{- include "yugabyte.applabel" ($appLabelArgs) | indent 4 }} + {{- include "yugabyte.labels" $ | indent 4 }} +spec: + ports: + {{- range $label, $port := $service.ports }} + - name: {{ $label | quote }} + port: {{ $port }} + {{- end }} + selector: + {{- include "yugabyte.appselector" ($appLabelArgs) | indent 4 }} +--- +{{- end }} +{{- end }} +{{- end }} diff --git a/helm-charts/yugabyte/templates/multicluster/mcs-service-export.yaml b/helm-charts/yugabyte/templates/multicluster/mcs-service-export.yaml new file mode 100644 index 0000000..eeafcb1 --- /dev/null +++ b/helm-charts/yugabyte/templates/multicluster/mcs-service-export.yaml @@ -0,0 +1,21 @@ +{{- /* + Ref - https://cloud.google.com/kubernetes-engine/docs/how-to/multi-cluster-services#registering_a_service_for_export + https://github.com/kubernetes/enhancements/tree/master/keps/sig-multicluster/1645-multi-cluster-services-api#exporting-services +*/}} +{{- if .Values.multicluster.createServiceExports }} +apiVersion: {{ .Values.multicluster.mcsApiVersion }} +kind: ServiceExport +metadata: + name: {{ .Values.oldNamingStyle | ternary "yb-masters" (printf "%s-%s" (include "yugabyte.fullname" .) "yb-masters") | quote }} + namespace: "{{ .Release.Namespace }}" + labels: + {{- include "yugabyte.labels" . | indent 4 }} +--- +apiVersion: {{ .Values.multicluster.mcsApiVersion }} +kind: ServiceExport +metadata: + name: {{ .Values.oldNamingStyle | ternary "yb-tservers" (printf "%s-%s" (include "yugabyte.fullname" .) "yb-tservers") | quote }} + namespace: "{{ .Release.Namespace }}" + labels: + {{- include "yugabyte.labels" . | indent 4 }} +{{ end -}} diff --git a/helm-charts/yugabyte/templates/multicluster/service-per-pod.yaml b/helm-charts/yugabyte/templates/multicluster/service-per-pod.yaml new file mode 100644 index 0000000..ed85657 --- /dev/null +++ b/helm-charts/yugabyte/templates/multicluster/service-per-pod.yaml @@ -0,0 +1,45 @@ +{{- if .Values.multicluster.createServicePerPod }} +{{- range $server := .Values.Services }} +{{- $vars := include "yugabyte.stsIndexVars" (dict "serviceName" $server.name "root" $) | fromYaml -}} + +{{- range $stsIdx := until (int $vars.stsCount) }} +{{- $loopVars := include "yugabyte.stsIndexLoopVars" (dict "stsIdx" $stsIdx "stsStart" $vars.stsStart "stsEnd" $vars.stsEnd "replicas" $vars.replicas "moveOpReplicas" $vars.moveOpReplicas) | fromYaml -}} +{{- $currentStsIndex := $loopVars.currentStsIndex -}} +{{- $useMoveOp := $loopVars.useMoveOp -}} +{{- $stsIndexSuffix := $loopVars.stsIndexSuffix -}} +{{- $currentReplicas := $loopVars.currentReplicas -}} +{{- $appLabelArgs := dict "label" $server.label "root" $ -}} +{{- range $replicaNum := until (int $currentReplicas) }} +{{- $basePodName := $.Values.oldNamingStyle | ternary $server.label (printf "%s-%s%s" (include "yugabyte.fullname" $) $server.label $stsIndexSuffix) -}} +{{- $podName := printf "%s-%d" $basePodName $replicaNum }} +--- +apiVersion: v1 +kind: Service +metadata: + name: {{ $podName | quote }} + labels: + {{- include "yugabyte.applabel" ($appLabelArgs) | indent 4 }} + {{- include "yugabyte.labels" $ | indent 4 }} + service-type: "non-endpoint" +spec: + ports: + {{- range $label, $port := $server.ports }} + {{- if or (eq $label "grpc-ybc-port") (eq $label "tcp-ybc-port")}} + {{- if $.Values.ybc.enabled }} + - name: "tcp-ybc-port" + port: {{ $port }} + {{- end }} + {{- else }} + - name: {{ $label | quote }} + port: {{ $port }} + {{- end }} + {{- end}} + selector: + statefulset.kubernetes.io/pod-name: {{ $podName | quote }} + {{- include "yugabyte.appselector" ($appLabelArgs) | indent 4 }} + {{- include "yugabyte.ipFamilyConfig" $ | indent 2 }} +--- +{{- end }} +{{- end }} +{{- end }} +{{- end }} diff --git a/helm-charts/yugabyte/templates/otel-collector.yaml b/helm-charts/yugabyte/templates/otel-collector.yaml new file mode 100644 index 0000000..92a58c9 --- /dev/null +++ b/helm-charts/yugabyte/templates/otel-collector.yaml @@ -0,0 +1,174 @@ +{{- $root := . -}} +--- +{{- if .Values.otelCollector.enabled }} +--- +{{- if .Values.otelCollector.secretEnv }} +{{ $appLabelArgs := dict "label" "yb-tserver" "root" $root }} +apiVersion: v1 +kind: Secret +metadata: + name: {{ include "yugabyte.fullname" $root }}-otel-secrets + namespace: "{{ $root.Release.Namespace }}" + labels: + {{- include "yugabyte.applabel" ($appLabelArgs) | indent 4 }} + {{- include "yugabyte.labels" $root | indent 4 }} +type: Opaque +data: +{{- range .Values.otelCollector.secretEnv }} + {{ .envName }}: {{ .envValue | quote }} +{{- end }} +{{- end }} +--- +{{ $appLabelArgs := dict "label" "yb-tserver" "root" $root }} +apiVersion: opentelemetry.io/v1beta1 +kind: OpenTelemetryCollector +metadata: + name: {{ $root.Values.oldNamingStyle | ternary "otel-yb-tserver" (printf "otel-%s-yb-tserver" (include "yugabyte.fullname" $root)) | quote }} + namespace: "{{ $root.Release.Namespace }}" + labels: + {{- include "yugabyte.applabel" ($appLabelArgs) | indent 4 }} + {{- include "yugabyte.labels" $root | indent 4 }} +spec: + config: + exporters: + {{- range $name, $exporter := .Values.otelCollector.exporters}} + {{ $name }}: +{{ toYaml $exporter | indent 8 }} + {{- end }} + extensions: + file_storage/queue: + create_directory: true + compaction: + directory: /mnt/disk0/otel-collector/queue + on_rebound: true + on_start: true + rebound_needed_threshold_mib: 100 + rebound_trigger_threshold_mib: 10 + directory: /mnt/disk0/otel-collector/queue + health_check: + endpoint: {{ (printf "%s:13133" (include "yugabyte.webserver_interface" $root)) | quote }} + path: "/health" + processors: + {{- range $name := (keys .Values.otelCollector.exporters) }} + attributes/{{ $name }}: + actions: + - action: upsert + key: ddsource + value: yugabyte + - action: upsert + key: service + value: yb-otel-collector + - action: upsert + key: host + value: ${POD_NAME} + {{- end }} + receivers: + filelog/ysql: + attributes: + audit_log_type: ysql + exclude: + - /mnt/disk0/yb-data/tserver/logs/*.gz + include: + - /mnt/disk0/yb-data/tserver/logs/postgresql-*.log + multiline: + line_start_pattern: {{ $root.Values.otelCollector.recievers.ysql.lineStartPattern | quote }} + operators: + - expr: 'body not matches "^.*\\w+: AUDIT:(.|\\n|\\r|\\s)*$"' + type: filter + - on_error: drop + regex: {{ $root.Values.otelCollector.recievers.ysql.regex | quote }} + timestamp: +{{ toYaml $root.Values.otelCollector.recievers.ysql.timestamp | indent 12 }} + type: regex_parser + start_at: beginning + storage: file_storage/queue + service: + extensions: + - file_storage/queue + - health_check + pipelines: + {{- range $name := (keys .Values.otelCollector.exporters) }} + logs/{{ $name }}: + exporters: + - {{ $name }} + processors: + - attributes/{{ $name }} + receivers: + - filelog/ysql + {{- end}} + telemetry: + logs: + output_paths: + - /mnt/disk0/otel-collector/logs/otel-collector.logs + image: {{ .Values.otelCollector.image | default "otel/opentelemetry-collector-contrib:0.114.0" | quote }} + ipFamilyPolicy: SingleStack + managementState: managed + mode: sidecar + replicas: 1 + resources: {{ .Values.otelCollector.resources | toYaml | nindent 4 }} + upgradeStrategy: automatic + env: + - name: USER + value: yugabyte + {{- range .Values.otelCollector.secretEnv }} + {{- if eq .envName "GOOGLE_APPLICATION_CREDENTIALS_CONTENT" }} + - name: GOOGLE_APPLICATION_CREDENTIALS + value: /mnt/disk0/otel-collector/gcp_credentials/gcp_credentials.json + {{- else }} + - name: {{ .envName }} + valueFrom: + secretKeyRef: + name: {{ include "yugabyte.fullname" $root }}-otel-secrets + key: {{ .envName }} + {{- end }} + {{- end }} + volumeMounts: + - mountPath: /mnt/disk0/ + name: {{ $root.Values.oldNamingStyle | ternary "datadir0" (printf "%s0" (include "yugabyte.volume_name" $root)) }} + initContainers: + - name: init-otel-collector + image: "{{ $root.Values.Image.repository }}:{{ $root.Values.Image.tag }}" + imagePullPolicy: {{ $root.Values.Image.pullPolicy }} + command: + - "sh" + - "-c" + - > + mkdir -p /mnt/disk0/otel-collector/logs; + rm -rf /mnt/disk0/otel-collector/gcp_credentials; + if [ -n "${GOOGLE_APPLICATION_CREDENTIALS_CONTENT}" ] ; then + mkdir -p /mnt/disk0/otel-collector/gcp_credentials; + echo ${GOOGLE_APPLICATION_CREDENTIALS_CONTENT} > /mnt/disk0/otel-collector/gcp_credentials/gcp_credentials.json; + fi + volumeMounts: + - mountPath: /mnt/disk0/ + name: {{ $root.Values.oldNamingStyle | ternary "datadir0" (printf "%s0" (include "yugabyte.volume_name" $root)) }} + env: + {{- range .Values.otelCollector.secretEnv }} + {{- if eq .envName "GOOGLE_APPLICATION_CREDENTIALS_CONTENT" }} + - name: {{ .envName }} + valueFrom: + secretKeyRef: + name: {{ include "yugabyte.fullname" $root }}-otel-secrets + key: {{ .envName }} + {{- end }} + {{- end }} + {{- if .Values.containerSecurityContext.enabled }} + {{- include "getSecurityContext" . | nindent 2 }} + {{- else if .Values.podSecurityContext.enabled }} + securityContext: + runAsUser: {{ required "runAsUser cannot be empty" .Values.podSecurityContext.runAsUser }} + {{- if ne .Values.podSecurityContext.runAsGroup nil }} + runAsGroup: {{ .Values.podSecurityContext.runAsGroup }} + {{- else }} + runAsGroup: {{ .Values.podSecurityContext.runAsUser }} + {{- end }} + runAsNonRoot: {{ .Values.podSecurityContext.runAsNonRoot }} + {{- if .Values.podSecurityContext.additionalSettings }} + {{- toYaml .Values.podSecurityContext.additionalSettings | nindent 4 }} + {{- end }} + {{- else if not .Values.ocpCompatibility.enabled }} + securityContext: + runAsUser: 0 + {{- end }} +--- +{{- end }} diff --git a/helm-charts/yugabyte/templates/secrets.yaml b/helm-charts/yugabyte/templates/secrets.yaml new file mode 100644 index 0000000..0bd9034 --- /dev/null +++ b/helm-charts/yugabyte/templates/secrets.yaml @@ -0,0 +1,7 @@ +{{- $root := . -}} +--- # Create secrets from other namespaces for masters. +{{- $data := dict "secretenv" $.Values.master.secretEnv "root" . "suffix" "master"}} +{{- include "yugabyte.envsecrets" $data }} +--- # Create secrets from other namespaces for tservers. +{{- $data := dict "secretenv" $.Values.tserver.secretEnv "root" . "suffix" "tserver" }} +{{- include "yugabyte.envsecrets" $data }} \ No newline at end of file diff --git a/helm-charts/yugabyte/templates/service-endpoints.yaml b/helm-charts/yugabyte/templates/service-endpoints.yaml new file mode 100644 index 0000000..d3cdd23 --- /dev/null +++ b/helm-charts/yugabyte/templates/service-endpoints.yaml @@ -0,0 +1,93 @@ +{{- $root := . -}} +--- +# Services endpoints +{{- if $root.Values.enableLoadBalancer }} +{{- range .Values.Services }} +{{- $service := . -}} +{{- $appLabelArgs := dict "label" .label "root" $root -}} +{{- range $endpoint := $root.Values.serviceEndpoints }} +{{- $serviceScopeArgs := dict "endpoint" $endpoint "defaultScope" $root.Values.defaultServiceScope }} +{{- $scope := include "yugabyte.servicescope" $serviceScopeArgs }} +{{- if eq $service.label $endpoint.app }} +# Only render if new naming style or old naming style + AZ scope +{{- if or (not $root.Values.oldNamingStyle) (eq $scope "AZ") }} +{{- $servicenameargs := dict "root" $root "endpoint" $endpoint "scope" $scope }} +{{- $serviceName := include "yugabyte.servicename" ($servicenameargs) }} +{{- $serviceArgs := dict "endpoint" $endpoint "serviceName" $serviceName "root" $root "scope" $scope }} +{{- $service := include "yugabyte.should_render_service" ($serviceArgs) }} +# Render if: +# 1. Always if scope is AZ +# 2. Namespaced scope: Service does not exist +# 3. Namespaced scope: Service exists and is owned by this release +{{- if eq $service "true" }} +{{- if (or (ne $endpoint.name "yugabyted-ui-service") $root.Values.yugabytedUi.enabled) }} +apiVersion: v1 +kind: Service +metadata: + name: {{ $serviceName | quote }} + namespace: "{{ $root.Release.Namespace }}" + annotations: + # Keep resource for namespaced services + {{- if eq $scope "Namespaced" }} + "helm.sh/resource-policy": keep + {{- end }} + {{- if $endpoint.annotations }} +{{ toYaml $endpoint.annotations | nindent 4 }} + {{- end }} + labels: + # scope is "Namespaced" or "AZ" + scope: {{ $scope }} + serviceName: {{ $endpoint.name }} + service-type: "endpoint" + {{- include "yugabyte.applabel" ($appLabelArgs) | indent 4 }} + {{- $labels := include "yugabyte.labels" $root | fromYaml }} + # For Namespaced service, remove zone and release name filter + {{- if eq $scope "Namespaced" }} + {{- $labels = omit $labels "yugabyte.io/zone" "release" }} + {{- end }} + {{- range $key,$value := $labels }} + {{ $key }}: {{ $value | quote }} + {{- end }} +spec: + {{- if eq $root.Release.Service "Tiller" }} + clusterIP: + {{- else }} + {{- if $endpoint.clusterIP }} + clusterIP: {{ $endpoint.clusterIP }} + {{- end }} + {{- end }} + type: {{ $endpoint.type }} + ports: + {{- range $label, $port := $endpoint.ports }} + - name: {{ $label | quote }} + port: {{ $port }} + {{- end }} + selector: + {{- if eq $endpoint.name "yugabyted-ui-service"}} + yugabytedUi: "true" + {{- else if eq $scope "Namespaced" }} + {{- include "yugabyte.namespacedserviceselector" ($appLabelArgs) | indent 4 }} + {{- else }} + {{- include "yugabyte.appselector" ($appLabelArgs) | indent 4 }} + {{- end }} + {{- if ne $endpoint.type "ClusterIP" }} + externalTrafficPolicy: {{ $endpoint.externalTrafficPolicy | default "Cluster" }} + {{- end }} + {{- if $endpoint.loadBalancerIP }} + loadBalancerIP: {{ $endpoint.loadBalancerIP }} + {{- end }} + {{- if eq $endpoint.name "yugabyted-ui-service"}} + sessionAffinity: {{ $endpoint.sessionAffinity }} + {{- end }} + {{- include "yugabyte.ipFamilyConfig" ($root) | indent 2 }} + {{- range $key, $value := $endpoint.extraArgs }} + {{ $key }}: {{ $value | quote }} + {{- end }} +--- +{{- end }} +{{- end }} +{{- end }} +{{- end }} +{{- end }} +{{- end }} +{{- end }} \ No newline at end of file diff --git a/helm-charts/yugabyte/templates/service.yaml b/helm-charts/yugabyte/templates/service.yaml new file mode 100644 index 0000000..8901cc0 --- /dev/null +++ b/helm-charts/yugabyte/templates/service.yaml @@ -0,0 +1,977 @@ +{{- $root := . -}} +{{- /* Validate stsIndex values */ -}} +{{- include "yugabyte.validateStsIndex" (dict "start" ($root.Values.stsIndex.master.start | int) "end" ($root.Values.stsIndex.master.end | int) "component" "master") -}} +{{- include "yugabyte.validateStsIndex" (dict "start" ($root.Values.stsIndex.tserver.start | int) "end" ($root.Values.stsIndex.tserver.end | int) "component" "tserver") -}} +--- +{{- if and (eq $root.Values.tls.enabled true) (eq $root.Values.tls.certManager.enabled false) }} +--- +apiVersion: v1 +kind: Secret +metadata: + name: {{ $root.Values.oldNamingStyle | ternary "yugabyte-tls-client-cert" (printf "%s-client-tls" (include "yugabyte.fullname" $root)) }} + namespace: "{{ $root.Release.Namespace }}" + labels: + {{- include "yugabyte.labels" $root | indent 4 }} +type: Opaque +data: +{{- if $root.Values.tls.rootCA.key }} +{{- $rootCAClient := buildCustomCert $root.Values.tls.rootCA.cert $root.Values.tls.rootCA.key -}} +{{- $client := genSignedCert "yugabyte" ( default nil ) ( default nil ) 3650 $rootCAClient }} + root.crt: {{ $rootCAClient.Cert | b64enc }} + yugabytedb.crt: {{ $client.Cert | b64enc }} + yugabytedb.key: {{ $client.Key | b64enc }} +{{- else }} + root.crt: {{ $root.Values.tls.rootCA.cert }} + yugabytedb.crt: {{ $root.Values.tls.clientCert.cert }} + yugabytedb.key: {{ $root.Values.tls.clientCert.key }} +{{- end }} +--- +{{- end }} +--- +{{- range .Values.Services }} +{{- $service := . -}} +{{- $appLabelArgs := dict "label" .label "root" $root -}} +{{- $serviceValues := (dict "Service" $service "Values" $root.Values "Chart" $root.Chart "Release" $root.Release) -}} +{{- $vars := include "yugabyte.stsIndexVars" (dict "serviceName" .name "root" $root) | fromYaml -}} + +{{- if and (eq $root.Values.tls.enabled true) (eq $root.Values.tls.certManager.enabled false) }} +{{- range $stsIdx := until (int $vars.stsCount) }} +{{- $loopVars := include "yugabyte.stsIndexLoopVars" (dict "stsIdx" $stsIdx "stsStart" $vars.stsStart "stsEnd" $vars.stsEnd "replicas" $vars.replicas "moveOpReplicas" $vars.moveOpReplicas) | fromYaml -}} +{{- $currentStsIndex := $loopVars.currentStsIndex -}} +{{- $useMoveOp := $loopVars.useMoveOp -}} +{{- $stsIndexSuffix := $loopVars.stsIndexSuffix -}} +{{- $currentReplicas := $loopVars.currentReplicas -}} +{{- if gt (int $currentReplicas) 0 }} +--- +apiVersion: v1 +kind: Secret +metadata: + name: {{ $root.Values.oldNamingStyle | ternary (printf "%s%s-yugabyte-tls-cert" $service.label $stsIndexSuffix) (printf "%s-%s%s-tls-cert" (include "yugabyte.fullname" $root) $service.label $stsIndexSuffix) }} + namespace: "{{ $root.Release.Namespace }}" + labels: + {{- include "yugabyte.applabel" ($appLabelArgs) | indent 4 }} + {{- include "yugabyte.labels" $root | indent 4 }} +type: Opaque +data: +{{- range $index := until ( int ( $currentReplicas ) ) }} +{{- $nodeOldStyle := printf "%s%s-%d.%s.%s.svc.%s" $service.label $stsIndexSuffix $index $service.name $root.Release.Namespace $root.Values.domainName }} +{{- $nodeNewStyle := printf "%s-%s%s-%d.%s-%s.%s.svc.%s" (include "yugabyte.fullname" $root) $service.label $stsIndexSuffix $index (include "yugabyte.fullname" $root) $service.name $root.Release.Namespace $root.Values.domainName }} + +{{- if $root.Values.multicluster.createServiceExports -}} + {{- $nodeOldStyle = printf "%s%s-%d.%s.%s.%s.svc.clusterset.local" $service.label $stsIndexSuffix $index $root.Values.multicluster.kubernetesClusterId $service.name $root.Release.Namespace }} + {{- $nodeNewStyle = printf "%s-%s%s-%d.%s.%s-%s.%s.svc.clusterset.local" (include "yugabyte.fullname" $root) $service.label $stsIndexSuffix $index $root.Values.multicluster.kubernetesClusterId (include "yugabyte.fullname" $root) $service.name $root.Release.Namespace }} +{{- end -}} + +{{- if $root.Values.multicluster.createServicePerPod -}} + {{- $nodeOldStyle = printf "%s%s-%d.%s.svc.%s" $service.label $stsIndexSuffix $index $root.Release.Namespace $root.Values.domainName }} + {{- $nodeNewStyle = printf "%s-%s%s-%d.%s.svc.%s" (include "yugabyte.fullname" $root) $service.label $stsIndexSuffix $index $root.Release.Namespace $root.Values.domainName }} +{{- end -}} + +{{- $node := $root.Values.oldNamingStyle | ternary $nodeOldStyle $nodeNewStyle }} +{{- if $root.Values.tls.rootCA.key }} +{{- $dns1 := printf "*.%s-%s%s.%s" (include "yugabyte.fullname" $root) $service.name $stsIndexSuffix $root.Release.Namespace }} +{{- $dns2 := printf "%s.svc.%s" $dns1 $root.Values.domainName }} +{{- if $root.Values.multicluster.createServiceExports -}} + {{- $dns1 = printf "*.%s.%s-%s%s.%s.svc.clusterset.local" $root.Values.multicluster.kubernetesClusterId (include "yugabyte.fullname" $root) $service.name $stsIndexSuffix $root.Release.Namespace }} +{{- end -}} +{{- if $root.Values.multicluster.createServicePerPod -}} + {{- $dns1 = printf "*.%s.svc.%s" $root.Release.Namespace $root.Values.domainName }} +{{- end -}} +{{- $rootCA := buildCustomCert $root.Values.tls.rootCA.cert $root.Values.tls.rootCA.key -}} +{{- $server := genSignedCert $node ( default nil ) (list $node $dns1 $dns2 ) 3650 $rootCA }} + node.{{$node}}.crt: {{ $server.Cert | b64enc }} + node.{{$node}}.key: {{ $server.Key | b64enc }} +{{- else }} + node.{{$node}}.crt: {{ $root.Values.tls.nodeCert.cert }} + node.{{$node}}.key: {{ $root.Values.tls.nodeCert.key }} +{{- end }} +{{- end }} + ca.crt: {{ $root.Values.tls.rootCA.cert }} +{{- end }} +{{- end }} +{{- end }} +--- +apiVersion: v1 +kind: Service +metadata: + name: {{ $root.Values.oldNamingStyle | ternary .name (printf "%s-%s" (include "yugabyte.fullname" $root) .name) | quote }} + labels: + {{- include "yugabyte.applabel" ($appLabelArgs) | indent 4 }} + {{- include "yugabyte.labels" $root | indent 4 }} + service-type: "headless" +spec: + clusterIP: None + publishNotReadyAddresses: true + ports: + {{- range $label, $port := .ports }} + {{- if or (eq $label "grpc-ybc-port") (eq $label "tcp-ybc-port")}} + {{- if $root.Values.ybc.enabled }} + - name: "tcp-ybc-port" + port: {{ $port }} + {{- end }} + {{- else if (eq $label "yugabyted-ui") }} + {{- if $root.Values.yugabytedUi.enabled }} + - name: {{ $label | quote }} + port: {{ $port }} + {{- end }} + {{- else }} + - name: {{ $label | quote }} + port: {{ $port }} + {{- end }} + {{- end }} + selector: + {{- include "yugabyte.appselector" ($appLabelArgs) | indent 4 }} + {{- include "yugabyte.ipFamilyConfig" ($root) | indent 2 }} + +{{- range $stsIdx := until (int $vars.stsCount) }} +{{- $loopVars := include "yugabyte.stsIndexLoopVars" (dict "stsIdx" $stsIdx "stsStart" $vars.stsStart "stsEnd" $vars.stsEnd "replicas" $vars.replicas "moveOpReplicas" $vars.moveOpReplicas) | fromYaml -}} +{{- $currentStsIndex := $loopVars.currentStsIndex -}} +{{- $useMoveOp := $loopVars.useMoveOp -}} +{{- $stsIndexSuffix := $loopVars.stsIndexSuffix -}} +{{- $currentReplicas := $loopVars.currentReplicas -}} +{{- if gt (int $currentReplicas) 0 }} +--- +apiVersion: apps/v1 +kind: StatefulSet +metadata: + name: {{ $root.Values.oldNamingStyle | ternary (printf "%s%s" $service.label $stsIndexSuffix) (printf "%s-%s%s" (include "yugabyte.fullname" $root) $service.label $stsIndexSuffix) | quote }} + namespace: "{{ $root.Release.Namespace }}" + labels: + {{- include "yugabyte.applabel" ($appLabelArgs) | indent 4 }} + {{- include "yugabyte.labels" $root | indent 4 }} + {{- if $root.Values.statefulSetAnnotations }} + annotations: +{{ toYaml $root.Values.statefulSetAnnotations | indent 4 }} + {{- end }} +spec: + serviceName: {{ $root.Values.oldNamingStyle | ternary $service.name (printf "%s-%s" (include "yugabyte.fullname" $root) $service.name) | quote }} + podManagementPolicy: {{ $root.Values.PodManagementPolicy }} + {{ if eq $service.name "yb-masters" }} + replicas: {{ $useMoveOp | ternary $root.Values.moveOp.replicas.master $root.Values.replicas.master }} + {{ else }} + replicas: {{ $useMoveOp | ternary $root.Values.moveOp.replicas.tserver $root.Values.replicas.tserver }} + {{ end }} + {{- $storageInfo := include "yugabyte.storageInfo" (dict "serviceName" $service.name "useMoveOp" $useMoveOp "root" $root) | fromYaml -}} + {{- $storageEphemeral := $useMoveOp | ternary $root.Values.moveOp.storage.ephemeral $root.Values.storage.ephemeral -}} + {{ if not $storageEphemeral }} + volumeClaimTemplates: + {{- range $index := until (int ($storageInfo.count )) }} + - metadata: + name: {{ $root.Values.oldNamingStyle | ternary (printf "datadir%d" $index) (printf "%s%d" (include "yugabyte.volume_name" $root) $index) }} + {{- if $root.Values.legacyVolumeClaimAnnotations }} + annotations: + volume.beta.kubernetes.io/storage-class: {{ $storageInfo.storageClass | quote }} + {{- end }} + labels: + {{- include "yugabyte.labels" $root | indent 10 }} + spec: + accessModes: + - "ReadWriteOnce" + {{- if $storageInfo.storageClass }} + storageClassName: {{ $storageInfo.storageClass }} + {{- end }} + resources: + requests: + storage: {{ $storageInfo.size }} + {{- end }} + {{- end }} + updateStrategy: + {{- if eq $root.Values.updateStrategy.type "RollingUpdate" }} + type: RollingUpdate + rollingUpdate: + {{- if eq $service.name "yb-masters" }} + partition: {{ $useMoveOp | ternary $root.Values.moveOp.partition.master $root.Values.partition.master }} + {{- else }} + partition: {{ $useMoveOp | ternary $root.Values.moveOp.partition.tserver $root.Values.partition.tserver }} + {{- end }} + {{- else }} + type: {{ $root.Values.updateStrategy.type }} + {{- end }} + selector: + matchLabels: + {{- include "yugabyte.appselector" ($appLabelArgs) | indent 6 }} + template: + metadata: + annotations: + {{- if eq $service.name "yb-masters" }} + checksum/gflags: {{ (not $root.Values.master.gflagsChecksum) | ternary (include (print $root.Template.BasePath "/master-gflags-secret.yaml") $root | sha256sum) $root.Values.master.gflagsChecksum }} + {{- if (or $root.Values.networkAnnotation $root.Values.master.podAnnotations $root.Values.tls.enabled) }} + {{- with $root.Values.networkAnnotation }}{{ toYaml . | nindent 8 }}{{ end }} + {{- with $root.Values.master.podAnnotations }}{{ toYaml . | nindent 8 }}{{ end }} + {{- if $root.Values.tls.enabled }} + checksum/rootCA: {{ (not $root.Values.tls.rootCAChecksum) | ternary (cat $root.Values.tls.rootCA.cert $root.Values.tls.rootCA.key | sha256sum) $root.Values.tls.rootCAChecksum }} + {{- end }} + {{- end }} + {{- else }} + checksum/gflags: {{ (not $root.Values.tserver.gflagsChecksum) | ternary (include (print $root.Template.BasePath "/tserver-gflags-secret.yaml") $root | sha256sum) $root.Values.tserver.gflagsChecksum }} + {{- if $root.Values.ybc.useYBDBImage }} + checksum/ybcGflags: {{ (not $root.Values.ybc.gflagsChecksum) | ternary (include (print $root.Template.BasePath "/controller-gflags-secret.yaml") $root | sha256sum) $root.Values.ybc.gflagsChecksum }} + {{- end }} + {{- if (or $root.Values.networkAnnotation $root.Values.tserver.podAnnotations $root.Values.tls.enabled) }} + {{- with $root.Values.networkAnnotation }}{{ toYaml . | nindent 8 }}{{ end }} + {{- with $root.Values.tserver.podAnnotations }}{{ toYaml . | nindent 8 }}{{ end }} + {{- if $root.Values.tls.enabled }} + checksum/rootCA: {{ (not $root.Values.tls.rootCAChecksum) | ternary (cat $root.Values.tls.rootCA.cert $root.Values.tls.rootCA.key | sha256sum) $root.Values.tls.rootCAChecksum }} + {{- end }} + {{- end }} + {{- if and (eq $service.name "yb-tservers") ($root.Values.otelCollector.enabled) }} + sidecar.opentelemetry.io/inject: {{ $root.Values.oldNamingStyle | ternary "otel-yb-tserver" (printf "otel-%s-%s" (include "yugabyte.fullname" $root) $service.label) | quote }} + checksum/otel: {{ $root.Values.otelCollector | toYaml | sha256sum }} # Required to trigger a pod restart when the config changes + {{- end}} + {{- end }} + labels: + {{- include "yugabyte.labels" $root | indent 8 }} + {{- include "yugabyte.applabel" ($appLabelArgs) | indent 8 }} + {{- if $root.Values.istioCompatibility.enabled }} + sidecar.istio.io/inject: "true" + {{- end }} + {{- if eq $service.name "yb-masters" }} + {{- with $root.Values.master.podLabels }}{{ toYaml . | nindent 8 }}{{ end }} + {{- else }} + {{- with $root.Values.tserver.podLabels }}{{ toYaml . | nindent 8 }}{{ end }} + {{- end }} + {{- if $root.Values.yugabytedUi.enabled }} + yugabytedUi: "true" + {{- end }} + spec: + {{- if $root.Values.Image.pullSecretName }} + imagePullSecrets: + - name: {{ $root.Values.Image.pullSecretName }} + {{ end }} + {{- $priorityClassName := "" }} + {{- if eq $service.name "yb-masters" }} + {{- $priorityClassName = $root.Values.master.priorityClassName | default $root.Values.priorityClassName }} + {{- else }} + {{- $priorityClassName = $root.Values.tserver.priorityClassName | default $root.Values.priorityClassName }} + {{- end }} + {{- if $priorityClassName }} + priorityClassName: {{ $priorityClassName | quote }} + {{- end }} + {{- if $root.Values.podSecurityContext.enabled }} + securityContext: + fsGroup: {{ $root.Values.podSecurityContext.fsGroup }} + runAsUser: {{ required "runAsUser cannot be empty" $root.Values.podSecurityContext.runAsUser }} + {{- if ne $root.Values.podSecurityContext.runAsGroup nil }} + runAsGroup: {{ $root.Values.podSecurityContext.runAsGroup }} + {{- else }} + runAsGroup: {{ $root.Values.podSecurityContext.runAsUser }} + {{- end }} + runAsNonRoot: {{ $root.Values.podSecurityContext.runAsNonRoot }} + {{- if $root.Values.podSecurityContext.additionalSettings }} + {{- toYaml $root.Values.podSecurityContext.additionalSettings | nindent 8 }} + {{- end }} + {{- end }} + {{- if $root.Values.nodeSelector }} + nodeSelector: + {{- with $root.Values.nodeSelector }}{{ toYaml . | nindent 8 }}{{ end }} + {{- end }} + {{- if eq $service.name "yb-masters" }} # yb-masters + {{- with $root.Values.master.serviceAccount }} + serviceAccountName: {{ . }} + {{- end }} + {{- if $root.Values.master.tolerations }} + tolerations: + {{- with $root.Values.master.tolerations }}{{ toYaml . | nindent 8 }}{{ end }} + {{- end }} + {{- else }} # yb-tservers + {{- with $root.Values.tserver.serviceAccount }} + serviceAccountName: {{ . }} + {{- end }} + {{- if $root.Values.tserver.tolerations }} + tolerations: + {{- with $root.Values.tserver.tolerations }}{{ toYaml . | nindent 8 }}{{ end }} + {{- end }} + {{- end }} + terminationGracePeriodSeconds: 300 + affinity: + # Set the anti-affinity selector scope to YB masters and tservers. + {{- $nodeAffinityData := dict}} + {{- if eq $service.name "yb-masters" -}} + {{- $nodeAffinityData = get $root.Values.master.affinity "nodeAffinity" | default (dict) -}} + {{- else -}} + {{- $nodeAffinityData = get $root.Values.tserver.affinity "nodeAffinity" | default (dict) -}} + {{- end -}} + {{ if $root.Values.AZ }} + {{- $userSelectorTerms := dig "requiredDuringSchedulingIgnoredDuringExecution" "nodeSelectorTerms" "" $nodeAffinityData | default (list) -}} + {{- $baseAffinity := include "yugabyte.multiAZNodeAffinity" $root | fromYaml -}} + {{- $requiredSchedule := (list) -}} + {{- if $userSelectorTerms -}} + {{- range $userSelectorTerms -}} + {{- $userTerm := . -}} + {{- range $baseAffinity.requiredDuringSchedulingIgnoredDuringExecution.nodeSelectorTerms -}} + {{- $matchExpr := concat .matchExpressions $userTerm.matchExpressions | dict "matchExpressions" -}} + {{- $requiredSchedule = mustMerge $matchExpr $userTerm | append $requiredSchedule -}} + {{- end -}} + {{- end -}} + {{- else -}} + {{- $requiredSchedule = $baseAffinity.requiredDuringSchedulingIgnoredDuringExecution.nodeSelectorTerms -}} + {{- end -}} + + {{- with $baseAffinity.requiredDuringSchedulingIgnoredDuringExecution -}} + {{- $_ := set . "nodeSelectorTerms" $requiredSchedule -}} + {{- end -}} + {{- $nodeAffinityData = mustMerge $baseAffinity $nodeAffinityData -}} + {{- end -}} + + {{- $basePodAntiAffinity := include "yugabyte.podAntiAffinity" ($appLabelArgs) | fromYaml -}} + {{- $podAntiAffinityData := $basePodAntiAffinity -}} + {{- if eq $service.name "yb-masters" -}} + {{- with $root.Values.master.affinity -}} + {{- $userPodAntiAffinity := get . "podAntiAffinity" | default (dict) -}} + {{- if $userPodAntiAffinity -}} + {{- $preferredList := dig "preferredDuringSchedulingIgnoredDuringExecution" "" $userPodAntiAffinity | default (list) | concat $basePodAntiAffinity.preferredDuringSchedulingIgnoredDuringExecution}} + {{- $_ := set $basePodAntiAffinity "preferredDuringSchedulingIgnoredDuringExecution" $preferredList -}} + {{- end -}} + {{- $podAntiAffinityData = mustMerge $basePodAntiAffinity $userPodAntiAffinity -}} + {{- end -}} + {{- else -}} + {{- with $root.Values.tserver.affinity -}} + {{- $userPodAntiAffinity := get . "podAntiAffinity" | default (dict) -}} + {{- if $userPodAntiAffinity -}} + {{- $preferredList := dig "preferredDuringSchedulingIgnoredDuringExecution" "" $userPodAntiAffinity | default (list) | concat $basePodAntiAffinity.preferredDuringSchedulingIgnoredDuringExecution}} + {{- $_ := set $basePodAntiAffinity "preferredDuringSchedulingIgnoredDuringExecution" $preferredList -}} + {{- end -}} + {{- $podAntiAffinityData = mustMerge $basePodAntiAffinity $userPodAntiAffinity -}} + {{- end -}} + {{- end -}} + + {{- if eq $service.name "yb-masters" -}} + {{- if $nodeAffinityData -}} + {{- $_ := set $root.Values.master.affinity "nodeAffinity" $nodeAffinityData -}} + {{- end -}} + {{- $_ := set $root.Values.master.affinity "podAntiAffinity" $podAntiAffinityData -}} + {{ toYaml $root.Values.master.affinity | nindent 8 }} + {{- else -}} + {{- if $nodeAffinityData -}} + {{- $_ := set $root.Values.tserver.affinity "nodeAffinity" $nodeAffinityData -}} + {{- end -}} + {{- $_ := set $root.Values.tserver.affinity "podAntiAffinity" $podAntiAffinityData -}} + {{ toYaml $root.Values.tserver.affinity | nindent 8 }} + {{ end }} + {{- with $root.Values.dnsConfig }} + dnsConfig: {{- toYaml . | nindent 8 }} + {{- end }} + {{- with $root.Values.dnsPolicy }} + dnsPolicy: {{ . | quote }} + {{- end }} + {{- if and $root.Values.tls.enabled $root.Values.tls.certManager.enabled }} + initContainers: + - name: certmanager-init + image: {{ $root.Values.Image.repository }}:{{ $root.Values.Image.tag }} + imagePullPolicy: {{ $root.Values.Image.pullPolicy }} + {{- if $root.Values.containerSecurityContext.enabled }} + {{- include "getSecurityContext" $root | nindent 10 }} + {{- end }} + command: + - "/bin/bash" + - "-c" + - | + {{ $serverFqdn := include "yugabyte.server_fqdn" $serviceValues }} + mkdir -p /mnt/disk0/certs; + chmod u+x /mnt/disk0/certs; + if [ -L /mnt/disk0/certs/certs ]; then + echo "Cleaning up old recursive symlink at /mnt/disk0/certs/certs if it exists"; + chmod --reference="$(dirname /mnt/disk0/certs)" /mnt/disk0/certs + rm -f /mnt/disk0/certs/certs; + fi + echo "Creating ephemeral /opt/certs/yugabyte/ as symlink to persisted /mnt/disk0/certs/" + ln -sF /mnt/disk0/certs /opt/certs/yugabyte + # Copy the root CA certificate to the persistent volume + cp /home/yugabyte/cert-manager/ca.crt /mnt/disk0/certs/ca.crt; + + if [[ -s /home/yugabyte/cert-manager/tls.crt ]]; then + echo "Verifying TLS certificate..." + echo "Running: openssl verify -CAfile /mnt/disk0/certs/ca.crt -untrusted /home/yugabyte/cert-manager/tls.crt /home/yugabyte/cert-manager/tls.crt" + openssl verify -CAfile /mnt/disk0/certs/ca.crt -untrusted /home/yugabyte/cert-manager/tls.crt /home/yugabyte/cert-manager/tls.crt; verifyResult=$?; + if [[ $verifyResult -eq 0 ]]; then + echo "TLS certificate is signed by the CA. Copying to persistent volume."; + cp /home/yugabyte/cert-manager/tls.crt /mnt/disk0/certs/node.{{$serverFqdn}}.crt; + cp /home/yugabyte/cert-manager/tls.key /mnt/disk0/certs/node.{{$serverFqdn}}.key; + else + echo "TLS certificate is not signed by the CA. Checking for existing certificates."; + if [[ -f /mnt/disk0/certs/node.{{$serverFqdn}}.crt ]]; then + echo "Validating existing certificates."; + echo "Running: openssl verify -CAfile /mnt/disk0/certs/ca.crt -untrusted /mnt/disk0/certs/node.{{$serverFqdn}}.crt /mnt/disk0/certs/node.{{$serverFqdn}}.crt" + openssl verify -CAfile /mnt/disk0/certs/ca.crt -untrusted /mnt/disk0/certs/node.{{$serverFqdn}}.crt /mnt/disk0/certs/node.{{$serverFqdn}}.crt; verifyResult=$?; + if [[ $verifyResult -eq 0 ]]; then + echo "Existing certificates are valid. Using them."; + else + echo "Existing certificates are not valid. Exiting."; + exit 1; + fi + else + echo "No existing certificates found. Certificates provided by cert-manager are not valid. Exiting. Please ensure certificates are valid and try again."; + exit 1; + fi + fi + else + echo "Using existing server certificate." + fi + # Always normalize cert permissions here; + # existing-cert path can otherwise retain group-writable (660) modes in non-root universes. + chmod 600 /mnt/disk0/certs/*; + + volumeMounts: + {{- if not $storageEphemeral }} + - name: {{ $root.Values.oldNamingStyle | ternary (printf "datadir0") (printf "%s0" (include "yugabyte.volume_name" $root)) }} + mountPath: /mnt/disk0 + {{- end }} + - name: {{ $root.Values.oldNamingStyle | ternary (printf "%s%s-yugabyte-tls-cert" $service.label $stsIndexSuffix) (printf "%s-%s%s-tls-cert" (include "yugabyte.fullname" $root) $service.label $stsIndexSuffix) }} + mountPath: /home/yugabyte/cert-manager + readOnly: true + - name: certs-dir + mountPath: /opt/certs + env: + - name: HOSTNAME + valueFrom: + fieldRef: + fieldPath: metadata.name + - name: NAMESPACE + valueFrom: + fieldRef: + fieldPath: metadata.namespace + {{- end }} + containers: + - name: "{{ $service.label }}" + image: "{{ $root.Values.Image.repository }}:{{ $root.Values.Image.tag }}" + imagePullPolicy: {{ $root.Values.Image.pullPolicy }} + {{- if $root.Values.containerSecurityContext.enabled }} + {{- include "getSecurityContext" $root | nindent 8 }} + {{- end }} + lifecycle: + postStart: + exec: + command: + - "bash" + - "-c" + - > + mkdir -p /mnt/disk0/cores; + mkdir -p /mnt/disk0/yb-data/scripts; + if [ ! -f /mnt/disk0/yb-data/scripts/log_cleanup.sh ]; then + if [ -f /home/yugabyte/bin/log_cleanup.sh ]; then + cp /home/yugabyte/bin/log_cleanup.sh /mnt/disk0/yb-data/scripts; + fi; + fi + {{- if (and (not $storageEphemeral) (not $service.skipHealthChecks)) }} + {{- if $root.Values.livenessProbe.enabled }} + {{- if $root.Values.customLivenessProbe }} + livenessProbe: {{- toYaml $root.Values.customLivenessProbe | nindent 10 }} + {{- else }} + livenessProbe: + exec: + command: + - bash + - -v + - -c + - | + {{- include "yugabyte.fs_data_dirs_probe" $storageInfo | nindent 14 }}; + exit_code="$?"; + echo "disk check exited with: ${exit_code}"; + exit "${exit_code}" + failureThreshold: {{ $root.Values.livenessProbe.failureThreshold }} + periodSeconds: {{ $root.Values.livenessProbe.periodSeconds }} + successThreshold: {{ $root.Values.livenessProbe.successThreshold }} + timeoutSeconds: {{ $root.Values.livenessProbe.timeoutSeconds }} + {{- end }} + {{- end }} + {{- if (and (eq $service.name "yb-masters") (include "yugabyte.master.startupProbe" $root)) }} + startupProbe: {{- include "yugabyte.master.startupProbe" $root | nindent 10 }} + {{- else if (and (eq $service.name "yb-tservers") (include "yugabyte.tserver.startupProbe" $root)) }} + startupProbe: {{- include "yugabyte.tserver.startupProbe" $root | nindent 10 }} + {{- end }} + {{- end }} + {{- if (and (eq $service.name "yb-masters") (include "yugabyte.master.readinessProbe" $root)) }} + readinessProbe: {{- include "yugabyte.master.readinessProbe" $root | nindent 10 }} + {{- else if (and (eq $service.name "yb-tservers") (include "yugabyte.tserver.readinessProbe" $root)) }} + readinessProbe: {{- include "yugabyte.tserver.readinessProbe" $root | nindent 10 }} + {{- end }} + env: + - name: POD_IP + valueFrom: + fieldRef: + fieldPath: status.podIP + - name: HOSTNAME + valueFrom: + fieldRef: + fieldPath: metadata.name + - name: NAMESPACE + valueFrom: + fieldRef: + fieldPath: metadata.namespace + - name: YBDEVOPS_CORECOPY_DIR + value: "/mnt/disk0/cores" + - name: CERT_MANAGER_ENABLED + value: {{ $root.Values.tls.certManager.enabled | quote }} + - name: SERVER_FQDN + value: {{ include "yugabyte.server_fqdn" $serviceValues }} + {{- if eq $service.name "yb-masters" }} + {{- with $root.Values.master.extraEnv }}{{ toYaml . | nindent 8 }}{{- end }} + {{- $data := dict "secretenv" $root.Values.master.secretEnv "root" $root "suffix" "master"}} + {{- include "yugabyte.addenvsecrets" $data | nindent 8 }} + {{- else }} + {{- with $root.Values.tserver.extraEnv }}{{ toYaml . | nindent 8 }}{{- end }} + {{- $data := dict "secretenv" $root.Values.tserver.secretEnv "root" $root "suffix" "tserver" }} + {{- include "yugabyte.addenvsecrets" $data | nindent 8 }} + {{- end }} + {{- if and $root.Values.tls.enabled $root.Values.tls.clientToServer (ne $service.name "yb-masters") }} + - name: SSL_CERTFILE + value: /root/.yugabytedb/root.crt + {{- end }} + resources: + {{- if eq $service.name "yb-masters" }} +{{ toYaml $root.Values.resource.master | indent 10 }} + {{ else }} +{{ toYaml $root.Values.resource.tserver | indent 10 }} + {{ end }} + # core dumps are collected to workingDir if + # kernel.core_pattern is set to a relative path like + # core.%e.%p.%t ref: + # https://github.com/yugabyte/charts/issues/11 + workingDir: "/mnt/disk0/cores" + command: + - "/sbin/tini" + - "--" + args: + - "/bin/bash" + - "-c" + - | + {{- $preCommands := ( (eq $service.name "yb-masters") | ternary $root.Values.master.advanced.preCommands $root.Values.tserver.advanced.preCommands ) }} {{- with $preCommands }} {{ . | nindent 12 }} {{- end }} + {{- if and (not $root.Values.preflight.skipUlimit) (not $root.Values.preflight.skipAll) }} + if [ -f /home/yugabyte/tools/k8s_preflight.py ]; then + /home/yugabyte/tools/k8s_preflight.py all + fi && \ + {{- end }} + {{- if (and (not $storageEphemeral) (not $root.Values.preflight.skipAll)) }} + {{- include "yugabyte.fs_data_dirs_probe" $storageInfo | nindent 12 }} && \ + {{- end }} + {{- $rpcAddr := include "yugabyte.rpc_bind_address" $serviceValues -}} + {{- $rpcPort := index $service.ports "tcp-rpc-port" -}} + {{- $rpcDict := dict "Addr" $rpcAddr "Port" $rpcPort -}} + {{- $rpcPreflight := include "yugabyte.preflight_check" (set $serviceValues "Preflight" $rpcDict) -}} + {{- if $rpcPreflight -}}{{ $rpcPreflight | nindent 12 }}{{ end -}} + {{- $broadcastAddr := include "yugabyte.server_broadcast_address" $serviceValues -}} + {{/* skip bind check for servicePerPod multi-cluster, we cannot/don't bind to service IP */}} + {{- if not $root.Values.multicluster.createServicePerPod }} + {{- $broadcastPort := index $service.ports "tcp-rpc-port" -}} + {{- $broadcastDict := dict "Addr" $broadcastAddr "Port" $broadcastPort -}} + {{- $broadcastPreflight := include "yugabyte.preflight_check" (set $serviceValues "Preflight" $broadcastDict) -}} + {{- if $broadcastPreflight -}}{{ $broadcastPreflight | nindent 12 }}{{ end -}} + {{- end }} + {{- $webserverAddr := include "yugabyte.webserver_interface" $serviceValues -}} + {{- $webserverPort := index $service.ports "http-ui" -}} + {{- $webserverDict := dict "Addr" $webserverAddr "Port" $webserverPort -}} + {{- $webserverPreflight := include "yugabyte.preflight_check" (set $serviceValues "Preflight" $webserverDict) -}} + {{- if $webserverPreflight -}}{{ $webserverPreflight | nindent 12 }}{{ end }} + if [[ -f /home/yugabyte/bin/post_install.sh ]]; then + /home/yugabyte/bin/post_install.sh + fi && \ + if [[ -f /home/yugabyte/tools/k8s_parent.py ]]; then + k8s_parent="/home/yugabyte/tools/k8s_parent.py" + else + k8s_parent="" + fi && \ + {{- if eq $service.name "yb-masters" }} + mkdir -p /tmp/yugabyte/master/conf && \ + envsubst < /opt/master/conf/server.conf.template > /tmp/yugabyte/master/conf/server.conf && \ + exec ${k8s_parent} /home/yugabyte/bin/yb-master \ + --flagfile /tmp/yugabyte/master/conf/server.conf + {{- else }} + {{- $cqlAddr := include "yugabyte.cql_proxy_bind_address" $serviceValues -}} + {{- $cqlPort := index $service.ports "tcp-yql-port" -}} + {{- $cqlDict := dict "Addr" $cqlAddr "Port" $cqlPort -}} + {{- $cqlPreflight := include "yugabyte.preflight_check" (set $serviceValues "Preflight" $cqlDict) -}} + {{- if $cqlPreflight -}}{{ $cqlPreflight | nindent 12 }}{{ end -}} + {{- $ysqlAddr := include "yugabyte.pgsql_proxy_bind_address" $serviceValues -}} + {{- $ysqlPort := index $service.ports "tcp-ysql-port" -}} + {{- if not $root.Values.disableYsql -}} + {{- $ysqlDict := dict "Addr" $ysqlAddr "Port" $ysqlPort -}} + {{- $ysqlPreflight := include "yugabyte.preflight_check" (set $serviceValues "Preflight" $ysqlDict) -}} + {{- if $ysqlPreflight -}}{{ $ysqlPreflight | nindent 12 }}{{ end -}} + {{- end }} + mkdir -p /tmp/yugabyte/tserver/conf && \ + envsubst < /opt/tserver/conf/server.conf.template > /tmp/yugabyte/tserver/conf/server.conf && \ + exec ${k8s_parent} /home/yugabyte/bin/yb-tserver \ + --flagfile /tmp/yugabyte/tserver/conf/server.conf + {{- end }} + ports: + {{- range $label, $port := $service.ports }} + {{- if (eq $label "yugabyted-ui") }} + {{- if $root.Values.yugabytedUi.enabled }} + - containerPort: {{ $port }} + name: {{ $label | quote }} + {{- end }} + {{- else if not (or (eq $label "grpc-ybc-port") (eq $label "tcp-ybc-port"))}} + - containerPort: {{ $port }} + name: {{ $label | quote }} + {{- end }} + {{- end}} + volumeMounts: + {{- if (eq $service.name "yb-tservers") }} + - name: tserver-tmp + mountPath: /tmp + - name: tserver-gflags + mountPath: /opt/tserver/conf + {{- else if (eq $service.name "yb-masters") }} + - name: master-gflags + mountPath: /opt/master/conf + {{- end }} + - name: debug-hooks-volume + mountPath: /opt/debug_hooks_config + {{ if not $storageEphemeral }} + {{- range $index := until (int ($storageInfo.count)) }} + - name: {{ $root.Values.oldNamingStyle | ternary (printf "datadir%d" $index) (printf "%s%d" (include "yugabyte.volume_name" $root) $index) }} + mountPath: /mnt/disk{{ $index }} + {{- end }} + {{- end }} + {{- if $root.Values.tls.enabled }} + - name: {{ $root.Values.oldNamingStyle | ternary (printf "%s%s-yugabyte-tls-cert" $service.label $stsIndexSuffix) (printf "%s-%s%s-tls-cert" (include "yugabyte.fullname" $root) $service.label $stsIndexSuffix) }} + mountPath: {{ $root.Values.tls.certManager.enabled | ternary "/home/yugabyte/cert-manager" "/opt/certs/yugabyte" }} + readOnly: true + {{- if $root.Values.tls.certManager.enabled }} + - name: certs-dir + mountPath: /opt/certs + {{- end }} + - name: {{ $root.Values.oldNamingStyle | ternary "yugabyte-tls-client-cert" (printf "%s-client-tls" (include "yugabyte.fullname" $root)) }} + mountPath: /root/.yugabytedb/ + readOnly: true + {{- end }} + {{- if and (eq $service.name "yb-masters") ($root.Values.master.extraVolumeMounts) -}} + {{- include "yugabyte.isExtraVolumesMappingExists" $root.Values.master -}} + {{- $root.Values.master.extraVolumeMounts | toYaml | nindent 10 -}} + {{- else if and (eq $service.name "yb-tservers") ($root.Values.tserver.extraVolumeMounts) -}} + {{- include "yugabyte.isExtraVolumesMappingExists" $root.Values.tserver -}} + {{- $root.Values.tserver.extraVolumeMounts | toYaml | nindent 10 -}} + {{- end -}} + + {{ if not $storageEphemeral }} + - name: yb-cleanup + image: "{{ $root.Values.Image.repository }}:{{ $root.Values.Image.tag }}" + imagePullPolicy: {{ $root.Values.Image.pullPolicy }} + {{- if $root.Values.containerSecurityContext.enabled }} + {{- include "getSecurityContext" $root | nindent 8 }} + {{- end }} + env: + - name: USER + value: "yugabyte" + {{- if $root.Values.otelCollector.enabled }} + - name: PRESERVE_AUDIT_LOGS # Allows the exporter sufficient time to collect logs before they are deleted. + value: "true" + {{- end }} + command: + - "/sbin/tini" + - "--" + args: + - "/bin/bash" + - "-c" + - > + while true; do + sleep 3600; + /home/yugabyte/scripts/log_cleanup.sh; + done + volumeMounts: + - name: {{ $root.Values.oldNamingStyle | ternary "datadir0" (printf "%s0" (include "yugabyte.volume_name" $root)) }} + mountPath: /home/yugabyte/ + subPath: yb-data + - name: {{ $root.Values.oldNamingStyle | ternary "datadir0" (printf "%s0" (include "yugabyte.volume_name" $root)) }} + mountPath: /var/yugabyte/cores + subPath: cores + {{- if $root.Values.ybCleanup.resources }} + resources: {{ toYaml $root.Values.ybCleanup.resources | nindent 10 }} + {{- end }} + {{- end }} + + {{- if $root.Values.yugabytedUi.enabled }} + - name: yugabyted-ui + image: "{{ $root.Values.Image.repository }}:{{ $root.Values.Image.tag }}" + imagePullPolicy: "IfNotPresent" + {{- if $root.Values.containerSecurityContext.enabled }} + {{- include "getSecurityContext" $root | nindent 8 }} + {{- end }} + env: + - name: HOSTNAME + valueFrom: + fieldRef: + fieldPath: metadata.name + - name: NAMESPACE + valueFrom: + fieldRef: + fieldPath: metadata.namespace + - name: YUGABYTED_UI_K8S + value: "true" + command: + - "/sbin/tini" + - "--" + args: + - "/bin/bash" + - "-c" + - | + {{- if $root.Values.yugabytedUi.recoverWithoutFailure }} + while true; do + {{- end }} + /home/yugabyte/bin/yugabyted-ui \ + {{- $rpcAddr := include "yugabyte.rpc_bind_address" $serviceValues }} + -database_host={{ $rpcAddr }} \ + {{- $webserverAddr := include "yugabyte.webserver_interface" $serviceValues }} + -bind_address={{ $webserverAddr }} \ + {{- $masterPort := "7000" }} + {{- $tserverPort := "9000" }} + {{- $ysqlPort := "5433" }} + {{- $ycqlPort := "9042" }} + {{- range $root.Values.Services -}} + {{- if eq .name "yb-masters" -}} + {{- $masterPort = index .ports "http-ui" -}} + {{- else if eq .name "yb-tservers" -}} + {{- $tserverPort = index .ports "http-ui" -}} + {{- $ysqlPort = index .ports "tcp-ysql-port" -}} + {{- $ycqlPort = index .ports "tcp-yql-port" -}} + {{- end -}} + {{- end }} + -ysql_port={{ $ysqlPort }} \ + -ycql_port={{ $ycqlPort }} \ + -master_ui_port={{ $masterPort }} \ + -tserver_ui_port={{ $tserverPort }} \ + {{- if $root.Values.tls.enabled }} + -secure={{ $root.Values.tls.enabled }} \ + {{- end }} + {{- if $root.Values.authCredentials.ysql.user }} + -ysql_username={{ $root.Values.authCredentials.ysql.user }} \ + {{- end }} + {{- if $root.Values.authCredentials.ycql.user }} + -ycql_username={{ $root.Values.authCredentials.ycql.user }} \ + {{- end }} + {{- if $root.Values.authCredentials.ysql.password }} + -ysql_password={{ $root.Values.authCredentials.ysql.password }} \ + {{- end }} + {{- if $root.Values.authCredentials.ycql.password }} + -ycql_password={{ $root.Values.authCredentials.ycql.password }} \ + {{- end }} + || echo "ERROR: yugabyted-ui failed. This might be because your yugabyte \ + version is older than 2.21.0. If this is the case, set yugabytedUi.enabled to false \ + in helm to disable yugabyted-ui, or upgrade to a version 2.21.0 or newer."; \ + {{- if $root.Values.yugabytedUi.recoverWithoutFailure }} + echo "Attempting restart in {{ $root.Values.yugabytedUi.recoveryInterval }}." + trap break TERM INT; \ + sleep {{ $root.Values.yugabytedUi.recoveryInterval }} & wait; \ + trap - TERM INT; + done \ + {{- end }} + {{- end }} + + {{- if and (eq $service.name "yb-tservers") ($root.Values.ybc.enabled) }} + - name: yb-controller + image: "{{ $root.Values.Image.repository }}:{{ $root.Values.Image.tag }}" + imagePullPolicy: {{ $root.Values.Image.pullPolicy }} + {{- if $root.Values.containerSecurityContext.enabled }} + {{- include "getSecurityContext" $root | nindent 8 }} + {{- end }} + {{- if $root.Values.ybc.useYBDBImage }} + env: + - name: POD_IP + valueFrom: + fieldRef: + fieldPath: status.podIP + - name: HOSTNAME + valueFrom: + fieldRef: + fieldPath: metadata.name + - name: NAMESPACE + valueFrom: + fieldRef: + fieldPath: metadata.namespace + - name: YBDEVOPS_CORECOPY_DIR + value: "/mnt/disk0/cores" + workingDir: "/mnt/disk0/cores" + command: + - "/sbin/tini" + - "--" + args: + - "/bin/bash" + - "-c" + - | + if [[ -f /home/yugabyte/tools/k8s_parent.py ]]; then + k8s_parent="/home/yugabyte/tools/k8s_parent.py" + else + k8s_parent="" + fi && \ + mkdir -p /tmp/yugabyte/controller/conf && \ + envsubst < /opt/controller/conf/server.conf.template > /tmp/yugabyte/controller/conf/server.conf && \ + exec ${k8s_parent} /home/yugabyte/controller/bin/yb-controller-server \ + --flagfile /tmp/yugabyte/controller/conf/server.conf + {{- else }} + lifecycle: + postStart: + exec: + command: + - "bash" + - "-c" + - > + mkdir -p /mnt/disk0/yw-data/controller/tmp; + mkdir -p /mnt/disk0/yw-data/controller/conf; + mkdir -p /mnt/disk0/ybc-data/controller/logs; + mkdir -p /tmp/yugabyte/controller; + ln -sf /mnt/disk0/ybc-data/controller/logs /tmp/yugabyte/controller; + ln -sf /mnt/disk0/yw-data/controller/bin /tmp/yugabyte/controller; + rm -f /tmp/yugabyte/controller/yb-controller.pid; + command: + - "/sbin/tini" + - "--" + args: + - "/bin/bash" + - "-c" + - > + while true; do + sleep 60; + /home/yugabyte/tools/k8s_ybc_parent.py status || /home/yugabyte/tools/k8s_ybc_parent.py start; + done + {{- end }} + {{- range $label, $port := $service.ports }} + {{- if or (eq $label "grpc-ybc-port") (eq $label "tcp-ybc-port")}} + ports: + - containerPort: {{ $port }} + name: "tcp-ybc-port" + {{- end }} + {{- end }} + volumeMounts: + - name: tserver-tmp + mountPath: /tmp + {{- if $root.Values.ybc.useYBDBImage }} + - name: controller-gflags + mountPath: /opt/controller/conf + {{- end }} + {{- if not $storageEphemeral }} + {{- range $index := until (int ($storageInfo.count)) }} + - name: {{ $root.Values.oldNamingStyle | ternary (printf "datadir%d" $index) (printf "%s%d" (include "yugabyte.volume_name" $root) $index) }} + mountPath: /mnt/disk{{ $index }} + {{- end }} + {{- end }} + {{- if $root.Values.tls.enabled }} + - name: {{ $root.Values.oldNamingStyle | ternary (printf "%s%s-yugabyte-tls-cert" $service.label $stsIndexSuffix) (printf "%s-%s%s-tls-cert" (include "yugabyte.fullname" $root) $service.label $stsIndexSuffix) }} + mountPath: {{ $root.Values.tls.certManager.enabled | ternary "/home/yugabyte/cert-manager" "/opt/certs/yugabyte" }} + readOnly: true + {{- if $root.Values.tls.certManager.enabled }} + - name: certs-dir + mountPath: /opt/certs + {{- end }} + {{- end }} + {{- if ($root.Values.tserver.extraVolumeMounts) -}} + {{- include "yugabyte.isExtraVolumesMappingExists" $root.Values.tserver -}} + {{- $root.Values.tserver.extraVolumeMounts | toYaml | nindent 10 -}} + {{- end -}} + {{- if $root.Values.ybc.resources }} + resources: {{ toYaml $root.Values.ybc.resources | nindent 10 }} + {{- end }} + {{- end}} + + volumes: + {{- if (eq $service.name "yb-masters") }} + - name: debug-hooks-volume + configMap: + name: {{ include "yugabyte.fullname" $root }}-master-hooks + defaultMode: 0755 + - name: master-gflags + secret: + secretName: {{ printf "%s%s-master-gflags" (include "yugabyte.fullname" $root) $stsIndexSuffix }} + defaultMode: 0755 + {{- else if (eq $service.name "yb-tservers") }} + - name: debug-hooks-volume + configMap: + name: {{ include "yugabyte.fullname" $root }}-tserver-hooks + defaultMode: 0755 + - name: tserver-gflags + secret: + secretName: {{ printf "%s%s-tserver-gflags" (include "yugabyte.fullname" $root) $stsIndexSuffix }} + defaultMode: 0755 + {{- if $root.Values.ybc.useYBDBImage }} + - name: controller-gflags + secret: + secretName: {{ include "yugabyte.fullname" $root }}-controller-gflags + defaultMode: 0755 + {{- end }} + - name: tserver-tmp + emptyDir: {} + {{- end }} + {{- if $root.Values.tls.enabled }} + {{- if $root.Values.tls.certManager.enabled }} + {{- /* certManager enabled */}} + - name: {{ $root.Values.oldNamingStyle | ternary (printf "%s%s-yugabyte-tls-cert" $service.label $stsIndexSuffix) (printf "%s-%s%s-tls-cert" (include "yugabyte.fullname" $root) $service.label $stsIndexSuffix) }} + projected: + sources: + - secret: + name: {{ $root.Values.oldNamingStyle | ternary (printf "%s%s-yugabyte-tls-cert" $service.label $stsIndexSuffix) (printf "%s-%s%s-tls-cert" (include "yugabyte.fullname" $root) $service.label $stsIndexSuffix) }} + {{- if and (not $root.Values.tls.certManager.bootstrapSelfsigned) (not (empty $root.Values.tls.rootCA.cert)) }} + - secret: + name: {{ printf "%s-root-ca" (include "yugabyte.fullname" $root) }} + {{- end }} + - name: {{ $root.Values.oldNamingStyle | ternary "yugabyte-tls-client-cert" (printf "%s-client-tls" (include "yugabyte.fullname" $root)) }} + projected: + sources: + {{- /* get the ca.crt from values or cert-manager */}} + {{- if and (not $root.Values.tls.certManager.bootstrapSelfsigned) (not (empty $root.Values.tls.rootCA.cert)) }} + - secret: + name: {{ printf "%s-root-ca" (include "yugabyte.fullname" $root) }} + items: + - key: ca.crt + path: root.crt + {{- else }} + - secret: + name: {{ $root.Values.oldNamingStyle | ternary "yugabyte-tls-client-cert" (printf "%s-client-tls" (include "yugabyte.fullname" $root)) }} + items: + - key: ca.crt + path: root.crt + {{- end }} + {{- /* finally mount the tls client cert and key from cert-manager */}} + - secret: + name: {{ $root.Values.oldNamingStyle | ternary "yugabyte-tls-client-cert" (printf "%s-client-tls" (include "yugabyte.fullname" $root)) }} + items: + - key: tls.crt + path: yugabytedb.crt + - key: tls.key + path: yugabytedb.key + defaultMode: 256 + - name: certs-dir + emptyDir: {} + {{- else }} + {{/* certManager disabled */}} + - name: {{ $root.Values.oldNamingStyle | ternary (printf "%s%s-yugabyte-tls-cert" $service.label $stsIndexSuffix) (printf "%s-%s%s-tls-cert" (include "yugabyte.fullname" $root) $service.label $stsIndexSuffix) }} + secret: + secretName: {{ $root.Values.oldNamingStyle | ternary (printf "%s%s-yugabyte-tls-cert" $service.label $stsIndexSuffix) (printf "%s-%s%s-tls-cert" (include "yugabyte.fullname" $root) $service.label $stsIndexSuffix) }} + defaultMode: 256 + - name: {{ $root.Values.oldNamingStyle | ternary "yugabyte-tls-client-cert" (printf "%s-client-tls" (include "yugabyte.fullname" $root)) }} + secret: + secretName: {{ $root.Values.oldNamingStyle | ternary "yugabyte-tls-client-cert" (printf "%s-client-tls" (include "yugabyte.fullname" $root)) }} + defaultMode: 256 + {{- end }} + {{- end }} + {{- if and (eq $service.name "yb-masters") ($root.Values.master.extraVolumes) -}} + {{- include "yugabyte.isExtraVolumesMappingExists" $root.Values.master -}} + {{- $root.Values.master.extraVolumes | toYaml | nindent 8 -}} + {{- else if and (eq $service.name "yb-tservers") ($root.Values.tserver.extraVolumes) -}} + {{- include "yugabyte.isExtraVolumesMappingExists" $root.Values.tserver -}} + {{- $root.Values.tserver.extraVolumes | toYaml | nindent 8 -}} + {{- end -}} +{{- end }} +{{- end }} +{{- if and $root.Values.useOldPodDisruptionBudget (not $root.Values.isMultiAz) }} +--- +{{/* +TODO: switch to policy/v1 completely when we stop supporting +Kubernetes versions < 1.21 +*/}} +{{- if $root.Capabilities.APIVersions.Has "policy/v1/PodDisruptionBudget" }} +apiVersion: policy/v1 +{{- else }} +apiVersion: policy/v1beta1 +{{- end }} +kind: PodDisruptionBudget +metadata: + name: {{ $root.Values.oldNamingStyle | ternary (printf "%s-pdb" $service.label) (printf "%s-%s-pdb" (include "yugabyte.fullname" $root) $service.name) }} + labels: + {{- include "yugabyte.applabel" ($appLabelArgs) | indent 4 }} + {{- include "yugabyte.labels" $root | indent 4 }} +spec: + maxUnavailable: {{ template "yugabyte.max_unavailable_for_quorum" $root }} + selector: + matchLabels: + {{- include "yugabyte.appselector" ($appLabelArgs) | indent 6 }} +{{- end }} +{{- end }} diff --git a/helm-charts/yugabyte/templates/setup-credentials-configmap.yaml b/helm-charts/yugabyte/templates/setup-credentials-configmap.yaml new file mode 100644 index 0000000..f7d845e --- /dev/null +++ b/helm-charts/yugabyte/templates/setup-credentials-configmap.yaml @@ -0,0 +1,264 @@ +{{- if or .Values.authCredentials.ycql.user .Values.authCredentials.ycql.password .Values.authCredentials.ycql.keyspace .Values.authCredentials.ysql.password .Values.authCredentials.ysql.user .Values.authCredentials.ysql.database .Values.authCredentials.ysql.passwordSecretName .Values.authCredentials.ycql.passwordSecretName}} +{{- $appLabelArgs := dict "label" "yugabyte" "root" . -}} +{{- $stsStart := int .Values.stsIndex.tserver.start -}} +{{- $stsIndexSuffix := eq $stsStart 0 | ternary "" (printf "-%d" $stsStart) }} +apiVersion: v1 +kind: ConfigMap +metadata: + name: {{ include "yugabyte.fullname" . }}-setup-credentials-script + namespace: "{{ .Release.Namespace }}" + labels: + {{- include "yugabyte.applabel" ($appLabelArgs) | indent 4 }} + {{- include "yugabyte.labels" . | indent 4 }} +data: + setup-credentials.sh: | + #!/bin/bash + + set -eo pipefail + + # Setup script to setup credentials + + # ----------------------------------------- + # Default Variables + # ----------------------------------------- + + readonly DEFAULT_YSQL_USER="yugabyte" + readonly DEFAULT_YSQL_PASSWORD="yugabyte" + readonly DEFAULT_YSQL_DB="yugabyte" + + readonly DEFAULT_YCQL_USER="cassandra" + readonly DEFAULT_YCQL_PASSWORD="cassandra" + + {{- range .Values.Services }} + {{- $service := . -}} + {{- if eq ($service.name) "yb-tservers" }} + readonly YSQL_PORT={{ index $service.ports "tcp-ysql-port" }} + # TODO: Update the tcp-yql-port to tcp-ycql-port in values.yaml + readonly YCQL_PORT={{ index $service.ports "tcp-yql-port" }} + {{- end }} + {{- end }} + + {{- $serviceName := .Values.oldNamingStyle | ternary (printf "yb-tservers%s" $stsIndexSuffix) (printf "%s-yb-tservers%s" (include "yugabyte.fullname" . ) $stsIndexSuffix) }} + {{- $tserverFQDN := printf "%s.%s.svc.%s" $serviceName .Release.Namespace .Values.domainName }} + + prefix_ysql_cmd=( + /home/yugabyte/bin/ysqlsh -h {{ $tserverFQDN }} + -p "$YSQL_PORT" + ) + + prefix_ycql_cmd=( + /home/yugabyte/bin/ycqlsh {{ $tserverFQDN }} + "$YCQL_PORT" + ) + + {{- if .Values.tls.enabled }} + prefix_ysql_cmd+=("sslmode=require") + prefix_ycql_cmd+=(--ssl) + {{- end }} + + # ----------------------------------------- + # Variables + # ----------------------------------------- + + ysql_user= + ysql_password= + ysql_db= + ycql_user= + ycql_password= + ycql_keyspace= + + # ----------------------------------------- + # Hepler functions + # ----------------------------------------- + + cleanup() { + local exit_code=$? + echo "Exiting with code $exit_code" + exit "$exit_code" + } + + function waitUntilHealthy() { + declare -a ysql_cmd + export PGPASSWORD="$2" + ysql_cmd=( + /home/yugabyte/bin/ysqlsh -h {{ $tserverFQDN }} + -p "$3" + -U "$1" + -c "\\conninfo" + ) + + if [[ "$4" == "true" ]]; then + ysql_cmd+=("sslmode=require") + fi + + echo "${ysql_cmd[@]}" + while ! "${ysql_cmd[@]}"; do + sleep 5s + done + } + + export -f waitUntilHealthy + + get_ysql_credentials() { + [[ -n "$YSQL_USER" ]] && ysql_user="$YSQL_USER" || ysql_user="$DEFAULT_YSQL_USER" + + [[ -n "$YSQL_PASSWORD" ]] && ysql_password="$YSQL_PASSWORD" + + if [[ -z "$YSQL_PASSWORD" ]] && [[ "$ysql_user" != "$DEFAULT_YSQL_USER" ]]; then + ysql_password="$YSQL_USER" + fi + + [[ -n "$YSQL_DB" ]] && ysql_db="$YSQL_DB" + + [[ -z "$YSQL_DB" ]] && [[ -n "$YSQL_USER" ]] && ysql_db="$ysql_user" + + api="ysql" + } + + get_ycql_credentials() { + [[ -n "$YCQL_USER" ]] && ycql_user="$YCQL_USER" || ycql_user="$DEFAULT_YCQL_USER" + + [[ -n "$YCQL_PASSWORD" ]] && ycql_password="$YCQL_PASSWORD" + + if [[ -z "$YCQL_PASSWORD" ]] && [[ "$ycql_user" != "$DEFAULT_YCQL_USER" ]]; then + ycql_password="$YCQL_USER" + fi + + [[ -n "$YCQL_KEYSPACE" ]] && ycql_keyspace="$YCQL_KEYSPACE" + + [[ -z "$YCQL_KEYSPACE" ]] && [[ -n "$YCQL_USER" ]] && ycql_keyspace="$ycql_user" + + api="ycql" + } + + create_user() { + declare -a ysql_cmd + declare -a ycql_cmd + + case "$api" in + "ysql") + export PGPASSWORD="$DEFAULT_YSQL_PASSWORD" + read -r -a ysql_cmd <<< "${prefix_ysql_cmd[@]}" + ysql_cmd+=( + -U "$DEFAULT_YSQL_USER" + -c "CREATE ROLE ${ysql_user} with LOGIN SUPERUSER password '${ysql_password}' ;" + -c "ALTER DATABASE ${ysql_db} OWNER TO ${ysql_user} ;" + ) + "${ysql_cmd[@]}" + ;; + "ycql") + read -r -a ycql_cmd <<< "${prefix_ycql_cmd[@]}" + ycql_cmd+=( + -u "$DEFAULT_YCQL_USER" + -p "$DEFAULT_YCQL_PASSWORD" + -e "CREATE ROLE IF NOT EXISTS ${ycql_user} WITH PASSWORD = '${ycql_password}' AND LOGIN = true AND SUPERUSER = true ;" + ) + "${ycql_cmd[@]}" + ;; + *) exit 1 + esac + } + + update_password() { + declare -a ysql_cmd + declare -a ycql_cmd + + case "$api" in + "ysql") + export PGPASSWORD="$DEFAULT_YSQL_PASSWORD" + read -r -a ysql_cmd <<< "${prefix_ysql_cmd[@]}" + ysql_cmd+=( + -U "$DEFAULT_YSQL_USER" + -c "ALTER ROLE ${ysql_user} WITH PASSWORD '${ysql_password}' ;" + ) + "${ysql_cmd[@]}" + ;; + "ycql") + read -r -a ycql_cmd <<< "${prefix_ycql_cmd[@]}" + ycql_cmd+=( + -u "$DEFAULT_YCQL_USER" + -p "$DEFAULT_YCQL_PASSWORD" + -e "ALTER ROLE ${ycql_user} WITH PASSWORD = '${ycql_password}' ;" + ) + "${ycql_cmd[@]}" + ;; + *) exit 1 + esac + } + + create_container() { + declare -a ysql_cmd + declare -a ycql_cmd + + case "$api" in + "ysql") + export PGPASSWORD="$DEFAULT_YSQL_PASSWORD" + read -r -a ysql_cmd <<< "${prefix_ysql_cmd[@]}" + ysql_cmd+=( + -U "$DEFAULT_YSQL_USER" + -c "CREATE DATABASE ${ysql_db} ;" + ) + "${ysql_cmd[@]}" + ;; + "ycql") + read -r -a ycql_cmd <<< "${prefix_ycql_cmd[@]}" + ycql_cmd+=( + -u "$DEFAULT_YCQL_USER" + -p "$DEFAULT_YCQL_PASSWORD" + -e "CREATE KEYSPACE IF NOT EXISTS ${ycql_keyspace} ;" + ) + "${ycql_cmd[@]}" + ;; + *) exit 1 + esac + } + + # ----------------------------------------- + # Main + # ----------------------------------------- + + trap cleanup EXIT + + echo "Waiting for YugabyteDB to start." + if ! timeout 3m bash -c "waitUntilHealthy ${DEFAULT_YSQL_USER} ${DEFAULT_YSQL_PASSWORD} ${YSQL_PORT} {{ .Values.tls.enabled }}"; then + echo "Timeout while waiting for database" + exit 1 + fi + + # YSQL Credentials + get_ysql_credentials + + ## Create YSQL DB + if [[ -n $ysql_db ]] && [[ "$ysql_db" != "$DEFAULT_YSQL_DB" ]]; then + create_container + fi + + ## Update YSQL Password + if [[ -n $ysql_password ]] && [[ "$ysql_password" != "$DEFAULT_YSQL_PASSWORD" ]] && [[ "$ysql_user" == "$DEFAULT_YSQL_USER" ]]; then + update_password + fi + + ## Create YSQL User + if [[ -n $ysql_user ]] && [[ "$ysql_user" != "$DEFAULT_YSQL_USER" ]]; then + create_user + fi + + # YCQL Credentials + get_ycql_credentials + + ## Create YCQL Keyspace + if [[ -n $ycql_keyspace ]] && [[ -n "$ycql_keyspace" ]]; then + create_container + fi + + ## Update YCQL Password + if [[ -n $ycql_password ]] && [[ "$ycql_password" != "$DEFAULT_YCQL_PASSWORD" ]] && [[ "$ycql_user" == "$DEFAULT_YCQL_USER" ]]; then + update_password + fi + + ## Create YCQL User + if [[ -n $ycql_user ]] && [[ "$ycql_user" != "$DEFAULT_YCQL_USER" ]]; then + create_user + fi + +{{- end }} diff --git a/helm-charts/yugabyte/templates/tserver-gflags-secret.yaml b/helm-charts/yugabyte/templates/tserver-gflags-secret.yaml new file mode 100644 index 0000000..2e26141 --- /dev/null +++ b/helm-charts/yugabyte/templates/tserver-gflags-secret.yaml @@ -0,0 +1,88 @@ +{{- $root := . -}} +{{- range $service := $root.Values.Services }} +{{- if eq $service.name "yb-tservers" }} +{{- $serviceValues := (dict "Service" $service "Values" $root.Values "Chart" $root.Chart "Release" $root.Release) -}} +{{- $appLabelArgs := dict "label" $service.label "root" $root -}} +{{- $vars := include "yugabyte.stsIndexVars" (dict "serviceName" $service.name "root" $root) | fromYaml -}} +{{- $masterStsVars := include "yugabyte.stsIndexVars" (dict "serviceName" "yb-masters" "root" $root) | fromYaml -}} + +{{- range $stsIdx := until (int $vars.stsCount) }} +{{- $loopVars := include "yugabyte.stsIndexLoopVars" (dict "stsIdx" $stsIdx "stsStart" $vars.stsStart "stsEnd" $vars.stsEnd "replicas" $vars.replicas "moveOpReplicas" $vars.moveOpReplicas) | fromYaml -}} +{{- $currentStsIndex := $loopVars.currentStsIndex -}} +{{- $useMoveOp := $loopVars.useMoveOp -}} +{{- $stsIndexSuffix := $loopVars.stsIndexSuffix -}} +{{- $storageInfo := $useMoveOp | ternary $root.Values.moveOp.storage.tserver $root.Values.storage.tserver -}} +{{- $storageEphemeral := $useMoveOp | ternary $root.Values.moveOp.storage.ephemeral $root.Values.storage.ephemeral }} +--- +apiVersion: v1 +kind: Secret +metadata: + name: {{ printf "%s%s-tserver-gflags" (include "yugabyte.fullname" $root) $stsIndexSuffix }} + namespace: "{{ $root.Release.Namespace }}" + labels: + {{- include "yugabyte.applabel" ($appLabelArgs) | indent 4 }} + {{- include "yugabyte.labels" $root | indent 4 }} +type: Opaque +stringData: + server.conf.template: | +{{- if not $storageEphemeral }} + --fs_data_dirs={{ template "yugabyte.fs_data_dirs" $storageInfo }} +{{- else }} + --fs_data_dirs=/var/yugabyte +{{- end }} +{{- if eq $root.Values.ip_version_support "v6_only" }} + --net_address_filter=ipv6_external,ipv6_non_link_local,ipv6_all,ipv4_external,ipv4_all +{{- end }} +{{- if $root.Values.masterAddresses }} + --tserver_master_addrs={{ $root.Values.masterAddresses }} +{{- else }} + --tserver_master_addrs={{ include "yugabyte.master_addresses" (dict "root" $root "vars" $masterStsVars) }} +{{- end }} +{{- if or $root.Values.authCredentials.ysql.password $root.Values.authCredentials.ysql.passwordSecretName }} + --ysql_enable_auth=true + {{- if (include "yugabyte.tserver.readinessProbe" $root) }} + --ysql_hba_conf_csv="local all yugabyte trust" + {{- end }} +{{- end }} +{{- if or $root.Values.authCredentials.ycql.user $root.Values.authCredentials.ycql.password $root.Values.authCredentials.ycql.passwordSecretName }} + --use_cassandra_authentication=true +{{- end }} +{{- if $root.Values.tls.enabled }} + --certs_dir=/opt/certs/yugabyte + --use_node_to_node_encryption={{ $root.Values.tls.nodeToNode }} + --allow_insecure_connections={{ $root.Values.tls.insecure }} + --use_client_to_server_encryption={{ $root.Values.tls.clientToServer }} + --certs_for_client_dir=/opt/certs/yugabyte + {{- if $root.Values.tserver.serverBroadcastAddress }} + --cert_node_filename={{ include "yugabyte.server_fqdn" $serviceValues }} + {{- end }} +{{- end }} +{{- if not $root.Values.disableYsql }} + --enable_ysql=true + --pgsql_proxy_bind_address={{ include "yugabyte.pgsql_proxy_bind_address" $serviceValues }} +{{- else }} + --enable_ysql=false +{{- end }} +{{- if $root.Values.yugabytedUi.enabled }} + --tserver_enable_metrics_snapshotter={{ $root.Values.yugabytedUi.metricsSnapshotter.enabled }} + --metrics_snapshotter_interval_ms={{ $root.Values.yugabytedUi.metricsSnapshotter.interval }} + --metrics_snapshotter_tserver_metrics_whitelist={{ join "," $root.Values.yugabytedUi.metricsSnapshotter.whitelist }} +{{- end }} + --metric_node_name=${EXPORTED_INSTANCE} + --memory_limit_hard_bytes={{ template "yugabyte.memory_hard_limit" dict "size" $root.Values.resource.tserver.limits.memory "limitPercent" $root.Values.tserver.memoryLimitHardPercentage }} + --stderrthreshold=0 + --max_log_size=256 + --num_cpus={{ ceil $root.Values.resource.tserver.requests.cpu }} + --undefok=num_cpus,enable_ysql + --use_node_hostname_for_local_tserver=true + --cql_proxy_bind_address={{ include "yugabyte.cql_proxy_bind_address" $serviceValues }} + --rpc_bind_addresses={{ include "yugabyte.rpc_bind_address" $serviceValues }} + --server_broadcast_addresses={{ $root.Values.tserver.serverBroadcastAddress | default (include "yugabyte.server_broadcast_address" $serviceValues) }} + --webserver_interface={{ include "yugabyte.webserver_interface" $serviceValues }} +{{- range $flag, $override := $root.Values.gflags.tserver }} + --{{ $flag }}={{ $override }} +{{- end }} +{{- end }} +{{- end }} +{{- end }} +--- diff --git a/helm-charts/yugabyte/templates/tserver-servicemonitor.yaml b/helm-charts/yugabyte/templates/tserver-servicemonitor.yaml new file mode 100644 index 0000000..4458e24 --- /dev/null +++ b/helm-charts/yugabyte/templates/tserver-servicemonitor.yaml @@ -0,0 +1,110 @@ +{{- $sm := .Values.serviceMonitor }} +{{ if and $sm.enabled (or $sm.tserver.enabled $sm.ycql.enabled $sm.ysql.enabled $sm.yedis.enabled) }} +{{- $appLabelArgs := dict "label" "yb-tserver" "root" . -}} +apiVersion: monitoring.coreos.com/v1 +kind: ServiceMonitor +metadata: + name: {{ include "yugabyte.fullname" . }}-yb-tserver + labels: + {{- include "yugabyte.applabel" ($appLabelArgs) | indent 4 }} + {{- include "yugabyte.labels" . | indent 4 }} + {{- with .Values.serviceMonitor.extraLabels }} + {{- toYaml . | nindent 4 }} + {{- end }} +spec: + jobLabel: "release" + selector: + matchLabels: + {{- if .Values.oldNamingStyle }} + app: "yb-tserver" + {{- else }} + app.kubernetes.io/name: "yb-tserver" + {{- end }} + release: {{ .Release.Name | quote }} + service-type: "headless" + endpoints: + + {{- with .Values.serviceMonitor.tserver }} + {{- if .enabled }} + - port: {{ .port }} + path: {{ .path }} + {{- if .interval }} + interval: {{ .interval }} + {{- else }} + interval: {{ $.Values.serviceMonitor.interval }} + {{- end }} + relabelings: + - targetLabel: "group" + replacement: "yb-tserver" + - targetLabel: "export_type" + replacement: "tserver_export" + - targetLabel: "node_prefix" + replacement: {{ $.Release.Name | quote }} + metricRelabelings: + {{- toYaml $.Values.serviceMonitor.commonMetricRelabelings | nindent 4 }} + {{- end }} + {{- end }} + + {{- with .Values.serviceMonitor.ycql }} + {{- if .enabled }} + - port: {{ .port }} + path: {{ .path }} + {{- if .interval }} + interval: {{ .interval }} + {{- else }} + interval: {{ $.Values.serviceMonitor.interval }} + {{- end }} + relabelings: + - targetLabel: "group" + replacement: "ycql" + - targetLabel: "export_type" + replacement: "cql_export" + - targetLabel: "node_prefix" + replacement: {{ $.Release.Name | quote }} + metricRelabelings: + {{- toYaml $.Values.serviceMonitor.commonMetricRelabelings | nindent 4 }} + {{- end }} + {{- end }} + + {{- with .Values.serviceMonitor.ysql }} + {{- if .enabled }} + - port: {{ .port }} + path: {{ .path }} + {{- if .interval }} + interval: {{ .interval }} + {{- else }} + interval: {{ $.Values.serviceMonitor.interval }} + {{- end }} + relabelings: + - targetLabel: "group" + replacement: "ysql" + - targetLabel: "export_type" + replacement: "ysql_export" + - targetLabel: "node_prefix" + replacement: {{ $.Release.Name | quote }} + metricRelabelings: + {{- toYaml $.Values.serviceMonitor.commonMetricRelabelings | nindent 4 }} + {{- end }} + {{- end }} + + {{- with .Values.serviceMonitor.yedis }} + {{- if .enabled }} + - port: {{ .port }} + path: {{ .path }} + {{- if .interval }} + interval: {{ .interval }} + {{- else }} + interval: {{ $.Values.serviceMonitor.interval }} + {{- end }} + relabelings: + - targetLabel: "group" + replacement: "yedis" + - targetLabel: "export_type" + replacement: "redis_export" + - targetLabel: "node_prefix" + replacement: {{ $.Release.Name | quote }} + metricRelabelings: + {{- toYaml $.Values.serviceMonitor.commonMetricRelabelings | nindent 4 }} + {{- end }} + {{- end }} +{{- end }} diff --git a/helm-charts/yugabyte/test-labels.sh b/helm-charts/yugabyte/test-labels.sh new file mode 100644 index 0000000..50c332b --- /dev/null +++ b/helm-charts/yugabyte/test-labels.sh @@ -0,0 +1,230 @@ +#!/bin/bash +# Script to test that all objects have Yugabyte labels + +set -e + +RELEASE_NAME="test-yugabyte" +NAMESPACE="default" + +echo "=== Testing Helm Chart Labels ===" +echo "" + +# 1. Lint the chart +echo "1. Running helm lint..." +helm lint . || echo "WARNING: Lint found issues" +echo "" + +# 2. Render templates and save to file +echo "2. Rendering templates..." +# Check if custom labels should be tested +if [ -n "$TEST_CUSTOM_LABELS" ] && [ "$TEST_CUSTOM_LABELS" = "true" ]; then + echo " Rendering with custom labels (commonLabels)..." + helm template $RELEASE_NAME . \ + --set commonLabels.environment=test \ + --set commonLabels.team=platform \ + --set commonLabels.cost-center=data-infra \ + > /tmp/rendered-templates.yaml +else + helm template $RELEASE_NAME . > /tmp/rendered-templates.yaml +fi +echo "Templates rendered to /tmp/rendered-templates.yaml" +echo "" + +# 3. Check that all objects have labels +echo "3. Checking for objects with labels..." +objects_with_labels=$(grep -A 5 "^kind:" /tmp/rendered-templates.yaml | grep -B 5 "labels:" | grep "^kind:" | wc -l) +echo "Found $objects_with_labels objects with labels" +echo "" + +# 4. Check for specific label patterns +echo "4. Checking for Yugabyte label patterns..." +echo "" + +echo "Checking for 'yugabyte.labels' template output (heritage, release, chart, component):" +if grep -q "heritage:" /tmp/rendered-templates.yaml && grep -q "release:" /tmp/rendered-templates.yaml && grep -q "chart:" /tmp/rendered-templates.yaml && grep -q "component:" /tmp/rendered-templates.yaml; then + echo "✓ Found heritage, release, chart, and component labels" +else + echo "✗ Missing standard labels" +fi +echo "" + +echo "Checking for app labels (app or app.kubernetes.io/name):" +if grep -q "app:" /tmp/rendered-templates.yaml || grep -q "app.kubernetes.io/name:" /tmp/rendered-templates.yaml; then + echo "✓ Found app labels" +else + echo "✗ Missing app labels" +fi +echo "" + +# Check for custom labels if commonLabels are provided +if [ "$TEST_CUSTOM_LABELS" = "true" ]; then + echo "Checking for custom labels (commonLabels)..." + # Extract labels section more precisely - look for lines after "labels:" and before next top-level key + custom_labels=$(awk '/labels:/ {flag=1; next} /^[a-zA-Z]/ && flag {flag=0} flag && /^[[:space:]]+[a-zA-Z0-9_.-]+:/ {print}' /tmp/rendered-templates.yaml | \ + grep -vE "^\s+(app|release|chart|component|heritage|service-type|scope|serviceName|app\.kubernetes\.io/name):" | \ + sed 's/:.*//' | sed 's/^\s*//' | sort -u) + + # Also check for the specific custom labels we set + if grep -q "environment: test" /tmp/rendered-templates.yaml || \ + grep -q "team: platform" /tmp/rendered-templates.yaml || \ + grep -q "cost-center: data-infra" /tmp/rendered-templates.yaml; then + echo "✓ Found custom labels from commonLabels" + echo " Custom labels detected:" + grep -E "(environment|team|cost-center):" /tmp/rendered-templates.yaml | head -3 | sed 's/^/ /' + elif [ -n "$custom_labels" ]; then + custom_count=$(echo "$custom_labels" | wc -l) + echo "✓ Found custom labels ($custom_count unique custom label keys)" + echo " Sample custom labels found:" + echo "$custom_labels" | head -5 | sed 's/^/ - /' + else + echo "ℹ No custom labels detected in rendered output" + fi + echo "" + + # Test that chart-managed labels cannot be overridden + echo "Checking that chart-managed labels are protected from commonLabels override..." + if grep -q "heritage: Helm" /tmp/rendered-templates.yaml || grep -q "heritage: Tiller" /tmp/rendered-templates.yaml; then + echo "✓ heritage label is protected (not overridden by commonLabels)" + else + echo "✗ heritage label may have been overridden" + fi + + if grep -q "release: \"$RELEASE_NAME\"" /tmp/rendered-templates.yaml || grep -q "release: $RELEASE_NAME" /tmp/rendered-templates.yaml; then + echo "✓ release label is protected (not overridden by commonLabels)" + else + echo "✗ release label may have been overridden" + fi + + if grep -q "chart: \"yugabyte\"" /tmp/rendered-templates.yaml || grep -q "chart: yugabyte" /tmp/rendered-templates.yaml; then + echo "✓ chart label is protected (not overridden by commonLabels)" + else + echo "✗ chart label may have been overridden" + fi + + if grep -q "component: \"yugabytedb\"" /tmp/rendered-templates.yaml || grep -q "component: yugabytedb" /tmp/rendered-templates.yaml; then + echo "✓ component label is protected (not overridden by commonLabels)" + else + echo "✗ component label may have been overridden" + fi + + # Check app labels are protected (service-specific) + if grep -q "app: \"yb-master\"" /tmp/rendered-templates.yaml || grep -q "app: \"yb-tserver\"" /tmp/rendered-templates.yaml || \ + grep -q "app.kubernetes.io/name: \"yb-master\"" /tmp/rendered-templates.yaml || grep -q "app.kubernetes.io/name: \"yb-tserver\"" /tmp/rendered-templates.yaml; then + echo "✓ app/app.kubernetes.io/name labels are protected (service-specific, not overridden)" + else + echo "✗ app labels may have been overridden" + fi + echo "" +fi + +# 5. Check specific object types +echo "5. Checking specific object types for labels..." +echo "" + +check_object_labels() { + local kind=$1 + local count=$(grep -c "^kind: $kind" /tmp/rendered-templates.yaml || echo "0") + if [ "$count" -gt 0 ]; then + local with_labels=$(grep -A 10 "^kind: $kind" /tmp/rendered-templates.yaml | grep -c "labels:" || echo "0") + if [ "$with_labels" -eq "$count" ]; then + echo "✓ All $count $kind objects have labels" + else + echo "✗ Some $kind objects missing labels ($with_labels/$count)" + fi + else + echo "- No $kind objects found" + fi +} + +check_object_labels "Secret" +check_object_labels "ConfigMap" +check_object_labels "Service" +check_object_labels "StatefulSet" +check_object_labels "ServiceMonitor" +check_object_labels "Job" +check_object_labels "Certificate" +check_object_labels "Issuer" +check_object_labels "PodDisruptionBudget" +check_object_labels "OpenTelemetryCollector" +echo "" + +# 6. Show sample of labels from different objects +echo "6. Sample labels from rendered objects:" +echo "" +# Function to extract complete labels section (until next top-level key) +extract_labels_section() { + local kind=$1 + awk -v kind="$kind" ' + /^kind: / && $2 == kind {found=1; next} + found && /labels:/ {in_labels=1; print; next} + in_labels && /^[a-zA-Z]/ && !/^ / {in_labels=0; found=0; exit} + in_labels {print} + ' /tmp/rendered-templates.yaml | head -20 +} + +echo "--- Sample Secret labels ---" +extract_labels_section "Secret" | head -12 +echo "" + +echo "--- Sample ConfigMap labels ---" +extract_labels_section "ConfigMap" | head -12 +echo "" + +echo "--- Sample Service labels ---" +extract_labels_section "Service" | head -20 +echo "" + +# 7. Count objects without labels (should be minimal - only NOTES.txt, etc.) +echo "7. Checking for objects without labels..." +objects_without_labels=0 +current_kind="" +in_object=false +while IFS= read -r line; do + if [[ "$line" =~ ^kind: ]]; then + current_kind=$(echo "$line" | awk '{print $2}') + in_object=true + has_labels=false + elif [[ "$line" =~ ^--- ]] && [ "$in_object" = true ]; then + if [ "$has_labels" = false ] && [ -n "$current_kind" ]; then + echo " - $current_kind (missing labels)" + objects_without_labels=$((objects_without_labels + 1)) + fi + in_object=false + current_kind="" + has_labels=false + elif [[ "$line" =~ labels: ]] && [ "$in_object" = true ]; then + has_labels=true + fi +done < /tmp/rendered-templates.yaml + +# Check last object if file doesn't end with --- +if [ "$in_object" = true ] && [ "$has_labels" = false ] && [ -n "$current_kind" ]; then + echo " - $current_kind (missing labels)" + objects_without_labels=$((objects_without_labels + 1)) +fi + +if [ "$objects_without_labels" -eq 0 ]; then + echo "✓ All objects have labels" +else + echo "⚠ Found $objects_without_labels objects without labels" +fi +echo "" + +echo "=== Testing Complete ===" +echo "" +echo "To inspect the rendered templates:" +echo " cat /tmp/rendered-templates.yaml" +echo "" +echo "To check a specific object type:" +echo " grep -A 20 '^kind: Secret' /tmp/rendered-templates.yaml | head -25" +echo "" +echo "To test with custom labels:" +echo " TEST_CUSTOM_LABELS=true ./test-labels.sh" +echo " # or" +echo " helm template test-release . --set commonLabels.environment=prod --set commonLabels.team=platform" +echo "" +echo "To test that chart-managed labels are protected:" +echo " helm template test-release . --set commonLabels.heritage=overridden --set commonLabels.release=overridden --set commonLabels.chart=overridden --set commonLabels.component=overridden --set commonLabels.app=overridden" +echo " # Chart-managed labels (heritage, release, chart, component, app, app.kubernetes.io/name) should NOT be overridden" +echo "" + diff --git a/helm-charts/yugabyte/tests/README.md b/helm-charts/yugabyte/tests/README.md new file mode 100644 index 0000000..f2bdea2 --- /dev/null +++ b/helm-charts/yugabyte/tests/README.md @@ -0,0 +1,19 @@ +# Unit Testing Helm charts +Unit tests for the yugabyte helm charts, which can be used to validate helm templates +gives us our expected results. + +This is leveraging https://github.com/helm-unittest/helm-unittest + +See https://github.com/quintush/helm-unittest/blob/master/DOCUMENT.md for details on creating new +tests + +## Install +``` +$ helm plugin install https://github.com/helm-unittest/helm-unittest.git +``` + +## Run tests +``` +$ cd stable/yugabyte +$ helm unittest -f "tests/test_*.yaml" . +``` diff --git a/helm-charts/yugabyte/tests/test_affinity_merges.yaml b/helm-charts/yugabyte/tests/test_affinity_merges.yaml new file mode 100644 index 0000000..ef45cc1 --- /dev/null +++ b/helm-charts/yugabyte/tests/test_affinity_merges.yaml @@ -0,0 +1,243 @@ +# yaml-language-server: $schema=https://raw.githubusercontent.com/quintush/helm-unittest/master/schema/helm-testsuite.json +suite: nodeAffinity and podAntiAffinity Merge +tests: +- it: Test with AZ + template: templates/service.yaml + values: + - ./values_affinity_merge.yaml + set: + AZ: test_az + oldNamingStyle: true + asserts: + - isSubset: + path: spec.template.spec.affinity.nodeAffinity.requiredDuringSchedulingIgnoredDuringExecution + content: + nodeSelectorTerms: + - matchExpressions: + - key: failure-domain.beta.kubernetes.io/zone + operator: In + values: + - test_az + - key: custom_label_1 + operator: In + values: + - custom_value_1 + matchFields: + - key: metadata.name + operator: In + values: + - name + - matchExpressions: + - key: topology.kubernetes.io/zone + operator: In + values: + - test_az + - key: custom_label_1 + operator: In + values: + - custom_value_1 + matchFields: + - key: metadata.name + operator: In + values: + - name + - matchExpressions: + - key: failure-domain.beta.kubernetes.io/zone + operator: In + values: + - test_az + - key: custom_label_2 + operator: In + values: + - custom_value_2 + - matchExpressions: + - key: topology.kubernetes.io/zone + operator: In + values: + - test_az + - key: custom_label_2 + operator: In + values: + - custom_value_2 + documentIndex: 1 + - isSubset: + path: spec.template.spec.affinity.podAntiAffinity + content: + preferredDuringSchedulingIgnoredDuringExecution: + - weight: 100 + podAffinityTerm: + labelSelector: + matchExpressions: + - key: app + operator: In + values: + - "yb-master" + topologyKey: kubernetes.io/hostname + - weight: 30 + podAffinityTerm: + labelSelector: + matchExpressions: + - key: paa_key + operator: In + values: + - paa_value + documentIndex: 1 + - isSubset: + path: spec.template.spec.affinity.nodeAffinity + content: + requiredDuringSchedulingIgnoredDuringExecution: + nodeSelectorTerms: + - matchExpressions: + - key: failure-domain.beta.kubernetes.io/zone + operator: In + values: + - test_az + - matchExpressions: + - key: topology.kubernetes.io/zone + operator: In + values: + - test_az + preferredDuringSchedulingIgnoredDuringExecution: + random_key: random_value + documentIndex: 4 + - isSubset: + path: spec.template.spec.affinity.podAntiAffinity + content: + preferredDuringSchedulingIgnoredDuringExecution: + - weight: 100 + podAffinityTerm: + labelSelector: + matchExpressions: + - key: app + operator: In + values: + - yb-tserver + topologyKey: kubernetes.io/hostname + requiredDuringSchedulingIgnoredDuringExecution: + random_key2: random_value2 + documentIndex: 4 +- it: Test without AZ + template: templates/service.yaml + values: + - ./values_affinity_merge.yaml + set: + AZ: false + oldNamingStyle: true + asserts: + - isSubset: + path: spec.template.spec.affinity.nodeAffinity.requiredDuringSchedulingIgnoredDuringExecution + content: + nodeSelectorTerms: + - matchExpressions: + - key: custom_label_1 + operator: In + values: + - custom_value_1 + matchFields: + - key: metadata.name + operator: In + values: + - name + - matchExpressions: + - key: custom_label_2 + operator: In + values: + - custom_value_2 + documentIndex: 1 + - isSubset: + path: spec.template.spec.affinity.podAntiAffinity + content: + preferredDuringSchedulingIgnoredDuringExecution: + - weight: 100 + podAffinityTerm: + labelSelector: + matchExpressions: + - key: app + operator: In + values: + - "yb-master" + topologyKey: kubernetes.io/hostname + - weight: 30 + podAffinityTerm: + labelSelector: + matchExpressions: + - key: paa_key + operator: In + values: + - paa_value + documentIndex: 1 + - isSubset: + path: spec.template.spec.affinity.nodeAffinity + content: + preferredDuringSchedulingIgnoredDuringExecution: + random_key: random_value + documentIndex: 4 + - isSubset: + path: spec.template.spec.affinity.podAntiAffinity + content: + preferredDuringSchedulingIgnoredDuringExecution: + - weight: 100 + podAffinityTerm: + labelSelector: + matchExpressions: + - key: app + operator: In + values: + - yb-tserver + topologyKey: kubernetes.io/hostname + requiredDuringSchedulingIgnoredDuringExecution: + random_key2: random_value2 + documentIndex: 4 +- it: Test single zone with default empty affinity has podAntiAffinity + template: templates/service.yaml + set: + AZ: us-west1-a + oldNamingStyle: true + master: + affinity: {} + tserver: + affinity: {} + asserts: + - isSubset: + path: spec.template.spec.affinity.podAntiAffinity + content: + preferredDuringSchedulingIgnoredDuringExecution: + - weight: 100 + podAffinityTerm: + labelSelector: + matchExpressions: + - key: app + operator: In + values: + - "yb-master" + topologyKey: kubernetes.io/hostname + documentIndex: 1 + - isSubset: + path: spec.template.spec.affinity.podAntiAffinity + content: + preferredDuringSchedulingIgnoredDuringExecution: + - weight: 100 + podAffinityTerm: + labelSelector: + matchExpressions: + - key: app + operator: In + values: + - "yb-tserver" + topologyKey: kubernetes.io/hostname + documentIndex: 4 + - isSubset: + path: spec.template.spec.affinity.nodeAffinity.requiredDuringSchedulingIgnoredDuringExecution + content: + nodeSelectorTerms: + - matchExpressions: + - key: failure-domain.beta.kubernetes.io/zone + operator: In + values: + - us-west1-a + - matchExpressions: + - key: topology.kubernetes.io/zone + operator: In + values: + - us-west1-a + documentIndex: 1 diff --git a/helm-charts/yugabyte/tests/test_labels.yaml b/helm-charts/yugabyte/tests/test_labels.yaml new file mode 100644 index 0000000..b8bea35 --- /dev/null +++ b/helm-charts/yugabyte/tests/test_labels.yaml @@ -0,0 +1,646 @@ +# yaml-language-server: $schema=https://raw.githubusercontent.com/quintush/helm-unittest/master/schema/helm-testsuite.json +suite: Labels on all objects +templates: +- master-gflags-secret.yaml +- tserver-gflags-secret.yaml +- debug_config_map.yaml +- setup-credentials-configmap.yaml +- master-servicemonitor.yaml +- tserver-servicemonitor.yaml +- otel-collector.yaml +- hooks/setup-credentials-job.yaml +- certificates.yaml +- service.yaml +tests: +# Test master-gflags-secret.yaml +- it: master-gflags-secret has labels + template: templates/master-gflags-secret.yaml + set: + Services: + - name: yb-masters + label: yb-master + ports: + tcp-rpc-port: 7100 + asserts: + - exists: + path: metadata.labels + - exists: + path: metadata.labels.app + - exists: + path: metadata.labels.release + - exists: + path: metadata.labels.chart + - exists: + path: metadata.labels.component + +# Test tserver-gflags-secret.yaml +- it: tserver-gflags-secret has labels + template: templates/tserver-gflags-secret.yaml + set: + Services: + - name: yb-tservers + label: yb-tserver + ports: + tcp-rpc-port: 9100 + asserts: + - exists: + path: metadata.labels + - exists: + path: metadata.labels.app + - exists: + path: metadata.labels.release + - exists: + path: metadata.labels.chart + - exists: + path: metadata.labels.component + + +# Test debug_config_map.yaml - master-hooks +- it: debug_config_map master-hooks has labels + template: templates/debug_config_map.yaml + set: + replicas: + master: 3 + asserts: + - exists: + path: metadata.labels + documentIndex: 0 + - exists: + path: metadata.labels.app + documentIndex: 0 + - exists: + path: metadata.labels.release + documentIndex: 0 + - exists: + path: metadata.labels.chart + documentIndex: 0 + - exists: + path: metadata.labels.component + documentIndex: 0 + +# Test debug_config_map.yaml - tserver-hooks +- it: debug_config_map tserver-hooks has labels + template: templates/debug_config_map.yaml + set: + replicas: + tserver: 3 + asserts: + - exists: + path: metadata.labels + documentIndex: 1 + - exists: + path: metadata.labels.app + documentIndex: 1 + - exists: + path: metadata.labels.release + documentIndex: 1 + - exists: + path: metadata.labels.chart + documentIndex: 1 + - exists: + path: metadata.labels.component + documentIndex: 1 + +# Test setup-credentials-configmap.yaml +- it: setup-credentials-configmap has labels + template: templates/setup-credentials-configmap.yaml + set: + authCredentials: + ysql: + password: testpass + asserts: + - exists: + path: metadata.labels + - exists: + path: metadata.labels.app + - exists: + path: metadata.labels.release + - exists: + path: metadata.labels.chart + - exists: + path: metadata.labels.component + +# Test master-servicemonitor.yaml +- it: master-servicemonitor has labels + template: templates/master-servicemonitor.yaml + set: + serviceMonitor: + enabled: true + master: + enabled: true + port: http-ui + path: /metrics + asserts: + - exists: + path: metadata.labels + - exists: + path: metadata.labels.app + - exists: + path: metadata.labels.release + - exists: + path: metadata.labels.chart + - exists: + path: metadata.labels.component + +# Test tserver-servicemonitor.yaml +- it: tserver-servicemonitor has labels + template: templates/tserver-servicemonitor.yaml + set: + serviceMonitor: + enabled: true + tserver: + enabled: true + port: http-ui + path: /metrics + asserts: + - exists: + path: metadata.labels + - exists: + path: metadata.labels.app + - exists: + path: metadata.labels.release + - exists: + path: metadata.labels.chart + - exists: + path: metadata.labels.component + +# Test otel-collector.yaml - Secret +- it: otel-collector secret has labels + template: templates/otel-collector.yaml + set: + otelCollector: + enabled: true + secretEnv: + - envName: TEST_ENV + envValue: test_value + asserts: + - exists: + path: metadata.labels + documentIndex: 0 + - exists: + path: metadata.labels.app + documentIndex: 0 + - exists: + path: metadata.labels.release + documentIndex: 0 + - exists: + path: metadata.labels.chart + documentIndex: 0 + - exists: + path: metadata.labels.component + documentIndex: 0 + +# Test otel-collector.yaml - OpenTelemetryCollector +- it: otel-collector OpenTelemetryCollector has labels + template: templates/otel-collector.yaml + set: + otelCollector: + enabled: true + exporters: + datadog: + apikey: test + asserts: + - exists: + path: metadata.labels + documentIndex: 1 + - exists: + path: metadata.labels.app + documentIndex: 1 + - exists: + path: metadata.labels.release + documentIndex: 1 + - exists: + path: metadata.labels.chart + documentIndex: 1 + - exists: + path: metadata.labels.component + documentIndex: 1 + +# Test hooks/setup-credentials-job.yaml - Job +- it: setup-credentials-job has labels + template: templates/hooks/setup-credentials-job.yaml + set: + authCredentials: + ysql: + password: testpass + asserts: + - exists: + path: metadata.labels + - exists: + path: metadata.labels.app + - exists: + path: metadata.labels.release + - exists: + path: metadata.labels.chart + - exists: + path: metadata.labels.component + +# Test hooks/setup-credentials-job.yaml - Pod template +- it: setup-credentials-job pod template has labels + template: templates/hooks/setup-credentials-job.yaml + set: + authCredentials: + ysql: + password: testpass + asserts: + - exists: + path: spec.template.metadata.labels + - exists: + path: spec.template.metadata.labels.app + - exists: + path: spec.template.metadata.labels.release + - exists: + path: spec.template.metadata.labels.chart + - exists: + path: spec.template.metadata.labels.component + +# Test certificates.yaml - Issuer (bootstrap) +- it: certificates issuer bootstrap has labels + template: templates/certificates.yaml + set: + tls: + certManager: + enabled: true + bootstrapSelfsigned: true + asserts: + - exists: + path: metadata.labels + documentIndex: 0 + - exists: + path: metadata.labels.app + documentIndex: 0 + - exists: + path: metadata.labels.release + documentIndex: 0 + - exists: + path: metadata.labels.chart + documentIndex: 0 + - exists: + path: metadata.labels.component + documentIndex: 0 + +# Test certificates.yaml - Certificate (CA) +- it: certificates CA certificate has labels + template: templates/certificates.yaml + set: + tls: + certManager: + enabled: true + bootstrapSelfsigned: true + certificates: + algorithm: RSA + keySize: 2048 + asserts: + - exists: + path: metadata.labels + documentIndex: 1 + - exists: + path: metadata.labels.app + documentIndex: 1 + - exists: + path: metadata.labels.release + documentIndex: 1 + - exists: + path: metadata.labels.chart + documentIndex: 1 + - exists: + path: metadata.labels.component + documentIndex: 1 + +# Test certificates.yaml - Service-specific Certificate +- it: certificates service certificate has labels + template: templates/certificates.yaml + set: + tls: + certManager: + enabled: true + bootstrapSelfsigned: true + certificates: + algorithm: RSA + keySize: 2048 + Services: + - name: yb-masters + label: yb-master + ports: + tcp-rpc-port: 7100 + replicas: + master: 3 + domainName: cluster.local + asserts: + - exists: + path: metadata.labels + documentIndex: 3 + - exists: + path: metadata.labels.app + documentIndex: 3 + - exists: + path: metadata.labels.release + documentIndex: 3 + - exists: + path: metadata.labels.chart + documentIndex: 3 + - exists: + path: metadata.labels.component + documentIndex: 3 + +# Test service.yaml - PodDisruptionBudget +- it: service PodDisruptionBudget has labels + template: templates/service.yaml + set: + Services: + - name: yb-masters + label: yb-master + ports: + tcp-rpc-port: 7100 + http-ui: 7000 + replicas: + master: 3 + storage: + master: + count: 1 + size: 10Gi + asserts: + - exists: + path: metadata.labels + documentIndex: 2 + - exists: + path: metadata.labels.app + documentIndex: 2 + - exists: + path: metadata.labels.release + documentIndex: 2 + - exists: + path: metadata.labels.chart + documentIndex: 2 + - exists: + path: metadata.labels.component + documentIndex: 2 + +# Test with oldNamingStyle - should use 'app' label +- it: labels use 'app' with oldNamingStyle + template: templates/master-gflags-secret.yaml + set: + oldNamingStyle: true + Services: + - name: yb-masters + label: yb-master + ports: + tcp-rpc-port: 7100 + asserts: + - equal: + path: metadata.labels.app + value: yb-master + +# Test with new naming style - should use 'app.kubernetes.io/name' label +- it: labels use 'app.kubernetes.io/name' with new naming style + template: templates/master-gflags-secret.yaml + set: + oldNamingStyle: false + Services: + - name: yb-masters + label: yb-master + ports: + tcp-rpc-port: 7100 + asserts: + - equal: + path: metadata.labels['app.kubernetes.io/name'] + value: yb-master + - notExists: + path: metadata.labels.app + - exists: + path: metadata.labels.heritage + - exists: + path: metadata.labels.release + - exists: + path: metadata.labels.chart + - exists: + path: metadata.labels.component + +# Test custom labels from commonLabels are included +- it: custom labels from commonLabels are included + template: templates/master-gflags-secret.yaml + set: + Services: + - name: yb-masters + label: yb-master + ports: + tcp-rpc-port: 7100 + commonLabels: + environment: production + team: platform + cost-center: data-infra + asserts: + - exists: + path: metadata.labels.environment + - equal: + path: metadata.labels.environment + value: production + - exists: + path: metadata.labels.team + - equal: + path: metadata.labels.team + value: platform + - exists: + path: metadata.labels['cost-center'] + - equal: + path: metadata.labels['cost-center'] + value: data-infra + - exists: + path: metadata.labels.app + - exists: + path: metadata.labels.release + +# Test that chart-managed labels cannot be overridden by commonLabels +- it: chart-managed labels are protected from commonLabels override + template: templates/master-gflags-secret.yaml + set: + Services: + - name: yb-masters + label: yb-master + ports: + tcp-rpc-port: 7100 + commonLabels: + heritage: overridden-heritage + release: overridden-release + chart: overridden-chart + component: overridden-component + app: overridden-app + asserts: + # Chart-managed labels should NOT be overridden + - equal: + path: metadata.labels.heritage + value: Helm + - exists: + path: metadata.labels.release + - notEqual: + path: metadata.labels.release + value: overridden-release + - equal: + path: metadata.labels.chart + value: yugabyte + - equal: + path: metadata.labels.component + value: yugabytedb + - equal: + path: metadata.labels.app + value: yb-master + +# Test that app.kubernetes.io/name cannot be overridden by commonLabels (new naming style) +- it: app.kubernetes.io/name is protected from commonLabels override + template: templates/master-gflags-secret.yaml + set: + oldNamingStyle: false + Services: + - name: yb-masters + label: yb-master + ports: + tcp-rpc-port: 7100 + commonLabels: + app.kubernetes.io/name: overridden-app-name + app: overridden-app + asserts: + # Service-specific app label should NOT be overridden + - equal: + path: metadata.labels['app.kubernetes.io/name'] + value: yb-master + # app label should not exist in new naming style + - notExists: + path: metadata.labels.app + +# Test StatefulSet selector matches pod template labels when commonLabels tries to override +- it: StatefulSet selector matches pod template labels (protected from commonLabels) + template: templates/service.yaml + set: + oldNamingStyle: false + Services: + - name: yb-masters + label: yb-master + ports: + tcp-rpc-port: 7100 + http-ui: 7000 + replicas: + master: 3 + storage: + master: + count: 1 + size: 10Gi + domainName: cluster.local + commonLabels: + app.kubernetes.io/name: overridden-name + release: overridden-release + environment: production + asserts: + # Verify StatefulSet exists at documentIndex 2 + - matchRegex: + path: kind + pattern: StatefulSet + documentIndex: 2 + # Selector should use service-specific app label, not overridden value + - equal: + path: spec.selector.matchLabels['app.kubernetes.io/name'] + value: yb-master + documentIndex: 2 + - exists: + path: spec.selector.matchLabels.release + documentIndex: 2 + # Pod template should also have service-specific app label + - equal: + path: spec.template.metadata.labels['app.kubernetes.io/name'] + value: yb-master + documentIndex: 2 + - exists: + path: spec.template.metadata.labels.release + documentIndex: 2 + # Custom labels should still be present + - exists: + path: spec.template.metadata.labels.environment + documentIndex: 2 + - equal: + path: spec.template.metadata.labels.environment + value: production + documentIndex: 2 + +# Test custom labels on multiple object types +- it: custom labels appear on ConfigMap + template: templates/debug_config_map.yaml + set: + replicas: + master: 3 + commonLabels: + custom-label-1: value1 + custom-label-2: value2 + asserts: + - exists: + path: metadata.labels['custom-label-1'] + documentIndex: 0 + - equal: + path: metadata.labels['custom-label-1'] + value: value1 + documentIndex: 0 + - exists: + path: metadata.labels['custom-label-2'] + documentIndex: 0 + - equal: + path: metadata.labels['custom-label-2'] + value: value2 + documentIndex: 0 + +# Test custom labels on ServiceMonitor +- it: custom labels appear on ServiceMonitor + template: templates/master-servicemonitor.yaml + set: + serviceMonitor: + enabled: true + master: + enabled: true + port: http-ui + path: /metrics + commonLabels: + monitoring: enabled + prometheus: scrape + asserts: + - exists: + path: metadata.labels.monitoring + - equal: + path: metadata.labels.monitoring + value: enabled + - exists: + path: metadata.labels.prometheus + - equal: + path: metadata.labels.prometheus + value: scrape + +# Test custom labels on Job +- it: custom labels appear on Job and pod template + template: templates/hooks/setup-credentials-job.yaml + set: + authCredentials: + ysql: + password: testpass + commonLabels: + job-type: setup + managed-by: helm + asserts: + # Check Job labels + - exists: + path: metadata.labels['job-type'] + - equal: + path: metadata.labels['job-type'] + value: setup + - exists: + path: metadata.labels['managed-by'] + - equal: + path: metadata.labels['managed-by'] + value: helm + # Check pod template labels + - exists: + path: spec.template.metadata.labels['job-type'] + - equal: + path: spec.template.metadata.labels['job-type'] + value: setup + - exists: + path: spec.template.metadata.labels['managed-by'] + - equal: + path: spec.template.metadata.labels['managed-by'] + value: helm + diff --git a/helm-charts/yugabyte/tests/test_priority_class_name.yaml b/helm-charts/yugabyte/tests/test_priority_class_name.yaml new file mode 100644 index 0000000..c551e54 --- /dev/null +++ b/helm-charts/yugabyte/tests/test_priority_class_name.yaml @@ -0,0 +1,127 @@ +# yaml-language-server: $schema=https://raw.githubusercontent.com/quintush/helm-unittest/master/schema/helm-testsuite.json +suite: priorityClassName on StatefulSet pod template +tests: +# Use oldNamingStyle so StatefulSet names are "yb-master" and "yb-tserver" for documentSelector +# With default values (no priorityClassName), field is omitted on both StatefulSets +- it: priorityClassName omitted when not set (master) + template: templates/service.yaml + values: + - ./values_priority_class_name.yaml + set: + oldNamingStyle: true + documentSelector: + path: metadata.name + value: yb-master + asserts: + - notExists: + path: spec.template.spec.priorityClassName + +- it: priorityClassName omitted when not set (tserver) + template: templates/service.yaml + values: + - ./values_priority_class_name.yaml + set: + oldNamingStyle: true + documentSelector: + path: metadata.name + value: yb-tserver + asserts: + - notExists: + path: spec.template.spec.priorityClassName + +# Global priorityClassName applies to both master and tserver StatefulSets +- it: global priorityClassName on master StatefulSet + template: templates/service.yaml + values: + - ./values_priority_class_name.yaml + - ./values_priority_class_name_global.yaml + set: + oldNamingStyle: true + documentSelector: + path: metadata.name + value: yb-master + asserts: + - equal: + path: spec.template.spec.priorityClassName + value: global-priority + +- it: global priorityClassName on tserver StatefulSet + template: templates/service.yaml + values: + - ./values_priority_class_name.yaml + - ./values_priority_class_name_global.yaml + set: + oldNamingStyle: true + documentSelector: + path: metadata.name + value: yb-tserver + asserts: + - equal: + path: spec.template.spec.priorityClassName + value: global-priority + +# Component-specific priorityClassName overrides per StatefulSet +- it: master priorityClassName set separately + template: templates/service.yaml + values: + - ./values_priority_class_name.yaml + set: + oldNamingStyle: true + master.priorityClassName: master-priority + tserver.priorityClassName: tserver-priority + documentSelector: + path: metadata.name + value: yb-master + asserts: + - equal: + path: spec.template.spec.priorityClassName + value: master-priority + +- it: tserver priorityClassName set separately + template: templates/service.yaml + values: + - ./values_priority_class_name.yaml + set: + oldNamingStyle: true + master.priorityClassName: master-priority + tserver.priorityClassName: tserver-priority + documentSelector: + path: metadata.name + value: yb-tserver + asserts: + - equal: + path: spec.template.spec.priorityClassName + value: tserver-priority + +# Component-specific overrides global +- it: master priorityClassName overrides global + template: templates/service.yaml + values: + - ./values_priority_class_name.yaml + set: + oldNamingStyle: true + priorityClassName: default-priority + master.priorityClassName: master-priority + documentSelector: + path: metadata.name + value: yb-master + asserts: + - equal: + path: spec.template.spec.priorityClassName + value: master-priority + +- it: tserver uses global when not overridden + template: templates/service.yaml + values: + - ./values_priority_class_name.yaml + set: + oldNamingStyle: true + priorityClassName: default-priority + master.priorityClassName: master-priority + documentSelector: + path: metadata.name + value: yb-tserver + asserts: + - equal: + path: spec.template.spec.priorityClassName + value: default-priority diff --git a/helm-charts/yugabyte/tests/test_setup_credentials.yaml b/helm-charts/yugabyte/tests/test_setup_credentials.yaml new file mode 100644 index 0000000..b29c7cb --- /dev/null +++ b/helm-charts/yugabyte/tests/test_setup_credentials.yaml @@ -0,0 +1,53 @@ +# yaml-language-server: $schema=https://raw.githubusercontent.com/quintush/helm-unittest/master/schema/helm-testsuite.json +suite: setup-credentials +templates: +- hooks/setup-credentials-job.yaml +tests: +- it: YSQL password + set: + authCredentials: + ysql: + password: ysql_password + asserts: + - equal: + path: spec.template.spec.containers[0].env[0].name + value: YSQL_PASSWORD + - equal: + path: spec.template.spec.containers[0].env[0].value + value: ysql_password +- it: YSQL password secret + set: + authCredentials: + ysql: + passwordSecretName: ysql_password_secret + asserts: + - equal: + path: spec.template.spec.containers[0].env[0].name + value: YSQL_PASSWORD + - equal: + path: spec.template.spec.containers[0].env[0].valueFrom.secretKeyRef.name + value: ysql_password_secret +- it: YCQL password + set: + authCredentials: + ycql: + password: ycql_password + asserts: + - equal: + path: spec.template.spec.containers[0].env[0].name + value: YCQL_PASSWORD + - equal: + path: spec.template.spec.containers[0].env[0].value + value: ycql_password +- it: YCQL password secret + set: + authCredentials: + ycql: + passwordSecretName: ycql_password_secret + asserts: + - equal: + path: spec.template.spec.containers[0].env[0].name + value: YCQL_PASSWORD + - equal: + path: spec.template.spec.containers[0].env[0].valueFrom.secretKeyRef.name + value: ycql_password_secret \ No newline at end of file diff --git a/helm-charts/yugabyte/tests/values_affinity_merge.yaml b/helm-charts/yugabyte/tests/values_affinity_merge.yaml new file mode 100644 index 0000000..b3de339 --- /dev/null +++ b/helm-charts/yugabyte/tests/values_affinity_merge.yaml @@ -0,0 +1,66 @@ +master: + ## Ref: https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.22/#affinity-v1-core + ## This might override the default affinity from service.yaml + ## Example. + # affinity: + # podAntiAffinity: + # requiredDuringSchedulingIgnoredDuringExecution: + # - labelSelector: + # matchExpressions: + # - key: app + # operator: In + # values: + # - "yb-master" + # topologyKey: kubernetes.io/hostname + affinity: + nodeAffinity: + requiredDuringSchedulingIgnoredDuringExecution: + nodeSelectorTerms: + - matchExpressions: + - key: custom_label_1 + operator: In + values: + - custom_value_1 + matchFields: + - key: metadata.name + operator: In + values: + - name + - matchExpressions: + - key: custom_label_2 + operator: In + values: + - custom_value_2 + podAntiAffinity: + preferredDuringSchedulingIgnoredDuringExecution: + - weight: 30 + podAffinityTerm: + labelSelector: + matchExpressions: + - key: paa_key + operator: In + values: + - paa_value + +tserver: + ## Ref: https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.22/#affinity-v1-core + ## This might override the default affinity from service.yaml + ## Example. + # affinity: + # podAntiAffinity: + # requiredDuringSchedulingIgnoredDuringExecution: + # - labelSelector: + # matchExpressions: + # - key: app + # operator: In + # values: + # - "yb-tserver" + # topologyKey: kubernetes.io/hostname + affinity: + nodeAffinity: + preferredDuringSchedulingIgnoredDuringExecution: + random_key: random_value + podAntiAffinity: + requiredDuringSchedulingIgnoredDuringExecution: + random_key2: random_value2 + diff --git a/helm-charts/yugabyte/tests/values_priority_class_name.yaml b/helm-charts/yugabyte/tests/values_priority_class_name.yaml new file mode 100644 index 0000000..02a07b2 --- /dev/null +++ b/helm-charts/yugabyte/tests/values_priority_class_name.yaml @@ -0,0 +1,11 @@ +# Minimal values for priorityClassName tests (merge with chart defaults). +# Tests override these via the test's `set` or additional values. +replicas: + master: 1 + tserver: 1 + +master: + priorityClassName: "" + +tserver: + priorityClassName: "" diff --git a/helm-charts/yugabyte/tests/values_priority_class_name_global.yaml b/helm-charts/yugabyte/tests/values_priority_class_name_global.yaml new file mode 100644 index 0000000..79929a6 --- /dev/null +++ b/helm-charts/yugabyte/tests/values_priority_class_name_global.yaml @@ -0,0 +1,6 @@ +# Values for "global priorityClassName" test +replicas: + master: 1 + tserver: 1 + +priorityClassName: global-priority diff --git a/helm-charts/yugabyte/values.yaml b/helm-charts/yugabyte/values.yaml new file mode 100644 index 0000000..eef5160 --- /dev/null +++ b/helm-charts/yugabyte/values.yaml @@ -0,0 +1,974 @@ +# Default values for yugabyte. +# This is a YAML-formatted file. +# Declare variables to be passed into your templates. +Component: "yugabytedb" + +fullnameOverride: "" +nameOverride: "" + +Image: + repository: "yugabytedb/yugabyte" + tag: 2025.2.3.2-b1 + pullPolicy: IfNotPresent + pullSecretName: "" + +storage: + ephemeral: false # will not allocate PVs when true + master: + count: 2 + size: 10Gi + storageClass: "" + tserver: + count: 2 + size: 10Gi + storageClass: "" + +resource: + master: + requests: + cpu: "2" + memory: 2Gi + limits: + cpu: "2" + ## Ensure the 'memory' value is strictly in 'Gi' or 'G' format. Deviating from these formats + ## may result in setting an incorrect value for the 'memory_limit_hard_bytes' flag. + ## Avoid using floating numbers for the numeric part of 'memory'. Doing so may lead to + ## the 'memory_limit_hard_bytes' being set to 0, as the function expects integer values. + memory: 2Gi + tserver: + requests: + cpu: "2" + memory: 4Gi + limits: + cpu: "2" + ## Ensure the 'memory' value is strictly in 'Gi' or 'G' format. Deviating from these formats + ## may result in setting an incorrect value for the 'memory_limit_hard_bytes' flag. + ## Avoid using floating numbers for the numeric part of 'memory'. Doing so may lead to + ## the 'memory_limit_hard_bytes' being set to 0, as the function expects integer values. + memory: 4Gi + +replicas: + master: 3 + tserver: 3 + ## Used to set replication factor when isMultiAz is set to true + totalMasters: 3 + +partition: + master: 0 + tserver: 0 + +# Used to decide if a move operation is in progress. +# This defines the range of StatefulSet indices that are part of a move operation. +# +# Rules: +# - start == end: No move operation in progress. All StatefulSets use standard values. +# - start != end: Move operation in progress. The StatefulSet with index 'end' uses values from moveOp. +# - end can only be 1 more than start (end = start + 1). This ensures only one StatefulSet +# is being migrated at a time. +# - Wraparound case: When start is at the 9, end will be 0 +# instead of start+1. This is the only exception to the "end = start + 1" rule. +# +# Example progression for 2 replicas (indices 0, 1): +# - Initial: start=0, end=0 (no migration) +# - Step 1: start=0, end=1 (migrating index 1, end = start + 1) +# - Complete: start=1, end=1 (migration complete) +stsIndex: + tserver: + start: 0 + end: 0 + master: + start: 0 + end: 0 + +# Used during move operation to define temporary configuration values. +# +# When a move operation is in progress (stsIndex.start != stsIndex.end), the StatefulSet +# with index equal to stsIndex.end will use the values defined here instead of the standard +# values (storage, replicas, partition, etc.) from the main configuration. +# +# This allows you to migrate a StatefulSet to new storage class, storage counts, or other settings +# without affecting the rest of the cluster. Once the migration is complete and stsIndex.start +# equals stsIndex.end, all StatefulSets will revert to using the standard values. +# +# Only used when stsIndex.start != stsIndex.end for the corresponding server type (master/tserver). +moveOp: + storage: + ephemeral: false # will not allocate PVs when true + master: + count: 2 + size: 10Gi + storageClass: "" + tserver: + count: 2 + size: 10Gi + storageClass: "" + + replicas: + master: 3 + tserver: 3 + + partition: + master: 0 + tserver: 0 + +updateStrategy: + type: RollingUpdate + +# Used in Multi-AZ setup +masterAddresses: "" + +isMultiAz: false +AZ: "" + +# Disable the YSQL +disableYsql: false + +tls: + # Set to true to enable the TLS. + enabled: false + nodeToNode: true + clientToServer: true + # Set to false to disallow any service with unencrypted communication from joining this cluster + insecure: false + # Set enabled to true to use cert-manager instead of providing your own node certs + certManager: + enabled: false + # Will create own ca certificate and issuer when set to true + bootstrapSelfsigned: true + # Use ClusterIssuer when set to true, otherwise use Issuer + useClusterIssuer: false + # Name of ClusterIssuer to use when useClusterIssuer is true + clusterIssuer: cluster-ca + # Name of Issuer to use when useClusterIssuer is false + issuer: yugabyte-ca + + # Set the below value to true for using custom issuer like AWSPCAClusterIssuer + useCustomIssuer: false + # if customIssuer is set to true, then below issuer values will get applied + customIssuer: + kind: Issuer + name: yugabyte-ca + group: cert-manager.io + + # Set to true to use existing server certificate. + # Useful during online certificate rotation. + useExistingServerCertificate: false + + certificates: + # The lifetime before cert-manager will issue a new certificate. + # The re-issued certificates will not be automatically reloaded by the service. + # It is necessary to provide some external means of restarting the pods. + duration: 2160h # 90d + renewBefore: 360h # 15d + algorithm: RSA # ECDSA or RSA + # Can be 2048, 4096 or 8192 for RSA + # Or 256, 384 or 521 for ECDSA + keySize: 2048 + # Enable this option to include a commonName in the Certificate. + # Certain custom Certificate Authorities (CAs), such as AWS PCA, require the commonName + # field to be present in the certificate for successful issuance. + # If set to true, the commonName of certs will automatically be set to the service name. + commonNameRequired: false + # If commonNameSuffix is specified, it will be used as the suffix for the commonName for the certificate. + commonNameSuffix: "" + + ## When certManager.enabled=false, rootCA.cert and rootCA.key are used to generate TLS certs. + ## When certManager.enabled=true and boostrapSelfsigned=true, rootCA is ignored. + ## When certManager.enabled=true and bootstrapSelfsigned=false, only rootCA.cert is used + ## to verify TLS certs generated and signed by the external provider. + rootCA: + cert: "LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSUM2VENDQWRHZ0F3SUJBZ0lCQVRBTkJna3Foa2lHOXcwQkFRc0ZBREFXTVJRd0VnWURWUVFERXd0WmRXZGgKWW5sMFpTQkVRakFlRncweE9UQXlNRGd3TURRd01qSmFGdzB5T1RBeU1EVXdNRFF3TWpKYU1CWXhGREFTQmdOVgpCQU1UQzFsMVoyRmllWFJsSUVSQ01JSUJJakFOQmdrcWhraUc5dzBCQVFFRkFBT0NBUThBTUlJQkNnS0NBUUVBCnVOMWF1aWc4b2pVMHM0OXF3QXhrT2FCaHkwcTlyaVg2akVyZWJyTHJOWDJOeHdWQmNVcWJkUlhVc3VZNS96RUQKUC9CZTNkcTFuMm9EQ2ZGVEwweGkyNFdNZExRcnJBMndCdzFtNHM1WmQzcEJ1U04yWHJkVVhkeUx6dUxlczJNbgovckJxcWRscXp6LzAyTk9TOE9SVFZCUVRTQTBSOFNMQ1RjSGxMQmRkMmdxZ1ZmemVXRlVObXhWQ2EwcHA5UENuCmpUamJJRzhJWkh5dnBkTyt3aURQM1Y1a1ZEaTkvbEtUaGUzcTFOeDg5VUNFcnRJa1pjSkYvWEs3aE90MU1sOXMKWDYzb2lVMTE1Q2svbGFGRjR6dWgrZk9VenpOVXRXeTc2RE92cm5pVGlaU0tQZDBBODNNa2l2N2VHaDVkV3owWgpsKzJ2a3dkZHJaRzVlaHhvbGhGS3pRSURBUUFCbzBJd1FEQU9CZ05WSFE4QkFmOEVCQU1DQXFRd0hRWURWUjBsCkJCWXdGQVlJS3dZQkJRVUhBd0VHQ0NzR0FRVUZCd01DTUE4R0ExVWRFd0VCL3dRRk1BTUJBZjh3RFFZSktvWkkKaHZjTkFRRUxCUUFEZ2dFQkFEQjVRbmlYd1ptdk52eG5VbS9sTTVFbms3VmhTUzRUZldIMHY4Q0srZWZMSVBTbwpVTkdLNXU5UzNEUWlvaU9SN1Vmc2YrRnk1QXljMmNUY1M2UXBxTCt0V1QrU1VITXNJNk9oQ05pQ1gvQjNKWERPCkd2R0RIQzBVOHo3aWJTcW5zQ2Rid05kajAyM0lwMHVqNE9DVHJ3azZjd0RBeXlwVWkwN2tkd28xYWJIWExqTnAKamVQMkwrY0hkc2dKM1N4WWpkK1kvei9IdmFrZG1RZDJTL1l2V0R3aU1SRDkrYmZXWkJVRHo3Y0QyQkxEVmU0aAp1bkFaK3NyelR2Sjd5dkVodzlHSDFyajd4Qm9VNjB5SUUrYSszK2xWSEs4WnBSV0NXMnh2eWNrYXJSKytPS2NKClFsL04wWExqNWJRUDVoUzdhOTdhQktTamNqY3E5VzNGcnhJa2tKST0KLS0tLS1FTkQgQ0VSVElGSUNBVEUtLS0tLQo=" + key: "LS0tLS1CRUdJTiBSU0EgUFJJVkFURSBLRVktLS0tLQpNSUlFcEFJQkFBS0NBUUVBdU4xYXVpZzhvalUwczQ5cXdBeGtPYUJoeTBxOXJpWDZqRXJlYnJMck5YMk54d1ZCCmNVcWJkUlhVc3VZNS96RURQL0JlM2RxMW4yb0RDZkZUTDB4aTI0V01kTFFyckEyd0J3MW00czVaZDNwQnVTTjIKWHJkVVhkeUx6dUxlczJNbi9yQnFxZGxxenovMDJOT1M4T1JUVkJRVFNBMFI4U0xDVGNIbExCZGQyZ3FnVmZ6ZQpXRlVObXhWQ2EwcHA5UENualRqYklHOElaSHl2cGRPK3dpRFAzVjVrVkRpOS9sS1RoZTNxMU54ODlVQ0VydElrClpjSkYvWEs3aE90MU1sOXNYNjNvaVUxMTVDay9sYUZGNHp1aCtmT1V6ek5VdFd5NzZET3ZybmlUaVpTS1BkMEEKODNNa2l2N2VHaDVkV3owWmwrMnZrd2RkclpHNWVoeG9saEZLelFJREFRQUJBb0lCQUJsdW1tU3gxR1djWER1Mwpwei8wZEhWWkV4c2NsU3U0SGRmZkZPcTF3cFlCUjlmeGFTZGsxQzR2YXF1UjhMaWl6WWVtVWViRGgraitkSnlSCmpwZ2JNaDV4S1BtRkw5empwU3ZUTkN4UHB3OUF5bm5sM3dyNHZhcU1CTS9aZGpuSGttRC9kQzBadEEvL0JIZ3YKNHk4d3VpWCsvUWdVaER0Z1JNcmR1ZUZ1OVlKaFo5UE9jYXkzSkkzMFhEYjdJSS9vNFNhYnhTcFI3bTg5WjY0NwpUb3hsOEhTSzl0SUQxbkl1bHVpTmx1dHI1RzdDdE93WTBSc2N5dmZ2elg4a1d2akpLZVJVbmhMSCtXVFZOaExICjdZc0tMNmlLa1NkckMzeWVPWnV4R0pEbVdrZVgxTzNPRUVGYkc4TjVEaGNqL0lXbDh1dGt3LzYwTEthNHBCS2cKTXhtNEx3RUNnWUVBNnlPRkhNY2pncHYxLzlHZC8yb3c2YmZKcTFjM1dqQkV2cnM2ZXNyMzgrU3UvdVFneXJNcAo5V01oZElpb2dYZjVlNjV5ZlIzYVBXcjJJdWMxZ0RUNlYycDZFR2h0NysyQkF1YkIzczloZisycVNRY1lkS3pmCnJOTDdKalE4ZEVGZWdYd041cHhKOTRTTVFZNEI4Qm9hOHNJWTd3TzU4dHpVMjZoclVnanFXQ1VDZ1lFQXlVUUIKNzViWlh6MGJ5cEc5NjNwYVp0bGlJY0cvUk1XMnVPOE9rVFNYSGdDSjBob25uRm5IMGZOc1pGTHdFWEtnTTRORworU3ZNbWtUekE5eVVSMHpIMFJ4UW44L1YzVWZLT2k5RktFeWx6NzNiRkV6ZW1QSEppQm12NWQ4ZTlOenZmU0E0CkdpRTYrYnFyV3VVWWRoRWlYTnY1SFNPZ3I4bUx1TzJDbGlmNTg0a0NnWUFlZzlDTmlJWmlOODAzOHNNWFYzZWIKalI5ZDNnYXY3SjJ2UnVyeTdvNDVGNDlpUXNiQ3AzZWxnY1RnczY5eWhkaFpwYXp6OGNEVndhREpyTW16cHF4cQpWY1liaFFIblppSWM5MGRubS9BaVF2eWJWNUZqNnQ5b05VVWtreGpaV1haalJXOGtZMW55QmtDUmJWVnhER0k4CjZOV0ZoeTFGaUVVVGNJcms3WVZFQlFLQmdRREpHTVIrYWRFamtlRlUwNjVadkZUYmN0VFVPY3dzb1Foalc2akkKZVMyTThxakNYeE80NnhQMnVTeFNTWFJKV3FpckQ3NDRkUVRvRjRCaEdXS21veGI3M3pqSGxWaHcwcXhDMnJ4VQorZENxODE0VXVJR3BlOTBMdWU3QTFlRU9kRHB1WVdUczVzc1FmdTE3MG5CUWQrcEhzaHNFZkhhdmJjZkhyTGpQCjQzMmhVUUtCZ1FDZ3hMZG5Pd2JMaHZLVkhhdTdPVXQxbGpUT240SnB5bHpnb3hFRXpzaDhDK0ZKUUQ1bkFxZXEKZUpWSkNCd2VkallBSDR6MUV3cHJjWnJIN3IyUTBqT2ZFallwU1dkZGxXaWh4OTNYODZ0aG83UzJuUlYrN1hNcQpPVW9ZcVZ1WGlGMWdMM1NGeHZqMHhxV3l0d0NPTW5DZGFCb0M0Tkw3enJtL0lZOEUwSkw2MkE9PQotLS0tLUVORCBSU0EgUFJJVkFURSBLRVktLS0tLQo=" + ## When tls.certManager.enabled=false + ## nodeCert and clientCert will be used only when rootCA.key is empty. + ## Will be ignored and genSignedCert will be used to generate + ## node and client certs if rootCA.key is provided. + ## cert and key are base64 encoded content of certificate and key. + nodeCert: + cert: "" + key: "" + clientCert: + cert: "" + key: "" + ## Checksum for CA certificate. If set to empty, statefulset + ## will calculate new checksum value and decide whether to restart pods + ## based on the result of comparing previous checksum value and new value. + ## If previous value is provided again, there will be no Pod restart + ## for CA certificate changes. + rootCAChecksum: "" + +gflags: + master: + default_memory_limit_to_ram_ratio: 0.85 + tserver: {} +# use_cassandra_authentication: false + ybc: {} + +yugabytedUi: + enabled: true + # If recoverWithoutFailure is true, yugabyted-ui will automatically try to restart itself + # instead of failing and causing the pod to restart + recoverWithoutFailure: true + recoveryInterval: 30s + # metricsSnapshotter must be enabled for yugabytedUi to properly display metrics + metricsSnapshotter: + enabled: true + # time between each metric snapshot in ms + interval: 11000 + whitelist: + - handler_latency_yb_tserver_TabletServerService_Read_count + - handler_latency_yb_tserver_TabletServerService_Write_count + - handler_latency_yb_tserver_TabletServerService_Read_sum + - handler_latency_yb_tserver_TabletServerService_Write_sum + - disk_usage + - cpu_usage + - node_up + +PodManagementPolicy: Parallel + +enableLoadBalancer: true + +ybc: + enabled: false + # Use inbuilt YB-Controller executable + useYBDBImage: false + ## https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/#resource-requests-and-limits-of-pod-and-container + ## Use the above link to learn more about Kubernetes resources configuration. + resources: + requests: + cpu: "1" + memory: 1Gi + limits: + cpu: "1" + memory: 1Gi + ## Checksum for controller gflags secret. If set to empty, statefulset + ## will calculate new checksum value and decide whether to restart pods + ## based on the result of comparing previous checksum value and new value. + ## If previous value is provided again, there will be no Pod restart + ## for gflags changes. + gflagsChecksum: "" + +ybCleanup: + ## https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/#resource-requests-and-limits-of-pod-and-container + ## Use the above link to learn more about Kubernetes resources configuration. + resources: + requests: + cpu: "0.25" + memory: 250Mi + limits: + cpu: "0.25" + memory: 250Mi + +domainName: "cluster.local" + +# ## Enable global service endpoints for tserver/master services across +# ## zones. Requires common label "app.kubernetes.io/part-of" on resources. +# globalServiceEndpoints: +# tserverGlobalService: +# enabled: false +# # Will use LoadBalancer only if 'enableLoadBalancer' is true. +# # Otherwise, ClusterIP service is created. +# type: LoadBalancer +# annotations: {} +# ## Sets the Service's externalTrafficPolicy +# externalTrafficPolicy: "" +# app: "yb-tserver" +# loadBalancerIP: "" +# name: "tserver-global-service" +# ports: +# tcp-yql-port: "9042" +# tcp-yedis-port: "6379" +# tcp-ysql-port: "5433" + +# masterGlobalService: +# enabled: false +# # Will use LoadBalancer only if 'enableLoadBalancer' is true. +# # Otherwise, ClusterIP service is created. +# type: LoadBalancer +# annotations: {} +# ## Sets the Service's externalTrafficPolicy +# externalTrafficPolicy: "" +# app: "yb-master" +# loadBalancerIP: "" +# name: "master-global-service" +# ports: +# http-ui: "7000" + +## If you would like to define which IP family to use for single stack or define +## the order of IP families for dual-stack, you can choose the address families by +## setting the ipFamilies. It can be any of these values: +## ["IPv4"] +## ["IPv6"] +## ["IPv4","IPv6"] (dual stack) +## ["IPv6","IPv4"] (dual stack) +## Docs: https://kubernetes.io/docs/concepts/services-networking/dual-stack/#dual-stack-service-configuration-scenarios +ipFamilies: [] + +## ipFamilyPolicy can be set to the following values: +## SingleStack +## PreferDualStack +## RequireDualStack +## Selects the .spec.clusterIP from the list of .spec.clusterIPs based on the address +## family of the first element in the .spec.ipFamilies array. +## Docs: https://kubernetes.io/docs/concepts/services-networking/dual-stack/#dual-stack-service-configuration-scenarios +ipFamilyPolicy: "" + +## Default service scope to use if not defined in service endpoint definition. +## Can be "Namespaced"/"AZ" +defaultServiceScope: "AZ" + +serviceEndpoints: + - name: "yb-master-ui" + type: LoadBalancer + # Can be AZ/Namespaced + scope: "AZ" + annotations: {} + clusterIP: "" + ## Sets the Service's externalTrafficPolicy + externalTrafficPolicy: "" + app: "yb-master" + loadBalancerIP: "" + ports: + http-ui: "7000" + extraArgs: {} + + - name: "yb-tserver-service" + type: LoadBalancer + # Can be AZ/Namespaced + scope: "AZ" + annotations: {} + clusterIP: "" + ## Sets the Service's externalTrafficPolicy + externalTrafficPolicy: "" + app: "yb-tserver" + loadBalancerIP: "" + ports: + tcp-yql-port: "9042" + tcp-yedis-port: "6379" + tcp-ysql-port: "5433" + extraArgs: {} + + - name: "yugabyted-ui-service" + type: LoadBalancer + # Can be AZ/Namespaced + scope: "AZ" + annotations: {} + clusterIP: "" + ## Sets the Service's externalTrafficPolicy + externalTrafficPolicy: "" + app: "yb-master" + loadBalancerIP: "" + sessionAffinity: ClientIP + ports: + yugabyted-ui: "15433" + extraArgs: {} + +Services: + - name: "yb-masters" + label: "yb-master" + skipHealthChecks: false + memory_limit_to_ram_ratio: 0.85 + ports: + http-ui: "7000" + tcp-rpc-port: "7100" + yugabyted-ui: "15433" + + - name: "yb-tservers" + label: "yb-tserver" + skipHealthChecks: false + ports: + http-ui: "9000" + tcp-rpc-port: "9100" + tcp-yql-port: "9042" + tcp-yedis-port: "6379" + tcp-ysql-port: "5433" + http-ycql-met: "12000" + http-yedis-met: "11000" + http-ysql-met: "13000" + tcp-ybc-port: "18018" + yugabyted-ui: "15433" + + +## Should be set to true only if Istio is being used. This also adds +## the Istio sidecar injection labels to the pods. +## TODO: remove this once +## https://github.com/yugabyte/yugabyte-db/issues/5641 is fixed. +## +istioCompatibility: + enabled: false + +## Settings required when using multicluster environment. +multicluster: + ## Creates a ClusterIP service for each yb-master and yb-tserver + ## pod. + createServicePerPod: false + ## creates a ClusterIP service whos name does not have release name + ## in it. A common service across different clusters for automatic + ## failover. Useful when using new naming style. + createCommonTserverService: false + + ## Enable it to deploy YugabyteDB in a multi-cluster services enabled + ## Kubernetes cluster (KEP-1645). This will create ServiceExport. + ## GKE Ref - https://cloud.google.com/kubernetes-engine/docs/how-to/multi-cluster-services#registering_a_service_for_export + ## You can use this gist for the reference to deploy the YugabyteDB in a multi-cluster scenario. + ## Gist - https://gist.github.com/baba230896/78cc9bb6f4ba0b3d0e611cd49ed201bf + createServiceExports: false + + ## Mandatory variable when createServiceExports is set to true. + ## Use: In case of GKE, you need to pass GKE Hub Membership Name. + ## GKE Ref - https://cloud.google.com/kubernetes-engine/docs/how-to/multi-cluster-services#enabling + kubernetesClusterId: "" + + ## mcsApiVersion is used for the MCS resources created by the + ## chart. Set to net.gke.io/v1 when using GKE MCS. + mcsApiVersion: "multicluster.x-k8s.io/v1alpha1" + +serviceMonitor: + ## If true, two ServiceMonitor CRs are created. One for yb-master + ## and one for yb-tserver + ## https://github.com/coreos/prometheus-operator/blob/master/Documentation/api.md#servicemonitor + ## + enabled: false + ## interval is the default scrape_interval for all the endpoints + interval: 30s + ## extraLabels can be used to add labels to the ServiceMonitors + ## being created + extraLabels: {} + # release: prom + + ## Configurations of ServiceMonitor for yb-master + master: + enabled: true + port: "http-ui" + interval: "" + path: "/prometheus-metrics" + + ## Configurations of ServiceMonitor for yb-tserver + tserver: + enabled: true + port: "http-ui" + interval: "" + path: "/prometheus-metrics" + ycql: + enabled: true + port: "http-ycql-met" + interval: "" + path: "/prometheus-metrics" + ysql: + enabled: true + port: "http-ysql-met" + interval: "" + path: "/prometheus-metrics" + yedis: + enabled: true + port: "http-yedis-met" + interval: "" + path: "/prometheus-metrics" + + commonMetricRelabelings: + # https://git.io/JJW5p + # Save the name of the metric so we can group_by since we cannot by __name__ directly... + - sourceLabels: ["__name__"] + regex: "(.*)" + targetLabel: "saved_name" + replacement: "$1" + # The following basically retrofit the handler_latency_* metrics to label format. + - sourceLabels: ["__name__"] + regex: "handler_latency_(yb_[^_]*)_([^_]*)_([^_]*)(.*)" + targetLabel: "server_type" + replacement: "$1" + - sourceLabels: ["__name__"] + regex: "handler_latency_(yb_[^_]*)_([^_]*)_([^_]*)(.*)" + targetLabel: "service_type" + replacement: "$2" + - sourceLabels: ["__name__"] + regex: "handler_latency_(yb_[^_]*)_([^_]*)_([^_]*)(_sum|_count)?" + targetLabel: "service_method" + replacement: "$3" + - sourceLabels: ["__name__"] + regex: "handler_latency_(yb_[^_]*)_([^_]*)_([^_]*)(_sum|_count)?" + targetLabel: "__name__" + replacement: "rpc_latency$4" + +resources: {} + +nodeSelector: {} + +## PriorityClassName for the StatefulSet pod template (sts.spec.template.spec.priorityClassName). +## Default for both master and tserver; override per component with master.priorityClassName / tserver.priorityClassName. +## See https://kubernetes.io/docs/concepts/scheduling-eviction/pod-priority-preemption/ +priorityClassName: "" + +affinity: {} + +statefulSetAnnotations: {} + +networkAnnotation: {} + +commonLabels: {} + +## @param dnsPolicy DNS Policy for pod +## ref: https://kubernetes.io/docs/concepts/services-networking/dns-pod-service/ +## E.g. +## dnsPolicy: ClusterFirst +dnsPolicy: "" +## @param dnsConfig DNS Configuration pod +## ref: https://kubernetes.io/docs/concepts/services-networking/dns-pod-service/ +## E.g. +## dnsConfig: +## options: +## - name: ndots +## value: "4" +dnsConfig: {} + + +master: + ## Ref: https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.22/#affinity-v1-core + ## This might override the default affinity from service.yaml + # To successfully merge, we need to follow rules for merging nodeSelectorTerms that kubernentes + # has. Each new node selector term is ORed together, and each match expression or match field in + # a single selector is ANDed together. + # This means, if a pod needs to be scheduled on a label 'custom_label_1' with a value + # 'custom_value_1', we need to add this 'subterm' to each of our pre-defined node affinity + # terms. + # + # Pod anti affinity is a simpler merge. Each term is applied separately, and the weight is tracked. + # The pod that achieves the highest weight is selected. + ## Example. + # affinity: + # podAntiAffinity: + # requiredDuringSchedulingIgnoredDuringExecution: + # - labelSelector: + # matchExpressions: + # - key: app + # operator: In + # values: + # - "yb-master" + # topologyKey: kubernetes.io/hostname + # + # For further examples, see examples/yugabyte/affinity_overrides.yaml + affinity: {} + + ## Extra environment variables passed to the Master pods. + ## Ref: https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.22/#envvar-v1-core + ## Example: + # extraEnv: + # - name: NODE_IP + # valueFrom: + # fieldRef: + # fieldPath: status.hostIP + extraEnv: [] + + # secretEnv variables are used to expose secrets data as env variables in the master pod. + # TODO Add namespace also to support copying secrets from other namespace. + # secretEnv: + # - name: MYSQL_LDAP_PASSWORD + # valueFrom: + # secretKeyRef: + # name: secretName + # key: password + secretEnv: [] + + ## Annotations to be added to the Master pods. + podAnnotations: {} + + ## Labels to be added to the Master pods. + podLabels: {} + + ## Tolerations to be added to the Master pods. + ## Ref: https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.22/#toleration-v1-core + ## Example: + # tolerations: + # - key: dedicated + # operator: Equal + # value: experimental + # effect: NoSchedule + tolerations: [] + + ## Extra volumes + ## extraVolumesMounts are mandatory for each extraVolumes. + ## Ref: https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.22/#volume-v1-core + ## Example: + # extraVolumes: + # - name: custom-nfs-vol + # persistentVolumeClaim: + # claimName: some-nfs-claim + extraVolumes: [] + + ## Extra volume mounts + ## Ref: https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.22/#volumemount-v1-core + ## Example: + # extraVolumeMounts: + # - name: custom-nfs-vol + # mountPath: /home/yugabyte/nfs-backup + extraVolumeMounts: [] + + ## Set service account for master DB pods. The service account + ## should exist in the namespace where the master DB pods are brought up. + serviceAccount: "" + + ## PriorityClassName for master pods (sts.spec.template.spec.priorityClassName). + ## Falls back to top-level priorityClassName if unset. + priorityClassName: "" + + ## Memory limit hard % (between 1-100) of the memory limit. + memoryLimitHardPercentage: 85 + + ## Readiness Probe + readinessProbe: + enabled: false + initialDelaySeconds: 30 + periodSeconds: 20 + timeoutSeconds: 10 + failureThreshold: 3 + successThreshold: 1 + + ## Custom readinessProbe that overrides the default one + ## Example: HTTP based Master readinessProbe + # customReadinessProbe: + # initialDelaySeconds: 30 + # periodSeconds: 20 + # timeoutSeconds: 10 + # failureThreshold: 3 + # successThreshold: 1 + # httpGet: + # path: / + # port: 7000 + ## Ref: https://kubernetes.io/docs/tasks/configure-pod-container/configure-liveness-readiness-startup-probes/#define-readiness-probes + customReadinessProbe: {} + + ## Startup probe + startupProbe: + enabled: false + initialDelaySeconds: 10 + periodSeconds: 10 + timeoutSeconds: 5 + failureThreshold: 30 + successThreshold: 1 + + ## Custom startupProbe that overrides the default one + ## Enabling it will overrides the tserver.startupProbe + ## Example: HTTP based Master startupProbe + # customStartupProbe: + # initialDelaySeconds: 30 + # periodSeconds: 10 + # timeoutSeconds: 5 + # failureThreshold: 3 + # successThreshold: 1 + # httpGet: + # path: / + # port: 7000 + ## Ref: https://kubernetes.io/docs/tasks/configure-pod-container/configure-liveness-readiness-startup-probes/#define-startup-probes + customStartupProbe: {} + + ## Checksum for master gflags secret. If set to empty, statefulset + ## will calculate new checksum value and decide whether to restart pods + ## based on the result of comparing previous checksum value and new value. + ## If previous value is provided again, there will be no Pod restart + ## for gflags changes. + gflagsChecksum: "" + + advanced: + ## Bash commands to run before the start of the master service + ## WARNING: This is an advanced feature. Incorrect use may cause startup failures, + ## security issues, or unexpected behavior. Use with caution and at your own risk. + preCommands: "" + + +tserver: + ## Ref: https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.22/#affinity-v1-core + ## This might override the default affinity from service.yaml + # To successfully merge, we need to follow rules for merging nodeSelectorTerms that kubernentes + # has. Each new node selector term is ORed together, and each match expression or match field in + # a single selector is ANDed together. + # This means, if a pod needs to be scheduled on a label 'custom_label_1' with a value + # 'custom_value_1', we need to add this 'subterm' to each of our pre-defined node affinity + # terms. + # + # Pod anti affinity is a simpler merge. Each term is applied separately, and the weight is tracked. + # The pod that achieves the highest weight is selected. + ## Example. + # affinity: + # podAntiAffinity: + # requiredDuringSchedulingIgnoredDuringExecution: + # - labelSelector: + # matchExpressions: + # - key: app + # operator: In + # values: + # - "yb-tserver" + # topologyKey: kubernetes.io/hostname + # For further examples, see examples/yugabyte/affinity_overrides.yaml + affinity: {} + + ## Extra environment variables passed to the TServer pods. + ## Ref: https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.22/#envvar-v1-core + ## Example: + # extraEnv: + # - name: NODE_IP + # valueFrom: + # fieldRef: + # fieldPath: status.hostIP + extraEnv: [] + + ## secretEnv variables are used to expose secrets data as env variables in the tserver pods. + ## If namespace field is not specified we assume that user already + ## created the secret in the same namespace as DB pods. + ## Example + # secretEnv: + # - name: MYSQL_LDAP_PASSWORD + # valueFrom: + # secretKeyRef: + # name: secretName + # namespace: my-other-namespace-with-ldap-secret + # key: password + secretEnv: [] + + ## Annotations to be added to the TServer pods. + podAnnotations: {} + + ## Labels to be added to the TServer pods. + podLabels: {} + + ## Tolerations to be added to the TServer pods. + ## Ref: https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.22/#toleration-v1-core + ## Example: + # tolerations: + # - key: dedicated + # operator: Equal + # value: experimental + # effect: NoSchedule + tolerations: [] + + ## PriorityClassName for tserver pods (sts.spec.template.spec.priorityClassName). + ## Falls back to top-level priorityClassName if unset. + priorityClassName: "" + + ## Sets the --server_broadcast_addresses flag on the TServer, no + ## preflight checks are done for this address. You might need to add + ## `use_private_ip: cloud` to the gflags.master and gflags.tserver. + serverBroadcastAddress: "" + + ## Extra volumes + ## extraVolumesMounts are mandatory for each extraVolumes. + ## Ref: https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.22/#volume-v1-core + ## Example: + # extraVolumes: + # - name: custom-nfs-vol + # persistentVolumeClaim: + # claimName: some-nfs-claim + extraVolumes: [] + + ## Extra volume mounts + ## Ref: https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.22/#volumemount-v1-core + ## Example: + # extraVolumeMounts: + # - name: custom-nfs-vol + # path: /home/yugabyte/nfs-backup + extraVolumeMounts: [] + + ## Set service account for tserver DB pods. The service account + ## should exist in the namespace where the tserver DB pods are brought up. + serviceAccount: "" + + ## Memory limit hard % (between 1-100) of the memory limit. + memoryLimitHardPercentage: 85 + + ## Readiness Probe + readinessProbe: + enabled: false + initialDelaySeconds: 30 + periodSeconds: 20 + timeoutSeconds: 10 + failureThreshold: 3 + successThreshold: 1 + + ## Custom readinessProbe that overrides the default one + ## Enabling it will overrides the tserver.readinessProbe + ## Example: HTTP based Tserver readinessProbe + # customReadinessProbe: + # initialDelaySeconds: 30 + # periodSeconds: 20 + # timeoutSeconds: 10 + # httpGet: + # path: / + # port: 9000 + ## Ref: https://kubernetes.io/docs/tasks/configure-pod-container/configure-liveness-readiness-startup-probes/#define-readiness-probes + customReadinessProbe: {} + + ## Startup probe + startupProbe: + enabled: false + initialDelaySeconds: 10 + periodSeconds: 10 + timeoutSeconds: 5 + failureThreshold: 30 + successThreshold: 1 + + ## Custom startupProbe that overrides the default one + ## Enabling it will overrides the tserver.startupProbe + ## Example: HTTP based Tserver startupProbe + # customStartupProbe: + # initialDelaySeconds: 30 + # periodSeconds: 10 + # timeoutSeconds: 5 + # failureThreshold: 3 + # successThreshold: 1 + # httpGet: + # path: / + # port: 9000 + ## Ref: https://kubernetes.io/docs/tasks/configure-pod-container/configure-liveness-readiness-startup-probes/#define-startup-probes + customStartupProbe: {} + + ## Checksum for tserver gflags secret. If set to empty, statefulset + ## will calculate new checksum value and decide whether to restart pods + ## based on the result of comparing previous checksum value and new value. + ## If previous value is provided again, there will be no Pod restart + ## for gflags changes. + gflagsChecksum: "" + + advanced: + ## Bash commands to run before the start of the tserver service + ## WARNING: This is an advanced feature. Incorrect use may cause startup failures, + ## security issues, or unexpected behavior. Use with caution and at your own risk. + preCommands: "" + +helm2Legacy: false + +ip_version_support: "v4_only" # v4_only, v6_only are the only supported values at the moment + +# For more https://docs.yugabyte.com/latest/reference/configuration/yugabyted/#environment-variables +authCredentials: + ysql: + user: "" + password: "" + database: "" + # Must contain the key ysqlPassword + passwordSecretName: "" + ycql: + user: "" + password: "" + keyspace: "" + # Must contain the key ycqlPassword + passwordSecretName: "" + +oldNamingStyle: true + +preflight: + # Set to true to skip disk IO check, DNS address resolution, and + # port bind checks + skipAll: false + # Set to true to skip port bind checks + skipBind: false + + ## Set to true to skip ulimit verification + ## SkipAll has higher priority + skipUlimit: false + +## Liveness Probe configuration for both master and tserver pods +livenessProbe: + enabled: true + failureThreshold: 3 + periodSeconds: 10 + successThreshold: 1 + timeoutSeconds: 1 + +## Custom livenessProbe that overrides the default one +## Example: +# customLivenessProbe: +# failureThreshold: 3 +# periodSeconds: 10 +# timeoutSeconds: 1 +# successThreshold: 1 +# exec: +# command: +# - /custom/health/check +customLivenessProbe: {} + +## Pod securityContext +## Ref: https://kubernetes.io/docs/reference/kubernetes-api/workload-resources/pod-v1/#security-context +## The following configuration runs YB-Master and YB-TServer as a non-root user +## Applied at the pod level; settings inherit to all containers in the pod +## unless overridden via containerSecurityContext below. +podSecurityContext: + enabled: false + ## Mark it false, if you want to stop the non root user validation + runAsNonRoot: true + fsGroup: 10001 + runAsUser: 10001 + runAsGroup: 10001 + additionalSettings: {} + +## Container securityContext +## Applied at the container level for each container in the yugabyte pods. +## When enabled, this overrides the values inherited from the pod-level +## podSecurityContext on a per-container basis. +## Ref: https://kubernetes.io/docs/tasks/configure-pod-container/security-context/ +containerSecurityContext: + enabled: false + ## Expected to have runAsUser values != 0 when + ## runAsNonRoot is set to true, otherwise container creation fails. + runAsUser: 10001 + runAsGroup: 10001 + runAsNonRoot: true + additionalSettings: {} + +## Added to handle old universe which has volume annotations +## K8s universe <= 2.5 to >= 2.6 +legacyVolumeClaimAnnotations: false + +useOldPodDisruptionBudget: true + +## Set to true to enable OCP compatibility mode. +ocpCompatibility: + enabled: false + +## Set to true to run OTEL collector as a sidecar in tserver pods +otelCollector: + enabled: false + image: "" + exporters: {} # Add exporters here + # exporters: + # datadog: + # api: + # key: + # site: datadoghq.com + # retry_on_failure: + # enabled: true + # sending_queue: + # enabled: true + # storage: file_storage/queue + + recievers: + ysql: + # Set ysql receiver params here, based on log_line_prefix set in ysql_pg.conf + lineStartPattern: "(?P\\d{4}-\\d{2}-\\d{2} \\d{2}:\\d{2}:\\d{2}[.]\\d{3} \\w{3})[ ][[](?P\\d+)[]][ ]" + regex: "(?P\\d{4}-\\d{2}-\\d{2} \\d{2}:\\d{2}:\\d{2}[.]\\d{3} \\w{3})[ ][[](?P\\d+)[]][ ](?P\\w+): AUDIT: (?P\\w+),(?P\\d+),(?P\\d+),(?P\\w+),(?P[^,]+),(?P[^,]*),(?P[^,]*),(?P(.|\\n|\\r|\\s)*)" + timestamp: + layout: '%Y-%m-%d %H:%M:%S.%L %Z' + parse_from: 'attributes.timestamp_with_ms' + resources: {} + # resources: + # requests: + # cpu: "100m" + # memory: "256Mi" + # limits: + # cpu: "200m" + # memory: "512Mi" + + # Add secret environment variables here if using AWS CloudWatch or GCP Log Explorer. + secretEnv: [] + # secretEnv: + # - envName: AWS_ACCESS_KEY_ID + # envValue: + # - envName: AWS_SECRET_ACCESS_KEY + # envValue: + # - envName: GOOGLE_APPLICATION_CREDENTIALS_CONTENT + # envValue: + + # Alternatively, set `tserver.serviceAccount` to a service account with the necessary permissions + # to utilize IAM roles for access instead of embedding credentials directly. + # Additionally, ensure that the appropriate nodeSelector is added to enable the metadata server + # for example: for IAM authentication in GKE. + # nodeSelector: + # iam.gke.io/gke-metadata-server-enabled: "true" diff --git a/helm-charts/yugabyte/yugabyte-rbac.yaml b/helm-charts/yugabyte/yugabyte-rbac.yaml new file mode 100644 index 0000000..d021fbc --- /dev/null +++ b/helm-charts/yugabyte/yugabyte-rbac.yaml @@ -0,0 +1,19 @@ +# Create YugaByte specific service account +apiVersion: v1 +kind: ServiceAccount +metadata: + name: yugabyte-helm + namespace: kube-system +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRoleBinding +metadata: + name: yugabyte-helm +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: ClusterRole + name: cluster-admin +subjects: + - kind: ServiceAccount + name: yugabyte-helm + namespace: kube-system From e0f2965e42e61cefa2605445ec9353f565d432d7 Mon Sep 17 00:00:00 2001 From: bandigesaikiran Date: Sun, 21 Jun 2026 13:48:32 +0530 Subject: [PATCH 4/6] feat: add keydb deployment support --- examples/keydb/values.yaml | 279 ++++++++++++++++ helm-charts/keydb/.helmignore | 23 ++ helm-charts/keydb/Chart.yaml | 23 ++ helm-charts/keydb/README.md | 181 ++++++++++ helm-charts/keydb/templates/_helpers.tpl | 71 ++++ helm-charts/keydb/templates/cm-health.yaml | 80 +++++ helm-charts/keydb/templates/pdb.yaml | 18 + helm-charts/keydb/templates/sa.yaml | 11 + helm-charts/keydb/templates/secret-utils.yaml | 46 +++ helm-charts/keydb/templates/sm.yaml | 31 ++ helm-charts/keydb/templates/sts.yaml | 311 ++++++++++++++++++ helm-charts/keydb/templates/svc-headless.yaml | 22 ++ helm-charts/keydb/templates/svc-lb.yaml | 26 ++ helm-charts/keydb/templates/svc.yaml | 28 ++ helm-charts/keydb/values.yaml | 279 ++++++++++++++++ 15 files changed, 1429 insertions(+) create mode 100644 examples/keydb/values.yaml create mode 100644 helm-charts/keydb/.helmignore create mode 100644 helm-charts/keydb/Chart.yaml create mode 100644 helm-charts/keydb/README.md create mode 100644 helm-charts/keydb/templates/_helpers.tpl create mode 100644 helm-charts/keydb/templates/cm-health.yaml create mode 100644 helm-charts/keydb/templates/pdb.yaml create mode 100644 helm-charts/keydb/templates/sa.yaml create mode 100644 helm-charts/keydb/templates/secret-utils.yaml create mode 100644 helm-charts/keydb/templates/sm.yaml create mode 100644 helm-charts/keydb/templates/sts.yaml create mode 100644 helm-charts/keydb/templates/svc-headless.yaml create mode 100644 helm-charts/keydb/templates/svc-lb.yaml create mode 100644 helm-charts/keydb/templates/svc.yaml create mode 100644 helm-charts/keydb/values.yaml diff --git a/examples/keydb/values.yaml b/examples/keydb/values.yaml new file mode 100644 index 0000000..dd7b5a6 --- /dev/null +++ b/examples/keydb/values.yaml @@ -0,0 +1,279 @@ +nameOverride: "" +fullnameOverride: "" + +imageRepository: eqalpha/keydb +imageTag: x86_64_v6.3.2 +imagePullPolicy: IfNotPresent +imagePullSecrets: [] + +nodes: 3 + +password: "" +existingSecret: "" +existingSecretPasswordKey: "password" +port: 6379 +portName: server +internalPort: 6379 +internalPortName: keydb + +threads: 2 + +multiMaster: "yes" +activeReplicas: "yes" +protectedMode: "no" +appendonly: "no" + +annotations: {} + +configExtraArgs: [] + # - somesimple: "argument" + # - client-output-buffer-limit: ["normal", "0", "0", "0"] + # - client-output-buffer-limit: ["replica", "268435456", "67108864", "60"] + # - client-output-buffer-limit: ["pubsub", "33554432", "8388608", "60"] + +podAnnotations: {} + +tolerations: {} + # - effect: NoSchedule + # key: key + # operator: Equal + # value: value + +nodeSelector: {} + # topology.kubernetes.io/region: some-region + +topologySpreadConstraints: [] +# - maxSkew: 1 +# ## Optional keys +# # whenUnsatisfiable: DoNotSchedule +# # topologyKey: "topology.kubernetes.io/zone" +# # minDomains: 1 +# # nodeAffinityPolicy: Honor +# # nodeTaintsPolicy: Honor + +affinity: + podAntiAffinity: + preferredDuringSchedulingIgnoredDuringExecution: + - weight: 100 + podAffinityTerm: + labelSelector: + matchExpressions: + - key: app.kubernetes.io/name + operator: In + values: + - '{{ include "keydb.name" . }}' + - key: app.kubernetes.io/instance + operator: In + values: + - '{{ .Release.Name }}' + topologyKey: "kubernetes.io/hostname" + +additionalAffinities: {} + # nodeAffinity: + # requiredDuringSchedulingIgnoredDuringExecution: + # nodeSelectorTerms: + # - matchExpressions: + # - key: node_pool + # operator: In + # values: somenodepool + +podDisruptionBudget: + enabled: true + maxUnavailable: 1 + +# Additional init containers +extraInitContainers: [] + +# Additional sidecar containers +extraContainers: [] +# - name: backup +# image: minio/mc:latest + +# Volumes that can be used in init and sidecar containers +extraVolumes: [] +# - name: volume-from-secret +# secret: +# secretName: secret-to-mount +# - name: empty-dir-volume +# emptyDir: {} + +# Liveness Probe +livenessProbe: + enabled: true + custom: {} + # tcpSocket: + # port: keydb + # initialDelaySeconds: 30 + initialDelaySeconds: 20 + periodSeconds: 5 + timeoutSeconds: 5 + successThreshold: 1 + failureThreshold: 5 + +# Readiness Probe +readinessProbe: + enabled: true + custom: {} + # tcpSocket: + # port: keydb + # initialDelaySeconds: 30 + initialDelaySeconds: 20 + periodSeconds: 5 + timeoutSeconds: 1 + successThreshold: 1 + failureThreshold: 5 + +# Random UUID for readiness GET probe +readinessProbeRandomUuid: "90f717dd-0e68-43b8-9363-fddaad00d6c9" + +# Startup Probe +startupProbe: + enabled: true + custom: {} + # tcpSocket: + # port: keydb + periodSeconds: 5 + timeoutSeconds: 1 + failureThreshold: 24 + +# Lifecycle Hooks +lifecycle: {} + # preStop: + # exec: + # command: + # - sh + # - -c + # - "sleep 15; kill 1" + +persistentVolume: + enabled: true + accessModes: + - ReadWriteOnce + selector: {} + # matchLabels: + # release: "stable" + # matchExpressions: + # - {key: environment, operator: In, values: [dev]} + size: 1Gi + + ## If defined, storageClassName: + ## If set to "-", storageClassName: "", which disables dynamic provisioning + ## If undefined (the default) or set to null, no storageClassName spec is + ## set, choosing the default provisioner. (gp2 on AWS, standard on + ## GKE, AWS & OpenStack) + ## + # storageClass: "-" + + # If persistentVolume is disable, use this to configure the empty dir + emptyDir: {} + +resources: {} + +# Please read https://kubernetes.io/docs/tasks/administer-cluster/sysctl-cluster/#enabling-unsafe-sysctls +# before sysctls setup +securityContext: {} + # sysctls: + # - name: net.core.somaxconn + # value: "512" + # - name: vm.overcommit_memory + # value: "1" + +keydb: + # Container security context + securityContext: {} + +service: + annotations: {} + appProtocol: + enabled: false + +serviceAccount: + enabled: false + create: true + name: "" + + # extraSpec: + # automountServiceAccountToken: false + # imagePullSecrets: + # - name: pull-secret + extraSpec: {} + +loadBalancer: + enabled: false + + # annotations: + # service.beta.kubernetes.io/aws-load-balancer-type: nlb + annotations: {} + + # extraSpec: + # loadBalancerIP: "1.2.3.4" + # loadBalancerSourceRanges: + # - 1.2.3.4/32 + extraSpec: {} + +# Prometheus-operator ServiceMonitor +serviceMonitor: + # Redis exporter must also be enabled + enabled: false + labels: + annotations: + interval: 30s + # scrapeTimeout: 20s + +# Redis exporter +exporter: + enabled: false + imageRepository: oliver006/redis_exporter + imageTag: v1.48.0-alpine + pullPolicy: IfNotPresent + + # Prometheus port & scrape path + port: 9121 + portName: redis-exporter + scrapePath: /metrics + + # Liveness Probe + livenessProbe: + httpGet: + path: /health + port: redis-exporter + + # Readiness Probe + readinessProbe: + httpGet: + path: /health + port: redis-exporter + + # Startup Probe + startupProbe: + httpGet: + path: /health + port: redis-exporter + failureThreshold: 24 + periodSeconds: 5 + + # CPU/Memory resource limits/requests + resources: {} + + # Container security context + securityContext: {} + + # Additional args for redis exporter + extraArgs: [] + # - somesimple: "argument" + # - client-output-buffer-limit: ["normal", "0", "0", "0"] + # - client-output-buffer-limit: ["replica", "268435456", "67108864", "60"] + # - client-output-buffer-limit: ["pubsub", "33554432", "8388608", "60"] + +scripts: + enabled: false + # CPU/Memory resource limits/requests + resources: {} + # Container security context + securityContext: {} + cleanupCoredumps: + enabled: false + minutes: 1440 + cleanupTempfiles: + enabled: true + minutes: 60 diff --git a/helm-charts/keydb/.helmignore b/helm-charts/keydb/.helmignore new file mode 100644 index 0000000..691fa13 --- /dev/null +++ b/helm-charts/keydb/.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/ \ No newline at end of file diff --git a/helm-charts/keydb/Chart.yaml b/helm-charts/keydb/Chart.yaml new file mode 100644 index 0000000..f164c80 --- /dev/null +++ b/helm-charts/keydb/Chart.yaml @@ -0,0 +1,23 @@ +apiVersion: v2 +name: keydb +description: A Helm chart for KeyDB multimaster setup +type: application +version: 0.48.0 +keywords: +- keydb +- redis +- keyvalue +- database +- multimaster +- HA +- high-availability +home: https://keydb.dev +maintainers: +- email: avoronkov@enapter.com + name: Antiarchitect + url: https://github.com/Antiarchitect +sources: +- https://github.com/Enapter/charts +- https://github.com/JohnSully/KeyDB +icon: https://enapter.github.io/charts/keydb.png +appVersion: 6.3.2 diff --git a/helm-charts/keydb/README.md b/helm-charts/keydb/README.md new file mode 100644 index 0000000..8d16f1d --- /dev/null +++ b/helm-charts/keydb/README.md @@ -0,0 +1,181 @@ +# KeyDB + +[KeyDB](https://keydb.dev) clocks in at 5X faster than Redis (node vs node). KeyDB is a popular drop in Redis alternative that people flock to because it enables you to consolidate a lot of the complexities associated with Redis. KeyDB is multithreaded with the ability to use several storage mediums natively and scale vertically. The superior architecture is enabling KeyDB to become the bridge between cache layer and traditional databases offering performance and durability. + +## TL;DR; + +```bash +helm repo add enapter https://enapter.github.io/charts/ +helm install keydb enapter/keydb +``` + +## Introduction + +This chart bootstraps a [KeyDB](https://keydb.dev) highly available multi-master statefulset in a [Kubernetes](http://kubernetes.io) cluster using the Helm package manager. + +## 0.40.1 Upgrade notice + +As the chart is not yet production ready (0.x) backward incompatible changes can be introduced in minor releases. + +`exporter.pullPolicy` is deprecated in favor of `exporter.imagePullPolicy` + + +## 0.38.0 Upgrade notice + +As the chart is not yet production ready (0.x) backward incompatible changes can be introduced in minor releases. + +This release enables using a dedicated ServiceAccount for the KeyDB StatefulSet. Either an SA created by the chart or a pre-exising SA can be used. The corresponding value setting `serviceAccount.enabled` is turned off by default for backward compatibility. + +Please note that the `serviceAccountName` field of the StatefulSet's spec is immutable, so an upgrade from a helm release where the dedicated SA is disabled (the default) to a release where it is explicitly enabled is impossible and will fail. You should plan a migration to an SA-enabled release in advance considering your environment and operational practices, e.g. using a blue-green deployment or scheduling a downtime for removal of the previous release. In case of removal please also consider data retention as necessary, e.g. verify the reclaim policy of the StorageClass in use. + +If you plan a deployment in an environment where dedicated ServiceAccounts are essential, e.g. in a service mesh, please consider enabling the SA setting from the start. + +## 0.33.0 Upgrade notice + +As the chart is not yet production ready (0.x) backward incompatible changes can be introduced in minor releases. +Since 0.33.0 `scripts.cleanup` is obsoleted by `scripts.cleanupTempfiles`. `scripts.cleanupCoredumps` section is added in order to provide ability to cleanup `core.*` files and is disabled by default. Please look `values.yaml`. + +## 0.30.0 Upgrade notice + +As the chart is not yet production ready (0.x) backward incompatible changes can be introduced in minor releases. +Since 0.30.0 `additionalAffinities` option is completely obsolete and `affinity` replaces it. `affinity` is rendered dynamically (approach is taken from Bitnami charts) so you can set dynamic things like `'{{ .Release.Name }}'` right inside the `affinity:` key in `values.yaml`. Will extend this approach for other places in the future. + +## 0.29.0 Upgrade notice + +As the chart is not yet production ready (0.x) backward incompatible changes can be introduced in minor releases. +Since 0.29.0 `configExtraArgs` and `exporter.extraArgs` are now arrays of dicts in order to allow repeating arguments with the same key. +If dict value is an array it is interpreted as multiple arguments for the key. + +### Config Example: + +``` +configExtraArgs: + - client-output-buffer-limit: ["normal", "0", "0", "0"] + - client-output-buffer-limit: ["replica", "268435456", "67108864", "60"] + - client-output-buffer-limit: ["pubsub", "33554432", "8388608", "60"] + - save: ~ + - tcp-backlog "1024" +``` + +### Resulting File: + +``` +... + +exec keydb-server /etc/keydb/redis.conf \ + + ... + + --client-output-buffer-limit "normal" "0" "0" "0" \ + --client-output-buffer-limit "replica" "268435456" "67108864" "60" \ + --client-output-buffer-limit "pubsub" "33554432" "8388608" "60" \ + --save \ + --tcp-backlog "1024" \ + + ... +``` + +## Prerequisites + +- PV provisioner support in the underlying infrastructure if you want to enable persistence + +## Installing the Chart + +To install the chart + +```bash +helm repo add enapter https://enapter.github.io/charts/ +helm install keydb enapter/keydb +``` + +## Configuration + +The following table lists the configurable parameters of the KeyDB chart and their default values. + +| Parameter | Description | Default | +|:--------------------------------|:---------------------------------------------------|:------------------------------------------| +| `imageRepository` | KeyDB docker image | `eqalpha/keydb` | +| `imageTag` | KeyDB docker image tag | `x86_64_v6.3.2` | +| `imagePullPolicy` | K8s imagePullPolicy | `IfNotPresent` | +| `imagePullSecrets` | KeyDB Pod imagePullSecrets | `[]` | +| `nodes` | Number of KeyDB master pods | `3` | +| `password` | If enabled KeyDB servers are password-protected | `""` | +| `existingSecret` | If enabled password is taken from secret | `""` | +| `existingSecretPasswordKey` | Secret key name. | `"password"` | +| `port` | KeyDB service port clients connect to | `6379` | +| `portName` | KeyDB service port name in the Service spec | `server` | +| `threads` | KeyDB server-threads per node | `2` | +| `multiMaster` | KeyDB multi-master setup | `yes` | +| `activeReplicas` | KeyDB active replication setup | `yes` | +| `protectedMode` | KeyDB protection mode | `no` | +| `appendonly` | KeyDB appendonly setting | `no` | +| `configExtraArgs` | Additional configuration arguments for KeyDB | `[]` | +| `annotations` | KeyDB StatefulSet annotations | `{}` | +| `podAnnotations` | KeyDB pods annotations | `{}` | +| `tolerations` | KeyDB tolerations setting | `{}` | +| `nodeSelector` | KeyDB nodeSelector setting | `{}` | +| `topologySpreadConstraints` | KeyDB topologySpreadConstraints setting | `[]` | +| `affinity` | StatefulSet Affinity rules | Look values.yaml | +| `extraInitContainers` | Additional init containers for StatefulSet | `[]` | +| `extraContainers` | Additional sidecar containers for StatefulSet | `[]` | +| `extraVolumes` | Additional volumes for init and sidecar containers | `[]` | +| `livenessProbe.custom` | Custom LivenessProbe for KeyDB pods | `{}` | +| `readinessProbe.custom` | Custom ReadinessProbe for KeyDB pods | `{}` | +| `readinessProbeRandomUuid` | Random UUIDv4 for readiness GET probe | `90f717dd-0e68-43b8-9363-fddaad00d6c9` | +| `startupProbe.custom` | Custom StartupProbe for KeyDB pods | `{}` | +| `persistentVolume.enabled` | Should PVC be created via volumeClaimTemplates | `true` | +| `persistentVolume.accessModes` | Volume access modes | `[ReadWriteOnce]` | +| `persistentVolume.selector` | PVC selector. (In order to match existing PVs) | `{}` | +| `persistentVolume.size` | Size of the volume | `1Gi` | +| `persistentVolume.storageClass` | StorageClassName for volume | `` | +| `podDisruptionBudget` | podDisruptionBudget for KeyDB pods | Look values.yaml | +| `resources` | Resources for KeyDB containers | `{}` | +| `scripts.enabled` | Turn on health util scripts | `false` | +| `scripts.cleanupCoredumps` | Coredumps cleanup scripts | Look values.yaml | +| `scripts.cleanupTempfiles` | Tempfiles cleanup scripts | Look values.yaml | +| `scripts.securityContext` | SecurityContext for scripts container | `{}` | +| `keydb.securityContext` | SecurityContext for KeyDB container | `{}` | +| `securityContext` | SecurityContext for KeyDB pods | `{}` | +| `service.annotations` | Service annotations | `{}` | +| `service.appProtocol.enabled` | Turn on appProtocol fields in port specs | `false` | +| `loadBalancer.enabled` | Create LoadBalancer service | `false` | +| `loadBalancer.annotations` | Annotations for LB | `{}` | +| `loadBalancer.extraSpec` | Additional spec for LB | `{}` | +| `serviceAccount.enabled` | Use a dedicated ServiceAccount (SA) | `false` | +| `serviceAccount.create` | Create the SA (rather than use an existing one) | `true` | +| `serviceAccount.name` | Set the name of an existing SA or override created | `` | +| `serviceAccount.extraSpec` | Additional spec for the created SA | `{}` | +| `serviceMonitor.enabled` | Prometheus operator ServiceMonitor | `false` | +| `serviceMonitor.labels` | Additional labels for ServiceMonitor | `{}` | +| `serviceMonitor.annotations` | Additional annotations for ServiceMonitor | `{}` | +| `serviceMonitor.interval` | ServiceMonitor scrape interval | `30s` | +| `serviceMonitor.scrapeTimeout` | ServiceMonitor scrape timeout | `nil` | +| `exporter.enabled` | Prometheus Exporter sidecar contaner | `false` | +| `exporter.imageRepository` | Exporter Image | `oliver006/redis_exporter` | +| `exporter.imageTag` | Exporter Image Tag | `v1.48.0-alpine` | +| `exporter.pullPolicy` | Exporter imagePullPolicy | `IfNotPresent` | +| `exporter.port` | `prometheus.io/port` | `9121` | +| `exporter.portName` | Exporter service port name in the Service spec | `redis-exporter` | +| `exporter.scrapePath` | `prometheus.io/path` | `/metrics` | +| `exporter.livenessProbe` | LivenessProbe for sidecar Prometheus exporter | Look values.yaml | +| `exporter.readinessProbe` | ReadinessProbe for sidecar Prometheus exporter | Look values.yaml | +| `exporter.startupProbe` | StartupProbe for sidecar Prometheus exporter | Look values.yaml | +| `exporter.resources` | Resources for sidecar Prometheus container | `{}` | +| `exporter.securityContext` | SecurityContext for Prometheus exporter container | `{}` | +| `exporter.extraArgs` | Additional arguments for exporter | `[]` | + +## Using existingSecret + +When definining existingSecret (by default is "") password value is ignored. Password is taken from that secret, instead of being provided as plain text under values.yaml file. \ +Secret key must be `existingSecretPasswordKey` (*password* by default). \ +Example of of such secret: +```bash +kubectl create secret generic keydb-password --from-literal=password=KEYDB_PASSWORD +``` +Definition of existingSecret in that case: +```yaml +password: "" +existingSecret: keydb-password +existingSecretPasswordKey: password-key-in-secret-file +``` +It is important to use only one way of providing passwords: via plain text under values.yaml or using already existing secret. diff --git a/helm-charts/keydb/templates/_helpers.tpl b/helm-charts/keydb/templates/_helpers.tpl new file mode 100644 index 0000000..d175617 --- /dev/null +++ b/helm-charts/keydb/templates/_helpers.tpl @@ -0,0 +1,71 @@ +{{/* vim: set filetype=mustache: */}} +{{/* +Expand the name of the chart. +*/}} +{{- define "keydb.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 "keydb.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 "keydb.chart" -}} +{{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" -}} +{{- end -}} + +{{/* +Common labels +*/}} +{{- define "keydb.labels" -}} +helm.sh/chart: {{ include "keydb.chart" . }} +{{ include "keydb.selectorLabels" . }} +{{- if .Chart.AppVersion }} +app.kubernetes.io/version: {{ .Chart.AppVersion | quote }} +{{- end }} +app.kubernetes.io/managed-by: {{ .Release.Service }} +{{- end -}} + +{{/* +Selector labels +*/}} +{{- define "keydb.selectorLabels" -}} +app.kubernetes.io/name: {{ include "keydb.name" . }} +app.kubernetes.io/instance: {{ .Release.Name }} +{{- end -}} + +{{/* +Create the name of the service account to use +*/}} +{{- define "keydb.serviceAccountName" -}} +{{- if .Values.serviceAccount.create -}} + {{ default (include "keydb.fullname" .) .Values.serviceAccount.name }} +{{- else -}} + {{ default "default" .Values.serviceAccount.name }} +{{- end -}} +{{- end -}} + +{{- define "common.tplvalues.render" -}} + {{- if typeIs "string" .value }} + {{- tpl .value .context }} + {{- else }} + {{- tpl (.value | toYaml) .context }} + {{- end }} +{{- end -}} \ No newline at end of file diff --git a/helm-charts/keydb/templates/cm-health.yaml b/helm-charts/keydb/templates/cm-health.yaml new file mode 100644 index 0000000..7034cfd --- /dev/null +++ b/helm-charts/keydb/templates/cm-health.yaml @@ -0,0 +1,80 @@ +apiVersion: v1 +kind: ConfigMap +metadata: + name: {{ include "keydb.fullname" . }}-health + labels: + {{- include "keydb.labels" . | nindent 4 }} +data: + ping_readiness_local.sh: |- + #!/bin/bash + + set -e + + loading_response="LOADING KeyDB is loading the dataset in memory" + + [[ -n "${REDIS_PASSWORD}" ]] && export REDISCLI_AUTH="${REDIS_PASSWORD}" + response="$( + timeout -s 15 "${1}" \ + keydb-cli \ + -h localhost \ + -p "${REDIS_PORT}" \ + GET {{ .Values.readinessProbeRandomUuid }} + )" + if [ "${response}" = "${loading_response}" ]; 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 15 "${1}" \ + keydb-cli \ + -h localhost \ + -p "${REDIS_PORT}" \ + PING + )" + if [ "${response}" != "PONG" ]; then + echo "${response}" + exit 1 + fi + +{{- if .Values.scripts.enabled }} + + scripts_local.sh: |- + #!/bin/bash + + set -e + + script_dir="$(dirname "$0")" + while true; do +{{- if .Values.scripts.cleanupCoredumps.enabled }} + "${script_dir}/cleanup_coredumps.sh" +{{- end }} +{{- if .Values.scripts.cleanupTempfiles.enabled }} + "${script_dir}/cleanup_tempfiles.sh" +{{- end }} + sleep 60 + done +{{- end }} + +{{- if .Values.scripts.cleanupCoredumps.enabled }} + cleanup_coredumps.sh: |- + #!/bin/bash + + set -e + + find /data/ -type f -name "core.*" -mmin +{{ .Values.scripts.cleanupCoredumps.minutes }} -delete +{{- end }} +{{- if .Values.scripts.cleanupTempfiles.enabled }} + cleanup_tempfiles.sh: |- + #!/bin/bash + + set -e + + find /data/ -type f \( -name "temp-*.aof" -o -name "temp-*.rdb" \) -mmin +{{ .Values.scripts.cleanupTempfiles.minutes }} -delete +{{- end }} diff --git a/helm-charts/keydb/templates/pdb.yaml b/helm-charts/keydb/templates/pdb.yaml new file mode 100644 index 0000000..6af8774 --- /dev/null +++ b/helm-charts/keydb/templates/pdb.yaml @@ -0,0 +1,18 @@ +{{- if .Values.podDisruptionBudget.enabled }} +apiVersion: policy/v1 +kind: PodDisruptionBudget +metadata: + name: {{ include "keydb.fullname" . }} + labels: + {{- include "keydb.labels" . | nindent 4 }} +spec: +{{- if .Values.podDisruptionBudget.maxUnavailable }} + maxUnavailable: {{ .Values.podDisruptionBudget.maxUnavailable }} +{{- end }} +{{- if .Values.podDisruptionBudget.minAvailable }} + minAvailable: {{ .Values.podDisruptionBudget.minAvailable }} +{{- end }} + selector: + matchLabels: + {{- include "keydb.selectorLabels" . | nindent 6 }} +{{- end }} diff --git a/helm-charts/keydb/templates/sa.yaml b/helm-charts/keydb/templates/sa.yaml new file mode 100644 index 0000000..db7569b --- /dev/null +++ b/helm-charts/keydb/templates/sa.yaml @@ -0,0 +1,11 @@ +{{- if .Values.serviceAccount.enabled | and .Values.serviceAccount.create }} +apiVersion: v1 +kind: ServiceAccount +metadata: + name: {{ include "keydb.serviceAccountName" . | quote }} + labels: + {{- include "keydb.labels" . | nindent 4 }} +{{- with .Values.serviceAccount.extraSpec }} +{{ toYaml . }} +{{- end }} +{{- end }} diff --git a/helm-charts/keydb/templates/secret-utils.yaml b/helm-charts/keydb/templates/secret-utils.yaml new file mode 100644 index 0000000..ec9b8fb --- /dev/null +++ b/helm-charts/keydb/templates/secret-utils.yaml @@ -0,0 +1,46 @@ +apiVersion: v1 +kind: Secret +metadata: + name: {{ include "keydb.fullname" . }}-utils + labels: + {{- include "keydb.labels" . | nindent 4 }} +type: Opaque +stringData: + server.sh: | + #!/bin/bash + set -euxo pipefail + + host="$(hostname)" + replicas=() + for node in {0..{{ (sub (.Values.nodes | int) 1) }}}; do + if [ "${host}" != "{{ include "keydb.fullname" . }}-${node}" ]; then + replicas+=("--replicaof {{ include "keydb.fullname" . }}-${node}.{{ include "keydb.fullname" . }}-headless {{ .Values.port }}") + fi + done + exec keydb-server /etc/keydb/redis.conf \ + --active-replica {{ .Values.activeReplicas | quote }} \ + --multi-master {{ .Values.multiMaster | quote }} \ + --appendonly {{ .Values.appendonly | quote }} \ + --bind "0.0.0.0" \ + --port "{{ .Values.internalPort }}" \ + --protected-mode {{ .Values.protectedMode | quote }} \ + --server-threads {{ .Values.threads | quote }} \ + {{- if .Values.existingSecret }} + --masterauth "${REDIS_PASSWORD}" \ + --requirepass "${REDIS_PASSWORD}" \ + {{- else if .Values.password }} + --masterauth {{ .Values.password | quote }} \ + --requirepass {{ .Values.password | quote }} \ + {{- end }} + {{- range $item := .Values.configExtraArgs }} + {{- range $key, $value := $item }} + {{- if kindIs "invalid" $value }} + --{{ $key }} \ + {{- else if kindIs "slice" $value }} + --{{ $key }}{{ range $value }} {{ . | quote }}{{ end }} \ + {{- else }} + --{{ $key }} {{ $value | quote }} \ + {{- end }} + {{- end }} + {{- end }} + "${replicas[@]}" diff --git a/helm-charts/keydb/templates/sm.yaml b/helm-charts/keydb/templates/sm.yaml new file mode 100644 index 0000000..8f94b4a --- /dev/null +++ b/helm-charts/keydb/templates/sm.yaml @@ -0,0 +1,31 @@ +{{- if and .Values.exporter.enabled .Values.serviceMonitor.enabled }} +apiVersion: monitoring.coreos.com/v1 +kind: ServiceMonitor +metadata: + name: {{ include "keydb.fullname" . }} + labels: + {{- include "keydb.labels" . | nindent 4 }} + {{- if .Values.serviceMonitor.labels }} + {{- toYaml .Values.serviceMonitor.labels | nindent 4 }} + {{- end }} + {{- if .Values.serviceMonitor.annotations }} + annotations: + {{- toYaml .Values.serviceMonitor.annotations | nindent 4 }} + {{- end }} +spec: + selector: + matchLabels: + {{- include "keydb.labels" . | nindent 6 }} + namespaceSelector: + matchNames: + - {{.Release.Namespace }} + endpoints: + - port: redis-exporter + path: {{ .Values.exporter.scrapePath }} + {{- if .Values.serviceMonitor.interval }} + interval: {{ .Values.serviceMonitor.interval }} + {{- end }} + {{- if .Values.serviceMonitor.scrapeTimeout }} + scrapeTimeout: {{ .Values.serviceMonitor.scrapeTimeout }} + {{- end }} +{{- end }} diff --git a/helm-charts/keydb/templates/sts.yaml b/helm-charts/keydb/templates/sts.yaml new file mode 100644 index 0000000..7dd9927 --- /dev/null +++ b/helm-charts/keydb/templates/sts.yaml @@ -0,0 +1,311 @@ +apiVersion: apps/v1 +kind: StatefulSet +metadata: + name: {{ include "keydb.fullname" . }} + {{- if .Values.annotations }} + annotations: + {{- toYaml .Values.annotations | nindent 4 }} + {{- end }} + labels: + {{- include "keydb.labels" . | nindent 4 }} +spec: + replicas: {{ .Values.nodes }} + serviceName: {{ include "keydb.fullname" . }}-headless + selector: + matchLabels: + {{- include "keydb.selectorLabels" . | nindent 6 }} + template: + metadata: + annotations: + checksum/secret-utils: {{ include (print $.Template.BasePath "/secret-utils.yaml") . | sha256sum }} + {{- if .Values.exporter.enabled }} + prometheus.io/scrape: "true" + prometheus.io/path: "{{ .Values.exporter.scrapePath }}" + prometheus.io/port: "{{ .Values.exporter.port }}" + {{- end }} + {{- if .Values.podAnnotations }} + {{- toYaml .Values.podAnnotations | nindent 8 }} + {{- end }} + labels: + {{- include "keydb.labels" . | nindent 8 }} + spec: + affinity: + {{- include "common.tplvalues.render" (dict "value" .Values.affinity "context" $) | nindent 8 }} + {{- if .Values.extraInitContainers }} + initContainers: + {{- toYaml .Values.extraInitContainers | nindent 6 }} + {{- end }} + containers: + - name: keydb + {{- if .Values.image }} + image: {{ .Values.image }} + {{- else }} + image: {{ .Values.imageRepository }}:{{ .Values.imageTag }} + {{- end }} + imagePullPolicy: {{ .Values.imagePullPolicy }} + command: + - /utils/server.sh + env: + - name: REDIS_PORT + value: {{ .Values.internalPort | quote }} + {{- if .Values.existingSecret }} + - name: REDIS_PASSWORD + valueFrom: + secretKeyRef: + name: {{ .Values.existingSecret }} + key: {{ .Values.existingSecretPasswordKey }} + {{- else if .Values.password }} + - name: REDIS_PASSWORD + value: "{{ .Values.password }}" + {{- end }} + ports: + - name: {{ .Values.internalPortName }} + containerPort: {{ .Values.internalPort | int }} + protocol: TCP + {{- if .Values.livenessProbe.enabled }} + livenessProbe: + {{- if .Values.livenessProbe.custom }} + {{- toYaml .Values.livenessProbe.custom | nindent 10 }} + {{- else }} + initialDelaySeconds: {{ .Values.livenessProbe.initialDelaySeconds }} + periodSeconds: {{ .Values.livenessProbe.periodSeconds }} + # One second longer than command timeout should prevent generation of zombie processes. + timeoutSeconds: {{ add1 .Values.livenessProbe.timeoutSeconds }} + successThreshold: {{ .Values.livenessProbe.successThreshold }} + failureThreshold: {{ .Values.livenessProbe.failureThreshold }} + exec: + command: + - sh + - -c + - /health/ping_liveness_local.sh {{ .Values.livenessProbe.timeoutSeconds }} + {{- end }} + {{- end }} + {{- if .Values.readinessProbe.enabled }} + readinessProbe: + {{- if .Values.readinessProbe.custom }} + {{- toYaml .Values.readinessProbe.custom | nindent 10 }} + {{- else }} + initialDelaySeconds: {{ .Values.readinessProbe.initialDelaySeconds }} + periodSeconds: {{ .Values.readinessProbe.periodSeconds }} + # One second longer than command timeout should prevent generation of zombie processes. + timeoutSeconds: {{ add1 .Values.readinessProbe.timeoutSeconds }} + successThreshold: {{ .Values.readinessProbe.successThreshold }} + failureThreshold: {{ .Values.readinessProbe.failureThreshold }} + exec: + command: + - sh + - -c + - /health/ping_readiness_local.sh {{ .Values.readinessProbe.timeoutSeconds }} + {{- end }} + {{- end }} + {{- if .Values.startupProbe.enabled }} + startupProbe: + {{- if .Values.startupProbe.custom }} + {{- toYaml .Values.startupProbe.custom | nindent 10 }} + {{- else }} + periodSeconds: {{ .Values.startupProbe.periodSeconds }} + # One second longer than command timeout should prevent generation of zombie processes. + timeoutSeconds: {{ add1 .Values.startupProbe.timeoutSeconds }} + failureThreshold: {{ .Values.startupProbe.failureThreshold }} + exec: + command: + - sh + - -c + - /health/ping_readiness_local.sh {{ .Values.startupProbe.timeoutSeconds }} + {{- end }} + {{- end }} + {{- if .Values.lifecycle }} + lifecycle: + {{- toYaml .Values.lifecycle | nindent 10 }} + {{- end }} + resources: + {{- toYaml .Values.resources | nindent 10 }} + securityContext: + {{- toYaml .Values.keydb.securityContext | nindent 10 }} + volumeMounts: + - name: health + mountPath: /health + - name: keydb-data + mountPath: /data + - name: utils + mountPath: /utils + readOnly: true + {{- if .Values.exporter.enabled }} + - name: redis-exporter + {{- if .Values.exporter.image }} + image: {{ .Values.exporter.image }} + {{- else }} + image: {{ .Values.exporter.imageRepository }}:{{ .Values.exporter.imageTag }} + {{- end }} + imagePullPolicy: {{ .Values.exporter.pullPolicy }} + args: + {{- range $item := .Values.exporter.extraArgs }} + {{- range $key, $value := $item }} + {{- if kindIs "invalid" $value }} + - --{{ $key }} + {{- else if kindIs "slice" $value }} + - --{{ $key }} + {{- range $value }} + - {{ . | quote }} + {{- end }} + {{- else }} + - --{{ $key }} + - {{ $value | quote }} + {{- end }} + {{- end }} + {{- end }} + env: + - name: REDIS_EXPORTER_WEB_LISTEN_ADDRESS + value: "0.0.0.0:{{ .Values.exporter.port }}" + - name: REDIS_EXPORTER_WEB_TELEMETRY_PATH + value: {{ .Values.exporter.scrapePath | quote }} + - name: REDIS_ADDR + value: "redis://localhost:{{ .Values.internalPort }}" + {{- if .Values.existingSecret }} + - name: REDIS_PASSWORD + valueFrom: + secretKeyRef: + name: {{ .Values.existingSecret }} + key: {{ .Values.existingSecretPasswordKey }} + {{- else if .Values.password }} + - name: REDIS_PASSWORD + value: "{{ .Values.password }}" + {{- end }} + {{- if .Values.exporter.livenessProbe }} + livenessProbe: + {{- toYaml .Values.exporter.livenessProbe | nindent 10 }} + {{- end }} + {{- if .Values.exporter.readinessProbe }} + readinessProbe: + {{- toYaml .Values.exporter.readinessProbe | nindent 10 }} + {{- end }} + {{- if .Values.exporter.startupProbe }} + startupProbe: + {{- toYaml .Values.exporter.startupProbe | nindent 10 }} + {{- end }} + resources: + {{- toYaml .Values.exporter.resources | nindent 10 }} + securityContext: + {{- toYaml .Values.exporter.securityContext | nindent 10 }} + ports: + - name: {{ .Values.exporter.portName | quote }} + containerPort: {{ .Values.exporter.port }} + protocol: TCP + {{- end }} + {{- if .Values.scripts.enabled }} + - name: scripts + {{- if .Values.image }} + image: {{ .Values.image }} + {{- else }} + image: {{ .Values.imageRepository }}:{{ .Values.imageTag }} + {{- end }} + imagePullPolicy: {{ .Values.imagePullPolicy }} + command: + - /health/scripts_local.sh + env: + - name: REDIS_PORT + value: {{ .Values.internalPort | quote }} + {{- if .Values.existingSecret }} + - name: REDIS_PASSWORD + valueFrom: + secretKeyRef: + name: {{ .Values.existingSecret }} + key: {{ .Values.existingSecretPasswordKey }} + {{- else if .Values.password }} + - name: REDIS_PASSWORD + value: "{{ .Values.password }}" + {{- end }} + resources: + {{- toYaml .Values.scripts.resources | nindent 10 }} + securityContext: + {{- toYaml .Values.scripts.securityContext | nindent 10 }} + volumeMounts: + - name: health + mountPath: /health + - name: keydb-data + mountPath: /data + {{- end }} + {{- if .Values.extraContainers }} + {{- toYaml .Values.extraContainers | nindent 6 }} + {{- end }} + imagePullSecrets: + {{- toYaml .Values.imagePullSecrets | nindent 8 }} + securityContext: + {{- toYaml .Values.securityContext | nindent 8 }} + {{- if .Values.serviceAccount.enabled }} + serviceAccountName: {{ include "keydb.serviceAccountName" . | quote }} + {{- end }} + {{- if .Values.tolerations }} + tolerations: + {{- toYaml .Values.tolerations | nindent 8 }} + {{- end }} + {{- if .Values.nodeSelector }} + nodeSelector: + {{- toYaml .Values.nodeSelector | nindent 8 }} + {{- end }} + {{- if .Values.topologySpreadConstraints }} + topologySpreadConstraints: + {{- range .Values.topologySpreadConstraints }} + - labelSelector: + matchLabels: + {{- include "keydb.selectorLabels" $ | nindent 14 }} + topologyKey: {{ default "topology.kubernetes.io/zone" .topologyKey }} + maxSkew: {{ .maxSkew }} + {{- if .minDomains }} + minDomains: {{ .minDomains }} + {{- end }} + whenUnsatisfiable: {{ default "DoNotSchedule" .whenUnsatisfiable }} + {{- if .nodeAffinityPolicy }} + nodeAffinityPolicy: {{ .nodeAffinityPolicy }} + {{- end }} + {{- if .nodeTaintsPolicy }} + nodeTaintsPolicy: {{ .nodeTaintsPolicy }} + {{- end }} + {{- end }} + {{- end }} + volumes: + - name: health + configMap: + name: {{ include "keydb.fullname" . }}-health + defaultMode: 0755 + - name: utils + secret: + secretName: {{ include "keydb.fullname" . }}-utils + defaultMode: 0755 + items: + - key: server.sh + path: server.sh + {{- if not .Values.persistentVolume.enabled }} + - name: keydb-data + emptyDir: {{- toYaml .Values.persistentVolume.emptyDir | nindent 10 }} + {{- end }} + {{- if .Values.extraVolumes }} + {{- toYaml .Values.extraVolumes | nindent 6 }} + {{- end }} + {{- if .Values.persistentVolume.enabled }} + volumeClaimTemplates: + - metadata: + name: keydb-data + annotations: + {{- if .Values.persistentVolume.annotations }} + {{- toYaml .Values.persistentVolume.annotations | nindent 8 }} + {{- end }} + labels: + spec: + accessModes: + {{- toYaml .Values.persistentVolume.accessModes | nindent 8 }} + resources: + requests: + storage: {{ .Values.persistentVolume.size }} + {{- if .Values.persistentVolume.storageClass }} + {{- if (eq "-" .Values.persistentVolume.storageClass) }} + storageClassName: "" + {{ else }} + storageClassName: {{ .Values.persistentVolume.storageClass }} + {{- end }} + {{- end }} + {{- if .Values.persistentVolume.selector }} + selector: + {{- toYaml .Values.persistentVolume.selector | nindent 8 }} + {{- end }} + {{- end }} diff --git a/helm-charts/keydb/templates/svc-headless.yaml b/helm-charts/keydb/templates/svc-headless.yaml new file mode 100644 index 0000000..ea4298e --- /dev/null +++ b/helm-charts/keydb/templates/svc-headless.yaml @@ -0,0 +1,22 @@ +# Headless service +apiVersion: v1 +kind: Service +metadata: + name: {{ include "keydb.fullname" . }}-headless + labels: + {{- include "keydb.labels" . | nindent 4 }} + annotations: + {{- toYaml .Values.service.annotations | nindent 4 }} +spec: + type: ClusterIP + clusterIP: None + ports: + - name: {{ .Values.portName | quote }} + port: {{ .Values.port | int }} + protocol: TCP + targetPort: {{ .Values.internalPortName | quote }} + {{- if .Values.service.appProtocol.enabled }} + appProtocol: redis + {{- end }} + selector: + {{- include "keydb.selectorLabels" . | nindent 4 }} diff --git a/helm-charts/keydb/templates/svc-lb.yaml b/helm-charts/keydb/templates/svc-lb.yaml new file mode 100644 index 0000000..4370915 --- /dev/null +++ b/helm-charts/keydb/templates/svc-lb.yaml @@ -0,0 +1,26 @@ +{{- if .Values.loadBalancer.enabled }} +# Load balancer service +apiVersion: v1 +kind: Service +metadata: + name: {{ include "keydb.fullname" . }}-lb + labels: + {{- include "keydb.labels" . | nindent 4 }} + annotations: + {{- toYaml .Values.loadBalancer.annotations | nindent 4 }} +spec: + type: LoadBalancer + {{- if .Values.loadBalancer.extraSpec }} + {{- toYaml .Values.loadBalancer.extraSpec | nindent 2 }} + {{- end }} + ports: + - name: {{ .Values.portName | quote }} + port: {{ .Values.port | int }} + protocol: TCP + targetPort: {{ .Values.internalPortName | quote }} + {{- if .Values.service.appProtocol.enabled }} + appProtocol: redis + {{- end }} + selector: + {{- include "keydb.selectorLabels" . | nindent 4 }} +{{- end }} diff --git a/helm-charts/keydb/templates/svc.yaml b/helm-charts/keydb/templates/svc.yaml new file mode 100644 index 0000000..1d1ef1d --- /dev/null +++ b/helm-charts/keydb/templates/svc.yaml @@ -0,0 +1,28 @@ +apiVersion: v1 +kind: Service +metadata: + name: {{ include "keydb.fullname" . }} + labels: + {{- include "keydb.labels" . | nindent 4 }} + annotations: + {{- toYaml .Values.service.annotations | nindent 4 }} +spec: + type: ClusterIP + ports: + - name: {{ .Values.portName | quote }} + port: {{ .Values.port | int }} + protocol: TCP + targetPort: {{ .Values.internalPortName | quote }} + {{- if .Values.service.appProtocol.enabled }} + appProtocol: redis + {{- end }} + - name: {{ .Values.exporter.portName | quote }} + port: {{ .Values.exporter.port | int }} + protocol: TCP + targetPort: {{ .Values.exporter.portName | quote }} + {{- if .Values.service.appProtocol.enabled }} + appProtocol: http + {{- end }} + selector: + {{- include "keydb.selectorLabels" . | nindent 4 }} + sessionAffinity: ClientIP diff --git a/helm-charts/keydb/values.yaml b/helm-charts/keydb/values.yaml new file mode 100644 index 0000000..dd7b5a6 --- /dev/null +++ b/helm-charts/keydb/values.yaml @@ -0,0 +1,279 @@ +nameOverride: "" +fullnameOverride: "" + +imageRepository: eqalpha/keydb +imageTag: x86_64_v6.3.2 +imagePullPolicy: IfNotPresent +imagePullSecrets: [] + +nodes: 3 + +password: "" +existingSecret: "" +existingSecretPasswordKey: "password" +port: 6379 +portName: server +internalPort: 6379 +internalPortName: keydb + +threads: 2 + +multiMaster: "yes" +activeReplicas: "yes" +protectedMode: "no" +appendonly: "no" + +annotations: {} + +configExtraArgs: [] + # - somesimple: "argument" + # - client-output-buffer-limit: ["normal", "0", "0", "0"] + # - client-output-buffer-limit: ["replica", "268435456", "67108864", "60"] + # - client-output-buffer-limit: ["pubsub", "33554432", "8388608", "60"] + +podAnnotations: {} + +tolerations: {} + # - effect: NoSchedule + # key: key + # operator: Equal + # value: value + +nodeSelector: {} + # topology.kubernetes.io/region: some-region + +topologySpreadConstraints: [] +# - maxSkew: 1 +# ## Optional keys +# # whenUnsatisfiable: DoNotSchedule +# # topologyKey: "topology.kubernetes.io/zone" +# # minDomains: 1 +# # nodeAffinityPolicy: Honor +# # nodeTaintsPolicy: Honor + +affinity: + podAntiAffinity: + preferredDuringSchedulingIgnoredDuringExecution: + - weight: 100 + podAffinityTerm: + labelSelector: + matchExpressions: + - key: app.kubernetes.io/name + operator: In + values: + - '{{ include "keydb.name" . }}' + - key: app.kubernetes.io/instance + operator: In + values: + - '{{ .Release.Name }}' + topologyKey: "kubernetes.io/hostname" + +additionalAffinities: {} + # nodeAffinity: + # requiredDuringSchedulingIgnoredDuringExecution: + # nodeSelectorTerms: + # - matchExpressions: + # - key: node_pool + # operator: In + # values: somenodepool + +podDisruptionBudget: + enabled: true + maxUnavailable: 1 + +# Additional init containers +extraInitContainers: [] + +# Additional sidecar containers +extraContainers: [] +# - name: backup +# image: minio/mc:latest + +# Volumes that can be used in init and sidecar containers +extraVolumes: [] +# - name: volume-from-secret +# secret: +# secretName: secret-to-mount +# - name: empty-dir-volume +# emptyDir: {} + +# Liveness Probe +livenessProbe: + enabled: true + custom: {} + # tcpSocket: + # port: keydb + # initialDelaySeconds: 30 + initialDelaySeconds: 20 + periodSeconds: 5 + timeoutSeconds: 5 + successThreshold: 1 + failureThreshold: 5 + +# Readiness Probe +readinessProbe: + enabled: true + custom: {} + # tcpSocket: + # port: keydb + # initialDelaySeconds: 30 + initialDelaySeconds: 20 + periodSeconds: 5 + timeoutSeconds: 1 + successThreshold: 1 + failureThreshold: 5 + +# Random UUID for readiness GET probe +readinessProbeRandomUuid: "90f717dd-0e68-43b8-9363-fddaad00d6c9" + +# Startup Probe +startupProbe: + enabled: true + custom: {} + # tcpSocket: + # port: keydb + periodSeconds: 5 + timeoutSeconds: 1 + failureThreshold: 24 + +# Lifecycle Hooks +lifecycle: {} + # preStop: + # exec: + # command: + # - sh + # - -c + # - "sleep 15; kill 1" + +persistentVolume: + enabled: true + accessModes: + - ReadWriteOnce + selector: {} + # matchLabels: + # release: "stable" + # matchExpressions: + # - {key: environment, operator: In, values: [dev]} + size: 1Gi + + ## If defined, storageClassName: + ## If set to "-", storageClassName: "", which disables dynamic provisioning + ## If undefined (the default) or set to null, no storageClassName spec is + ## set, choosing the default provisioner. (gp2 on AWS, standard on + ## GKE, AWS & OpenStack) + ## + # storageClass: "-" + + # If persistentVolume is disable, use this to configure the empty dir + emptyDir: {} + +resources: {} + +# Please read https://kubernetes.io/docs/tasks/administer-cluster/sysctl-cluster/#enabling-unsafe-sysctls +# before sysctls setup +securityContext: {} + # sysctls: + # - name: net.core.somaxconn + # value: "512" + # - name: vm.overcommit_memory + # value: "1" + +keydb: + # Container security context + securityContext: {} + +service: + annotations: {} + appProtocol: + enabled: false + +serviceAccount: + enabled: false + create: true + name: "" + + # extraSpec: + # automountServiceAccountToken: false + # imagePullSecrets: + # - name: pull-secret + extraSpec: {} + +loadBalancer: + enabled: false + + # annotations: + # service.beta.kubernetes.io/aws-load-balancer-type: nlb + annotations: {} + + # extraSpec: + # loadBalancerIP: "1.2.3.4" + # loadBalancerSourceRanges: + # - 1.2.3.4/32 + extraSpec: {} + +# Prometheus-operator ServiceMonitor +serviceMonitor: + # Redis exporter must also be enabled + enabled: false + labels: + annotations: + interval: 30s + # scrapeTimeout: 20s + +# Redis exporter +exporter: + enabled: false + imageRepository: oliver006/redis_exporter + imageTag: v1.48.0-alpine + pullPolicy: IfNotPresent + + # Prometheus port & scrape path + port: 9121 + portName: redis-exporter + scrapePath: /metrics + + # Liveness Probe + livenessProbe: + httpGet: + path: /health + port: redis-exporter + + # Readiness Probe + readinessProbe: + httpGet: + path: /health + port: redis-exporter + + # Startup Probe + startupProbe: + httpGet: + path: /health + port: redis-exporter + failureThreshold: 24 + periodSeconds: 5 + + # CPU/Memory resource limits/requests + resources: {} + + # Container security context + securityContext: {} + + # Additional args for redis exporter + extraArgs: [] + # - somesimple: "argument" + # - client-output-buffer-limit: ["normal", "0", "0", "0"] + # - client-output-buffer-limit: ["replica", "268435456", "67108864", "60"] + # - client-output-buffer-limit: ["pubsub", "33554432", "8388608", "60"] + +scripts: + enabled: false + # CPU/Memory resource limits/requests + resources: {} + # Container security context + securityContext: {} + cleanupCoredumps: + enabled: false + minutes: 1440 + cleanupTempfiles: + enabled: true + minutes: 60 From d13c376c89d1ed5599353358fb13778018f3d14d Mon Sep 17 00:00:00 2001 From: bandigesaikiran19 Date: Fri, 26 Jun 2026 08:24:52 +0000 Subject: [PATCH 5/6] Added PR review changes for keydb --- examples/keydb/values.yaml | 1808 ++++++++++++++--- helm-charts/keydb/.helmignore | 4 +- helm-charts/keydb/Chart.lock | 6 + helm-charts/keydb/Chart.yaml | 45 +- helm-charts/keydb/README.md | 814 ++++++-- helm-charts/keydb/charts/common/.helmignore | 26 + helm-charts/keydb/charts/common/Chart.yaml | 23 + helm-charts/keydb/charts/common/README.md | 387 ++++ .../charts/common/templates/_affinities.tpl | 169 ++ .../charts/common/templates/_capabilities.tpl | 178 ++ .../common/templates/_compatibility.tpl | 46 + .../keydb/charts/common/templates/_errors.tpl | 92 + .../keydb/charts/common/templates/_images.tpl | 115 ++ .../charts/common/templates/_ingress.tpl | 41 + .../keydb/charts/common/templates/_labels.tpl | 46 + .../keydb/charts/common/templates/_names.tpl | 72 + .../charts/common/templates/_resources.tpl | 50 + .../charts/common/templates/_secrets.tpl | 192 ++ .../charts/common/templates/_storage.tpl | 21 + .../charts/common/templates/_tplvalues.tpl | 52 + .../keydb/charts/common/templates/_utils.tpl | 77 + .../charts/common/templates/_warnings.tpl | 109 + .../templates/validations/_cassandra.tpl | 51 + .../common/templates/validations/_mariadb.tpl | 108 + .../common/templates/validations/_mongodb.tpl | 67 + .../common/templates/validations/_mysql.tpl | 67 + .../templates/validations/_postgresql.tpl | 105 + .../common/templates/validations/_redis.tpl | 48 + .../templates/validations/_validations.tpl | 51 + helm-charts/keydb/charts/common/values.yaml | 8 + helm-charts/keydb/templates/NOTES.txt | 168 ++ helm-charts/keydb/templates/_helpers.tpl | 222 +- helm-charts/keydb/templates/ca-cert.yaml | 53 + helm-charts/keydb/templates/cm-health.yaml | 80 - helm-charts/keydb/templates/extra-list.yaml | 9 + .../keydb/templates/health-configmap.yaml | 156 ++ helm-charts/keydb/templates/master/cert.yaml | 44 + .../keydb/templates/master/configmap.yaml | 54 + .../templates/master/headless-service.yaml | 28 + .../keydb/templates/master/networkpolicy.yaml | 79 + helm-charts/keydb/templates/master/pdb.yaml | 30 + .../keydb/templates/master/service.yaml | 53 + .../keydb/templates/master/statefulset.yaml | 436 ++++ helm-charts/keydb/templates/master/vpa.yaml | 45 + helm-charts/keydb/templates/metrics-svc.yaml | 28 + helm-charts/keydb/templates/pdb.yaml | 18 - .../keydb/templates/prometheusrule.yaml | 24 + helm-charts/keydb/templates/replica/cert.yaml | 44 + .../keydb/templates/replica/configmap.yaml | 63 + .../templates/replica/headless-service.yaml | 30 + helm-charts/keydb/templates/replica/hpa.yaml | 42 + .../templates/replica/networkpolicy.yaml | 88 + helm-charts/keydb/templates/replica/pdb.yaml | 30 + .../keydb/templates/replica/service.yaml | 55 + .../keydb/templates/replica/statefulset.yaml | 459 +++++ helm-charts/keydb/templates/replica/vpa.yaml | 45 + helm-charts/keydb/templates/sa.yaml | 11 - helm-charts/keydb/templates/secret-utils.yaml | 46 - helm-charts/keydb/templates/secret.yaml | 20 + .../keydb/templates/service-account.yaml | 19 + .../keydb/templates/servicemonitor.yaml | 50 + helm-charts/keydb/templates/sm.yaml | 31 - helm-charts/keydb/templates/sts.yaml | 311 --- helm-charts/keydb/templates/svc-headless.yaml | 22 - helm-charts/keydb/templates/svc-lb.yaml | 26 - helm-charts/keydb/templates/svc.yaml | 28 - helm-charts/keydb/templates/tls-secret.yaml | 91 + helm-charts/keydb/values.yaml | 1760 +++++++++++++--- 68 files changed, 8374 insertions(+), 1302 deletions(-) create mode 100644 helm-charts/keydb/Chart.lock create mode 100644 helm-charts/keydb/charts/common/.helmignore create mode 100644 helm-charts/keydb/charts/common/Chart.yaml create mode 100644 helm-charts/keydb/charts/common/README.md create mode 100644 helm-charts/keydb/charts/common/templates/_affinities.tpl create mode 100644 helm-charts/keydb/charts/common/templates/_capabilities.tpl create mode 100644 helm-charts/keydb/charts/common/templates/_compatibility.tpl create mode 100644 helm-charts/keydb/charts/common/templates/_errors.tpl create mode 100644 helm-charts/keydb/charts/common/templates/_images.tpl create mode 100644 helm-charts/keydb/charts/common/templates/_ingress.tpl create mode 100644 helm-charts/keydb/charts/common/templates/_labels.tpl create mode 100644 helm-charts/keydb/charts/common/templates/_names.tpl create mode 100644 helm-charts/keydb/charts/common/templates/_resources.tpl create mode 100644 helm-charts/keydb/charts/common/templates/_secrets.tpl create mode 100644 helm-charts/keydb/charts/common/templates/_storage.tpl create mode 100644 helm-charts/keydb/charts/common/templates/_tplvalues.tpl create mode 100644 helm-charts/keydb/charts/common/templates/_utils.tpl create mode 100644 helm-charts/keydb/charts/common/templates/_warnings.tpl create mode 100644 helm-charts/keydb/charts/common/templates/validations/_cassandra.tpl create mode 100644 helm-charts/keydb/charts/common/templates/validations/_mariadb.tpl create mode 100644 helm-charts/keydb/charts/common/templates/validations/_mongodb.tpl create mode 100644 helm-charts/keydb/charts/common/templates/validations/_mysql.tpl create mode 100644 helm-charts/keydb/charts/common/templates/validations/_postgresql.tpl create mode 100644 helm-charts/keydb/charts/common/templates/validations/_redis.tpl create mode 100644 helm-charts/keydb/charts/common/templates/validations/_validations.tpl create mode 100644 helm-charts/keydb/charts/common/values.yaml create mode 100644 helm-charts/keydb/templates/NOTES.txt create mode 100644 helm-charts/keydb/templates/ca-cert.yaml delete mode 100644 helm-charts/keydb/templates/cm-health.yaml create mode 100644 helm-charts/keydb/templates/extra-list.yaml create mode 100644 helm-charts/keydb/templates/health-configmap.yaml create mode 100644 helm-charts/keydb/templates/master/cert.yaml create mode 100644 helm-charts/keydb/templates/master/configmap.yaml create mode 100644 helm-charts/keydb/templates/master/headless-service.yaml create mode 100644 helm-charts/keydb/templates/master/networkpolicy.yaml create mode 100644 helm-charts/keydb/templates/master/pdb.yaml create mode 100644 helm-charts/keydb/templates/master/service.yaml create mode 100644 helm-charts/keydb/templates/master/statefulset.yaml create mode 100644 helm-charts/keydb/templates/master/vpa.yaml create mode 100644 helm-charts/keydb/templates/metrics-svc.yaml delete mode 100644 helm-charts/keydb/templates/pdb.yaml create mode 100644 helm-charts/keydb/templates/prometheusrule.yaml create mode 100644 helm-charts/keydb/templates/replica/cert.yaml create mode 100644 helm-charts/keydb/templates/replica/configmap.yaml create mode 100644 helm-charts/keydb/templates/replica/headless-service.yaml create mode 100644 helm-charts/keydb/templates/replica/hpa.yaml create mode 100644 helm-charts/keydb/templates/replica/networkpolicy.yaml create mode 100644 helm-charts/keydb/templates/replica/pdb.yaml create mode 100644 helm-charts/keydb/templates/replica/service.yaml create mode 100644 helm-charts/keydb/templates/replica/statefulset.yaml create mode 100644 helm-charts/keydb/templates/replica/vpa.yaml delete mode 100644 helm-charts/keydb/templates/sa.yaml delete mode 100644 helm-charts/keydb/templates/secret-utils.yaml create mode 100644 helm-charts/keydb/templates/secret.yaml create mode 100644 helm-charts/keydb/templates/service-account.yaml create mode 100644 helm-charts/keydb/templates/servicemonitor.yaml delete mode 100644 helm-charts/keydb/templates/sm.yaml delete mode 100644 helm-charts/keydb/templates/sts.yaml delete mode 100644 helm-charts/keydb/templates/svc-headless.yaml delete mode 100644 helm-charts/keydb/templates/svc-lb.yaml delete mode 100644 helm-charts/keydb/templates/svc.yaml create mode 100644 helm-charts/keydb/templates/tls-secret.yaml diff --git a/examples/keydb/values.yaml b/examples/keydb/values.yaml index dd7b5a6..6e9824e 100644 --- a/examples/keydb/values.yaml +++ b/examples/keydb/values.yaml @@ -1,279 +1,1529 @@ -nameOverride: "" -fullnameOverride: "" - -imageRepository: eqalpha/keydb -imageTag: x86_64_v6.3.2 -imagePullPolicy: IfNotPresent -imagePullSecrets: [] - -nodes: 3 - -password: "" -existingSecret: "" -existingSecretPasswordKey: "password" -port: 6379 -portName: server -internalPort: 6379 -internalPortName: keydb - -threads: 2 - -multiMaster: "yes" -activeReplicas: "yes" -protectedMode: "no" -appendonly: "no" - -annotations: {} - -configExtraArgs: [] - # - somesimple: "argument" - # - client-output-buffer-limit: ["normal", "0", "0", "0"] - # - client-output-buffer-limit: ["replica", "268435456", "67108864", "60"] - # - client-output-buffer-limit: ["pubsub", "33554432", "8388608", "60"] - -podAnnotations: {} - -tolerations: {} - # - effect: NoSchedule - # key: key - # operator: Equal - # value: value - -nodeSelector: {} - # topology.kubernetes.io/region: some-region - -topologySpreadConstraints: [] -# - maxSkew: 1 -# ## Optional keys -# # whenUnsatisfiable: DoNotSchedule -# # topologyKey: "topology.kubernetes.io/zone" -# # minDomains: 1 -# # nodeAffinityPolicy: Honor -# # nodeTaintsPolicy: Honor - -affinity: - podAntiAffinity: - preferredDuringSchedulingIgnoredDuringExecution: - - weight: 100 - podAffinityTerm: - labelSelector: - matchExpressions: - - key: app.kubernetes.io/name - operator: In - values: - - '{{ include "keydb.name" . }}' - - key: app.kubernetes.io/instance - operator: In - values: - - '{{ .Release.Name }}' - topologyKey: "kubernetes.io/hostname" - -additionalAffinities: {} - # nodeAffinity: - # requiredDuringSchedulingIgnoredDuringExecution: - # nodeSelectorTerms: - # - matchExpressions: - # - key: node_pool - # operator: In - # values: somenodepool - -podDisruptionBudget: - enabled: true - maxUnavailable: 1 - -# Additional init containers -extraInitContainers: [] - -# Additional sidecar containers -extraContainers: [] -# - name: backup -# image: minio/mc:latest - -# Volumes that can be used in init and sidecar containers -extraVolumes: [] -# - name: volume-from-secret -# secret: -# secretName: secret-to-mount -# - name: empty-dir-volume -# emptyDir: {} - -# Liveness Probe -livenessProbe: - enabled: true - custom: {} - # tcpSocket: - # port: keydb - # initialDelaySeconds: 30 - initialDelaySeconds: 20 - periodSeconds: 5 - timeoutSeconds: 5 - successThreshold: 1 - failureThreshold: 5 - -# Readiness Probe -readinessProbe: - enabled: true - custom: {} - # tcpSocket: - # port: keydb - # initialDelaySeconds: 30 - initialDelaySeconds: 20 - periodSeconds: 5 - timeoutSeconds: 1 - successThreshold: 1 - failureThreshold: 5 - -# Random UUID for readiness GET probe -readinessProbeRandomUuid: "90f717dd-0e68-43b8-9363-fddaad00d6c9" - -# Startup Probe -startupProbe: - enabled: true - custom: {} - # tcpSocket: - # port: keydb - periodSeconds: 5 - timeoutSeconds: 1 - failureThreshold: 24 - -# Lifecycle Hooks -lifecycle: {} - # preStop: - # exec: - # command: - # - sh - # - -c - # - "sleep 15; kill 1" - -persistentVolume: - enabled: true - accessModes: - - ReadWriteOnce - selector: {} - # matchLabels: - # release: "stable" - # matchExpressions: - # - {key: environment, operator: In, values: [dev]} - size: 1Gi - - ## If defined, storageClassName: - ## If set to "-", storageClassName: "", which disables dynamic provisioning - ## If undefined (the default) or set to null, no storageClassName spec is - ## set, choosing the default provisioner. (gp2 on AWS, standard on - ## GKE, AWS & OpenStack) - ## - # storageClass: "-" - - # If persistentVolume is disable, use this to configure the empty dir - emptyDir: {} - -resources: {} - -# Please read https://kubernetes.io/docs/tasks/administer-cluster/sysctl-cluster/#enabling-unsafe-sysctls -# before sysctls setup -securityContext: {} - # sysctls: - # - name: net.core.somaxconn - # value: "512" - # - name: vm.overcommit_memory - # value: "1" - -keydb: - # Container security context - securityContext: {} - -service: - annotations: {} - appProtocol: - enabled: false - -serviceAccount: - enabled: false - create: true - name: "" - - # extraSpec: - # automountServiceAccountToken: false - # imagePullSecrets: - # - name: pull-secret - extraSpec: {} - -loadBalancer: - enabled: false - - # annotations: - # service.beta.kubernetes.io/aws-load-balancer-type: nlb - annotations: {} - - # extraSpec: - # loadBalancerIP: "1.2.3.4" - # loadBalancerSourceRanges: - # - 1.2.3.4/32 - extraSpec: {} - -# Prometheus-operator ServiceMonitor -serviceMonitor: - # Redis exporter must also be enabled - enabled: false - labels: - annotations: - interval: 30s - # scrapeTimeout: 20s - -# Redis exporter -exporter: - enabled: false - imageRepository: oliver006/redis_exporter - imageTag: v1.48.0-alpine - pullPolicy: IfNotPresent - - # Prometheus port & scrape path - port: 9121 - portName: redis-exporter - scrapePath: /metrics - - # Liveness Probe - livenessProbe: - httpGet: - path: /health - port: redis-exporter - - # Readiness Probe - readinessProbe: - httpGet: - path: /health - port: redis-exporter - - # Startup Probe - startupProbe: - httpGet: - path: /health - port: redis-exporter - failureThreshold: 24 - periodSeconds: 5 - - # CPU/Memory resource limits/requests - resources: {} - - # Container security context - securityContext: {} - - # Additional args for redis exporter - extraArgs: [] - # - somesimple: "argument" - # - client-output-buffer-limit: ["normal", "0", "0", "0"] - # - client-output-buffer-limit: ["replica", "268435456", "67108864", "60"] - # - client-output-buffer-limit: ["pubsub", "33554432", "8388608", "60"] - -scripts: - enabled: false - # CPU/Memory resource limits/requests - resources: {} - # Container security context - securityContext: {} - cleanupCoredumps: - enabled: false - minutes: 1440 - cleanupTempfiles: - enabled: true - minutes: 60 +# Copyright Broadcom, Inc. All Rights Reserved. +# SPDX-License-Identifier: APACHE-2.0 + +## @section Global parameters +## Global Docker image parameters +## Please, note that this will override the image parameters, including dependencies, configured to use the global value +## Current available global Docker image parameters: imageRegistry, imagePullSecrets and storageClass +## + +## @param global.imageRegistry Global Docker image registry +## @param global.imagePullSecrets Global Docker registry secret names as an array +## @param global.defaultStorageClass Global default StorageClass for Persistent Volume(s) +## @param global.keydb.password Global KeyDB password (overrides `auth.password`) +## +global: + imageRegistry: "" + ## e.g: + ## imagePullSecrets: + ## - myRegistryKeySecretName + ## + imagePullSecrets: [] + defaultStorageClass: "" + keydb: + password: "" + ## Security parameters + ## + security: + ## @param global.security.allowInsecureImages Allows skipping image verification + allowInsecureImages: false + ## Compatibility adaptations for Kubernetes platforms + ## + compatibility: + ## Compatibility adaptations for Openshift + ## + openshift: + ## @param global.compatibility.openshift.adaptSecurityContext Adapt the securityContext sections of the deployment to make them compatible with Openshift restricted-v2 SCC: remove runAsUser, runAsGroup and fsGroup and let the platform use their allowed default IDs. Possible values: auto (apply if the detected running cluster is Openshift), force (perform the adaptation always), disabled (do not perform adaptation) + ## + adaptSecurityContext: auto + +## @section Common parameters +## + +## @param kubeVersion Override Kubernetes version +## +kubeVersion: "" +## @param apiVersions Override Kubernetes API versions reported by .Capabilities +## +apiVersions: [] +## @param nameOverride String to partially override common.names.name +## +nameOverride: "" +## @param fullnameOverride String to fully override common.names.fullname +## +fullnameOverride: "" +## @param namespaceOverride String to fully override common.names.namespace +## +namespaceOverride: "" +## @param commonLabels Labels to add to all deployed objects +## +commonLabels: {} +## @param commonAnnotations Annotations to add to all deployed objects +## +commonAnnotations: {} +## @param clusterDomain Kubernetes cluster domain name +## +clusterDomain: cluster.local +## @param extraDeploy Array of extra objects to deploy with the release +## +extraDeploy: [] +## Diagnostic mode +## @param diagnosticMode.enabled Enable diagnostic mode (all probes will be disabled and the command will be overridden) +## @param diagnosticMode.command Command to override all containers in the chart release +## @param diagnosticMode.args Args to override all containers in the chart release +## +diagnosticMode: + enabled: false + command: + - sleep + args: + - infinity + +## @section KeyDB Image parameters +## ref: https://hub.docker.com/r/bitnami/keydb/tags/ +## @param image.registry [default: REGISTRY_NAME] KeyDB image registry +## @param image.repository [default: REPOSITORY_NAME/keydb] KeyDB image repository +## @skip image.tag KeyDB image tag (immutable tags are recommended) +## @param image.digest KeyDB image digest in the way sha256:aa.... Please note this parameter, if set, will override the tag image tag (immutable tags are recommended) +## @param image.pullPolicy KeyDB image pull policy +## @param image.pullSecrets KeyDB image pull secrets +## @param image.debug Enable KeyDB image debug mode +## +image: + registry: docker.io + repository: bitnamilegacy/keydb + tag: latest + digest: "" + ## Specify a imagePullPolicy + ## ref: https://kubernetes.io/docs/concepts/containers/images/#pre-pulled-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/ + ## e.g: + ## pullSecrets: + ## - myRegistryKeySecretName + ## + pullSecrets: [] + debug: false + +## @section KeyDB common configuration parameters +## https://github.com/bitnami/containers/tree/main/bitnami/keydb#configuration +## + +## @param architecture KeyDB architecture. Allowed values: `standalone` or `replication` +## ref: https://docs.keydb.dev/docs/replication +## ref: https://docs.keydb.dev/docs/active-rep +## ref: https://docs.keydb.dev/docs/multi-master +## +architecture: replication +## KeyDB Authentication parameters +## ref: https://github.com/bitnami/containers/tree/main/bitnami/keydb#setting-the-server-password-on-first-run +## +auth: + ## @param auth.enabled Enable password authentication + ## + enabled: true + ## @param auth.password KeyDB password + ## Defaults to a random 10-character alphanumeric string if not set + ## + password: "" + ## @param auth.existingSecret The name of an existing secret with KeyDB credentials + ## NOTE: When it's set, the previous `auth.password` parameter is ignored + ## + existingSecret: "keydb-auth" + ## @param auth.existingSecretPasswordKey Password key to be retrieved from existing secret + ## NOTE: ignored unless `auth.existingSecret` parameter is set + ## + existingSecretPasswordKey: "password" + ## @param auth.usePasswordFiles Mount credentials as files instead of using an environment variable + ## + usePasswordFiles: true +## TLS configuration +## +tls: + ## @param tls.enabled Enable TLS communications + ## + enabled: false + ## @param tls.autoGenerated.enabled Enable automatic generation of certificates for TLS + ## @param tls.autoGenerated.engine Mechanism to generate the certificates (allowed values: helm, cert-manager) + autoGenerated: + enabled: true + engine: helm + ## @param tls.autoGenerated.certManager.existingIssuer The name of an existing Issuer to use for generating the certificates (only for `cert-manager` engine) + ## @param tls.autoGenerated.certManager.existingIssuerKind Existing Issuer kind, defaults to Issuer (only for `cert-manager` engine) + ## @param tls.autoGenerated.certManager.keyAlgorithm Key algorithm for the certificates (only for `cert-manager` engine) + ## @param tls.autoGenerated.certManager.keySize Key size for the certificates (only for `cert-manager` engine) + ## @param tls.autoGenerated.certManager.duration Duration for the certificates (only for `cert-manager` engine) + ## @param tls.autoGenerated.certManager.renewBefore Renewal period for the certificates (only for `cert-manager` engine) + certManager: + existingIssuer: "" + existingIssuerKind: "" + keySize: 2048 + keyAlgorithm: RSA + duration: 2160h + renewBefore: 360h + ## @param tls.ca CA certificate for TLS. Ignored if `tls.existingCASecret` is set + ## @param tls.existingCASecret The name of an existing Secret containing the CA certificate for TLS + ## @param tls.master.cert TLS certificate for KeyDB master nodes. Ignored if `tls.master.existingSecret` is set + ## @param tls.master.key TLS key for KeyDB master nodes. Ignored if `tls.master.existingSecret` is set + ## @param tls.master.existingSecret The name of an existing Secret containing the KeyDB master nodes certificates for TLS + ## @param tls.replica.cert TLS certificate for KeyDB replica nodes. Ignored if `tls.replica.existingSecret` is set + ## @param tls.replica.key TLS key for KeyDB replica nodes. Ignored if `tls.replica.existingSecret` is set + ## @param tls.replica.existingSecret The name of an existing Secret containing the KeyDB replica nodes certificates for TLS + ## + ca: "" + existingCASecret: "" + master: + cert: "" + key: "" + existingSecret: "" + replica: + cert: "" + key: "" + existingSecret: "" +## @param commonConfiguration [string] Common configuration to be added to both master and replica nodes +## ref: https://docs.keydb.dev/docs/config-file +## +commonConfiguration: "" + +## @section KeyDB Master Configuration Parameters +## +master: + ## @param master.replicaCount Number of KeyDB master replicas to deploy + ## + replicaCount: 1 + ## @param master.containerPorts.keydb Container port to open on KeyDB master nodes + ## + containerPorts: + keydb: 6379 + ## @param master.extraContainerPorts Optionally specify extra list of additional ports for KeyDB master containers + ## e.g: + ## extraContainerPorts: + ## - name: myservice + ## containerPort: 9090 + ## + extraContainerPorts: [] + ## Configure extra options for KeyDB master containers' liveness and readiness probes + ## ref: https://kubernetes.io/docs/tasks/configure-pod-container/configure-liveness-readiness-probes/#configure-probes + ## @param master.livenessProbe.enabled Enable livenessProbe on KeyDB master containers + ## @param master.livenessProbe.initialDelaySeconds Initial delay seconds for livenessProbe + ## @param master.livenessProbe.periodSeconds Period seconds for livenessProbe + ## @param master.livenessProbe.timeoutSeconds Timeout seconds for livenessProbe + ## @param master.livenessProbe.failureThreshold Failure threshold for livenessProbe + ## @param master.livenessProbe.successThreshold Success threshold for livenessProbe + ## + livenessProbe: + enabled: true + initialDelaySeconds: 20 + periodSeconds: 5 + timeoutSeconds: 5 + successThreshold: 1 + failureThreshold: 5 + ## @param master.readinessProbe.enabled Enable readinessProbe on KeyDB master containers + ## @param master.readinessProbe.initialDelaySeconds Initial delay seconds for readinessProbe + ## @param master.readinessProbe.periodSeconds Period seconds for readinessProbe + ## @param master.readinessProbe.timeoutSeconds Timeout seconds for readinessProbe + ## @param master.readinessProbe.failureThreshold Failure threshold for readinessProbe + ## @param master.readinessProbe.successThreshold Success threshold for readinessProbe + ## + readinessProbe: + enabled: true + initialDelaySeconds: 20 + periodSeconds: 5 + timeoutSeconds: 1 + successThreshold: 1 + failureThreshold: 5 + ## @param master.startupProbe.enabled Enable startupProbe on KeyDB master containers + ## @param master.startupProbe.initialDelaySeconds Initial delay seconds for startupProbe + ## @param master.startupProbe.periodSeconds Period seconds for startupProbe + ## @param master.startupProbe.timeoutSeconds Timeout seconds for startupProbe + ## @param master.startupProbe.failureThreshold Failure threshold for startupProbe + ## @param master.startupProbe.successThreshold Success threshold for startupProbe + ## + startupProbe: + enabled: false + initialDelaySeconds: 20 + periodSeconds: 5 + timeoutSeconds: 5 + successThreshold: 1 + failureThreshold: 5 + ## @param master.customLivenessProbe Custom livenessProbe that overrides the default one + ## + customLivenessProbe: {} + ## @param master.customReadinessProbe Custom readinessProbe that overrides the default one + ## + customReadinessProbe: {} + ## @param master.customStartupProbe Custom startupProbe that overrides the default one + ## + customStartupProbe: {} + ## KeyDB master resource requests and limits + ## ref: http://kubernetes.io/docs/concepts/configuration/manage-compute-resources-container/ + ## @param master.resourcesPreset Set KeyDB master container resources according to one common preset (allowed values: none, nano, small, medium, large, xlarge, 2xlarge). This is ignored if resources is set (resources is recommended for production). + ## More information: https://github.com/bitnami/charts/blob/main/bitnami/common/templates/_resources.tpl#L15 + ## + resourcesPreset: "nano" + ## @param master.resources Set KeyDB master container requests and limits for different resources like CPU or memory (essential for production workloads) + ## Example: + ## resources: + ## requests: + ## cpu: 2 + ## memory: 512Mi + ## limits: + ## cpu: 3 + ## memory: 1024Mi + ## + resources: {} + ## Configure Pods Security Context + ## ref: https://kubernetes.io/docs/tasks/configure-pod-container/security-context/#set-the-security-context-for-a-pod + ## @param master.podSecurityContext.enabled Enable KeyDB master pods' Security Context + ## @param master.podSecurityContext.fsGroupChangePolicy Set filesystem group change policy for KeyDB master pods + ## @param master.podSecurityContext.sysctls Set kernel settings using the sysctl interface for KeyDB master pods + ## @param master.podSecurityContext.supplementalGroups Set filesystem extra groups for KeyDB master pods + ## @param master.podSecurityContext.fsGroup Set fsGroup in KeyDB master pods' Security Context + ## + podSecurityContext: + enabled: true + fsGroupChangePolicy: Always + sysctls: [] + supplementalGroups: [] + fsGroup: 1001 + ## Configure Container Security Context + ## ref: https://kubernetes.io/docs/tasks/configure-pod-container/security-context/#set-the-security-context-for-a-container + ## @param master.containerSecurityContext.enabled Enabled KeyDB master container' Security Context + ## @param master.containerSecurityContext.seLinuxOptions [object,nullable] Set SELinux options in KeyDB master container + ## @param master.containerSecurityContext.runAsUser Set runAsUser in KeyDB master container' Security Context + ## @param master.containerSecurityContext.runAsGroup Set runAsGroup in KeyDB master container' Security Context + ## @param master.containerSecurityContext.runAsNonRoot Set runAsNonRoot in KeyDB master container' Security Context + ## @param master.containerSecurityContext.readOnlyRootFilesystem Set readOnlyRootFilesystem in KeyDB master container' Security Context + ## @param master.containerSecurityContext.privileged Set privileged in KeyDB master container' Security Context + ## @param master.containerSecurityContext.allowPrivilegeEscalation Set allowPrivilegeEscalation in KeyDB master container' Security Context + ## @param master.containerSecurityContext.capabilities.drop List of capabilities to be dropped in KeyDB master container + ## @param master.containerSecurityContext.seccompProfile.type Set seccomp profile in KeyDB master container + ## + containerSecurityContext: + enabled: true + seLinuxOptions: {} + runAsUser: 1001 + runAsGroup: 1001 + runAsNonRoot: true + readOnlyRootFilesystem: true + privileged: false + allowPrivilegeEscalation: false + capabilities: + drop: ["ALL"] + seccompProfile: + type: "RuntimeDefault" + ## @param master.configuration Exclusive configuration for KeyDB master nodes (appended to common one) + ## ref: https://docs.keydb.dev/docs/config-file + ## + configuration: "" + ## @param master.existingConfigmap The name of an existing ConfigMap with your custom configuration for KeyDB master + ## + existingConfigmap: "" + ## @param master.disableCommands Array with KeyDB commands to disable on master nodes + ## Commands will be completely disabled by renaming each to an empty string. + ## ref: https://docs.keydb.dev/docs/commands + ## + disableCommands: + - FLUSHDB + - FLUSHALL + ## @param master.command Override default KeyDB master container command (useful when using custom images) + ## + command: [] + ## @param master.args Override default KeyDB master container args (useful when using custom images) + ## + args: [] + ## @param master.automountServiceAccountToken Mount Service Account token in KeyDB master pods + ## + automountServiceAccountToken: false + ## @param master.hostAliases KeyDB master pods host aliases + ## https://kubernetes.io/docs/concepts/services-networking/add-entries-to-pod-etc-hosts-with-host-aliases/ + ## + hostAliases: [] + ## @param master.statefulsetAnnotations Annotations for KeyDB master statefulset + ## ref: https://kubernetes.io/docs/concepts/overview/working-with-objects/annotations/ + ## + statefulsetAnnotations: {} + ## @param master.podLabels Extra labels for KeyDB master pods + ## ref: https://kubernetes.io/docs/concepts/overview/working-with-objects/labels/ + ## + podLabels: {} + ## @param master.podAnnotations Annotations for KeyDB master pods + ## ref: https://kubernetes.io/docs/concepts/overview/working-with-objects/annotations/ + ## + podAnnotations: {} + ## @param master.podAffinityPreset Pod affinity preset. Ignored if `affinity` is set. Allowed values: `soft` or `hard` + ## ref: https://kubernetes.io/docs/concepts/scheduling-eviction/assign-pod-node/#inter-pod-affinity-and-anti-affinity + ## + podAffinityPreset: "" + ## @param master.podAntiAffinityPreset Pod anti-affinity preset. Ignored if `affinity` is set. Allowed values: `soft` or `hard` + ## ref: https://kubernetes.io/docs/concepts/scheduling-eviction/assign-pod-node/#inter-pod-affinity-and-anti-affinity + ## + podAntiAffinityPreset: soft + ## Node affinity preset + ## ref: https://kubernetes.io/docs/concepts/scheduling-eviction/assign-pod-node/#node-affinity + ## + nodeAffinityPreset: + ## @param master.nodeAffinityPreset.type Node affinity preset type. Ignored if `affinity` is set. Allowed values: `soft` or `hard` + ## + type: "" + ## @param master.nodeAffinityPreset.key Node label key to match. Ignored if `affinity` is set + ## + key: "" + ## @param master.nodeAffinityPreset.values Node label values to match. Ignored if `affinity` is set + ## E.g. + ## values: + ## - e2e-az1 + ## - e2e-az2 + ## + values: [] + ## @param master.affinity Affinity for KeyDB master pods assignment + ## 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 + ## + affinity: {} + ## @param master.nodeSelector Node labels for KeyDB master pods assignment + ## ref: https://kubernetes.io/docs/concepts/scheduling-eviction/assign-pod-node/ + ## + nodeSelector: {} + ## @param master.tolerations Tolerations for KeyDB master pods assignment + ## ref: https://kubernetes.io/docs/concepts/configuration/taint-and-toleration/ + ## + tolerations: [] + ## @param master.updateStrategy.type KeyDB master strategy type + ## ref: https://kubernetes.io/docs/concepts/workloads/controllers/deployment/#strategy + ## ref: https://kubernetes.io/docs/concepts/workloads/controllers/statefulset/#update-strategies + ## + updateStrategy: + ## Can be set to RollingUpdate or OnDelete + ## + type: RollingUpdate + ## @param master.priorityClassName KeyDB master pods' priorityClassName + ## + priorityClassName: "" + ## @param master.topologySpreadConstraints Topology Spread Constraints for KeyDB master pod assignment spread across your cluster among failure-domains + ## Ref: https://kubernetes.io/docs/concepts/workloads/pods/pod-topology-spread-constraints/#spread-constraints-for-pods + ## + topologySpreadConstraints: [] + ## @param master.schedulerName Name of the k8s scheduler (other than default) for KeyDB master pods + ## ref: https://kubernetes.io/docs/tasks/administer-cluster/configure-multiple-schedulers/ + ## + schedulerName: "" + ## @param master.terminationGracePeriodSeconds Seconds KeyDB master pods need to terminate gracefully + ## ref: https://kubernetes.io/docs/concepts/workloads/pods/pod/#termination-of-pods + ## + terminationGracePeriodSeconds: "" + ## @param master.lifecycleHooks for KeyDB master containers to automate configuration before or after startup + ## + lifecycleHooks: {} + ## @param master.extraEnvVars Array with extra environment variables to add to KeyDB master containers + ## e.g: + ## extraEnvVars: + ## - name: FOO + ## value: "bar" + ## + extraEnvVars: [] + ## @param master.extraEnvVarsCM Name of existing ConfigMap containing extra env vars for KeyDB master containers + ## + extraEnvVarsCM: "" + ## @param master.extraEnvVarsSecret Name of existing Secret containing extra env vars for KeyDB master containers + ## + extraEnvVarsSecret: "" + ## @param master.extraVolumes Optionally specify extra list of additional volumes for the KeyDB master pods + ## + extraVolumes: [] + ## @param master.extraVolumeMounts Optionally specify extra list of additional volumeMounts for the KeyDB master containers + ## + extraVolumeMounts: [] + ## @param master.sidecars Add additional sidecar containers to the KeyDB master pods + ## e.g: + ## sidecars: + ## - name: your-image-name + ## image: your-image + ## imagePullPolicy: Always + ## ports: + ## - name: portname + ## containerPort: 1234 + ## + sidecars: [] + ## @param master.initContainers Add additional init containers to the KeyDB master pods + ## ref: https://kubernetes.io/docs/concepts/workloads/pods/init-containers/ + ## e.g: + ## initContainers: + ## - name: your-image-name + ## image: your-image + ## imagePullPolicy: Always + ## command: ['sh', '-c', 'echo "hello world"'] + ## + initContainers: [] + ## Pod Disruption Budget configuration + ## ref: https://kubernetes.io/docs/tasks/run-application/configure-pdb + ## @param master.pdb.create Enable/disable a Pod Disruption Budget creation for KeyDB master pods + ## @param master.pdb.minAvailable Minimum number/percentage of KeyDB master pods that should remain scheduled + ## @param master.pdb.maxUnavailable Maximum number/percentage of KeyDB master pods that may be made unavailable. Defaults to `1` if both `pdb.minAvailable` and `pdb.maxUnavailable` are empty. + ## + pdb: + create: true + minAvailable: "" + maxUnavailable: "" + ## Autoscaling configuration + ## ref: https://kubernetes.io/docs/concepts/workloads/autoscaling/ + ## + autoscaling: + ## @param master.autoscaling.vpa.enabled Enable VPA for KeyDB master pods + ## @param master.autoscaling.vpa.annotations Annotations for VPA resource + ## @param master.autoscaling.vpa.controlledResources VPA List of resources that the vertical pod autoscaler can control. Defaults to cpu and memory + ## @param master.autoscaling.vpa.maxAllowed VPA Max allowed resources for the pod + ## @param master.autoscaling.vpa.minAllowed VPA Min allowed resources for the pod + ## + vpa: + enabled: false + annotations: {} + controlledResources: [] + maxAllowed: {} + minAllowed: {} + ## @param master.autoscaling.vpa.updatePolicy.updateMode Autoscaling update policy + ## Specifies whether recommended updates are applied when a Pod is started and whether recommended updates are applied during the life of a Pod + ## Possible values are "Off", "Initial", "Recreate", and "Auto". + ## + updatePolicy: + updateMode: Auto + ## @section KeyDB Master Persistence Parameters + ## ref: https://kubernetes.io/docs/concepts/storage/persistent-volumes + ## + persistence: + ## @param master.persistence.enabled Enable persistence using Persistent Volume Claims + ## + enabled: true + ## @param master.persistence.mountPath Path to mount the data volume at on KeyDB master containers + ## + mountPath: /bitnami/keydb/data + ## @param master.persistence.subPath The subdirectory of the volume to mount on KeyDB master containers + ## + subPath: "" + ## @param master.persistence.medium Provide a medium for `emptyDir` volumes + ## + medium: "" + ## @param master.persistence.sizeLimit Set this to enable a size limit for `emptyDir` volumes + ## + sizeLimit: "" + ## @param master.persistence.storageClass Storage class of backing PVC + ## If defined, storageClassName: + ## If set to "-", storageClassName: "", which disables dynamic provisioning + ## If undefined (the default) or set to null, no storageClassName spec is + ## set, choosing the default provisioner. (gp2 on AWS, standard on + ## GKE, AWS & OpenStack) + ## + storageClass: "" + ## @param master.persistence.annotations Additional Persistent Volume Claim annotations + ## + annotations: {} + ## @param master.persistence.accessModes Persistent Volume Access Modes + ## + accessModes: + - ReadWriteOnce + ## @param master.persistence.size Size of data volume + ## + size: 8Gi + ## @param master.persistence.selector Selector to match an existing Persistent Volume for WordPress data PVC + ## If set, the PVC can't have a PV dynamically provisioned for it + ## E.g. + ## selector: + ## matchLabels: + ## app: my-app + ## + selector: {} + ## @param master.persistence.dataSource Custom PVC data source + ## + dataSource: {} + ## @param master.persistence.existingClaim The name of an existing PVC to use for persistence (only if master.replicaCount=1) + ## + existingClaim: "" + ## persistentVolumeClaimRetentionPolicy + ## ref: https://kubernetes.io/docs/concepts/workloads/controllers/statefulset/#persistentvolumeclaim-retention + ## @param master.persistentVolumeClaimRetentionPolicy.enabled Controls if and how PVCs are deleted during the lifecycle of a StatefulSet + ## @param master.persistentVolumeClaimRetentionPolicy.whenScaled Volume retention behavior when the replica count of the StatefulSet is reduced + ## @param master.persistentVolumeClaimRetentionPolicy.whenDeleted Volume retention behavior that applies when the StatefulSet is deleted + ## + persistentVolumeClaimRetentionPolicy: + enabled: false + whenScaled: Retain + whenDeleted: Retain + ## @section KeyDB Master Traffic Exposure Parameters + ## KeyDB Master service parameters + ## + service: + ## @param master.service.type KeyDB master service type + ## + type: ClusterIP + ## @param master.service.ports.keydb KeyDB master service port + ## + ports: + keydb: 6379 + ## Node ports to expose + ## @param master.service.nodePorts.keydb Node port for KeyDB master + ## NOTE: choose port between <30000-32767> + ## + nodePorts: + keydb: "" + ## @param master.service.clusterIP KeyDB master service Cluster IP + ## e.g.: + ## clusterIP: None + ## + clusterIP: "" + ## @param master.service.loadBalancerIP KeyDB master service Load Balancer IP + ## ref: https://kubernetes.io/docs/concepts/services-networking/service/#type-loadbalancer + ## + loadBalancerIP: "" + ## @param master.service.loadBalancerSourceRanges KeyDB master service Load Balancer sources + ## ref: https://kubernetes.io/docs/tasks/access-application-cluster/configure-cloud-provider-firewall/#restrict-access-for-loadbalancer-service + ## e.g: + ## loadBalancerSourceRanges: + ## - 10.10.10.0/24 + ## + loadBalancerSourceRanges: [] + ## @param master.service.externalTrafficPolicy KeyDB master service external traffic policy + ## ref http://kubernetes.io/docs/tasks/access-application-cluster/create-external-load-balancer/#preserving-the-client-source-ip + ## + externalTrafficPolicy: Cluster + ## @param master.service.annotations Additional custom annotations for KeyDB master service + ## + annotations: {} + ## @param master.service.extraPorts Extra ports to expose in KeyDB master service (normally used with the `sidecars` value) + ## + extraPorts: [] + ## @param master.service.sessionAffinity Control where client requests go, to the same pod or round-robin + ## Values: ClientIP or None + ## ref: https://kubernetes.io/docs/concepts/services-networking/service/ + ## + sessionAffinity: None + ## @param master.service.sessionAffinityConfig Additional settings for the sessionAffinity + ## sessionAffinityConfig: + ## clientIP: + ## timeoutSeconds: 300 + ## + sessionAffinityConfig: {} + ## Headless service properties + ## + headless: + ## @param master.service.headless.annotations Annotations for the headless service. + ## + annotations: {} + ## KeyDB Master Network Policies + ## Ref: https://kubernetes.io/docs/concepts/services-networking/network-policies/ + ## + networkPolicy: + ## @param master.networkPolicy.enabled Specifies whether a NetworkPolicy should be created for KeyDB master + ## + enabled: true + ## @param master.networkPolicy.allowExternal Don't require server label for connections + ## The Policy model to apply. When set to false, only pods with the correct + ## server label will have network access to the ports server is listening + ## on. When true, server will accept connections from any source + ## (with the correct destination port). + ## + allowExternal: true + ## @param master.networkPolicy.allowExternalEgress Allow the pod to access any range of port and all destinations. + ## + allowExternalEgress: true + ## @param master.networkPolicy.addExternalClientAccess Allow access from pods with client label set to "true". Ignored if `networkPolicy.allowExternal` is true. + ## + addExternalClientAccess: true + ## @param master.networkPolicy.extraIngress [array] Add extra ingress rules to the NetworkPolicy + ## e.g: + ## extraIngress: + ## - ports: + ## - port: 1234 + ## from: + ## - podSelector: + ## - matchLabels: + ## - role: frontend + ## - podSelector: + ## - matchExpressions: + ## - key: role + ## operator: In + ## values: + ## - frontend + extraIngress: [] + ## @param master.networkPolicy.extraEgress [array] Add extra ingress rules to the NetworkPolicy (ignored if allowExternalEgress=true) + ## e.g: + ## extraEgress: + ## - ports: + ## - port: 1234 + ## to: + ## - podSelector: + ## - matchLabels: + ## - role: frontend + ## - podSelector: + ## - matchExpressions: + ## - key: role + ## operator: In + ## values: + ## - frontend + ## + extraEgress: [] + ## @param master.networkPolicy.ingressPodMatchLabels [object] Labels to match to allow traffic from other pods. Ignored if `networkPolicy.allowExternal` is true. + ## e.g: + ## ingressPodMatchLabels: + ## my-client: "true" + # + ingressPodMatchLabels: {} + ## @param master.networkPolicy.ingressNSMatchLabels [object] Labels to match to allow traffic from other namespaces. Ignored if `networkPolicy.allowExternal` is true. + ## @param master.networkPolicy.ingressNSPodMatchLabels [object] Pod labels to match to allow traffic from other namespaces. Ignored if `networkPolicy.allowExternal` is true. + ## + ingressNSMatchLabels: {} + ingressNSPodMatchLabels: {} + +## @section KeyDB Replicas Configuration Parameters +## +replica: + ## @param replica.replicaCount Number of KeyDB replicas to deploy + ## + replicaCount: 1 + ## @param replica.containerPorts.keydb Container port to open on KeyDB replicas nodes + ## + containerPorts: + keydb: 6379 + ## @param replica.extraContainerPorts Optionally specify extra list of additional ports for KeyDB replicas containers + ## e.g: + ## extraContainerPorts: + ## - name: myservice + ## containerPort: 9090 + ## + extraContainerPorts: [] + ## Configure extra options for KeyDB replicas containers' liveness and readiness probes + ## ref: https://kubernetes.io/docs/tasks/configure-pod-container/configure-liveness-readiness-probes/#configure-probes + ## @param replica.livenessProbe.enabled Enable livenessProbe on KeyDB replicas containers + ## @param replica.livenessProbe.initialDelaySeconds Initial delay seconds for livenessProbe + ## @param replica.livenessProbe.periodSeconds Period seconds for livenessProbe + ## @param replica.livenessProbe.timeoutSeconds Timeout seconds for livenessProbe + ## @param replica.livenessProbe.failureThreshold Failure threshold for livenessProbe + ## @param replica.livenessProbe.successThreshold Success threshold for livenessProbe + ## + livenessProbe: + enabled: true + initialDelaySeconds: 20 + periodSeconds: 5 + timeoutSeconds: 5 + successThreshold: 1 + failureThreshold: 5 + ## @param replica.readinessProbe.enabled Enable readinessProbe on KeyDB replicas containers + ## @param replica.readinessProbe.initialDelaySeconds Initial delay seconds for readinessProbe + ## @param replica.readinessProbe.periodSeconds Period seconds for readinessProbe + ## @param replica.readinessProbe.timeoutSeconds Timeout seconds for readinessProbe + ## @param replica.readinessProbe.failureThreshold Failure threshold for readinessProbe + ## @param replica.readinessProbe.successThreshold Success threshold for readinessProbe + ## + readinessProbe: + enabled: true + initialDelaySeconds: 20 + periodSeconds: 5 + timeoutSeconds: 1 + successThreshold: 1 + failureThreshold: 5 + ## @param replica.startupProbe.enabled Enable startupProbe on KeyDB replicas containers + ## @param replica.startupProbe.initialDelaySeconds Initial delay seconds for startupProbe + ## @param replica.startupProbe.periodSeconds Period seconds for startupProbe + ## @param replica.startupProbe.timeoutSeconds Timeout seconds for startupProbe + ## @param replica.startupProbe.failureThreshold Failure threshold for startupProbe + ## @param replica.startupProbe.successThreshold Success threshold for startupProbe + ## + startupProbe: + enabled: false + initialDelaySeconds: 20 + periodSeconds: 5 + timeoutSeconds: 5 + successThreshold: 1 + failureThreshold: 5 + ## @param replica.customLivenessProbe Custom livenessProbe that overrides the default one + ## + customLivenessProbe: {} + ## @param replica.customReadinessProbe Custom readinessProbe that overrides the default one + ## + customReadinessProbe: {} + ## @param replica.customStartupProbe Custom startupProbe that overrides the default one + ## + customStartupProbe: {} + ## KeyDB replicas resource requests and limits + ## ref: http://kubernetes.io/docs/concepts/configuration/manage-compute-resources-container/ + ## @param replica.resourcesPreset Set KeyDB replicas container resources according to one common preset (allowed values: none, nano, small, medium, large, xlarge, 2xlarge). This is ignored if resources is set (resources is recommended for production). + ## More information: https://github.com/bitnami/charts/blob/main/bitnami/common/templates/_resources.tpl#L15 + ## + resourcesPreset: "nano" + ## @param replica.resources Set KeyDB replicas container requests and limits for different resources like CPU or memory (essential for production workloads) + ## Example: + ## resources: + ## requests: + ## cpu: 2 + ## memory: 512Mi + ## limits: + ## cpu: 3 + ## memory: 1024Mi + ## + resources: {} + ## Configure Pods Security Context + ## ref: https://kubernetes.io/docs/tasks/configure-pod-container/security-context/#set-the-security-context-for-a-pod + ## @param replica.podSecurityContext.enabled Enable KeyDB replicas pods' Security Context + ## @param replica.podSecurityContext.fsGroupChangePolicy Set filesystem group change policy for KeyDB replicas pods + ## @param replica.podSecurityContext.sysctls Set kernel settings using the sysctl interface for KeyDB replicas pods + ## @param replica.podSecurityContext.supplementalGroups Set filesystem extra groups for KeyDB replicas pods + ## @param replica.podSecurityContext.fsGroup Set fsGroup in KeyDB replicas pods' Security Context + ## + podSecurityContext: + enabled: true + fsGroupChangePolicy: Always + sysctls: [] + supplementalGroups: [] + fsGroup: 1001 + ## Configure Container Security Context + ## ref: https://kubernetes.io/docs/tasks/configure-pod-container/security-context/#set-the-security-context-for-a-container + ## @param replica.containerSecurityContext.enabled Enabled KeyDB replicas container' Security Context + ## @param replica.containerSecurityContext.seLinuxOptions [object,nullable] Set SELinux options in KeyDB replicas container + ## @param replica.containerSecurityContext.runAsUser Set runAsUser in KeyDB replicas container' Security Context + ## @param replica.containerSecurityContext.runAsGroup Set runAsGroup in KeyDB replicas container' Security Context + ## @param replica.containerSecurityContext.runAsNonRoot Set runAsNonRoot in KeyDB replicas container' Security Context + ## @param replica.containerSecurityContext.readOnlyRootFilesystem Set readOnlyRootFilesystem in KeyDB replicas container' Security Context + ## @param replica.containerSecurityContext.privileged Set privileged in KeyDB replicas container' Security Context + ## @param replica.containerSecurityContext.allowPrivilegeEscalation Set allowPrivilegeEscalation in KeyDB replicas container' Security Context + ## @param replica.containerSecurityContext.capabilities.drop List of capabilities to be dropped in KeyDB replicas container + ## @param replica.containerSecurityContext.seccompProfile.type Set seccomp profile in KeyDB replicas container + ## + containerSecurityContext: + enabled: true + seLinuxOptions: {} + runAsUser: 1001 + runAsGroup: 1001 + runAsNonRoot: true + readOnlyRootFilesystem: true + privileged: false + allowPrivilegeEscalation: false + capabilities: + drop: ["ALL"] + seccompProfile: + type: "RuntimeDefault" + ## @param replica.activeReplica Configure replica as an active replica + ## + activeReplica: false + ## @param replica.configuration Exclusive configuration for KeyDB replicas nodes (appended to common one) + ## ref: https://docs.keydb.dev/docs/config-file + ## + configuration: "" + ## @param replica.existingConfigmap The name of an existing ConfigMap with your custom configuration for KeyDB replicas + ## + existingConfigmap: "" + ## @param replica.disableCommands Array with KeyDB commands to disable on master nodes + ## Commands will be completely disabled by renaming each to an empty string. + ## ref: https://docs.keydb.dev/docs/commands + ## + disableCommands: + - FLUSHDB + - FLUSHALL + ## @param replica.command Override default KeyDB replicas container command (useful when using custom images) + ## + command: [] + ## @param replica.args Override default KeyDB replicas container args (useful when using custom images) + ## + args: [] + ## @param replica.automountServiceAccountToken Mount Service Account token in KeyDB replicas pods + ## + automountServiceAccountToken: false + ## @param replica.hostAliases KeyDB replicas pods host aliases + ## https://kubernetes.io/docs/concepts/services-networking/add-entries-to-pod-etc-hosts-with-host-aliases/ + ## + hostAliases: [] + ## @param replica.statefulsetAnnotations Annotations for KeyDB replicas statefulset + ## ref: https://kubernetes.io/docs/concepts/overview/working-with-objects/annotations/ + ## + statefulsetAnnotations: {} + ## @param replica.podLabels Extra labels for KeyDB replicas pods + ## ref: https://kubernetes.io/docs/concepts/overview/working-with-objects/labels/ + ## + podLabels: {} + ## @param replica.podAnnotations Annotations for KeyDB replicas pods + ## ref: https://kubernetes.io/docs/concepts/overview/working-with-objects/annotations/ + ## + podAnnotations: {} + ## @param replica.podAffinityPreset Pod affinity preset. Ignored if `affinity` is set. Allowed values: `soft` or `hard` + ## ref: https://kubernetes.io/docs/concepts/scheduling-eviction/assign-pod-node/#inter-pod-affinity-and-anti-affinity + ## + podAffinityPreset: "" + ## @param replica.podAntiAffinityPreset Pod anti-affinity preset. Ignored if `affinity` is set. Allowed values: `soft` or `hard` + ## ref: https://kubernetes.io/docs/concepts/scheduling-eviction/assign-pod-node/#inter-pod-affinity-and-anti-affinity + ## + podAntiAffinityPreset: soft + ## Node affinity preset + ## ref: https://kubernetes.io/docs/concepts/scheduling-eviction/assign-pod-node/#node-affinity + ## + nodeAffinityPreset: + ## @param replica.nodeAffinityPreset.type Node affinity preset type. Ignored if `affinity` is set. Allowed values: `soft` or `hard` + ## + type: "" + ## @param replica.nodeAffinityPreset.key Node label key to match. Ignored if `affinity` is set + ## + key: "" + ## @param replica.nodeAffinityPreset.values Node label values to match. Ignored if `affinity` is set + ## E.g. + ## values: + ## - e2e-az1 + ## - e2e-az2 + ## + values: [] + ## @param replica.affinity Affinity for KeyDB replicas pods assignment + ## 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 + ## + affinity: {} + ## @param replica.nodeSelector Node labels for KeyDB replicas pods assignment + ## ref: https://kubernetes.io/docs/concepts/scheduling-eviction/assign-pod-node/ + ## + nodeSelector: {} + ## @param replica.tolerations Tolerations for KeyDB replicas pods assignment + ## ref: https://kubernetes.io/docs/concepts/configuration/taint-and-toleration/ + ## + tolerations: [] + ## @param replica.updateStrategy.type KeyDB replicas strategy type + ## ref: https://kubernetes.io/docs/concepts/workloads/controllers/deployment/#strategy + ## ref: https://kubernetes.io/docs/concepts/workloads/controllers/statefulset/#update-strategies + ## + updateStrategy: + ## Can be set to RollingUpdate or OnDelete + ## + type: RollingUpdate + ## @param replica.priorityClassName KeyDB replicas pods' priorityClassName + ## + priorityClassName: "" + ## @param replica.topologySpreadConstraints Topology Spread Constraints for KeyDB replicas pod assignment spread across your cluster among failure-domains + ## Ref: https://kubernetes.io/docs/concepts/workloads/pods/pod-topology-spread-constraints/#spread-constraints-for-pods + ## + topologySpreadConstraints: [] + ## @param replica.schedulerName Name of the k8s scheduler (other than default) for KeyDB replicas pods + ## ref: https://kubernetes.io/docs/tasks/administer-cluster/configure-multiple-schedulers/ + ## + schedulerName: "" + ## @param replica.terminationGracePeriodSeconds Seconds KeyDB replicas pods need to terminate gracefully + ## ref: https://kubernetes.io/docs/concepts/workloads/pods/pod/#termination-of-pods + ## + terminationGracePeriodSeconds: "" + ## @param replica.lifecycleHooks for KeyDB replicas containers to automate configuration before or after startup + ## + lifecycleHooks: {} + ## @param replica.extraEnvVars Array with extra environment variables to add to KeyDB replicas containers + ## e.g: + ## extraEnvVars: + ## - name: FOO + ## value: "bar" + ## + extraEnvVars: [] + ## @param replica.extraEnvVarsCM Name of existing ConfigMap containing extra env vars for KeyDB replicas containers + ## + extraEnvVarsCM: "" + ## @param replica.extraEnvVarsSecret Name of existing Secret containing extra env vars for KeyDB replicas containers + ## + extraEnvVarsSecret: "" + ## @param replica.extraVolumes Optionally specify extra list of additional volumes for the KeyDB replicas pods + ## + extraVolumes: [] + ## @param replica.extraVolumeMounts Optionally specify extra list of additional volumeMounts for the KeyDB replicas containers + ## + extraVolumeMounts: [] + ## @param replica.sidecars Add additional sidecar containers to the KeyDB replicas pods + ## e.g: + ## sidecars: + ## - name: your-image-name + ## image: your-image + ## imagePullPolicy: Always + ## ports: + ## - name: portname + ## containerPort: 1234 + ## + sidecars: [] + ## @param replica.initContainers Add additional init containers to the KeyDB replicas pods + ## ref: https://kubernetes.io/docs/concepts/workloads/pods/init-containers/ + ## e.g: + ## initContainers: + ## - name: your-image-name + ## image: your-image + ## imagePullPolicy: Always + ## command: ['sh', '-c', 'echo "hello world"'] + ## + initContainers: [] + ## Pod Disruption Budget configuration + ## ref: https://kubernetes.io/docs/tasks/run-application/configure-pdb + ## @param replica.pdb.create Enable/disable a Pod Disruption Budget creation for KeyDB replicas pods + ## @param replica.pdb.minAvailable Minimum number/percentage of KeyDB replicas pods that should remain scheduled + ## @param replica.pdb.maxUnavailable Maximum number/percentage of KeyDB replicas pods that may be made unavailable. Defaults to `1` if both `pdb.minAvailable` and `pdb.maxUnavailable` are empty. + ## + pdb: + create: true + minAvailable: "" + maxUnavailable: "" + ## Autoscaling configuration + ## ref: https://kubernetes.io/docs/concepts/workloads/autoscaling/ + ## + autoscaling: + ## @param replica.autoscaling.vpa.enabled Enable VPA for KeyDB replicas pods + ## @param replica.autoscaling.vpa.annotations Annotations for VPA resource + ## @param replica.autoscaling.vpa.controlledResources VPA List of resources that the vertical pod autoscaler can control. Defaults to cpu and memory + ## @param replica.autoscaling.vpa.maxAllowed VPA Max allowed resources for the pod + ## @param replica.autoscaling.vpa.minAllowed VPA Min allowed resources for the pod + ## + vpa: + enabled: false + annotations: {} + controlledResources: [] + maxAllowed: {} + minAllowed: {} + ## @param replica.autoscaling.vpa.updatePolicy.updateMode Autoscaling update policy + ## Specifies whether recommended updates are applied when a Pod is started and whether recommended updates are applied during the life of a Pod + ## Possible values are "Off", "Initial", "Recreate", and "Auto". + ## + updatePolicy: + updateMode: Auto + ## @param replica.autoscaling.hpa.enabled Enable HPA for KeyDB Replicas pods + ## @param replica.autoscaling.hpa.minReplicas Minimum number of replicas + ## @param replica.autoscaling.hpa.maxReplicas Maximum number of replicas + ## @param replica.autoscaling.hpa.targetCPU Target CPU utilization percentage + ## @param replica.autoscaling.hpa.targetMemory Target Memory utilization percentage + ## + hpa: + enabled: false + minReplicas: "" + maxReplicas: "" + targetCPU: "" + targetMemory: "" + ## @section KeyDB Replicas Persistence Parameters + ## ref: https://kubernetes.io/docs/concepts/storage/persistent-volumes + ## + persistence: + ## @param replica.persistence.enabled Enable persistence using Persistent Volume Claims + ## + enabled: true + ## @param replica.persistence.mountPath Path to mount the data volume at on KeyDB replicas containers + ## + mountPath: /bitnami/keydb/data + ## @param replica.persistence.subPath The subdirectory of the volume to mount on KeyDB replicas containers + ## + subPath: "" + ## @param replica.persistence.medium Provide a medium for `emptyDir` volumes + ## + medium: "" + ## @param replica.persistence.sizeLimit Set this to enable a size limit for `emptyDir` volumes + ## + sizeLimit: "" + ## @param replica.persistence.storageClass Storage class of backing PVC + ## If defined, storageClassName: + ## If set to "-", storageClassName: "", which disables dynamic provisioning + ## If undefined (the default) or set to null, no storageClassName spec is + ## set, choosing the default provisioner. (gp2 on AWS, standard on + ## GKE, AWS & OpenStack) + ## + storageClass: "" + ## @param replica.persistence.annotations Additional Persistent Volume Claim annotations + ## + annotations: {} + ## @param replica.persistence.accessModes Persistent Volume Access Modes + ## + accessModes: + - ReadWriteOnce + ## @param replica.persistence.size Size of data volume + ## + size: 8Gi + ## @param replica.persistence.selector Selector to match an existing Persistent Volume for WordPress data PVC + ## If set, the PVC can't have a PV dynamically provisioned for it + ## E.g. + ## selector: + ## matchLabels: + ## app: my-app + ## + selector: {} + ## @param replica.persistence.dataSource Custom PVC data source + ## + dataSource: {} + ## @param replica.persistence.existingClaim The name of an existing PVC to use for persistence (only if replica.replicaCount=1) + ## + existingClaim: "" + ## persistentVolumeClaimRetentionPolicy + ## ref: https://kubernetes.io/docs/concepts/workloads/controllers/statefulset/#persistentvolumeclaim-retention + ## @param replica.persistentVolumeClaimRetentionPolicy.enabled Controls if and how PVCs are deleted during the lifecycle of a StatefulSet + ## @param replica.persistentVolumeClaimRetentionPolicy.whenScaled Volume retention behavior when the replica count of the StatefulSet is reduced + ## @param replica.persistentVolumeClaimRetentionPolicy.whenDeleted Volume retention behavior that applies when the StatefulSet is deleted + ## + persistentVolumeClaimRetentionPolicy: + enabled: false + whenScaled: Retain + whenDeleted: Retain + ## @section KeyDB Replicas Traffic Exposure Parameters + ## KeyDB Replicas service parameters + ## + service: + ## @param replica.service.type KeyDB replicas service type + ## + type: ClusterIP + ## @param replica.service.ports.keydb KeyDB replicas service port + ## + ports: + keydb: 6379 + ## Node ports to expose + ## @param replica.service.nodePorts.keydb Node port for KeyDB replicas + ## NOTE: choose port between <30000-32767> + ## + nodePorts: + keydb: "" + ## @param replica.service.clusterIP KeyDB replicas service Cluster IP + ## e.g.: + ## clusterIP: None + ## + clusterIP: "" + ## @param replica.service.loadBalancerIP KeyDB replicas service Load Balancer IP + ## ref: https://kubernetes.io/docs/concepts/services-networking/service/#type-loadbalancer + ## + loadBalancerIP: "" + ## @param replica.service.loadBalancerSourceRanges KeyDB replicas service Load Balancer sources + ## ref: https://kubernetes.io/docs/tasks/access-application-cluster/configure-cloud-provider-firewall/#restrict-access-for-loadbalancer-service + ## e.g: + ## loadBalancerSourceRanges: + ## - 10.10.10.0/24 + ## + loadBalancerSourceRanges: [] + ## @param replica.service.externalTrafficPolicy KeyDB replicas service external traffic policy + ## ref http://kubernetes.io/docs/tasks/access-application-cluster/create-external-load-balancer/#preserving-the-client-source-ip + ## + externalTrafficPolicy: Cluster + ## @param replica.service.annotations Additional custom annotations for KeyDB replicas service + ## + annotations: {} + ## @param replica.service.extraPorts Extra ports to expose in KeyDB replicas service (normally used with the `sidecars` value) + ## + extraPorts: [] + ## @param replica.service.sessionAffinity Control where client requests go, to the same pod or round-robin + ## Values: ClientIP or None + ## ref: https://kubernetes.io/docs/concepts/services-networking/service/ + ## + sessionAffinity: None + ## @param replica.service.sessionAffinityConfig Additional settings for the sessionAffinity + ## sessionAffinityConfig: + ## clientIP: + ## timeoutSeconds: 300 + ## + sessionAffinityConfig: {} + ## Headless service properties + ## + headless: + ## @param replica.service.headless.annotations Annotations for the headless service. + ## + annotations: {} + ## KeyDB Replicas Network Policies + ## Ref: https://kubernetes.io/docs/concepts/services-networking/network-policies/ + ## + networkPolicy: + ## @param replica.networkPolicy.enabled Specifies whether a NetworkPolicy should be created for KeyDB replicas + ## + enabled: true + ## @param replica.networkPolicy.allowExternal Don't require server label for connections + ## The Policy model to apply. When set to false, only pods with the correct + ## server label will have network access to the ports server is listening + ## on. When true, server will accept connections from any source + ## (with the correct destination port). + ## + allowExternal: true + ## @param replica.networkPolicy.allowExternalEgress Allow the pod to access any range of port and all destinations. + ## + allowExternalEgress: true + ## @param replica.networkPolicy.addExternalClientAccess Allow access from pods with client label set to "true". Ignored if `networkPolicy.allowExternal` is true. + ## + addExternalClientAccess: true + ## @param replica.networkPolicy.extraIngress [array] Add extra ingress rules to the NetworkPolicy + ## e.g: + ## extraIngress: + ## - ports: + ## - port: 1234 + ## from: + ## - podSelector: + ## - matchLabels: + ## - role: frontend + ## - podSelector: + ## - matchExpressions: + ## - key: role + ## operator: In + ## values: + ## - frontend + extraIngress: [] + ## @param replica.networkPolicy.extraEgress [array] Add extra ingress rules to the NetworkPolicy (ignored if allowExternalEgress=true) + ## e.g: + ## extraEgress: + ## - ports: + ## - port: 1234 + ## to: + ## - podSelector: + ## - matchLabels: + ## - role: frontend + ## - podSelector: + ## - matchExpressions: + ## - key: role + ## operator: In + ## values: + ## - frontend + ## + extraEgress: [] + ## @param replica.networkPolicy.ingressPodMatchLabels [object] Labels to match to allow traffic from other pods. Ignored if `networkPolicy.allowExternal` is true. + ## e.g: + ## ingressPodMatchLabels: + ## my-client: "true" + # + ingressPodMatchLabels: {} + ## @param replica.networkPolicy.ingressNSMatchLabels [object] Labels to match to allow traffic from other namespaces. Ignored if `networkPolicy.allowExternal` is true. + ## @param replica.networkPolicy.ingressNSPodMatchLabels [object] Pod labels to match to allow traffic from other namespaces. Ignored if `networkPolicy.allowExternal` is true. + ## + ingressNSMatchLabels: {} + ingressNSPodMatchLabels: {} + +## @section Metrics Parameters +## +metrics: + ## @param metrics.enabled Start a sidecar Prometheus exporter to expose KeyDB metrics + ## + enabled: false + ## Bitnami Redis Exporter image + ## ref: https://hub.docker.com/r/bitnami/redis-exporter/tags/ + ## @param metrics.image.registry [default: REGISTRY_NAME] Redis Exporter image registry + ## @param metrics.image.repository [default: REPOSITORY_NAME/redis-exporter] Redis Exporter image repository + ## @skip metrics.image.tag Redis Exporter image tag (immutable tags are recommended) + ## @param metrics.image.digest Redis Exporter image digest in the way sha256:aa.... Please note this parameter, if set, will override the tag + ## @param metrics.image.pullPolicy Redis Exporter image pull policy + ## @param metrics.image.pullSecrets Redis Exporter image pull secrets + ## + image: + registry: docker.io + repository: bitnamilegacy/redis-exporter + tag: latest + digest: "" + 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/ + ## e.g: + ## pullSecrets: + ## - myRegistryKeySecretName + ## + pullSecrets: [] + ## @param metrics.containerPorts.http Metrics HTTP container port + ## + containerPorts: + http: 9121 + ## Configure extra options for KeyDB containers' liveness, readiness & startup probes + ## ref: https://kubernetes.io/docs/tasks/configure-pod-container/configure-liveness-readiness-startup-probes/ + ## @param metrics.startupProbe.enabled Enable startupProbe on KeyDB replicas nodes + ## @param metrics.startupProbe.initialDelaySeconds Initial delay seconds for startupProbe + ## @param metrics.startupProbe.periodSeconds Period seconds for startupProbe + ## @param metrics.startupProbe.timeoutSeconds Timeout seconds for startupProbe + ## @param metrics.startupProbe.failureThreshold Failure threshold for startupProbe + ## @param metrics.startupProbe.successThreshold Success threshold for startupProbe + ## + startupProbe: + enabled: false + initialDelaySeconds: 10 + periodSeconds: 10 + timeoutSeconds: 5 + successThreshold: 1 + failureThreshold: 5 + ## @param metrics.livenessProbe.enabled Enable livenessProbe on KeyDB replicas nodes + ## @param metrics.livenessProbe.initialDelaySeconds Initial delay seconds for livenessProbe + ## @param metrics.livenessProbe.periodSeconds Period seconds for livenessProbe + ## @param metrics.livenessProbe.timeoutSeconds Timeout seconds for livenessProbe + ## @param metrics.livenessProbe.failureThreshold Failure threshold for livenessProbe + ## @param metrics.livenessProbe.successThreshold Success threshold for livenessProbe + ## + livenessProbe: + enabled: true + initialDelaySeconds: 10 + periodSeconds: 10 + timeoutSeconds: 5 + successThreshold: 1 + failureThreshold: 5 + ## @param metrics.readinessProbe.enabled Enable readinessProbe on KeyDB replicas nodes + ## @param metrics.readinessProbe.initialDelaySeconds Initial delay seconds for readinessProbe + ## @param metrics.readinessProbe.periodSeconds Period seconds for readinessProbe + ## @param metrics.readinessProbe.timeoutSeconds Timeout seconds for readinessProbe + ## @param metrics.readinessProbe.failureThreshold Failure threshold for readinessProbe + ## @param metrics.readinessProbe.successThreshold Success threshold for readinessProbe + ## + readinessProbe: + enabled: true + initialDelaySeconds: 5 + periodSeconds: 10 + timeoutSeconds: 1 + successThreshold: 1 + failureThreshold: 3 + ## @param metrics.customStartupProbe Custom startupProbe that overrides the default one + ## + customStartupProbe: {} + ## @param metrics.customLivenessProbe Custom livenessProbe that overrides the default one + ## + customLivenessProbe: {} + ## @param metrics.customReadinessProbe Custom readinessProbe that overrides the default one + ## + customReadinessProbe: {} + ## @param metrics.command Override default metrics container init command (useful when using custom images) + ## + command: [] + ## @param metrics.keydbHost A way to specify an alternative KeyDB hostname + ## Useful for certificate CN/SAN matching + ## + keydbHost: "localhost" + ## @param metrics.extraArgs Extra arguments for KeyDB metrics exporter, for example: + ## e.g.: + ## extraArgs: + ## check-keys: myKey,myOtherKey + ## + extraArgs: {} + ## @param metrics.extraEnvVars Array with extra environment variables to add to KeyDB metrics exporter + ## e.g: + ## extraEnvVars: + ## - name: FOO + ## value: "bar" + ## + extraEnvVars: [] + ## Configure Container Security Context + ## ref: https://kubernetes.io/docs/tasks/configure-pod-container/security-context/#set-the-security-context-for-a-pod + ## @param metrics.containerSecurityContext.enabled Enabled KeyDB metrics exporter containers' Security Context + ## @param metrics.containerSecurityContext.seLinuxOptions [object,nullable] Set SELinux options in container + ## @param metrics.containerSecurityContext.runAsUser Set KeyDB metrics exporter containers' Security Context runAsUser + ## @param metrics.containerSecurityContext.runAsGroup Set KeyDB metrics exporter containers' Security Context runAsGroup + ## @param metrics.containerSecurityContext.runAsNonRoot Set KeyDB metrics exporter containers' Security Context runAsNonRoot + ## @param metrics.containerSecurityContext.allowPrivilegeEscalation Set KeyDB metrics exporter containers' Security Context allowPrivilegeEscalation + ## @param metrics.containerSecurityContext.readOnlyRootFilesystem Set container's Security Context read-only root filesystem + ## @param metrics.containerSecurityContext.seccompProfile.type Set KeyDB metrics exporter containers' Security Context seccompProfile + ## @param metrics.containerSecurityContext.capabilities.drop Set KeyDB metrics exporter containers' Security Context capabilities to drop + ## + containerSecurityContext: + enabled: true + seLinuxOptions: {} + runAsUser: 1001 + runAsGroup: 1001 + runAsNonRoot: true + allowPrivilegeEscalation: false + readOnlyRootFilesystem: true + seccompProfile: + type: RuntimeDefault + capabilities: + drop: ["ALL"] + ## @param metrics.extraVolumeMounts Optionally specify extra list of additional volumeMounts for the KeyDB metrics sidecar + ## + extraVolumeMounts: [] + ## KeyDB metrics exporter resource requests and limits + ## ref: https://kubernetes.io/docs/concepts/configuration/manage-compute-resources-container/ + ## @param metrics.resourcesPreset Set container resources according to one common preset (allowed values: none, nano, micro, small, medium, large, xlarge, 2xlarge). This is ignored if metrics.resources is set (metrics.resources is recommended for production). + ## More information: https://github.com/bitnami/charts/blob/main/bitnami/common/templates/_resources.tpl#L15 + ## + resourcesPreset: "nano" + ## @param metrics.resources Set container requests and limits for different resources like CPU or memory (essential for production workloads) + ## Example: + ## resources: + ## requests: + ## cpu: 2 + ## memory: 512Mi + ## limits: + ## cpu: 3 + ## memory: 1024Mi + ## + resources: {} + ## @param metrics.podLabels Extra labels for KeyDB metrics exporter pods + ## ref: https://kubernetes.io/docs/concepts/overview/working-with-objects/labels/ + ## + podLabels: {} + ## @param metrics.podAnnotations [object] Annotations for KeyDB metrics exporter pods + ## ref: https://kubernetes.io/docs/concepts/overview/working-with-objects/annotations/ + ## + podAnnotations: + prometheus.io/scrape: "true" + prometheus.io/port: "{{ .Values.metrics.containerPorts.http }}" + ## KeyDB metrics exporter service properties + ## + service: + ## @param metrics.service.port Metrics service port + ## + port: 9121 + ## @param metrics.service.annotations Annotations for the metrics service + ## + annotations: {} + ## Prometheus Operator ServiceMonitor configuration + ## + serviceMonitor: + ## @param metrics.serviceMonitor.enabled if `true`, creates a Prometheus Operator ServiceMonitor (also requires `metrics.enabled` to be `true`) + ## + enabled: false + ## @param metrics.serviceMonitor.namespace Namespace in which Prometheus is running + ## + namespace: "" + ## @param metrics.serviceMonitor.annotations Additional custom annotations for the ServiceMonitor + ## + annotations: {} + ## @param metrics.serviceMonitor.labels Extra labels for the ServiceMonitor + ## + labels: {} + ## @param metrics.serviceMonitor.jobLabel The name of the label on the target service to use as the job name in Prometheus + ## + jobLabel: "" + ## @param metrics.serviceMonitor.honorLabels honorLabels chooses the metric's labels on collisions with target labels + ## + honorLabels: false + ## @param metrics.serviceMonitor.interval Interval at which metrics should be scraped. + ## ref: https://github.com/coreos/prometheus-operator/blob/master/Documentation/api.md#endpoint + ## e.g: + ## interval: 10s + ## + interval: "" + ## @param metrics.serviceMonitor.scrapeTimeout Timeout after which the scrape is ended + ## ref: https://github.com/coreos/prometheus-operator/blob/master/Documentation/api.md#endpoint + ## e.g: + ## scrapeTimeout: 10s + ## + scrapeTimeout: "" + ## @param metrics.serviceMonitor.metricRelabelings Specify additional relabeling of metrics + ## + metricRelabelings: [] + ## @param metrics.serviceMonitor.relabelings Specify general relabeling + ## + relabelings: [] + ## @param metrics.serviceMonitor.selector Prometheus instance selector labels + ## ref: https://github.com/bitnami/charts/tree/main/bitnami/prometheus-operator#prometheus-configuration + ## selector: + ## prometheus: my-prometheus + ## + selector: {} + ## Custom PrometheusRule to be defined + ## ref: https://github.com/coreos/prometheus-operator#customresourcedefinitions + ## + prometheusRule: + ## @param metrics.prometheusRule.enabled Create a custom prometheusRule Resource for scraping metrics using PrometheusOperator + ## + enabled: false + ## @param metrics.prometheusRule.namespace The namespace in which the prometheusRule will be created + ## + namespace: "" + ## @param metrics.prometheusRule.annotations Additional custom annotations for the prometheusRule + ## + annotations: {} + ## @param metrics.prometheusRule.labels Extra labels for the prometheusRule + ## + labels: {} + ## @param metrics.prometheusRule.rules Custom Prometheus rules + ## e.g: + ## rules: + ## - alert: KeyDBDown + ## expr: redis_up{service="{{ include "common.names.fullname" . }}-metrics"} == 0 + ## for: 2m + ## labels: + ## severity: error + ## annotations: + ## summary: KeyDB instance {{ "{{ $labels.instance }}" }} down + ## description: KeyDB instance {{ "{{ $labels.instance }}" }} is down + ## - alert: KeyDBMemoryHigh + ## expr: > + ## redis_memory_used_bytes{service="{{ include "common.names.fullname" . }}-metrics"} * 100 + ## / + ## redis_memory_max_bytes{service="{{ include "common.names.fullname" . }}-metrics"} + ## > 90 + ## for: 2m + ## labels: + ## severity: error + ## annotations: + ## summary: KeyDB instance {{ "{{ $labels.instance }}" }} is using too much memory + ## description: | + ## KeyDB instance {{ "{{ $labels.instance }}" }} is using {{ "{{ $value }}" }}% of its available memory. + ## - alert: KeyDBKeyEviction + ## expr: | + ## increase(redis_evicted_keys_total{service="{{ include "common.names.fullname" . }}-metrics"}[5m]) > 0 + ## for: 1s + ## labels: + ## severity: error + ## annotations: + ## summary: KeyDB instance {{ "{{ $labels.instance }}" }} has evicted keys + ## description: | + ## KeyDB instance {{ "{{ $labels.instance }}" }} has evicted {{ "{{ $value }}" }} keys in the last 5 minutes. + ## + rules: [] + +## @section Other Parameters + +## ServiceAccount configuration +## +serviceAccount: + ## @param serviceAccount.create Specifies whether a ServiceAccount should be created for KeyDB replicas pods + ## + create: true + ## @param serviceAccount.name The name of the ServiceAccount to use + ## If not set and create is true, a name is generated using the common.names.fullname template + ## + name: "" + ## @param serviceAccount.annotations Additional Service Account annotations (evaluated as a template) + ## + annotations: {} + ## @param serviceAccount.automountServiceAccountToken Automount service account token for the server service account + ## + automountServiceAccountToken: true + +## @section Init Container Parameters +## + +## 'volumePermissions' init container parameters +## Changes the owner and group of the persistent volume mount point to runAsUser:fsGroup values +## based on the *podSecurityContext/*containerSecurityContext parameters +## +volumePermissions: + ## @param volumePermissions.enabled Enable init container that changes the owner/group of the PV mount point to `runAsUser:fsGroup` + ## + enabled: false + ## OS Shell + Utility image + ## ref: https://hub.docker.com/r/bitnami/os-shell/tags/ + ## @param volumePermissions.image.registry [default: REGISTRY_NAME] OS Shell + Utility image registry + ## @param volumePermissions.image.repository [default: REPOSITORY_NAME/os-shell] OS Shell + Utility image repository + ## @skip volumePermissions.image.tag OS Shell + Utility image tag (immutable tags are recommended) + ## @param volumePermissions.image.pullPolicy OS Shell + Utility image pull policy + ## @param volumePermissions.image.pullSecrets OS Shell + Utility image pull secrets + ## + image: + registry: docker.io + repository: bitnamilegacy/os-shell + tag: latest + 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/ + ## e.g: + ## pullSecrets: + ## - myRegistryKeySecretName + ## + pullSecrets: [] + ## Init container's resource requests and limits + ## ref: http://kubernetes.io/docs/concepts/configuration/manage-compute-resources-container/ + ## @param volumePermissions.resourcesPreset Set init container resources according to one common preset (allowed values: none, nano, small, medium, large, xlarge, 2xlarge). This is ignored if volumePermissions.resources is set (volumePermissions.resources is recommended for production). + ## More information: https://github.com/bitnami/charts/blob/main/bitnami/common/templates/_resources.tpl#L15 + ## + resourcesPreset: "nano" + ## @param volumePermissions.resources Set init container requests and limits for different resources like CPU or memory (essential for production workloads) + ## Example: + ## resources: + ## requests: + ## cpu: 2 + ## memory: 512Mi + ## limits: + ## cpu: 3 + ## memory: 1024Mi + ## + resources: {} + ## Init container Container Security Context + ## ref: https://kubernetes.io/docs/tasks/configure-pod-container/security-context/#set-the-security-context-for-a-container + ## @param volumePermissions.containerSecurityContext.enabled Enabled init container' Security Context + ## @param volumePermissions.containerSecurityContext.seLinuxOptions [object,nullable] Set SELinux options in init container + ## @param volumePermissions.containerSecurityContext.runAsUser Set init container's Security Context runAsUser + ## NOTE: when runAsUser is set to special value "auto", init container will try to chown the + ## data folder to auto-determined user&group, using commands: `id -u`:`id -G | cut -d" " -f2` + ## "auto" is especially useful for OpenShift which has scc with dynamic user ids (and 0 is not allowed) + ## + containerSecurityContext: + enabled: true + seLinuxOptions: {} + runAsUser: 0 diff --git a/helm-charts/keydb/.helmignore b/helm-charts/keydb/.helmignore index 691fa13..a0a332a 100644 --- a/helm-charts/keydb/.helmignore +++ b/helm-charts/keydb/.helmignore @@ -14,10 +14,10 @@ *.swp *.bak *.tmp -*.orig *~ # Various IDEs .project .idea/ *.tmproj -.vscode/ \ No newline at end of file +# Changelog +CHANGELOG.md diff --git a/helm-charts/keydb/Chart.lock b/helm-charts/keydb/Chart.lock new file mode 100644 index 0000000..d0f537a --- /dev/null +++ b/helm-charts/keydb/Chart.lock @@ -0,0 +1,6 @@ +dependencies: +- name: common + repository: oci://registry-1.docker.io/bitnamicharts + version: 2.31.4 +digest: sha256:fc442e77200e1914dd46fe26490dcf62f44caa51db673c2f8e67d5319cd4c163 +generated: "2025-08-13T18:09:24.973575966Z" diff --git a/helm-charts/keydb/Chart.yaml b/helm-charts/keydb/Chart.yaml index f164c80..a5c9488 100644 --- a/helm-charts/keydb/Chart.yaml +++ b/helm-charts/keydb/Chart.yaml @@ -1,23 +1,36 @@ +annotations: + category: Database + images: | + - name: keydb + image: docker.io/bitnamilegacy/keydb:latest + - name: os-shell + image: docker.io/bitnamilegacy/os-shell:latest + - name: redis-exporter + image: docker.io/bitnamilegacy/redis-exporter:latest + licenses: Apache-2.0 + tanzuCategory: service apiVersion: v2 -name: keydb -description: A Helm chart for KeyDB multimaster setup -type: application -version: 0.48.0 +appVersion: 6.3.4 +dependencies: +- name: common + repository: oci://registry-1.docker.io/bitnamicharts + tags: + - bitnami-common + version: 2.x.x +description: KeyDB is a high performance fork of Redis with a focus on multithreading, + memory efficiency, and high throughput. +home: https://bitnami.com +icon: https://dyltqmyl993wv.cloudfront.net/assets/stacks/keydb/img/keydb-stack-220x234.png keywords: - keydb -- redis - keyvalue - database -- multimaster -- HA -- high-availability -home: https://keydb.dev +- cache maintainers: -- email: avoronkov@enapter.com - name: Antiarchitect - url: https://github.com/Antiarchitect +- name: Broadcom, Inc. All Rights Reserved. + url: https://github.com/bitnami/charts +name: keydb sources: -- https://github.com/Enapter/charts -- https://github.com/JohnSully/KeyDB -icon: https://enapter.github.io/charts/keydb.png -appVersion: 6.3.2 +- https://github.com/bitnami/charts/tree/main/bitnami/keydb +- https://github.com/bitnami/containers/tree/main/bitnami/keydb +version: 0.5.22 diff --git a/helm-charts/keydb/README.md b/helm-charts/keydb/README.md index 8d16f1d..e7d8ad3 100644 --- a/helm-charts/keydb/README.md +++ b/helm-charts/keydb/README.md @@ -1,181 +1,721 @@ -# KeyDB + -[KeyDB](https://keydb.dev) clocks in at 5X faster than Redis (node vs node). KeyDB is a popular drop in Redis alternative that people flock to because it enables you to consolidate a lot of the complexities associated with Redis. KeyDB is multithreaded with the ability to use several storage mediums natively and scale vertically. The superior architecture is enabling KeyDB to become the bridge between cache layer and traditional databases offering performance and durability. +# Bitnami package for KeyDB -## TL;DR; +KeyDB is a high performance fork of Redis with a focus on multithreading, memory efficiency, and high throughput. -```bash -helm repo add enapter https://enapter.github.io/charts/ -helm install keydb enapter/keydb +[Overview of KeyDB](https://github.com/Snapchat/KeyDB) + +Trademarks: This software listing is packaged by Bitnami. The respective trademarks mentioned in the offering are owned by the respective companies, and use of them does not imply any affiliation or endorsement. + +## TL;DR + +```console +helm install my-release oci://registry-1.docker.io/bitnamicharts/keydb ``` +Looking to use KeyDB in production? Try [VMware Tanzu Application Catalog](https://bitnami.com/enterprise), the commercial edition of the Bitnami catalog. + +## ⚠️ Important Notice: Upcoming changes to the Bitnami Catalog + +Beginning August 28th, 2025, Bitnami will evolve its public catalog to offer a curated set of hardened, security-focused images under the new [Bitnami Secure Images initiative](https://news.broadcom.com/app-dev/broadcom-introduces-bitnami-secure-images-for-production-ready-containerized-applications). As part of this transition: + +- Granting community users access for the first time to security-optimized versions of popular container images. +- Bitnami will begin deprecating support for non-hardened, Debian-based software images in its free tier and will gradually remove non-latest tags from the public catalog. As a result, community users will have access to a reduced number of hardened images. These images are published only under the “latest” tag and are intended for development purposes +- Starting August 28th, over two weeks, all existing container images, including older or versioned tags (e.g., 2.50.0, 10.6), will be migrated from the public catalog (docker.io/bitnami) to the “Bitnami Legacy” repository (docker.io/bitnamilegacy), where they will no longer receive updates. +- For production workloads and long-term support, users are encouraged to adopt Bitnami Secure Images, which include hardened containers, smaller attack surfaces, CVE transparency (via VEX/KEV), SBOMs, and enterprise support. + +These changes aim to improve the security posture of all Bitnami users by promoting best practices for software supply chain integrity and up-to-date deployments. For more details, visit the [Bitnami Secure Images announcement](https://github.com/bitnami/containers/issues/83267). + ## Introduction -This chart bootstraps a [KeyDB](https://keydb.dev) highly available multi-master statefulset in a [Kubernetes](http://kubernetes.io) cluster using the Helm package manager. +Bitnami charts for Helm are carefully engineered, actively maintained and are the quickest and easiest way to deploy containers on a Kubernetes cluster that are ready to handle production workloads. + +This chart bootstraps a [KeyDB](https://github.com/Snapchat/KeyDB) deployment in a [Kubernetes](https://kubernetes.io) cluster using the [Helm](https://helm.sh) package manager. + +## Prerequisites + +- Kubernetes 1.23+ +- Helm 3.8.0+ +- PV provisioner support in the underlying infrastructure + +## Installing the Chart + +To install the chart with the release name `my-release`: + +```console +helm install my-release oci://REGISTRY_NAME/REPOSITORY_NAME/keydb +``` + +> Note: You need to substitute the placeholders `REGISTRY_NAME` and `REPOSITORY_NAME` with a reference to your Helm chart registry and repository. For example, in the case of Bitnami, you need to use `REGISTRY_NAME=registry-1.docker.io` and `REPOSITORY_NAME=bitnamicharts`. + +The command deploys KeyDB on the Kubernetes cluster in the default configuration. The [Parameters](#parameters) section lists the parameters that can be configured during installation. -## 0.40.1 Upgrade notice +> **Tip**: List all releases using `helm list` -As the chart is not yet production ready (0.x) backward incompatible changes can be introduced in minor releases. +## Configuration and installation details -`exporter.pullPolicy` is deprecated in favor of `exporter.imagePullPolicy` +### Cluster topologies +#### Default: Master - Replicas -## 0.38.0 Upgrade notice +When installing the chart with `architecture=replication`, it will deploy a KeyDB Master statefulset and a KeyDB Replica statefulset. The master is responsible for all write operations, while the replicas replicate the write operations from the master and serve read operations. Two services will be exposed: -As the chart is not yet production ready (0.x) backward incompatible changes can be introduced in minor releases. +- KeyDB Master service: Points to the master, where read-write operations can be performed +- KeyDB Replicas service: Points to the replicas, where only read operations are allowed by default. -This release enables using a dedicated ServiceAccount for the KeyDB StatefulSet. Either an SA created by the chart or a pre-exising SA can be used. The corresponding value setting `serviceAccount.enabled` is turned off by default for backward compatibility. +In case the master crashes, the replicas will wait until the master node is respawned again by the Kubernetes Controller Manager. -Please note that the `serviceAccountName` field of the StatefulSet's spec is immutable, so an upgrade from a helm release where the dedicated SA is disabled (the default) to a release where it is explicitly enabled is impossible and will fail. You should plan a migration to an SA-enabled release in advance considering your environment and operational practices, e.g. using a blue-green deployment or scheduling a downtime for removal of the previous release. In case of removal please also consider data retention as necessary, e.g. verify the reclaim policy of the StorageClass in use. +#### Active Replicas -If you plan a deployment in an environment where dedicated ServiceAccounts are essential, e.g. in a service mesh, please consider enabling the SA setting from the start. +Similar to the Master-Replicas architecture, but with the ability to perform read and write operations on the replicas. This is achieved by setting `replica.activeReplica=true`. Find more information about how this mechanism works at the [KeyDB documentation](https://docs.keydb.dev/docs/active-rep). -## 0.33.0 Upgrade notice +#### Standalone -As the chart is not yet production ready (0.x) backward incompatible changes can be introduced in minor releases. -Since 0.33.0 `scripts.cleanup` is obsoleted by `scripts.cleanupTempfiles`. `scripts.cleanupCoredumps` section is added in order to provide ability to cleanup `core.*` files and is disabled by default. Please look `values.yaml`. +When installing the chart with `architecture=standalone`, it will deploy a standalone KeyDB Master statefulset. A single service will be exposed: -## 0.30.0 Upgrade notice +- KeyDB Master service: Points to the master, where read-write operations can be performed -As the chart is not yet production ready (0.x) backward incompatible changes can be introduced in minor releases. -Since 0.30.0 `additionalAffinities` option is completely obsolete and `affinity` replaces it. `affinity` is rendered dynamically (approach is taken from Bitnami charts) so you can set dynamic things like `'{{ .Release.Name }}'` right inside the `affinity:` key in `values.yaml`. Will extend this approach for other places in the future. +#### Multi Master - Replicas -## 0.29.0 Upgrade notice +Similar to the Master-Replicas architecture, this architectures deploys both a KeyDB Master statefulset and a KeyDB Replica statefulset. However, in this architecture N Master replicas can be deployed, and KeyDB replicas are configured to follow multiple masters. This can be achieved by setting `master.replicaCount` to a value greater than 1 and setting `replica.activeReplica=true` (please note active replication is mandatory when using multi-master). -As the chart is not yet production ready (0.x) backward incompatible changes can be introduced in minor releases. -Since 0.29.0 `configExtraArgs` and `exporter.extraArgs` are now arrays of dicts in order to allow repeating arguments with the same key. -If dict value is an array it is interpreted as multiple arguments for the key. +Find more information about how this mechanism works at the [KeyDB documentation](https://docs.keydb.dev/docs/multi-master). -### Config Example: +### Prometheus metrics +This chart can be integrated with Prometheus by setting `metrics.enabled` to `true`. This will deploy a sidecar container with [redis_exporter](https://github.com/oliver006/redis_exporter) in all pods and a `metrics` service, which can be configured under the `metrics.service` section. This `metrics` service will have the necessary annotations to be automatically scraped by Prometheus. + +#### Prometheus requirements + +It is necessary to have a working installation of Prometheus or Prometheus Operator for the integration to work. Install the [Bitnami Prometheus helm chart](https://github.com/bitnami/charts/tree/main/bitnami/prometheus) or the [Bitnami Kube Prometheus helm chart](https://github.com/bitnami/charts/tree/main/bitnami/kube-prometheus) to easily have a working Prometheus in your cluster. + +#### Integration with Prometheus Operator + +The chart can deploy `ServiceMonitor` objects for integration with Prometheus Operator installations. To do so, set the value `metrics.serviceMonitor.enabled=true`. Ensure that the Prometheus Operator `CustomResourceDefinitions` are installed in the cluster or it will fail with the following error: + +```text +no matches for kind "ServiceMonitor" in version "monitoring.coreos.com/v1" ``` -configExtraArgs: - - client-output-buffer-limit: ["normal", "0", "0", "0"] - - client-output-buffer-limit: ["replica", "268435456", "67108864", "60"] - - client-output-buffer-limit: ["pubsub", "33554432", "8388608", "60"] - - save: ~ - - tcp-backlog "1024" + +Install the [Bitnami Kube Prometheus helm chart](https://github.com/bitnami/charts/tree/main/bitnami/kube-prometheus) for having the necessary CRDs and the Prometheus Operator. + +### Update credentials + +The Bitnami KeyDB chart, when upgrading, reuses the secret previously rendered by the chart or the one specified in `auth.existingSecret`. To update credentials, use one of the following: + +- Run `helm upgrade` specifying a new password in `auth.password` +- Run `helm upgrade` specifying a new secret in `auth.existingSecret` + +### Using a password file + +To use a password file for KeyDB you need to create a secret containing the password and then deploy the chart using that secret. Follow these instructions: + +- Create the secret: + +```console +kubectl create secret generic keydb-password-secret --from-literal=keydb-password=KEYDB_PASSWORD ``` -### Resulting File: +> Note: the replace the KEYDB_PASSWORD placeholder with the actual password to use. +- Deploy the Helm Chart using the secret name as parameter: + +```text +auth.enabled=true +auth.existingSecret=keydb-password-secret +auth.existingSecretPasswordKey=keydb-password +auth.usePasswordFiles=true ``` -... -exec keydb-server /etc/keydb/redis.conf \ +### Securing traffic using TLS - ... +This chart supports encrypting communications using TLS. To enable this feature, set the `tls.enabled`. - --client-output-buffer-limit "normal" "0" "0" "0" \ - --client-output-buffer-limit "replica" "268435456" "67108864" "60" \ - --client-output-buffer-limit "pubsub" "33554432" "8388608" "60" \ - --save \ - --tcp-backlog "1024" \ +It is necessary to create a secret containing the TLS certificates and pass it to the chart via the `tls.existingCASecret`, `tls.master.existingSecret` and `tls.replica.existingSecret` (only for replication architecture) parameters. Every secret should contain a `tls.crt` and `tls.key` keys including the certificate and key files respectively. For example: create the CA secret with the certificates files: - ... +```console +kubectl create secret generic ca-tls-secret --from-file=./tls.crt --from-file=./tls.key ``` -## Prerequisites +You can manually create the required TLS certificates or relying on the chart auto-generation capabilities. The chart supports two different ways to auto-generate the required certificates: -- PV provisioner support in the underlying infrastructure if you want to enable persistence +- Using Helm capabilities. Enable this feature by setting `tls.autoGenerated.enabled` to `true` and `tls.autoGenerated.engine` to `helm`. +- Relying on CertManager (please note it's required to have CertManager installed in your K8s cluster). Enable this feature by setting `tls.autoGenerated.enabled` to `true` and `tls.autoGenerated.engine` to `cert-manager`. Please note it's supported to use an existing Issuer/ClusterIssuer for issuing the TLS certificates by setting the `tls.autoGenerated.certManager.existingIssuer` and `tls.autoGenerated.certManager.existingIssuerKind` parameters. -## Installing the Chart +### Metrics + +The chart optionally can start a metrics exporter for [prometheus](https://prometheus.io). Metrics can be scraped from within the cluster using something similar as the described in the [example Prometheus scrape configuration](https://github.com/prometheus/prometheus/blob/master/documentation/examples/prometheus-kubernetes.yml). If metrics are to be scraped from outside the cluster, the Kubernetes API proxy can be utilized to access the endpoint. -To install the chart +If you have enabled TLS by specifying `tls.enabled=true` you also need to specify TLS options to the metrics exporter. You can do that via `metrics.extraArgs`. You can find the metrics exporter CLI flags for TLS [here](https://github.com/oliver006/redis_exporter#command-line-flags). For example: -```bash -helm repo add enapter https://enapter.github.io/charts/ -helm install keydb enapter/keydb +You can either specify `metrics.extraArgs.skip-tls-verification=true` to skip TLS verification or providing the following values under `metrics.extraArgs` for TLS client authentication: + +```console +tls-client-key-file +tls-client-cert-file +tls-ca-cert-file ``` -## Configuration - -The following table lists the configurable parameters of the KeyDB chart and their default values. - -| Parameter | Description | Default | -|:--------------------------------|:---------------------------------------------------|:------------------------------------------| -| `imageRepository` | KeyDB docker image | `eqalpha/keydb` | -| `imageTag` | KeyDB docker image tag | `x86_64_v6.3.2` | -| `imagePullPolicy` | K8s imagePullPolicy | `IfNotPresent` | -| `imagePullSecrets` | KeyDB Pod imagePullSecrets | `[]` | -| `nodes` | Number of KeyDB master pods | `3` | -| `password` | If enabled KeyDB servers are password-protected | `""` | -| `existingSecret` | If enabled password is taken from secret | `""` | -| `existingSecretPasswordKey` | Secret key name. | `"password"` | -| `port` | KeyDB service port clients connect to | `6379` | -| `portName` | KeyDB service port name in the Service spec | `server` | -| `threads` | KeyDB server-threads per node | `2` | -| `multiMaster` | KeyDB multi-master setup | `yes` | -| `activeReplicas` | KeyDB active replication setup | `yes` | -| `protectedMode` | KeyDB protection mode | `no` | -| `appendonly` | KeyDB appendonly setting | `no` | -| `configExtraArgs` | Additional configuration arguments for KeyDB | `[]` | -| `annotations` | KeyDB StatefulSet annotations | `{}` | -| `podAnnotations` | KeyDB pods annotations | `{}` | -| `tolerations` | KeyDB tolerations setting | `{}` | -| `nodeSelector` | KeyDB nodeSelector setting | `{}` | -| `topologySpreadConstraints` | KeyDB topologySpreadConstraints setting | `[]` | -| `affinity` | StatefulSet Affinity rules | Look values.yaml | -| `extraInitContainers` | Additional init containers for StatefulSet | `[]` | -| `extraContainers` | Additional sidecar containers for StatefulSet | `[]` | -| `extraVolumes` | Additional volumes for init and sidecar containers | `[]` | -| `livenessProbe.custom` | Custom LivenessProbe for KeyDB pods | `{}` | -| `readinessProbe.custom` | Custom ReadinessProbe for KeyDB pods | `{}` | -| `readinessProbeRandomUuid` | Random UUIDv4 for readiness GET probe | `90f717dd-0e68-43b8-9363-fddaad00d6c9` | -| `startupProbe.custom` | Custom StartupProbe for KeyDB pods | `{}` | -| `persistentVolume.enabled` | Should PVC be created via volumeClaimTemplates | `true` | -| `persistentVolume.accessModes` | Volume access modes | `[ReadWriteOnce]` | -| `persistentVolume.selector` | PVC selector. (In order to match existing PVs) | `{}` | -| `persistentVolume.size` | Size of the volume | `1Gi` | -| `persistentVolume.storageClass` | StorageClassName for volume | `` | -| `podDisruptionBudget` | podDisruptionBudget for KeyDB pods | Look values.yaml | -| `resources` | Resources for KeyDB containers | `{}` | -| `scripts.enabled` | Turn on health util scripts | `false` | -| `scripts.cleanupCoredumps` | Coredumps cleanup scripts | Look values.yaml | -| `scripts.cleanupTempfiles` | Tempfiles cleanup scripts | Look values.yaml | -| `scripts.securityContext` | SecurityContext for scripts container | `{}` | -| `keydb.securityContext` | SecurityContext for KeyDB container | `{}` | -| `securityContext` | SecurityContext for KeyDB pods | `{}` | -| `service.annotations` | Service annotations | `{}` | -| `service.appProtocol.enabled` | Turn on appProtocol fields in port specs | `false` | -| `loadBalancer.enabled` | Create LoadBalancer service | `false` | -| `loadBalancer.annotations` | Annotations for LB | `{}` | -| `loadBalancer.extraSpec` | Additional spec for LB | `{}` | -| `serviceAccount.enabled` | Use a dedicated ServiceAccount (SA) | `false` | -| `serviceAccount.create` | Create the SA (rather than use an existing one) | `true` | -| `serviceAccount.name` | Set the name of an existing SA or override created | `` | -| `serviceAccount.extraSpec` | Additional spec for the created SA | `{}` | -| `serviceMonitor.enabled` | Prometheus operator ServiceMonitor | `false` | -| `serviceMonitor.labels` | Additional labels for ServiceMonitor | `{}` | -| `serviceMonitor.annotations` | Additional annotations for ServiceMonitor | `{}` | -| `serviceMonitor.interval` | ServiceMonitor scrape interval | `30s` | -| `serviceMonitor.scrapeTimeout` | ServiceMonitor scrape timeout | `nil` | -| `exporter.enabled` | Prometheus Exporter sidecar contaner | `false` | -| `exporter.imageRepository` | Exporter Image | `oliver006/redis_exporter` | -| `exporter.imageTag` | Exporter Image Tag | `v1.48.0-alpine` | -| `exporter.pullPolicy` | Exporter imagePullPolicy | `IfNotPresent` | -| `exporter.port` | `prometheus.io/port` | `9121` | -| `exporter.portName` | Exporter service port name in the Service spec | `redis-exporter` | -| `exporter.scrapePath` | `prometheus.io/path` | `/metrics` | -| `exporter.livenessProbe` | LivenessProbe for sidecar Prometheus exporter | Look values.yaml | -| `exporter.readinessProbe` | ReadinessProbe for sidecar Prometheus exporter | Look values.yaml | -| `exporter.startupProbe` | StartupProbe for sidecar Prometheus exporter | Look values.yaml | -| `exporter.resources` | Resources for sidecar Prometheus container | `{}` | -| `exporter.securityContext` | SecurityContext for Prometheus exporter container | `{}` | -| `exporter.extraArgs` | Additional arguments for exporter | `[]` | - -## Using existingSecret - -When definining existingSecret (by default is "") password value is ignored. Password is taken from that secret, instead of being provided as plain text under values.yaml file. \ -Secret key must be `existingSecretPasswordKey` (*password* by default). \ -Example of of such secret: -```bash -kubectl create secret generic keydb-password --from-literal=password=KEYDB_PASSWORD +### [Rolling VS Immutable tags](https://techdocs.broadcom.com/us/en/vmware-tanzu/application-catalog/tanzu-application-catalog/services/tac-doc/apps-tutorials-understand-rolling-tags-containers-index.html) + +It is strongly recommended to use immutable tags in a production environment. This ensures your deployment does not change automatically if the same tag is updated with a different image. + +Bitnami will release a new chart updating its containers if a new version of the main container, significant changes, or critical vulnerabilities exist. + +### Resource requests and limits + +Bitnami charts allow setting resource requests and limits for all containers inside the chart deployment. These are inside the `resources` value (check parameter table). Setting requests is essential for production workloads and these should be adapted to your specific use case. + +To make this process easier, the chart contains the `resourcesPreset` values, which automatically sets the `resources` section according to different presets. Check these presets in [the bitnami/common chart](https://github.com/bitnami/charts/blob/main/bitnami/common/templates/_resources.tpl#L15). However, in production workloads using `resourcesPreset` is discouraged as it may not fully adapt to your specific needs. Find more information on container resource management in the [official Kubernetes documentation](https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/). + +### Additional environment variables + +In case you want to add extra environment variables (useful for advanced operations like custom init scripts), you can use the `extraEnvVars` property. + +```yaml +master: + extraEnvVars: + - name: LOG_LEVEL + value: error ``` -Definition of existingSecret in that case: + +Alternatively, you can use a ConfigMap or a Secret with the environment variables. To do so, use the `extraEnvVarsCM` or the `extraEnvVarsSecret` values. + +### Sidecars + +If additional containers are needed in the same pod as KeyDB (such as additional metrics or logging exporters), they can be defined using the `sidecars` parameter. + ```yaml -password: "" -existingSecret: keydb-password -existingSecretPasswordKey: password-key-in-secret-file +master: + sidecars: + - name: your-image-name + image: your-image + imagePullPolicy: Always + ports: + - name: portname + containerPort: 1234 ``` -It is important to use only one way of providing passwords: via plain text under values.yaml or using already existing secret. + +If these sidecars export extra ports, extra port definitions can be added using the `service.extraPorts` parameter (where available), as shown in the example below: + +```yaml +master: + service: + extraPorts: + - name: extraPort + port: 11311 + targetPort: 11311 +``` + +> NOTE: This Helm chart already includes sidecar containers for the Prometheus exporters (where applicable). These can be activated by setting the `metrics.enabled` parameter to `true` at deployment time. The `sidecars` parameter should therefore only be used for any extra sidecar containers. + +If additional init containers are needed in the same pod, they can be defined using the `initContainers` parameter. Here is an example: + +```yaml +master: + initContainers: + - name: your-image-name + image: your-image + imagePullPolicy: Always + ports: + - name: portname + containerPort: 1234 +``` + +Learn more about [sidecar containers](https://kubernetes.io/docs/concepts/workloads/pods/) and [init containers](https://kubernetes.io/docs/concepts/workloads/pods/init-containers/). + +### Pod affinity + +This chart allows you to set your custom affinity using the `affinity` parameter. Find more information about Pod affinity in the [kubernetes documentation](https://kubernetes.io/docs/concepts/configuration/assign-pod-node/#affinity-and-anti-affinity). + +As an alternative, use one of the preset configurations for pod affinity, pod anti-affinity, and node affinity available at the [bitnami/common](https://github.com/bitnami/charts/tree/main/bitnami/common#affinities) chart. To do so, set the `podAffinityPreset`, `podAntiAffinityPreset`, or `nodeAffinityPreset` parameters. + +### Backup and restore + +To back up and restore Helm chart deployments on Kubernetes, you need to back up the persistent volumes from the source deployment and attach them to a new deployment using [Velero](https://velero.io/), a Kubernetes backup/restore tool. Find the instructions for using Velero in [this guide](https://techdocs.broadcom.com/us/en/vmware-tanzu/application-catalog/tanzu-application-catalog/services/tac-doc/apps-tutorials-backup-restore-deployments-velero-index.html). + +## Persistence + +The [Bitnami KeyDB](https://github.com/bitnami/containers/tree/main/bitnami/keydb) image stores the KeyDB data and configurations at the `/bitnami/keydb/data` path of the container. Persistent Volume Claims are used to keep the data across deployments. + +If you encounter errors when working with persistent volumes, refer to our [troubleshooting guide for persistent volumes](https://docs.bitnami.com/kubernetes/faq/troubleshooting/troubleshooting-persistence-volumes/). + +## Parameters + +### Global parameters + +| Name | Description | Value | +| ----------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------- | +| `global.imageRegistry` | Global Docker image registry | `""` | +| `global.imagePullSecrets` | Global Docker registry secret names as an array | `[]` | +| `global.defaultStorageClass` | Global default StorageClass for Persistent Volume(s) | `""` | +| `global.keydb.password` | Global KeyDB password (overrides `auth.password`) | `""` | +| `global.security.allowInsecureImages` | Allows skipping image verification | `false` | +| `global.compatibility.openshift.adaptSecurityContext` | Adapt the securityContext sections of the deployment to make them compatible with Openshift restricted-v2 SCC: remove runAsUser, runAsGroup and fsGroup and let the platform use their allowed default IDs. Possible values: auto (apply if the detected running cluster is Openshift), force (perform the adaptation always), disabled (do not perform adaptation) | `auto` | + +### Common parameters + +| Name | Description | Value | +| ------------------------ | --------------------------------------------------------------------------------------- | --------------- | +| `kubeVersion` | Override Kubernetes version | `""` | +| `apiVersions` | Override Kubernetes API versions reported by .Capabilities | `[]` | +| `nameOverride` | String to partially override common.names.name | `""` | +| `fullnameOverride` | String to fully override common.names.fullname | `""` | +| `namespaceOverride` | String to fully override common.names.namespace | `""` | +| `commonLabels` | Labels to add to all deployed objects | `{}` | +| `commonAnnotations` | Annotations to add to all deployed objects | `{}` | +| `clusterDomain` | Kubernetes cluster domain name | `cluster.local` | +| `extraDeploy` | Array of extra objects to deploy with the release | `[]` | +| `diagnosticMode.enabled` | Enable diagnostic mode (all probes will be disabled and the command will be overridden) | `false` | +| `diagnosticMode.command` | Command to override all containers in the chart release | `["sleep"]` | +| `diagnosticMode.args` | Args to override all containers in the chart release | `["infinity"]` | + +### KeyDB Image parameters + +| Name | Description | Value | +| ------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------ | ----------------------- | +| `image.registry` | KeyDB image registry | `REGISTRY_NAME` | +| `image.repository` | KeyDB image repository | `REPOSITORY_NAME/keydb` | +| `image.digest` | KeyDB image digest in the way sha256:aa.... Please note this parameter, if set, will override the tag image tag (immutable tags are recommended) | `""` | +| `image.pullPolicy` | KeyDB image pull policy | `IfNotPresent` | +| `image.pullSecrets` | KeyDB image pull secrets | `[]` | +| `image.debug` | Enable KeyDB image debug mode | `false` | + +### KeyDB common configuration parameters + +| Name | Description | Value | +| -------------------------------------------------- | ------------------------------------------------------------------------------------------------------ | ------------- | +| `architecture` | KeyDB architecture. Allowed values: `standalone` or `replication` | `replication` | +| `auth.enabled` | Enable password authentication | `true` | +| `auth.password` | KeyDB password | `""` | +| `auth.existingSecret` | The name of an existing secret with KeyDB credentials | `""` | +| `auth.existingSecretPasswordKey` | Password key to be retrieved from existing secret | `""` | +| `auth.usePasswordFiles` | Mount credentials as files instead of using an environment variable | `true` | +| `tls.enabled` | Enable TLS communications | `false` | +| `tls.autoGenerated.enabled` | Enable automatic generation of certificates for TLS | `true` | +| `tls.autoGenerated.engine` | Mechanism to generate the certificates (allowed values: helm, cert-manager) | `helm` | +| `tls.autoGenerated.certManager.existingIssuer` | The name of an existing Issuer to use for generating the certificates (only for `cert-manager` engine) | `""` | +| `tls.autoGenerated.certManager.existingIssuerKind` | Existing Issuer kind, defaults to Issuer (only for `cert-manager` engine) | `""` | +| `tls.autoGenerated.certManager.keyAlgorithm` | Key algorithm for the certificates (only for `cert-manager` engine) | `RSA` | +| `tls.autoGenerated.certManager.keySize` | Key size for the certificates (only for `cert-manager` engine) | `2048` | +| `tls.autoGenerated.certManager.duration` | Duration for the certificates (only for `cert-manager` engine) | `2160h` | +| `tls.autoGenerated.certManager.renewBefore` | Renewal period for the certificates (only for `cert-manager` engine) | `360h` | +| `tls.ca` | CA certificate for TLS. Ignored if `tls.existingCASecret` is set | `""` | +| `tls.existingCASecret` | The name of an existing Secret containing the CA certificate for TLS | `""` | +| `tls.master.cert` | TLS certificate for KeyDB master nodes. Ignored if `tls.master.existingSecret` is set | `""` | +| `tls.master.key` | TLS key for KeyDB master nodes. Ignored if `tls.master.existingSecret` is set | `""` | +| `tls.master.existingSecret` | The name of an existing Secret containing the KeyDB master nodes certificates for TLS | `""` | +| `tls.replica.cert` | TLS certificate for KeyDB replica nodes. Ignored if `tls.replica.existingSecret` is set | `""` | +| `tls.replica.key` | TLS key for KeyDB replica nodes. Ignored if `tls.replica.existingSecret` is set | `""` | +| `tls.replica.existingSecret` | The name of an existing Secret containing the KeyDB replica nodes certificates for TLS | `""` | +| `commonConfiguration` | Common configuration to be added to both master and replica nodes | `""` | + +### KeyDB Master Configuration Parameters + +| Name | Description | Value | +| ---------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------ | +| `master.replicaCount` | Number of KeyDB master replicas to deploy | `1` | +| `master.containerPorts.keydb` | Container port to open on KeyDB master nodes | `6379` | +| `master.extraContainerPorts` | Optionally specify extra list of additional ports for KeyDB master containers | `[]` | +| `master.livenessProbe.enabled` | Enable livenessProbe on KeyDB master containers | `true` | +| `master.livenessProbe.initialDelaySeconds` | Initial delay seconds for livenessProbe | `20` | +| `master.livenessProbe.periodSeconds` | Period seconds for livenessProbe | `5` | +| `master.livenessProbe.timeoutSeconds` | Timeout seconds for livenessProbe | `5` | +| `master.livenessProbe.failureThreshold` | Failure threshold for livenessProbe | `5` | +| `master.livenessProbe.successThreshold` | Success threshold for livenessProbe | `1` | +| `master.readinessProbe.enabled` | Enable readinessProbe on KeyDB master containers | `true` | +| `master.readinessProbe.initialDelaySeconds` | Initial delay seconds for readinessProbe | `20` | +| `master.readinessProbe.periodSeconds` | Period seconds for readinessProbe | `5` | +| `master.readinessProbe.timeoutSeconds` | Timeout seconds for readinessProbe | `1` | +| `master.readinessProbe.failureThreshold` | Failure threshold for readinessProbe | `5` | +| `master.readinessProbe.successThreshold` | Success threshold for readinessProbe | `1` | +| `master.startupProbe.enabled` | Enable startupProbe on KeyDB master containers | `false` | +| `master.startupProbe.initialDelaySeconds` | Initial delay seconds for startupProbe | `20` | +| `master.startupProbe.periodSeconds` | Period seconds for startupProbe | `5` | +| `master.startupProbe.timeoutSeconds` | Timeout seconds for startupProbe | `5` | +| `master.startupProbe.failureThreshold` | Failure threshold for startupProbe | `5` | +| `master.startupProbe.successThreshold` | Success threshold for startupProbe | `1` | +| `master.customLivenessProbe` | Custom livenessProbe that overrides the default one | `{}` | +| `master.customReadinessProbe` | Custom readinessProbe that overrides the default one | `{}` | +| `master.customStartupProbe` | Custom startupProbe that overrides the default one | `{}` | +| `master.resourcesPreset` | Set KeyDB master container resources according to one common preset (allowed values: none, nano, small, medium, large, xlarge, 2xlarge). This is ignored if resources is set (resources is recommended for production). | `nano` | +| `master.resources` | Set KeyDB master container requests and limits for different resources like CPU or memory (essential for production workloads) | `{}` | +| `master.podSecurityContext.enabled` | Enable KeyDB master pods' Security Context | `true` | +| `master.podSecurityContext.fsGroupChangePolicy` | Set filesystem group change policy for KeyDB master pods | `Always` | +| `master.podSecurityContext.sysctls` | Set kernel settings using the sysctl interface for KeyDB master pods | `[]` | +| `master.podSecurityContext.supplementalGroups` | Set filesystem extra groups for KeyDB master pods | `[]` | +| `master.podSecurityContext.fsGroup` | Set fsGroup in KeyDB master pods' Security Context | `1001` | +| `master.containerSecurityContext.enabled` | Enabled KeyDB master container' Security Context | `true` | +| `master.containerSecurityContext.seLinuxOptions` | Set SELinux options in KeyDB master container | `{}` | +| `master.containerSecurityContext.runAsUser` | Set runAsUser in KeyDB master container' Security Context | `1001` | +| `master.containerSecurityContext.runAsGroup` | Set runAsGroup in KeyDB master container' Security Context | `1001` | +| `master.containerSecurityContext.runAsNonRoot` | Set runAsNonRoot in KeyDB master container' Security Context | `true` | +| `master.containerSecurityContext.readOnlyRootFilesystem` | Set readOnlyRootFilesystem in KeyDB master container' Security Context | `true` | +| `master.containerSecurityContext.privileged` | Set privileged in KeyDB master container' Security Context | `false` | +| `master.containerSecurityContext.allowPrivilegeEscalation` | Set allowPrivilegeEscalation in KeyDB master container' Security Context | `false` | +| `master.containerSecurityContext.capabilities.drop` | List of capabilities to be dropped in KeyDB master container | `["ALL"]` | +| `master.containerSecurityContext.seccompProfile.type` | Set seccomp profile in KeyDB master container | `RuntimeDefault` | +| `master.configuration` | Exclusive configuration for KeyDB master nodes (appended to common one) | `""` | +| `master.existingConfigmap` | The name of an existing ConfigMap with your custom configuration for KeyDB master | `""` | +| `master.disableCommands` | Array with KeyDB commands to disable on master nodes | `["FLUSHDB","FLUSHALL"]` | +| `master.command` | Override default KeyDB master container command (useful when using custom images) | `[]` | +| `master.args` | Override default KeyDB master container args (useful when using custom images) | `[]` | +| `master.automountServiceAccountToken` | Mount Service Account token in KeyDB master pods | `false` | +| `master.hostAliases` | KeyDB master pods host aliases | `[]` | +| `master.statefulsetAnnotations` | Annotations for KeyDB master statefulset | `{}` | +| `master.podLabels` | Extra labels for KeyDB master pods | `{}` | +| `master.podAnnotations` | Annotations for KeyDB master pods | `{}` | +| `master.podAffinityPreset` | Pod affinity preset. Ignored if `affinity` is set. Allowed values: `soft` or `hard` | `""` | +| `master.podAntiAffinityPreset` | Pod anti-affinity preset. Ignored if `affinity` is set. Allowed values: `soft` or `hard` | `soft` | +| `master.nodeAffinityPreset.type` | Node affinity preset type. Ignored if `affinity` is set. Allowed values: `soft` or `hard` | `""` | +| `master.nodeAffinityPreset.key` | Node label key to match. Ignored if `affinity` is set | `""` | +| `master.nodeAffinityPreset.values` | Node label values to match. Ignored if `affinity` is set | `[]` | +| `master.affinity` | Affinity for KeyDB master pods assignment | `{}` | +| `master.nodeSelector` | Node labels for KeyDB master pods assignment | `{}` | +| `master.tolerations` | Tolerations for KeyDB master pods assignment | `[]` | +| `master.updateStrategy.type` | KeyDB master strategy type | `RollingUpdate` | +| `master.priorityClassName` | KeyDB master pods' priorityClassName | `""` | +| `master.topologySpreadConstraints` | Topology Spread Constraints for KeyDB master pod assignment spread across your cluster among failure-domains | `[]` | +| `master.schedulerName` | Name of the k8s scheduler (other than default) for KeyDB master pods | `""` | +| `master.terminationGracePeriodSeconds` | Seconds KeyDB master pods need to terminate gracefully | `""` | +| `master.lifecycleHooks` | for KeyDB master containers to automate configuration before or after startup | `{}` | +| `master.extraEnvVars` | Array with extra environment variables to add to KeyDB master containers | `[]` | +| `master.extraEnvVarsCM` | Name of existing ConfigMap containing extra env vars for KeyDB master containers | `""` | +| `master.extraEnvVarsSecret` | Name of existing Secret containing extra env vars for KeyDB master containers | `""` | +| `master.extraVolumes` | Optionally specify extra list of additional volumes for the KeyDB master pods | `[]` | +| `master.extraVolumeMounts` | Optionally specify extra list of additional volumeMounts for the KeyDB master containers | `[]` | +| `master.sidecars` | Add additional sidecar containers to the KeyDB master pods | `[]` | +| `master.initContainers` | Add additional init containers to the KeyDB master pods | `[]` | +| `master.pdb.create` | Enable/disable a Pod Disruption Budget creation for KeyDB master pods | `true` | +| `master.pdb.minAvailable` | Minimum number/percentage of KeyDB master pods that should remain scheduled | `""` | +| `master.pdb.maxUnavailable` | Maximum number/percentage of KeyDB master pods that may be made unavailable. Defaults to `1` if both `pdb.minAvailable` and `pdb.maxUnavailable` are empty. | `""` | +| `master.autoscaling.vpa.enabled` | Enable VPA for KeyDB master pods | `false` | +| `master.autoscaling.vpa.annotations` | Annotations for VPA resource | `{}` | +| `master.autoscaling.vpa.controlledResources` | VPA List of resources that the vertical pod autoscaler can control. Defaults to cpu and memory | `[]` | +| `master.autoscaling.vpa.maxAllowed` | VPA Max allowed resources for the pod | `{}` | +| `master.autoscaling.vpa.minAllowed` | VPA Min allowed resources for the pod | `{}` | +| `master.autoscaling.vpa.updatePolicy.updateMode` | Autoscaling update policy | `Auto` | + +### KeyDB Master Persistence Parameters + +| Name | Description | Value | +| --------------------------------------------------------- | ---------------------------------------------------------------------------------- | --------------------- | +| `master.persistence.enabled` | Enable persistence using Persistent Volume Claims | `true` | +| `master.persistence.mountPath` | Path to mount the data volume at on KeyDB master containers | `/bitnami/keydb/data` | +| `master.persistence.subPath` | The subdirectory of the volume to mount on KeyDB master containers | `""` | +| `master.persistence.medium` | Provide a medium for `emptyDir` volumes | `""` | +| `master.persistence.sizeLimit` | Set this to enable a size limit for `emptyDir` volumes | `""` | +| `master.persistence.storageClass` | Storage class of backing PVC | `""` | +| `master.persistence.annotations` | Additional Persistent Volume Claim annotations | `{}` | +| `master.persistence.accessModes` | Persistent Volume Access Modes | `["ReadWriteOnce"]` | +| `master.persistence.size` | Size of data volume | `8Gi` | +| `master.persistence.selector` | Selector to match an existing Persistent Volume for WordPress data PVC | `{}` | +| `master.persistence.dataSource` | Custom PVC data source | `{}` | +| `master.persistence.existingClaim` | The name of an existing PVC to use for persistence (only if master.replicaCount=1) | `""` | +| `master.persistentVolumeClaimRetentionPolicy.enabled` | Controls if and how PVCs are deleted during the lifecycle of a StatefulSet | `false` | +| `master.persistentVolumeClaimRetentionPolicy.whenScaled` | Volume retention behavior when the replica count of the StatefulSet is reduced | `Retain` | +| `master.persistentVolumeClaimRetentionPolicy.whenDeleted` | Volume retention behavior that applies when the StatefulSet is deleted | `Retain` | + +### KeyDB Master Traffic Exposure Parameters + +| Name | Description | Value | +| ---------------------------------------------- | ------------------------------------------------------------------------------------------------------------- | ----------- | +| `master.service.type` | KeyDB master service type | `ClusterIP` | +| `master.service.ports.keydb` | KeyDB master service port | `6379` | +| `master.service.nodePorts.keydb` | Node port for KeyDB master | `""` | +| `master.service.clusterIP` | KeyDB master service Cluster IP | `""` | +| `master.service.loadBalancerIP` | KeyDB master service Load Balancer IP | `""` | +| `master.service.loadBalancerSourceRanges` | KeyDB master service Load Balancer sources | `[]` | +| `master.service.externalTrafficPolicy` | KeyDB master service external traffic policy | `Cluster` | +| `master.service.annotations` | Additional custom annotations for KeyDB master service | `{}` | +| `master.service.extraPorts` | Extra ports to expose in KeyDB master service (normally used with the `sidecars` value) | `[]` | +| `master.service.sessionAffinity` | Control where client requests go, to the same pod or round-robin | `None` | +| `master.service.sessionAffinityConfig` | Additional settings for the sessionAffinity | `{}` | +| `master.service.headless.annotations` | Annotations for the headless service. | `{}` | +| `master.networkPolicy.enabled` | Specifies whether a NetworkPolicy should be created for KeyDB master | `true` | +| `master.networkPolicy.allowExternal` | Don't require server label for connections | `true` | +| `master.networkPolicy.allowExternalEgress` | Allow the pod to access any range of port and all destinations. | `true` | +| `master.networkPolicy.addExternalClientAccess` | Allow access from pods with client label set to "true". Ignored if `networkPolicy.allowExternal` is true. | `true` | +| `master.networkPolicy.extraIngress` | Add extra ingress rules to the NetworkPolicy | `[]` | +| `master.networkPolicy.extraEgress` | Add extra ingress rules to the NetworkPolicy (ignored if allowExternalEgress=true) | `[]` | +| `master.networkPolicy.ingressPodMatchLabels` | Labels to match to allow traffic from other pods. Ignored if `networkPolicy.allowExternal` is true. | `{}` | +| `master.networkPolicy.ingressNSMatchLabels` | Labels to match to allow traffic from other namespaces. Ignored if `networkPolicy.allowExternal` is true. | `{}` | +| `master.networkPolicy.ingressNSPodMatchLabels` | Pod labels to match to allow traffic from other namespaces. Ignored if `networkPolicy.allowExternal` is true. | `{}` | + +### KeyDB Replicas Configuration Parameters + +| Name | Description | Value | +| ----------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------ | +| `replica.replicaCount` | Number of KeyDB replicas to deploy | `1` | +| `replica.containerPorts.keydb` | Container port to open on KeyDB replicas nodes | `6379` | +| `replica.extraContainerPorts` | Optionally specify extra list of additional ports for KeyDB replicas containers | `[]` | +| `replica.livenessProbe.enabled` | Enable livenessProbe on KeyDB replicas containers | `true` | +| `replica.livenessProbe.initialDelaySeconds` | Initial delay seconds for livenessProbe | `20` | +| `replica.livenessProbe.periodSeconds` | Period seconds for livenessProbe | `5` | +| `replica.livenessProbe.timeoutSeconds` | Timeout seconds for livenessProbe | `5` | +| `replica.livenessProbe.failureThreshold` | Failure threshold for livenessProbe | `5` | +| `replica.livenessProbe.successThreshold` | Success threshold for livenessProbe | `1` | +| `replica.readinessProbe.enabled` | Enable readinessProbe on KeyDB replicas containers | `true` | +| `replica.readinessProbe.initialDelaySeconds` | Initial delay seconds for readinessProbe | `20` | +| `replica.readinessProbe.periodSeconds` | Period seconds for readinessProbe | `5` | +| `replica.readinessProbe.timeoutSeconds` | Timeout seconds for readinessProbe | `1` | +| `replica.readinessProbe.failureThreshold` | Failure threshold for readinessProbe | `5` | +| `replica.readinessProbe.successThreshold` | Success threshold for readinessProbe | `1` | +| `replica.startupProbe.enabled` | Enable startupProbe on KeyDB replicas containers | `false` | +| `replica.startupProbe.initialDelaySeconds` | Initial delay seconds for startupProbe | `20` | +| `replica.startupProbe.periodSeconds` | Period seconds for startupProbe | `5` | +| `replica.startupProbe.timeoutSeconds` | Timeout seconds for startupProbe | `5` | +| `replica.startupProbe.failureThreshold` | Failure threshold for startupProbe | `5` | +| `replica.startupProbe.successThreshold` | Success threshold for startupProbe | `1` | +| `replica.customLivenessProbe` | Custom livenessProbe that overrides the default one | `{}` | +| `replica.customReadinessProbe` | Custom readinessProbe that overrides the default one | `{}` | +| `replica.customStartupProbe` | Custom startupProbe that overrides the default one | `{}` | +| `replica.resourcesPreset` | Set KeyDB replicas container resources according to one common preset (allowed values: none, nano, small, medium, large, xlarge, 2xlarge). This is ignored if resources is set (resources is recommended for production). | `nano` | +| `replica.resources` | Set KeyDB replicas container requests and limits for different resources like CPU or memory (essential for production workloads) | `{}` | +| `replica.podSecurityContext.enabled` | Enable KeyDB replicas pods' Security Context | `true` | +| `replica.podSecurityContext.fsGroupChangePolicy` | Set filesystem group change policy for KeyDB replicas pods | `Always` | +| `replica.podSecurityContext.sysctls` | Set kernel settings using the sysctl interface for KeyDB replicas pods | `[]` | +| `replica.podSecurityContext.supplementalGroups` | Set filesystem extra groups for KeyDB replicas pods | `[]` | +| `replica.podSecurityContext.fsGroup` | Set fsGroup in KeyDB replicas pods' Security Context | `1001` | +| `replica.containerSecurityContext.enabled` | Enabled KeyDB replicas container' Security Context | `true` | +| `replica.containerSecurityContext.seLinuxOptions` | Set SELinux options in KeyDB replicas container | `{}` | +| `replica.containerSecurityContext.runAsUser` | Set runAsUser in KeyDB replicas container' Security Context | `1001` | +| `replica.containerSecurityContext.runAsGroup` | Set runAsGroup in KeyDB replicas container' Security Context | `1001` | +| `replica.containerSecurityContext.runAsNonRoot` | Set runAsNonRoot in KeyDB replicas container' Security Context | `true` | +| `replica.containerSecurityContext.readOnlyRootFilesystem` | Set readOnlyRootFilesystem in KeyDB replicas container' Security Context | `true` | +| `replica.containerSecurityContext.privileged` | Set privileged in KeyDB replicas container' Security Context | `false` | +| `replica.containerSecurityContext.allowPrivilegeEscalation` | Set allowPrivilegeEscalation in KeyDB replicas container' Security Context | `false` | +| `replica.containerSecurityContext.capabilities.drop` | List of capabilities to be dropped in KeyDB replicas container | `["ALL"]` | +| `replica.containerSecurityContext.seccompProfile.type` | Set seccomp profile in KeyDB replicas container | `RuntimeDefault` | +| `replica.activeReplica` | Configure replica as an active replica | `false` | +| `replica.configuration` | Exclusive configuration for KeyDB replicas nodes (appended to common one) | `""` | +| `replica.existingConfigmap` | The name of an existing ConfigMap with your custom configuration for KeyDB replicas | `""` | +| `replica.disableCommands` | Array with KeyDB commands to disable on master nodes | `["FLUSHDB","FLUSHALL"]` | +| `replica.command` | Override default KeyDB replicas container command (useful when using custom images) | `[]` | +| `replica.args` | Override default KeyDB replicas container args (useful when using custom images) | `[]` | +| `replica.automountServiceAccountToken` | Mount Service Account token in KeyDB replicas pods | `false` | +| `replica.hostAliases` | KeyDB replicas pods host aliases | `[]` | +| `replica.statefulsetAnnotations` | Annotations for KeyDB replicas statefulset | `{}` | +| `replica.podLabels` | Extra labels for KeyDB replicas pods | `{}` | +| `replica.podAnnotations` | Annotations for KeyDB replicas pods | `{}` | +| `replica.podAffinityPreset` | Pod affinity preset. Ignored if `affinity` is set. Allowed values: `soft` or `hard` | `""` | +| `replica.podAntiAffinityPreset` | Pod anti-affinity preset. Ignored if `affinity` is set. Allowed values: `soft` or `hard` | `soft` | +| `replica.nodeAffinityPreset.type` | Node affinity preset type. Ignored if `affinity` is set. Allowed values: `soft` or `hard` | `""` | +| `replica.nodeAffinityPreset.key` | Node label key to match. Ignored if `affinity` is set | `""` | +| `replica.nodeAffinityPreset.values` | Node label values to match. Ignored if `affinity` is set | `[]` | +| `replica.affinity` | Affinity for KeyDB replicas pods assignment | `{}` | +| `replica.nodeSelector` | Node labels for KeyDB replicas pods assignment | `{}` | +| `replica.tolerations` | Tolerations for KeyDB replicas pods assignment | `[]` | +| `replica.updateStrategy.type` | KeyDB replicas strategy type | `RollingUpdate` | +| `replica.priorityClassName` | KeyDB replicas pods' priorityClassName | `""` | +| `replica.topologySpreadConstraints` | Topology Spread Constraints for KeyDB replicas pod assignment spread across your cluster among failure-domains | `[]` | +| `replica.schedulerName` | Name of the k8s scheduler (other than default) for KeyDB replicas pods | `""` | +| `replica.terminationGracePeriodSeconds` | Seconds KeyDB replicas pods need to terminate gracefully | `""` | +| `replica.lifecycleHooks` | for KeyDB replicas containers to automate configuration before or after startup | `{}` | +| `replica.extraEnvVars` | Array with extra environment variables to add to KeyDB replicas containers | `[]` | +| `replica.extraEnvVarsCM` | Name of existing ConfigMap containing extra env vars for KeyDB replicas containers | `""` | +| `replica.extraEnvVarsSecret` | Name of existing Secret containing extra env vars for KeyDB replicas containers | `""` | +| `replica.extraVolumes` | Optionally specify extra list of additional volumes for the KeyDB replicas pods | `[]` | +| `replica.extraVolumeMounts` | Optionally specify extra list of additional volumeMounts for the KeyDB replicas containers | `[]` | +| `replica.sidecars` | Add additional sidecar containers to the KeyDB replicas pods | `[]` | +| `replica.initContainers` | Add additional init containers to the KeyDB replicas pods | `[]` | +| `replica.pdb.create` | Enable/disable a Pod Disruption Budget creation for KeyDB replicas pods | `true` | +| `replica.pdb.minAvailable` | Minimum number/percentage of KeyDB replicas pods that should remain scheduled | `""` | +| `replica.pdb.maxUnavailable` | Maximum number/percentage of KeyDB replicas pods that may be made unavailable. Defaults to `1` if both `pdb.minAvailable` and `pdb.maxUnavailable` are empty. | `""` | +| `replica.autoscaling.vpa.enabled` | Enable VPA for KeyDB replicas pods | `false` | +| `replica.autoscaling.vpa.annotations` | Annotations for VPA resource | `{}` | +| `replica.autoscaling.vpa.controlledResources` | VPA List of resources that the vertical pod autoscaler can control. Defaults to cpu and memory | `[]` | +| `replica.autoscaling.vpa.maxAllowed` | VPA Max allowed resources for the pod | `{}` | +| `replica.autoscaling.vpa.minAllowed` | VPA Min allowed resources for the pod | `{}` | +| `replica.autoscaling.vpa.updatePolicy.updateMode` | Autoscaling update policy | `Auto` | +| `replica.autoscaling.hpa.enabled` | Enable HPA for KeyDB Replicas pods | `false` | +| `replica.autoscaling.hpa.minReplicas` | Minimum number of replicas | `""` | +| `replica.autoscaling.hpa.maxReplicas` | Maximum number of replicas | `""` | +| `replica.autoscaling.hpa.targetCPU` | Target CPU utilization percentage | `""` | +| `replica.autoscaling.hpa.targetMemory` | Target Memory utilization percentage | `""` | + +### KeyDB Replicas Persistence Parameters + +| Name | Description | Value | +| ---------------------------------------------------------- | ----------------------------------------------------------------------------------- | --------------------- | +| `replica.persistence.enabled` | Enable persistence using Persistent Volume Claims | `true` | +| `replica.persistence.mountPath` | Path to mount the data volume at on KeyDB replicas containers | `/bitnami/keydb/data` | +| `replica.persistence.subPath` | The subdirectory of the volume to mount on KeyDB replicas containers | `""` | +| `replica.persistence.medium` | Provide a medium for `emptyDir` volumes | `""` | +| `replica.persistence.sizeLimit` | Set this to enable a size limit for `emptyDir` volumes | `""` | +| `replica.persistence.storageClass` | Storage class of backing PVC | `""` | +| `replica.persistence.annotations` | Additional Persistent Volume Claim annotations | `{}` | +| `replica.persistence.accessModes` | Persistent Volume Access Modes | `["ReadWriteOnce"]` | +| `replica.persistence.size` | Size of data volume | `8Gi` | +| `replica.persistence.selector` | Selector to match an existing Persistent Volume for WordPress data PVC | `{}` | +| `replica.persistence.dataSource` | Custom PVC data source | `{}` | +| `replica.persistence.existingClaim` | The name of an existing PVC to use for persistence (only if replica.replicaCount=1) | `""` | +| `replica.persistentVolumeClaimRetentionPolicy.enabled` | Controls if and how PVCs are deleted during the lifecycle of a StatefulSet | `false` | +| `replica.persistentVolumeClaimRetentionPolicy.whenScaled` | Volume retention behavior when the replica count of the StatefulSet is reduced | `Retain` | +| `replica.persistentVolumeClaimRetentionPolicy.whenDeleted` | Volume retention behavior that applies when the StatefulSet is deleted | `Retain` | + +### KeyDB Replicas Traffic Exposure Parameters + +| Name | Description | Value | +| ----------------------------------------------- | ------------------------------------------------------------------------------------------------------------- | ----------- | +| `replica.service.type` | KeyDB replicas service type | `ClusterIP` | +| `replica.service.ports.keydb` | KeyDB replicas service port | `6379` | +| `replica.service.nodePorts.keydb` | Node port for KeyDB replicas | `""` | +| `replica.service.clusterIP` | KeyDB replicas service Cluster IP | `""` | +| `replica.service.loadBalancerIP` | KeyDB replicas service Load Balancer IP | `""` | +| `replica.service.loadBalancerSourceRanges` | KeyDB replicas service Load Balancer sources | `[]` | +| `replica.service.externalTrafficPolicy` | KeyDB replicas service external traffic policy | `Cluster` | +| `replica.service.annotations` | Additional custom annotations for KeyDB replicas service | `{}` | +| `replica.service.extraPorts` | Extra ports to expose in KeyDB replicas service (normally used with the `sidecars` value) | `[]` | +| `replica.service.sessionAffinity` | Control where client requests go, to the same pod or round-robin | `None` | +| `replica.service.sessionAffinityConfig` | Additional settings for the sessionAffinity | `{}` | +| `replica.service.headless.annotations` | Annotations for the headless service. | `{}` | +| `replica.networkPolicy.enabled` | Specifies whether a NetworkPolicy should be created for KeyDB replicas | `true` | +| `replica.networkPolicy.allowExternal` | Don't require server label for connections | `true` | +| `replica.networkPolicy.allowExternalEgress` | Allow the pod to access any range of port and all destinations. | `true` | +| `replica.networkPolicy.addExternalClientAccess` | Allow access from pods with client label set to "true". Ignored if `networkPolicy.allowExternal` is true. | `true` | +| `replica.networkPolicy.extraIngress` | Add extra ingress rules to the NetworkPolicy | `[]` | +| `replica.networkPolicy.extraEgress` | Add extra ingress rules to the NetworkPolicy (ignored if allowExternalEgress=true) | `[]` | +| `replica.networkPolicy.ingressPodMatchLabels` | Labels to match to allow traffic from other pods. Ignored if `networkPolicy.allowExternal` is true. | `{}` | +| `replica.networkPolicy.ingressNSMatchLabels` | Labels to match to allow traffic from other namespaces. Ignored if `networkPolicy.allowExternal` is true. | `{}` | +| `replica.networkPolicy.ingressNSPodMatchLabels` | Pod labels to match to allow traffic from other namespaces. Ignored if `networkPolicy.allowExternal` is true. | `{}` | + +### Metrics Parameters + +| Name | Description | Value | +| ----------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------------------------------- | +| `metrics.enabled` | Start a sidecar Prometheus exporter to expose KeyDB metrics | `false` | +| `metrics.image.registry` | Redis Exporter image registry | `REGISTRY_NAME` | +| `metrics.image.repository` | Redis Exporter image repository | `REPOSITORY_NAME/redis-exporter` | +| `metrics.image.digest` | Redis Exporter image digest in the way sha256:aa.... Please note this parameter, if set, will override the tag | `""` | +| `metrics.image.pullPolicy` | Redis Exporter image pull policy | `IfNotPresent` | +| `metrics.image.pullSecrets` | Redis Exporter image pull secrets | `[]` | +| `metrics.containerPorts.http` | Metrics HTTP container port | `9121` | +| `metrics.startupProbe.enabled` | Enable startupProbe on KeyDB replicas nodes | `false` | +| `metrics.startupProbe.initialDelaySeconds` | Initial delay seconds for startupProbe | `10` | +| `metrics.startupProbe.periodSeconds` | Period seconds for startupProbe | `10` | +| `metrics.startupProbe.timeoutSeconds` | Timeout seconds for startupProbe | `5` | +| `metrics.startupProbe.failureThreshold` | Failure threshold for startupProbe | `5` | +| `metrics.startupProbe.successThreshold` | Success threshold for startupProbe | `1` | +| `metrics.livenessProbe.enabled` | Enable livenessProbe on KeyDB replicas nodes | `true` | +| `metrics.livenessProbe.initialDelaySeconds` | Initial delay seconds for livenessProbe | `10` | +| `metrics.livenessProbe.periodSeconds` | Period seconds for livenessProbe | `10` | +| `metrics.livenessProbe.timeoutSeconds` | Timeout seconds for livenessProbe | `5` | +| `metrics.livenessProbe.failureThreshold` | Failure threshold for livenessProbe | `5` | +| `metrics.livenessProbe.successThreshold` | Success threshold for livenessProbe | `1` | +| `metrics.readinessProbe.enabled` | Enable readinessProbe on KeyDB replicas nodes | `true` | +| `metrics.readinessProbe.initialDelaySeconds` | Initial delay seconds for readinessProbe | `5` | +| `metrics.readinessProbe.periodSeconds` | Period seconds for readinessProbe | `10` | +| `metrics.readinessProbe.timeoutSeconds` | Timeout seconds for readinessProbe | `1` | +| `metrics.readinessProbe.failureThreshold` | Failure threshold for readinessProbe | `3` | +| `metrics.readinessProbe.successThreshold` | Success threshold for readinessProbe | `1` | +| `metrics.customStartupProbe` | Custom startupProbe that overrides the default one | `{}` | +| `metrics.customLivenessProbe` | Custom livenessProbe that overrides the default one | `{}` | +| `metrics.customReadinessProbe` | Custom readinessProbe that overrides the default one | `{}` | +| `metrics.command` | Override default metrics container init command (useful when using custom images) | `[]` | +| `metrics.keydbHost` | A way to specify an alternative KeyDB hostname | `localhost` | +| `metrics.extraArgs` | Extra arguments for KeyDB metrics exporter, for example: | `{}` | +| `metrics.extraEnvVars` | Array with extra environment variables to add to KeyDB metrics exporter | `[]` | +| `metrics.containerSecurityContext.enabled` | Enabled KeyDB metrics exporter containers' Security Context | `true` | +| `metrics.containerSecurityContext.seLinuxOptions` | Set SELinux options in container | `{}` | +| `metrics.containerSecurityContext.runAsUser` | Set KeyDB metrics exporter containers' Security Context runAsUser | `1001` | +| `metrics.containerSecurityContext.runAsGroup` | Set KeyDB metrics exporter containers' Security Context runAsGroup | `1001` | +| `metrics.containerSecurityContext.runAsNonRoot` | Set KeyDB metrics exporter containers' Security Context runAsNonRoot | `true` | +| `metrics.containerSecurityContext.allowPrivilegeEscalation` | Set KeyDB metrics exporter containers' Security Context allowPrivilegeEscalation | `false` | +| `metrics.containerSecurityContext.readOnlyRootFilesystem` | Set container's Security Context read-only root filesystem | `true` | +| `metrics.containerSecurityContext.seccompProfile.type` | Set KeyDB metrics exporter containers' Security Context seccompProfile | `RuntimeDefault` | +| `metrics.containerSecurityContext.capabilities.drop` | Set KeyDB metrics exporter containers' Security Context capabilities to drop | `["ALL"]` | +| `metrics.extraVolumeMounts` | Optionally specify extra list of additional volumeMounts for the KeyDB metrics sidecar | `[]` | +| `metrics.resourcesPreset` | Set container resources according to one common preset (allowed values: none, nano, micro, small, medium, large, xlarge, 2xlarge). This is ignored if metrics.resources is set (metrics.resources is recommended for production). | `nano` | +| `metrics.resources` | Set container requests and limits for different resources like CPU or memory (essential for production workloads) | `{}` | +| `metrics.podLabels` | Extra labels for KeyDB metrics exporter pods | `{}` | +| `metrics.podAnnotations` | Annotations for KeyDB metrics exporter pods | `{}` | +| `metrics.service.port` | Metrics service port | `9121` | +| `metrics.service.annotations` | Annotations for the metrics service | `{}` | +| `metrics.serviceMonitor.enabled` | if `true`, creates a Prometheus Operator ServiceMonitor (also requires `metrics.enabled` to be `true`) | `false` | +| `metrics.serviceMonitor.namespace` | Namespace in which Prometheus is running | `""` | +| `metrics.serviceMonitor.annotations` | Additional custom annotations for the ServiceMonitor | `{}` | +| `metrics.serviceMonitor.labels` | Extra labels for the ServiceMonitor | `{}` | +| `metrics.serviceMonitor.jobLabel` | The name of the label on the target service to use as the job name in Prometheus | `""` | +| `metrics.serviceMonitor.honorLabels` | honorLabels chooses the metric's labels on collisions with target labels | `false` | +| `metrics.serviceMonitor.interval` | Interval at which metrics should be scraped. | `""` | +| `metrics.serviceMonitor.scrapeTimeout` | Timeout after which the scrape is ended | `""` | +| `metrics.serviceMonitor.metricRelabelings` | Specify additional relabeling of metrics | `[]` | +| `metrics.serviceMonitor.relabelings` | Specify general relabeling | `[]` | +| `metrics.serviceMonitor.selector` | Prometheus instance selector labels | `{}` | +| `metrics.prometheusRule.enabled` | Create a custom prometheusRule Resource for scraping metrics using PrometheusOperator | `false` | +| `metrics.prometheusRule.namespace` | The namespace in which the prometheusRule will be created | `""` | +| `metrics.prometheusRule.annotations` | Additional custom annotations for the prometheusRule | `{}` | +| `metrics.prometheusRule.labels` | Extra labels for the prometheusRule | `{}` | +| `metrics.prometheusRule.rules` | Custom Prometheus rules | `[]` | + +### Other Parameters + +| Name | Description | Value | +| --------------------------------------------- | ---------------------------------------------------------------------------- | ------ | +| `serviceAccount.create` | Specifies whether a ServiceAccount should be created for KeyDB replicas pods | `true` | +| `serviceAccount.name` | The name of the ServiceAccount to use | `""` | +| `serviceAccount.annotations` | Additional Service Account annotations (evaluated as a template) | `{}` | +| `serviceAccount.automountServiceAccountToken` | Automount service account token for the server service account | `true` | + +### Init Container Parameters + +| Name | Description | Value | +| ----------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------------------------- | +| `volumePermissions.enabled` | Enable init container that changes the owner/group of the PV mount point to `runAsUser:fsGroup` | `false` | +| `volumePermissions.image.registry` | OS Shell + Utility image registry | `REGISTRY_NAME` | +| `volumePermissions.image.repository` | OS Shell + Utility image repository | `REPOSITORY_NAME/os-shell` | +| `volumePermissions.image.pullPolicy` | OS Shell + Utility image pull policy | `IfNotPresent` | +| `volumePermissions.image.pullSecrets` | OS Shell + Utility image pull secrets | `[]` | +| `volumePermissions.resourcesPreset` | Set init container resources according to one common preset (allowed values: none, nano, small, medium, large, xlarge, 2xlarge). This is ignored if volumePermissions.resources is set (volumePermissions.resources is recommended for production). | `nano` | +| `volumePermissions.resources` | Set init container requests and limits for different resources like CPU or memory (essential for production workloads) | `{}` | +| `volumePermissions.containerSecurityContext.enabled` | Enabled init container' Security Context | `true` | +| `volumePermissions.containerSecurityContext.seLinuxOptions` | Set SELinux options in init container | `{}` | +| `volumePermissions.containerSecurityContext.runAsUser` | Set init container's Security Context runAsUser | `0` | + +The above parameters map to the env variables defined in [bitnami/keydb](https://github.com/bitnami/containers/tree/main/bitnami/keydb). For more information please refer to the [bitnami/keydb](https://github.com/bitnami/containers/tree/main/bitnami/keydb) image documentation. + +Specify each parameter using the `--set key=value[,key=value]` argument to `helm install`. For example, + +```console +helm install my-release \ + --set auth.enabled=true \ + --set auth.password=secretpassword \ + oci://REGISTRY_NAME/REPOSITORY_NAME/keydb +``` + +> Note: You need to substitute the placeholders `REGISTRY_NAME` and `REPOSITORY_NAME` with a reference to your Helm chart registry and repository. For example, in the case of Bitnami, you need to use `REGISTRY_NAME=registry-1.docker.io` and `REPOSITORY_NAME=bitnamicharts`. + +The above command sets the KeyDB server password to `secretpassword`. + +> NOTE: Once this chart is deployed, it is not possible to change the application's access credentials, such as usernames or passwords, using Helm. To change these application credentials after deployment, delete any persistent volumes (PVs) used by the chart and re-deploy it, or use the application's built-in administrative tools if available. + +Alternatively, a YAML file that specifies the values for the parameters can be provided while installing the chart. For example, + +```console +helm install my-release -f values.yaml oci://REGISTRY_NAME/REPOSITORY_NAME/keydb +``` + +> Note: You need to substitute the placeholders `REGISTRY_NAME` and `REPOSITORY_NAME` with a reference to your Helm chart registry and repository. For example, in the case of Bitnami, you need to use `REGISTRY_NAME=registry-1.docker.io` and `REPOSITORY_NAME=bitnamicharts`. +> **Tip**: You can use the default [values.yaml](https://github.com/bitnami/charts/tree/main/bitnami/keydb/values.yaml) + +## Troubleshooting + +Find more information about how to deal with common errors related to Bitnami's Helm charts in [this troubleshooting guide](https://docs.bitnami.com/general/how-to/troubleshoot-helm-chart-issues). + +## License + +Copyright © 2025 Broadcom. The term "Broadcom" refers to Broadcom Inc. and/or its subsidiaries. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. \ No newline at end of file diff --git a/helm-charts/keydb/charts/common/.helmignore b/helm-charts/keydb/charts/common/.helmignore new file mode 100644 index 0000000..d0e1084 --- /dev/null +++ b/helm-charts/keydb/charts/common/.helmignore @@ -0,0 +1,26 @@ +# 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 +*~ +# Various IDEs +.project +.idea/ +*.tmproj +.vscode/ +# img folder +img/ +# Changelog +CHANGELOG.md diff --git a/helm-charts/keydb/charts/common/Chart.yaml b/helm-charts/keydb/charts/common/Chart.yaml new file mode 100644 index 0000000..fb04f76 --- /dev/null +++ b/helm-charts/keydb/charts/common/Chart.yaml @@ -0,0 +1,23 @@ +annotations: + category: Infrastructure + licenses: Apache-2.0 +apiVersion: v2 +appVersion: 2.31.4 +description: A Library Helm Chart for grouping common logic between bitnami charts. + This chart is not deployable by itself. +home: https://bitnami.com +icon: https://dyltqmyl993wv.cloudfront.net/downloads/logos/bitnami-mark.png +keywords: +- common +- helper +- template +- function +- bitnami +maintainers: +- name: Broadcom, Inc. All Rights Reserved. + url: https://github.com/bitnami/charts +name: common +sources: +- https://github.com/bitnami/charts/tree/main/bitnami/common +type: library +version: 2.31.4 diff --git a/helm-charts/keydb/charts/common/README.md b/helm-charts/keydb/charts/common/README.md new file mode 100644 index 0000000..71368aa --- /dev/null +++ b/helm-charts/keydb/charts/common/README.md @@ -0,0 +1,387 @@ +# Bitnami Common Library Chart + +A [Helm Library Chart](https://helm.sh/docs/topics/library_charts/#helm) for grouping common logic between Bitnami charts. + +## TL;DR + +```yaml +dependencies: + - name: common + version: 2.x.x + repository: oci://registry-1.docker.io/bitnamicharts +``` + +```console +helm dependency update +``` + +```yaml +apiVersion: v1 +kind: ConfigMap +metadata: + name: {{ include "common.names.fullname" . }} +data: + myvalue: "Hello World" +``` + +Looking to use our applications in production? Try [VMware Tanzu Application Catalog](https://bitnami.com/enterprise), the commercial edition of the Bitnami catalog. + +## ⚠️ Important Notice: Upcoming changes to the Bitnami Catalog + +Beginning August 28th, 2025, Bitnami will evolve its public catalog to offer a curated set of hardened, security-focused images under the new [Bitnami Secure Images initiative](https://news.broadcom.com/app-dev/broadcom-introduces-bitnami-secure-images-for-production-ready-containerized-applications). As part of this transition: + +- Granting community users access for the first time to security-optimized versions of popular container images. +- Bitnami will begin deprecating support for non-hardened, Debian-based software images in its free tier and will gradually remove non-latest tags from the public catalog. As a result, community users will have access to a reduced number of hardened images. These images are published only under the “latest” tag and are intended for development purposes +- Starting August 28th, over two weeks, all existing container images, including older or versioned tags (e.g., 2.50.0, 10.6), will be migrated from the public catalog (docker.io/bitnami) to the “Bitnami Legacy” repository (docker.io/bitnamilegacy), where they will no longer receive updates. +- For production workloads and long-term support, users are encouraged to adopt Bitnami Secure Images, which include hardened containers, smaller attack surfaces, CVE transparency (via VEX/KEV), SBOMs, and enterprise support. + +These changes aim to improve the security posture of all Bitnami users by promoting best practices for software supply chain integrity and up-to-date deployments. For more details, visit the [Bitnami Secure Images announcement](https://github.com/bitnami/containers/issues/83267). + +## Introduction + +This chart provides a common template helpers which can be used to develop new charts using [Helm](https://helm.sh) package manager. + +## Prerequisites + +- Kubernetes 1.23+ +- Helm 3.8.0+ + +## Parameters + +The following table lists the helpers available in the library which are scoped in different sections. + +### Affinities + +| Helper identifier | Description | Expected Input | +| ------------------------------- | ---------------------------------------------------- | ------------------------------------------------------------ | +| `common.affinities.nodes.soft` | Return a soft nodeAffinity definition | `dict "key" "FOO" "values" (list "BAR" "BAZ")` | +| `common.affinities.nodes.hard` | Return a hard nodeAffinity definition | `dict "key" "FOO" "values" (list "BAR" "BAZ")` | +| `common.affinities.nodes` | Return a nodeAffinity definition | `dict "type" "soft" "key" "FOO" "values" (list "BAR" "BAZ")` | +| `common.affinities.topologyKey` | Return a topologyKey definition | `dict "topologyKey" "FOO"` | +| `common.affinities.pods.soft` | Return a soft podAffinity/podAntiAffinity definition | `dict "component" "FOO" "context" $` | +| `common.affinities.pods.hard` | Return a hard podAffinity/podAntiAffinity definition | `dict "component" "FOO" "context" $` | +| `common.affinities.pods` | Return a podAffinity/podAntiAffinity definition | `dict "type" "soft" "key" "FOO" "values" (list "BAR" "BAZ")` | + +### Capabilities + +| Helper identifier | Description | Expected Input | +| --------------------------------------------------------- | ---------------------------------------------------------------------------------------------- | --------------------------------------- | +| `common.capabilities.kubeVersion` | Return the target Kubernetes version (using client default if .Values.kubeVersion is not set). | `.` Chart context | +| `common.capabilities.apiVersions.has` | Return true if the apiVersion is supported | `dict "version" "batch/v1" "context" $` | +| `common.capabilities.job.apiVersion` | Return the appropriate apiVersion for job. | `.` Chart context | +| `common.capabilities.cronjob.apiVersion` | Return the appropriate apiVersion for cronjob. | `.` Chart context | +| `common.capabilities.daemonset.apiVersion` | Return the appropriate apiVersion for daemonset. | `.` Chart context | +| `common.capabilities.deployment.apiVersion` | Return the appropriate apiVersion for deployment. | `.` Chart context | +| `common.capabilities.statefulset.apiVersion` | Return the appropriate apiVersion for statefulset. | `.` Chart context | +| `common.capabilities.ingress.apiVersion` | Return the appropriate apiVersion for ingress. | `.` Chart context | +| `common.capabilities.rbac.apiVersion` | Return the appropriate apiVersion for RBAC resources. | `.` Chart context | +| `common.capabilities.crd.apiVersion` | Return the appropriate apiVersion for CRDs. | `.` Chart context | +| `common.capabilities.policy.apiVersion` | Return the appropriate apiVersion for podsecuritypolicy. | `.` Chart context | +| `common.capabilities.networkPolicy.apiVersion` | Return the appropriate apiVersion for networkpolicy. | `.` Chart context | +| `common.capabilities.apiService.apiVersion` | Return the appropriate apiVersion for APIService. | `.` Chart context | +| `common.capabilities.hpa.apiVersion` | Return the appropriate apiVersion for Horizontal Pod Autoscaler | `.` Chart context | +| `common.capabilities.vpa.apiVersion` | Return the appropriate apiVersion for Vertical Pod Autoscaler. | `.` Chart context | +| `common.capabilities.psp.supported` | Returns true if PodSecurityPolicy is supported | `.` Chart context | +| `common.capabilities.supportsHelmVersion` | Returns true if the used Helm version is 3.3+ | `.` Chart context | +| `common.capabilities.admissionConfiguration.supported` | Returns true if AdmissionConfiguration is supported | `.` Chart context | +| `common.capabilities.admissionConfiguration.apiVersion` | Return the appropriate apiVersion for AdmissionConfiguration. | `.` Chart context | +| `common.capabilities.podSecurityConfiguration.apiVersion` | Return the appropriate apiVersion for PodSecurityConfiguration. | `.` Chart context | + +### Compatibility + +| Helper identifier | Description | Expected Input | +| -------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------- | +| `common.compatibility.isOpenshift` | Return true if the detected platform is Openshift | `.` Chart context | +| `common.compatibility.renderSecurityContext` | Render a compatible securityContext depending on the platform. By default it is maintained as it is. In other platforms like Openshift we remove default user/group values that do not work out of the box with the restricted-v1 SCC | `dict "secContext" .Values.containerSecurityContext "context" $` | + +### Errors + +| Helper identifier | Description | Expected Input | +| --------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------- | +| `common.errors.upgrade.passwords.empty` | It will ensure required passwords are given when we are upgrading a chart. If `validationErrors` is not empty it will throw an error and will stop the upgrade action. | `dict "validationErrors" (list $validationError00 $validationError01) "context" $` | +| `common.errors.insecureImages` | Throw error when original container images are replaced. The error can be bypassed by setting the `global.security.allowInsecureImages` to true. | `dict "images" (list .Values.path.to.the.imageRoot) "context" $` | + +### Images + +| Helper identifier | Description | Expected Input | +| --------------------------------- | -------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------ | +| `common.images.image` | Return the proper and full image name | `dict "imageRoot" .Values.path.to.the.image "global" $`, see [ImageRoot](#imageroot) for the structure. | +| `common.images.pullSecrets` | Return the proper Docker Image Registry Secret Names (deprecated: use common.images.renderPullSecrets instead) | `dict "images" (list .Values.path.to.the.image1, .Values.path.to.the.image2) "global" .Values.global` | +| `common.images.renderPullSecrets` | Return the proper Docker Image Registry Secret Names (evaluates values as templates) | `dict "images" (list .Values.path.to.the.image1, .Values.path.to.the.image2) "context" $` | +| `common.images.version` | Return the proper image version | `dict "imageRoot" .Values.path.to.the.image "chart" .Chart` , see [ImageRoot](#imageroot) for the structure. | + +### Ingress + +| Helper identifier | Description | Expected Input | +| ----------------------------------------- | ----------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| `common.ingress.backend` | Generate a proper Ingress backend entry depending on the API version | `dict "serviceName" "foo" "servicePort" "bar"`, see the [Ingress deprecation notice](https://kubernetes.io/blog/2019/07/18/api-deprecations-in-1-16/) for the syntax differences | +| `common.ingress.certManagerRequest` | Prints "true" if required cert-manager annotations for TLS signed certificates are set in the Ingress annotations | `dict "annotations" .Values.path.to.the.ingress.annotations` | + +### Labels + +| Helper identifier | Description | Expected Input | +| --------------------------- | --------------------------------------------------------------------------- | ----------------- | +| `common.labels.standard` | Return Kubernetes standard labels | `.` Chart context | +| `common.labels.matchLabels` | Labels to use on `deploy.spec.selector.matchLabels` and `svc.spec.selector` | `.` Chart context | + +### Names + +| Helper identifier | Description | Expected Input | +| ---------------------------------- | --------------------------------------------------------------------- | --------------------------------------------------------------------------------------------- | +| `common.names.name` | Expand the name of the chart or use `.Values.nameOverride` | `.` Chart context | +| `common.names.fullname` | Create a default fully qualified app name. | `.` Chart context | +| `common.names.namespace` | Allow the release namespace to be overridden | `.` Chart context | +| `common.names.fullname.namespace` | Create a fully qualified app name adding the installation's namespace | `.` Chart context | +| `common.names.chart` | Chart name plus version | `.` Chart context | +| `common.names.dependency.fullname` | Create a default fully qualified dependency name. | `dict "chartName" "dependency-chart-name" "chartValues" .Values.dependency-chart "context" $` | + +### Resources + +| Helper identifier | Description | Expected Input | +| ------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------- | -------------------- | +| `common.resources.preset` | Return a resource request/limit object based on a given preset. These presets are for basic testing and not meant to be used in production. | `dict "type" "nano"` | + +### Secrets + +| Helper identifier | Description | Expected Input | +| --------------------------------- | -------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| `common.secrets.name` | Generate the name of the secret. | `dict "existingSecret" .Values.path.to.the.existingSecret "defaultNameSuffix" "mySuffix" "context" $` see [ExistingSecret](#existingsecret) for the structure. | +| `common.secrets.key` | Generate secret key. | `dict "existingSecret" .Values.path.to.the.existingSecret "key" "keyName"` see [ExistingSecret](#existingsecret) for the structure. | +| `common.secrets.passwords.manage` | Generate secret password or retrieve one if already created. | `dict "secret" "secret-name" "key" "keyName" "providedValues" (list "path.to.password1" "path.to.password2") "length" 10 "strong" false "chartName" "chartName" "honorProvidedValues" false "context" $`, length, strong, honorProvidedValues and chartName fields are optional. | +| `common.secrets.exists` | Returns whether a previous generated secret already exists. | `dict "secret" "secret-name" "context" $` | +| `common.secrets.lookup` | Reuses the value from an existing secret, otherwise sets its value to a default value. | `dict "secret" "secret-name" "key" "keyName" "defaultValue" .Values.myValue "context" $` | + +### Storage + +| Helper identifier | Description | Expected Input | +| ---------------------- | -------------------------------- | ------------------------------------------------------------------------------------------------------------------- | +| `common.storage.class` | Return the proper Storage Class | `dict "persistence" .Values.path.to.the.persistence "global" $`, see [Persistence](#persistence) for the structure. | + +### TplValues + +| Helper identifier | Description | Expected Input | +| ---------------------------------- | ------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------- | +| `common.tplvalues.render` | Renders a value that contains template | `dict "value" .Values.path.to.the.Value "context" $`, value is the value should rendered as template, context frequently is the chart context `$` or `.` | +| `common.tplvalues.merge` | Merge a list of values that contains template after rendering them. | `dict "values" (list .Values.path.to.the.Value1 .Values.path.to.the.Value2) "context" $` | +| `common.tplvalues.merge-overwrite` | Merge a list of values that contains template after rendering them. | `dict "values" (list .Values.path.to.the.Value1 .Values.path.to.the.Value2) "context" $` | + +### Utils + +| Helper identifier | Description | Expected Input | +| ------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------- | +| `common.utils.fieldToEnvVar` | Build environment variable name given a field. | `dict "field" "my-password"` | +| `common.utils.secret.getvalue` | Print instructions to get a secret value. | `dict "secret" "secret-name" "field" "secret-value-field" "context" $` | +| `common.utils.getValueFromKey` | Gets a value from `.Values` object given its key path | `dict "key" "path.to.key" "context" $` | +| `common.utils.getKeyFromList` | Returns first `.Values` key with a defined value or first of the list if all non-defined | `dict "keys" (list "path.to.key1" "path.to.key2") "context" $` | +| `common.utils.checksumTemplate` | Checksum a template at "path" containing a *single* resource (ConfigMap,Secret) for use in pod annotations, excluding the metadata (see #18376) | `dict "path" "/configmap.yaml" "context" $` | + +### Validations + +| Helper identifier | Description | Expected Input | +| --------------------------------------------- | ------------------------------------------------------------------------------------------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | +| `common.validations.values.single.empty` | Validate a value must not be empty. | `dict "valueKey" "path.to.value" "secret" "secret.name" "field" "my-password" "subchart" "subchart" "context" $` secret, field and subchart are optional. In case they are given, the helper will generate a how to get instruction. See [ValidateValue](#validatevalue) | +| `common.validations.values.multiple.empty` | Validate a multiple values must not be empty. It returns a shared error for all the values. | `dict "required" (list $validateValueConf00 $validateValueConf01) "context" $`. See [ValidateValue](#validatevalue) | +| `common.validations.values.mariadb.passwords` | This helper will ensure required password for MariaDB are not empty. It returns a shared error for all the values. | `dict "secret" "mariadb-secret" "subchart" "true" "context" $` subchart field is optional and could be true or false it depends on where you will use mariadb chart and the helper. | + +### Warnings + +| Helper identifier | Description | Expected Input | +| -------------------------------- | ----------------------------------------------------------------- | ---------------------------------------------------------- | +| `common.warnings.rollingTag` | Warning about using rolling tag. | `ImageRoot` see [ImageRoot](#imageroot) for the structure. | +| `common.warnings.modifiedImages` | Warning about replaced images from the original. | `ImageRoot` see [ImageRoot](#imageroot) for the structure. | +| `common.warnings.resources` | Warning about not setting the resource object in all deployments. | `dict "sections" (list "path1" "path2") context $` | + +## Special input schemas + +### ImageRoot + +```yaml +registry: + type: string + description: Docker registry where the image is located + example: docker.io + +repository: + type: string + description: Repository and image name + example: bitnami/nginx + +tag: + type: string + description: image tag + example: 1.16.1-debian-10-r63 + +pullPolicy: + type: string + description: Specify a imagePullPolicy.' + +pullSecrets: + type: array + items: + type: string + description: Optionally specify an array of imagePullSecrets (evaluated as templates). + +debug: + type: boolean + description: Set to true if you would like to see extra information on logs + example: false + +## An instance would be: +# registry: docker.io +# repository: bitnami/nginx +# tag: 1.16.1-debian-10-r63 +# pullPolicy: IfNotPresent +# debug: false +``` + +### Persistence + +```yaml +enabled: + type: boolean + description: Whether enable persistence. + example: true + +storageClass: + type: string + description: Ghost data Persistent Volume Storage Class, If set to "-", storageClassName: "" which disables dynamic provisioning. + example: "-" + +accessMode: + type: string + description: Access mode for the Persistent Volume Storage. + example: ReadWriteOnce + +size: + type: string + description: Size the Persistent Volume Storage. + example: 8Gi + +path: + type: string + description: Path to be persisted. + example: /bitnami + +## An instance would be: +# enabled: true +# storageClass: "-" +# accessMode: ReadWriteOnce +# size: 8Gi +# path: /bitnami +``` + +### ExistingSecret + +```yaml +name: + type: string + description: Name of the existing secret. + example: mySecret +keyMapping: + description: Mapping between the expected key name and the name of the key in the existing secret. + type: object + +## An instance would be: +# name: mySecret +# keyMapping: +# password: myPasswordKey +``` + +#### Example of use + +When we store sensitive data for a deployment in a secret, some times we want to give to users the possibility of using theirs existing secrets. + +```yaml +# templates/secret.yaml +--- +apiVersion: v1 +kind: Secret +metadata: + name: {{ include "common.names.fullname" . }} + labels: + app: {{ include "common.names.fullname" . }} +type: Opaque +data: + password: {{ .Values.password | b64enc | quote }} + +# templates/dpl.yaml +--- +... + env: + - name: PASSWORD + valueFrom: + secretKeyRef: + name: {{ include "common.secrets.name" (dict "existingSecret" .Values.existingSecret "context" $) }} + key: {{ include "common.secrets.key" (dict "existingSecret" .Values.existingSecret "key" "password") }} +... + +# values.yaml +--- +name: mySecret +keyMapping: + password: myPasswordKey +``` + +### ValidateValue + +#### NOTES.txt + +```console +{{- $validateValueConf00 := (dict "valueKey" "path.to.value00" "secret" "secretName" "field" "password-00") -}} +{{- $validateValueConf01 := (dict "valueKey" "path.to.value01" "secret" "secretName" "field" "password-01") -}} + +{{ include "common.validations.values.multiple.empty" (dict "required" (list $validateValueConf00 $validateValueConf01) "context" $) }} +``` + +If we force those values to be empty we will see some alerts + +```console +helm install test mychart --set path.to.value00="",path.to.value01="" + 'path.to.value00' must not be empty, please add '--set path.to.value00=$PASSWORD_00' to the command. To get the current value: + + export PASSWORD_00=$(kubectl get secret --namespace default secretName -o jsonpath="{.data.password-00}" | base64 -d) + + 'path.to.value01' must not be empty, please add '--set path.to.value01=$PASSWORD_01' to the command. To get the current value: + + export PASSWORD_01=$(kubectl get secret --namespace default secretName -o jsonpath="{.data.password-01}" | base64 -d) +``` + +## Upgrading + +### To 1.0.0 + +[On November 13, 2020, Helm v2 support was formally finished](https://github.com/helm/charts#status-of-the-project), this major version is the result of the required changes applied to the Helm Chart to be able to incorporate the different features added in Helm v3 and to be consistent with the Helm project itself regarding the Helm v2 EOL. + +#### What changes were introduced in this major version? + +- Previous versions of this Helm Chart use `apiVersion: v1` (installable by both Helm 2 and 3), this Helm Chart was updated to `apiVersion: v2` (installable by Helm 3 only). [Here](https://helm.sh/docs/topics/charts/#the-apiversion-field) you can find more information about the `apiVersion` field. +- Use `type: library`. [Here](https://v3.helm.sh/docs/faq/#library-chart-support) you can find more information. +- The different fields present in the *Chart.yaml* file has been ordered alphabetically in a homogeneous way for all the Bitnami Helm Charts + +#### Considerations when upgrading to this version + +- If you want to upgrade to this version from a previous one installed with Helm v3, you shouldn't face any issues +- If you want to upgrade to this version using Helm v2, this scenario is not supported as this version doesn't support Helm v2 anymore +- If you installed the previous version with Helm v2 and wants to upgrade to this version with Helm v3, please refer to the [official Helm documentation](https://helm.sh/docs/topics/v2_v3_migration/#migration-use-cases) about migrating from Helm v2 to v3 + +#### Useful links + +- +- +- + +## License + +Copyright © 2025 Broadcom. The term "Broadcom" refers to Broadcom Inc. and/or its subsidiaries. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. diff --git a/helm-charts/keydb/charts/common/templates/_affinities.tpl b/helm-charts/keydb/charts/common/templates/_affinities.tpl new file mode 100644 index 0000000..c6ccc62 --- /dev/null +++ b/helm-charts/keydb/charts/common/templates/_affinities.tpl @@ -0,0 +1,169 @@ +{{/* +Copyright Broadcom, Inc. All Rights Reserved. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{/* vim: set filetype=mustache: */}} + +{{/* +Return a soft nodeAffinity definition +{{ include "common.affinities.nodes.soft" (dict "key" "FOO" "values" (list "BAR" "BAZ")) -}} +*/}} +{{- define "common.affinities.nodes.soft" -}} +preferredDuringSchedulingIgnoredDuringExecution: + - preference: + matchExpressions: + - key: {{ .key }} + operator: In + values: + {{- range .values }} + - {{ . | quote }} + {{- end }} + weight: 1 +{{- end -}} + +{{/* +Return a hard nodeAffinity definition +{{ include "common.affinities.nodes.hard" (dict "key" "FOO" "values" (list "BAR" "BAZ")) -}} +*/}} +{{- define "common.affinities.nodes.hard" -}} +requiredDuringSchedulingIgnoredDuringExecution: + nodeSelectorTerms: + - matchExpressions: + - key: {{ .key }} + operator: In + values: + {{- range .values }} + - {{ . | quote }} + {{- end }} +{{- end -}} + +{{/* +Return a nodeAffinity definition +{{ include "common.affinities.nodes" (dict "type" "soft" "key" "FOO" "values" (list "BAR" "BAZ")) -}} +*/}} +{{- define "common.affinities.nodes" -}} + {{- if eq .type "soft" }} + {{- include "common.affinities.nodes.soft" . -}} + {{- else if eq .type "hard" }} + {{- include "common.affinities.nodes.hard" . -}} + {{- end -}} +{{- end -}} + +{{/* +Return a topologyKey definition +{{ include "common.affinities.topologyKey" (dict "topologyKey" "BAR") -}} +*/}} +{{- define "common.affinities.topologyKey" -}} +{{ .topologyKey | default "kubernetes.io/hostname" -}} +{{- end -}} + +{{/* +Return a soft podAffinity/podAntiAffinity definition +{{ include "common.affinities.pods.soft" (dict "component" "FOO" "customLabels" .Values.podLabels "extraMatchLabels" .Values.extraMatchLabels "topologyKey" "BAR" "extraPodAffinityTerms" .Values.extraPodAffinityTerms "extraNamespaces" (list "namespace1" "namespace2") "context" $) -}} +*/}} +{{- define "common.affinities.pods.soft" -}} +{{- $component := default "" .component -}} +{{- $customLabels := default (dict) .customLabels -}} +{{- $extraMatchLabels := default (dict) .extraMatchLabels -}} +{{- $extraPodAffinityTerms := default (list) .extraPodAffinityTerms -}} +{{- $extraNamespaces := default (list) .extraNamespaces -}} +preferredDuringSchedulingIgnoredDuringExecution: + - podAffinityTerm: + labelSelector: + matchLabels: {{- (include "common.labels.matchLabels" ( dict "customLabels" $customLabels "context" .context )) | nindent 10 }} + {{- if not (empty $component) }} + {{ printf "app.kubernetes.io/component: %s" $component }} + {{- end }} + {{- range $key, $value := $extraMatchLabels }} + {{ $key }}: {{ $value | quote }} + {{- end }} + {{- if $extraNamespaces }} + namespaces: + - {{ .context.Release.Namespace }} + {{- with $extraNamespaces }} + {{- include "common.tplvalues.render" (dict "value" . "context" $) | nindent 8 }} + {{- end }} + {{- end }} + topologyKey: {{ include "common.affinities.topologyKey" (dict "topologyKey" .topologyKey) }} + weight: 1 + {{- range $extraPodAffinityTerms }} + - podAffinityTerm: + labelSelector: + matchLabels: {{- (include "common.labels.matchLabels" ( dict "customLabels" $customLabels "context" $.context )) | nindent 10 }} + {{- if not (empty $component) }} + {{ printf "app.kubernetes.io/component: %s" $component }} + {{- end }} + {{- range $key, $value := .extraMatchLabels }} + {{ $key }}: {{ $value | quote }} + {{- end }} + {{- if .namespaces }} + namespaces: + - {{ $.context.Release.Namespace }} + {{- with .namespaces }} + {{- include "common.tplvalues.render" (dict "value" . "context" $) | nindent 8 }} + {{- end }} + {{- end }} + topologyKey: {{ include "common.affinities.topologyKey" (dict "topologyKey" .topologyKey) }} + weight: {{ .weight | default 1 -}} + {{- end -}} +{{- end -}} + +{{/* +Return a hard podAffinity/podAntiAffinity definition +{{ include "common.affinities.pods.hard" (dict "component" "FOO" "customLabels" .Values.podLabels "extraMatchLabels" .Values.extraMatchLabels "topologyKey" "BAR" "extraPodAffinityTerms" .Values.extraPodAffinityTerms "extraNamespaces" (list "namespace1" "namespace2") "context" $) -}} +*/}} +{{- define "common.affinities.pods.hard" -}} +{{- $component := default "" .component -}} +{{- $customLabels := default (dict) .customLabels -}} +{{- $extraMatchLabels := default (dict) .extraMatchLabels -}} +{{- $extraPodAffinityTerms := default (list) .extraPodAffinityTerms -}} +{{- $extraNamespaces := default (list) .extraNamespaces -}} +requiredDuringSchedulingIgnoredDuringExecution: + - labelSelector: + matchLabels: {{- (include "common.labels.matchLabels" ( dict "customLabels" $customLabels "context" .context )) | nindent 8 }} + {{- if not (empty $component) }} + {{ printf "app.kubernetes.io/component: %s" $component }} + {{- end }} + {{- range $key, $value := $extraMatchLabels }} + {{ $key }}: {{ $value | quote }} + {{- end }} + {{- if $extraNamespaces }} + namespaces: + - {{ .context.Release.Namespace }} + {{- with $extraNamespaces }} + {{- include "common.tplvalues.render" (dict "value" . "context" $) | nindent 6 }} + {{- end }} + {{- end }} + topologyKey: {{ include "common.affinities.topologyKey" (dict "topologyKey" .topologyKey) }} + {{- range $extraPodAffinityTerms }} + - labelSelector: + matchLabels: {{- (include "common.labels.matchLabels" ( dict "customLabels" $customLabels "context" $.context )) | nindent 8 }} + {{- if not (empty $component) }} + {{ printf "app.kubernetes.io/component: %s" $component }} + {{- end }} + {{- range $key, $value := .extraMatchLabels }} + {{ $key }}: {{ $value | quote }} + {{- end }} + {{- if .namespaces }} + namespaces: + - {{ $.context.Release.Namespace }} + {{- with .namespaces }} + {{- include "common.tplvalues.render" (dict "value" . "context" $) | nindent 6 }} + {{- end }} + {{- end }} + topologyKey: {{ include "common.affinities.topologyKey" (dict "topologyKey" .topologyKey) }} + {{- end -}} +{{- end -}} + +{{/* +Return a podAffinity/podAntiAffinity definition +{{ include "common.affinities.pods" (dict "type" "soft" "key" "FOO" "values" (list "BAR" "BAZ")) -}} +*/}} +{{- define "common.affinities.pods" -}} + {{- if eq .type "soft" }} + {{- include "common.affinities.pods.soft" . -}} + {{- else if eq .type "hard" }} + {{- include "common.affinities.pods.hard" . -}} + {{- end -}} +{{- end -}} diff --git a/helm-charts/keydb/charts/common/templates/_capabilities.tpl b/helm-charts/keydb/charts/common/templates/_capabilities.tpl new file mode 100644 index 0000000..58f58c1 --- /dev/null +++ b/helm-charts/keydb/charts/common/templates/_capabilities.tpl @@ -0,0 +1,178 @@ +{{/* +Copyright Broadcom, Inc. All Rights Reserved. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{/* vim: set filetype=mustache: */}} + +{{/* +Return the target Kubernetes version +*/}} +{{- define "common.capabilities.kubeVersion" -}} +{{- default (default .Capabilities.KubeVersion.Version .Values.kubeVersion) ((.Values.global).kubeVersion) -}} +{{- end -}} + +{{/* +Return true if the apiVersion is supported +Usage: +{{ include "common.capabilities.apiVersions.has" (dict "version" "batch/v1" "context" $) }} +*/}} +{{- define "common.capabilities.apiVersions.has" -}} +{{- $providedAPIVersions := default .context.Values.apiVersions ((.context.Values.global).apiVersions) -}} +{{- if and (empty $providedAPIVersions) (.context.Capabilities.APIVersions.Has .version) -}} + {{- true -}} +{{- else if has .version $providedAPIVersions -}} + {{- true -}} +{{- end -}} +{{- end -}} + +{{/* +Return the appropriate apiVersion for poddisruptionbudget. +*/}} +{{- define "common.capabilities.policy.apiVersion" -}} +{{- print "policy/v1" -}} +{{- end -}} + +{{/* +Return the appropriate apiVersion for networkpolicy. +*/}} +{{- define "common.capabilities.networkPolicy.apiVersion" -}} +{{- print "networking.k8s.io/v1" -}} +{{- end -}} + +{{/* +Return the appropriate apiVersion for job. +*/}} +{{- define "common.capabilities.job.apiVersion" -}} +{{- print "batch/v1" -}} +{{- end -}} + +{{/* +Return the appropriate apiVersion for cronjob. +*/}} +{{- define "common.capabilities.cronjob.apiVersion" -}} +{{- print "batch/v1" -}} +{{- end -}} + +{{/* +Return the appropriate apiVersion for daemonset. +*/}} +{{- define "common.capabilities.daemonset.apiVersion" -}} +{{- print "apps/v1" -}} +{{- end -}} + +{{/* +Return the appropriate apiVersion for deployment. +*/}} +{{- define "common.capabilities.deployment.apiVersion" -}} +{{- print "apps/v1" -}} +{{- end -}} + +{{/* +Return the appropriate apiVersion for statefulset. +*/}} +{{- define "common.capabilities.statefulset.apiVersion" -}} +{{- print "apps/v1" -}} +{{- end -}} + +{{/* +Return the appropriate apiVersion for ingress. +*/}} +{{- define "common.capabilities.ingress.apiVersion" -}} +{{- print "networking.k8s.io/v1" -}} +{{- end -}} + +{{/* +Return the appropriate apiVersion for RBAC resources. +*/}} +{{- define "common.capabilities.rbac.apiVersion" -}} +{{- print "rbac.authorization.k8s.io/v1" -}} +{{- end -}} + +{{/* +Return the appropriate apiVersion for CRDs. +*/}} +{{- define "common.capabilities.crd.apiVersion" -}} +{{- print "apiextensions.k8s.io/v1" -}} +{{- end -}} + +{{/* +Return the appropriate apiVersion for APIService. +*/}} +{{- define "common.capabilities.apiService.apiVersion" -}} +{{- print "apiregistration.k8s.io/v1" -}} +{{- end -}} + +{{/* +Return the appropriate apiVersion for Horizontal Pod Autoscaler. +*/}} +{{- define "common.capabilities.hpa.apiVersion" -}} +{{- $kubeVersion := include "common.capabilities.kubeVersion" .context -}} +{{- print "autoscaling/v2" -}} +{{- end -}} + +{{/* +Return the appropriate apiVersion for Vertical Pod Autoscaler. +*/}} +{{- define "common.capabilities.vpa.apiVersion" -}} +{{- $kubeVersion := include "common.capabilities.kubeVersion" . -}} +{{- if and (not (empty $kubeVersion)) (semverCompare "<1.25-0" $kubeVersion) -}} +{{- print "autoscaling/v1beta2" -}} +{{- else -}} +{{- print "autoscaling/v1" -}} +{{- end -}} +{{- end -}} + +{{/* +Returns true if PodSecurityPolicy is supported +*/}} +{{- define "common.capabilities.psp.supported" -}} +{{- $kubeVersion := include "common.capabilities.kubeVersion" . -}} +{{- if or (empty $kubeVersion) (semverCompare "<1.25-0" $kubeVersion) -}} + {{- true -}} +{{- end -}} +{{- end -}} + +{{/* +Returns true if AdmissionConfiguration is supported +*/}} +{{- define "common.capabilities.admissionConfiguration.supported" -}} +{{- $kubeVersion := include "common.capabilities.kubeVersion" . -}} + {{- true -}} +{{- end -}} + +{{/* +Return the appropriate apiVersion for AdmissionConfiguration. +*/}} +{{- define "common.capabilities.admissionConfiguration.apiVersion" -}} +{{- $kubeVersion := include "common.capabilities.kubeVersion" . -}} +{{- if and (not (empty $kubeVersion)) (semverCompare "<1.25-0" $kubeVersion) -}} +{{- print "apiserver.config.k8s.io/v1beta1" -}} +{{- else -}} +{{- print "apiserver.config.k8s.io/v1" -}} +{{- end -}} +{{- end -}} + +{{/* +Return the appropriate apiVersion for PodSecurityConfiguration. +*/}} +{{- define "common.capabilities.podSecurityConfiguration.apiVersion" -}} +{{- $kubeVersion := include "common.capabilities.kubeVersion" . -}} +{{- if and (not (empty $kubeVersion)) (semverCompare "<1.25-0" $kubeVersion) -}} +{{- print "pod-security.admission.config.k8s.io/v1beta1" -}} +{{- else -}} +{{- print "pod-security.admission.config.k8s.io/v1" -}} +{{- end -}} +{{- end -}} + +{{/* +Returns true if the used Helm version is 3.3+. +A way to check the used Helm version was not introduced until version 3.3.0 with .Capabilities.HelmVersion, which contains an additional "{}}" structure. +This check is introduced as a regexMatch instead of {{ if .Capabilities.HelmVersion }} because checking for the key HelmVersion in <3.3 results in a "interface not found" error. +**To be removed when the catalog's minimun Helm version is 3.3** +*/}} +{{- define "common.capabilities.supportsHelmVersion" -}} +{{- if regexMatch "{(v[0-9])*[^}]*}}$" (.Capabilities | toString ) }} + {{- true -}} +{{- end -}} +{{- end -}} diff --git a/helm-charts/keydb/charts/common/templates/_compatibility.tpl b/helm-charts/keydb/charts/common/templates/_compatibility.tpl new file mode 100644 index 0000000..19c26db --- /dev/null +++ b/helm-charts/keydb/charts/common/templates/_compatibility.tpl @@ -0,0 +1,46 @@ +{{/* +Copyright Broadcom, Inc. All Rights Reserved. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{/* vim: set filetype=mustache: */}} + +{{/* +Return true if the detected platform is Openshift +Usage: +{{- include "common.compatibility.isOpenshift" . -}} +*/}} +{{- define "common.compatibility.isOpenshift" -}} +{{- if .Capabilities.APIVersions.Has "security.openshift.io/v1" -}} +{{- true -}} +{{- end -}} +{{- end -}} + +{{/* +Render a compatible securityContext depending on the platform. By default it is maintained as it is. In other platforms like Openshift we remove default user/group values that do not work out of the box with the restricted-v1 SCC +Usage: +{{- include "common.compatibility.renderSecurityContext" (dict "secContext" .Values.containerSecurityContext "context" $) -}} +*/}} +{{- define "common.compatibility.renderSecurityContext" -}} +{{- $adaptedContext := .secContext -}} + +{{- if (((.context.Values.global).compatibility).openshift) -}} + {{- if or (eq .context.Values.global.compatibility.openshift.adaptSecurityContext "force") (and (eq .context.Values.global.compatibility.openshift.adaptSecurityContext "auto") (include "common.compatibility.isOpenshift" .context)) -}} + {{/* Remove incompatible user/group values that do not work in Openshift out of the box */}} + {{- $adaptedContext = omit $adaptedContext "fsGroup" "runAsUser" "runAsGroup" -}} + {{- if not .secContext.seLinuxOptions -}} + {{/* If it is an empty object, we remove it from the resulting context because it causes validation issues */}} + {{- $adaptedContext = omit $adaptedContext "seLinuxOptions" -}} + {{- end -}} + {{- end -}} +{{- end -}} +{{/* Remove empty seLinuxOptions object if global.compatibility.omitEmptySeLinuxOptions is set to true */}} +{{- if and (((.context.Values.global).compatibility).omitEmptySeLinuxOptions) (not .secContext.seLinuxOptions) -}} + {{- $adaptedContext = omit $adaptedContext "seLinuxOptions" -}} +{{- end -}} +{{/* Remove fields that are disregarded when running the container in privileged mode */}} +{{- if $adaptedContext.privileged -}} + {{- $adaptedContext = omit $adaptedContext "capabilities" -}} +{{- end -}} +{{- omit $adaptedContext "enabled" | toYaml -}} +{{- end -}} diff --git a/helm-charts/keydb/charts/common/templates/_errors.tpl b/helm-charts/keydb/charts/common/templates/_errors.tpl new file mode 100644 index 0000000..fb704c9 --- /dev/null +++ b/helm-charts/keydb/charts/common/templates/_errors.tpl @@ -0,0 +1,92 @@ +{{/* +Copyright Broadcom, Inc. All Rights Reserved. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{/* vim: set filetype=mustache: */}} +{{/* +Throw error when upgrading using empty passwords values that must not be empty. + +Usage: +{{- $validationError00 := include "common.validations.values.single.empty" (dict "valueKey" "path.to.password00" "secret" "secretName" "field" "password-00") -}} +{{- $validationError01 := include "common.validations.values.single.empty" (dict "valueKey" "path.to.password01" "secret" "secretName" "field" "password-01") -}} +{{ include "common.errors.upgrade.passwords.empty" (dict "validationErrors" (list $validationError00 $validationError01) "context" $) }} + +Required password params: + - validationErrors - String - Required. List of validation strings to be return, if it is empty it won't throw error. + - context - Context - Required. Parent context. +*/}} +{{- define "common.errors.upgrade.passwords.empty" -}} + {{- $validationErrors := join "" .validationErrors -}} + {{- if and $validationErrors .context.Release.IsUpgrade -}} + {{- $errorString := "\nPASSWORDS ERROR: You must provide your current passwords when upgrading the release." -}} + {{- $errorString = print $errorString "\n Note that even after reinstallation, old credentials may be needed as they may be kept in persistent volume claims." -}} + {{- $errorString = print $errorString "\n Further information can be obtained at https://docs.bitnami.com/general/how-to/troubleshoot-helm-chart-issues/#credential-errors-while-upgrading-chart-releases" -}} + {{- $errorString = print $errorString "\n%s" -}} + {{- printf $errorString $validationErrors | fail -}} + {{- end -}} +{{- end -}} + +{{/* +Throw error when original container images are replaced. +The error can be bypassed by setting the "global.security.allowInsecureImages" to true. In this case, +a warning message will be shown instead. + +Usage: +{{ include "common.errors.insecureImages" (dict "images" (list .Values.path.to.the.imageRoot) "context" $) }} +*/}} +{{- define "common.errors.insecureImages" -}} +{{- $relocatedImages := list -}} +{{- $replacedImages := list -}} +{{- $bitnamiLegacyImages := list -}} +{{- $retaggedImages := list -}} +{{- $globalRegistry := ((.context.Values.global).imageRegistry) -}} +{{- $originalImages := .context.Chart.Annotations.images -}} +{{- range .images -}} + {{- $registryName := default .registry $globalRegistry -}} + {{- $fullImageNameNoTag := printf "%s/%s" $registryName .repository -}} + {{- $fullImageName := printf "%s:%s" $fullImageNameNoTag .tag -}} + {{- if not (contains $fullImageNameNoTag $originalImages) -}} + {{- if not (contains $registryName $originalImages) -}} + {{- $relocatedImages = append $relocatedImages $fullImageName -}} + {{- else if not (contains .repository $originalImages) -}} + {{- $replacedImages = append $replacedImages $fullImageName -}} + {{- if contains "docker.io/bitnamilegacy/" $fullImageNameNoTag -}} + {{- $bitnamiLegacyImages = append $bitnamiLegacyImages $fullImageName -}} + {{- end -}} + {{- end -}} + {{- end -}} + {{- if not (contains (printf "%s:%s" .repository .tag) $originalImages) -}} + {{- $retaggedImages = append $retaggedImages $fullImageName -}} + {{- end -}} +{{- end -}} + +{{- if and (or (gt (len $relocatedImages) 0) (gt (len $replacedImages) 0)) (((.context.Values.global).security).allowInsecureImages) -}} + {{- print "\n\n⚠ SECURITY WARNING: Verifying original container images was skipped. Please note this Helm chart was designed, tested, and validated on multiple platforms using a specific set of Bitnami and Bitnami Secure Images containers. Substituting other containers is likely to cause degraded security and performance, broken chart features, and missing environment variables.\n" -}} +{{- else if (or (gt (len $relocatedImages) 0) (gt (len $replacedImages) 0)) -}} + {{- $errorString := "Original containers have been substituted for unrecognized ones. Deploying this chart with non-standard containers is likely to cause degraded security and performance, broken chart features, and missing environment variables." -}} + {{- $errorString = print $errorString "\n\nUnrecognized images:" -}} + {{- range (concat $relocatedImages $replacedImages) -}} + {{- $errorString = print $errorString "\n - " . -}} + {{- end -}} + {{- if and (eq (len $relocatedImages) 0) (eq (len $replacedImages) (len $bitnamiLegacyImages)) -}} + {{- $errorString = print "\n\n⚠ WARNING: " $errorString -}} + {{- print $errorString -}} + {{- else if or (contains "docker.io/bitnami/" $originalImages) (contains "docker.io/bitnamiprem/" $originalImages) (contains "docker.io/bitnamisecure/" $originalImages) -}} + {{- $errorString = print "\n\n⚠ ERROR: " $errorString -}} + {{- $errorString = print $errorString "\n\nIf you are sure you want to proceed with non-standard containers, you can skip container image verification by setting the global parameter 'global.security.allowInsecureImages' to true." -}} + {{- $errorString = print $errorString "\nFurther information can be obtained at https://github.com/bitnami/charts/issues/30850" -}} + {{- print $errorString | fail -}} + {{- else if gt (len $replacedImages) 0 -}} + {{- $errorString = print "\n\n⚠ WARNING: " $errorString -}} + {{- print $errorString -}} + {{- end -}} +{{- else if gt (len $retaggedImages) 0 -}} + {{- $warnString := "\n\n⚠ WARNING: Original containers have been retagged. Please note this Helm chart was tested, and validated on multiple platforms using a specific set of Bitnami and Bitnami Secure Images containers. Substituting original image tags could cause unexpected behavior." -}} + {{- $warnString = print $warnString "\n\nRetagged images:" -}} + {{- range $retaggedImages -}} + {{- $warnString = print $warnString "\n - " . -}} + {{- end -}} + {{- print $warnString -}} +{{- end -}} +{{- end -}} diff --git a/helm-charts/keydb/charts/common/templates/_images.tpl b/helm-charts/keydb/charts/common/templates/_images.tpl new file mode 100644 index 0000000..76bb7ce --- /dev/null +++ b/helm-charts/keydb/charts/common/templates/_images.tpl @@ -0,0 +1,115 @@ +{{/* +Copyright Broadcom, Inc. All Rights Reserved. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{/* vim: set filetype=mustache: */}} +{{/* +Return the proper image name. +If image tag and digest are not defined, termination fallbacks to chart appVersion. +{{ include "common.images.image" ( dict "imageRoot" .Values.path.to.the.image "global" .Values.global "chart" .Chart ) }} +*/}} +{{- define "common.images.image" -}} +{{- $registryName := default .imageRoot.registry ((.global).imageRegistry) -}} +{{- $repositoryName := .imageRoot.repository -}} +{{- $separator := ":" -}} +{{- $termination := .imageRoot.tag | toString -}} + +{{- if not .imageRoot.tag }} + {{- if .chart }} + {{- $termination = .chart.AppVersion | toString -}} + {{- end -}} +{{- end -}} +{{- if .imageRoot.digest }} + {{- $separator = "@" -}} + {{- $termination = .imageRoot.digest | toString -}} +{{- end -}} +{{- if $registryName }} + {{- printf "%s/%s%s%s" $registryName $repositoryName $separator $termination -}} +{{- else -}} + {{- printf "%s%s%s" $repositoryName $separator $termination -}} +{{- end -}} +{{- end -}} + +{{/* +Return the proper Docker Image Registry Secret Names (deprecated: use common.images.renderPullSecrets instead) +{{ include "common.images.pullSecrets" ( dict "images" (list .Values.path.to.the.image1, .Values.path.to.the.image2) "global" .Values.global) }} +*/}} +{{- define "common.images.pullSecrets" -}} + {{- $pullSecrets := list }} + + {{- range ((.global).imagePullSecrets) -}} + {{- if kindIs "map" . -}} + {{- $pullSecrets = append $pullSecrets .name -}} + {{- else -}} + {{- $pullSecrets = append $pullSecrets . -}} + {{- end }} + {{- end -}} + + {{- range .images -}} + {{- range .pullSecrets -}} + {{- if kindIs "map" . -}} + {{- $pullSecrets = append $pullSecrets .name -}} + {{- else -}} + {{- $pullSecrets = append $pullSecrets . -}} + {{- end -}} + {{- end -}} + {{- end -}} + + {{- if (not (empty $pullSecrets)) -}} +imagePullSecrets: + {{- range $pullSecrets | uniq }} + - name: {{ . }} + {{- end }} + {{- end }} +{{- end -}} + +{{/* +Return the proper Docker Image Registry Secret Names evaluating values as templates +{{ include "common.images.renderPullSecrets" ( dict "images" (list .Values.path.to.the.image1, .Values.path.to.the.image2) "context" $) }} +*/}} +{{- define "common.images.renderPullSecrets" -}} + {{- $pullSecrets := list }} + {{- $context := .context }} + + {{- range (($context.Values.global).imagePullSecrets) -}} + {{- if kindIs "map" . -}} + {{- $pullSecrets = append $pullSecrets (include "common.tplvalues.render" (dict "value" .name "context" $context)) -}} + {{- else -}} + {{- $pullSecrets = append $pullSecrets (include "common.tplvalues.render" (dict "value" . "context" $context)) -}} + {{- end -}} + {{- end -}} + + {{- range .images -}} + {{- range .pullSecrets -}} + {{- if kindIs "map" . -}} + {{- $pullSecrets = append $pullSecrets (include "common.tplvalues.render" (dict "value" .name "context" $context)) -}} + {{- else -}} + {{- $pullSecrets = append $pullSecrets (include "common.tplvalues.render" (dict "value" . "context" $context)) -}} + {{- end -}} + {{- end -}} + {{- end -}} + + {{- if (not (empty $pullSecrets)) -}} +imagePullSecrets: + {{- range $pullSecrets | uniq }} + - name: {{ . }} + {{- end }} + {{- end }} +{{- end -}} + +{{/* +Return the proper image version (ingores image revision/prerelease info & fallbacks to chart appVersion) +{{ include "common.images.version" ( dict "imageRoot" .Values.path.to.the.image "chart" .Chart ) }} +*/}} +{{- define "common.images.version" -}} +{{- $imageTag := .imageRoot.tag | toString -}} +{{/* regexp from https://github.com/Masterminds/semver/blob/23f51de38a0866c5ef0bfc42b3f735c73107b700/version.go#L41-L44 */}} +{{- if regexMatch `^([0-9]+)(\.[0-9]+)?(\.[0-9]+)?(-([0-9A-Za-z\-]+(\.[0-9A-Za-z\-]+)*))?(\+([0-9A-Za-z\-]+(\.[0-9A-Za-z\-]+)*))?$` $imageTag -}} + {{- $version := semver $imageTag -}} + {{- printf "%d.%d.%d" $version.Major $version.Minor $version.Patch -}} +{{- else -}} + {{- print .chart.AppVersion -}} +{{- end -}} +{{- end -}} + diff --git a/helm-charts/keydb/charts/common/templates/_ingress.tpl b/helm-charts/keydb/charts/common/templates/_ingress.tpl new file mode 100644 index 0000000..2d0dbf1 --- /dev/null +++ b/helm-charts/keydb/charts/common/templates/_ingress.tpl @@ -0,0 +1,41 @@ +{{/* +Copyright Broadcom, Inc. All Rights Reserved. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{/* vim: set filetype=mustache: */}} + +{{/* +Generate backend entry that is compatible with all Kubernetes API versions. + +Usage: +{{ include "common.ingress.backend" (dict "serviceName" "backendName" "servicePort" "backendPort" "context" $) }} + +Params: + - serviceName - String. Name of an existing service backend + - servicePort - String/Int. Port name (or number) of the service. It will be translated to different yaml depending if it is a string or an integer. + - context - Dict - Required. The context for the template evaluation. +*/}} +{{- define "common.ingress.backend" -}} +service: + name: {{ .serviceName }} + port: + {{- if typeIs "string" .servicePort }} + name: {{ .servicePort }} + {{- else if or (typeIs "int" .servicePort) (typeIs "float64" .servicePort) }} + number: {{ .servicePort | int }} + {{- end }} +{{- end -}} + +{{/* +Return true if cert-manager required annotations for TLS signed +certificates are set in the Ingress annotations +Ref: https://cert-manager.io/docs/usage/ingress/#supported-annotations +Usage: +{{ include "common.ingress.certManagerRequest" ( dict "annotations" .Values.path.to.the.ingress.annotations ) }} +*/}} +{{- define "common.ingress.certManagerRequest" -}} +{{ if or (hasKey .annotations "cert-manager.io/cluster-issuer") (hasKey .annotations "cert-manager.io/issuer") (hasKey .annotations "kubernetes.io/tls-acme") }} + {{- true -}} +{{- end -}} +{{- end -}} diff --git a/helm-charts/keydb/charts/common/templates/_labels.tpl b/helm-charts/keydb/charts/common/templates/_labels.tpl new file mode 100644 index 0000000..0a0cc54 --- /dev/null +++ b/helm-charts/keydb/charts/common/templates/_labels.tpl @@ -0,0 +1,46 @@ +{{/* +Copyright Broadcom, Inc. All Rights Reserved. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{/* vim: set filetype=mustache: */}} + +{{/* +Kubernetes standard labels +{{ include "common.labels.standard" (dict "customLabels" .Values.commonLabels "context" $) -}} +*/}} +{{- define "common.labels.standard" -}} +{{- if and (hasKey . "customLabels") (hasKey . "context") -}} +{{- $default := dict "app.kubernetes.io/name" (include "common.names.name" .context) "helm.sh/chart" (include "common.names.chart" .context) "app.kubernetes.io/instance" .context.Release.Name "app.kubernetes.io/managed-by" .context.Release.Service -}} +{{- with .context.Chart.AppVersion -}} +{{- $_ := set $default "app.kubernetes.io/version" . -}} +{{- end -}} +{{ template "common.tplvalues.merge" (dict "values" (list .customLabels $default) "context" .context) }} +{{- else -}} +app.kubernetes.io/name: {{ include "common.names.name" . }} +helm.sh/chart: {{ include "common.names.chart" . }} +app.kubernetes.io/instance: {{ .Release.Name }} +app.kubernetes.io/managed-by: {{ .Release.Service }} +{{- with .Chart.AppVersion }} +app.kubernetes.io/version: {{ . | quote }} +{{- end -}} +{{- end -}} +{{- end -}} + +{{/* +Labels used on immutable fields such as deploy.spec.selector.matchLabels or svc.spec.selector +{{ include "common.labels.matchLabels" (dict "customLabels" .Values.podLabels "context" $) -}} + +We don't want to loop over custom labels appending them to the selector +since it's very likely that it will break deployments, services, etc. +However, it's important to overwrite the standard labels if the user +overwrote them on metadata.labels fields. +*/}} +{{- define "common.labels.matchLabels" -}} +{{- if and (hasKey . "customLabels") (hasKey . "context") -}} +{{ merge (pick (include "common.tplvalues.render" (dict "value" .customLabels "context" .context) | fromYaml) "app.kubernetes.io/name" "app.kubernetes.io/instance") (dict "app.kubernetes.io/name" (include "common.names.name" .context) "app.kubernetes.io/instance" .context.Release.Name ) | toYaml }} +{{- else -}} +app.kubernetes.io/name: {{ include "common.names.name" . }} +app.kubernetes.io/instance: {{ .Release.Name }} +{{- end -}} +{{- end -}} diff --git a/helm-charts/keydb/charts/common/templates/_names.tpl b/helm-charts/keydb/charts/common/templates/_names.tpl new file mode 100644 index 0000000..d5d0ae4 --- /dev/null +++ b/helm-charts/keydb/charts/common/templates/_names.tpl @@ -0,0 +1,72 @@ +{{/* +Copyright Broadcom, Inc. All Rights Reserved. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{/* vim: set filetype=mustache: */}} +{{/* +Expand the name of the chart. +*/}} +{{- define "common.names.name" -}} +{{- default .Chart.Name .Values.nameOverride | trunc 63 | trimSuffix "-" -}} +{{- end -}} + +{{/* +Create chart name and version as used by the chart label. +*/}} +{{- define "common.names.chart" -}} +{{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | 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 "common.names.fullname" -}} +{{- if .Values.fullnameOverride -}} +{{- .Values.fullnameOverride | trunc 63 | trimSuffix "-" -}} +{{- else -}} +{{- $name := default .Chart.Name .Values.nameOverride -}} +{{- $releaseName := regexReplaceAll "(-?[^a-z\\d\\-])+-?" (lower .Release.Name) "-" -}} +{{- if contains $name $releaseName -}} +{{- $releaseName | trunc 63 | trimSuffix "-" -}} +{{- else -}} +{{- printf "%s-%s" $releaseName $name | trunc 63 | trimSuffix "-" -}} +{{- end -}} +{{- end -}} +{{- end -}} + +{{/* +Create a default fully qualified dependency 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. +Usage: +{{ include "common.names.dependency.fullname" (dict "chartName" "dependency-chart-name" "chartValues" .Values.dependency-chart "context" $) }} +*/}} +{{- define "common.names.dependency.fullname" -}} +{{- if .chartValues.fullnameOverride -}} +{{- .chartValues.fullnameOverride | trunc 63 | trimSuffix "-" -}} +{{- else -}} +{{- $name := default .chartName .chartValues.nameOverride -}} +{{- if contains $name .context.Release.Name -}} +{{- .context.Release.Name | trunc 63 | trimSuffix "-" -}} +{{- else -}} +{{- printf "%s-%s" .context.Release.Name $name | trunc 63 | trimSuffix "-" -}} +{{- end -}} +{{- end -}} +{{- end -}} + +{{/* +Allow the release namespace to be overridden for multi-namespace deployments in combined charts. +*/}} +{{- define "common.names.namespace" -}} +{{- default .Release.Namespace .Values.namespaceOverride | trunc 63 | trimSuffix "-" -}} +{{- end -}} + +{{/* +Create a fully qualified app name adding the installation's namespace. +*/}} +{{- define "common.names.fullname.namespace" -}} +{{- printf "%s-%s" (include "common.names.fullname" .) (include "common.names.namespace" .) | trunc 63 | trimSuffix "-" -}} +{{- end -}} diff --git a/helm-charts/keydb/charts/common/templates/_resources.tpl b/helm-charts/keydb/charts/common/templates/_resources.tpl new file mode 100644 index 0000000..d8a43e1 --- /dev/null +++ b/helm-charts/keydb/charts/common/templates/_resources.tpl @@ -0,0 +1,50 @@ +{{/* +Copyright Broadcom, Inc. All Rights Reserved. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{/* vim: set filetype=mustache: */}} + +{{/* +Return a resource request/limit object based on a given preset. +These presets are for basic testing and not meant to be used in production +{{ include "common.resources.preset" (dict "type" "nano") -}} +*/}} +{{- define "common.resources.preset" -}} +{{/* The limits are the requests increased by 50% (except ephemeral-storage and xlarge/2xlarge sizes)*/}} +{{- $presets := dict + "nano" (dict + "requests" (dict "cpu" "100m" "memory" "128Mi" "ephemeral-storage" "50Mi") + "limits" (dict "cpu" "150m" "memory" "192Mi" "ephemeral-storage" "2Gi") + ) + "micro" (dict + "requests" (dict "cpu" "250m" "memory" "256Mi" "ephemeral-storage" "50Mi") + "limits" (dict "cpu" "375m" "memory" "384Mi" "ephemeral-storage" "2Gi") + ) + "small" (dict + "requests" (dict "cpu" "500m" "memory" "512Mi" "ephemeral-storage" "50Mi") + "limits" (dict "cpu" "750m" "memory" "768Mi" "ephemeral-storage" "2Gi") + ) + "medium" (dict + "requests" (dict "cpu" "500m" "memory" "1024Mi" "ephemeral-storage" "50Mi") + "limits" (dict "cpu" "750m" "memory" "1536Mi" "ephemeral-storage" "2Gi") + ) + "large" (dict + "requests" (dict "cpu" "1.0" "memory" "2048Mi" "ephemeral-storage" "50Mi") + "limits" (dict "cpu" "1.5" "memory" "3072Mi" "ephemeral-storage" "2Gi") + ) + "xlarge" (dict + "requests" (dict "cpu" "1.0" "memory" "3072Mi" "ephemeral-storage" "50Mi") + "limits" (dict "cpu" "3.0" "memory" "6144Mi" "ephemeral-storage" "2Gi") + ) + "2xlarge" (dict + "requests" (dict "cpu" "1.0" "memory" "3072Mi" "ephemeral-storage" "50Mi") + "limits" (dict "cpu" "6.0" "memory" "12288Mi" "ephemeral-storage" "2Gi") + ) + }} +{{- if hasKey $presets .type -}} +{{- index $presets .type | toYaml -}} +{{- else -}} +{{- printf "ERROR: Preset key '%s' invalid. Allowed values are %s" .type (join "," (keys $presets)) | fail -}} +{{- end -}} +{{- end -}} diff --git a/helm-charts/keydb/charts/common/templates/_secrets.tpl b/helm-charts/keydb/charts/common/templates/_secrets.tpl new file mode 100644 index 0000000..7868c00 --- /dev/null +++ b/helm-charts/keydb/charts/common/templates/_secrets.tpl @@ -0,0 +1,192 @@ +{{/* +Copyright Broadcom, Inc. All Rights Reserved. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{/* vim: set filetype=mustache: */}} +{{/* +Generate secret name. + +Usage: +{{ include "common.secrets.name" (dict "existingSecret" .Values.path.to.the.existingSecret "defaultNameSuffix" "mySuffix" "context" $) }} + +Params: + - existingSecret - ExistingSecret/String - Optional. The path to the existing secrets in the values.yaml given by the user + to be used instead of the default one. Allows for it to be of type String (just the secret name) for backwards compatibility. + +info: https://github.com/bitnami/charts/tree/main/bitnami/common#existingsecret + - defaultNameSuffix - String - Optional. It is used only if we have several secrets in the same deployment. + - context - Dict - Required. The context for the template evaluation. +*/}} +{{- define "common.secrets.name" -}} +{{- $name := (include "common.names.fullname" .context) -}} + +{{- if .defaultNameSuffix -}} +{{- $name = printf "%s-%s" $name .defaultNameSuffix | trunc 63 | trimSuffix "-" -}} +{{- end -}} + +{{- with .existingSecret -}} +{{- if not (typeIs "string" .) -}} +{{- with .name -}} +{{- $name = . -}} +{{- end -}} +{{- else -}} +{{- $name = . -}} +{{- end -}} +{{- end -}} + +{{- printf "%s" $name -}} +{{- end -}} + +{{/* +Generate secret key. + +Usage: +{{ include "common.secrets.key" (dict "existingSecret" .Values.path.to.the.existingSecret "key" "keyName") }} + +Params: + - existingSecret - ExistingSecret/String - Optional. The path to the existing secrets in the values.yaml given by the user + to be used instead of the default one. Allows for it to be of type String (just the secret name) for backwards compatibility. + +info: https://github.com/bitnami/charts/tree/main/bitnami/common#existingsecret + - key - String - Required. Name of the key in the secret. +*/}} +{{- define "common.secrets.key" -}} +{{- $key := .key -}} + +{{- if .existingSecret -}} + {{- if not (typeIs "string" .existingSecret) -}} + {{- if .existingSecret.keyMapping -}} + {{- $key = index .existingSecret.keyMapping $.key -}} + {{- end -}} + {{- end }} +{{- end -}} + +{{- printf "%s" $key -}} +{{- end -}} + +{{/* +Generate secret password or retrieve one if already created. + +Usage: +{{ include "common.secrets.passwords.manage" (dict "secret" "secret-name" "key" "keyName" "providedValues" (list "path.to.password1" "path.to.password2") "length" 10 "strong" false "chartName" "chartName" "honorProvidedValues" false "context" $) }} + +Params: + - secret - String - Required - Name of the 'Secret' resource where the password is stored. + - key - String - Required - Name of the key in the secret. + - providedValues - List - Required - The path to the validating value in the values.yaml, e.g: "mysql.password". Will pick first parameter with a defined value. + - length - int - Optional - Length of the generated random password. + - strong - Boolean - Optional - Whether to add symbols to the generated random password. + - chartName - String - Optional - Name of the chart used when said chart is deployed as a subchart. + - context - Context - Required - Parent context. + - failOnNew - Boolean - Optional - Default to true. If set to false, skip errors adding new keys to existing secrets. + - skipB64enc - Boolean - Optional - Default to false. If set to true, no the secret will not be base64 encrypted. + - skipQuote - Boolean - Optional - Default to false. If set to true, no quotes will be added around the secret. + - honorProvidedValues - Boolean - Optional - Default to false. If set to true, the values in providedValues have higher priority than an existing secret +The order in which this function returns a secret password: + 1. Password provided via the values.yaml if honorProvidedValues = true + (If one of the keys passed to the 'providedValues' parameter to this function is a valid path to a key in the values.yaml and has a value, the value of the first key with a value will be returned) + 2. Already existing 'Secret' resource + (If a 'Secret' resource is found under the name provided to the 'secret' parameter to this function and that 'Secret' resource contains a key with the name passed as the 'key' parameter to this function then the value of this existing secret password will be returned) + 3. Password provided via the values.yaml if honorProvidedValues = false + (If one of the keys passed to the 'providedValues' parameter to this function is a valid path to a key in the values.yaml and has a value, the value of the first key with a value will be returned) + 4. Randomly generated secret password + (A new random secret password with the length specified in the 'length' parameter will be generated and returned) + +*/}} +{{- define "common.secrets.passwords.manage" -}} + +{{- $password := "" }} +{{- $subchart := "" }} +{{- $chartName := default "" .chartName }} +{{- $passwordLength := default 10 .length }} +{{- $providedPasswordKey := include "common.utils.getKeyFromList" (dict "keys" .providedValues "context" $.context) }} +{{- $providedPasswordValue := include "common.utils.getValueFromKey" (dict "key" $providedPasswordKey "context" $.context) }} +{{- $secretData := (lookup "v1" "Secret" (include "common.names.namespace" .context) .secret).data }} +{{- if $secretData }} + {{- if hasKey $secretData .key }} + {{- $password = index $secretData .key | b64dec }} + {{- else if not (eq .failOnNew false) }} + {{- printf "\nPASSWORDS ERROR: The secret \"%s\" does not contain the key \"%s\"\n" .secret .key | fail -}} + {{- end -}} +{{- end }} + +{{- if and $providedPasswordValue .honorProvidedValues }} + {{- $password = tpl ($providedPasswordValue | toString) .context }} +{{- end }} + +{{- if not $password }} + {{- if $providedPasswordValue }} + {{- $password = tpl ($providedPasswordValue | toString) .context }} + {{- else }} + {{- if .context.Values.enabled }} + {{- $subchart = $chartName }} + {{- end -}} + + {{- if not (eq .failOnNew false) }} + {{- $requiredPassword := dict "valueKey" $providedPasswordKey "secret" .secret "field" .key "subchart" $subchart "context" $.context -}} + {{- $requiredPasswordError := include "common.validations.values.single.empty" $requiredPassword -}} + {{- $passwordValidationErrors := list $requiredPasswordError -}} + {{- include "common.errors.upgrade.passwords.empty" (dict "validationErrors" $passwordValidationErrors "context" $.context) -}} + {{- end }} + + {{- if .strong }} + {{- $subStr := list (lower (randAlpha 1)) (randNumeric 1) (upper (randAlpha 1)) | join "_" }} + {{- $password = randAscii $passwordLength }} + {{- $password = regexReplaceAllLiteral "\\W" $password "@" | substr 5 $passwordLength }} + {{- $password = printf "%s%s" $subStr $password | toString | shuffle }} + {{- else }} + {{- $password = randAlphaNum $passwordLength }} + {{- end }} + {{- end -}} +{{- end -}} +{{- if not .skipB64enc }} +{{- $password = $password | b64enc }} +{{- end -}} +{{- if .skipQuote -}} +{{- printf "%s" $password -}} +{{- else -}} +{{- printf "%s" $password | quote -}} +{{- end -}} +{{- end -}} + +{{/* +Reuses the value from an existing secret, otherwise sets its value to a default value. + +Usage: +{{ include "common.secrets.lookup" (dict "secret" "secret-name" "key" "keyName" "defaultValue" .Values.myValue "context" $) }} + +Params: + - secret - String - Required - Name of the 'Secret' resource where the password is stored. + - key - String - Required - Name of the key in the secret. + - defaultValue - String - Required - The path to the validating value in the values.yaml, e.g: "mysql.password". Will pick first parameter with a defined value. + - context - Context - Required - Parent context. + +*/}} +{{- define "common.secrets.lookup" -}} +{{- $value := "" -}} +{{- $secretData := (lookup "v1" "Secret" (include "common.names.namespace" .context) .secret).data -}} +{{- if and $secretData (hasKey $secretData .key) -}} + {{- $value = index $secretData .key -}} +{{- else if .defaultValue -}} + {{- $value = .defaultValue | toString | b64enc -}} +{{- end -}} +{{- if $value -}} +{{- printf "%s" $value -}} +{{- end -}} +{{- end -}} + +{{/* +Returns whether a previous generated secret already exists + +Usage: +{{ include "common.secrets.exists" (dict "secret" "secret-name" "context" $) }} + +Params: + - secret - String - Required - Name of the 'Secret' resource where the password is stored. + - context - Context - Required - Parent context. +*/}} +{{- define "common.secrets.exists" -}} +{{- $secret := (lookup "v1" "Secret" (include "common.names.namespace" .context) .secret) }} +{{- if $secret }} + {{- true -}} +{{- end -}} +{{- end -}} diff --git a/helm-charts/keydb/charts/common/templates/_storage.tpl b/helm-charts/keydb/charts/common/templates/_storage.tpl new file mode 100644 index 0000000..aa75856 --- /dev/null +++ b/helm-charts/keydb/charts/common/templates/_storage.tpl @@ -0,0 +1,21 @@ +{{/* +Copyright Broadcom, Inc. All Rights Reserved. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{/* vim: set filetype=mustache: */}} + +{{/* +Return the proper Storage Class +{{ include "common.storage.class" ( dict "persistence" .Values.path.to.the.persistence "global" $) }} +*/}} +{{- define "common.storage.class" -}} +{{- $storageClass := (.global).storageClass | default .persistence.storageClass | default (.global).defaultStorageClass | default "" -}} +{{- if $storageClass -}} + {{- if (eq "-" $storageClass) -}} + {{- printf "storageClassName: \"\"" -}} + {{- else -}} + {{- printf "storageClassName: %s" $storageClass -}} + {{- end -}} +{{- end -}} +{{- end -}} diff --git a/helm-charts/keydb/charts/common/templates/_tplvalues.tpl b/helm-charts/keydb/charts/common/templates/_tplvalues.tpl new file mode 100644 index 0000000..a04f4c1 --- /dev/null +++ b/helm-charts/keydb/charts/common/templates/_tplvalues.tpl @@ -0,0 +1,52 @@ +{{/* +Copyright Broadcom, Inc. All Rights Reserved. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{/* vim: set filetype=mustache: */}} +{{/* +Renders a value that contains template perhaps with scope if the scope is present. +Usage: +{{ include "common.tplvalues.render" ( dict "value" .Values.path.to.the.Value "context" $ ) }} +{{ include "common.tplvalues.render" ( dict "value" .Values.path.to.the.Value "context" $ "scope" $app ) }} +*/}} +{{- define "common.tplvalues.render" -}} +{{- $value := typeIs "string" .value | ternary .value (.value | toYaml) }} +{{- if contains "{{" (toJson .value) }} + {{- if .scope }} + {{- tpl (cat "{{- with $.RelativeScope -}}" $value "{{- end }}") (merge (dict "RelativeScope" .scope) .context) }} + {{- else }} + {{- tpl $value .context }} + {{- end }} +{{- else }} + {{- $value }} +{{- end }} +{{- end -}} + +{{/* +Merge a list of values that contains template after rendering them. +Merge precedence is consistent with http://masterminds.github.io/sprig/dicts.html#merge-mustmerge +Usage: +{{ include "common.tplvalues.merge" ( dict "values" (list .Values.path.to.the.Value1 .Values.path.to.the.Value2) "context" $ ) }} +*/}} +{{- define "common.tplvalues.merge" -}} +{{- $dst := dict -}} +{{- range .values -}} +{{- $dst = include "common.tplvalues.render" (dict "value" . "context" $.context "scope" $.scope) | fromYaml | merge $dst -}} +{{- end -}} +{{ $dst | toYaml }} +{{- end -}} + +{{/* +Merge a list of values that contains template after rendering them. +Merge precedence is consistent with https://masterminds.github.io/sprig/dicts.html#mergeoverwrite-mustmergeoverwrite +Usage: +{{ include "common.tplvalues.merge-overwrite" ( dict "values" (list .Values.path.to.the.Value1 .Values.path.to.the.Value2) "context" $ ) }} +*/}} +{{- define "common.tplvalues.merge-overwrite" -}} +{{- $dst := dict -}} +{{- range .values -}} +{{- $dst = include "common.tplvalues.render" (dict "value" . "context" $.context "scope" $.scope) | fromYaml | mergeOverwrite $dst -}} +{{- end -}} +{{ $dst | toYaml }} +{{- end -}} diff --git a/helm-charts/keydb/charts/common/templates/_utils.tpl b/helm-charts/keydb/charts/common/templates/_utils.tpl new file mode 100644 index 0000000..d53c74a --- /dev/null +++ b/helm-charts/keydb/charts/common/templates/_utils.tpl @@ -0,0 +1,77 @@ +{{/* +Copyright Broadcom, Inc. All Rights Reserved. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{/* vim: set filetype=mustache: */}} +{{/* +Print instructions to get a secret value. +Usage: +{{ include "common.utils.secret.getvalue" (dict "secret" "secret-name" "field" "secret-value-field" "context" $) }} +*/}} +{{- define "common.utils.secret.getvalue" -}} +{{- $varname := include "common.utils.fieldToEnvVar" . -}} +export {{ $varname }}=$(kubectl get secret --namespace {{ include "common.names.namespace" .context | quote }} {{ .secret }} -o jsonpath="{.data.{{ .field }}}" | base64 -d) +{{- end -}} + +{{/* +Build env var name given a field +Usage: +{{ include "common.utils.fieldToEnvVar" dict "field" "my-password" }} +*/}} +{{- define "common.utils.fieldToEnvVar" -}} + {{- $fieldNameSplit := splitList "-" .field -}} + {{- $upperCaseFieldNameSplit := list -}} + + {{- range $fieldNameSplit -}} + {{- $upperCaseFieldNameSplit = append $upperCaseFieldNameSplit ( upper . ) -}} + {{- end -}} + + {{ join "_" $upperCaseFieldNameSplit }} +{{- end -}} + +{{/* +Gets a value from .Values given +Usage: +{{ include "common.utils.getValueFromKey" (dict "key" "path.to.key" "context" $) }} +*/}} +{{- define "common.utils.getValueFromKey" -}} +{{- $splitKey := splitList "." .key -}} +{{- $value := "" -}} +{{- $latestObj := $.context.Values -}} +{{- range $splitKey -}} + {{- if not $latestObj -}} + {{- printf "please review the entire path of '%s' exists in values" $.key | fail -}} + {{- end -}} + {{- $value = ( index $latestObj . ) -}} + {{- $latestObj = $value -}} +{{- end -}} +{{- printf "%v" (default "" $value) -}} +{{- end -}} + +{{/* +Returns first .Values key with a defined value or first of the list if all non-defined +Usage: +{{ include "common.utils.getKeyFromList" (dict "keys" (list "path.to.key1" "path.to.key2") "context" $) }} +*/}} +{{- define "common.utils.getKeyFromList" -}} +{{- $key := first .keys -}} +{{- $reverseKeys := reverse .keys }} +{{- range $reverseKeys }} + {{- $value := include "common.utils.getValueFromKey" (dict "key" . "context" $.context ) }} + {{- if $value -}} + {{- $key = . }} + {{- end -}} +{{- end -}} +{{- printf "%s" $key -}} +{{- end -}} + +{{/* +Checksum a template at "path" containing a *single* resource (ConfigMap,Secret) for use in pod annotations, excluding the metadata (see #18376). +Usage: +{{ include "common.utils.checksumTemplate" (dict "path" "/configmap.yaml" "context" $) }} +*/}} +{{- define "common.utils.checksumTemplate" -}} +{{- $obj := include (print .context.Template.BasePath .path) .context | fromYaml -}} +{{ omit $obj "apiVersion" "kind" "metadata" | toYaml | sha256sum }} +{{- end -}} diff --git a/helm-charts/keydb/charts/common/templates/_warnings.tpl b/helm-charts/keydb/charts/common/templates/_warnings.tpl new file mode 100644 index 0000000..62c44df --- /dev/null +++ b/helm-charts/keydb/charts/common/templates/_warnings.tpl @@ -0,0 +1,109 @@ +{{/* +Copyright Broadcom, Inc. All Rights Reserved. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{/* vim: set filetype=mustache: */}} +{{/* +Warning about using rolling tag. +Usage: +{{ include "common.warnings.rollingTag" .Values.path.to.the.imageRoot }} +*/}} +{{- define "common.warnings.rollingTag" -}} + +{{- if and (contains "bitnami/" .repository) (not (.tag | toString | regexFind "-r\\d+$|sha256:")) }} +WARNING: Rolling tag detected ({{ .repository }}:{{ .tag }}), please note that it is strongly recommended to avoid using rolling tags in a production environment. ++info https://techdocs.broadcom.com/us/en/vmware-tanzu/application-catalog/tanzu-application-catalog/services/tac-doc/apps-tutorials-understand-rolling-tags-containers-index.html +{{- end }} +{{- end -}} + +{{/* +Warning about replaced images from the original. +Usage: +{{ include "common.warnings.modifiedImages" (dict "images" (list .Values.path.to.the.imageRoot) "context" $) }} +*/}} +{{- define "common.warnings.modifiedImages" -}} +{{- $affectedImages := list -}} +{{- $printMessage := false -}} +{{- $originalImages := .context.Chart.Annotations.images -}} +{{- range .images -}} + {{- $fullImageName := printf (printf "%s/%s:%s" .registry .repository .tag) -}} + {{- if not (contains $fullImageName $originalImages) }} + {{- $affectedImages = append $affectedImages (printf "%s/%s:%s" .registry .repository .tag) -}} + {{- $printMessage = true -}} + {{- end -}} +{{- end -}} +{{- if $printMessage }} + +⚠ SECURITY WARNING: Original containers have been substituted. This Helm chart was designed, tested, and validated on multiple platforms using a specific set of Bitnami and Tanzu Application Catalog containers. Substituting other containers is likely to cause degraded security and performance, broken chart features, and missing environment variables. + +Substituted images detected: +{{- range $affectedImages }} + - {{ . }} +{{- end }} +{{- end -}} +{{- end -}} + +{{/* +Warning about not setting the resource object in all deployments. +Usage: +{{ include "common.warnings.resources" (dict "sections" (list "path1" "path2") context $) }} +Example: +{{- include "common.warnings.resources" (dict "sections" (list "csiProvider.provider" "server" "volumePermissions" "") "context" $) }} +The list in the example assumes that the following values exist: + - csiProvider.provider.resources + - server.resources + - volumePermissions.resources + - resources +*/}} +{{- define "common.warnings.resources" -}} +{{- $values := .context.Values -}} +{{- $printMessage := false -}} +{{ $affectedSections := list -}} +{{- range .sections -}} + {{- if eq . "" -}} + {{/* Case where the resources section is at the root (one main deployment in the chart) */}} + {{- if not (index $values "resources") -}} + {{- $affectedSections = append $affectedSections "resources" -}} + {{- $printMessage = true -}} + {{- end -}} + {{- else -}} + {{/* Case where the are multiple resources sections (more than one main deployment in the chart) */}} + {{- $keys := split "." . -}} + {{/* We iterate through the different levels until arriving to the resource section. Example: a.b.c.resources */}} + {{- $section := $values -}} + {{- range $keys -}} + {{- $section = index $section . -}} + {{- end -}} + {{- if not (index $section "resources") -}} + {{/* If the section has enabled=false or replicaCount=0, do not include it */}} + {{- if and (hasKey $section "enabled") -}} + {{- if index $section "enabled" -}} + {{/* enabled=true */}} + {{- $affectedSections = append $affectedSections (printf "%s.resources" .) -}} + {{- $printMessage = true -}} + {{- end -}} + {{- else if and (hasKey $section "replicaCount") -}} + {{/* We need a casting to int because number 0 is not treated as an int by default */}} + {{- if (gt (index $section "replicaCount" | int) 0) -}} + {{/* replicaCount > 0 */}} + {{- $affectedSections = append $affectedSections (printf "%s.resources" .) -}} + {{- $printMessage = true -}} + {{- end -}} + {{- else -}} + {{/* Default case, add it to the affected sections */}} + {{- $affectedSections = append $affectedSections (printf "%s.resources" .) -}} + {{- $printMessage = true -}} + {{- end -}} + {{- end -}} + {{- end -}} +{{- end -}} +{{- if $printMessage }} + +WARNING: There are "resources" sections in the chart not set. Using "resourcesPreset" is not recommended for production. For production installations, please set the following values according to your workload needs: +{{- range $affectedSections }} + - {{ . }} +{{- end }} ++info https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/ +{{- end -}} +{{- end -}} diff --git a/helm-charts/keydb/charts/common/templates/validations/_cassandra.tpl b/helm-charts/keydb/charts/common/templates/validations/_cassandra.tpl new file mode 100644 index 0000000..f8fd213 --- /dev/null +++ b/helm-charts/keydb/charts/common/templates/validations/_cassandra.tpl @@ -0,0 +1,51 @@ +{{/* +Copyright Broadcom, Inc. All Rights Reserved. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{/* vim: set filetype=mustache: */}} +{{/* +Auxiliary function to get the right value for existingSecret. + +Usage: +{{ include "common.cassandra.values.existingSecret" (dict "context" $) }} +Params: + - subchart - Boolean - Optional. Whether Cassandra is used as subchart or not. Default: false +*/}} +{{- define "common.cassandra.values.existingSecret" -}} + {{- if .subchart -}} + {{- .context.Values.cassandra.dbUser.existingSecret | quote -}} + {{- else -}} + {{- .context.Values.dbUser.existingSecret | quote -}} + {{- end -}} +{{- end -}} + +{{/* +Auxiliary function to get the right value for enabled cassandra. + +Usage: +{{ include "common.cassandra.values.enabled" (dict "context" $) }} +*/}} +{{- define "common.cassandra.values.enabled" -}} + {{- if .subchart -}} + {{- printf "%v" .context.Values.cassandra.enabled -}} + {{- else -}} + {{- printf "%v" (not .context.Values.enabled) -}} + {{- end -}} +{{- end -}} + +{{/* +Auxiliary function to get the right value for the key dbUser + +Usage: +{{ include "common.cassandra.values.key.dbUser" (dict "subchart" "true" "context" $) }} +Params: + - subchart - Boolean - Optional. Whether Cassandra is used as subchart or not. Default: false +*/}} +{{- define "common.cassandra.values.key.dbUser" -}} + {{- if .subchart -}} + cassandra.dbUser + {{- else -}} + dbUser + {{- end -}} +{{- end -}} diff --git a/helm-charts/keydb/charts/common/templates/validations/_mariadb.tpl b/helm-charts/keydb/charts/common/templates/validations/_mariadb.tpl new file mode 100644 index 0000000..6ea8c0f --- /dev/null +++ b/helm-charts/keydb/charts/common/templates/validations/_mariadb.tpl @@ -0,0 +1,108 @@ +{{/* +Copyright Broadcom, Inc. All Rights Reserved. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{/* vim: set filetype=mustache: */}} +{{/* +Validate MariaDB required passwords are not empty. + +Usage: +{{ include "common.validations.values.mariadb.passwords" (dict "secret" "secretName" "subchart" false "context" $) }} +Params: + - secret - String - Required. Name of the secret where MariaDB values are stored, e.g: "mysql-passwords-secret" + - subchart - Boolean - Optional. Whether MariaDB is used as subchart or not. Default: false +*/}} +{{- define "common.validations.values.mariadb.passwords" -}} + {{- $existingSecret := include "common.mariadb.values.auth.existingSecret" . -}} + {{- $enabled := include "common.mariadb.values.enabled" . -}} + {{- $architecture := include "common.mariadb.values.architecture" . -}} + {{- $authPrefix := include "common.mariadb.values.key.auth" . -}} + {{- $valueKeyRootPassword := printf "%s.rootPassword" $authPrefix -}} + {{- $valueKeyUsername := printf "%s.username" $authPrefix -}} + {{- $valueKeyPassword := printf "%s.password" $authPrefix -}} + {{- $valueKeyReplicationPassword := printf "%s.replicationPassword" $authPrefix -}} + + {{- if and (or (not $existingSecret) (eq $existingSecret "\"\"")) (eq $enabled "true") -}} + {{- $requiredPasswords := list -}} + + {{- $requiredRootPassword := dict "valueKey" $valueKeyRootPassword "secret" .secret "field" "mariadb-root-password" -}} + {{- $requiredPasswords = append $requiredPasswords $requiredRootPassword -}} + + {{- $valueUsername := include "common.utils.getValueFromKey" (dict "key" $valueKeyUsername "context" .context) }} + {{- if not (empty $valueUsername) -}} + {{- $requiredPassword := dict "valueKey" $valueKeyPassword "secret" .secret "field" "mariadb-password" -}} + {{- $requiredPasswords = append $requiredPasswords $requiredPassword -}} + {{- end -}} + + {{- if (eq $architecture "replication") -}} + {{- $requiredReplicationPassword := dict "valueKey" $valueKeyReplicationPassword "secret" .secret "field" "mariadb-replication-password" -}} + {{- $requiredPasswords = append $requiredPasswords $requiredReplicationPassword -}} + {{- end -}} + + {{- include "common.validations.values.multiple.empty" (dict "required" $requiredPasswords "context" .context) -}} + + {{- end -}} +{{- end -}} + +{{/* +Auxiliary function to get the right value for existingSecret. + +Usage: +{{ include "common.mariadb.values.auth.existingSecret" (dict "context" $) }} +Params: + - subchart - Boolean - Optional. Whether MariaDB is used as subchart or not. Default: false +*/}} +{{- define "common.mariadb.values.auth.existingSecret" -}} + {{- if .subchart -}} + {{- .context.Values.mariadb.auth.existingSecret | quote -}} + {{- else -}} + {{- .context.Values.auth.existingSecret | quote -}} + {{- end -}} +{{- end -}} + +{{/* +Auxiliary function to get the right value for enabled mariadb. + +Usage: +{{ include "common.mariadb.values.enabled" (dict "context" $) }} +*/}} +{{- define "common.mariadb.values.enabled" -}} + {{- if .subchart -}} + {{- printf "%v" .context.Values.mariadb.enabled -}} + {{- else -}} + {{- printf "%v" (not .context.Values.enabled) -}} + {{- end -}} +{{- end -}} + +{{/* +Auxiliary function to get the right value for architecture + +Usage: +{{ include "common.mariadb.values.architecture" (dict "subchart" "true" "context" $) }} +Params: + - subchart - Boolean - Optional. Whether MariaDB is used as subchart or not. Default: false +*/}} +{{- define "common.mariadb.values.architecture" -}} + {{- if .subchart -}} + {{- .context.Values.mariadb.architecture -}} + {{- else -}} + {{- .context.Values.architecture -}} + {{- end -}} +{{- end -}} + +{{/* +Auxiliary function to get the right value for the key auth + +Usage: +{{ include "common.mariadb.values.key.auth" (dict "subchart" "true" "context" $) }} +Params: + - subchart - Boolean - Optional. Whether MariaDB is used as subchart or not. Default: false +*/}} +{{- define "common.mariadb.values.key.auth" -}} + {{- if .subchart -}} + mariadb.auth + {{- else -}} + auth + {{- end -}} +{{- end -}} diff --git a/helm-charts/keydb/charts/common/templates/validations/_mongodb.tpl b/helm-charts/keydb/charts/common/templates/validations/_mongodb.tpl new file mode 100644 index 0000000..e678a6d --- /dev/null +++ b/helm-charts/keydb/charts/common/templates/validations/_mongodb.tpl @@ -0,0 +1,67 @@ +{{/* +Copyright Broadcom, Inc. All Rights Reserved. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{/* vim: set filetype=mustache: */}} +{{/* +Auxiliary function to get the right value for existingSecret. + +Usage: +{{ include "common.mongodb.values.auth.existingSecret" (dict "context" $) }} +Params: + - subchart - Boolean - Optional. Whether MongoDb is used as subchart or not. Default: false +*/}} +{{- define "common.mongodb.values.auth.existingSecret" -}} + {{- if .subchart -}} + {{- .context.Values.mongodb.auth.existingSecret | quote -}} + {{- else -}} + {{- .context.Values.auth.existingSecret | quote -}} + {{- end -}} +{{- end -}} + +{{/* +Auxiliary function to get the right value for enabled mongodb. + +Usage: +{{ include "common.mongodb.values.enabled" (dict "context" $) }} +*/}} +{{- define "common.mongodb.values.enabled" -}} + {{- if .subchart -}} + {{- printf "%v" .context.Values.mongodb.enabled -}} + {{- else -}} + {{- printf "%v" (not .context.Values.enabled) -}} + {{- end -}} +{{- end -}} + +{{/* +Auxiliary function to get the right value for the key auth + +Usage: +{{ include "common.mongodb.values.key.auth" (dict "subchart" "true" "context" $) }} +Params: + - subchart - Boolean - Optional. Whether MongoDB® is used as subchart or not. Default: false +*/}} +{{- define "common.mongodb.values.key.auth" -}} + {{- if .subchart -}} + mongodb.auth + {{- else -}} + auth + {{- end -}} +{{- end -}} + +{{/* +Auxiliary function to get the right value for architecture + +Usage: +{{ include "common.mongodb.values.architecture" (dict "subchart" "true" "context" $) }} +Params: + - subchart - Boolean - Optional. Whether MongoDB® is used as subchart or not. Default: false +*/}} +{{- define "common.mongodb.values.architecture" -}} + {{- if .subchart -}} + {{- .context.Values.mongodb.architecture -}} + {{- else -}} + {{- .context.Values.architecture -}} + {{- end -}} +{{- end -}} diff --git a/helm-charts/keydb/charts/common/templates/validations/_mysql.tpl b/helm-charts/keydb/charts/common/templates/validations/_mysql.tpl new file mode 100644 index 0000000..fbb65c3 --- /dev/null +++ b/helm-charts/keydb/charts/common/templates/validations/_mysql.tpl @@ -0,0 +1,67 @@ +{{/* +Copyright Broadcom, Inc. All Rights Reserved. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{/* vim: set filetype=mustache: */}} +{{/* +Auxiliary function to get the right value for existingSecret. + +Usage: +{{ include "common.mysql.values.auth.existingSecret" (dict "context" $) }} +Params: + - subchart - Boolean - Optional. Whether MySQL is used as subchart or not. Default: false +*/}} +{{- define "common.mysql.values.auth.existingSecret" -}} + {{- if .subchart -}} + {{- .context.Values.mysql.auth.existingSecret | quote -}} + {{- else -}} + {{- .context.Values.auth.existingSecret | quote -}} + {{- end -}} +{{- end -}} + +{{/* +Auxiliary function to get the right value for enabled mysql. + +Usage: +{{ include "common.mysql.values.enabled" (dict "context" $) }} +*/}} +{{- define "common.mysql.values.enabled" -}} + {{- if .subchart -}} + {{- printf "%v" .context.Values.mysql.enabled -}} + {{- else -}} + {{- printf "%v" (not .context.Values.enabled) -}} + {{- end -}} +{{- end -}} + +{{/* +Auxiliary function to get the right value for architecture + +Usage: +{{ include "common.mysql.values.architecture" (dict "subchart" "true" "context" $) }} +Params: + - subchart - Boolean - Optional. Whether MySQL is used as subchart or not. Default: false +*/}} +{{- define "common.mysql.values.architecture" -}} + {{- if .subchart -}} + {{- .context.Values.mysql.architecture -}} + {{- else -}} + {{- .context.Values.architecture -}} + {{- end -}} +{{- end -}} + +{{/* +Auxiliary function to get the right value for the key auth + +Usage: +{{ include "common.mysql.values.key.auth" (dict "subchart" "true" "context" $) }} +Params: + - subchart - Boolean - Optional. Whether MySQL is used as subchart or not. Default: false +*/}} +{{- define "common.mysql.values.key.auth" -}} + {{- if .subchart -}} + mysql.auth + {{- else -}} + auth + {{- end -}} +{{- end -}} diff --git a/helm-charts/keydb/charts/common/templates/validations/_postgresql.tpl b/helm-charts/keydb/charts/common/templates/validations/_postgresql.tpl new file mode 100644 index 0000000..51d4716 --- /dev/null +++ b/helm-charts/keydb/charts/common/templates/validations/_postgresql.tpl @@ -0,0 +1,105 @@ +{{/* +Copyright Broadcom, Inc. All Rights Reserved. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{/* vim: set filetype=mustache: */}} +{{/* +Auxiliary function to decide whether evaluate global values. + +Usage: +{{ include "common.postgresql.values.use.global" (dict "key" "key-of-global" "context" $) }} +Params: + - key - String - Required. Field to be evaluated within global, e.g: "existingSecret" +*/}} +{{- define "common.postgresql.values.use.global" -}} + {{- if .context.Values.global -}} + {{- if .context.Values.global.postgresql -}} + {{- index .context.Values.global.postgresql .key | quote -}} + {{- end -}} + {{- end -}} +{{- end -}} + +{{/* +Auxiliary function to get the right value for existingSecret. + +Usage: +{{ include "common.postgresql.values.existingSecret" (dict "context" $) }} +*/}} +{{- define "common.postgresql.values.existingSecret" -}} + {{- $globalValue := include "common.postgresql.values.use.global" (dict "key" "existingSecret" "context" .context) -}} + + {{- if .subchart -}} + {{- default (.context.Values.postgresql.existingSecret | quote) $globalValue -}} + {{- else -}} + {{- default (.context.Values.existingSecret | quote) $globalValue -}} + {{- end -}} +{{- end -}} + +{{/* +Auxiliary function to get the right value for enabled postgresql. + +Usage: +{{ include "common.postgresql.values.enabled" (dict "context" $) }} +*/}} +{{- define "common.postgresql.values.enabled" -}} + {{- if .subchart -}} + {{- printf "%v" .context.Values.postgresql.enabled -}} + {{- else -}} + {{- printf "%v" (not .context.Values.enabled) -}} + {{- end -}} +{{- end -}} + +{{/* +Auxiliary function to get the right value for the key postgressPassword. + +Usage: +{{ include "common.postgresql.values.key.postgressPassword" (dict "subchart" "true" "context" $) }} +Params: + - subchart - Boolean - Optional. Whether postgresql is used as subchart or not. Default: false +*/}} +{{- define "common.postgresql.values.key.postgressPassword" -}} + {{- $globalValue := include "common.postgresql.values.use.global" (dict "key" "postgresqlUsername" "context" .context) -}} + + {{- if not $globalValue -}} + {{- if .subchart -}} + postgresql.postgresqlPassword + {{- else -}} + postgresqlPassword + {{- end -}} + {{- else -}} + global.postgresql.postgresqlPassword + {{- end -}} +{{- end -}} + +{{/* +Auxiliary function to get the right value for enabled.replication. + +Usage: +{{ include "common.postgresql.values.enabled.replication" (dict "subchart" "true" "context" $) }} +Params: + - subchart - Boolean - Optional. Whether postgresql is used as subchart or not. Default: false +*/}} +{{- define "common.postgresql.values.enabled.replication" -}} + {{- if .subchart -}} + {{- printf "%v" .context.Values.postgresql.replication.enabled -}} + {{- else -}} + {{- printf "%v" .context.Values.replication.enabled -}} + {{- end -}} +{{- end -}} + +{{/* +Auxiliary function to get the right value for the key replication.password. + +Usage: +{{ include "common.postgresql.values.key.replicationPassword" (dict "subchart" "true" "context" $) }} +Params: + - subchart - Boolean - Optional. Whether postgresql is used as subchart or not. Default: false +*/}} +{{- define "common.postgresql.values.key.replicationPassword" -}} + {{- if .subchart -}} + postgresql.replication.password + {{- else -}} + replication.password + {{- end -}} +{{- end -}} diff --git a/helm-charts/keydb/charts/common/templates/validations/_redis.tpl b/helm-charts/keydb/charts/common/templates/validations/_redis.tpl new file mode 100644 index 0000000..9fedfef --- /dev/null +++ b/helm-charts/keydb/charts/common/templates/validations/_redis.tpl @@ -0,0 +1,48 @@ +{{/* +Copyright Broadcom, Inc. All Rights Reserved. +SPDX-License-Identifier: APACHE-2.0 +*/}} + + +{{/* vim: set filetype=mustache: */}} +{{/* +Auxiliary function to get the right value for enabled redis. + +Usage: +{{ include "common.redis.values.enabled" (dict "context" $) }} +*/}} +{{- define "common.redis.values.enabled" -}} + {{- if .subchart -}} + {{- printf "%v" .context.Values.redis.enabled -}} + {{- else -}} + {{- printf "%v" (not .context.Values.enabled) -}} + {{- end -}} +{{- end -}} + +{{/* +Auxiliary function to get the right prefix path for the values + +Usage: +{{ include "common.redis.values.key.prefix" (dict "subchart" "true" "context" $) }} +Params: + - subchart - Boolean - Optional. Whether redis is used as subchart or not. Default: false +*/}} +{{- define "common.redis.values.keys.prefix" -}} + {{- if .subchart -}}redis.{{- else -}}{{- end -}} +{{- end -}} + +{{/* +Checks whether the redis chart's includes the standarizations (version >= 14) + +Usage: +{{ include "common.redis.values.standarized.version" (dict "context" $) }} +*/}} +{{- define "common.redis.values.standarized.version" -}} + + {{- $standarizedAuth := printf "%s%s" (include "common.redis.values.keys.prefix" .) "auth" -}} + {{- $standarizedAuthValues := include "common.utils.getValueFromKey" (dict "key" $standarizedAuth "context" .context) }} + + {{- if $standarizedAuthValues -}} + {{- true -}} + {{- end -}} +{{- end -}} diff --git a/helm-charts/keydb/charts/common/templates/validations/_validations.tpl b/helm-charts/keydb/charts/common/templates/validations/_validations.tpl new file mode 100644 index 0000000..7cdee61 --- /dev/null +++ b/helm-charts/keydb/charts/common/templates/validations/_validations.tpl @@ -0,0 +1,51 @@ +{{/* +Copyright Broadcom, Inc. All Rights Reserved. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{/* vim: set filetype=mustache: */}} +{{/* +Validate values must not be empty. + +Usage: +{{- $validateValueConf00 := (dict "valueKey" "path.to.value" "secret" "secretName" "field" "password-00") -}} +{{- $validateValueConf01 := (dict "valueKey" "path.to.value" "secret" "secretName" "field" "password-01") -}} +{{ include "common.validations.values.empty" (dict "required" (list $validateValueConf00 $validateValueConf01) "context" $) }} + +Validate value params: + - valueKey - String - Required. The path to the validating value in the values.yaml, e.g: "mysql.password" + - secret - String - Optional. Name of the secret where the validating value is generated/stored, e.g: "mysql-passwords-secret" + - field - String - Optional. Name of the field in the secret data, e.g: "mysql-password" +*/}} +{{- define "common.validations.values.multiple.empty" -}} + {{- range .required -}} + {{- include "common.validations.values.single.empty" (dict "valueKey" .valueKey "secret" .secret "field" .field "context" $.context) -}} + {{- end -}} +{{- end -}} + +{{/* +Validate a value must not be empty. + +Usage: +{{ include "common.validations.value.empty" (dict "valueKey" "mariadb.password" "secret" "secretName" "field" "my-password" "subchart" "subchart" "context" $) }} + +Validate value params: + - valueKey - String - Required. The path to the validating value in the values.yaml, e.g: "mysql.password" + - secret - String - Optional. Name of the secret where the validating value is generated/stored, e.g: "mysql-passwords-secret" + - field - String - Optional. Name of the field in the secret data, e.g: "mysql-password" + - subchart - String - Optional - Name of the subchart that the validated password is part of. +*/}} +{{- define "common.validations.values.single.empty" -}} + {{- $value := include "common.utils.getValueFromKey" (dict "key" .valueKey "context" .context) }} + {{- $subchart := ternary "" (printf "%s." .subchart) (empty .subchart) }} + + {{- if not $value -}} + {{- $varname := "my-value" -}} + {{- $getCurrentValue := "" -}} + {{- if and .secret .field -}} + {{- $varname = include "common.utils.fieldToEnvVar" . -}} + {{- $getCurrentValue = printf " To get the current value:\n\n %s\n" (include "common.utils.secret.getvalue" .) -}} + {{- end -}} + {{- printf "\n '%s' must not be empty, please add '--set %s%s=$%s' to the command.%s" .valueKey $subchart .valueKey $varname $getCurrentValue -}} + {{- end -}} +{{- end -}} diff --git a/helm-charts/keydb/charts/common/values.yaml b/helm-charts/keydb/charts/common/values.yaml new file mode 100644 index 0000000..de2cac5 --- /dev/null +++ b/helm-charts/keydb/charts/common/values.yaml @@ -0,0 +1,8 @@ +# Copyright Broadcom, Inc. All Rights Reserved. +# SPDX-License-Identifier: APACHE-2.0 + +## bitnami/common +## It is required by CI/CD tools and processes. +## @skip exampleValue +## +exampleValue: common-chart diff --git a/helm-charts/keydb/templates/NOTES.txt b/helm-charts/keydb/templates/NOTES.txt new file mode 100644 index 0000000..c060c1a --- /dev/null +++ b/helm-charts/keydb/templates/NOTES.txt @@ -0,0 +1,168 @@ +CHART NAME: {{ .Chart.Name }} +CHART VERSION: {{ .Chart.Version }} +APP VERSION: {{ .Chart.AppVersion }} + +⚠ WARNING: Since August 28th, 2025, only a limited subset of images/charts are available for free. + Subscribe to Bitnami Secure Images to receive continued support and security updates. + More info at https://bitnami.com and https://github.com/bitnami/containers/issues/83267 + +** Please be patient while the chart is being deployed ** + +{{- if .Values.diagnosticMode.enabled }} +The chart has been deployed in diagnostic mode. All probes have been disabled and the command has been overwritten with: + + command: {{- include "common.tplvalues.render" (dict "value" .Values.diagnosticMode.command "context" $) | nindent 4 }} + args: {{- include "common.tplvalues.render" (dict "value" .Values.diagnosticMode.args "context" $) | nindent 4 }} + +Get the list of pods by executing: + + kubectl get pods --namespace {{ include "common.names.namespace" . | quote }} -l app.kubernetes.io/instance={{ .Release.Name }} + +Access the pod you want to debug by executing + + kubectl exec --namespace {{ include "common.names.namespace" . | quote }} -ti -- bash + +In order to replicate the container startup scripts execute this command: + + keydb-server /opt/bitnami/keydb/etc/keydb.conf + +{{- else }} + +{{- if contains .Values.master.service.type "LoadBalancer" }} +{{- if not .Values.auth.enabled }} +{{- if or (not .Values.master.networkPolicy.enabled) (and .Values.master.networkPolicy.enabled .Values.master.networkPolicy.allowExternal) }} + +------------------------------------------------------------------------------- + WARNING + + By specifying "master.service.type=LoadBalancer" and "auth.enabled=false" you have + most likely exposed the KeyDB service externally without any authentication + mechanism. + + For security reasons, we strongly suggest that you switch to "ClusterIP" or + "NodePort". As alternative, you can also switch to "auth.enabled=true" + providing a valid password on "password" parameter. + +------------------------------------------------------------------------------- +{{- end }} +{{- end }} +{{- end }} + +{{- if eq .Values.architecture "replication" }} + +KeyDB can be accessed on the following DNS names from within your cluster: + + {{ printf "%s.%s.svc.%s" (include "keydb.master.fullname" .) (include "common.names.namespace" . ) .Values.clusterDomain }} (port {{ .Values.master.service.ports.keydb }}) + {{ printf "%s.%s.svc.%s" (include "keydb.replica.fullname" .) (include "common.names.namespace" . ) .Values.clusterDomain }} (port {{ .Values.replica.service.ports.keydb }}){{ if not .Values.replica.activeReplica }} only for read operations{{ end }} + +{{- else }} + +KeyDB can be accessed via port {{ .Values.master.service.ports.keydb }} on the following DNS name from within your cluster: + + {{ include "keydb.master.fullname" . }}.{{ include "common.names.namespace" . }}.svc.{{ .Values.clusterDomain }} + +{{- end }} + +{{ if .Values.auth.enabled }} + +To get your password run: + + export KEYDB_PASSWORD=$(kubectl get secret --namespace {{ include "common.names.namespace" . }} {{ include "keydb.secretName" . }} -o jsonpath="{.data.{{ include "keydb.secretPasswordKey" . }}}" | base64 -d) + +{{- end }} + +To connect to your KeyDB server: + +1. Run a KeyDB pod that you can use as a client: + + kubectl run --namespace {{ include "common.names.namespace" . }} keydb-client --restart='Never' {{ if .Values.auth.enabled }} --env KEYDB_PASSWORD=$KEYDB_PASSWORD {{ end }} --image {{ template "keydb.image" . }} --command -- sleep infinity + +{{- if .Values.tls.enabled }} + + Copy your TLS certificates to the client pod: + + kubectl cp --namespace {{ include "common.names.namespace" . }} /path/to/client.cert keydb-client:/tmp/client.cert + kubectl cp --namespace {{ include "common.names.namespace" . }} /path/to/client.key keydb-client:/tmp/client.key + kubectl cp --namespace {{ include "common.names.namespace" . }} /path/to/CA.cert keydb-client:/tmp/CA.cert + +{{- end }} + + Use the following command to attach to the client pod: + + kubectl exec --tty -i keydb-client \ + {{- if and .Values.master.networkPolicy.enabled (not .Values.master.networkPolicy.allowExternal) }}--labels="{{ template "common.names.fullname" . }}-client=true" \{{- end }} + --namespace {{ include "common.names.namespace" . }} -- bash + +2. Connect using the KeyDB CLI: + +{{- if eq .Values.architecture "replication" }} + {{ if .Values.auth.enabled }}REDISCLI_AUTH="$KEYDB_PASSWORD" {{ end }}keydb-cli -h {{ include "keydb.master.fullname" . }} -p {{ .Values.master.service.ports.keydb }}{{ if .Values.tls.enabled }} --tls --cert /tmp/client.cert --key /tmp/client.key --cacert /tmp/CA.cert{{ end }} + {{ if .Values.auth.enabled }}REDISCLI_AUTH="$KEYDB_PASSWORD" {{ end }}keydb-cli -h {{ include "keydb.replica.fullname" . }} -p {{ .Values.replica.service.ports.keydb }}{{ if .Values.tls.enabled }} --tls --cert /tmp/client.cert --key /tmp/client.key --cacert /tmp/CA.cert{{ end }} +{{- else }} + {{ if .Values.auth.enabled }}REDISCLI_AUTH="$KEYDB_PASSWORD" {{ end }}keydb-cli -h {{ include "keydb.master.fullname" . }} -p {{ .Values.master.service.ports.keydb }}{{ if .Values.tls.enabled }} --tls --cert /tmp/client.cert --key /tmp/client.key --cacert /tmp/CA.cert{{ end }} +{{- end }} + +{{- if and .Values.master.networkPolicy.enabled (not .Values.master.networkPolicy.allowExternal) }} + +Note: Since NetworkPolicy is enabled, only pods with label {{ template "common.names.fullname" . }}-client=true" will be able to connect to KeyDB. + +{{- else }} + +To connect to your Master nodes from outside the cluster execute the following commands: + +{{- if contains "NodePort" .Values.master.service.type }} + + export NODE_IP=$(kubectl get nodes --namespace {{ include "common.names.namespace" . }} -o jsonpath="{.items[0].status.addresses[0].address}") + export NODE_PORT=$(kubectl get --namespace {{ include "common.names.namespace" . }} -o jsonpath="{.spec.ports[0].nodePort}" services {{ include "keydb.master.fullname" . }}) + {{ if .Values.auth.enabled }}REDISCLI_AUTH="$KEYDB_PASSWORD" {{ end }}keydb-cli -h $NODE_IP -p $NODE_PORT {{- if .Values.tls.enabled }} --tls --cert /tmp/client.cert --key /tmp/client.key --cacert /tmp/CA.cert{{ end }} + +{{- else if contains "LoadBalancer" .Values.master.service.type }} + + NOTE: It may take a few minutes for the LoadBalancer IP to be available. + Watch the status with: 'kubectl get svc --namespace {{ include "common.names.namespace" . }} -w {{ include "keydb.master.fullname" . }}' + + export SERVICE_IP=$(kubectl get svc --namespace {{ include "common.names.namespace" . }} {{ include "keydb.master.fullname" . }} --template "{{ "{{ range (index .status.loadBalancer.ingress 0) }}{{ . }}{{ end }}" }}") + {{ if .Values.auth.enabled }}REDISCLI_AUTH="$KEYDB_PASSWORD" {{ end }}keydb-cli -h $SERVICE_IP -p {{ .Values.master.service.ports.keydb }} {{- if .Values.tls.enabled }} --tls --cert /tmp/client.cert --key /tmp/client.key --cacert /tmp/CA.cert{{ end }} + +{{- else if contains "ClusterIP" .Values.master.service.type }} + + kubectl port-forward --namespace {{ include "common.names.namespace" . }} svc/{{ include "keydb.master.fullname" . }} {{ .Values.master.service.ports.keydb }}:{{ .Values.master.service.ports.keydb }} & + {{ if .Values.auth.enabled }}REDISCLI_AUTH="$KEYDB_PASSWORD" {{ end }}keydb-cli -h 127.0.0.1 -p {{ .Values.master.service.ports.keydb }} {{- if .Values.tls.enabled }} --tls --cert /tmp/client.cert --key /tmp/client.key --cacert /tmp/CA.cert{{ end }} + +{{- end }} + +{{- if eq .Values.architecture "replication" }} + +To connect to your Replica nodes from outside the cluster execute the following commands: + +{{- if contains "NodePort" .Values.replica.service.type }} + + export NODE_IP=$(kubectl get nodes --namespace {{ include "common.names.namespace" . }} -o jsonpath="{.items[0].status.addresses[0].address}") + export NODE_PORT=$(kubectl get --namespace {{ include "common.names.namespace" . }} -o jsonpath="{.spec.ports[0].nodePort}" services {{ include "keydb.replica.fullname" . }}) + {{ if .Values.auth.enabled }}REDISCLI_AUTH="$KEYDB_PASSWORD" {{ end }}keydb-cli -h $NODE_IP -p $NODE_PORT {{- if .Values.tls.enabled }} --tls --cert /tmp/client.cert --key /tmp/client.key --cacert /tmp/CA.cert{{ end }} + +{{- else if contains "LoadBalancer" .Values.replica.service.type }} + + NOTE: It may take a few minutes for the LoadBalancer IP to be available. + Watch the status with: 'kubectl get svc --namespace {{ include "common.names.namespace" . }} -w {{ include "keydb.replica.fullname" . }}' + + export SERVICE_IP=$(kubectl get svc --namespace {{ include "common.names.namespace" . }} {{ include "keydb.replica.fullname" . }} --template "{{ "{{ range (index .status.loadBalancer.ingress 0) }}{{ . }}{{ end }}" }}") + {{ if .Values.auth.enabled }}REDISCLI_AUTH="$KEYDB_PASSWORD" {{ end }}keydb-cli -h $SERVICE_IP -p {{ .Values.replica.service.ports.keydb }} {{- if .Values.tls.enabled }} --tls --cert /tmp/client.cert --key /tmp/client.key --cacert /tmp/CA.cert{{ end }} + +{{- else if contains "ClusterIP" .Values.replica.service.type }} + + kubectl port-forward --namespace {{ include "common.names.namespace" . }} svc/{{ include "keydb.replica.fullname" . }} {{ .Values.replica.service.ports.keydb }}:{{ .Values.replica.service.ports.keydb }} & + {{ if .Values.auth.enabled }}REDISCLI_AUTH="$KEYDB_PASSWORD" {{ end }}keydb-cli -h 127.0.0.1 -p {{ .Values.replica.service.ports.keydb }} {{- if .Values.tls.enabled }} --tls --cert /tmp/client.cert --key /tmp/client.key --cacert /tmp/CA.cert{{ end }} + +{{- end }} +{{- end }} +{{- end }} +{{- end }} + +{{- include "common.warnings.rollingTag" .Values.image }} +{{- include "common.warnings.rollingTag" .Values.metrics.image }} +{{- include "common.warnings.rollingTag" .Values.volumePermissions.image }} +{{- include "keydb.validateValues" . }} +{{- include "common.warnings.resources" (dict "sections" (list "master" "replica" "metrics" "volumePermissions") "context" $) }} +{{- include "common.warnings.modifiedImages" (dict "images" (list .Values.image .Values.metrics.image .Values.volumePermissions.image) "context" $) }} +{{- include "common.errors.insecureImages" (dict "images" (list .Values.image .Values.metrics.image .Values.volumePermissions.image) "context" $) }} diff --git a/helm-charts/keydb/templates/_helpers.tpl b/helm-charts/keydb/templates/_helpers.tpl index d175617..f5462a4 100644 --- a/helm-charts/keydb/templates/_helpers.tpl +++ b/helm-charts/keydb/templates/_helpers.tpl @@ -1,54 +1,49 @@ -{{/* vim: set filetype=mustache: */}} {{/* -Expand the name of the chart. +Copyright Broadcom, Inc. All Rights Reserved. +SPDX-License-Identifier: APACHE-2.0 */}} -{{- define "keydb.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. +Return the proper KeyDB Master fullname */}} -{{- define "keydb.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 "-" -}} +{{- define "keydb.master.fullname" -}} +{{- printf "%s-master" (include "common.names.fullname" .) | trunc 63 | trimSuffix "-" -}} {{- end -}} + +{{/* +Return the proper KeyDB Replicas fullname +*/}} +{{- define "keydb.replica.fullname" -}} +{{- printf "%s-replica" (include "common.names.fullname" .) | trunc 63 | trimSuffix "-" -}} {{- end -}} + +{{/* +Return the proper KeyDB image name +*/}} +{{- define "keydb.image" -}} +{{ include "common.images.image" (dict "imageRoot" .Values.image "global" .Values.global) }} {{- end -}} {{/* -Create chart name and version as used by the chart label. +Return the proper KeyDB metrics exporter name */}} -{{- define "keydb.chart" -}} -{{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" -}} +{{- define "keydb.metrics.image" -}} +{{- include "common.images.image" ( dict "imageRoot" .Values.metrics.image "global" .Values.global ) -}} {{- end -}} + {{/* -Common labels +Return the proper image name (for the init container volume-permissions image) */}} -{{- define "keydb.labels" -}} -helm.sh/chart: {{ include "keydb.chart" . }} -{{ include "keydb.selectorLabels" . }} -{{- if .Chart.AppVersion }} -app.kubernetes.io/version: {{ .Chart.AppVersion | quote }} -{{- end }} -app.kubernetes.io/managed-by: {{ .Release.Service }} +{{- define "keydb.volumePermissions.image" -}} +{{- include "common.images.image" ( dict "imageRoot" .Values.volumePermissions.image "global" .Values.global ) -}} {{- end -}} {{/* -Selector labels +Return the proper Docker Image Registry Secret Names */}} -{{- define "keydb.selectorLabels" -}} -app.kubernetes.io/name: {{ include "keydb.name" . }} -app.kubernetes.io/instance: {{ .Release.Name }} +{{- define "keydb.imagePullSecrets" -}} +{{- include "common.images.renderPullSecrets" (dict "images" (list .Values.image .Values.metrics.image .Values.volumePermissions.image) "context" $) -}} {{- end -}} {{/* @@ -56,16 +51,163 @@ Create the name of the service account to use */}} {{- define "keydb.serviceAccountName" -}} {{- if .Values.serviceAccount.create -}} - {{ default (include "keydb.fullname" .) .Values.serviceAccount.name }} + {{ default (include "common.names.fullname" .) .Values.serviceAccount.name }} {{- else -}} {{ default "default" .Values.serviceAccount.name }} {{- end -}} {{- end -}} -{{- define "common.tplvalues.render" -}} - {{- if typeIs "string" .value }} - {{- tpl .value .context }} - {{- else }} - {{- tpl (.value | toYaml) .context }} - {{- end }} -{{- end -}} \ No newline at end of file +{{/* +Return the name of the configmap with KeyDB master configuration +*/}} +{{- define "keydb.master.configmapName" -}} +{{- if .Values.master.existingConfigmap -}} + {{- print (tpl .Values.master.existingConfigmap $) -}} +{{- else -}} + {{- printf "%s-config" (include "keydb.master.fullname" .) -}} +{{- end -}} +{{- end -}} + +{{/* +Return the name of the configmap with KeyDB replica configuration +*/}} +{{- define "keydb.replica.configmapName" -}} +{{- if .Values.replica.existingConfigmap -}} + {{- print (tpl .Values.replica.existingConfigmap $) -}} +{{- else -}} + {{- printf "%s-config" (include "keydb.replica.fullname" .) -}} +{{- end -}} +{{- end -}} + +{{/* +Return the name of the secret with KeyDB credentials +*/}} +{{- define "keydb.secretName" -}} +{{- if .Values.auth.existingSecret -}} + {{- print (tpl .Values.auth.existingSecret $) -}} +{{- else -}} + {{- print (include "common.names.fullname" .) -}} +{{- end -}} +{{- end -}} + +{{/* +Get the password key to be retrieved from KeyDB secret +*/}} +{{- define "keydb.secretPasswordKey" -}} +{{- if and .Values.auth.existingSecret .Values.auth.existingSecretPasswordKey -}} + {{- print (tpl .Values.auth.existingSecretPasswordKey $) -}} +{{- else -}} + {{- print "keydb-password" -}} +{{- end -}} +{{- end -}} + +{{/* +Return the name of the secret containing the TLS certificates for KeyDB master nodes +*/}} +{{- define "keydb.tls.master.secretName" -}} +{{- if or .Values.tls.autoGenerated.enabled (and (not (empty .Values.tls.master.cert)) (not (empty .Values.tls.master.key))) -}} + {{- printf "%s-crt" (include "keydb.master.fullname" .) -}} +{{- else -}} + {{- required "An existing secret name must be provided with TLS certs for KeyDB master if cert and key are not provided!" (tpl .Values.tls.master.existingSecret .) -}} +{{- end -}} +{{- end -}} + +{{/* +Return the name of the secret containing the TLS certificates for KeyDB replica nodes +*/}} +{{- define "keydb.tls.replica.secretName" -}} +{{- if or .Values.tls.autoGenerated.enabled (and (not (empty .Values.tls.replica.cert)) (not (empty .Values.tls.replica.key))) -}} + {{- printf "%s-crt" (include "keydb.replica.fullname" .) -}} +{{- else -}} + {{- required "An existing secret name must be provided with TLS certs for KeyDB replica if cert and key are not provided!" (tpl .Values.tls.replica.existingSecret .) -}} +{{- end -}} +{{- end -}} + +{{/* +Compile all warnings into a single message. +*/}} +{{- define "keydb.validateValues" -}} +{{- $messages := list -}} +{{- $messages := append $messages (include "keydb.validateValues.architecture" .) -}} +{{- $messages := append $messages (include "keydb.validateValues.master.replicaCount" .) -}} +{{- $messages := append $messages (include "keydb.validateValues.replica.replicaCount" .) -}} +{{- $messages := append $messages (include "keydb.validateValues.tls" .) -}} +{{- $messages := without $messages "" -}} +{{- $message := join "\n" $messages -}} + +{{- if $message -}} +{{- printf "\nVALUES VALIDATION:\n%s" $message -}} +{{- end -}} +{{- end -}} + +{{/* +Validate values of KeyDB - must provide a valid architecture +*/}} +{{- define "keydb.validateValues.architecture" -}} +{{- if and (ne .Values.architecture "standalone") (ne .Values.architecture "replication") -}} +architecture + Invalid architecture selected. Valid values are "standalone" and + "replication". Please set a valid architecture (--set architecture="xxxx") +{{- end -}} +{{- end -}} + +{{/* +Validate values of KeyDB - number of Master replicas +*/}} +{{- define "keydb.validateValues.master.replicaCount" -}} +{{- $masterReplicaCount := int .Values.master.replicaCount }} +{{- $replicaReplicaCount := int .Values.replica.replicaCount }} +{{- if and .Values.master.persistence.enabled .Values.master.persistence.existingClaim (gt $masterReplicaCount 1) -}} +master.replicaCount + A single existing PVC cannot be shared between multiple Master replicas. + Please set a valid number of replicas (--set master.replicaCount=1), disable persistence + (--set master.persistence.enabled=false) or rely on dynamic provisioning via Persistent + Volume Claims (--set master.persistence.existingClaim=""). +{{- end -}} +{{- if and (eq .Values.architecture "replication") (gt $masterReplicaCount 1) (gt $replicaReplicaCount 0) (not .Values.replica.activeReplica) -}} +master.replicaCount + Multipe Master replicas are only supported when replicas are configured as active replicas. + Please set a valid number of replicas (--set master.replicaCount=1), set replicas as active + (--set replica.activeReplica=true) or disable replication (--set architecture="standalone"). +{{- end -}} +{{- end -}} + +{{/* +Validate values of KeyDB - number of Replicas +*/}} +{{- define "keydb.validateValues.replica.replicaCount" -}} +{{- $replicaReplicaCount := int .Values.replica.replicaCount }} +{{- if and .Values.replica.persistence.enabled .Values.replica.persistence.existingClaim (or (gt $replicaReplicaCount 1) .Values.replica.autoscaling.hpa.enabled) -}} +replica.replicaCount + A single existing PVC cannot be shared between multiple Replicas. + Please set a valid number of replicas (--set replica.replicaCount=1), + disable HPA (--set replica.autoscaling.hpa.enabled=false), disable persistence + (--set replica.persistence.enabled=false) or rely on dynamic provisioning via Persistent + Volume Claims (--set replica.persistence.existingClaim=""). +{{- end -}} +{{- end -}} + +{{/* +Validate values of KeyDB - TLS +*/}} +{{- define "keydb.validateValues.tls" -}} +{{- if and .Values.tls.enabled .Values.tls.autoGenerated.enabled -}} +{{- if or (not (empty .Values.tls.ca)) (not (empty .Values.tls.master.cert)) (not (empty .Values.tls.master.key)) (not (empty .Values.tls.replica.cert)) (not (empty .Values.tls.replica.key)) -}} +tls.autoGenerated + When enabling auto-generated TLS certificates, all certificate and key fields must be empty. + Please disable auto-generated TLS certificates (--set tls.autoGenerated.enabled=false) or + remove the certificate and key fields. +{{- end -}} +{{- if or (not (empty .Values.tls.existingCASecret) ) (not (empty .Values.tls.master.existingSecret)) (not (empty .Values.tls.replica.existingSecret)) -}} +tls.autoGenerated + When enabling auto-generated TLS certificates, all existing secret fields must be empty. + Please disable auto-generated TLS certificates (--set tls.autoGenerated.enabled=false) or + remove the existing secret fields. +{{- end -}} +{{- if and (ne .Values.tls.autoGenerated.engine "helm") (ne .Values.tls.autoGenerated.engine "cert-manager") -}} +tls.autoGenerated.engine + Invalid mechanism to generate the TLS certificates selected. Valid values are "helm" and + "cert-manager". Please set a valid one (--set tls.autoGenerated.engine="xxx") +{{- end -}} +{{- end -}} +{{- end -}} diff --git a/helm-charts/keydb/templates/ca-cert.yaml b/helm-charts/keydb/templates/ca-cert.yaml new file mode 100644 index 0000000..ff2f298 --- /dev/null +++ b/helm-charts/keydb/templates/ca-cert.yaml @@ -0,0 +1,53 @@ +{{- /* +Copyright Broadcom, Inc. All Rights Reserved. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{- if and .Values.tls.enabled .Values.tls.autoGenerated.enabled (eq .Values.tls.autoGenerated.engine "cert-manager") }} +{{- if empty .Values.tls.autoGenerated.certManager.existingIssuer }} +apiVersion: cert-manager.io/v1 +kind: Issuer +metadata: + name: {{ printf "%s-clusterissuer" (include "common.names.fullname" .) }} + namespace: {{ include "common.names.namespace" . | quote }} + labels: {{- include "common.labels.standard" ( dict "customLabels" .Values.commonLabels "context" $ ) | nindent 4 }} + app.kubernetes.io/part-of: keydb + {{- if .Values.commonAnnotations }} + annotations: {{- include "common.tplvalues.render" ( dict "value" .Values.commonAnnotations "context" $ ) | nindent 4 }} + {{- end }} +spec: + selfSigned: {} +--- +{{- end }} +apiVersion: cert-manager.io/v1 +kind: Certificate +metadata: + name: {{ printf "%s-ca-crt" (include "common.names.fullname" .) }} + namespace: {{ include "common.names.namespace" . | quote }} + labels: {{- include "common.labels.standard" ( dict "customLabels" .Values.commonLabels "context" $ ) | nindent 4 }} + app.kubernetes.io/part-of: keydb + {{- if .Values.commonAnnotations }} + annotations: {{- include "common.tplvalues.render" ( dict "value" .Values.commonAnnotations "context" $ ) | nindent 4 }} + {{- end }} +spec: + secretName: {{ printf "%s-ca-crt" (include "common.names.fullname" .) }} + commonName: {{ printf "%s-root-ca" (include "common.names.fullname" .) }} + isCA: true + issuerRef: + name: {{ default (printf "%s-clusterissuer" (include "common.names.fullname" .)) .Values.tls.autoGenerated.certManager.existingIssuer }} + kind: {{ default "Issuer" .Values.tls.autoGenerated.certManager.existingIssuerKind }} +--- +apiVersion: cert-manager.io/v1 +kind: Issuer +metadata: + name: {{ printf "%s-ca-issuer" (include "common.names.fullname" .) }} + namespace: {{ include "common.names.namespace" . | quote }} + labels: {{- include "common.labels.standard" ( dict "customLabels" .Values.commonLabels "context" $ ) | nindent 4 }} + app.kubernetes.io/part-of: keydb + {{- if .Values.commonAnnotations }} + annotations: {{- include "common.tplvalues.render" ( dict "value" .Values.commonAnnotations "context" $ ) | nindent 4 }} + {{- end }} +spec: + ca: + secretName: {{ printf "%s-ca-crt" (include "common.names.fullname" .) }} +{{- end }} diff --git a/helm-charts/keydb/templates/cm-health.yaml b/helm-charts/keydb/templates/cm-health.yaml deleted file mode 100644 index 7034cfd..0000000 --- a/helm-charts/keydb/templates/cm-health.yaml +++ /dev/null @@ -1,80 +0,0 @@ -apiVersion: v1 -kind: ConfigMap -metadata: - name: {{ include "keydb.fullname" . }}-health - labels: - {{- include "keydb.labels" . | nindent 4 }} -data: - ping_readiness_local.sh: |- - #!/bin/bash - - set -e - - loading_response="LOADING KeyDB is loading the dataset in memory" - - [[ -n "${REDIS_PASSWORD}" ]] && export REDISCLI_AUTH="${REDIS_PASSWORD}" - response="$( - timeout -s 15 "${1}" \ - keydb-cli \ - -h localhost \ - -p "${REDIS_PORT}" \ - GET {{ .Values.readinessProbeRandomUuid }} - )" - if [ "${response}" = "${loading_response}" ]; 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 15 "${1}" \ - keydb-cli \ - -h localhost \ - -p "${REDIS_PORT}" \ - PING - )" - if [ "${response}" != "PONG" ]; then - echo "${response}" - exit 1 - fi - -{{- if .Values.scripts.enabled }} - - scripts_local.sh: |- - #!/bin/bash - - set -e - - script_dir="$(dirname "$0")" - while true; do -{{- if .Values.scripts.cleanupCoredumps.enabled }} - "${script_dir}/cleanup_coredumps.sh" -{{- end }} -{{- if .Values.scripts.cleanupTempfiles.enabled }} - "${script_dir}/cleanup_tempfiles.sh" -{{- end }} - sleep 60 - done -{{- end }} - -{{- if .Values.scripts.cleanupCoredumps.enabled }} - cleanup_coredumps.sh: |- - #!/bin/bash - - set -e - - find /data/ -type f -name "core.*" -mmin +{{ .Values.scripts.cleanupCoredumps.minutes }} -delete -{{- end }} -{{- if .Values.scripts.cleanupTempfiles.enabled }} - cleanup_tempfiles.sh: |- - #!/bin/bash - - set -e - - find /data/ -type f \( -name "temp-*.aof" -o -name "temp-*.rdb" \) -mmin +{{ .Values.scripts.cleanupTempfiles.minutes }} -delete -{{- end }} diff --git a/helm-charts/keydb/templates/extra-list.yaml b/helm-charts/keydb/templates/extra-list.yaml new file mode 100644 index 0000000..329f5c6 --- /dev/null +++ b/helm-charts/keydb/templates/extra-list.yaml @@ -0,0 +1,9 @@ +{{- /* +Copyright Broadcom, Inc. All Rights Reserved. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{- range .Values.extraDeploy }} +--- +{{ include "common.tplvalues.render" (dict "value" . "context" $) }} +{{- end }} diff --git a/helm-charts/keydb/templates/health-configmap.yaml b/helm-charts/keydb/templates/health-configmap.yaml new file mode 100644 index 0000000..9c0efaa --- /dev/null +++ b/helm-charts/keydb/templates/health-configmap.yaml @@ -0,0 +1,156 @@ +{{- /* +Copyright Broadcom, Inc. All Rights Reserved. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +apiVersion: v1 +kind: ConfigMap +metadata: + name: {{ printf "%s-health" (include "common.names.fullname" .) }} + namespace: {{ include "common.names.namespace" . | quote }} + labels: {{- include "common.labels.standard" ( dict "customLabels" .Values.commonLabels "context" $ ) | nindent 4 }} + app.kubernetes.io/part-of: keydb + {{- if .Values.commonAnnotations }} + annotations: {{- include "common.tplvalues.render" ( dict "value" .Values.commonAnnotations "context" $ ) | nindent 4 }} + {{- end }} +data: + ping_readiness_local.sh: |- + #!/bin/bash + + . /opt/bitnami/scripts/keydb-env.sh + . /opt/bitnami/scripts/liblog.sh + + response=$( + timeout -s 15 $1 \ + keydb-cli \ + -h localhost \ + {{- if .Values.auth.enabled }} + -a "$KEYDB_PASSWORD" \ + {{- end }} + {{- if .Values.tls.enabled }} + --tls \ + --cacert /opt/bitnami/keydb/certs/ca.crt \ + --cert /opt/bitnami/keydb/certs/tls.crt \ + --key /opt/bitnami/keydb/certs/tls.key \ + {{- end }} + -p $KEYDB_PORT_NUMBER \ + ping + ) + if [[ "$?" -eq "124" ]]; then + error "Timed out" + exit 1 + fi + if [[ "$response" != "PONG" ]]; then + error "$response" + exit 1 + fi + ping_liveness_local.sh: |- + #!/bin/bash + + . /opt/bitnami/scripts/keydb-env.sh + . /opt/bitnami/scripts/liblog.sh + + response=$( + timeout -s 15 $1 \ + keydb-cli \ + -h localhost \ + {{- if .Values.auth.enabled }} + -a "$KEYDB_PASSWORD" \ + {{- end }} + {{- if .Values.tls.enabled }} + --tls \ + --cacert /opt/bitnami/keydb/certs/ca.crt \ + --cert /opt/bitnami/keydb/certs/tls.crt \ + --key /opt/bitnami/keydb/certs/tls.key \ + {{- end }} + -p $KEYDB_PORT_NUMBER \ + ping + ) + if [[ "$?" -eq "124" ]]; then + error "Timed out" + exit 1 + fi + responseFirstWord="$(echo "$response" | head -n1 | awk '{print $1;}')" + if [[ "$response" != "PONG" ]] && [[ "$responseFirstWord" != "LOADING" ]] && [[ "$responseFirstWord" != "MASTERDOWN" ]]; then + error "$response" + exit 1 + fi +{{- if eq .Values.architecture "replication" }} + ping_readiness_master.sh: |- + #!/bin/bash + + . /opt/bitnami/scripts/keydb-env.sh + . /opt/bitnami/scripts/liblog.sh + + response=$( + timeout -s 15 $1 \ + keydb-cli \ + -h {{ include "keydb.master.fullname" . }} \ + -p {{ .Values.master.service.ports.keydb }} \ + {{- if .Values.auth.enabled }} + -a "$KEYDB_MASTER_PASSWORD" \ + {{- end }} + {{- if .Values.tls.enabled }} + --tls \ + --cacert /opt/bitnami/keydb/certs/ca.crt \ + --cert /opt/bitnami/keydb/certs/tls.crt \ + --key /opt/bitnami/keydb/certs/tls.key \ + {{- end }} + ping + ) + if [[ "$?" -eq "124" ]]; then + error "Timed out" + exit 1 + fi + if [[ "$response" != "PONG" ]]; then + error "$response" + exit 1 + fi + ping_liveness_master.sh: |- + #!/bin/bash + + . /opt/bitnami/scripts/keydb-env.sh + . /opt/bitnami/scripts/liblog.sh + + response=$( + timeout -s 15 $1 \ + keydb-cli \ + -h {{ include "keydb.master.fullname" . }} \ + -p {{ .Values.master.service.ports.keydb }} \ + {{- if .Values.auth.enabled }} + -a "$KEYDB_MASTER_PASSWORD" \ + {{- end }} + {{- if .Values.tls.enabled }} + --tls \ + --cacert /opt/bitnami/keydb/certs/ca.crt \ + --cert /opt/bitnami/keydb/certs/tls.crt \ + --key /opt/bitnami/keydb/certs/tls.key \ + {{- end }} + ping + ) + if [[ "$?" -eq "124" ]]; then + error "Timed out" + exit 1 + fi + responseFirstWord="$(echo "$response" | head -n1 | awk '{print $1;}')" + if [[ "$response" != "PONG" ]] && [[ "$responseFirstWord" != "LOADING" ]]; then + error "$response" + exit 1 + fi + ping_readiness_local_and_master.sh: |- + #!/bin/bash + + script_dir="$(dirname "$0")" + exit_status=0 + "$script_dir/ping_readiness_local.sh" $1 || exit_status=$? + "$script_dir/ping_readiness_master.sh" $1 || exit_status=$? + exit $exit_status + ping_liveness_local_and_master.sh: |- + #!/bin/bash + + script_dir="$(dirname "$0")" + exit_status=0 + "$script_dir/ping_liveness_local.sh" $1 || exit_status=$? + "$script_dir/ping_liveness_master.sh" $1 || exit_status=$? + exit $exit_status +{{- end }} diff --git a/helm-charts/keydb/templates/master/cert.yaml b/helm-charts/keydb/templates/master/cert.yaml new file mode 100644 index 0000000..3684b43 --- /dev/null +++ b/helm-charts/keydb/templates/master/cert.yaml @@ -0,0 +1,44 @@ +{{- /* +Copyright Broadcom, Inc. All Rights Reserved. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{- if and .Values.tls.enabled .Values.tls.autoGenerated.enabled (eq .Values.tls.autoGenerated.engine "cert-manager") }} +apiVersion: cert-manager.io/v1 +kind: Certificate +metadata: + name: {{ printf "%s-crt" (include "keydb.master.fullname" .) }} + namespace: {{ include "common.names.namespace" . | quote }} + labels: {{- include "common.labels.standard" ( dict "customLabels" .Values.commonLabels "context" $ ) | nindent 4 }} + app.kubernetes.io/part-of: keydb + app.kubernetes.io/component: master + {{- if .Values.commonAnnotations }} + annotations: {{- include "common.tplvalues.render" ( dict "value" .Values.commonAnnotations "context" $ ) | nindent 4 }} + {{- end }} +spec: + secretName: {{ template "keydb.tls.master.secretName" . }} + commonName: {{ printf "%s.%s.svc.%s" (include "keydb.master.fullname" .) (include "common.names.namespace" .) .Values.clusterDomain }} + issuerRef: + name: {{ printf "%s-ca-issuer" (include "common.names.fullname" .) }} + kind: Issuer + subject: + organizations: + - "KeyDB" + dnsNames: + - '*.{{ include "common.names.namespace" . }}' + - '*.{{ include "common.names.namespace" . }}.svc' + - '*.{{ include "common.names.namespace" . }}.svc.{{ .Values.clusterDomain }}' + - '*.{{ include "keydb.master.fullname" . }}' + - '*.{{ include "keydb.master.fullname" . }}.{{ include "common.names.namespace" . }}' + - '*.{{ include "keydb.master.fullname" . }}.{{ include "common.names.namespace" . }}.svc' + - '*.{{ include "keydb.master.fullname" . }}.{{ include "common.names.namespace" . }}.svc.{{ .Values.clusterDomain }}' + - '*.{{ printf "%s-hl" (include "keydb.master.fullname" .) }}' + - '*.{{ printf "%s-hl" (include "keydb.master.fullname" .) }}.{{ include "common.names.namespace" . }}' + - '*.{{ printf "%s-hl" (include "keydb.master.fullname" .) }}.{{ include "common.names.namespace" . }}.svc' + - '*.{{ printf "%s-hl" (include "keydb.master.fullname" .) }}.{{ include "common.names.namespace" . }}.svc.{{ .Values.clusterDomain }}' + privateKey: + algorithm: {{ .Values.tls.autoGenerated.certManager.keyAlgorithm }} + size: {{ int .Values.tls.autoGenerated.certManager.keySize }} + duration: {{ .Values.tls.autoGenerated.certManager.duration }} + renewBefore: {{ .Values.tls.autoGenerated.certManager.renewBefore }} +{{- end }} diff --git a/helm-charts/keydb/templates/master/configmap.yaml b/helm-charts/keydb/templates/master/configmap.yaml new file mode 100644 index 0000000..f01fedd --- /dev/null +++ b/helm-charts/keydb/templates/master/configmap.yaml @@ -0,0 +1,54 @@ +{{- /* +Copyright Broadcom, Inc. All Rights Reserved. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{- if not .Values.master.existingConfigmap }} +apiVersion: v1 +kind: ConfigMap +metadata: + name: {{ template "keydb.master.configmapName" . }} + namespace: {{ include "common.names.namespace" . | quote }} + labels: {{- include "common.labels.standard" ( dict "customLabels" .Values.commonLabels "context" $ ) | nindent 4 }} + app.kubernetes.io/part-of: keydb + app.kubernetes.io/component: master + {{- if .Values.commonAnnotations }} + annotations: {{- include "common.tplvalues.render" ( dict "value" .Values.commonAnnotations "context" $ ) | nindent 4 }} + {{- end }} +data: + keydb.conf: |- + {{- if .Values.commonConfiguration }} + {{- include "common.tplvalues.render" (dict "value" .Values.commonConfiguration "context" .) | nindent 4 }} + {{- else }} + # Enable AOF + # ref: https://docs.keydb.dev/docs/persistence/#append-only-file + appendonly yes + # Disable RDB persistence, AOF persistence already enabled + # ref: https://docs.keydb.dev/docs/persistence/#rdb-disadvantages + save "" + loglevel notice + {{- end }} + {{- if .Values.master.configuration }} + {{- include "common.tplvalues.render" ( dict "value" .Values.master.configuration "context" $ ) | nindent 4 }} + {{- else }} + bind 0.0.0.0 :: + dir {{ .Values.master.persistence.mountPath }} + {{- if not .Values.auth.enabled }} + protected-mode no + {{- end }} + {{- if .Values.tls.enabled }} + port 0 + tls-port {{ .Values.master.containerPorts.keydb }} + tls-cert-file /opt/bitnami/keydb/certs/tls.crt + tls-key-file /opt/bitnami/keydb/certs/tls.key + tls-ca-cert-file /opt/bitnami/keydb/certs/ca.crt + tls-auth-clients optional + {{- else }} + port {{ .Values.master.containerPorts.keydb }} + {{- end }} + {{- range .Values.master.disableCommands }} + rename-command {{ . }} "" + {{- end }} + {{- end }} + +{{- end }} diff --git a/helm-charts/keydb/templates/master/headless-service.yaml b/helm-charts/keydb/templates/master/headless-service.yaml new file mode 100644 index 0000000..ca8e734 --- /dev/null +++ b/helm-charts/keydb/templates/master/headless-service.yaml @@ -0,0 +1,28 @@ +{{- /* +Copyright Broadcom, Inc. All Rights Reserved. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +apiVersion: v1 +kind: Service +metadata: + name: {{ printf "%s-hl" (include "keydb.master.fullname" .) }} + namespace: {{ include "common.names.namespace" . | quote }} + labels: {{- include "common.labels.standard" ( dict "customLabels" .Values.commonLabels "context" $ ) | nindent 4 }} + app.kubernetes.io/part-of: keydb + app.kubernetes.io/component: master + {{- if or .Values.master.service.headless.annotations .Values.commonAnnotations }} + {{- $annotations := include "common.tplvalues.merge" (dict "values" (list .Values.master.service.headless.annotations .Values.commonAnnotations) "context" .) }} + annotations: {{- include "common.tplvalues.render" ( dict "value" $annotations "context" $ ) | nindent 4 }} + {{- end }} +spec: + type: ClusterIP + clusterIP: None + ports: + - name: tcp-keydb + port: {{ .Values.master.containerPorts.keydb }} + targetPort: keydb + {{- $podLabels := include "common.tplvalues.merge" (dict "values" (list .Values.master.podLabels .Values.commonLabels) "context" .) | fromYaml }} + selector: {{- include "common.labels.matchLabels" ( dict "customLabels" $podLabels "context" $ ) | nindent 4 }} + app.kubernetes.io/part-of: keydb + app.kubernetes.io/component: master diff --git a/helm-charts/keydb/templates/master/networkpolicy.yaml b/helm-charts/keydb/templates/master/networkpolicy.yaml new file mode 100644 index 0000000..4efc893 --- /dev/null +++ b/helm-charts/keydb/templates/master/networkpolicy.yaml @@ -0,0 +1,79 @@ +{{- /* +Copyright Broadcom, Inc. All Rights Reserved. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{- if .Values.master.networkPolicy.enabled }} +kind: NetworkPolicy +apiVersion: {{ include "common.capabilities.networkPolicy.apiVersion" . }} +metadata: + name: {{ template "keydb.master.fullname" . }} + namespace: {{ include "common.names.namespace" . | quote }} + labels: {{- include "common.labels.standard" ( dict "customLabels" .Values.commonLabels "context" $ ) | nindent 4 }} + app.kubernetes.io/part-of: keydb + app.kubernetes.io/component: master + {{- if .Values.commonAnnotations }} + annotations: {{- include "common.tplvalues.render" ( dict "value" .Values.commonAnnotations "context" $ ) | nindent 4 }} + {{- end }} +spec: + {{- $podLabels := include "common.tplvalues.merge" ( dict "values" ( list .Values.master.podLabels .Values.commonLabels ) "context" . ) }} + podSelector: + matchLabels: {{- include "common.labels.matchLabels" ( dict "customLabels" $podLabels "context" $ ) | nindent 6 }} + app.kubernetes.io/part-of: keydb + app.kubernetes.io/component: master + policyTypes: + - Ingress + - Egress + egress: + {{- if .Values.master.networkPolicy.allowExternalEgress }} + - {} + {{- else }} + - ports: + # Allow dns resolution + - port: 53 + protocol: UDP + - port: 53 + protocol: TCP + {{- if .Values.master.networkPolicy.extraEgress }} + {{- include "common.tplvalues.render" ( dict "value" .Values.master.networkPolicy.extraEgress "context" $ ) | nindent 4 }} + {{- end }} + {{- end }} + ingress: + - ports: + - port: {{ .Values.master.containerPorts.keydb }} + {{- if .Values.metrics.enabled }} + - port: {{ .Values.metrics.containerPorts.http }} + {{- if ne .Values.metrics.containerPorts.http .Values.metrics.service.port }} + - port: {{ .Values.metrics.service.port }} + {{- end }} + {{- end }} + {{- range .Values.master.extraContainerPorts }} + - port: {{ .containerPort }} + {{- end }} + {{- if not .Values.master.networkPolicy.allowExternal }} + from: + - podSelector: + matchLabels: {{- include "common.labels.matchLabels" ( dict "customLabels" .Values.commonLabels "context" $ ) | nindent 14 }} + {{- if .Values.master.networkPolicy.addExternalClientAccess }} + - podSelector: + matchLabels: + {{ template "common.names.fullname" . }}-client: "true" + {{- end }} + {{- if .Values.master.networkPolicy.ingressPodMatchLabels }} + - podSelector: + matchLabels: {{- include "common.tplvalues.render" (dict "value" .Values.master.networkPolicy.ingressPodMatchLabels "context" $ ) | nindent 14 }} + {{- end }} + {{- if .Values.master.networkPolicy.ingressNSMatchLabels }} + - namespaceSelector: + matchLabels: {{- include "common.tplvalues.render" (dict "value" .Values.master.networkPolicy.ingressNSMatchLabels "context" $ ) | nindent 14 }} + {{- if .Values.master.networkPolicy.ingressNSPodMatchLabels }} + podSelector: + matchLabels: + matchLabels: {{- include "common.tplvalues.render" (dict "value" .Values.master.networkPolicy.ingressNSPodMatchLabels "context" $ ) | nindent 14 }} + {{- end }} + {{- end }} + {{- end }} + {{- if .Values.master.networkPolicy.extraIngress }} + {{- include "common.tplvalues.render" ( dict "value" .Values.master.networkPolicy.extraIngress "context" $ ) | nindent 4 }} + {{- end }} +{{- end }} diff --git a/helm-charts/keydb/templates/master/pdb.yaml b/helm-charts/keydb/templates/master/pdb.yaml new file mode 100644 index 0000000..ebe83b5 --- /dev/null +++ b/helm-charts/keydb/templates/master/pdb.yaml @@ -0,0 +1,30 @@ +{{- /* +Copyright Broadcom, Inc. All Rights Reserved. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{- if .Values.master.pdb.create }} +apiVersion: {{ include "common.capabilities.policy.apiVersion" . }} +kind: PodDisruptionBudget +metadata: + name: {{ template "keydb.master.fullname" . }} + namespace: {{ include "common.names.namespace" . | quote }} + labels: {{- include "common.labels.standard" ( dict "customLabels" .Values.commonLabels "context" $ ) | nindent 4 }} + app.kubernetes.io/part-of: keydb + app.kubernetes.io/component: master + {{- if .Values.commonAnnotations }} + annotations: {{- include "common.tplvalues.render" ( dict "value" .Values.commonAnnotations "context" $ ) | nindent 4 }} + {{- end }} +spec: + {{- if .Values.master.pdb.minAvailable }} + minAvailable: {{ .Values.master.pdb.minAvailable }} + {{- end }} + {{- if or .Values.master.pdb.maxUnavailable ( not .Values.master.pdb.minAvailable ) }} + maxUnavailable: {{ .Values.master.pdb.maxUnavailable | default 1 }} + {{- end }} + {{- $podLabels := include "common.tplvalues.merge" ( dict "values" ( list .Values.master.podLabels .Values.commonLabels ) "context" . ) }} + selector: + matchLabels: {{- include "common.labels.matchLabels" ( dict "customLabels" $podLabels "context" $ ) | nindent 6 }} + app.kubernetes.io/part-of: keydb + app.kubernetes.io/component: master +{{- end }} diff --git a/helm-charts/keydb/templates/master/service.yaml b/helm-charts/keydb/templates/master/service.yaml new file mode 100644 index 0000000..687baeb --- /dev/null +++ b/helm-charts/keydb/templates/master/service.yaml @@ -0,0 +1,53 @@ +{{- /* +Copyright Broadcom, Inc. All Rights Reserved. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +apiVersion: v1 +kind: Service +metadata: + name: {{ template "keydb.master.fullname" . }} + namespace: {{ include "common.names.namespace" . | quote }} + labels: {{- include "common.labels.standard" ( dict "customLabels" .Values.commonLabels "context" $ ) | nindent 4 }} + app.kubernetes.io/part-of: keydb + app.kubernetes.io/component: master + {{- if or .Values.master.service.annotations .Values.commonAnnotations }} + {{- $annotations := include "common.tplvalues.merge" (dict "values" (list .Values.master.service.annotations .Values.commonAnnotations) "context" .) }} + annotations: {{- include "common.tplvalues.render" ( dict "value" $annotations "context" $ ) | nindent 4 }} + {{- end }} +spec: + type: {{ .Values.master.service.type }} + {{- if and .Values.master.service.clusterIP (eq .Values.master.service.type "ClusterIP") }} + clusterIP: {{ .Values.master.service.clusterIP }} + {{- end }} + {{- if .Values.master.service.sessionAffinity }} + sessionAffinity: {{ .Values.master.service.sessionAffinity }} + {{- end }} + {{- if .Values.master.service.sessionAffinityConfig }} + sessionAffinityConfig: {{- include "common.tplvalues.render" (dict "value" .Values.master.service.sessionAffinityConfig "context" $) | nindent 4 }} + {{- end }} + {{- if or (eq .Values.master.service.type "LoadBalancer") (eq .Values.master.service.type "NodePort") }} + externalTrafficPolicy: {{ .Values.master.service.externalTrafficPolicy | quote }} + {{- end }} + {{- if and (eq .Values.master.service.type "LoadBalancer") (not (empty .Values.master.service.loadBalancerSourceRanges)) }} + loadBalancerSourceRanges: {{ .Values.master.service.loadBalancerSourceRanges }} + {{- end }} + {{- if and (eq .Values.master.service.type "LoadBalancer") (not (empty .Values.master.service.loadBalancerIP)) }} + loadBalancerIP: {{ .Values.master.service.loadBalancerIP }} + {{- end }} + ports: + - name: tcp-keydb + port: {{ .Values.master.service.ports.keydb }} + targetPort: keydb + {{- if and (or (eq .Values.master.service.type "NodePort") (eq .Values.master.service.type "LoadBalancer")) (not (empty .Values.master.service.nodePorts.keydb)) }} + nodePort: {{ .Values.master.service.nodePorts.keydb }} + {{- else if eq .Values.master.service.type "ClusterIP" }} + nodePort: null + {{- end }} + {{- if .Values.master.service.extraPorts }} + {{- include "common.tplvalues.render" (dict "value" .Values.master.service.extraPorts "context" $) | nindent 4 }} + {{- end }} + {{- $podLabels := include "common.tplvalues.merge" (dict "values" (list .Values.master.podLabels .Values.commonLabels) "context" .) | fromYaml }} + selector: {{- include "common.labels.matchLabels" ( dict "customLabels" $podLabels "context" $ ) | nindent 4 }} + app.kubernetes.io/part-of: keydb + app.kubernetes.io/component: master diff --git a/helm-charts/keydb/templates/master/statefulset.yaml b/helm-charts/keydb/templates/master/statefulset.yaml new file mode 100644 index 0000000..b7986e6 --- /dev/null +++ b/helm-charts/keydb/templates/master/statefulset.yaml @@ -0,0 +1,436 @@ +{{- /* +Copyright Broadcom, Inc. All Rights Reserved. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +apiVersion: {{ include "common.capabilities.statefulset.apiVersion" . }} +kind: StatefulSet +metadata: + name: {{ template "keydb.master.fullname" . }} + namespace: {{ include "common.names.namespace" . | quote }} + labels: {{- include "common.labels.standard" ( dict "customLabels" .Values.commonLabels "context" $ ) | nindent 4 }} + app.kubernetes.io/part-of: keydb + app.kubernetes.io/component: master + {{- if or .Values.master.statefulsetAnnotations .Values.commonAnnotations }} + {{- $annotations := include "common.tplvalues.merge" (dict "values" (list .Values.master.statefulsetAnnotations .Values.commonAnnotations) "context" .) }} + annotations: {{- include "common.tplvalues.render" ( dict "value" $annotations "context" $ ) | nindent 4 }} + {{- end }} +spec: + replicas: {{ .Values.master.replicaCount }} + {{- $podLabels := include "common.tplvalues.merge" (dict "values" (list .Values.master.podLabels .Values.commonLabels) "context" .) }} + {{- if and .Values.metrics.enabled .Values.metrics.podLabels }} + {{- $podLabels = include "common.tplvalues.merge" (dict "values" (list .Values.metrics.podLabels $podLabels) "context" .) }} + {{- end }} + selector: + matchLabels: {{- include "common.labels.matchLabels" ( dict "customLabels" $podLabels "context" $ ) | nindent 6 }} + app.kubernetes.io/part-of: keydb + app.kubernetes.io/component: master + serviceName: {{ printf "%s-hl" (include "keydb.master.fullname" .) }} + {{- if .Values.master.updateStrategy }} + updateStrategy: {{- toYaml .Values.master.updateStrategy | nindent 4 }} + {{- end }} + template: + metadata: + annotations: + {{- if empty .Values.master.existingConfigmap }} + checksum/configmap: {{ include (print $.Template.BasePath "/master/configmap.yaml") . | sha256sum }} + {{- end }} + checksum/health: {{ pick ( include (print $.Template.BasePath "/health-configmap.yaml") . | fromYaml ) "data" | toYaml | sha256sum }} + {{- if or .Values.master.podAnnotations (and .Values.metrics.enabled .Values.metrics.podAnnotations) }} + {{- $podAnnotations := include "common.tplvalues.merge" (dict "values" (list .Values.master.podAnnotations .Values.metrics.podAnnotations) "context" .) }} + {{- include "common.tplvalues.render" (dict "value" $podAnnotations "context" $) | nindent 8 }} + {{- end }} + labels: {{- include "common.labels.standard" ( dict "customLabels" $podLabels "context" $ ) | nindent 8 }} + app.kubernetes.io/part-of: keydb + app.kubernetes.io/component: master + spec: + {{- include "keydb.imagePullSecrets" . | nindent 6 }} + serviceAccountName: {{ template "keydb.serviceAccountName" . }} + automountServiceAccountToken: {{ .Values.master.automountServiceAccountToken }} + {{- if .Values.master.hostAliases }} + hostAliases: {{- include "common.tplvalues.render" (dict "value" .Values.master.hostAliases "context" $) | nindent 8 }} + {{- end }} + {{- if .Values.master.affinity }} + affinity: {{- include "common.tplvalues.render" ( dict "value" .Values.master.affinity "context" $) | nindent 8 }} + {{- else }} + affinity: + {{- if not (empty .Values.master.podAffinityPreset) }} + podAffinity: {{- include "common.affinities.pods" (dict "type" .Values.master.podAffinityPreset "component" "master" "customLabels" $podLabels "context" $) | nindent 10 }} + {{- end }} + {{- if not (empty .Values.master.podAntiAffinityPreset) }} + podAntiAffinity: {{- include "common.affinities.pods" (dict "type" .Values.master.podAntiAffinityPreset "component" "master" "customLabels" $podLabels "context" $) | nindent 10 }} + {{- end }} + {{- if not (empty .Values.master.nodeAffinityPreset.type) }} + nodeAffinity: {{- include "common.affinities.nodes" (dict "type" .Values.master.nodeAffinityPreset.type "key" .Values.master.nodeAffinityPreset.key "values" .Values.master.nodeAffinityPreset.values) | nindent 10 }} + {{- end }} + {{- end }} + {{- if .Values.master.nodeSelector }} + nodeSelector: {{- include "common.tplvalues.render" ( dict "value" .Values.master.nodeSelector "context" $) | nindent 8 }} + {{- end }} + {{- if .Values.master.tolerations }} + tolerations: {{- include "common.tplvalues.render" (dict "value" .Values.master.tolerations "context" .) | nindent 8 }} + {{- end }} + {{- if .Values.master.priorityClassName }} + priorityClassName: {{ .Values.master.priorityClassName | quote }} + {{- end }} + {{- if .Values.master.schedulerName }} + schedulerName: {{ .Values.master.schedulerName | quote }} + {{- end }} + {{- if .Values.master.topologySpreadConstraints }} + topologySpreadConstraints: {{- include "common.tplvalues.render" (dict "value" .Values.master.topologySpreadConstraints "context" .) | nindent 8 }} + {{- end }} + {{- if .Values.master.podSecurityContext.enabled }} + securityContext: {{- include "common.compatibility.renderSecurityContext" (dict "secContext" .Values.master.podSecurityContext "context" $) | nindent 8 }} + {{- end }} + {{- if .Values.master.terminationGracePeriodSeconds }} + terminationGracePeriodSeconds: {{ .Values.master.terminationGracePeriodSeconds }} + {{- end }} + initContainers: + {{- if and .Values.volumePermissions.enabled .Values.master.persistence.enabled }} + - name: volume-permissions + image: {{ include "keydb.volumePermissions.image" . }} + imagePullPolicy: {{ .Values.volumePermissions.image.pullPolicy | quote }} + command: + - /bin/bash + - -ec + - | + find {{ .Values.master.persistence.mountPath }} -mindepth 1 -maxdepth 1 -not -name ".snapshot" -not -name "lost+found" | xargs -r chown -R {{ printf "%d:%d" (int .Values.master.containerSecurityContext.runAsUser) (int .Values.master.podSecurityContext.fsGroup) }} + {{- if .Values.volumePermissions.containerSecurityContext.enabled }} + securityContext: {{- include "common.compatibility.renderSecurityContext" (dict "secContext" .Values.volumePermissions.containerSecurityContext "context" $) | nindent 12 }} + {{- end }} + {{- if .Values.volumePermissions.resources }} + resources: {{- toYaml .Values.volumePermissions.resources | nindent 12 }} + {{- else if ne .Values.volumePermissions.resourcesPreset "none" }} + resources: {{- include "common.resources.preset" (dict "type" .Values.volumePermissions.resourcesPreset) | nindent 12 }} + {{- end }} + volumeMounts: + - name: data + mountPath: {{ .Values.master.persistence.mountPath }} + {{- if .Values.master.persistence.subPath }} + subPath: {{ .Values.master.persistence.subPath }} + {{- end }} + {{- end }} + {{- if .Values.master.initContainers }} + {{- include "common.tplvalues.render" (dict "value" .Values.master.initContainers "context" $) | nindent 8 }} + {{- end }} + containers: + - name: keydb + image: {{ template "keydb.image" . }} + imagePullPolicy: {{ .Values.image.pullPolicy }} + {{- if .Values.master.containerSecurityContext.enabled }} + securityContext: {{- include "common.compatibility.renderSecurityContext" (dict "secContext" .Values.master.containerSecurityContext "context" $) | nindent 12 }} + {{- end }} + {{- if .Values.diagnosticMode.enabled }} + command: {{- include "common.tplvalues.render" (dict "value" .Values.diagnosticMode.command "context" $) | nindent 12 }} + {{- else if .Values.master.command }} + command: {{- include "common.tplvalues.render" (dict "value" .Values.master.command "context" $) | nindent 12 }} + {{- else }} + command: + - /bin/bash + {{- end }} + {{- if .Values.diagnosticMode.enabled }} + args: {{- include "common.tplvalues.render" (dict "value" .Values.diagnosticMode.args "context" $) | nindent 12 }} + {{- else if .Values.master.args }} + args: {{- include "common.tplvalues.render" (dict "value" .Values.master.args "context" $) | nindent 12 }} + {{- else }} + args: + - -ec + - | + . /opt/bitnami/scripts/keydb-env.sh + + args=("/opt/bitnami/keydb/etc/keydb.conf") + {{- if .Values.auth.enabled }} + args+=("--requirepass" "$KEYDB_PASSWORD") + args+=("--masterauth" "$KEYDB_PASSWORD") + {{- end }} + + exec keydb-server "${args[@]}" + {{- end }} + env: + - name: BITNAMI_DEBUG + value: {{ ternary "true" "false" (or .Values.image.debug .Values.diagnosticMode.enabled) | quote }} + - name: KEYDB_PORT_NUMBER + value: {{ .Values.master.containerPorts.keydb | quote }} + {{- if .Values.auth.enabled }} + {{- if .Values.auth.usePasswordFiles }} + - name: KEYDB_PASSWORD_FILE + value: "/opt/bitnami/keydb/secrets/keydb-password" + {{- else }} + - name: KEYDB_PASSWORD + valueFrom: + secretKeyRef: + name: {{ template "keydb.secretName" . }} + key: {{ template "keydb.secretPasswordKey" . }} + {{- end }} + {{- end }} + {{- if .Values.master.extraEnvVars }} + {{- include "common.tplvalues.render" (dict "value" .Values.master.extraEnvVars "context" $) | nindent 12 }} + {{- end }} + {{- if or .Values.master.extraEnvVarsCM .Values.master.extraEnvVarsSecret }} + envFrom: + {{- if .Values.master.extraEnvVarsCM }} + - configMapRef: + name: {{ include "common.tplvalues.render" (dict "value" .Values.master.extraEnvVarsCM "context" $) }} + {{- end }} + {{- if .Values.master.extraEnvVarsSecret }} + - secretRef: + name: {{ include "common.tplvalues.render" (dict "value" .Values.master.extraEnvVarsSecret "context" $) }} + {{- end }} + {{- end }} + {{- if .Values.master.resources }} + resources: {{- toYaml .Values.master.resources | nindent 12 }} + {{- else if ne .Values.master.resourcesPreset "none" }} + resources: {{- include "common.resources.preset" (dict "type" .Values.master.resourcesPreset) | nindent 12 }} + {{- end }} + ports: + - name: keydb + containerPort: {{ .Values.master.containerPorts.keydb }} + {{- if .Values.master.extraContainerPorts }} + {{- include "common.tplvalues.render" (dict "value" .Values.master.extraContainerPorts "context" $) | nindent 12 }} + {{- end }} + {{- if not .Values.diagnosticMode.enabled }} + {{- if .Values.master.customLivenessProbe }} + livenessProbe: {{- include "common.tplvalues.render" (dict "value" .Values.master.customLivenessProbe "context" $) | nindent 12 }} + {{- else if .Values.master.livenessProbe.enabled }} + livenessProbe: {{- include "common.tplvalues.render" (dict "value" (omit .Values.master.livenessProbe "enabled") "context" $) | nindent 12 }} + exec: + command: + - sh + - -c + - /opt/bitnami/scripts/health/ping_liveness_local.sh {{ .Values.master.livenessProbe.timeoutSeconds }} + {{- end }} + {{- if .Values.master.customReadinessProbe }} + readinessProbe: {{- include "common.tplvalues.render" (dict "value" .Values.master.customReadinessProbe "context" $) | nindent 12 }} + {{- else if .Values.master.readinessProbe.enabled }} + readinessProbe: {{- include "common.tplvalues.render" (dict "value" (omit .Values.master.readinessProbe "enabled") "context" $) | nindent 12 }} + exec: + command: + - sh + - -c + - /opt/bitnami/scripts/health/ping_readiness_local.sh {{ .Values.master.readinessProbe.timeoutSeconds }} + {{- end }} + {{- if .Values.master.customStartupProbe }} + startupProbe: {{- include "common.tplvalues.render" (dict "value" .Values.master.customStartupProbe "context" $) | nindent 12 }} + {{- else if .Values.master.startupProbe.enabled }} + startupProbe: {{- include "common.tplvalues.render" (dict "value" (omit .Values.master.startupProbe "enabled") "context" $) | nindent 12 }} + tcpSocket: + port: keydb + {{- end }} + {{- end }} + {{- if .Values.master.lifecycleHooks }} + lifecycle: {{- include "common.tplvalues.render" (dict "value" .Values.master.lifecycleHooks "context" $) | nindent 12 }} + {{- end }} + volumeMounts: + - name: data + mountPath: {{ .Values.master.persistence.mountPath }} + {{- if .Values.master.persistence.subPath }} + subPath: {{ .Values.master.persistence.subPath }} + {{- end }} + - name: health-scripts + mountPath: /opt/bitnami/scripts/health + readOnly: true + {{- if and .Values.auth.enabled .Values.auth.usePasswordFiles }} + - name: keydb-password + mountPath: /opt/bitnami/keydb/secrets + readOnly: true + {{- end }} + {{- if .Values.tls.enabled }} + - name: keydb-certificates + mountPath: /opt/bitnami/keydb/certs + readOnly: true + {{- end }} + - name: config + mountPath: /opt/bitnami/keydb/etc + readOnly: true + - name: empty-dir + mountPath: /tmp + subPath: tmp-dir + {{- if .Values.master.extraVolumeMounts }} + {{- include "common.tplvalues.render" (dict "value" .Values.master.extraVolumeMounts "context" $) | nindent 12 }} + {{- end }} + {{- if .Values.metrics.enabled }} + - name: metrics + image: {{ include "keydb.metrics.image" . }} + imagePullPolicy: {{ .Values.metrics.image.pullPolicy | quote }} + {{- if .Values.metrics.containerSecurityContext.enabled }} + securityContext: {{- include "common.compatibility.renderSecurityContext" (dict "secContext" .Values.metrics.containerSecurityContext "context" $) | nindent 12 }} + {{- end }} + {{- if .Values.diagnosticMode.enabled }} + command: {{- include "common.tplvalues.render" (dict "value" .Values.diagnosticMode.command "context" $) | nindent 12 }} + {{- else if .Values.metrics.command }} + command: {{- include "common.tplvalues.render" (dict "value" .Values.metrics.command "context" $) | nindent 12 }} + {{- else }} + command: + - /bin/bash + - -c + - | + {{- if and .Values.auth.enabled .Values.auth.usePasswordFiles }} + export REDIS_PASSWORD="$(< $REDIS_PASSWORD_FILE)" + {{- end }} + redis_exporter{{- range $key, $value := .Values.metrics.extraArgs }} --{{ $key }}={{ $value }}{{- end }} + {{- end }} + {{- if .Values.diagnosticMode.enabled }} + args: {{- include "common.tplvalues.render" (dict "value" .Values.diagnosticMode.args "context" $) | nindent 12 }} + {{- end }} + env: + - name: REDIS_ALIAS + value: {{ template "common.names.fullname" . }} + - name: REDIS_EXPORTER_WEB_LISTEN_ADDRESS + value: {{ printf ":%v" .Values.metrics.containerPorts.http }} + {{- if .Values.auth.enabled }} + - name: REDIS_USER + value: default + {{- if .Values.auth.usePasswordFiles }} + - name: REDIS_PASSWORD_FILE + value: "/secrets/keydb-password" + {{- else }} + - name: REDIS_PASSWORD + valueFrom: + secretKeyRef: + name: {{ template "keydb.secretName" . }} + key: {{ template "keydb.secretPasswordKey" . }} + {{- end }} + {{- end }} + - name: REDIS_ADDR + value: redis://{{ .Values.metrics.keydbHost }}:{{ .Values.master.containerPorts.keydb }} + {{- if .Values.tls.enabled }} + - name: REDIS_EXPORTER_TLS_CLIENT_KEY_FILE + value: "/certs/tls.key" + - name: REDIS_EXPORTER_TLS_CLIENT_CERT_FILE + value: "/certs/tls.crt" + - name: REDIS_EXPORTER_TLS_CA_CERT_FILE + value: "/certs/ca.crt" + {{- end }} + {{- if .Values.metrics.extraEnvVars }} + {{- include "common.tplvalues.render" (dict "value" .Values.metrics.extraEnvVars "context" $) | nindent 12 }} + {{- end }} + ports: + - name: metrics + containerPort: {{ .Values.metrics.containerPorts.http }} + {{- if not .Values.diagnosticMode.enabled }} + {{- if .Values.metrics.customStartupProbe }} + startupProbe: {{- include "common.tplvalues.render" (dict "value" .Values.metrics.customStartupProbe "context" $) | nindent 12 }} + {{- else if .Values.metrics.startupProbe.enabled }} + startupProbe: {{- include "common.tplvalues.render" (dict "value" (omit .Values.metrics.startupProbe "enabled") "context" $) | nindent 12 }} + tcpSocket: + port: metrics + {{- end }} + {{- if .Values.metrics.customLivenessProbe }} + livenessProbe: {{- include "common.tplvalues.render" (dict "value" .Values.metrics.customLivenessProbe "context" $) | nindent 12 }} + {{- else if .Values.metrics.livenessProbe.enabled }} + livenessProbe: {{- include "common.tplvalues.render" (dict "value" (omit .Values.metrics.livenessProbe "enabled") "context" $) | nindent 12 }} + tcpSocket: + port: metrics + {{- end }} + {{- if .Values.metrics.customReadinessProbe }} + readinessProbe: {{- include "common.tplvalues.render" (dict "value" .Values.metrics.customReadinessProbe "context" $) | nindent 12 }} + {{- else if .Values.metrics.readinessProbe.enabled }} + readinessProbe: {{- include "common.tplvalues.render" (dict "value" (omit .Values.metrics.readinessProbe "enabled") "context" $) | nindent 12 }} + httpGet: + path: / + port: metrics + {{- end }} + {{- end }} + {{- if .Values.metrics.resources }} + resources: {{- toYaml .Values.metrics.resources | nindent 12 }} + {{- else if ne .Values.metrics.resourcesPreset "none" }} + resources: {{- include "common.resources.preset" (dict "type" .Values.metrics.resourcesPreset) | nindent 12 }} + {{- end }} + volumeMounts: + - name: empty-dir + mountPath: /tmp + subPath: app-tmp-dir + {{- if and .Values.auth.enabled .Values.auth.usePasswordFiles }} + - name: keydb-password + mountPath: /secrets + readOnly: true + {{- end }} + {{- if .Values.tls.enabled }} + - name: keydb-certificates + mountPath: /certs + readOnly: true + {{- end }} + {{- if .Values.metrics.extraVolumeMounts }} + {{- include "common.tplvalues.render" ( dict "value" .Values.metrics.extraVolumeMounts "context" $ ) | nindent 12 }} + {{- end }} + {{- end }} + {{- if .Values.master.sidecars }} + {{- include "common.tplvalues.render" ( dict "value" .Values.master.sidecars "context" $) | nindent 8 }} + {{- end }} + volumes: + - name: empty-dir + emptyDir: {} + - name: health-scripts + configMap: + name: {{ printf "%s-health" (include "common.names.fullname" .) }} + defaultMode: 0755 + - name: config + configMap: + name: {{ template "keydb.master.configmapName" . }} + {{- if and .Values.auth.enabled .Values.auth.usePasswordFiles }} + - name: keydb-password + secret: + secretName: {{ template "keydb.secretName" . }} + items: + - key: {{ template "keydb.secretPasswordKey" . }} + path: keydb-password + {{- end }} + {{- if .Values.tls.enabled }} + - name: keydb-certificates + secret: + secretName: {{ template "keydb.tls.master.secretName" . }} + defaultMode: 256 + {{- end }} + {{- if .Values.master.extraVolumes }} + {{- include "common.tplvalues.render" (dict "value" .Values.master.extraVolumes "context" $) | nindent 8 }} + {{- end }} + {{- if or (not .Values.master.persistence.enabled) (not (empty .Values.master.persistence.existingClaim)) }} + - name: data + {{- if not (empty .Values.master.persistence.existingClaim) }} + persistentVolumeClaim: + claimName: {{ tpl .Values.master.persistence.existingClaim . }} + {{- else }} + {{- if or .Values.master.persistence.medium .Values.master.persistence.sizeLimit }} + emptyDir: + {{- if .Values.master.persistence.medium }} + medium: {{ .Values.master.persistence.medium | quote }} + {{- end }} + {{- if .Values.master.persistence.sizeLimit }} + sizeLimit: {{ .Values.master.persistence.sizeLimit | quote }} + {{- end }} + {{- else }} + emptyDir: {} + {{- end }} + {{- end }} + {{- else }} + {{- if .Values.master.persistentVolumeClaimRetentionPolicy.enabled }} + persistentVolumeClaimRetentionPolicy: + whenDeleted: {{ .Values.master.persistentVolumeClaimRetentionPolicy.whenDeleted }} + whenScaled: {{ .Values.master.persistentVolumeClaimRetentionPolicy.whenScaled }} + {{- end }} + volumeClaimTemplates: + - metadata: + name: data + {{- if or .Values.master.persistence.annotations .Values.commonAnnotations }} + {{- $claimAnnotations := include "common.tplvalues.merge" (dict "values" .Values.master.persistence.annotations .Values.commonAnnotations "context" .) | fromYaml }} + annotations: {{- include "common.tplvalues.render" ( dict "value" $claimAnnotations "context" $ ) | nindent 10 }} + {{- end }} + {{- if .Values.commonLabels }} + labels: {{- include "common.labels.matchLabels" ( dict "customLabels" .Values.commonLabels "context" $ ) | nindent 10 }} + {{- end }} + spec: + accessModes: + {{- range .Values.master.persistence.accessModes }} + - {{ . | quote }} + {{- end }} + resources: + requests: + storage: {{ .Values.master.persistence.size | quote }} + {{- if .Values.master.persistence.selector }} + selector: {{- include "common.tplvalues.render" (dict "value" .Values.master.persistence.selector "context" $) | nindent 10 }} + {{- end }} + {{- if .Values.master.persistence.dataSource }} + dataSource: {{- include "common.tplvalues.render" (dict "value" .Values.master.persistence.dataSource "context" $) | nindent 10 }} + {{- end }} + {{- include "common.storage.class" (dict "persistence" .Values.master.persistence "global" .Values.global) | nindent 8 }} + {{- end }} diff --git a/helm-charts/keydb/templates/master/vpa.yaml b/helm-charts/keydb/templates/master/vpa.yaml new file mode 100644 index 0000000..186bdc7 --- /dev/null +++ b/helm-charts/keydb/templates/master/vpa.yaml @@ -0,0 +1,45 @@ +{{- /* +Copyright Broadcom, Inc. All Rights Reserved. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{- if and (include "common.capabilities.apiVersions.has" ( dict "version" "autoscaling.k8s.io/v1/VerticalPodAutoscaler" "context" . )) .Values.master.autoscaling.vpa.enabled }} +apiVersion: autoscaling.k8s.io/v1 +kind: VerticalPodAutoscaler +metadata: + name: {{ template "keydb.master.fullname" . }} + namespace: {{ include "common.names.namespace" . | quote }} + labels: {{- include "common.labels.standard" ( dict "customLabels" .Values.commonLabels "context" $ ) | nindent 4 }} + app.kubernetes.io/part-of: keydb + app.kubernetes.io/component: master + {{- if or .Values.master.autoscaling.vpa.annotations .Values.commonAnnotations }} + {{- $annotations := include "common.tplvalues.merge" ( dict "values" ( list .Values.master.autoscaling.vpa.annotations .Values.commonAnnotations ) "context" . ) }} + annotations: {{- include "common.tplvalues.render" ( dict "value" $annotations "context" $) | nindent 4 }} + {{- end }} +spec: + resourcePolicy: + containerPolicies: + - containerName: master + {{- with .Values.master.autoscaling.vpa.controlledResources }} + controlledResources: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.master.autoscaling.vpa.maxAllowed }} + maxAllowed: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.master.autoscaling.vpa.minAllowed }} + minAllowed: + {{- toYaml . | nindent 8 }} + {{- end }} + targetRef: + apiVersion: {{ include "common.capabilities.statefulset.apiVersion" . }} + kind: Statefulset + name: {{ template "keydb.master.fullname" . }} + {{- if .Values.master.autoscaling.vpa.updatePolicy }} + updatePolicy: + {{- with .Values.master.autoscaling.vpa.updatePolicy.updateMode }} + updateMode: {{ . }} + {{- end }} + {{- end }} +{{- end }} diff --git a/helm-charts/keydb/templates/metrics-svc.yaml b/helm-charts/keydb/templates/metrics-svc.yaml new file mode 100644 index 0000000..72ed2ef --- /dev/null +++ b/helm-charts/keydb/templates/metrics-svc.yaml @@ -0,0 +1,28 @@ +{{- /* +Copyright Broadcom, Inc. All Rights Reserved. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{- if .Values.metrics.enabled }} +apiVersion: v1 +kind: Service +metadata: + name: {{ printf "%s-metrics" (include "common.names.fullname" .) }} + namespace: {{ include "common.names.namespace" . | quote }} + labels: {{- include "common.labels.standard" ( dict "customLabels" .Values.commonLabels "context" $ ) | nindent 4 }} + app.kubernetes.io/component: metrics + app.kubernetes.io/part-of: keydb + {{- if or .Values.metrics.service.annotations .Values.commonAnnotations }} + {{- $annotations := include "common.tplvalues.merge" ( dict "values" ( list .Values.metrics.service.annotations .Values.commonAnnotations ) "context" . ) }} + annotations: {{- include "common.tplvalues.render" ( dict "value" $annotations "context" $) | nindent 4 }} + {{- end }} +spec: + type: ClusterIP + ports: + - name: http-metrics + port: {{ .Values.metrics.service.port }} + protocol: TCP + targetPort: metrics + selector: {{- include "common.labels.matchLabels" ( dict "customLabels" .Values.commonLabels "context" $ ) | nindent 4 }} + app.kubernetes.io/part-of: keydb +{{- end }} diff --git a/helm-charts/keydb/templates/pdb.yaml b/helm-charts/keydb/templates/pdb.yaml deleted file mode 100644 index 6af8774..0000000 --- a/helm-charts/keydb/templates/pdb.yaml +++ /dev/null @@ -1,18 +0,0 @@ -{{- if .Values.podDisruptionBudget.enabled }} -apiVersion: policy/v1 -kind: PodDisruptionBudget -metadata: - name: {{ include "keydb.fullname" . }} - labels: - {{- include "keydb.labels" . | nindent 4 }} -spec: -{{- if .Values.podDisruptionBudget.maxUnavailable }} - maxUnavailable: {{ .Values.podDisruptionBudget.maxUnavailable }} -{{- end }} -{{- if .Values.podDisruptionBudget.minAvailable }} - minAvailable: {{ .Values.podDisruptionBudget.minAvailable }} -{{- end }} - selector: - matchLabels: - {{- include "keydb.selectorLabels" . | nindent 6 }} -{{- end }} diff --git a/helm-charts/keydb/templates/prometheusrule.yaml b/helm-charts/keydb/templates/prometheusrule.yaml new file mode 100644 index 0000000..bf186d6 --- /dev/null +++ b/helm-charts/keydb/templates/prometheusrule.yaml @@ -0,0 +1,24 @@ +{{- /* +Copyright Broadcom, Inc. All Rights Reserved. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{- if and .Values.metrics.enabled .Values.metrics.prometheusRule.enabled }} +apiVersion: monitoring.coreos.com/v1 +kind: PrometheusRule +metadata: + name: {{ template "common.names.fullname" . }} + namespace: {{ default (include "common.names.namespace" .) .Values.metrics.prometheusRule.namespace | quote }} + {{- $labels := include "common.tplvalues.merge" (dict "values" (list .Values.metrics.prometheusRule.labels .Values.commonLabels) "context" .) }} + labels: {{- include "common.labels.standard" ( dict "customLabels" $labels "context" $ ) | nindent 4 }} + app.kubernetes.io/component: metrics + app.kubernetes.io/part-of: keydb + {{- if or .Values.metrics.prometheusRule.annotations .Values.commonAnnotations }} + {{- $annotations := include "common.tplvalues.merge" (dict "values" (list .Values.metrics.prometheusRule.annotations .Values.commonAnnotations) "context" .) }} + annotations: {{- include "common.tplvalues.render" ( dict "value" $annotations "context" $ ) | nindent 4 }} + {{- end }} +spec: + groups: + - name: {{ include "common.names.fullname" . }} + rules: {{- include "common.tplvalues.render" ( dict "value" .Values.metrics.prometheusRule.rules "context" $ ) | nindent 8 }} +{{- end }} diff --git a/helm-charts/keydb/templates/replica/cert.yaml b/helm-charts/keydb/templates/replica/cert.yaml new file mode 100644 index 0000000..f2ef11b --- /dev/null +++ b/helm-charts/keydb/templates/replica/cert.yaml @@ -0,0 +1,44 @@ +{{- /* +Copyright Broadcom, Inc. All Rights Reserved. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{- if and (eq .Values.architecture "replication") .Values.tls.enabled .Values.tls.autoGenerated.enabled (eq .Values.tls.autoGenerated.engine "cert-manager") }} +apiVersion: cert-manager.io/v1 +kind: Certificate +metadata: + name: {{ printf "%s-crt" (include "keydb.replica.fullname" .) }} + namespace: {{ include "common.names.namespace" . | quote }} + labels: {{- include "common.labels.standard" ( dict "customLabels" .Values.commonLabels "context" $ ) | nindent 4 }} + app.kubernetes.io/part-of: keydb + app.kubernetes.io/component: replica + {{- if .Values.commonAnnotations }} + annotations: {{- include "common.tplvalues.render" ( dict "value" .Values.commonAnnotations "context" $ ) | nindent 4 }} + {{- end }} +spec: + secretName: {{ template "keydb.tls.replica.secretName" . }} + commonName: {{ printf "%s.%s.svc.%s" (include "keydb.replica.fullname" .) (include "common.names.namespace" .) .Values.clusterDomain }} + issuerRef: + name: {{ printf "%s-ca-issuer" (include "common.names.fullname" .) }} + kind: Issuer + subject: + organizations: + - "KeyDB" + dnsNames: + - '*.{{ include "common.names.namespace" . }}' + - '*.{{ include "common.names.namespace" . }}.svc' + - '*.{{ include "common.names.namespace" . }}.svc.{{ .Values.clusterDomain }}' + - '*.{{ include "keydb.replica.fullname" . }}' + - '*.{{ include "keydb.replica.fullname" . }}.{{ include "common.names.namespace" . }}' + - '*.{{ include "keydb.replica.fullname" . }}.{{ include "common.names.namespace" . }}.svc' + - '*.{{ include "keydb.replica.fullname" . }}.{{ include "common.names.namespace" . }}.svc.{{ .Values.clusterDomain }}' + - '*.{{ printf "%s-hl" (include "keydb.replica.fullname" .) }}' + - '*.{{ printf "%s-hl" (include "keydb.replica.fullname" .) }}.{{ include "common.names.namespace" . }}' + - '*.{{ printf "%s-hl" (include "keydb.replica.fullname" .) }}.{{ include "common.names.namespace" . }}.svc' + - '*.{{ printf "%s-hl" (include "keydb.replica.fullname" .) }}.{{ include "common.names.namespace" . }}.svc.{{ .Values.clusterDomain }}' + privateKey: + algorithm: {{ .Values.tls.autoGenerated.certManager.keyAlgorithm }} + size: {{ int .Values.tls.autoGenerated.certManager.keySize }} + duration: {{ .Values.tls.autoGenerated.certManager.duration }} + renewBefore: {{ .Values.tls.autoGenerated.certManager.renewBefore }} +{{- end }} diff --git a/helm-charts/keydb/templates/replica/configmap.yaml b/helm-charts/keydb/templates/replica/configmap.yaml new file mode 100644 index 0000000..6f3c3d8 --- /dev/null +++ b/helm-charts/keydb/templates/replica/configmap.yaml @@ -0,0 +1,63 @@ +{{- /* +Copyright Broadcom, Inc. All Rights Reserved. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{- if and (eq .Values.architecture "replication") (not .Values.replica.existingConfigmap) }} +apiVersion: v1 +kind: ConfigMap +metadata: + name: {{ template "keydb.replica.configmapName" . }} + namespace: {{ include "common.names.namespace" . | quote }} + labels: {{- include "common.labels.standard" ( dict "customLabels" .Values.commonLabels "context" $ ) | nindent 4 }} + app.kubernetes.io/part-of: keydb + app.kubernetes.io/component: replica + {{- if .Values.commonAnnotations }} + annotations: {{- include "common.tplvalues.render" ( dict "value" .Values.commonAnnotations "context" $ ) | nindent 4 }} + {{- end }} +data: + keydb.conf: |- + {{- if .Values.commonConfiguration }} + {{- include "common.tplvalues.render" (dict "value" .Values.commonConfiguration "context" .) | nindent 4 }} + {{- else }} + # Enable AOF + # ref: https://docs.keydb.dev/docs/persistence/#append-only-file + appendonly yes + # Disable RDB persistence, AOF persistence already enabled + # ref: https://docs.keydb.dev/docs/persistence/#rdb-disadvantages + save "" + loglevel notice + {{- end }} + {{- if .Values.replica.configuration }} + {{- include "common.tplvalues.render" ( dict "value" .Values.replica.configuration "context" $ ) | nindent 4 }} + {{- else }} + bind 0.0.0.0 :: + dir {{ .Values.replica.persistence.mountPath }} + {{- if not .Values.auth.enabled }} + protected-mode no + {{- end }} + {{- if .Values.tls.enabled }} + port 0 + tls-port {{ .Values.replica.containerPorts.keydb }} + tls-cert-file /opt/bitnami/keydb/certs/tls.crt + tls-key-file /opt/bitnami/keydb/certs/tls.key + tls-ca-cert-file /opt/bitnami/keydb/certs/ca.crt + tls-replication yes + tls-auth-clients optional + {{- else }} + port {{ .Values.replica.containerPorts.keydb }} + {{- end }} + replica-announce-port {{ .Values.replica.service.ports.keydb }} + {{- if .Values.replica.activeReplica }} + active-replica yes + {{- $masterReplicaCount := int .Values.master.replicaCount }} + {{- if gt $masterReplicaCount 1 }} + multi-master yes + {{- end }} + {{- end }} + {{- range .Values.replica.disableCommands }} + rename-command {{ . }} "" + {{- end }} + {{- end }} + +{{- end }} diff --git a/helm-charts/keydb/templates/replica/headless-service.yaml b/helm-charts/keydb/templates/replica/headless-service.yaml new file mode 100644 index 0000000..ad48972 --- /dev/null +++ b/helm-charts/keydb/templates/replica/headless-service.yaml @@ -0,0 +1,30 @@ +{{- /* +Copyright Broadcom, Inc. All Rights Reserved. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{- if eq .Values.architecture "replication" }} +apiVersion: v1 +kind: Service +metadata: + name: {{ printf "%s-hl" (include "keydb.replica.fullname" .) }} + namespace: {{ include "common.names.namespace" . | quote }} + labels: {{- include "common.labels.standard" ( dict "customLabels" .Values.commonLabels "context" $ ) | nindent 4 }} + app.kubernetes.io/part-of: keydb + app.kubernetes.io/component: replica + {{- if or .Values.replica.service.headless.annotations .Values.commonAnnotations }} + {{- $annotations := include "common.tplvalues.merge" (dict "values" (list .Values.replica.service.headless.annotations .Values.commonAnnotations) "context" .) }} + annotations: {{- include "common.tplvalues.render" ( dict "value" $annotations "context" $ ) | nindent 4 }} + {{- end }} +spec: + type: ClusterIP + clusterIP: None + ports: + - name: tcp-keydb + port: {{ .Values.replica.containerPorts.keydb }} + targetPort: keydb + {{- $podLabels := include "common.tplvalues.merge" (dict "values" (list .Values.replica.podLabels .Values.commonLabels) "context" .) | fromYaml }} + selector: {{- include "common.labels.matchLabels" ( dict "customLabels" $podLabels "context" $ ) | nindent 4 }} + app.kubernetes.io/part-of: keydb + app.kubernetes.io/component: replica +{{- end }} diff --git a/helm-charts/keydb/templates/replica/hpa.yaml b/helm-charts/keydb/templates/replica/hpa.yaml new file mode 100644 index 0000000..acf416b --- /dev/null +++ b/helm-charts/keydb/templates/replica/hpa.yaml @@ -0,0 +1,42 @@ +{{- /* +Copyright Broadcom, Inc. All Rights Reserved. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{- if and (eq .Values.architecture "replication") .Values.replica.autoscaling.hpa.enabled }} +apiVersion: {{ include "common.capabilities.hpa.apiVersion" . }} +kind: HorizontalPodAutoscaler +metadata: + name: {{ template "keydb.replica.fullname" . }} + namespace: {{ include "common.names.namespace" . | quote }} + labels: {{- include "common.labels.standard" ( dict "customLabels" .Values.commonLabels "context" $ ) | nindent 4 }} + app.kubernetes.io/part-of: keydb + app.kubernetes.io/component: replica + {{- if .Values.commonAnnotations }} + annotations: {{- include "common.tplvalues.render" ( dict "value" .Values.commonAnnotations "context" $ ) | nindent 4 }} + {{- end }} +spec: + scaleTargetRef: + apiVersion: {{ include "common.capabilities.statefulset.apiVersion" . }} + kind: StatefulSet + name: {{ template "keydb.replica.fullname" . }} + minReplicas: {{ .Values.replica.autoscaling.hpa.minReplicas }} + maxReplicas: {{ .Values.replica.autoscaling.hpa.maxReplicas }} + metrics: + {{- if .Values.replica.autoscaling.hpa.targetMemory }} + - type: Resource + resource: + name: memory + target: + type: Utilization + averageUtilization: {{ .Values.worker.autoscaling.hpa.targetMemory }} + {{- end }} + {{- if .Values.replica.autoscaling.hpa.targetCPU }} + - type: Resource + resource: + name: cpu + target: + type: Utilization + averageUtilization: {{ .Values.worker.autoscaling.hpa.targetCPU }} + {{- end }} +{{- end }} diff --git a/helm-charts/keydb/templates/replica/networkpolicy.yaml b/helm-charts/keydb/templates/replica/networkpolicy.yaml new file mode 100644 index 0000000..d17341b --- /dev/null +++ b/helm-charts/keydb/templates/replica/networkpolicy.yaml @@ -0,0 +1,88 @@ +{{- /* +Copyright Broadcom, Inc. All Rights Reserved. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{- if and (eq .Values.architecture "replication") .Values.replica.networkPolicy.enabled }} +kind: NetworkPolicy +apiVersion: {{ include "common.capabilities.networkPolicy.apiVersion" . }} +metadata: + name: {{ template "keydb.replica.fullname" . }} + namespace: {{ include "common.names.namespace" . | quote }} + labels: {{- include "common.labels.standard" ( dict "customLabels" .Values.commonLabels "context" $ ) | nindent 4 }} + app.kubernetes.io/part-of: keydb + app.kubernetes.io/component: replica + {{- if .Values.commonAnnotations }} + annotations: {{- include "common.tplvalues.render" ( dict "value" .Values.commonAnnotations "context" $ ) | nindent 4 }} + {{- end }} +spec: + {{- $podLabels := include "common.tplvalues.merge" ( dict "values" ( list .Values.replica.podLabels .Values.commonLabels ) "context" . ) }} + podSelector: + matchLabels: {{- include "common.labels.matchLabels" ( dict "customLabels" $podLabels "context" $ ) | nindent 6 }} + app.kubernetes.io/part-of: keydb + app.kubernetes.io/component: replica + policyTypes: + - Ingress + - Egress + egress: + {{- if .Values.replica.networkPolicy.allowExternalEgress }} + - {} + {{- else }} + # Allow dns resolution + - ports: + - port: 53 + protocol: UDP + - port: 53 + protocol: TCP + # Allow outbound connections to master pods + - ports: + - port: {{ .Values.master.containerPorts.redis }} + to: + - podSelector: + {{- $masterPodLabels := include "common.tplvalues.merge" ( dict "values" ( list .Values.master.podLabels .Values.commonLabels ) "context" . ) }} + matchLabels: {{- include "common.labels.matchLabels" ( dict "customLabels" $masterPodLabels "context" $ ) | nindent 6 }} + app.kubernetes.io/part-of: keydb + app.kubernetes.io/component: master + {{- if .Values.replica.networkPolicy.extraEgress }} + {{- include "common.tplvalues.render" ( dict "value" .Values.replica.networkPolicy.extraEgress "context" $ ) | nindent 4 }} + {{- end }} + {{- end }} + ingress: + - ports: + - port: {{ .Values.replica.containerPorts.keydb }} + {{- if .Values.metrics.enabled }} + - port: {{ .Values.metrics.containerPorts.http }} + {{- if ne .Values.metrics.containerPorts.http .Values.metrics.service.port }} + - port: {{ .Values.metrics.service.port }} + {{- end }} + {{- end }} + {{- range .Values.replica.extraContainerPorts }} + - port: {{ .containerPort }} + {{- end }} + {{- if not .Values.replica.networkPolicy.allowExternal }} + from: + - podSelector: + matchLabels: {{- include "common.labels.matchLabels" ( dict "customLabels" .Values.commonLabels "context" $ ) | nindent 14 }} + {{- if .Values.replica.networkPolicy.addExternalClientAccess }} + - podSelector: + matchLabels: + {{ template "common.names.fullname" . }}-client: "true" + {{- end }} + {{- if .Values.replica.networkPolicy.ingressPodMatchLabels }} + - podSelector: + matchLabels: {{- include "common.tplvalues.render" (dict "value" .Values.replica.networkPolicy.ingressPodMatchLabels "context" $ ) | nindent 14 }} + {{- end }} + {{- if .Values.replica.networkPolicy.ingressNSMatchLabels }} + - namespaceSelector: + matchLabels: {{- include "common.tplvalues.render" (dict "value" .Values.replica.networkPolicy.ingressNSMatchLabels "context" $ ) | nindent 14 }} + {{- if .Values.replica.networkPolicy.ingressNSPodMatchLabels }} + podSelector: + matchLabels: + matchLabels: {{- include "common.tplvalues.render" (dict "value" .Values.replica.networkPolicy.ingressNSPodMatchLabels "context" $ ) | nindent 14 }} + {{- end }} + {{- end }} + {{- end }} + {{- if .Values.replica.networkPolicy.extraIngress }} + {{- include "common.tplvalues.render" ( dict "value" .Values.replica.networkPolicy.extraIngress "context" $ ) | nindent 4 }} + {{- end }} +{{- end }} diff --git a/helm-charts/keydb/templates/replica/pdb.yaml b/helm-charts/keydb/templates/replica/pdb.yaml new file mode 100644 index 0000000..381f4c7 --- /dev/null +++ b/helm-charts/keydb/templates/replica/pdb.yaml @@ -0,0 +1,30 @@ +{{- /* +Copyright Broadcom, Inc. All Rights Reserved. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{- if and (eq .Values.architecture "replication") .Values.replica.pdb.create }} +apiVersion: {{ include "common.capabilities.policy.apiVersion" . }} +kind: PodDisruptionBudget +metadata: + name: {{ template "keydb.replica.fullname" . }} + namespace: {{ include "common.names.namespace" . | quote }} + labels: {{- include "common.labels.standard" ( dict "customLabels" .Values.commonLabels "context" $ ) | nindent 4 }} + app.kubernetes.io/part-of: keydb + app.kubernetes.io/component: replica + {{- if .Values.commonAnnotations }} + annotations: {{- include "common.tplvalues.render" ( dict "value" .Values.commonAnnotations "context" $ ) | nindent 4 }} + {{- end }} +spec: + {{- if .Values.replica.pdb.minAvailable }} + minAvailable: {{ .Values.replica.pdb.minAvailable }} + {{- end }} + {{- if or .Values.replica.pdb.maxUnavailable ( not .Values.replica.pdb.minAvailable ) }} + maxUnavailable: {{ .Values.replica.pdb.maxUnavailable | default 1 }} + {{- end }} + {{- $podLabels := include "common.tplvalues.merge" ( dict "values" ( list .Values.replica.podLabels .Values.commonLabels ) "context" . ) }} + selector: + matchLabels: {{- include "common.labels.matchLabels" ( dict "customLabels" $podLabels "context" $ ) | nindent 6 }} + app.kubernetes.io/part-of: keydb + app.kubernetes.io/component: replica +{{- end }} diff --git a/helm-charts/keydb/templates/replica/service.yaml b/helm-charts/keydb/templates/replica/service.yaml new file mode 100644 index 0000000..fb51af9 --- /dev/null +++ b/helm-charts/keydb/templates/replica/service.yaml @@ -0,0 +1,55 @@ +{{- /* +Copyright Broadcom, Inc. All Rights Reserved. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{- if eq .Values.architecture "replication" }} +apiVersion: v1 +kind: Service +metadata: + name: {{ template "keydb.replica.fullname" . }} + namespace: {{ include "common.names.namespace" . | quote }} + labels: {{- include "common.labels.standard" ( dict "customLabels" .Values.commonLabels "context" $ ) | nindent 4 }} + app.kubernetes.io/part-of: keydb + app.kubernetes.io/component: replica + {{- if or .Values.replica.service.annotations .Values.commonAnnotations }} + {{- $annotations := include "common.tplvalues.merge" (dict "values" (list .Values.replica.service.annotations .Values.commonAnnotations) "context" .) }} + annotations: {{- include "common.tplvalues.render" ( dict "value" $annotations "context" $ ) | nindent 4 }} + {{- end }} +spec: + type: {{ .Values.replica.service.type }} + {{- if and .Values.replica.service.clusterIP (eq .Values.replica.service.type "ClusterIP") }} + clusterIP: {{ .Values.replica.service.clusterIP }} + {{- end }} + {{- if .Values.replica.service.sessionAffinity }} + sessionAffinity: {{ .Values.replica.service.sessionAffinity }} + {{- end }} + {{- if .Values.replica.service.sessionAffinityConfig }} + sessionAffinityConfig: {{- include "common.tplvalues.render" (dict "value" .Values.replica.service.sessionAffinityConfig "context" $) | nindent 4 }} + {{- end }} + {{- if or (eq .Values.replica.service.type "LoadBalancer") (eq .Values.replica.service.type "NodePort") }} + externalTrafficPolicy: {{ .Values.replica.service.externalTrafficPolicy | quote }} + {{- end }} + {{- if and (eq .Values.replica.service.type "LoadBalancer") (not (empty .Values.replica.service.loadBalancerSourceRanges)) }} + loadBalancerSourceRanges: {{ .Values.replica.service.loadBalancerSourceRanges }} + {{- end }} + {{- if and (eq .Values.replica.service.type "LoadBalancer") (not (empty .Values.replica.service.loadBalancerIP)) }} + loadBalancerIP: {{ .Values.replica.service.loadBalancerIP }} + {{- end }} + ports: + - name: tcp-keydb + port: {{ .Values.replica.service.ports.keydb }} + targetPort: keydb + {{- if and (or (eq .Values.replica.service.type "NodePort") (eq .Values.replica.service.type "LoadBalancer")) (not (empty .Values.replica.service.nodePorts.keydb)) }} + nodePort: {{ .Values.replica.service.nodePorts.keydb }} + {{- else if eq .Values.replica.service.type "ClusterIP" }} + nodePort: null + {{- end }} + {{- if .Values.replica.service.extraPorts }} + {{- include "common.tplvalues.render" (dict "value" .Values.replica.service.extraPorts "context" $) | nindent 4 }} + {{- end }} + {{- $podLabels := include "common.tplvalues.merge" (dict "values" (list .Values.replica.podLabels .Values.commonLabels) "context" .) | fromYaml }} + selector: {{- include "common.labels.matchLabels" ( dict "customLabels" $podLabels "context" $ ) | nindent 4 }} + app.kubernetes.io/part-of: keydb + app.kubernetes.io/component: replica +{{- end }} diff --git a/helm-charts/keydb/templates/replica/statefulset.yaml b/helm-charts/keydb/templates/replica/statefulset.yaml new file mode 100644 index 0000000..470549e --- /dev/null +++ b/helm-charts/keydb/templates/replica/statefulset.yaml @@ -0,0 +1,459 @@ +{{- /* +Copyright Broadcom, Inc. All Rights Reserved. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{- if eq .Values.architecture "replication" }} +apiVersion: {{ include "common.capabilities.statefulset.apiVersion" . }} +kind: StatefulSet +metadata: + name: {{ template "keydb.replica.fullname" . }} + namespace: {{ include "common.names.namespace" . | quote }} + labels: {{- include "common.labels.standard" ( dict "customLabels" .Values.commonLabels "context" $ ) | nindent 4 }} + app.kubernetes.io/part-of: keydb + app.kubernetes.io/component: replica + {{- if or .Values.replica.statefulsetAnnotations .Values.commonAnnotations }} + {{- $annotations := include "common.tplvalues.merge" (dict "values" (list .Values.replica.statefulsetAnnotations .Values.commonAnnotations) "context" .) }} + annotations: {{- include "common.tplvalues.render" ( dict "value" $annotations "context" $ ) | nindent 4 }} + {{- end }} +spec: + {{- if not .Values.replica.autoscaling.hpa.enabled }} + replicas: {{ .Values.replica.replicaCount }} + {{- end }} + {{- $podLabels := include "common.tplvalues.merge" (dict "values" (list .Values.replica.podLabels .Values.commonLabels) "context" .) }} + {{- if and .Values.metrics.enabled .Values.metrics.podLabels }} + {{- $podLabels = include "common.tplvalues.merge" (dict "values" (list .Values.metrics.podLabels $podLabels) "context" .) }} + {{- end }} + selector: + matchLabels: {{- include "common.labels.matchLabels" ( dict "customLabels" $podLabels "context" $ ) | nindent 6 }} + app.kubernetes.io/part-of: keydb + app.kubernetes.io/component: replica + serviceName: {{ printf "%s-hl" (include "keydb.replica.fullname" .) }} + {{- if .Values.replica.updateStrategy }} + updateStrategy: {{- toYaml .Values.replica.updateStrategy | nindent 4 }} + {{- end }} + template: + metadata: + annotations: + {{- if empty .Values.replica.existingConfigmap }} + checksum/configmap: {{ include (print $.Template.BasePath "/replica/configmap.yaml") . | sha256sum }} + {{- end }} + checksum/health: {{ pick ( include (print $.Template.BasePath "/health-configmap.yaml") . | fromYaml ) "data" | toYaml | sha256sum }} + {{- if or .Values.replica.podAnnotations (and .Values.metrics.enabled .Values.metrics.podAnnotations) }} + {{- $podAnnotations := include "common.tplvalues.merge" (dict "values" (list .Values.replica.podAnnotations .Values.metrics.podAnnotations) "context" .) }} + {{- include "common.tplvalues.render" (dict "value" $podAnnotations "context" $) | nindent 8 }} + {{- end }} + labels: {{- include "common.labels.standard" ( dict "customLabels" $podLabels "context" $ ) | nindent 8 }} + app.kubernetes.io/part-of: keydb + app.kubernetes.io/component: replica + spec: + {{- include "keydb.imagePullSecrets" . | nindent 6 }} + serviceAccountName: {{ template "keydb.serviceAccountName" . }} + automountServiceAccountToken: {{ .Values.replica.automountServiceAccountToken }} + {{- if .Values.replica.hostAliases }} + hostAliases: {{- include "common.tplvalues.render" (dict "value" .Values.replica.hostAliases "context" $) | nindent 8 }} + {{- end }} + {{- if .Values.replica.affinity }} + affinity: {{- include "common.tplvalues.render" ( dict "value" .Values.replica.affinity "context" $) | nindent 8 }} + {{- else }} + affinity: + {{- if not (empty .Values.replica.podAffinityPreset) }} + podAffinity: {{- include "common.affinities.pods" (dict "type" .Values.replica.podAffinityPreset "component" "replica" "customLabels" $podLabels "context" $) | nindent 10 }} + {{- end }} + {{- if not (empty .Values.replica.podAntiAffinityPreset) }} + podAntiAffinity: {{- include "common.affinities.pods" (dict "type" .Values.replica.podAntiAffinityPreset "component" "replica" "customLabels" $podLabels "context" $) | nindent 10 }} + {{- end }} + {{- if not (empty .Values.replica.nodeAffinityPreset.type) }} + nodeAffinity: {{- include "common.affinities.nodes" (dict "type" .Values.replica.nodeAffinityPreset.type "key" .Values.replica.nodeAffinityPreset.key "values" .Values.replica.nodeAffinityPreset.values) | nindent 10 }} + {{- end }} + {{- end }} + {{- if .Values.replica.nodeSelector }} + nodeSelector: {{- include "common.tplvalues.render" ( dict "value" .Values.replica.nodeSelector "context" $) | nindent 8 }} + {{- end }} + {{- if .Values.replica.tolerations }} + tolerations: {{- include "common.tplvalues.render" (dict "value" .Values.replica.tolerations "context" .) | nindent 8 }} + {{- end }} + {{- if .Values.replica.priorityClassName }} + priorityClassName: {{ .Values.replica.priorityClassName | quote }} + {{- end }} + {{- if .Values.replica.schedulerName }} + schedulerName: {{ .Values.replica.schedulerName | quote }} + {{- end }} + {{- if .Values.replica.topologySpreadConstraints }} + topologySpreadConstraints: {{- include "common.tplvalues.render" (dict "value" .Values.replica.topologySpreadConstraints "context" .) | nindent 8 }} + {{- end }} + {{- if .Values.replica.podSecurityContext.enabled }} + securityContext: {{- include "common.compatibility.renderSecurityContext" (dict "secContext" .Values.replica.podSecurityContext "context" $) | nindent 8 }} + {{- end }} + {{- if .Values.replica.terminationGracePeriodSeconds }} + terminationGracePeriodSeconds: {{ .Values.replica.terminationGracePeriodSeconds }} + {{- end }} + initContainers: + {{- if and .Values.volumePermissions.enabled .Values.replica.persistence.enabled }} + - name: volume-permissions + image: {{ include "keydb.volumePermissions.image" . }} + imagePullPolicy: {{ .Values.volumePermissions.image.pullPolicy | quote }} + command: + - /bin/bash + - -ec + - | + find {{ .Values.replica.persistence.mountPath }} -mindepth 1 -maxdepth 1 -not -name ".snapshot" -not -name "lost+found" | xargs -r chown -R {{ printf "%d:%d" (int .Values.replica.containerSecurityContext.runAsUser) (int .Values.replica.podSecurityContext.fsGroup) }} + {{- if .Values.volumePermissions.containerSecurityContext.enabled }} + securityContext: {{- include "common.compatibility.renderSecurityContext" (dict "secContext" .Values.volumePermissions.containerSecurityContext "context" $) | nindent 12 }} + {{- end }} + {{- if .Values.volumePermissions.resources }} + resources: {{- toYaml .Values.volumePermissions.resources | nindent 12 }} + {{- else if ne .Values.volumePermissions.resourcesPreset "none" }} + resources: {{- include "common.resources.preset" (dict "type" .Values.volumePermissions.resourcesPreset) | nindent 12 }} + {{- end }} + volumeMounts: + - name: data + mountPath: {{ .Values.replica.persistence.mountPath }} + {{- if .Values.replica.persistence.subPath }} + subPath: {{ .Values.replica.persistence.subPath }} + {{- end }} + {{- end }} + {{- if .Values.replica.initContainers }} + {{- include "common.tplvalues.render" (dict "value" .Values.replica.initContainers "context" $) | nindent 8 }} + {{- end }} + containers: + - name: keydb + image: {{ template "keydb.image" . }} + imagePullPolicy: {{ .Values.image.pullPolicy }} + {{- if .Values.replica.containerSecurityContext.enabled }} + securityContext: {{- include "common.compatibility.renderSecurityContext" (dict "secContext" .Values.replica.containerSecurityContext "context" $) | nindent 12 }} + {{- end }} + {{- if .Values.diagnosticMode.enabled }} + command: {{- include "common.tplvalues.render" (dict "value" .Values.diagnosticMode.command "context" $) | nindent 12 }} + {{- else if .Values.replica.command }} + command: {{- include "common.tplvalues.render" (dict "value" .Values.replica.command "context" $) | nindent 12 }} + {{- else }} + command: + - /bin/bash + {{- end }} + {{- if .Values.diagnosticMode.enabled }} + args: {{- include "common.tplvalues.render" (dict "value" .Values.diagnosticMode.args "context" $) | nindent 12 }} + {{- else if .Values.replica.args }} + args: {{- include "common.tplvalues.render" (dict "value" .Values.replica.args "context" $) | nindent 12 }} + {{- else }} + args: + - -ec + - | + . /opt/bitnami/scripts/keydb-env.sh + + args=("/opt/bitnami/keydb/etc/keydb.conf") + {{- if .Values.auth.enabled }} + args+=("--requirepass" "$KEYDB_PASSWORD") + args+=("--masterauth" "$KEYDB_MASTER_PASSWORD") + {{- end }} + + {{- $masterReplicaCount := int .Values.master.replicaCount }} + {{- $masterFullname := include "keydb.master.fullname" . }} + {{- $masterHlSvcName := printf "%s-hl" (include "keydb.master.fullname" .) }} + {{- $replicaHlSvcName := printf "%s-hl" (include "keydb.replica.fullname" .) }} + {{- $releaseNamespace := include "common.names.namespace" . }} + {{- $clusterDomain := .Values.clusterDomain }} + {{- $masterPort := int .Values.master.containerPorts.keydb }} + {{- range $i := until $masterReplicaCount }} + args+=("--replicaof" "{{ printf "%s-%d.%s.%s.svc.%s" $masterFullname $i $masterHlSvcName $releaseNamespace $clusterDomain }}" {{ $masterPort }}) + {{- end }} + args+=("--replica-announce-ip" "${HOSTNAME}.{{ printf "%s.%s.svc.%s" $replicaHlSvcName $releaseNamespace $clusterDomain }}") + + exec keydb-server "${args[@]}" + {{- end }} + env: + - name: BITNAMI_DEBUG + value: {{ ternary "true" "false" (or .Values.image.debug .Values.diagnosticMode.enabled) | quote }} + - name: KEYDB_PORT_NUMBER + value: {{ .Values.replica.containerPorts.keydb | quote }} + {{- if .Values.auth.enabled }} + {{- if .Values.auth.usePasswordFiles }} + - name: KEYDB_PASSWORD_FILE + value: "/opt/bitnami/keydb/secrets/keydb-password" + - name: KEYDB_MASTER_PASSWORD_FILE + value: "/opt/bitnami/keydb/secrets/keydb-password" + {{- else }} + - name: KEYDB_PASSWORD + valueFrom: + secretKeyRef: + name: {{ template "keydb.secretName" . }} + key: {{ template "keydb.secretPasswordKey" . }} + - name: KEYDB_MASTER_PASSWORD + valueFrom: + secretKeyRef: + name: {{ template "keydb.secretName" . }} + key: {{ template "keydb.secretPasswordKey" . }} + {{- end }} + {{- end }} + {{- if .Values.replica.extraEnvVars }} + {{- include "common.tplvalues.render" (dict "value" .Values.replica.extraEnvVars "context" $) | nindent 12 }} + {{- end }} + {{- if or .Values.replica.extraEnvVarsCM .Values.replica.extraEnvVarsSecret }} + envFrom: + {{- if .Values.replica.extraEnvVarsCM }} + - configMapRef: + name: {{ include "common.tplvalues.render" (dict "value" .Values.replica.extraEnvVarsCM "context" $) }} + {{- end }} + {{- if .Values.replica.extraEnvVarsSecret }} + - secretRef: + name: {{ include "common.tplvalues.render" (dict "value" .Values.replica.extraEnvVarsSecret "context" $) }} + {{- end }} + {{- end }} + {{- if .Values.replica.resources }} + resources: {{- toYaml .Values.replica.resources | nindent 12 }} + {{- else if ne .Values.replica.resourcesPreset "none" }} + resources: {{- include "common.resources.preset" (dict "type" .Values.replica.resourcesPreset) | nindent 12 }} + {{- end }} + ports: + - name: keydb + containerPort: {{ .Values.replica.containerPorts.keydb }} + {{- if .Values.replica.extraContainerPorts }} + {{- include "common.tplvalues.render" (dict "value" .Values.replica.extraContainerPorts "context" $) | nindent 12 }} + {{- end }} + {{- if not .Values.diagnosticMode.enabled }} + {{- if .Values.replica.customLivenessProbe }} + livenessProbe: {{- include "common.tplvalues.render" (dict "value" .Values.replica.customLivenessProbe "context" $) | nindent 12 }} + {{- else if .Values.replica.livenessProbe.enabled }} + livenessProbe: {{- include "common.tplvalues.render" (dict "value" (omit .Values.replica.livenessProbe "enabled") "context" $) | nindent 12 }} + exec: + command: + - sh + - -c + - /opt/bitnami/scripts/health/ping_liveness_local_and_master.sh {{ .Values.replica.livenessProbe.timeoutSeconds }} + {{- end }} + {{- if .Values.replica.customReadinessProbe }} + readinessProbe: {{- include "common.tplvalues.render" (dict "value" .Values.replica.customReadinessProbe "context" $) | nindent 12 }} + {{- else if .Values.replica.readinessProbe.enabled }} + readinessProbe: {{- include "common.tplvalues.render" (dict "value" (omit .Values.replica.readinessProbe "enabled") "context" $) | nindent 12 }} + exec: + command: + - sh + - -c + - /opt/bitnami/scripts/health/ping_readiness_local_and_master.sh {{ .Values.replica.readinessProbe.timeoutSeconds }} + {{- end }} + {{- if .Values.replica.customStartupProbe }} + startupProbe: {{- include "common.tplvalues.render" (dict "value" .Values.replica.customStartupProbe "context" $) | nindent 12 }} + {{- else if .Values.replica.startupProbe.enabled }} + startupProbe: {{- include "common.tplvalues.render" (dict "value" (omit .Values.replica.startupProbe "enabled") "context" $) | nindent 12 }} + tcpSocket: + port: keydb + {{- end }} + {{- end }} + {{- if .Values.replica.lifecycleHooks }} + lifecycle: {{- include "common.tplvalues.render" (dict "value" .Values.replica.lifecycleHooks "context" $) | nindent 12 }} + {{- end }} + volumeMounts: + - name: data + mountPath: {{ .Values.replica.persistence.mountPath }} + {{- if .Values.replica.persistence.subPath }} + subPath: {{ .Values.replica.persistence.subPath }} + {{- end }} + - name: health-scripts + mountPath: /opt/bitnami/scripts/health + readOnly: true + {{- if and .Values.auth.enabled .Values.auth.usePasswordFiles }} + - name: keydb-password + mountPath: /opt/bitnami/keydb/secrets + readOnly: true + {{- end }} + {{- if .Values.tls.enabled }} + - name: keydb-certificates + mountPath: /opt/bitnami/keydb/certs + readOnly: true + {{- end }} + - name: config + mountPath: /opt/bitnami/keydb/etc + readOnly: true + - name: empty-dir + mountPath: /tmp + subPath: tmp-dir + {{- if .Values.replica.extraVolumeMounts }} + {{- include "common.tplvalues.render" (dict "value" .Values.replica.extraVolumeMounts "context" $) | nindent 12 }} + {{- end }} + {{- if .Values.metrics.enabled }} + - name: metrics + image: {{ include "keydb.metrics.image" . }} + imagePullPolicy: {{ .Values.metrics.image.pullPolicy | quote }} + {{- if .Values.metrics.containerSecurityContext.enabled }} + securityContext: {{- include "common.compatibility.renderSecurityContext" (dict "secContext" .Values.metrics.containerSecurityContext "context" $) | nindent 12 }} + {{- end }} + {{- if .Values.diagnosticMode.enabled }} + command: {{- include "common.tplvalues.render" (dict "value" .Values.diagnosticMode.command "context" $) | nindent 12 }} + {{- else if .Values.metrics.command }} + command: {{- include "common.tplvalues.render" (dict "value" .Values.metrics.command "context" $) | nindent 12 }} + {{- else }} + command: + - /bin/bash + - -c + - | + {{- if and .Values.auth.enabled .Values.auth.usePasswordFiles }} + export REDIS_PASSWORD="$(< $REDIS_PASSWORD_FILE)" + {{- end }} + redis_exporter{{- range $key, $value := .Values.metrics.extraArgs }} --{{ $key }}={{ $value }}{{- end }} + {{- end }} + {{- if .Values.diagnosticMode.enabled }} + args: {{- include "common.tplvalues.render" (dict "value" .Values.diagnosticMode.args "context" $) | nindent 12 }} + {{- end }} + env: + - name: REDIS_ALIAS + value: {{ template "common.names.fullname" . }} + - name: REDIS_EXPORTER_WEB_LISTEN_ADDRESS + value: {{ printf ":%v" .Values.metrics.containerPorts.http }} + {{- if .Values.auth.enabled }} + - name: REDIS_USER + value: default + {{- if .Values.auth.usePasswordFiles }} + - name: REDIS_PASSWORD_FILE + value: "/secrets/keydb-password" + {{- else }} + - name: REDIS_PASSWORD + valueFrom: + secretKeyRef: + name: {{ template "keydb.secretName" . }} + key: {{ template "keydb.secretPasswordKey" . }} + {{- end }} + {{- end }} + - name: REDIS_ADDR + value: redis://{{ .Values.metrics.keydbHost }}:{{ .Values.master.containerPorts.keydb }} + {{- if .Values.tls.enabled }} + - name: REDIS_EXPORTER_TLS_CLIENT_KEY_FILE + value: "/certs/tls.key" + - name: REDIS_EXPORTER_TLS_CLIENT_CERT_FILE + value: "/certs/tls.crt" + - name: REDIS_EXPORTER_TLS_CA_CERT_FILE + value: "/certs/ca.crt" + {{- end }} + {{- if .Values.metrics.extraEnvVars }} + {{- include "common.tplvalues.render" (dict "value" .Values.metrics.extraEnvVars "context" $) | nindent 12 }} + {{- end }} + ports: + - name: metrics + containerPort: {{ .Values.metrics.containerPorts.http }} + {{- if not .Values.diagnosticMode.enabled }} + {{- if .Values.metrics.customStartupProbe }} + startupProbe: {{- include "common.tplvalues.render" (dict "value" .Values.metrics.customStartupProbe "context" $) | nindent 12 }} + {{- else if .Values.metrics.startupProbe.enabled }} + startupProbe: {{- include "common.tplvalues.render" (dict "value" (omit .Values.metrics.startupProbe "enabled") "context" $) | nindent 12 }} + tcpSocket: + port: metrics + {{- end }} + {{- if .Values.metrics.customLivenessProbe }} + livenessProbe: {{- include "common.tplvalues.render" (dict "value" .Values.metrics.customLivenessProbe "context" $) | nindent 12 }} + {{- else if .Values.metrics.livenessProbe.enabled }} + livenessProbe: {{- include "common.tplvalues.render" (dict "value" (omit .Values.metrics.livenessProbe "enabled") "context" $) | nindent 12 }} + tcpSocket: + port: metrics + {{- end }} + {{- if .Values.metrics.customReadinessProbe }} + readinessProbe: {{- include "common.tplvalues.render" (dict "value" .Values.metrics.customReadinessProbe "context" $) | nindent 12 }} + {{- else if .Values.metrics.readinessProbe.enabled }} + readinessProbe: {{- include "common.tplvalues.render" (dict "value" (omit .Values.metrics.readinessProbe "enabled") "context" $) | nindent 12 }} + httpGet: + path: / + port: metrics + {{- end }} + {{- end }} + {{- if .Values.metrics.resources }} + resources: {{- toYaml .Values.metrics.resources | nindent 12 }} + {{- else if ne .Values.metrics.resourcesPreset "none" }} + resources: {{- include "common.resources.preset" (dict "type" .Values.metrics.resourcesPreset) | nindent 12 }} + {{- end }} + volumeMounts: + - name: empty-dir + mountPath: /tmp + subPath: app-tmp-dir + {{- if and .Values.auth.enabled .Values.auth.usePasswordFiles }} + - name: keydb-password + mountPath: /secrets + readOnly: true + {{- end }} + {{- if .Values.tls.enabled }} + - name: keydb-certificates + mountPath: /certs + readOnly: true + {{- end }} + {{- if .Values.metrics.extraVolumeMounts }} + {{- include "common.tplvalues.render" ( dict "value" .Values.metrics.extraVolumeMounts "context" $ ) | nindent 12 }} + {{- end }} + {{- end }} + {{- if .Values.replica.sidecars }} + {{- include "common.tplvalues.render" ( dict "value" .Values.replica.sidecars "context" $) | nindent 8 }} + {{- end }} + volumes: + - name: empty-dir + emptyDir: {} + - name: health-scripts + configMap: + name: {{ printf "%s-health" (include "common.names.fullname" .) }} + defaultMode: 0755 + - name: config + configMap: + name: {{ template "keydb.replica.configmapName" . }} + {{- if and .Values.auth.enabled .Values.auth.usePasswordFiles }} + - name: keydb-password + secret: + secretName: {{ template "keydb.secretName" . }} + items: + - key: {{ template "keydb.secretPasswordKey" . }} + path: keydb-password + {{- end }} + {{- if .Values.tls.enabled }} + - name: keydb-certificates + secret: + secretName: {{ template "keydb.tls.replica.secretName" . }} + defaultMode: 256 + {{- end }} + {{- if .Values.replica.extraVolumes }} + {{- include "common.tplvalues.render" (dict "value" .Values.replica.extraVolumes "context" $) | nindent 8 }} + {{- end }} + {{- if or (not .Values.replica.persistence.enabled) (not (empty .Values.replica.persistence.existingClaim)) }} + - name: data + {{- if not (empty .Values.replica.persistence.existingClaim) }} + persistentVolumeClaim: + claimName: {{ tpl .Values.replica.persistence.existingClaim . }} + {{- else }} + {{- if or .Values.replica.persistence.medium .Values.replica.persistence.sizeLimit }} + emptyDir: + {{- if .Values.replica.persistence.medium }} + medium: {{ .Values.replica.persistence.medium | quote }} + {{- end }} + {{- if .Values.replica.persistence.sizeLimit }} + sizeLimit: {{ .Values.replica.persistence.sizeLimit | quote }} + {{- end }} + {{- else }} + emptyDir: {} + {{- end }} + {{- end }} + {{- else }} + {{- if .Values.replica.persistentVolumeClaimRetentionPolicy.enabled }} + persistentVolumeClaimRetentionPolicy: + whenDeleted: {{ .Values.replica.persistentVolumeClaimRetentionPolicy.whenDeleted }} + whenScaled: {{ .Values.replica.persistentVolumeClaimRetentionPolicy.whenScaled }} + {{- end }} + volumeClaimTemplates: + - metadata: + name: data + {{- if or .Values.replica.persistence.annotations .Values.commonAnnotations }} + {{- $claimAnnotations := include "common.tplvalues.merge" (dict "values" .Values.replica.persistence.annotations .Values.commonAnnotations "context" .) | fromYaml }} + annotations: {{- include "common.tplvalues.render" ( dict "value" $claimAnnotations "context" $ ) | nindent 10 }} + {{- end }} + {{- if .Values.commonLabels }} + labels: {{- include "common.labels.matchLabels" ( dict "customLabels" .Values.commonLabels "context" $ ) | nindent 10 }} + {{- end }} + spec: + accessModes: + {{- range .Values.replica.persistence.accessModes }} + - {{ . | quote }} + {{- end }} + resources: + requests: + storage: {{ .Values.replica.persistence.size | quote }} + {{- if .Values.replica.persistence.selector }} + selector: {{- include "common.tplvalues.render" (dict "value" .Values.replica.persistence.selector "context" $) | nindent 10 }} + {{- end }} + {{- if .Values.replica.persistence.dataSource }} + dataSource: {{- include "common.tplvalues.render" (dict "value" .Values.replica.persistence.dataSource "context" $) | nindent 10 }} + {{- end }} + {{- include "common.storage.class" (dict "persistence" .Values.replica.persistence "global" .Values.global) | nindent 8 }} + {{- end }} +{{- end }} diff --git a/helm-charts/keydb/templates/replica/vpa.yaml b/helm-charts/keydb/templates/replica/vpa.yaml new file mode 100644 index 0000000..8d8d06b --- /dev/null +++ b/helm-charts/keydb/templates/replica/vpa.yaml @@ -0,0 +1,45 @@ +{{- /* +Copyright Broadcom, Inc. All Rights Reserved. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{- if and (eq .Values.architecture "replication") (include "common.capabilities.apiVersions.has" ( dict "version" "autoscaling.k8s.io/v1/VerticalPodAutoscaler" "context" . )) .Values.replica.autoscaling.vpa.enabled }} +apiVersion: autoscaling.k8s.io/v1 +kind: VerticalPodAutoscaler +metadata: + name: {{ template "keydb.replica.fullname" . }} + namespace: {{ include "common.names.namespace" . | quote }} + labels: {{- include "common.labels.standard" ( dict "customLabels" .Values.commonLabels "context" $ ) | nindent 4 }} + app.kubernetes.io/part-of: keydb + app.kubernetes.io/component: replica + {{- if or .Values.replica.autoscaling.vpa.annotations .Values.commonAnnotations }} + {{- $annotations := include "common.tplvalues.merge" ( dict "values" ( list .Values.replica.autoscaling.vpa.annotations .Values.commonAnnotations ) "context" . ) }} + annotations: {{- include "common.tplvalues.render" ( dict "value" $annotations "context" $) | nindent 4 }} + {{- end }} +spec: + resourcePolicy: + containerPolicies: + - containerName: replica + {{- with .Values.replica.autoscaling.vpa.controlledResources }} + controlledResources: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.replica.autoscaling.vpa.maxAllowed }} + maxAllowed: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.replica.autoscaling.vpa.minAllowed }} + minAllowed: + {{- toYaml . | nindent 8 }} + {{- end }} + targetRef: + apiVersion: {{ include "common.capabilities.statefulset.apiVersion" . }} + kind: Statefulset + name: {{ template "keydb.replica.fullname" . }} + {{- if .Values.replica.autoscaling.vpa.updatePolicy }} + updatePolicy: + {{- with .Values.replica.autoscaling.vpa.updatePolicy.updateMode }} + updateMode: {{ . }} + {{- end }} + {{- end }} +{{- end }} diff --git a/helm-charts/keydb/templates/sa.yaml b/helm-charts/keydb/templates/sa.yaml deleted file mode 100644 index db7569b..0000000 --- a/helm-charts/keydb/templates/sa.yaml +++ /dev/null @@ -1,11 +0,0 @@ -{{- if .Values.serviceAccount.enabled | and .Values.serviceAccount.create }} -apiVersion: v1 -kind: ServiceAccount -metadata: - name: {{ include "keydb.serviceAccountName" . | quote }} - labels: - {{- include "keydb.labels" . | nindent 4 }} -{{- with .Values.serviceAccount.extraSpec }} -{{ toYaml . }} -{{- end }} -{{- end }} diff --git a/helm-charts/keydb/templates/secret-utils.yaml b/helm-charts/keydb/templates/secret-utils.yaml deleted file mode 100644 index ec9b8fb..0000000 --- a/helm-charts/keydb/templates/secret-utils.yaml +++ /dev/null @@ -1,46 +0,0 @@ -apiVersion: v1 -kind: Secret -metadata: - name: {{ include "keydb.fullname" . }}-utils - labels: - {{- include "keydb.labels" . | nindent 4 }} -type: Opaque -stringData: - server.sh: | - #!/bin/bash - set -euxo pipefail - - host="$(hostname)" - replicas=() - for node in {0..{{ (sub (.Values.nodes | int) 1) }}}; do - if [ "${host}" != "{{ include "keydb.fullname" . }}-${node}" ]; then - replicas+=("--replicaof {{ include "keydb.fullname" . }}-${node}.{{ include "keydb.fullname" . }}-headless {{ .Values.port }}") - fi - done - exec keydb-server /etc/keydb/redis.conf \ - --active-replica {{ .Values.activeReplicas | quote }} \ - --multi-master {{ .Values.multiMaster | quote }} \ - --appendonly {{ .Values.appendonly | quote }} \ - --bind "0.0.0.0" \ - --port "{{ .Values.internalPort }}" \ - --protected-mode {{ .Values.protectedMode | quote }} \ - --server-threads {{ .Values.threads | quote }} \ - {{- if .Values.existingSecret }} - --masterauth "${REDIS_PASSWORD}" \ - --requirepass "${REDIS_PASSWORD}" \ - {{- else if .Values.password }} - --masterauth {{ .Values.password | quote }} \ - --requirepass {{ .Values.password | quote }} \ - {{- end }} - {{- range $item := .Values.configExtraArgs }} - {{- range $key, $value := $item }} - {{- if kindIs "invalid" $value }} - --{{ $key }} \ - {{- else if kindIs "slice" $value }} - --{{ $key }}{{ range $value }} {{ . | quote }}{{ end }} \ - {{- else }} - --{{ $key }} {{ $value | quote }} \ - {{- end }} - {{- end }} - {{- end }} - "${replicas[@]}" diff --git a/helm-charts/keydb/templates/secret.yaml b/helm-charts/keydb/templates/secret.yaml new file mode 100644 index 0000000..6c31696 --- /dev/null +++ b/helm-charts/keydb/templates/secret.yaml @@ -0,0 +1,20 @@ +{{- /* +Copyright Broadcom, Inc. All Rights Reserved. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{- if and .Values.auth.enabled (not .Values.auth.existingSecret) }} +apiVersion: v1 +kind: Secret +metadata: + name: {{ template "keydb.secretName" . }} + namespace: {{ include "common.names.namespace" . | quote }} + labels: {{- include "common.labels.standard" ( dict "customLabels" .Values.commonLabels "context" $ ) | nindent 4 }} + app.kubernetes.io/part-of: keydb + {{- if .Values.commonAnnotations }} + annotations: {{- include "common.tplvalues.render" ( dict "value" .Values.commonAnnotations "context" $ ) | nindent 4 }} + {{- end }} +type: Opaque +data: + keydb-password: {{ include "common.secrets.passwords.manage" (dict "secret" (include "keydb.secretName" .) "key" "keydb-password" "providedValues" (list "global.keydb.password" "auth.password") "length" 10 "honorProvidedValues" true "context" $) }} +{{- end }} diff --git a/helm-charts/keydb/templates/service-account.yaml b/helm-charts/keydb/templates/service-account.yaml new file mode 100644 index 0000000..94171cb --- /dev/null +++ b/helm-charts/keydb/templates/service-account.yaml @@ -0,0 +1,19 @@ +{{- /* +Copyright Broadcom, Inc. All Rights Reserved. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{- if .Values.serviceAccount.create }} +apiVersion: v1 +kind: ServiceAccount +metadata: + name: {{ include "keydb.serviceAccountName" . }} + namespace: {{ include "common.names.namespace" . | quote }} + labels: {{- include "common.labels.standard" ( dict "customLabels" .Values.commonLabels "context" $ ) | nindent 4 }} + app.kubernetes.io/part-of: keydb + {{- if or .Values.serviceAccount.annotations .Values.commonAnnotations }} + {{- $annotations := include "common.tplvalues.merge" (dict "values" (list .Values.serviceAccount.annotations .Values.commonAnnotations) "context" .) }} + annotations: {{- include "common.tplvalues.render" ( dict "value" $annotations "context" $ ) | nindent 4 }} + {{- end }} +automountServiceAccountToken: {{ .Values.serviceAccount.automountServiceAccountToken }} +{{- end }} diff --git a/helm-charts/keydb/templates/servicemonitor.yaml b/helm-charts/keydb/templates/servicemonitor.yaml new file mode 100644 index 0000000..45f126d --- /dev/null +++ b/helm-charts/keydb/templates/servicemonitor.yaml @@ -0,0 +1,50 @@ +{{- /* +Copyright Broadcom, Inc. All Rights Reserved. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{- if and .Values.metrics.enabled .Values.metrics.serviceMonitor.enabled }} +apiVersion: monitoring.coreos.com/v1 +kind: ServiceMonitor +metadata: + name: {{ template "common.names.fullname" . }} + namespace: {{ default (include "common.names.namespace" .) .Values.metrics.serviceMonitor.namespace | quote }} + {{- $labels := include "common.tplvalues.merge" (dict "values" (list .Values.metrics.serviceMonitor.labels .Values.commonLabels) "context" .) }} + labels: {{- include "common.labels.standard" ( dict "customLabels" $labels "context" $ ) | nindent 4 }} + app.kubernetes.io/component: metrics + app.kubernetes.io/part-of: keydb + {{- if or .Values.metrics.serviceMonitor.annotations .Values.commonAnnotations }} + {{- $annotations := include "common.tplvalues.merge" (dict "values" (list .Values.metrics.serviceMonitor.annotations .Values.commonAnnotations) "context" .) }} + annotations: {{- include "common.tplvalues.render" ( dict "value" $annotations "context" $ ) | nindent 4 }} + {{- end }} +spec: + jobLabel: {{ .Values.metrics.serviceMonitor.jobLabel | quote }} + selector: + matchLabels: {{- include "common.labels.matchLabels" ( dict "customLabels" .Values.commonLabels "context" $ ) | nindent 6 }} + app.kubernetes.io/component: metrics + app.kubernetes.io/part-of: keydb + {{- if .Values.metrics.serviceMonitor.selector }} + {{- include "common.tplvalues.render" (dict "value" .Values.metrics.serviceMonitor.selector "context" $) | nindent 6 }} + {{- end }} + endpoints: + - port: http-metrics + path: "/metrics" + {{- if .Values.metrics.serviceMonitor.interval }} + interval: {{ .Values.metrics.serviceMonitor.interval }} + {{- end }} + {{- if .Values.metrics.serviceMonitor.scrapeTimeout }} + scrapeTimeout: {{ .Values.metrics.serviceMonitor.scrapeTimeout }} + {{- end }} + {{- if .Values.metrics.serviceMonitor.honorLabels }} + honorLabels: {{ .Values.metrics.serviceMonitor.honorLabels }} + {{- end }} + {{- if .Values.metrics.serviceMonitor.metricRelabelings }} + metricRelabelings: {{- include "common.tplvalues.render" ( dict "value" .Values.metrics.serviceMonitor.metricRelabelings "context" $) | nindent 8 }} + {{- end }} + {{- if .Values.metrics.serviceMonitor.relabelings }} + relabelings: {{- include "common.tplvalues.render" ( dict "value" .Values.metrics.serviceMonitor.relabelings "context" $) | nindent 8 }} + {{- end }} + namespaceSelector: + matchNames: + - {{ include "common.names.namespace" . | quote }} +{{- end }} diff --git a/helm-charts/keydb/templates/sm.yaml b/helm-charts/keydb/templates/sm.yaml deleted file mode 100644 index 8f94b4a..0000000 --- a/helm-charts/keydb/templates/sm.yaml +++ /dev/null @@ -1,31 +0,0 @@ -{{- if and .Values.exporter.enabled .Values.serviceMonitor.enabled }} -apiVersion: monitoring.coreos.com/v1 -kind: ServiceMonitor -metadata: - name: {{ include "keydb.fullname" . }} - labels: - {{- include "keydb.labels" . | nindent 4 }} - {{- if .Values.serviceMonitor.labels }} - {{- toYaml .Values.serviceMonitor.labels | nindent 4 }} - {{- end }} - {{- if .Values.serviceMonitor.annotations }} - annotations: - {{- toYaml .Values.serviceMonitor.annotations | nindent 4 }} - {{- end }} -spec: - selector: - matchLabels: - {{- include "keydb.labels" . | nindent 6 }} - namespaceSelector: - matchNames: - - {{.Release.Namespace }} - endpoints: - - port: redis-exporter - path: {{ .Values.exporter.scrapePath }} - {{- if .Values.serviceMonitor.interval }} - interval: {{ .Values.serviceMonitor.interval }} - {{- end }} - {{- if .Values.serviceMonitor.scrapeTimeout }} - scrapeTimeout: {{ .Values.serviceMonitor.scrapeTimeout }} - {{- end }} -{{- end }} diff --git a/helm-charts/keydb/templates/sts.yaml b/helm-charts/keydb/templates/sts.yaml deleted file mode 100644 index 7dd9927..0000000 --- a/helm-charts/keydb/templates/sts.yaml +++ /dev/null @@ -1,311 +0,0 @@ -apiVersion: apps/v1 -kind: StatefulSet -metadata: - name: {{ include "keydb.fullname" . }} - {{- if .Values.annotations }} - annotations: - {{- toYaml .Values.annotations | nindent 4 }} - {{- end }} - labels: - {{- include "keydb.labels" . | nindent 4 }} -spec: - replicas: {{ .Values.nodes }} - serviceName: {{ include "keydb.fullname" . }}-headless - selector: - matchLabels: - {{- include "keydb.selectorLabels" . | nindent 6 }} - template: - metadata: - annotations: - checksum/secret-utils: {{ include (print $.Template.BasePath "/secret-utils.yaml") . | sha256sum }} - {{- if .Values.exporter.enabled }} - prometheus.io/scrape: "true" - prometheus.io/path: "{{ .Values.exporter.scrapePath }}" - prometheus.io/port: "{{ .Values.exporter.port }}" - {{- end }} - {{- if .Values.podAnnotations }} - {{- toYaml .Values.podAnnotations | nindent 8 }} - {{- end }} - labels: - {{- include "keydb.labels" . | nindent 8 }} - spec: - affinity: - {{- include "common.tplvalues.render" (dict "value" .Values.affinity "context" $) | nindent 8 }} - {{- if .Values.extraInitContainers }} - initContainers: - {{- toYaml .Values.extraInitContainers | nindent 6 }} - {{- end }} - containers: - - name: keydb - {{- if .Values.image }} - image: {{ .Values.image }} - {{- else }} - image: {{ .Values.imageRepository }}:{{ .Values.imageTag }} - {{- end }} - imagePullPolicy: {{ .Values.imagePullPolicy }} - command: - - /utils/server.sh - env: - - name: REDIS_PORT - value: {{ .Values.internalPort | quote }} - {{- if .Values.existingSecret }} - - name: REDIS_PASSWORD - valueFrom: - secretKeyRef: - name: {{ .Values.existingSecret }} - key: {{ .Values.existingSecretPasswordKey }} - {{- else if .Values.password }} - - name: REDIS_PASSWORD - value: "{{ .Values.password }}" - {{- end }} - ports: - - name: {{ .Values.internalPortName }} - containerPort: {{ .Values.internalPort | int }} - protocol: TCP - {{- if .Values.livenessProbe.enabled }} - livenessProbe: - {{- if .Values.livenessProbe.custom }} - {{- toYaml .Values.livenessProbe.custom | nindent 10 }} - {{- else }} - initialDelaySeconds: {{ .Values.livenessProbe.initialDelaySeconds }} - periodSeconds: {{ .Values.livenessProbe.periodSeconds }} - # One second longer than command timeout should prevent generation of zombie processes. - timeoutSeconds: {{ add1 .Values.livenessProbe.timeoutSeconds }} - successThreshold: {{ .Values.livenessProbe.successThreshold }} - failureThreshold: {{ .Values.livenessProbe.failureThreshold }} - exec: - command: - - sh - - -c - - /health/ping_liveness_local.sh {{ .Values.livenessProbe.timeoutSeconds }} - {{- end }} - {{- end }} - {{- if .Values.readinessProbe.enabled }} - readinessProbe: - {{- if .Values.readinessProbe.custom }} - {{- toYaml .Values.readinessProbe.custom | nindent 10 }} - {{- else }} - initialDelaySeconds: {{ .Values.readinessProbe.initialDelaySeconds }} - periodSeconds: {{ .Values.readinessProbe.periodSeconds }} - # One second longer than command timeout should prevent generation of zombie processes. - timeoutSeconds: {{ add1 .Values.readinessProbe.timeoutSeconds }} - successThreshold: {{ .Values.readinessProbe.successThreshold }} - failureThreshold: {{ .Values.readinessProbe.failureThreshold }} - exec: - command: - - sh - - -c - - /health/ping_readiness_local.sh {{ .Values.readinessProbe.timeoutSeconds }} - {{- end }} - {{- end }} - {{- if .Values.startupProbe.enabled }} - startupProbe: - {{- if .Values.startupProbe.custom }} - {{- toYaml .Values.startupProbe.custom | nindent 10 }} - {{- else }} - periodSeconds: {{ .Values.startupProbe.periodSeconds }} - # One second longer than command timeout should prevent generation of zombie processes. - timeoutSeconds: {{ add1 .Values.startupProbe.timeoutSeconds }} - failureThreshold: {{ .Values.startupProbe.failureThreshold }} - exec: - command: - - sh - - -c - - /health/ping_readiness_local.sh {{ .Values.startupProbe.timeoutSeconds }} - {{- end }} - {{- end }} - {{- if .Values.lifecycle }} - lifecycle: - {{- toYaml .Values.lifecycle | nindent 10 }} - {{- end }} - resources: - {{- toYaml .Values.resources | nindent 10 }} - securityContext: - {{- toYaml .Values.keydb.securityContext | nindent 10 }} - volumeMounts: - - name: health - mountPath: /health - - name: keydb-data - mountPath: /data - - name: utils - mountPath: /utils - readOnly: true - {{- if .Values.exporter.enabled }} - - name: redis-exporter - {{- if .Values.exporter.image }} - image: {{ .Values.exporter.image }} - {{- else }} - image: {{ .Values.exporter.imageRepository }}:{{ .Values.exporter.imageTag }} - {{- end }} - imagePullPolicy: {{ .Values.exporter.pullPolicy }} - args: - {{- range $item := .Values.exporter.extraArgs }} - {{- range $key, $value := $item }} - {{- if kindIs "invalid" $value }} - - --{{ $key }} - {{- else if kindIs "slice" $value }} - - --{{ $key }} - {{- range $value }} - - {{ . | quote }} - {{- end }} - {{- else }} - - --{{ $key }} - - {{ $value | quote }} - {{- end }} - {{- end }} - {{- end }} - env: - - name: REDIS_EXPORTER_WEB_LISTEN_ADDRESS - value: "0.0.0.0:{{ .Values.exporter.port }}" - - name: REDIS_EXPORTER_WEB_TELEMETRY_PATH - value: {{ .Values.exporter.scrapePath | quote }} - - name: REDIS_ADDR - value: "redis://localhost:{{ .Values.internalPort }}" - {{- if .Values.existingSecret }} - - name: REDIS_PASSWORD - valueFrom: - secretKeyRef: - name: {{ .Values.existingSecret }} - key: {{ .Values.existingSecretPasswordKey }} - {{- else if .Values.password }} - - name: REDIS_PASSWORD - value: "{{ .Values.password }}" - {{- end }} - {{- if .Values.exporter.livenessProbe }} - livenessProbe: - {{- toYaml .Values.exporter.livenessProbe | nindent 10 }} - {{- end }} - {{- if .Values.exporter.readinessProbe }} - readinessProbe: - {{- toYaml .Values.exporter.readinessProbe | nindent 10 }} - {{- end }} - {{- if .Values.exporter.startupProbe }} - startupProbe: - {{- toYaml .Values.exporter.startupProbe | nindent 10 }} - {{- end }} - resources: - {{- toYaml .Values.exporter.resources | nindent 10 }} - securityContext: - {{- toYaml .Values.exporter.securityContext | nindent 10 }} - ports: - - name: {{ .Values.exporter.portName | quote }} - containerPort: {{ .Values.exporter.port }} - protocol: TCP - {{- end }} - {{- if .Values.scripts.enabled }} - - name: scripts - {{- if .Values.image }} - image: {{ .Values.image }} - {{- else }} - image: {{ .Values.imageRepository }}:{{ .Values.imageTag }} - {{- end }} - imagePullPolicy: {{ .Values.imagePullPolicy }} - command: - - /health/scripts_local.sh - env: - - name: REDIS_PORT - value: {{ .Values.internalPort | quote }} - {{- if .Values.existingSecret }} - - name: REDIS_PASSWORD - valueFrom: - secretKeyRef: - name: {{ .Values.existingSecret }} - key: {{ .Values.existingSecretPasswordKey }} - {{- else if .Values.password }} - - name: REDIS_PASSWORD - value: "{{ .Values.password }}" - {{- end }} - resources: - {{- toYaml .Values.scripts.resources | nindent 10 }} - securityContext: - {{- toYaml .Values.scripts.securityContext | nindent 10 }} - volumeMounts: - - name: health - mountPath: /health - - name: keydb-data - mountPath: /data - {{- end }} - {{- if .Values.extraContainers }} - {{- toYaml .Values.extraContainers | nindent 6 }} - {{- end }} - imagePullSecrets: - {{- toYaml .Values.imagePullSecrets | nindent 8 }} - securityContext: - {{- toYaml .Values.securityContext | nindent 8 }} - {{- if .Values.serviceAccount.enabled }} - serviceAccountName: {{ include "keydb.serviceAccountName" . | quote }} - {{- end }} - {{- if .Values.tolerations }} - tolerations: - {{- toYaml .Values.tolerations | nindent 8 }} - {{- end }} - {{- if .Values.nodeSelector }} - nodeSelector: - {{- toYaml .Values.nodeSelector | nindent 8 }} - {{- end }} - {{- if .Values.topologySpreadConstraints }} - topologySpreadConstraints: - {{- range .Values.topologySpreadConstraints }} - - labelSelector: - matchLabels: - {{- include "keydb.selectorLabels" $ | nindent 14 }} - topologyKey: {{ default "topology.kubernetes.io/zone" .topologyKey }} - maxSkew: {{ .maxSkew }} - {{- if .minDomains }} - minDomains: {{ .minDomains }} - {{- end }} - whenUnsatisfiable: {{ default "DoNotSchedule" .whenUnsatisfiable }} - {{- if .nodeAffinityPolicy }} - nodeAffinityPolicy: {{ .nodeAffinityPolicy }} - {{- end }} - {{- if .nodeTaintsPolicy }} - nodeTaintsPolicy: {{ .nodeTaintsPolicy }} - {{- end }} - {{- end }} - {{- end }} - volumes: - - name: health - configMap: - name: {{ include "keydb.fullname" . }}-health - defaultMode: 0755 - - name: utils - secret: - secretName: {{ include "keydb.fullname" . }}-utils - defaultMode: 0755 - items: - - key: server.sh - path: server.sh - {{- if not .Values.persistentVolume.enabled }} - - name: keydb-data - emptyDir: {{- toYaml .Values.persistentVolume.emptyDir | nindent 10 }} - {{- end }} - {{- if .Values.extraVolumes }} - {{- toYaml .Values.extraVolumes | nindent 6 }} - {{- end }} - {{- if .Values.persistentVolume.enabled }} - volumeClaimTemplates: - - metadata: - name: keydb-data - annotations: - {{- if .Values.persistentVolume.annotations }} - {{- toYaml .Values.persistentVolume.annotations | nindent 8 }} - {{- end }} - labels: - spec: - accessModes: - {{- toYaml .Values.persistentVolume.accessModes | nindent 8 }} - resources: - requests: - storage: {{ .Values.persistentVolume.size }} - {{- if .Values.persistentVolume.storageClass }} - {{- if (eq "-" .Values.persistentVolume.storageClass) }} - storageClassName: "" - {{ else }} - storageClassName: {{ .Values.persistentVolume.storageClass }} - {{- end }} - {{- end }} - {{- if .Values.persistentVolume.selector }} - selector: - {{- toYaml .Values.persistentVolume.selector | nindent 8 }} - {{- end }} - {{- end }} diff --git a/helm-charts/keydb/templates/svc-headless.yaml b/helm-charts/keydb/templates/svc-headless.yaml deleted file mode 100644 index ea4298e..0000000 --- a/helm-charts/keydb/templates/svc-headless.yaml +++ /dev/null @@ -1,22 +0,0 @@ -# Headless service -apiVersion: v1 -kind: Service -metadata: - name: {{ include "keydb.fullname" . }}-headless - labels: - {{- include "keydb.labels" . | nindent 4 }} - annotations: - {{- toYaml .Values.service.annotations | nindent 4 }} -spec: - type: ClusterIP - clusterIP: None - ports: - - name: {{ .Values.portName | quote }} - port: {{ .Values.port | int }} - protocol: TCP - targetPort: {{ .Values.internalPortName | quote }} - {{- if .Values.service.appProtocol.enabled }} - appProtocol: redis - {{- end }} - selector: - {{- include "keydb.selectorLabels" . | nindent 4 }} diff --git a/helm-charts/keydb/templates/svc-lb.yaml b/helm-charts/keydb/templates/svc-lb.yaml deleted file mode 100644 index 4370915..0000000 --- a/helm-charts/keydb/templates/svc-lb.yaml +++ /dev/null @@ -1,26 +0,0 @@ -{{- if .Values.loadBalancer.enabled }} -# Load balancer service -apiVersion: v1 -kind: Service -metadata: - name: {{ include "keydb.fullname" . }}-lb - labels: - {{- include "keydb.labels" . | nindent 4 }} - annotations: - {{- toYaml .Values.loadBalancer.annotations | nindent 4 }} -spec: - type: LoadBalancer - {{- if .Values.loadBalancer.extraSpec }} - {{- toYaml .Values.loadBalancer.extraSpec | nindent 2 }} - {{- end }} - ports: - - name: {{ .Values.portName | quote }} - port: {{ .Values.port | int }} - protocol: TCP - targetPort: {{ .Values.internalPortName | quote }} - {{- if .Values.service.appProtocol.enabled }} - appProtocol: redis - {{- end }} - selector: - {{- include "keydb.selectorLabels" . | nindent 4 }} -{{- end }} diff --git a/helm-charts/keydb/templates/svc.yaml b/helm-charts/keydb/templates/svc.yaml deleted file mode 100644 index 1d1ef1d..0000000 --- a/helm-charts/keydb/templates/svc.yaml +++ /dev/null @@ -1,28 +0,0 @@ -apiVersion: v1 -kind: Service -metadata: - name: {{ include "keydb.fullname" . }} - labels: - {{- include "keydb.labels" . | nindent 4 }} - annotations: - {{- toYaml .Values.service.annotations | nindent 4 }} -spec: - type: ClusterIP - ports: - - name: {{ .Values.portName | quote }} - port: {{ .Values.port | int }} - protocol: TCP - targetPort: {{ .Values.internalPortName | quote }} - {{- if .Values.service.appProtocol.enabled }} - appProtocol: redis - {{- end }} - - name: {{ .Values.exporter.portName | quote }} - port: {{ .Values.exporter.port | int }} - protocol: TCP - targetPort: {{ .Values.exporter.portName | quote }} - {{- if .Values.service.appProtocol.enabled }} - appProtocol: http - {{- end }} - selector: - {{- include "keydb.selectorLabels" . | nindent 4 }} - sessionAffinity: ClientIP diff --git a/helm-charts/keydb/templates/tls-secret.yaml b/helm-charts/keydb/templates/tls-secret.yaml new file mode 100644 index 0000000..890090a --- /dev/null +++ b/helm-charts/keydb/templates/tls-secret.yaml @@ -0,0 +1,91 @@ +{{- /* +Copyright Broadcom, Inc. All Rights Reserved. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{- if and .Values.tls.enabled .Values.tls.autoGenerated.enabled (eq .Values.tls.autoGenerated.engine "helm") -}} +{{- $ca := genCA "keydb-ca" 365 }} +{{- $releaseNamespace := include "common.names.namespace" . }} +{{- $clusterDomain := .Values.clusterDomain }} +{{- $masterFullname := include "keydb.master.fullname" . }} +{{- $masterHlSvcName := printf "%s-hl" (include "keydb.master.fullname" .) }} +{{- $masterAltNames := list (printf "*.%s.%s.svc.%s" $masterHlSvcName $releaseNamespace $clusterDomain) (printf "%s.%s.svc.%s" $masterHlSvcName $releaseNamespace $clusterDomain) $masterHlSvcName (printf "%s.%s.svc.%s" $masterFullname $releaseNamespace $clusterDomain) $masterFullname "127.0.0.1" "localhost" }} +{{- $masterCert := genSignedCert $masterFullname nil $masterAltNames 365 $ca }} +{{- $masterSecretName := include "keydb.tls.master.secretName" . }} +apiVersion: v1 +kind: Secret +metadata: + name: {{ $masterSecretName }} + namespace: {{ include "common.names.namespace" . | quote }} + labels: {{- include "common.labels.standard" ( dict "customLabels" .Values.commonLabels "context" $ ) | nindent 4 }} + app.kubernetes.io/part-of: keydb + app.kubernetes.io/component: master + {{- if .Values.commonAnnotations }} + annotations: {{- include "common.tplvalues.render" ( dict "value" .Values.commonAnnotations "context" $ ) | nindent 4 }} + {{- end }} +type: kubernetes.io/tls +data: + ca.crt: {{ include "common.secrets.lookup" (dict "secret" $masterSecretName "key" "ca.crt" "defaultValue" $ca.Cert "context" $) }} + tls.crt: {{ include "common.secrets.lookup" (dict "secret" $masterSecretName "key" "tls.crt" "defaultValue" $masterCert.Cert "context" $) }} + tls.key: {{ include "common.secrets.lookup" (dict "secret" $masterSecretName "key" "tls.key" "defaultValue" $masterCert.Key "context" $) }} +--- +{{- if eq .Values.architecture "replication" }} +{{- $replicaFullname := include "keydb.replica.fullname" . }} +{{- $replicaAltNames := list (printf "%s.%s.svc.%s" $replicaFullname $releaseNamespace $clusterDomain) $replicaFullname "127.0.0.1" "localhost" }} +{{- $replicaCert := genSignedCert $replicaFullname nil $replicaAltNames 365 $ca }} +{{- $replicaSecretName := include "keydb.tls.replica.secretName" . }} +apiVersion: v1 +kind: Secret +metadata: + name: {{ $replicaSecretName }} + namespace: {{ include "common.names.namespace" . | quote }} + labels: {{- include "common.labels.standard" ( dict "customLabels" .Values.commonLabels "context" $ ) | nindent 4 }} + app.kubernetes.io/part-of: keydb + app.kubernetes.io/component: replica + {{- if .Values.commonAnnotations }} + annotations: {{- include "common.tplvalues.render" ( dict "value" .Values.commonAnnotations "context" $ ) | nindent 4 }} + {{- end }} +type: kubernetes.io/tls +data: + ca.crt: {{ include "common.secrets.lookup" (dict "secret" $replicaSecretName "key" "ca.crt" "defaultValue" $ca.Cert "context" $) }} + tls.crt: {{ include "common.secrets.lookup" (dict "secret" $replicaSecretName "key" "tls.crt" "defaultValue" $replicaCert.Cert "context" $) }} + tls.key: {{ include "common.secrets.lookup" (dict "secret" $replicaSecretName "key" "tls.key" "defaultValue" $replicaCert.Key "context" $) }} +{{- end }} +{{- else if and .Values.tls.enabled (not .Values.tls.autoGenerated.enabled) (empty .Values.tls.existingCASecret) (empty .Values.tls.master.existingSecret) (empty .Values.tls.replica.existingSecret) -}} +apiVersion: v1 +kind: Secret +metadata: + name: {{ template "keydb.tls.master.secretName" . }} + namespace: {{ include "common.names.namespace" . | quote }} + labels: {{- include "common.labels.standard" ( dict "customLabels" .Values.commonLabels "context" $ ) | nindent 4 }} + app.kubernetes.io/part-of: keydb + app.kubernetes.io/component: master + {{- if .Values.commonAnnotations }} + annotations: {{- include "common.tplvalues.render" ( dict "value" .Values.commonAnnotations "context" $ ) | nindent 4 }} + {{- end }} +type: kubernetes.io/tls +data: + ca.crt: {{ required "A valid .Values.tls.ca entry required!" .Values.tls.ca | b64enc | quote }} + tls.crt: {{ required "A valid .Values.tls.master.cert entry required!" .Values.tls.master.cert | b64enc | quote }} + tls.key: {{ required "A valid .Values.tls.master.key entry required!" .Values.tls.master.key | b64enc | quote }} +--- +{{- if eq .Values.architecture "replication" }} +apiVersion: v1 +kind: Secret +metadata: + name: {{ template "keydb.tls.replica.secretName" . }} + namespace: {{ include "common.names.namespace" . | quote }} + labels: {{- include "common.labels.standard" ( dict "customLabels" .Values.commonLabels "context" $ ) | nindent 4 }} + app.kubernetes.io/part-of: keydb + app.kubernetes.io/component: replica + {{- if .Values.commonAnnotations }} + annotations: {{- include "common.tplvalues.render" ( dict "value" .Values.commonAnnotations "context" $ ) | nindent 4 }} + {{- end }} +type: kubernetes.io/tls +data: + ca.crt: {{ required "A valid .Values.tls.ca entry required!" .Values.tls.ca | b64enc | quote }} + tls.crt: {{ required "A valid .Values.tls.replica.cert entry required!" .Values.tls.replica.cert | b64enc | quote }} + tls.key: {{ required "A valid .Values.tls.replica.key entry required!" .Values.tls.replica.key | b64enc | quote }} +{{- end }} +{{- end }} + diff --git a/helm-charts/keydb/values.yaml b/helm-charts/keydb/values.yaml index dd7b5a6..e494035 100644 --- a/helm-charts/keydb/values.yaml +++ b/helm-charts/keydb/values.yaml @@ -1,279 +1,1529 @@ -nameOverride: "" -fullnameOverride: "" - -imageRepository: eqalpha/keydb -imageTag: x86_64_v6.3.2 -imagePullPolicy: IfNotPresent -imagePullSecrets: [] - -nodes: 3 - -password: "" -existingSecret: "" -existingSecretPasswordKey: "password" -port: 6379 -portName: server -internalPort: 6379 -internalPortName: keydb - -threads: 2 - -multiMaster: "yes" -activeReplicas: "yes" -protectedMode: "no" -appendonly: "no" - -annotations: {} - -configExtraArgs: [] - # - somesimple: "argument" - # - client-output-buffer-limit: ["normal", "0", "0", "0"] - # - client-output-buffer-limit: ["replica", "268435456", "67108864", "60"] - # - client-output-buffer-limit: ["pubsub", "33554432", "8388608", "60"] - -podAnnotations: {} - -tolerations: {} - # - effect: NoSchedule - # key: key - # operator: Equal - # value: value - -nodeSelector: {} - # topology.kubernetes.io/region: some-region - -topologySpreadConstraints: [] -# - maxSkew: 1 -# ## Optional keys -# # whenUnsatisfiable: DoNotSchedule -# # topologyKey: "topology.kubernetes.io/zone" -# # minDomains: 1 -# # nodeAffinityPolicy: Honor -# # nodeTaintsPolicy: Honor - -affinity: - podAntiAffinity: - preferredDuringSchedulingIgnoredDuringExecution: - - weight: 100 - podAffinityTerm: - labelSelector: - matchExpressions: - - key: app.kubernetes.io/name - operator: In - values: - - '{{ include "keydb.name" . }}' - - key: app.kubernetes.io/instance - operator: In - values: - - '{{ .Release.Name }}' - topologyKey: "kubernetes.io/hostname" - -additionalAffinities: {} - # nodeAffinity: - # requiredDuringSchedulingIgnoredDuringExecution: - # nodeSelectorTerms: - # - matchExpressions: - # - key: node_pool - # operator: In - # values: somenodepool +# Copyright Broadcom, Inc. All Rights Reserved. +# SPDX-License-Identifier: APACHE-2.0 -podDisruptionBudget: - enabled: true - maxUnavailable: 1 - -# Additional init containers -extraInitContainers: [] - -# Additional sidecar containers -extraContainers: [] -# - name: backup -# image: minio/mc:latest - -# Volumes that can be used in init and sidecar containers -extraVolumes: [] -# - name: volume-from-secret -# secret: -# secretName: secret-to-mount -# - name: empty-dir-volume -# emptyDir: {} - -# Liveness Probe -livenessProbe: - enabled: true - custom: {} - # tcpSocket: - # port: keydb - # initialDelaySeconds: 30 - initialDelaySeconds: 20 - periodSeconds: 5 - timeoutSeconds: 5 - successThreshold: 1 - failureThreshold: 5 - -# Readiness Probe -readinessProbe: - enabled: true - custom: {} - # tcpSocket: - # port: keydb - # initialDelaySeconds: 30 - initialDelaySeconds: 20 - periodSeconds: 5 - timeoutSeconds: 1 - successThreshold: 1 - failureThreshold: 5 +## @section Global parameters +## Global Docker image parameters +## Please, note that this will override the image parameters, including dependencies, configured to use the global value +## Current available global Docker image parameters: imageRegistry, imagePullSecrets and storageClass +## -# Random UUID for readiness GET probe -readinessProbeRandomUuid: "90f717dd-0e68-43b8-9363-fddaad00d6c9" - -# Startup Probe -startupProbe: - enabled: true - custom: {} - # tcpSocket: - # port: keydb - periodSeconds: 5 - timeoutSeconds: 1 - failureThreshold: 24 - -# Lifecycle Hooks -lifecycle: {} - # preStop: - # exec: - # command: - # - sh - # - -c - # - "sleep 15; kill 1" - -persistentVolume: - enabled: true - accessModes: - - ReadWriteOnce - selector: {} - # matchLabels: - # release: "stable" - # matchExpressions: - # - {key: environment, operator: In, values: [dev]} - size: 1Gi - - ## If defined, storageClassName: - ## If set to "-", storageClassName: "", which disables dynamic provisioning - ## If undefined (the default) or set to null, no storageClassName spec is - ## set, choosing the default provisioner. (gp2 on AWS, standard on - ## GKE, AWS & OpenStack) +## @param global.imageRegistry Global Docker image registry +## @param global.imagePullSecrets Global Docker registry secret names as an array +## @param global.defaultStorageClass Global default StorageClass for Persistent Volume(s) +## @param global.keydb.password Global KeyDB password (overrides `auth.password`) +## +global: + imageRegistry: "" + ## e.g: + ## imagePullSecrets: + ## - myRegistryKeySecretName ## - # storageClass: "-" - - # If persistentVolume is disable, use this to configure the empty dir - emptyDir: {} - -resources: {} - -# Please read https://kubernetes.io/docs/tasks/administer-cluster/sysctl-cluster/#enabling-unsafe-sysctls -# before sysctls setup -securityContext: {} - # sysctls: - # - name: net.core.somaxconn - # value: "512" - # - name: vm.overcommit_memory - # value: "1" - -keydb: - # Container security context - securityContext: {} - -service: - annotations: {} - appProtocol: - enabled: false - -serviceAccount: - enabled: false - create: true - name: "" + imagePullSecrets: [] + defaultStorageClass: "" + keydb: + password: "" + ## Security parameters + ## + security: + ## @param global.security.allowInsecureImages Allows skipping image verification + allowInsecureImages: false + ## Compatibility adaptations for Kubernetes platforms + ## + compatibility: + ## Compatibility adaptations for Openshift + ## + openshift: + ## @param global.compatibility.openshift.adaptSecurityContext Adapt the securityContext sections of the deployment to make them compatible with Openshift restricted-v2 SCC: remove runAsUser, runAsGroup and fsGroup and let the platform use their allowed default IDs. Possible values: auto (apply if the detected running cluster is Openshift), force (perform the adaptation always), disabled (do not perform adaptation) + ## + adaptSecurityContext: auto - # extraSpec: - # automountServiceAccountToken: false - # imagePullSecrets: - # - name: pull-secret - extraSpec: {} +## @section Common parameters +## -loadBalancer: +## @param kubeVersion Override Kubernetes version +## +kubeVersion: "" +## @param apiVersions Override Kubernetes API versions reported by .Capabilities +## +apiVersions: [] +## @param nameOverride String to partially override common.names.name +## +nameOverride: "" +## @param fullnameOverride String to fully override common.names.fullname +## +fullnameOverride: "" +## @param namespaceOverride String to fully override common.names.namespace +## +namespaceOverride: "" +## @param commonLabels Labels to add to all deployed objects +## +commonLabels: {} +## @param commonAnnotations Annotations to add to all deployed objects +## +commonAnnotations: {} +## @param clusterDomain Kubernetes cluster domain name +## +clusterDomain: cluster.local +## @param extraDeploy Array of extra objects to deploy with the release +## +extraDeploy: [] +## Diagnostic mode +## @param diagnosticMode.enabled Enable diagnostic mode (all probes will be disabled and the command will be overridden) +## @param diagnosticMode.command Command to override all containers in the chart release +## @param diagnosticMode.args Args to override all containers in the chart release +## +diagnosticMode: enabled: false + command: + - sleep + args: + - infinity - # annotations: - # service.beta.kubernetes.io/aws-load-balancer-type: nlb - annotations: {} - - # extraSpec: - # loadBalancerIP: "1.2.3.4" - # loadBalancerSourceRanges: - # - 1.2.3.4/32 - extraSpec: {} +## @section KeyDB Image parameters +## ref: https://hub.docker.com/r/bitnami/keydb/tags/ +## @param image.registry [default: REGISTRY_NAME] KeyDB image registry +## @param image.repository [default: REPOSITORY_NAME/keydb] KeyDB image repository +## @skip image.tag KeyDB image tag (immutable tags are recommended) +## @param image.digest KeyDB image digest in the way sha256:aa.... Please note this parameter, if set, will override the tag image tag (immutable tags are recommended) +## @param image.pullPolicy KeyDB image pull policy +## @param image.pullSecrets KeyDB image pull secrets +## @param image.debug Enable KeyDB image debug mode +## +image: + registry: docker.io + repository: bitnamilegacy/keydb + tag: latest + digest: "" + ## Specify a imagePullPolicy + ## ref: https://kubernetes.io/docs/concepts/containers/images/#pre-pulled-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/ + ## e.g: + ## pullSecrets: + ## - myRegistryKeySecretName + ## + pullSecrets: [] + debug: false -# Prometheus-operator ServiceMonitor -serviceMonitor: - # Redis exporter must also be enabled - enabled: false - labels: - annotations: - interval: 30s - # scrapeTimeout: 20s +## @section KeyDB common configuration parameters +## https://github.com/bitnami/containers/tree/main/bitnami/keydb#configuration +## -# Redis exporter -exporter: +## @param architecture KeyDB architecture. Allowed values: `standalone` or `replication` +## ref: https://docs.keydb.dev/docs/replication +## ref: https://docs.keydb.dev/docs/active-rep +## ref: https://docs.keydb.dev/docs/multi-master +## +architecture: replication +## KeyDB Authentication parameters +## ref: https://github.com/bitnami/containers/tree/main/bitnami/keydb#setting-the-server-password-on-first-run +## +auth: + ## @param auth.enabled Enable password authentication + ## + enabled: true + ## @param auth.password KeyDB password + ## Defaults to a random 10-character alphanumeric string if not set + ## + password: "2Z2LjbKyhS9ClRJH6IAHGnIHSS07Ws8O4VfSY4TN100=" + ## @param auth.existingSecret The name of an existing secret with KeyDB credentials + ## NOTE: When it's set, the previous `auth.password` parameter is ignored + ## + existingSecret: "" + ## @param auth.existingSecretPasswordKey Password key to be retrieved from existing secret + ## NOTE: ignored unless `auth.existingSecret` parameter is set + ## + existingSecretPasswordKey: "" + ## @param auth.usePasswordFiles Mount credentials as files instead of using an environment variable + ## + usePasswordFiles: true +## TLS configuration +## +tls: + ## @param tls.enabled Enable TLS communications + ## enabled: false - imageRepository: oliver006/redis_exporter - imageTag: v1.48.0-alpine - pullPolicy: IfNotPresent - - # Prometheus port & scrape path - port: 9121 - portName: redis-exporter - scrapePath: /metrics + ## @param tls.autoGenerated.enabled Enable automatic generation of certificates for TLS + ## @param tls.autoGenerated.engine Mechanism to generate the certificates (allowed values: helm, cert-manager) + autoGenerated: + enabled: true + engine: helm + ## @param tls.autoGenerated.certManager.existingIssuer The name of an existing Issuer to use for generating the certificates (only for `cert-manager` engine) + ## @param tls.autoGenerated.certManager.existingIssuerKind Existing Issuer kind, defaults to Issuer (only for `cert-manager` engine) + ## @param tls.autoGenerated.certManager.keyAlgorithm Key algorithm for the certificates (only for `cert-manager` engine) + ## @param tls.autoGenerated.certManager.keySize Key size for the certificates (only for `cert-manager` engine) + ## @param tls.autoGenerated.certManager.duration Duration for the certificates (only for `cert-manager` engine) + ## @param tls.autoGenerated.certManager.renewBefore Renewal period for the certificates (only for `cert-manager` engine) + certManager: + existingIssuer: "" + existingIssuerKind: "" + keySize: 2048 + keyAlgorithm: RSA + duration: 2160h + renewBefore: 360h + ## @param tls.ca CA certificate for TLS. Ignored if `tls.existingCASecret` is set + ## @param tls.existingCASecret The name of an existing Secret containing the CA certificate for TLS + ## @param tls.master.cert TLS certificate for KeyDB master nodes. Ignored if `tls.master.existingSecret` is set + ## @param tls.master.key TLS key for KeyDB master nodes. Ignored if `tls.master.existingSecret` is set + ## @param tls.master.existingSecret The name of an existing Secret containing the KeyDB master nodes certificates for TLS + ## @param tls.replica.cert TLS certificate for KeyDB replica nodes. Ignored if `tls.replica.existingSecret` is set + ## @param tls.replica.key TLS key for KeyDB replica nodes. Ignored if `tls.replica.existingSecret` is set + ## @param tls.replica.existingSecret The name of an existing Secret containing the KeyDB replica nodes certificates for TLS + ## + ca: "" + existingCASecret: "" + master: + cert: "" + key: "" + existingSecret: "" + replica: + cert: "" + key: "" + existingSecret: "" +## @param commonConfiguration [string] Common configuration to be added to both master and replica nodes +## ref: https://docs.keydb.dev/docs/config-file +## +commonConfiguration: "" - # Liveness Probe +## @section KeyDB Master Configuration Parameters +## +master: + ## @param master.replicaCount Number of KeyDB master replicas to deploy + ## + replicaCount: 1 + ## @param master.containerPorts.keydb Container port to open on KeyDB master nodes + ## + containerPorts: + keydb: 6379 + ## @param master.extraContainerPorts Optionally specify extra list of additional ports for KeyDB master containers + ## e.g: + ## extraContainerPorts: + ## - name: myservice + ## containerPort: 9090 + ## + extraContainerPorts: [] + ## Configure extra options for KeyDB master containers' liveness and readiness probes + ## ref: https://kubernetes.io/docs/tasks/configure-pod-container/configure-liveness-readiness-probes/#configure-probes + ## @param master.livenessProbe.enabled Enable livenessProbe on KeyDB master containers + ## @param master.livenessProbe.initialDelaySeconds Initial delay seconds for livenessProbe + ## @param master.livenessProbe.periodSeconds Period seconds for livenessProbe + ## @param master.livenessProbe.timeoutSeconds Timeout seconds for livenessProbe + ## @param master.livenessProbe.failureThreshold Failure threshold for livenessProbe + ## @param master.livenessProbe.successThreshold Success threshold for livenessProbe + ## livenessProbe: - httpGet: - path: /health - port: redis-exporter - - # Readiness Probe + enabled: true + initialDelaySeconds: 20 + periodSeconds: 5 + timeoutSeconds: 5 + successThreshold: 1 + failureThreshold: 5 + ## @param master.readinessProbe.enabled Enable readinessProbe on KeyDB master containers + ## @param master.readinessProbe.initialDelaySeconds Initial delay seconds for readinessProbe + ## @param master.readinessProbe.periodSeconds Period seconds for readinessProbe + ## @param master.readinessProbe.timeoutSeconds Timeout seconds for readinessProbe + ## @param master.readinessProbe.failureThreshold Failure threshold for readinessProbe + ## @param master.readinessProbe.successThreshold Success threshold for readinessProbe + ## readinessProbe: - httpGet: - path: /health - port: redis-exporter + enabled: true + initialDelaySeconds: 20 + periodSeconds: 5 + timeoutSeconds: 1 + successThreshold: 1 + failureThreshold: 5 + ## @param master.startupProbe.enabled Enable startupProbe on KeyDB master containers + ## @param master.startupProbe.initialDelaySeconds Initial delay seconds for startupProbe + ## @param master.startupProbe.periodSeconds Period seconds for startupProbe + ## @param master.startupProbe.timeoutSeconds Timeout seconds for startupProbe + ## @param master.startupProbe.failureThreshold Failure threshold for startupProbe + ## @param master.startupProbe.successThreshold Success threshold for startupProbe + ## + startupProbe: + enabled: false + initialDelaySeconds: 20 + periodSeconds: 5 + timeoutSeconds: 5 + successThreshold: 1 + failureThreshold: 5 + ## @param master.customLivenessProbe Custom livenessProbe that overrides the default one + ## + customLivenessProbe: {} + ## @param master.customReadinessProbe Custom readinessProbe that overrides the default one + ## + customReadinessProbe: {} + ## @param master.customStartupProbe Custom startupProbe that overrides the default one + ## + customStartupProbe: {} + ## KeyDB master resource requests and limits + ## ref: http://kubernetes.io/docs/concepts/configuration/manage-compute-resources-container/ + ## @param master.resourcesPreset Set KeyDB master container resources according to one common preset (allowed values: none, nano, small, medium, large, xlarge, 2xlarge). This is ignored if resources is set (resources is recommended for production). + ## More information: https://github.com/bitnami/charts/blob/main/bitnami/common/templates/_resources.tpl#L15 + ## + resourcesPreset: "nano" + ## @param master.resources Set KeyDB master container requests and limits for different resources like CPU or memory (essential for production workloads) + ## Example: + ## resources: + ## requests: + ## cpu: 2 + ## memory: 512Mi + ## limits: + ## cpu: 3 + ## memory: 1024Mi + ## + resources: {} + ## Configure Pods Security Context + ## ref: https://kubernetes.io/docs/tasks/configure-pod-container/security-context/#set-the-security-context-for-a-pod + ## @param master.podSecurityContext.enabled Enable KeyDB master pods' Security Context + ## @param master.podSecurityContext.fsGroupChangePolicy Set filesystem group change policy for KeyDB master pods + ## @param master.podSecurityContext.sysctls Set kernel settings using the sysctl interface for KeyDB master pods + ## @param master.podSecurityContext.supplementalGroups Set filesystem extra groups for KeyDB master pods + ## @param master.podSecurityContext.fsGroup Set fsGroup in KeyDB master pods' Security Context + ## + podSecurityContext: + enabled: true + fsGroupChangePolicy: Always + sysctls: [] + supplementalGroups: [] + fsGroup: 1001 + ## Configure Container Security Context + ## ref: https://kubernetes.io/docs/tasks/configure-pod-container/security-context/#set-the-security-context-for-a-container + ## @param master.containerSecurityContext.enabled Enabled KeyDB master container' Security Context + ## @param master.containerSecurityContext.seLinuxOptions [object,nullable] Set SELinux options in KeyDB master container + ## @param master.containerSecurityContext.runAsUser Set runAsUser in KeyDB master container' Security Context + ## @param master.containerSecurityContext.runAsGroup Set runAsGroup in KeyDB master container' Security Context + ## @param master.containerSecurityContext.runAsNonRoot Set runAsNonRoot in KeyDB master container' Security Context + ## @param master.containerSecurityContext.readOnlyRootFilesystem Set readOnlyRootFilesystem in KeyDB master container' Security Context + ## @param master.containerSecurityContext.privileged Set privileged in KeyDB master container' Security Context + ## @param master.containerSecurityContext.allowPrivilegeEscalation Set allowPrivilegeEscalation in KeyDB master container' Security Context + ## @param master.containerSecurityContext.capabilities.drop List of capabilities to be dropped in KeyDB master container + ## @param master.containerSecurityContext.seccompProfile.type Set seccomp profile in KeyDB master container + ## + containerSecurityContext: + enabled: true + seLinuxOptions: {} + runAsUser: 1001 + runAsGroup: 1001 + runAsNonRoot: true + readOnlyRootFilesystem: true + privileged: false + allowPrivilegeEscalation: false + capabilities: + drop: ["ALL"] + seccompProfile: + type: "RuntimeDefault" + ## @param master.configuration Exclusive configuration for KeyDB master nodes (appended to common one) + ## ref: https://docs.keydb.dev/docs/config-file + ## + configuration: "" + ## @param master.existingConfigmap The name of an existing ConfigMap with your custom configuration for KeyDB master + ## + existingConfigmap: "" + ## @param master.disableCommands Array with KeyDB commands to disable on master nodes + ## Commands will be completely disabled by renaming each to an empty string. + ## ref: https://docs.keydb.dev/docs/commands + ## + disableCommands: + - FLUSHDB + - FLUSHALL + ## @param master.command Override default KeyDB master container command (useful when using custom images) + ## + command: [] + ## @param master.args Override default KeyDB master container args (useful when using custom images) + ## + args: [] + ## @param master.automountServiceAccountToken Mount Service Account token in KeyDB master pods + ## + automountServiceAccountToken: false + ## @param master.hostAliases KeyDB master pods host aliases + ## https://kubernetes.io/docs/concepts/services-networking/add-entries-to-pod-etc-hosts-with-host-aliases/ + ## + hostAliases: [] + ## @param master.statefulsetAnnotations Annotations for KeyDB master statefulset + ## ref: https://kubernetes.io/docs/concepts/overview/working-with-objects/annotations/ + ## + statefulsetAnnotations: {} + ## @param master.podLabels Extra labels for KeyDB master pods + ## ref: https://kubernetes.io/docs/concepts/overview/working-with-objects/labels/ + ## + podLabels: {} + ## @param master.podAnnotations Annotations for KeyDB master pods + ## ref: https://kubernetes.io/docs/concepts/overview/working-with-objects/annotations/ + ## + podAnnotations: {} + ## @param master.podAffinityPreset Pod affinity preset. Ignored if `affinity` is set. Allowed values: `soft` or `hard` + ## ref: https://kubernetes.io/docs/concepts/scheduling-eviction/assign-pod-node/#inter-pod-affinity-and-anti-affinity + ## + podAffinityPreset: "" + ## @param master.podAntiAffinityPreset Pod anti-affinity preset. Ignored if `affinity` is set. Allowed values: `soft` or `hard` + ## ref: https://kubernetes.io/docs/concepts/scheduling-eviction/assign-pod-node/#inter-pod-affinity-and-anti-affinity + ## + podAntiAffinityPreset: soft + ## Node affinity preset + ## ref: https://kubernetes.io/docs/concepts/scheduling-eviction/assign-pod-node/#node-affinity + ## + nodeAffinityPreset: + ## @param master.nodeAffinityPreset.type Node affinity preset type. Ignored if `affinity` is set. Allowed values: `soft` or `hard` + ## + type: "" + ## @param master.nodeAffinityPreset.key Node label key to match. Ignored if `affinity` is set + ## + key: "" + ## @param master.nodeAffinityPreset.values Node label values to match. Ignored if `affinity` is set + ## E.g. + ## values: + ## - e2e-az1 + ## - e2e-az2 + ## + values: [] + ## @param master.affinity Affinity for KeyDB master pods assignment + ## 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 + ## + affinity: {} + ## @param master.nodeSelector Node labels for KeyDB master pods assignment + ## ref: https://kubernetes.io/docs/concepts/scheduling-eviction/assign-pod-node/ + ## + nodeSelector: {} + ## @param master.tolerations Tolerations for KeyDB master pods assignment + ## ref: https://kubernetes.io/docs/concepts/configuration/taint-and-toleration/ + ## + tolerations: [] + ## @param master.updateStrategy.type KeyDB master strategy type + ## ref: https://kubernetes.io/docs/concepts/workloads/controllers/deployment/#strategy + ## ref: https://kubernetes.io/docs/concepts/workloads/controllers/statefulset/#update-strategies + ## + updateStrategy: + ## Can be set to RollingUpdate or OnDelete + ## + type: RollingUpdate + ## @param master.priorityClassName KeyDB master pods' priorityClassName + ## + priorityClassName: "" + ## @param master.topologySpreadConstraints Topology Spread Constraints for KeyDB master pod assignment spread across your cluster among failure-domains + ## Ref: https://kubernetes.io/docs/concepts/workloads/pods/pod-topology-spread-constraints/#spread-constraints-for-pods + ## + topologySpreadConstraints: [] + ## @param master.schedulerName Name of the k8s scheduler (other than default) for KeyDB master pods + ## ref: https://kubernetes.io/docs/tasks/administer-cluster/configure-multiple-schedulers/ + ## + schedulerName: "" + ## @param master.terminationGracePeriodSeconds Seconds KeyDB master pods need to terminate gracefully + ## ref: https://kubernetes.io/docs/concepts/workloads/pods/pod/#termination-of-pods + ## + terminationGracePeriodSeconds: "" + ## @param master.lifecycleHooks for KeyDB master containers to automate configuration before or after startup + ## + lifecycleHooks: {} + ## @param master.extraEnvVars Array with extra environment variables to add to KeyDB master containers + ## e.g: + ## extraEnvVars: + ## - name: FOO + ## value: "bar" + ## + extraEnvVars: [] + ## @param master.extraEnvVarsCM Name of existing ConfigMap containing extra env vars for KeyDB master containers + ## + extraEnvVarsCM: "" + ## @param master.extraEnvVarsSecret Name of existing Secret containing extra env vars for KeyDB master containers + ## + extraEnvVarsSecret: "" + ## @param master.extraVolumes Optionally specify extra list of additional volumes for the KeyDB master pods + ## + extraVolumes: [] + ## @param master.extraVolumeMounts Optionally specify extra list of additional volumeMounts for the KeyDB master containers + ## + extraVolumeMounts: [] + ## @param master.sidecars Add additional sidecar containers to the KeyDB master pods + ## e.g: + ## sidecars: + ## - name: your-image-name + ## image: your-image + ## imagePullPolicy: Always + ## ports: + ## - name: portname + ## containerPort: 1234 + ## + sidecars: [] + ## @param master.initContainers Add additional init containers to the KeyDB master pods + ## ref: https://kubernetes.io/docs/concepts/workloads/pods/init-containers/ + ## e.g: + ## initContainers: + ## - name: your-image-name + ## image: your-image + ## imagePullPolicy: Always + ## command: ['sh', '-c', 'echo "hello world"'] + ## + initContainers: [] + ## Pod Disruption Budget configuration + ## ref: https://kubernetes.io/docs/tasks/run-application/configure-pdb + ## @param master.pdb.create Enable/disable a Pod Disruption Budget creation for KeyDB master pods + ## @param master.pdb.minAvailable Minimum number/percentage of KeyDB master pods that should remain scheduled + ## @param master.pdb.maxUnavailable Maximum number/percentage of KeyDB master pods that may be made unavailable. Defaults to `1` if both `pdb.minAvailable` and `pdb.maxUnavailable` are empty. + ## + pdb: + create: true + minAvailable: "" + maxUnavailable: "" + ## Autoscaling configuration + ## ref: https://kubernetes.io/docs/concepts/workloads/autoscaling/ + ## + autoscaling: + ## @param master.autoscaling.vpa.enabled Enable VPA for KeyDB master pods + ## @param master.autoscaling.vpa.annotations Annotations for VPA resource + ## @param master.autoscaling.vpa.controlledResources VPA List of resources that the vertical pod autoscaler can control. Defaults to cpu and memory + ## @param master.autoscaling.vpa.maxAllowed VPA Max allowed resources for the pod + ## @param master.autoscaling.vpa.minAllowed VPA Min allowed resources for the pod + ## + vpa: + enabled: false + annotations: {} + controlledResources: [] + maxAllowed: {} + minAllowed: {} + ## @param master.autoscaling.vpa.updatePolicy.updateMode Autoscaling update policy + ## Specifies whether recommended updates are applied when a Pod is started and whether recommended updates are applied during the life of a Pod + ## Possible values are "Off", "Initial", "Recreate", and "Auto". + ## + updatePolicy: + updateMode: Auto + ## @section KeyDB Master Persistence Parameters + ## ref: https://kubernetes.io/docs/concepts/storage/persistent-volumes + ## + persistence: + ## @param master.persistence.enabled Enable persistence using Persistent Volume Claims + ## + enabled: true + ## @param master.persistence.mountPath Path to mount the data volume at on KeyDB master containers + ## + mountPath: /bitnami/keydb/data + ## @param master.persistence.subPath The subdirectory of the volume to mount on KeyDB master containers + ## + subPath: "" + ## @param master.persistence.medium Provide a medium for `emptyDir` volumes + ## + medium: "" + ## @param master.persistence.sizeLimit Set this to enable a size limit for `emptyDir` volumes + ## + sizeLimit: "" + ## @param master.persistence.storageClass Storage class of backing PVC + ## If defined, storageClassName: + ## If set to "-", storageClassName: "", which disables dynamic provisioning + ## If undefined (the default) or set to null, no storageClassName spec is + ## set, choosing the default provisioner. (gp2 on AWS, standard on + ## GKE, AWS & OpenStack) + ## + storageClass: "" + ## @param master.persistence.annotations Additional Persistent Volume Claim annotations + ## + annotations: {} + ## @param master.persistence.accessModes Persistent Volume Access Modes + ## + accessModes: + - ReadWriteOnce + ## @param master.persistence.size Size of data volume + ## + size: 8Gi + ## @param master.persistence.selector Selector to match an existing Persistent Volume for WordPress data PVC + ## If set, the PVC can't have a PV dynamically provisioned for it + ## E.g. + ## selector: + ## matchLabels: + ## app: my-app + ## + selector: {} + ## @param master.persistence.dataSource Custom PVC data source + ## + dataSource: {} + ## @param master.persistence.existingClaim The name of an existing PVC to use for persistence (only if master.replicaCount=1) + ## + existingClaim: "" + ## persistentVolumeClaimRetentionPolicy + ## ref: https://kubernetes.io/docs/concepts/workloads/controllers/statefulset/#persistentvolumeclaim-retention + ## @param master.persistentVolumeClaimRetentionPolicy.enabled Controls if and how PVCs are deleted during the lifecycle of a StatefulSet + ## @param master.persistentVolumeClaimRetentionPolicy.whenScaled Volume retention behavior when the replica count of the StatefulSet is reduced + ## @param master.persistentVolumeClaimRetentionPolicy.whenDeleted Volume retention behavior that applies when the StatefulSet is deleted + ## + persistentVolumeClaimRetentionPolicy: + enabled: false + whenScaled: Retain + whenDeleted: Retain + ## @section KeyDB Master Traffic Exposure Parameters + ## KeyDB Master service parameters + ## + service: + ## @param master.service.type KeyDB master service type + ## + type: ClusterIP + ## @param master.service.ports.keydb KeyDB master service port + ## + ports: + keydb: 6379 + ## Node ports to expose + ## @param master.service.nodePorts.keydb Node port for KeyDB master + ## NOTE: choose port between <30000-32767> + ## + nodePorts: + keydb: "" + ## @param master.service.clusterIP KeyDB master service Cluster IP + ## e.g.: + ## clusterIP: None + ## + clusterIP: "" + ## @param master.service.loadBalancerIP KeyDB master service Load Balancer IP + ## ref: https://kubernetes.io/docs/concepts/services-networking/service/#type-loadbalancer + ## + loadBalancerIP: "" + ## @param master.service.loadBalancerSourceRanges KeyDB master service Load Balancer sources + ## ref: https://kubernetes.io/docs/tasks/access-application-cluster/configure-cloud-provider-firewall/#restrict-access-for-loadbalancer-service + ## e.g: + ## loadBalancerSourceRanges: + ## - 10.10.10.0/24 + ## + loadBalancerSourceRanges: [] + ## @param master.service.externalTrafficPolicy KeyDB master service external traffic policy + ## ref http://kubernetes.io/docs/tasks/access-application-cluster/create-external-load-balancer/#preserving-the-client-source-ip + ## + externalTrafficPolicy: Cluster + ## @param master.service.annotations Additional custom annotations for KeyDB master service + ## + annotations: {} + ## @param master.service.extraPorts Extra ports to expose in KeyDB master service (normally used with the `sidecars` value) + ## + extraPorts: [] + ## @param master.service.sessionAffinity Control where client requests go, to the same pod or round-robin + ## Values: ClientIP or None + ## ref: https://kubernetes.io/docs/concepts/services-networking/service/ + ## + sessionAffinity: None + ## @param master.service.sessionAffinityConfig Additional settings for the sessionAffinity + ## sessionAffinityConfig: + ## clientIP: + ## timeoutSeconds: 300 + ## + sessionAffinityConfig: {} + ## Headless service properties + ## + headless: + ## @param master.service.headless.annotations Annotations for the headless service. + ## + annotations: {} + ## KeyDB Master Network Policies + ## Ref: https://kubernetes.io/docs/concepts/services-networking/network-policies/ + ## + networkPolicy: + ## @param master.networkPolicy.enabled Specifies whether a NetworkPolicy should be created for KeyDB master + ## + enabled: true + ## @param master.networkPolicy.allowExternal Don't require server label for connections + ## The Policy model to apply. When set to false, only pods with the correct + ## server label will have network access to the ports server is listening + ## on. When true, server will accept connections from any source + ## (with the correct destination port). + ## + allowExternal: true + ## @param master.networkPolicy.allowExternalEgress Allow the pod to access any range of port and all destinations. + ## + allowExternalEgress: true + ## @param master.networkPolicy.addExternalClientAccess Allow access from pods with client label set to "true". Ignored if `networkPolicy.allowExternal` is true. + ## + addExternalClientAccess: true + ## @param master.networkPolicy.extraIngress [array] Add extra ingress rules to the NetworkPolicy + ## e.g: + ## extraIngress: + ## - ports: + ## - port: 1234 + ## from: + ## - podSelector: + ## - matchLabels: + ## - role: frontend + ## - podSelector: + ## - matchExpressions: + ## - key: role + ## operator: In + ## values: + ## - frontend + extraIngress: [] + ## @param master.networkPolicy.extraEgress [array] Add extra ingress rules to the NetworkPolicy (ignored if allowExternalEgress=true) + ## e.g: + ## extraEgress: + ## - ports: + ## - port: 1234 + ## to: + ## - podSelector: + ## - matchLabels: + ## - role: frontend + ## - podSelector: + ## - matchExpressions: + ## - key: role + ## operator: In + ## values: + ## - frontend + ## + extraEgress: [] + ## @param master.networkPolicy.ingressPodMatchLabels [object] Labels to match to allow traffic from other pods. Ignored if `networkPolicy.allowExternal` is true. + ## e.g: + ## ingressPodMatchLabels: + ## my-client: "true" + # + ingressPodMatchLabels: {} + ## @param master.networkPolicy.ingressNSMatchLabels [object] Labels to match to allow traffic from other namespaces. Ignored if `networkPolicy.allowExternal` is true. + ## @param master.networkPolicy.ingressNSPodMatchLabels [object] Pod labels to match to allow traffic from other namespaces. Ignored if `networkPolicy.allowExternal` is true. + ## + ingressNSMatchLabels: {} + ingressNSPodMatchLabels: {} - # Startup Probe +## @section KeyDB Replicas Configuration Parameters +## +replica: + ## @param replica.replicaCount Number of KeyDB replicas to deploy + ## + replicaCount: 1 + ## @param replica.containerPorts.keydb Container port to open on KeyDB replicas nodes + ## + containerPorts: + keydb: 6379 + ## @param replica.extraContainerPorts Optionally specify extra list of additional ports for KeyDB replicas containers + ## e.g: + ## extraContainerPorts: + ## - name: myservice + ## containerPort: 9090 + ## + extraContainerPorts: [] + ## Configure extra options for KeyDB replicas containers' liveness and readiness probes + ## ref: https://kubernetes.io/docs/tasks/configure-pod-container/configure-liveness-readiness-probes/#configure-probes + ## @param replica.livenessProbe.enabled Enable livenessProbe on KeyDB replicas containers + ## @param replica.livenessProbe.initialDelaySeconds Initial delay seconds for livenessProbe + ## @param replica.livenessProbe.periodSeconds Period seconds for livenessProbe + ## @param replica.livenessProbe.timeoutSeconds Timeout seconds for livenessProbe + ## @param replica.livenessProbe.failureThreshold Failure threshold for livenessProbe + ## @param replica.livenessProbe.successThreshold Success threshold for livenessProbe + ## + livenessProbe: + enabled: true + initialDelaySeconds: 20 + periodSeconds: 5 + timeoutSeconds: 5 + successThreshold: 1 + failureThreshold: 5 + ## @param replica.readinessProbe.enabled Enable readinessProbe on KeyDB replicas containers + ## @param replica.readinessProbe.initialDelaySeconds Initial delay seconds for readinessProbe + ## @param replica.readinessProbe.periodSeconds Period seconds for readinessProbe + ## @param replica.readinessProbe.timeoutSeconds Timeout seconds for readinessProbe + ## @param replica.readinessProbe.failureThreshold Failure threshold for readinessProbe + ## @param replica.readinessProbe.successThreshold Success threshold for readinessProbe + ## + readinessProbe: + enabled: true + initialDelaySeconds: 20 + periodSeconds: 5 + timeoutSeconds: 1 + successThreshold: 1 + failureThreshold: 5 + ## @param replica.startupProbe.enabled Enable startupProbe on KeyDB replicas containers + ## @param replica.startupProbe.initialDelaySeconds Initial delay seconds for startupProbe + ## @param replica.startupProbe.periodSeconds Period seconds for startupProbe + ## @param replica.startupProbe.timeoutSeconds Timeout seconds for startupProbe + ## @param replica.startupProbe.failureThreshold Failure threshold for startupProbe + ## @param replica.startupProbe.successThreshold Success threshold for startupProbe + ## startupProbe: - httpGet: - path: /health - port: redis-exporter - failureThreshold: 24 + enabled: false + initialDelaySeconds: 20 periodSeconds: 5 + timeoutSeconds: 5 + successThreshold: 1 + failureThreshold: 5 + ## @param replica.customLivenessProbe Custom livenessProbe that overrides the default one + ## + customLivenessProbe: {} + ## @param replica.customReadinessProbe Custom readinessProbe that overrides the default one + ## + customReadinessProbe: {} + ## @param replica.customStartupProbe Custom startupProbe that overrides the default one + ## + customStartupProbe: {} + ## KeyDB replicas resource requests and limits + ## ref: http://kubernetes.io/docs/concepts/configuration/manage-compute-resources-container/ + ## @param replica.resourcesPreset Set KeyDB replicas container resources according to one common preset (allowed values: none, nano, small, medium, large, xlarge, 2xlarge). This is ignored if resources is set (resources is recommended for production). + ## More information: https://github.com/bitnami/charts/blob/main/bitnami/common/templates/_resources.tpl#L15 + ## + resourcesPreset: "nano" + ## @param replica.resources Set KeyDB replicas container requests and limits for different resources like CPU or memory (essential for production workloads) + ## Example: + ## resources: + ## requests: + ## cpu: 2 + ## memory: 512Mi + ## limits: + ## cpu: 3 + ## memory: 1024Mi + ## + resources: {} + ## Configure Pods Security Context + ## ref: https://kubernetes.io/docs/tasks/configure-pod-container/security-context/#set-the-security-context-for-a-pod + ## @param replica.podSecurityContext.enabled Enable KeyDB replicas pods' Security Context + ## @param replica.podSecurityContext.fsGroupChangePolicy Set filesystem group change policy for KeyDB replicas pods + ## @param replica.podSecurityContext.sysctls Set kernel settings using the sysctl interface for KeyDB replicas pods + ## @param replica.podSecurityContext.supplementalGroups Set filesystem extra groups for KeyDB replicas pods + ## @param replica.podSecurityContext.fsGroup Set fsGroup in KeyDB replicas pods' Security Context + ## + podSecurityContext: + enabled: true + fsGroupChangePolicy: Always + sysctls: [] + supplementalGroups: [] + fsGroup: 1001 + ## Configure Container Security Context + ## ref: https://kubernetes.io/docs/tasks/configure-pod-container/security-context/#set-the-security-context-for-a-container + ## @param replica.containerSecurityContext.enabled Enabled KeyDB replicas container' Security Context + ## @param replica.containerSecurityContext.seLinuxOptions [object,nullable] Set SELinux options in KeyDB replicas container + ## @param replica.containerSecurityContext.runAsUser Set runAsUser in KeyDB replicas container' Security Context + ## @param replica.containerSecurityContext.runAsGroup Set runAsGroup in KeyDB replicas container' Security Context + ## @param replica.containerSecurityContext.runAsNonRoot Set runAsNonRoot in KeyDB replicas container' Security Context + ## @param replica.containerSecurityContext.readOnlyRootFilesystem Set readOnlyRootFilesystem in KeyDB replicas container' Security Context + ## @param replica.containerSecurityContext.privileged Set privileged in KeyDB replicas container' Security Context + ## @param replica.containerSecurityContext.allowPrivilegeEscalation Set allowPrivilegeEscalation in KeyDB replicas container' Security Context + ## @param replica.containerSecurityContext.capabilities.drop List of capabilities to be dropped in KeyDB replicas container + ## @param replica.containerSecurityContext.seccompProfile.type Set seccomp profile in KeyDB replicas container + ## + containerSecurityContext: + enabled: true + seLinuxOptions: {} + runAsUser: 1001 + runAsGroup: 1001 + runAsNonRoot: true + readOnlyRootFilesystem: true + privileged: false + allowPrivilegeEscalation: false + capabilities: + drop: ["ALL"] + seccompProfile: + type: "RuntimeDefault" + ## @param replica.activeReplica Configure replica as an active replica + ## + activeReplica: false + ## @param replica.configuration Exclusive configuration for KeyDB replicas nodes (appended to common one) + ## ref: https://docs.keydb.dev/docs/config-file + ## + configuration: "" + ## @param replica.existingConfigmap The name of an existing ConfigMap with your custom configuration for KeyDB replicas + ## + existingConfigmap: "" + ## @param replica.disableCommands Array with KeyDB commands to disable on master nodes + ## Commands will be completely disabled by renaming each to an empty string. + ## ref: https://docs.keydb.dev/docs/commands + ## + disableCommands: + - FLUSHDB + - FLUSHALL + ## @param replica.command Override default KeyDB replicas container command (useful when using custom images) + ## + command: [] + ## @param replica.args Override default KeyDB replicas container args (useful when using custom images) + ## + args: [] + ## @param replica.automountServiceAccountToken Mount Service Account token in KeyDB replicas pods + ## + automountServiceAccountToken: false + ## @param replica.hostAliases KeyDB replicas pods host aliases + ## https://kubernetes.io/docs/concepts/services-networking/add-entries-to-pod-etc-hosts-with-host-aliases/ + ## + hostAliases: [] + ## @param replica.statefulsetAnnotations Annotations for KeyDB replicas statefulset + ## ref: https://kubernetes.io/docs/concepts/overview/working-with-objects/annotations/ + ## + statefulsetAnnotations: {} + ## @param replica.podLabels Extra labels for KeyDB replicas pods + ## ref: https://kubernetes.io/docs/concepts/overview/working-with-objects/labels/ + ## + podLabels: {} + ## @param replica.podAnnotations Annotations for KeyDB replicas pods + ## ref: https://kubernetes.io/docs/concepts/overview/working-with-objects/annotations/ + ## + podAnnotations: {} + ## @param replica.podAffinityPreset Pod affinity preset. Ignored if `affinity` is set. Allowed values: `soft` or `hard` + ## ref: https://kubernetes.io/docs/concepts/scheduling-eviction/assign-pod-node/#inter-pod-affinity-and-anti-affinity + ## + podAffinityPreset: "" + ## @param replica.podAntiAffinityPreset Pod anti-affinity preset. Ignored if `affinity` is set. Allowed values: `soft` or `hard` + ## ref: https://kubernetes.io/docs/concepts/scheduling-eviction/assign-pod-node/#inter-pod-affinity-and-anti-affinity + ## + podAntiAffinityPreset: soft + ## Node affinity preset + ## ref: https://kubernetes.io/docs/concepts/scheduling-eviction/assign-pod-node/#node-affinity + ## + nodeAffinityPreset: + ## @param replica.nodeAffinityPreset.type Node affinity preset type. Ignored if `affinity` is set. Allowed values: `soft` or `hard` + ## + type: "" + ## @param replica.nodeAffinityPreset.key Node label key to match. Ignored if `affinity` is set + ## + key: "" + ## @param replica.nodeAffinityPreset.values Node label values to match. Ignored if `affinity` is set + ## E.g. + ## values: + ## - e2e-az1 + ## - e2e-az2 + ## + values: [] + ## @param replica.affinity Affinity for KeyDB replicas pods assignment + ## 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 + ## + affinity: {} + ## @param replica.nodeSelector Node labels for KeyDB replicas pods assignment + ## ref: https://kubernetes.io/docs/concepts/scheduling-eviction/assign-pod-node/ + ## + nodeSelector: {} + ## @param replica.tolerations Tolerations for KeyDB replicas pods assignment + ## ref: https://kubernetes.io/docs/concepts/configuration/taint-and-toleration/ + ## + tolerations: [] + ## @param replica.updateStrategy.type KeyDB replicas strategy type + ## ref: https://kubernetes.io/docs/concepts/workloads/controllers/deployment/#strategy + ## ref: https://kubernetes.io/docs/concepts/workloads/controllers/statefulset/#update-strategies + ## + updateStrategy: + ## Can be set to RollingUpdate or OnDelete + ## + type: RollingUpdate + ## @param replica.priorityClassName KeyDB replicas pods' priorityClassName + ## + priorityClassName: "" + ## @param replica.topologySpreadConstraints Topology Spread Constraints for KeyDB replicas pod assignment spread across your cluster among failure-domains + ## Ref: https://kubernetes.io/docs/concepts/workloads/pods/pod-topology-spread-constraints/#spread-constraints-for-pods + ## + topologySpreadConstraints: [] + ## @param replica.schedulerName Name of the k8s scheduler (other than default) for KeyDB replicas pods + ## ref: https://kubernetes.io/docs/tasks/administer-cluster/configure-multiple-schedulers/ + ## + schedulerName: "" + ## @param replica.terminationGracePeriodSeconds Seconds KeyDB replicas pods need to terminate gracefully + ## ref: https://kubernetes.io/docs/concepts/workloads/pods/pod/#termination-of-pods + ## + terminationGracePeriodSeconds: "" + ## @param replica.lifecycleHooks for KeyDB replicas containers to automate configuration before or after startup + ## + lifecycleHooks: {} + ## @param replica.extraEnvVars Array with extra environment variables to add to KeyDB replicas containers + ## e.g: + ## extraEnvVars: + ## - name: FOO + ## value: "bar" + ## + extraEnvVars: [] + ## @param replica.extraEnvVarsCM Name of existing ConfigMap containing extra env vars for KeyDB replicas containers + ## + extraEnvVarsCM: "" + ## @param replica.extraEnvVarsSecret Name of existing Secret containing extra env vars for KeyDB replicas containers + ## + extraEnvVarsSecret: "" + ## @param replica.extraVolumes Optionally specify extra list of additional volumes for the KeyDB replicas pods + ## + extraVolumes: [] + ## @param replica.extraVolumeMounts Optionally specify extra list of additional volumeMounts for the KeyDB replicas containers + ## + extraVolumeMounts: [] + ## @param replica.sidecars Add additional sidecar containers to the KeyDB replicas pods + ## e.g: + ## sidecars: + ## - name: your-image-name + ## image: your-image + ## imagePullPolicy: Always + ## ports: + ## - name: portname + ## containerPort: 1234 + ## + sidecars: [] + ## @param replica.initContainers Add additional init containers to the KeyDB replicas pods + ## ref: https://kubernetes.io/docs/concepts/workloads/pods/init-containers/ + ## e.g: + ## initContainers: + ## - name: your-image-name + ## image: your-image + ## imagePullPolicy: Always + ## command: ['sh', '-c', 'echo "hello world"'] + ## + initContainers: [] + ## Pod Disruption Budget configuration + ## ref: https://kubernetes.io/docs/tasks/run-application/configure-pdb + ## @param replica.pdb.create Enable/disable a Pod Disruption Budget creation for KeyDB replicas pods + ## @param replica.pdb.minAvailable Minimum number/percentage of KeyDB replicas pods that should remain scheduled + ## @param replica.pdb.maxUnavailable Maximum number/percentage of KeyDB replicas pods that may be made unavailable. Defaults to `1` if both `pdb.minAvailable` and `pdb.maxUnavailable` are empty. + ## + pdb: + create: true + minAvailable: "" + maxUnavailable: "" + ## Autoscaling configuration + ## ref: https://kubernetes.io/docs/concepts/workloads/autoscaling/ + ## + autoscaling: + ## @param replica.autoscaling.vpa.enabled Enable VPA for KeyDB replicas pods + ## @param replica.autoscaling.vpa.annotations Annotations for VPA resource + ## @param replica.autoscaling.vpa.controlledResources VPA List of resources that the vertical pod autoscaler can control. Defaults to cpu and memory + ## @param replica.autoscaling.vpa.maxAllowed VPA Max allowed resources for the pod + ## @param replica.autoscaling.vpa.minAllowed VPA Min allowed resources for the pod + ## + vpa: + enabled: false + annotations: {} + controlledResources: [] + maxAllowed: {} + minAllowed: {} + ## @param replica.autoscaling.vpa.updatePolicy.updateMode Autoscaling update policy + ## Specifies whether recommended updates are applied when a Pod is started and whether recommended updates are applied during the life of a Pod + ## Possible values are "Off", "Initial", "Recreate", and "Auto". + ## + updatePolicy: + updateMode: Auto + ## @param replica.autoscaling.hpa.enabled Enable HPA for KeyDB Replicas pods + ## @param replica.autoscaling.hpa.minReplicas Minimum number of replicas + ## @param replica.autoscaling.hpa.maxReplicas Maximum number of replicas + ## @param replica.autoscaling.hpa.targetCPU Target CPU utilization percentage + ## @param replica.autoscaling.hpa.targetMemory Target Memory utilization percentage + ## + hpa: + enabled: false + minReplicas: "" + maxReplicas: "" + targetCPU: "" + targetMemory: "" + ## @section KeyDB Replicas Persistence Parameters + ## ref: https://kubernetes.io/docs/concepts/storage/persistent-volumes + ## + persistence: + ## @param replica.persistence.enabled Enable persistence using Persistent Volume Claims + ## + enabled: true + ## @param replica.persistence.mountPath Path to mount the data volume at on KeyDB replicas containers + ## + mountPath: /bitnami/keydb/data + ## @param replica.persistence.subPath The subdirectory of the volume to mount on KeyDB replicas containers + ## + subPath: "" + ## @param replica.persistence.medium Provide a medium for `emptyDir` volumes + ## + medium: "" + ## @param replica.persistence.sizeLimit Set this to enable a size limit for `emptyDir` volumes + ## + sizeLimit: "" + ## @param replica.persistence.storageClass Storage class of backing PVC + ## If defined, storageClassName: + ## If set to "-", storageClassName: "", which disables dynamic provisioning + ## If undefined (the default) or set to null, no storageClassName spec is + ## set, choosing the default provisioner. (gp2 on AWS, standard on + ## GKE, AWS & OpenStack) + ## + storageClass: "" + ## @param replica.persistence.annotations Additional Persistent Volume Claim annotations + ## + annotations: {} + ## @param replica.persistence.accessModes Persistent Volume Access Modes + ## + accessModes: + - ReadWriteOnce + ## @param replica.persistence.size Size of data volume + ## + size: 8Gi + ## @param replica.persistence.selector Selector to match an existing Persistent Volume for WordPress data PVC + ## If set, the PVC can't have a PV dynamically provisioned for it + ## E.g. + ## selector: + ## matchLabels: + ## app: my-app + ## + selector: {} + ## @param replica.persistence.dataSource Custom PVC data source + ## + dataSource: {} + ## @param replica.persistence.existingClaim The name of an existing PVC to use for persistence (only if replica.replicaCount=1) + ## + existingClaim: "" + ## persistentVolumeClaimRetentionPolicy + ## ref: https://kubernetes.io/docs/concepts/workloads/controllers/statefulset/#persistentvolumeclaim-retention + ## @param replica.persistentVolumeClaimRetentionPolicy.enabled Controls if and how PVCs are deleted during the lifecycle of a StatefulSet + ## @param replica.persistentVolumeClaimRetentionPolicy.whenScaled Volume retention behavior when the replica count of the StatefulSet is reduced + ## @param replica.persistentVolumeClaimRetentionPolicy.whenDeleted Volume retention behavior that applies when the StatefulSet is deleted + ## + persistentVolumeClaimRetentionPolicy: + enabled: false + whenScaled: Retain + whenDeleted: Retain + ## @section KeyDB Replicas Traffic Exposure Parameters + ## KeyDB Replicas service parameters + ## + service: + ## @param replica.service.type KeyDB replicas service type + ## + type: ClusterIP + ## @param replica.service.ports.keydb KeyDB replicas service port + ## + ports: + keydb: 6379 + ## Node ports to expose + ## @param replica.service.nodePorts.keydb Node port for KeyDB replicas + ## NOTE: choose port between <30000-32767> + ## + nodePorts: + keydb: "" + ## @param replica.service.clusterIP KeyDB replicas service Cluster IP + ## e.g.: + ## clusterIP: None + ## + clusterIP: "" + ## @param replica.service.loadBalancerIP KeyDB replicas service Load Balancer IP + ## ref: https://kubernetes.io/docs/concepts/services-networking/service/#type-loadbalancer + ## + loadBalancerIP: "" + ## @param replica.service.loadBalancerSourceRanges KeyDB replicas service Load Balancer sources + ## ref: https://kubernetes.io/docs/tasks/access-application-cluster/configure-cloud-provider-firewall/#restrict-access-for-loadbalancer-service + ## e.g: + ## loadBalancerSourceRanges: + ## - 10.10.10.0/24 + ## + loadBalancerSourceRanges: [] + ## @param replica.service.externalTrafficPolicy KeyDB replicas service external traffic policy + ## ref http://kubernetes.io/docs/tasks/access-application-cluster/create-external-load-balancer/#preserving-the-client-source-ip + ## + externalTrafficPolicy: Cluster + ## @param replica.service.annotations Additional custom annotations for KeyDB replicas service + ## + annotations: {} + ## @param replica.service.extraPorts Extra ports to expose in KeyDB replicas service (normally used with the `sidecars` value) + ## + extraPorts: [] + ## @param replica.service.sessionAffinity Control where client requests go, to the same pod or round-robin + ## Values: ClientIP or None + ## ref: https://kubernetes.io/docs/concepts/services-networking/service/ + ## + sessionAffinity: None + ## @param replica.service.sessionAffinityConfig Additional settings for the sessionAffinity + ## sessionAffinityConfig: + ## clientIP: + ## timeoutSeconds: 300 + ## + sessionAffinityConfig: {} + ## Headless service properties + ## + headless: + ## @param replica.service.headless.annotations Annotations for the headless service. + ## + annotations: {} + ## KeyDB Replicas Network Policies + ## Ref: https://kubernetes.io/docs/concepts/services-networking/network-policies/ + ## + networkPolicy: + ## @param replica.networkPolicy.enabled Specifies whether a NetworkPolicy should be created for KeyDB replicas + ## + enabled: true + ## @param replica.networkPolicy.allowExternal Don't require server label for connections + ## The Policy model to apply. When set to false, only pods with the correct + ## server label will have network access to the ports server is listening + ## on. When true, server will accept connections from any source + ## (with the correct destination port). + ## + allowExternal: true + ## @param replica.networkPolicy.allowExternalEgress Allow the pod to access any range of port and all destinations. + ## + allowExternalEgress: true + ## @param replica.networkPolicy.addExternalClientAccess Allow access from pods with client label set to "true". Ignored if `networkPolicy.allowExternal` is true. + ## + addExternalClientAccess: true + ## @param replica.networkPolicy.extraIngress [array] Add extra ingress rules to the NetworkPolicy + ## e.g: + ## extraIngress: + ## - ports: + ## - port: 1234 + ## from: + ## - podSelector: + ## - matchLabels: + ## - role: frontend + ## - podSelector: + ## - matchExpressions: + ## - key: role + ## operator: In + ## values: + ## - frontend + extraIngress: [] + ## @param replica.networkPolicy.extraEgress [array] Add extra ingress rules to the NetworkPolicy (ignored if allowExternalEgress=true) + ## e.g: + ## extraEgress: + ## - ports: + ## - port: 1234 + ## to: + ## - podSelector: + ## - matchLabels: + ## - role: frontend + ## - podSelector: + ## - matchExpressions: + ## - key: role + ## operator: In + ## values: + ## - frontend + ## + extraEgress: [] + ## @param replica.networkPolicy.ingressPodMatchLabels [object] Labels to match to allow traffic from other pods. Ignored if `networkPolicy.allowExternal` is true. + ## e.g: + ## ingressPodMatchLabels: + ## my-client: "true" + # + ingressPodMatchLabels: {} + ## @param replica.networkPolicy.ingressNSMatchLabels [object] Labels to match to allow traffic from other namespaces. Ignored if `networkPolicy.allowExternal` is true. + ## @param replica.networkPolicy.ingressNSPodMatchLabels [object] Pod labels to match to allow traffic from other namespaces. Ignored if `networkPolicy.allowExternal` is true. + ## + ingressNSMatchLabels: {} + ingressNSPodMatchLabels: {} - # CPU/Memory resource limits/requests +## @section Metrics Parameters +## +metrics: + ## @param metrics.enabled Start a sidecar Prometheus exporter to expose KeyDB metrics + ## + enabled: false + ## Bitnami Redis Exporter image + ## ref: https://hub.docker.com/r/bitnami/redis-exporter/tags/ + ## @param metrics.image.registry [default: REGISTRY_NAME] Redis Exporter image registry + ## @param metrics.image.repository [default: REPOSITORY_NAME/redis-exporter] Redis Exporter image repository + ## @skip metrics.image.tag Redis Exporter image tag (immutable tags are recommended) + ## @param metrics.image.digest Redis Exporter image digest in the way sha256:aa.... Please note this parameter, if set, will override the tag + ## @param metrics.image.pullPolicy Redis Exporter image pull policy + ## @param metrics.image.pullSecrets Redis Exporter image pull secrets + ## + image: + registry: docker.io + repository: bitnamilegacy/redis-exporter + tag: latest + digest: "" + 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/ + ## e.g: + ## pullSecrets: + ## - myRegistryKeySecretName + ## + pullSecrets: [] + ## @param metrics.containerPorts.http Metrics HTTP container port + ## + containerPorts: + http: 9121 + ## Configure extra options for KeyDB containers' liveness, readiness & startup probes + ## ref: https://kubernetes.io/docs/tasks/configure-pod-container/configure-liveness-readiness-startup-probes/ + ## @param metrics.startupProbe.enabled Enable startupProbe on KeyDB replicas nodes + ## @param metrics.startupProbe.initialDelaySeconds Initial delay seconds for startupProbe + ## @param metrics.startupProbe.periodSeconds Period seconds for startupProbe + ## @param metrics.startupProbe.timeoutSeconds Timeout seconds for startupProbe + ## @param metrics.startupProbe.failureThreshold Failure threshold for startupProbe + ## @param metrics.startupProbe.successThreshold Success threshold for startupProbe + ## + startupProbe: + enabled: false + initialDelaySeconds: 10 + periodSeconds: 10 + timeoutSeconds: 5 + successThreshold: 1 + failureThreshold: 5 + ## @param metrics.livenessProbe.enabled Enable livenessProbe on KeyDB replicas nodes + ## @param metrics.livenessProbe.initialDelaySeconds Initial delay seconds for livenessProbe + ## @param metrics.livenessProbe.periodSeconds Period seconds for livenessProbe + ## @param metrics.livenessProbe.timeoutSeconds Timeout seconds for livenessProbe + ## @param metrics.livenessProbe.failureThreshold Failure threshold for livenessProbe + ## @param metrics.livenessProbe.successThreshold Success threshold for livenessProbe + ## + livenessProbe: + enabled: true + initialDelaySeconds: 10 + periodSeconds: 10 + timeoutSeconds: 5 + successThreshold: 1 + failureThreshold: 5 + ## @param metrics.readinessProbe.enabled Enable readinessProbe on KeyDB replicas nodes + ## @param metrics.readinessProbe.initialDelaySeconds Initial delay seconds for readinessProbe + ## @param metrics.readinessProbe.periodSeconds Period seconds for readinessProbe + ## @param metrics.readinessProbe.timeoutSeconds Timeout seconds for readinessProbe + ## @param metrics.readinessProbe.failureThreshold Failure threshold for readinessProbe + ## @param metrics.readinessProbe.successThreshold Success threshold for readinessProbe + ## + readinessProbe: + enabled: true + initialDelaySeconds: 5 + periodSeconds: 10 + timeoutSeconds: 1 + successThreshold: 1 + failureThreshold: 3 + ## @param metrics.customStartupProbe Custom startupProbe that overrides the default one + ## + customStartupProbe: {} + ## @param metrics.customLivenessProbe Custom livenessProbe that overrides the default one + ## + customLivenessProbe: {} + ## @param metrics.customReadinessProbe Custom readinessProbe that overrides the default one + ## + customReadinessProbe: {} + ## @param metrics.command Override default metrics container init command (useful when using custom images) + ## + command: [] + ## @param metrics.keydbHost A way to specify an alternative KeyDB hostname + ## Useful for certificate CN/SAN matching + ## + keydbHost: "localhost" + ## @param metrics.extraArgs Extra arguments for KeyDB metrics exporter, for example: + ## e.g.: + ## extraArgs: + ## check-keys: myKey,myOtherKey + ## + extraArgs: {} + ## @param metrics.extraEnvVars Array with extra environment variables to add to KeyDB metrics exporter + ## e.g: + ## extraEnvVars: + ## - name: FOO + ## value: "bar" + ## + extraEnvVars: [] + ## Configure Container Security Context + ## ref: https://kubernetes.io/docs/tasks/configure-pod-container/security-context/#set-the-security-context-for-a-pod + ## @param metrics.containerSecurityContext.enabled Enabled KeyDB metrics exporter containers' Security Context + ## @param metrics.containerSecurityContext.seLinuxOptions [object,nullable] Set SELinux options in container + ## @param metrics.containerSecurityContext.runAsUser Set KeyDB metrics exporter containers' Security Context runAsUser + ## @param metrics.containerSecurityContext.runAsGroup Set KeyDB metrics exporter containers' Security Context runAsGroup + ## @param metrics.containerSecurityContext.runAsNonRoot Set KeyDB metrics exporter containers' Security Context runAsNonRoot + ## @param metrics.containerSecurityContext.allowPrivilegeEscalation Set KeyDB metrics exporter containers' Security Context allowPrivilegeEscalation + ## @param metrics.containerSecurityContext.readOnlyRootFilesystem Set container's Security Context read-only root filesystem + ## @param metrics.containerSecurityContext.seccompProfile.type Set KeyDB metrics exporter containers' Security Context seccompProfile + ## @param metrics.containerSecurityContext.capabilities.drop Set KeyDB metrics exporter containers' Security Context capabilities to drop + ## + containerSecurityContext: + enabled: true + seLinuxOptions: {} + runAsUser: 1001 + runAsGroup: 1001 + runAsNonRoot: true + allowPrivilegeEscalation: false + readOnlyRootFilesystem: true + seccompProfile: + type: RuntimeDefault + capabilities: + drop: ["ALL"] + ## @param metrics.extraVolumeMounts Optionally specify extra list of additional volumeMounts for the KeyDB metrics sidecar + ## + extraVolumeMounts: [] + ## KeyDB metrics exporter resource requests and limits + ## ref: https://kubernetes.io/docs/concepts/configuration/manage-compute-resources-container/ + ## @param metrics.resourcesPreset Set container resources according to one common preset (allowed values: none, nano, micro, small, medium, large, xlarge, 2xlarge). This is ignored if metrics.resources is set (metrics.resources is recommended for production). + ## More information: https://github.com/bitnami/charts/blob/main/bitnami/common/templates/_resources.tpl#L15 + ## + resourcesPreset: "nano" + ## @param metrics.resources Set container requests and limits for different resources like CPU or memory (essential for production workloads) + ## Example: + ## resources: + ## requests: + ## cpu: 2 + ## memory: 512Mi + ## limits: + ## cpu: 3 + ## memory: 1024Mi + ## resources: {} + ## @param metrics.podLabels Extra labels for KeyDB metrics exporter pods + ## ref: https://kubernetes.io/docs/concepts/overview/working-with-objects/labels/ + ## + podLabels: {} + ## @param metrics.podAnnotations [object] Annotations for KeyDB metrics exporter pods + ## ref: https://kubernetes.io/docs/concepts/overview/working-with-objects/annotations/ + ## + podAnnotations: + prometheus.io/scrape: "true" + prometheus.io/port: "{{ .Values.metrics.containerPorts.http }}" + ## KeyDB metrics exporter service properties + ## + service: + ## @param metrics.service.port Metrics service port + ## + port: 9121 + ## @param metrics.service.annotations Annotations for the metrics service + ## + annotations: {} + ## Prometheus Operator ServiceMonitor configuration + ## + serviceMonitor: + ## @param metrics.serviceMonitor.enabled if `true`, creates a Prometheus Operator ServiceMonitor (also requires `metrics.enabled` to be `true`) + ## + enabled: false + ## @param metrics.serviceMonitor.namespace Namespace in which Prometheus is running + ## + namespace: "" + ## @param metrics.serviceMonitor.annotations Additional custom annotations for the ServiceMonitor + ## + annotations: {} + ## @param metrics.serviceMonitor.labels Extra labels for the ServiceMonitor + ## + labels: {} + ## @param metrics.serviceMonitor.jobLabel The name of the label on the target service to use as the job name in Prometheus + ## + jobLabel: "" + ## @param metrics.serviceMonitor.honorLabels honorLabels chooses the metric's labels on collisions with target labels + ## + honorLabels: false + ## @param metrics.serviceMonitor.interval Interval at which metrics should be scraped. + ## ref: https://github.com/coreos/prometheus-operator/blob/master/Documentation/api.md#endpoint + ## e.g: + ## interval: 10s + ## + interval: "" + ## @param metrics.serviceMonitor.scrapeTimeout Timeout after which the scrape is ended + ## ref: https://github.com/coreos/prometheus-operator/blob/master/Documentation/api.md#endpoint + ## e.g: + ## scrapeTimeout: 10s + ## + scrapeTimeout: "" + ## @param metrics.serviceMonitor.metricRelabelings Specify additional relabeling of metrics + ## + metricRelabelings: [] + ## @param metrics.serviceMonitor.relabelings Specify general relabeling + ## + relabelings: [] + ## @param metrics.serviceMonitor.selector Prometheus instance selector labels + ## ref: https://github.com/bitnami/charts/tree/main/bitnami/prometheus-operator#prometheus-configuration + ## selector: + ## prometheus: my-prometheus + ## + selector: {} + ## Custom PrometheusRule to be defined + ## ref: https://github.com/coreos/prometheus-operator#customresourcedefinitions + ## + prometheusRule: + ## @param metrics.prometheusRule.enabled Create a custom prometheusRule Resource for scraping metrics using PrometheusOperator + ## + enabled: false + ## @param metrics.prometheusRule.namespace The namespace in which the prometheusRule will be created + ## + namespace: "" + ## @param metrics.prometheusRule.annotations Additional custom annotations for the prometheusRule + ## + annotations: {} + ## @param metrics.prometheusRule.labels Extra labels for the prometheusRule + ## + labels: {} + ## @param metrics.prometheusRule.rules Custom Prometheus rules + ## e.g: + ## rules: + ## - alert: KeyDBDown + ## expr: redis_up{service="{{ include "common.names.fullname" . }}-metrics"} == 0 + ## for: 2m + ## labels: + ## severity: error + ## annotations: + ## summary: KeyDB instance {{ "{{ $labels.instance }}" }} down + ## description: KeyDB instance {{ "{{ $labels.instance }}" }} is down + ## - alert: KeyDBMemoryHigh + ## expr: > + ## redis_memory_used_bytes{service="{{ include "common.names.fullname" . }}-metrics"} * 100 + ## / + ## redis_memory_max_bytes{service="{{ include "common.names.fullname" . }}-metrics"} + ## > 90 + ## for: 2m + ## labels: + ## severity: error + ## annotations: + ## summary: KeyDB instance {{ "{{ $labels.instance }}" }} is using too much memory + ## description: | + ## KeyDB instance {{ "{{ $labels.instance }}" }} is using {{ "{{ $value }}" }}% of its available memory. + ## - alert: KeyDBKeyEviction + ## expr: | + ## increase(redis_evicted_keys_total{service="{{ include "common.names.fullname" . }}-metrics"}[5m]) > 0 + ## for: 1s + ## labels: + ## severity: error + ## annotations: + ## summary: KeyDB instance {{ "{{ $labels.instance }}" }} has evicted keys + ## description: | + ## KeyDB instance {{ "{{ $labels.instance }}" }} has evicted {{ "{{ $value }}" }} keys in the last 5 minutes. + ## + rules: [] - # Container security context - securityContext: {} +## @section Other Parameters - # Additional args for redis exporter - extraArgs: [] - # - somesimple: "argument" - # - client-output-buffer-limit: ["normal", "0", "0", "0"] - # - client-output-buffer-limit: ["replica", "268435456", "67108864", "60"] - # - client-output-buffer-limit: ["pubsub", "33554432", "8388608", "60"] +## ServiceAccount configuration +## +serviceAccount: + ## @param serviceAccount.create Specifies whether a ServiceAccount should be created for KeyDB replicas pods + ## + create: true + ## @param serviceAccount.name The name of the ServiceAccount to use + ## If not set and create is true, a name is generated using the common.names.fullname template + ## + name: "" + ## @param serviceAccount.annotations Additional Service Account annotations (evaluated as a template) + ## + annotations: {} + ## @param serviceAccount.automountServiceAccountToken Automount service account token for the server service account + ## + automountServiceAccountToken: true -scripts: +## @section Init Container Parameters +## + +## 'volumePermissions' init container parameters +## Changes the owner and group of the persistent volume mount point to runAsUser:fsGroup values +## based on the *podSecurityContext/*containerSecurityContext parameters +## +volumePermissions: + ## @param volumePermissions.enabled Enable init container that changes the owner/group of the PV mount point to `runAsUser:fsGroup` + ## enabled: false - # CPU/Memory resource limits/requests + ## OS Shell + Utility image + ## ref: https://hub.docker.com/r/bitnami/os-shell/tags/ + ## @param volumePermissions.image.registry [default: REGISTRY_NAME] OS Shell + Utility image registry + ## @param volumePermissions.image.repository [default: REPOSITORY_NAME/os-shell] OS Shell + Utility image repository + ## @skip volumePermissions.image.tag OS Shell + Utility image tag (immutable tags are recommended) + ## @param volumePermissions.image.pullPolicy OS Shell + Utility image pull policy + ## @param volumePermissions.image.pullSecrets OS Shell + Utility image pull secrets + ## + image: + registry: docker.io + repository: bitnamilegacy/os-shell + tag: latest + 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/ + ## e.g: + ## pullSecrets: + ## - myRegistryKeySecretName + ## + pullSecrets: [] + ## Init container's resource requests and limits + ## ref: http://kubernetes.io/docs/concepts/configuration/manage-compute-resources-container/ + ## @param volumePermissions.resourcesPreset Set init container resources according to one common preset (allowed values: none, nano, small, medium, large, xlarge, 2xlarge). This is ignored if volumePermissions.resources is set (volumePermissions.resources is recommended for production). + ## More information: https://github.com/bitnami/charts/blob/main/bitnami/common/templates/_resources.tpl#L15 + ## + resourcesPreset: "nano" + ## @param volumePermissions.resources Set init container requests and limits for different resources like CPU or memory (essential for production workloads) + ## Example: + ## resources: + ## requests: + ## cpu: 2 + ## memory: 512Mi + ## limits: + ## cpu: 3 + ## memory: 1024Mi + ## resources: {} - # Container security context - securityContext: {} - cleanupCoredumps: - enabled: false - minutes: 1440 - cleanupTempfiles: + ## Init container Container Security Context + ## ref: https://kubernetes.io/docs/tasks/configure-pod-container/security-context/#set-the-security-context-for-a-container + ## @param volumePermissions.containerSecurityContext.enabled Enabled init container' Security Context + ## @param volumePermissions.containerSecurityContext.seLinuxOptions [object,nullable] Set SELinux options in init container + ## @param volumePermissions.containerSecurityContext.runAsUser Set init container's Security Context runAsUser + ## NOTE: when runAsUser is set to special value "auto", init container will try to chown the + ## data folder to auto-determined user&group, using commands: `id -u`:`id -G | cut -d" " -f2` + ## "auto" is especially useful for OpenShift which has scc with dynamic user ids (and 0 is not allowed) + ## + containerSecurityContext: enabled: true - minutes: 60 + seLinuxOptions: {} + runAsUser: 0 From ffaeb47e0e82a86eefba1aa4e95e69e72dfd68fd Mon Sep 17 00:00:00 2001 From: bandigesaikiran19 Date: Fri, 26 Jun 2026 10:56:24 +0000 Subject: [PATCH 6/6] Added PR reviews for yugabyte --- examples/yugabyte/values.yaml | 61 ++++++++++--------- helm-charts/yugabyte/templates/_helpers.tpl | 23 +++++++ .../yugabyte/templates/certificates.yaml | 3 +- helm-charts/yugabyte/templates/service.yaml | 21 ++++--- helm-charts/yugabyte/values.yaml | 3 + 5 files changed, 71 insertions(+), 40 deletions(-) diff --git a/examples/yugabyte/values.yaml b/examples/yugabyte/values.yaml index eef5160..cdeccec 100644 --- a/examples/yugabyte/values.yaml +++ b/examples/yugabyte/values.yaml @@ -13,14 +13,14 @@ Image: pullSecretName: "" storage: - ephemeral: false # will not allocate PVs when true + ephemeral: true #ll not allocate PVs when true master: - count: 2 - size: 10Gi + count: 1 + size: 1Gi storageClass: "" tserver: - count: 2 - size: 10Gi + count: 1 + size: 1Gi storageClass: "" resource: @@ -48,10 +48,10 @@ resource: memory: 4Gi replicas: - master: 3 - tserver: 3 + master: 1 + tserver: 1 ## Used to set replication factor when isMultiAz is set to true - totalMasters: 3 + totalMasters: 1 partition: master: 0 @@ -96,11 +96,11 @@ moveOp: ephemeral: false # will not allocate PVs when true master: count: 2 - size: 10Gi + size: 1Gi storageClass: "" tserver: count: 2 - size: 10Gi + size: 1Gi storageClass: "" replicas: @@ -177,8 +177,11 @@ tls: ## When certManager.enabled=true and bootstrapSelfsigned=false, only rootCA.cert is used ## to verify TLS certs generated and signed by the external provider. rootCA: - cert: "LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSUM2VENDQWRHZ0F3SUJBZ0lCQVRBTkJna3Foa2lHOXcwQkFRc0ZBREFXTVJRd0VnWURWUVFERXd0WmRXZGgKWW5sMFpTQkVRakFlRncweE9UQXlNRGd3TURRd01qSmFGdzB5T1RBeU1EVXdNRFF3TWpKYU1CWXhGREFTQmdOVgpCQU1UQzFsMVoyRmllWFJsSUVSQ01JSUJJakFOQmdrcWhraUc5dzBCQVFFRkFBT0NBUThBTUlJQkNnS0NBUUVBCnVOMWF1aWc4b2pVMHM0OXF3QXhrT2FCaHkwcTlyaVg2akVyZWJyTHJOWDJOeHdWQmNVcWJkUlhVc3VZNS96RUQKUC9CZTNkcTFuMm9EQ2ZGVEwweGkyNFdNZExRcnJBMndCdzFtNHM1WmQzcEJ1U04yWHJkVVhkeUx6dUxlczJNbgovckJxcWRscXp6LzAyTk9TOE9SVFZCUVRTQTBSOFNMQ1RjSGxMQmRkMmdxZ1ZmemVXRlVObXhWQ2EwcHA5UENuCmpUamJJRzhJWkh5dnBkTyt3aURQM1Y1a1ZEaTkvbEtUaGUzcTFOeDg5VUNFcnRJa1pjSkYvWEs3aE90MU1sOXMKWDYzb2lVMTE1Q2svbGFGRjR6dWgrZk9VenpOVXRXeTc2RE92cm5pVGlaU0tQZDBBODNNa2l2N2VHaDVkV3owWgpsKzJ2a3dkZHJaRzVlaHhvbGhGS3pRSURBUUFCbzBJd1FEQU9CZ05WSFE4QkFmOEVCQU1DQXFRd0hRWURWUjBsCkJCWXdGQVlJS3dZQkJRVUhBd0VHQ0NzR0FRVUZCd01DTUE4R0ExVWRFd0VCL3dRRk1BTUJBZjh3RFFZSktvWkkKaHZjTkFRRUxCUUFEZ2dFQkFEQjVRbmlYd1ptdk52eG5VbS9sTTVFbms3VmhTUzRUZldIMHY4Q0srZWZMSVBTbwpVTkdLNXU5UzNEUWlvaU9SN1Vmc2YrRnk1QXljMmNUY1M2UXBxTCt0V1QrU1VITXNJNk9oQ05pQ1gvQjNKWERPCkd2R0RIQzBVOHo3aWJTcW5zQ2Rid05kajAyM0lwMHVqNE9DVHJ3azZjd0RBeXlwVWkwN2tkd28xYWJIWExqTnAKamVQMkwrY0hkc2dKM1N4WWpkK1kvei9IdmFrZG1RZDJTL1l2V0R3aU1SRDkrYmZXWkJVRHo3Y0QyQkxEVmU0aAp1bkFaK3NyelR2Sjd5dkVodzlHSDFyajd4Qm9VNjB5SUUrYSszK2xWSEs4WnBSV0NXMnh2eWNrYXJSKytPS2NKClFsL04wWExqNWJRUDVoUzdhOTdhQktTamNqY3E5VzNGcnhJa2tKST0KLS0tLS1FTkQgQ0VSVElGSUNBVEUtLS0tLQo=" - key: "LS0tLS1CRUdJTiBSU0EgUFJJVkFURSBLRVktLS0tLQpNSUlFcEFJQkFBS0NBUUVBdU4xYXVpZzhvalUwczQ5cXdBeGtPYUJoeTBxOXJpWDZqRXJlYnJMck5YMk54d1ZCCmNVcWJkUlhVc3VZNS96RURQL0JlM2RxMW4yb0RDZkZUTDB4aTI0V01kTFFyckEyd0J3MW00czVaZDNwQnVTTjIKWHJkVVhkeUx6dUxlczJNbi9yQnFxZGxxenovMDJOT1M4T1JUVkJRVFNBMFI4U0xDVGNIbExCZGQyZ3FnVmZ6ZQpXRlVObXhWQ2EwcHA5UENualRqYklHOElaSHl2cGRPK3dpRFAzVjVrVkRpOS9sS1RoZTNxMU54ODlVQ0VydElrClpjSkYvWEs3aE90MU1sOXNYNjNvaVUxMTVDay9sYUZGNHp1aCtmT1V6ek5VdFd5NzZET3ZybmlUaVpTS1BkMEEKODNNa2l2N2VHaDVkV3owWmwrMnZrd2RkclpHNWVoeG9saEZLelFJREFRQUJBb0lCQUJsdW1tU3gxR1djWER1Mwpwei8wZEhWWkV4c2NsU3U0SGRmZkZPcTF3cFlCUjlmeGFTZGsxQzR2YXF1UjhMaWl6WWVtVWViRGgraitkSnlSCmpwZ2JNaDV4S1BtRkw5empwU3ZUTkN4UHB3OUF5bm5sM3dyNHZhcU1CTS9aZGpuSGttRC9kQzBadEEvL0JIZ3YKNHk4d3VpWCsvUWdVaER0Z1JNcmR1ZUZ1OVlKaFo5UE9jYXkzSkkzMFhEYjdJSS9vNFNhYnhTcFI3bTg5WjY0NwpUb3hsOEhTSzl0SUQxbkl1bHVpTmx1dHI1RzdDdE93WTBSc2N5dmZ2elg4a1d2akpLZVJVbmhMSCtXVFZOaExICjdZc0tMNmlLa1NkckMzeWVPWnV4R0pEbVdrZVgxTzNPRUVGYkc4TjVEaGNqL0lXbDh1dGt3LzYwTEthNHBCS2cKTXhtNEx3RUNnWUVBNnlPRkhNY2pncHYxLzlHZC8yb3c2YmZKcTFjM1dqQkV2cnM2ZXNyMzgrU3UvdVFneXJNcAo5V01oZElpb2dYZjVlNjV5ZlIzYVBXcjJJdWMxZ0RUNlYycDZFR2h0NysyQkF1YkIzczloZisycVNRY1lkS3pmCnJOTDdKalE4ZEVGZWdYd041cHhKOTRTTVFZNEI4Qm9hOHNJWTd3TzU4dHpVMjZoclVnanFXQ1VDZ1lFQXlVUUIKNzViWlh6MGJ5cEc5NjNwYVp0bGlJY0cvUk1XMnVPOE9rVFNYSGdDSjBob25uRm5IMGZOc1pGTHdFWEtnTTRORworU3ZNbWtUekE5eVVSMHpIMFJ4UW44L1YzVWZLT2k5RktFeWx6NzNiRkV6ZW1QSEppQm12NWQ4ZTlOenZmU0E0CkdpRTYrYnFyV3VVWWRoRWlYTnY1SFNPZ3I4bUx1TzJDbGlmNTg0a0NnWUFlZzlDTmlJWmlOODAzOHNNWFYzZWIKalI5ZDNnYXY3SjJ2UnVyeTdvNDVGNDlpUXNiQ3AzZWxnY1RnczY5eWhkaFpwYXp6OGNEVndhREpyTW16cHF4cQpWY1liaFFIblppSWM5MGRubS9BaVF2eWJWNUZqNnQ5b05VVWtreGpaV1haalJXOGtZMW55QmtDUmJWVnhER0k4CjZOV0ZoeTFGaUVVVGNJcms3WVZFQlFLQmdRREpHTVIrYWRFamtlRlUwNjVadkZUYmN0VFVPY3dzb1Foalc2akkKZVMyTThxakNYeE80NnhQMnVTeFNTWFJKV3FpckQ3NDRkUVRvRjRCaEdXS21veGI3M3pqSGxWaHcwcXhDMnJ4VQorZENxODE0VXVJR3BlOTBMdWU3QTFlRU9kRHB1WVdUczVzc1FmdTE3MG5CUWQrcEhzaHNFZkhhdmJjZkhyTGpQCjQzMmhVUUtCZ1FDZ3hMZG5Pd2JMaHZLVkhhdTdPVXQxbGpUT240SnB5bHpnb3hFRXpzaDhDK0ZKUUQ1bkFxZXEKZUpWSkNCd2VkallBSDR6MUV3cHJjWnJIN3IyUTBqT2ZFallwU1dkZGxXaWh4OTNYODZ0aG83UzJuUlYrN1hNcQpPVW9ZcVZ1WGlGMWdMM1NGeHZqMHhxV3l0d0NPTW5DZGFCb0M0Tkw3enJtL0lZOEUwSkw2MkE9PQotLS0tLUVORCBSU0EgUFJJVkFURSBLRVktLS0tLQo=" + existingSecret: "yugabyte-root-ca" + certKey: "ca.crt" + keyKey: "ca.key" + # cert: "LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSUM2VENDQWRHZ0F3SUJBZ0lCQVRBTkJna3Foa2lHOXcwQkFRc0ZBREFXTVJRd0VnWURWUVFERXd0WmRXZGgKWW5sMFpTQkVRakFlRncweE9UQXlNRGd3TURRd01qSmFGdzB5T1RBeU1EVXdNRFF3TWpKYU1CWXhGREFTQmdOVgpCQU1UQzFsMVoyRmllWFJsSUVSQ01JSUJJakFOQmdrcWhraUc5dzBCQVFFRkFBT0NBUThBTUlJQkNnS0NBUUVBCnVOMWF1aWc4b2pVMHM0OXF3QXhrT2FCaHkwcTlyaVg2akVyZWJyTHJOWDJOeHdWQmNVcWJkUlhVc3VZNS96RUQKUC9CZTNkcTFuMm9EQ2ZGVEwweGkyNFdNZExRcnJBMndCdzFtNHM1WmQzcEJ1U04yWHJkVVhkeUx6dUxlczJNbgovckJxcWRscXp6LzAyTk9TOE9SVFZCUVRTQTBSOFNMQ1RjSGxMQmRkMmdxZ1ZmemVXRlVObXhWQ2EwcHA5UENuCmpUamJJRzhJWkh5dnBkTyt3aURQM1Y1a1ZEaTkvbEtUaGUzcTFOeDg5VUNFcnRJa1pjSkYvWEs3aE90MU1sOXMKWDYzb2lVMTE1Q2svbGFGRjR6dWgrZk9VenpOVXRXeTc2RE92cm5pVGlaU0tQZDBBODNNa2l2N2VHaDVkV3owWgpsKzJ2a3dkZHJaRzVlaHhvbGhGS3pRSURBUUFCbzBJd1FEQU9CZ05WSFE4QkFmOEVCQU1DQXFRd0hRWURWUjBsCkJCWXdGQVlJS3dZQkJRVUhBd0VHQ0NzR0FRVUZCd01DTUE4R0ExVWRFd0VCL3dRRk1BTUJBZjh3RFFZSktvWkkKaHZjTkFRRUxCUUFEZ2dFQkFEQjVRbmlYd1ptdk52eG5VbS9sTTVFbms3VmhTUzRUZldIMHY4Q0srZWZMSVBTbwpVTkdLNXU5UzNEUWlvaU9SN1Vmc2YrRnk1QXljMmNUY1M2UXBxTCt0V1QrU1VITXNJNk9oQ05pQ1gvQjNKWERPCkd2R0RIQzBVOHo3aWJTcW5zQ2Rid05kajAyM0lwMHVqNE9DVHJ3azZjd0RBeXlwVWkwN2tkd28xYWJIWExqTnAKamVQMkwrY0hkc2dKM1N4WWpkK1kvei9IdmFrZG1RZDJTL1l2V0R3aU1SRDkrYmZXWkJVRHo3Y0QyQkxEVmU0aAp1bkFaK3NyelR2Sjd5dkVodzlHSDFyajd4Qm9VNjB5SUUrYSszK2xWSEs4WnBSV0NXMnh2eWNrYXJSKytPS2NKClFsL04wWExqNWJRUDVoUzdhOTdhQktTamNqY3E5VzNGcnhJa2tKST0KLS0tLS1FTkQgQ0VSVElGSUNBVEUtLS0tLQo=" + # key: "LS0tLS1CRUdJTiBSU0EgUFJJVkFURSBLRVktLS0tLQpNSUlFcEFJQkFBS0NBUUVBdU4xYXVpZzhvalUwczQ5cXdBeGtPYUJoeTBxOXJpWDZqRXJlYnJMck5YMk54d1ZCCmNVcWJkUlhVc3VZNS96RURQL0JlM2RxMW4yb0RDZkZUTDB4aTI0V01kTFFyckEyd0J3MW00czVaZDNwQnVTTjIKWHJkVVhkeUx6dUxlczJNbi9yQnFxZGxxenovMDJOT1M4T1JUVkJRVFNBMFI4U0xDVGNIbExCZGQyZ3FnVmZ6ZQpXRlVObXhWQ2EwcHA5UENualRqYklHOElaSHl2cGRPK3dpRFAzVjVrVkRpOS9sS1RoZTNxMU54ODlVQ0VydElrClpjSkYvWEs3aE90MU1sOXNYNjNvaVUxMTVDay9sYUZGNHp1aCtmT1V6ek5VdFd5NzZET3ZybmlUaVpTS1BkMEEKODNNa2l2N2VHaDVkV3owWmwrMnZrd2RkclpHNWVoeG9saEZLelFJREFRQUJBb0lCQUJsdW1tU3gxR1djWER1Mwpwei8wZEhWWkV4c2NsU3U0SGRmZkZPcTF3cFlCUjlmeGFTZGsxQzR2YXF1UjhMaWl6WWVtVWViRGgraitkSnlSCmpwZ2JNaDV4S1BtRkw5empwU3ZUTkN4UHB3OUF5bm5sM3dyNHZhcU1CTS9aZGpuSGttRC9kQzBadEEvL0JIZ3YKNHk4d3VpWCsvUWdVaER0Z1JNcmR1ZUZ1OVlKaFo5UE9jYXkzSkkzMFhEYjdJSS9vNFNhYnhTcFI3bTg5WjY0NwpUb3hsOEhTSzl0SUQxbkl1bHVpTmx1dHI1RzdDdE93WTBSc2N5dmZ2elg4a1d2akpLZVJVbmhMSCtXVFZOaExICjdZc0tMNmlLa1NkckMzeWVPWnV4R0pEbVdrZVgxTzNPRUVGYkc4TjVEaGNqL0lXbDh1dGt3LzYwTEthNHBCS2cKTXhtNEx3RUNnWUVBNnlPRkhNY2pncHYxLzlHZC8yb3c2YmZKcTFjM1dqQkV2cnM2ZXNyMzgrU3UvdVFneXJNcAo5V01oZElpb2dYZjVlNjV5ZlIzYVBXcjJJdWMxZ0RUNlYycDZFR2h0NysyQkF1YkIzczloZisycVNRY1lkS3pmCnJOTDdKalE4ZEVGZWdYd041cHhKOTRTTVFZNEI4Qm9hOHNJWTd3TzU4dHpVMjZoclVnanFXQ1VDZ1lFQXlVUUIKNzViWlh6MGJ5cEc5NjNwYVp0bGlJY0cvUk1XMnVPOE9rVFNYSGdDSjBob25uRm5IMGZOc1pGTHdFWEtnTTRORworU3ZNbWtUekE5eVVSMHpIMFJ4UW44L1YzVWZLT2k5RktFeWx6NzNiRkV6ZW1QSEppQm12NWQ4ZTlOenZmU0E0CkdpRTYrYnFyV3VVWWRoRWlYTnY1SFNPZ3I4bUx1TzJDbGlmNTg0a0NnWUFlZzlDTmlJWmlOODAzOHNNWFYzZWIKalI5ZDNnYXY3SjJ2UnVyeTdvNDVGNDlpUXNiQ3AzZWxnY1RnczY5eWhkaFpwYXp6OGNEVndhREpyTW16cHF4cQpWY1liaFFIblppSWM5MGRubS9BaVF2eWJWNUZqNnQ5b05VVWtreGpaV1haalJXOGtZMW55QmtDUmJWVnhER0k4CjZOV0ZoeTFGaUVVVGNJcms3WVZFQlFLQmdRREpHTVIrYWRFamtlRlUwNjVadkZUYmN0VFVPY3dzb1Foalc2akkKZVMyTThxakNYeE80NnhQMnVTeFNTWFJKV3FpckQ3NDRkUVRvRjRCaEdXS21veGI3M3pqSGxWaHcwcXhDMnJ4VQorZENxODE0VXVJR3BlOTBMdWU3QTFlRU9kRHB1WVdUczVzc1FmdTE3MG5CUWQrcEhzaHNFZkhhdmJjZkhyTGpQCjQzMmhVUUtCZ1FDZ3hMZG5Pd2JMaHZLVkhhdTdPVXQxbGpUT240SnB5bHpnb3hFRXpzaDhDK0ZKUUQ1bkFxZXEKZUpWSkNCd2VkallBSDR6MUV3cHJjWnJIN3IyUTBqT2ZFallwU1dkZGxXaWh4OTNYODZ0aG83UzJuUlYrN1hNcQpPVW9ZcVZ1WGlGMWdMM1NGeHZqMHhxV3l0d0NPTW5DZGFCb0M0Tkw3enJtL0lZOEUwSkw2MkE9PQotLS0tLUVORCBSU0EgUFJJVkFURSBLRVktLS0tLQo=" ## When tls.certManager.enabled=false ## nodeCert and clientCert will be used only when rootCA.key is empty. ## Will be ignored and genSignedCert will be used to generate @@ -234,13 +237,13 @@ ybc: useYBDBImage: false ## https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/#resource-requests-and-limits-of-pod-and-container ## Use the above link to learn more about Kubernetes resources configuration. - resources: - requests: - cpu: "1" - memory: 1Gi - limits: - cpu: "1" - memory: 1Gi + resources: {} + # requests: + # cpu: "0.1" + # memory: 32Mi + # limits: + # cpu: "0.2" + # memory: 64Mi ## Checksum for controller gflags secret. If set to empty, statefulset ## will calculate new checksum value and decide whether to restart pods ## based on the result of comparing previous checksum value and new value. @@ -251,13 +254,13 @@ ybc: ybCleanup: ## https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/#resource-requests-and-limits-of-pod-and-container ## Use the above link to learn more about Kubernetes resources configuration. - resources: - requests: - cpu: "0.25" - memory: 250Mi - limits: - cpu: "0.25" - memory: 250Mi + resources: {} + # requests: + # cpu: "0.25" + # memory: 50Mi + # limits: + # cpu: "0.25" + # memory: 250Mi domainName: "cluster.local" @@ -840,11 +843,11 @@ ip_version_support: "v4_only" # v4_only, v6_only are the only supported values a # For more https://docs.yugabyte.com/latest/reference/configuration/yugabyted/#environment-variables authCredentials: ysql: - user: "" + user: "yugabyte" password: "" - database: "" + database: "yugabyte" # Must contain the key ysqlPassword - passwordSecretName: "" + passwordSecretName: "yugabyte-ysql-password" ycql: user: "" password: "" diff --git a/helm-charts/yugabyte/templates/_helpers.tpl b/helm-charts/yugabyte/templates/_helpers.tpl index 3aa798c..e6d8a50 100644 --- a/helm-charts/yugabyte/templates/_helpers.tpl +++ b/helm-charts/yugabyte/templates/_helpers.tpl @@ -233,6 +233,29 @@ It uses a base multiplier of 1000 for 'G' units and 1024 for 'Gi' units. {{- printf "%d" .size | regexFind "\\d+" | mul $baseMultiplier | mul $baseMultiplier | mul $multiplier -}} {{- end -}} +{{/* +Resolve TLS root CA data from either inline values or an existing Secret. +*/}} +{{- define "yugabyte.tlsRootCA" -}} +{{- $root := .root -}} +{{- $secretName := $root.Values.tls.rootCA.existingSecret | default "" -}} +{{- $cert := $root.Values.tls.rootCA.cert | default "" -}} +{{- $key := $root.Values.tls.rootCA.key | default "" -}} +{{- if $secretName -}} +{{- $secret := lookup "v1" "Secret" $root.Release.Namespace $secretName | default dict -}} +{{- $secretData := get $secret "data" | default dict -}} +{{- $certData := get $secretData ($root.Values.tls.rootCA.certKey | default "ca.crt") | default "" -}} +{{- $keyData := get $secretData ($root.Values.tls.rootCA.keyKey | default "ca.key") | default "" -}} +{{- if not (empty $certData) -}} +{{- $cert = $certData -}} +{{- end -}} +{{- if not (empty $keyData) -}} +{{- $key = $keyData -}} +{{- end -}} +{{- end -}} +{{- dict "cert" $cert "key" $key | toYaml -}} +{{- end -}} + {{/* Create chart name and version as used by the chart label. */}} diff --git a/helm-charts/yugabyte/templates/certificates.yaml b/helm-charts/yugabyte/templates/certificates.yaml index 602b619..daf7800 100644 --- a/helm-charts/yugabyte/templates/certificates.yaml +++ b/helm-charts/yugabyte/templates/certificates.yaml @@ -1,4 +1,5 @@ {{- $root := . -}} +{{- $tlsRootCA := include "yugabyte.tlsRootCA" (dict "root" $root) | fromYaml -}} --- {{- if $root.Values.tls.certManager.enabled }} {{- if $root.Values.tls.certManager.bootstrapSelfsigned }} @@ -67,7 +68,7 @@ metadata: {{- include "yugabyte.labels" $root | indent 4 }} type: Opaque data: - ca.crt: {{ $root.Values.tls.rootCA.cert }} + ca.crt: {{ $tlsRootCA.cert }} {{/* if useExistingServerCertificate is true, then tls.crt and tls.key will not be set */}} {{if $root.Values.tls.certManager.useExistingServerCertificate -}} tls.crt: "" diff --git a/helm-charts/yugabyte/templates/service.yaml b/helm-charts/yugabyte/templates/service.yaml index 8901cc0..4e52c6d 100644 --- a/helm-charts/yugabyte/templates/service.yaml +++ b/helm-charts/yugabyte/templates/service.yaml @@ -1,4 +1,5 @@ {{- $root := . -}} +{{- $tlsRootCA := include "yugabyte.tlsRootCA" (dict "root" $root) | fromYaml -}} {{- /* Validate stsIndex values */ -}} {{- include "yugabyte.validateStsIndex" (dict "start" ($root.Values.stsIndex.master.start | int) "end" ($root.Values.stsIndex.master.end | int) "component" "master") -}} {{- include "yugabyte.validateStsIndex" (dict "start" ($root.Values.stsIndex.tserver.start | int) "end" ($root.Values.stsIndex.tserver.end | int) "component" "tserver") -}} @@ -14,14 +15,14 @@ metadata: {{- include "yugabyte.labels" $root | indent 4 }} type: Opaque data: -{{- if $root.Values.tls.rootCA.key }} -{{- $rootCAClient := buildCustomCert $root.Values.tls.rootCA.cert $root.Values.tls.rootCA.key -}} +{{- if $tlsRootCA.key }} +{{- $rootCAClient := buildCustomCert $tlsRootCA.cert $tlsRootCA.key -}} {{- $client := genSignedCert "yugabyte" ( default nil ) ( default nil ) 3650 $rootCAClient }} root.crt: {{ $rootCAClient.Cert | b64enc }} yugabytedb.crt: {{ $client.Cert | b64enc }} yugabytedb.key: {{ $client.Key | b64enc }} {{- else }} - root.crt: {{ $root.Values.tls.rootCA.cert }} + root.crt: {{ $tlsRootCA.cert }} yugabytedb.crt: {{ $root.Values.tls.clientCert.cert }} yugabytedb.key: {{ $root.Values.tls.clientCert.key }} {{- end }} @@ -68,7 +69,7 @@ data: {{- end -}} {{- $node := $root.Values.oldNamingStyle | ternary $nodeOldStyle $nodeNewStyle }} -{{- if $root.Values.tls.rootCA.key }} +{{- if $tlsRootCA.key }} {{- $dns1 := printf "*.%s-%s%s.%s" (include "yugabyte.fullname" $root) $service.name $stsIndexSuffix $root.Release.Namespace }} {{- $dns2 := printf "%s.svc.%s" $dns1 $root.Values.domainName }} {{- if $root.Values.multicluster.createServiceExports -}} @@ -77,7 +78,7 @@ data: {{- if $root.Values.multicluster.createServicePerPod -}} {{- $dns1 = printf "*.%s.svc.%s" $root.Release.Namespace $root.Values.domainName }} {{- end -}} -{{- $rootCA := buildCustomCert $root.Values.tls.rootCA.cert $root.Values.tls.rootCA.key -}} +{{- $rootCA := buildCustomCert $tlsRootCA.cert $tlsRootCA.key -}} {{- $server := genSignedCert $node ( default nil ) (list $node $dns1 $dns2 ) 3650 $rootCA }} node.{{$node}}.crt: {{ $server.Cert | b64enc }} node.{{$node}}.key: {{ $server.Key | b64enc }} @@ -86,7 +87,7 @@ data: node.{{$node}}.key: {{ $root.Values.tls.nodeCert.key }} {{- end }} {{- end }} - ca.crt: {{ $root.Values.tls.rootCA.cert }} + ca.crt: {{ $tlsRootCA.cert }} {{- end }} {{- end }} {{- end }} @@ -199,7 +200,7 @@ spec: {{- with $root.Values.networkAnnotation }}{{ toYaml . | nindent 8 }}{{ end }} {{- with $root.Values.master.podAnnotations }}{{ toYaml . | nindent 8 }}{{ end }} {{- if $root.Values.tls.enabled }} - checksum/rootCA: {{ (not $root.Values.tls.rootCAChecksum) | ternary (cat $root.Values.tls.rootCA.cert $root.Values.tls.rootCA.key | sha256sum) $root.Values.tls.rootCAChecksum }} + checksum/rootCA: {{ (not $root.Values.tls.rootCAChecksum) | ternary (cat $tlsRootCA.cert $tlsRootCA.key | sha256sum) $root.Values.tls.rootCAChecksum }} {{- end }} {{- end }} {{- else }} @@ -211,7 +212,7 @@ spec: {{- with $root.Values.networkAnnotation }}{{ toYaml . | nindent 8 }}{{ end }} {{- with $root.Values.tserver.podAnnotations }}{{ toYaml . | nindent 8 }}{{ end }} {{- if $root.Values.tls.enabled }} - checksum/rootCA: {{ (not $root.Values.tls.rootCAChecksum) | ternary (cat $root.Values.tls.rootCA.cert $root.Values.tls.rootCA.key | sha256sum) $root.Values.tls.rootCAChecksum }} + checksum/rootCA: {{ (not $root.Values.tls.rootCAChecksum) | ternary (cat $tlsRootCA.cert $tlsRootCA.key | sha256sum) $root.Values.tls.rootCAChecksum }} {{- end }} {{- end }} {{- if and (eq $service.name "yb-tservers") ($root.Values.otelCollector.enabled) }} @@ -898,7 +899,7 @@ spec: sources: - secret: name: {{ $root.Values.oldNamingStyle | ternary (printf "%s%s-yugabyte-tls-cert" $service.label $stsIndexSuffix) (printf "%s-%s%s-tls-cert" (include "yugabyte.fullname" $root) $service.label $stsIndexSuffix) }} - {{- if and (not $root.Values.tls.certManager.bootstrapSelfsigned) (not (empty $root.Values.tls.rootCA.cert)) }} + {{- if and (not $root.Values.tls.certManager.bootstrapSelfsigned) (or (not (empty $tlsRootCA.cert)) (not (empty $root.Values.tls.rootCA.existingSecret))) }} - secret: name: {{ printf "%s-root-ca" (include "yugabyte.fullname" $root) }} {{- end }} @@ -906,7 +907,7 @@ spec: projected: sources: {{- /* get the ca.crt from values or cert-manager */}} - {{- if and (not $root.Values.tls.certManager.bootstrapSelfsigned) (not (empty $root.Values.tls.rootCA.cert)) }} + {{- if and (not $root.Values.tls.certManager.bootstrapSelfsigned) (or (not (empty $tlsRootCA.cert)) (not (empty $root.Values.tls.rootCA.existingSecret))) }} - secret: name: {{ printf "%s-root-ca" (include "yugabyte.fullname" $root) }} items: diff --git a/helm-charts/yugabyte/values.yaml b/helm-charts/yugabyte/values.yaml index eef5160..01f6c6a 100644 --- a/helm-charts/yugabyte/values.yaml +++ b/helm-charts/yugabyte/values.yaml @@ -177,6 +177,9 @@ tls: ## When certManager.enabled=true and bootstrapSelfsigned=false, only rootCA.cert is used ## to verify TLS certs generated and signed by the external provider. rootCA: + existingSecret: "" + certKey: "ca.crt" + keyKey: "ca.key" cert: "LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSUM2VENDQWRHZ0F3SUJBZ0lCQVRBTkJna3Foa2lHOXcwQkFRc0ZBREFXTVJRd0VnWURWUVFERXd0WmRXZGgKWW5sMFpTQkVRakFlRncweE9UQXlNRGd3TURRd01qSmFGdzB5T1RBeU1EVXdNRFF3TWpKYU1CWXhGREFTQmdOVgpCQU1UQzFsMVoyRmllWFJsSUVSQ01JSUJJakFOQmdrcWhraUc5dzBCQVFFRkFBT0NBUThBTUlJQkNnS0NBUUVBCnVOMWF1aWc4b2pVMHM0OXF3QXhrT2FCaHkwcTlyaVg2akVyZWJyTHJOWDJOeHdWQmNVcWJkUlhVc3VZNS96RUQKUC9CZTNkcTFuMm9EQ2ZGVEwweGkyNFdNZExRcnJBMndCdzFtNHM1WmQzcEJ1U04yWHJkVVhkeUx6dUxlczJNbgovckJxcWRscXp6LzAyTk9TOE9SVFZCUVRTQTBSOFNMQ1RjSGxMQmRkMmdxZ1ZmemVXRlVObXhWQ2EwcHA5UENuCmpUamJJRzhJWkh5dnBkTyt3aURQM1Y1a1ZEaTkvbEtUaGUzcTFOeDg5VUNFcnRJa1pjSkYvWEs3aE90MU1sOXMKWDYzb2lVMTE1Q2svbGFGRjR6dWgrZk9VenpOVXRXeTc2RE92cm5pVGlaU0tQZDBBODNNa2l2N2VHaDVkV3owWgpsKzJ2a3dkZHJaRzVlaHhvbGhGS3pRSURBUUFCbzBJd1FEQU9CZ05WSFE4QkFmOEVCQU1DQXFRd0hRWURWUjBsCkJCWXdGQVlJS3dZQkJRVUhBd0VHQ0NzR0FRVUZCd01DTUE4R0ExVWRFd0VCL3dRRk1BTUJBZjh3RFFZSktvWkkKaHZjTkFRRUxCUUFEZ2dFQkFEQjVRbmlYd1ptdk52eG5VbS9sTTVFbms3VmhTUzRUZldIMHY4Q0srZWZMSVBTbwpVTkdLNXU5UzNEUWlvaU9SN1Vmc2YrRnk1QXljMmNUY1M2UXBxTCt0V1QrU1VITXNJNk9oQ05pQ1gvQjNKWERPCkd2R0RIQzBVOHo3aWJTcW5zQ2Rid05kajAyM0lwMHVqNE9DVHJ3azZjd0RBeXlwVWkwN2tkd28xYWJIWExqTnAKamVQMkwrY0hkc2dKM1N4WWpkK1kvei9IdmFrZG1RZDJTL1l2V0R3aU1SRDkrYmZXWkJVRHo3Y0QyQkxEVmU0aAp1bkFaK3NyelR2Sjd5dkVodzlHSDFyajd4Qm9VNjB5SUUrYSszK2xWSEs4WnBSV0NXMnh2eWNrYXJSKytPS2NKClFsL04wWExqNWJRUDVoUzdhOTdhQktTamNqY3E5VzNGcnhJa2tKST0KLS0tLS1FTkQgQ0VSVElGSUNBVEUtLS0tLQo=" key: "LS0tLS1CRUdJTiBSU0EgUFJJVkFURSBLRVktLS0tLQpNSUlFcEFJQkFBS0NBUUVBdU4xYXVpZzhvalUwczQ5cXdBeGtPYUJoeTBxOXJpWDZqRXJlYnJMck5YMk54d1ZCCmNVcWJkUlhVc3VZNS96RURQL0JlM2RxMW4yb0RDZkZUTDB4aTI0V01kTFFyckEyd0J3MW00czVaZDNwQnVTTjIKWHJkVVhkeUx6dUxlczJNbi9yQnFxZGxxenovMDJOT1M4T1JUVkJRVFNBMFI4U0xDVGNIbExCZGQyZ3FnVmZ6ZQpXRlVObXhWQ2EwcHA5UENualRqYklHOElaSHl2cGRPK3dpRFAzVjVrVkRpOS9sS1RoZTNxMU54ODlVQ0VydElrClpjSkYvWEs3aE90MU1sOXNYNjNvaVUxMTVDay9sYUZGNHp1aCtmT1V6ek5VdFd5NzZET3ZybmlUaVpTS1BkMEEKODNNa2l2N2VHaDVkV3owWmwrMnZrd2RkclpHNWVoeG9saEZLelFJREFRQUJBb0lCQUJsdW1tU3gxR1djWER1Mwpwei8wZEhWWkV4c2NsU3U0SGRmZkZPcTF3cFlCUjlmeGFTZGsxQzR2YXF1UjhMaWl6WWVtVWViRGgraitkSnlSCmpwZ2JNaDV4S1BtRkw5empwU3ZUTkN4UHB3OUF5bm5sM3dyNHZhcU1CTS9aZGpuSGttRC9kQzBadEEvL0JIZ3YKNHk4d3VpWCsvUWdVaER0Z1JNcmR1ZUZ1OVlKaFo5UE9jYXkzSkkzMFhEYjdJSS9vNFNhYnhTcFI3bTg5WjY0NwpUb3hsOEhTSzl0SUQxbkl1bHVpTmx1dHI1RzdDdE93WTBSc2N5dmZ2elg4a1d2akpLZVJVbmhMSCtXVFZOaExICjdZc0tMNmlLa1NkckMzeWVPWnV4R0pEbVdrZVgxTzNPRUVGYkc4TjVEaGNqL0lXbDh1dGt3LzYwTEthNHBCS2cKTXhtNEx3RUNnWUVBNnlPRkhNY2pncHYxLzlHZC8yb3c2YmZKcTFjM1dqQkV2cnM2ZXNyMzgrU3UvdVFneXJNcAo5V01oZElpb2dYZjVlNjV5ZlIzYVBXcjJJdWMxZ0RUNlYycDZFR2h0NysyQkF1YkIzczloZisycVNRY1lkS3pmCnJOTDdKalE4ZEVGZWdYd041cHhKOTRTTVFZNEI4Qm9hOHNJWTd3TzU4dHpVMjZoclVnanFXQ1VDZ1lFQXlVUUIKNzViWlh6MGJ5cEc5NjNwYVp0bGlJY0cvUk1XMnVPOE9rVFNYSGdDSjBob25uRm5IMGZOc1pGTHdFWEtnTTRORworU3ZNbWtUekE5eVVSMHpIMFJ4UW44L1YzVWZLT2k5RktFeWx6NzNiRkV6ZW1QSEppQm12NWQ4ZTlOenZmU0E0CkdpRTYrYnFyV3VVWWRoRWlYTnY1SFNPZ3I4bUx1TzJDbGlmNTg0a0NnWUFlZzlDTmlJWmlOODAzOHNNWFYzZWIKalI5ZDNnYXY3SjJ2UnVyeTdvNDVGNDlpUXNiQ3AzZWxnY1RnczY5eWhkaFpwYXp6OGNEVndhREpyTW16cHF4cQpWY1liaFFIblppSWM5MGRubS9BaVF2eWJWNUZqNnQ5b05VVWtreGpaV1haalJXOGtZMW55QmtDUmJWVnhER0k4CjZOV0ZoeTFGaUVVVGNJcms3WVZFQlFLQmdRREpHTVIrYWRFamtlRlUwNjVadkZUYmN0VFVPY3dzb1Foalc2akkKZVMyTThxakNYeE80NnhQMnVTeFNTWFJKV3FpckQ3NDRkUVRvRjRCaEdXS21veGI3M3pqSGxWaHcwcXhDMnJ4VQorZENxODE0VXVJR3BlOTBMdWU3QTFlRU9kRHB1WVdUczVzc1FmdTE3MG5CUWQrcEhzaHNFZkhhdmJjZkhyTGpQCjQzMmhVUUtCZ1FDZ3hMZG5Pd2JMaHZLVkhhdTdPVXQxbGpUT240SnB5bHpnb3hFRXpzaDhDK0ZKUUQ1bkFxZXEKZUpWSkNCd2VkallBSDR6MUV3cHJjWnJIN3IyUTBqT2ZFallwU1dkZGxXaWh4OTNYODZ0aG83UzJuUlYrN1hNcQpPVW9ZcVZ1WGlGMWdMM1NGeHZqMHhxV3l0d0NPTW5DZGFCb0M0Tkw3enJtL0lZOEUwSkw2MkE9PQotLS0tLUVORCBSU0EgUFJJVkFURSBLRVktLS0tLQo=" ## When tls.certManager.enabled=false