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

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
26 changes: 26 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -109,6 +109,32 @@ In that go template, the following variables may be used:
- `.tlsEnabled` (whether TLS encryption is enabled or not)
- `.caData` (CA certificate that clients may use to connect to valkey)

### Custom cluster domain

By default, Valkey services are accessed using DNS names with the `cluster.local` domain suffix (e.g., `valkey-test.namespace.svc.cluster.local`).
If your Kubernetes cluster uses a custom cluster domain, you can configure it using the `spec.clusterDomain` field:

```yaml
apiVersion: cache.cs.sap.com/v1alpha1
kind: Valkey
metadata:
name: test
spec:
clusterDomain: kube.prod
replicas: 3
sentinel:
enabled: true
```

This will result in DNS names like:
- `valkey-test.namespace.svc.kube.prod` instead of `valkey-test.namespace.svc.cluster.local`

The cluster domain value is used for:
- Service DNS names in the binding secret
- TLS certificate DNS names (when using cert-manager)

If not specified, the default value `cluster.local` is used for backward compatibility.

### Customize pod settings

The following attributes allow to tweak the created pods/containers:
Expand Down
7 changes: 5 additions & 2 deletions api/v1alpha1/types.go
Original file line number Diff line number Diff line change
Expand Up @@ -30,8 +30,11 @@ type ValkeySpec struct {
TLS *TLSProperties `json:"tls,omitempty"`
Persistence *PersistenceProperties `json:"persistence,omitempty"`
Binding *BindingProperties `json:"binding,omitempty"`
ExtraEnvVars []corev1.EnvVar `json:"extraEnvVars,omitempty"`
ExtraFlags []string `json:"extraFlags,omitempty"`
// +kubebuilder:validation:Pattern=`^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$`
// +kubebuilder:default="cluster.local"
ClusterDomain string `json:"clusterDomain,omitempty"`
ExtraEnvVars []corev1.EnvVar `json:"extraEnvVars,omitempty"`
ExtraFlags []string `json:"extraFlags,omitempty"`
}

// SentinelProperties models attributes of the sentinel sidecar
Expand Down
4 changes: 4 additions & 0 deletions crds/cache.cs.sap.com_valkeys.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -967,6 +967,10 @@ spec:
template:
type: string
type: object
clusterDomain:
default: cluster.local
pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$
type: string
extraEnvVars:
items:
description: EnvVar represents an environment variable present in
Expand Down
15 changes: 15 additions & 0 deletions examples/custom-cluster-domain.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
apiVersion: cache.cs.sap.com/v1alpha1
kind: Valkey
metadata:
name: valkey-custom-domain
spec:
# Custom cluster domain for environments that don't use the default cluster.local
clusterDomain: kube.prod
replicas: 3
sentinel:
enabled: true
metrics:
enabled: true
tls:
enabled: true
certManager: {}
14 changes: 10 additions & 4 deletions pkg/operator/binding.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,17 +23,23 @@ import (
func reconcileBinding(ctx context.Context, client client.Client, valkey *operatorv1alpha1.Valkey) error {
params := make(map[string]any)

// Use cluster domain from spec, defaulting to "cluster.local" for backward compatibility
clusterDomain := valkey.Spec.ClusterDomain
if clusterDomain == "" {
clusterDomain = "cluster.local"
}

if valkey.Spec.Sentinel != nil && valkey.Spec.Sentinel.Enabled {
params["sentinelEnabled"] = true
params["host"] = fmt.Sprintf("valkey-%s.%s.svc.cluster.local", valkey.Name, valkey.Namespace)
params["host"] = fmt.Sprintf("valkey-%s.%s.svc.%s", valkey.Name, valkey.Namespace, clusterDomain)
params["port"] = 6379
params["sentinelHost"] = fmt.Sprintf("valkey-%s.%s.svc.cluster.local", valkey.Name, valkey.Namespace)
params["sentinelHost"] = fmt.Sprintf("valkey-%s.%s.svc.%s", valkey.Name, valkey.Namespace, clusterDomain)
params["sentinelPort"] = 26379
params["primaryName"] = "myprimary"
} else {
params["primaryHost"] = fmt.Sprintf("valkey-%s-primary.%s.svc.cluster.local", valkey.Name, valkey.Namespace)
params["primaryHost"] = fmt.Sprintf("valkey-%s-primary.%s.svc.%s", valkey.Name, valkey.Namespace, clusterDomain)
params["primaryPort"] = 6379
params["replicaHost"] = fmt.Sprintf("valkey-%s-replicas.%s.svc.cluster.local", valkey.Name, valkey.Namespace)
params["replicaHost"] = fmt.Sprintf("valkey-%s-replicas.%s.svc.%s", valkey.Name, valkey.Namespace, clusterDomain)
params["replicaPort"] = 6379
}

Expand Down
16 changes: 10 additions & 6 deletions pkg/operator/data/parameters.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@ fullnameOverride: {{ $fullname }}
{{- $bindingSecretName = printf "%s-binding" $fullname }}
{{- end }}

{{- $clusterDomain := (dig "clusterDomain" "cluster.local" .) }}

image:
repository: bitnamilegacy/valkey
{{- with .Version}}
Expand Down Expand Up @@ -232,6 +234,8 @@ tls:
{{- end }}
{{- end }}

clusterDomain: {{ $clusterDomain }}

networkPolicy:
enabled: true
extraEgress:
Expand All @@ -256,27 +260,27 @@ extraDeploy:
secretName: {{ printf "%s-tls" $fullname }}
commonName: {{ $fullname }}
dnsNames:
- '{{ printf "%s.%s.svc.cluster.local" $fullname .Namespace }}'
- '{{ printf "%s.%s.svc.%s" $fullname .Namespace $clusterDomain }}'
- '{{ printf "%s.%s.svc" $fullname .Namespace }}'
- '{{ printf "%s.%s" $fullname .Namespace }}'
- '{{ printf "%s" $fullname }}'
- '{{ printf "*.%s.%s.svc.cluster.local" $fullname .Namespace }}'
- '{{ printf "*.%s.%s.svc.%s" $fullname .Namespace $clusterDomain }}'
- '{{ printf "*.%s.%s.svc" $fullname .Namespace }}'
- '{{ printf "*.%s.%s" $fullname .Namespace }}'
- '{{ printf "*.%s" $fullname }}'
- '{{ printf "%s-primary.%s.svc.cluster.local" $fullname .Namespace }}'
- '{{ printf "%s-primary.%s.svc.%s" $fullname .Namespace $clusterDomain }}'
- '{{ printf "%s-primary.%s.svc" $fullname .Namespace }}'
- '{{ printf "%s-primary.%s" $fullname .Namespace }}'
- '{{ printf "%s-primary" $fullname }}'
- '{{ printf "*.%s-primary.%s.svc.cluster.local" $fullname .Namespace }}'
- '{{ printf "*.%s-primary.%s.svc.%s" $fullname .Namespace $clusterDomain }}'
- '{{ printf "*.%s-primary.%s.svc" $fullname .Namespace }}'
- '{{ printf "*.%s-primary.%s" $fullname .Namespace }}'
- '{{ printf "*.%s-primary" $fullname }}'
- '{{ printf "%s-headless.%s.svc.cluster.local" $fullname .Namespace }}'
- '{{ printf "%s-headless.%s.svc.%s" $fullname .Namespace $clusterDomain }}'
- '{{ printf "%s-headless.%s.svc" $fullname .Namespace }}'
- '{{ printf "%s-headless.%s" $fullname .Namespace }}'
- '{{ printf "%s-headless" $fullname }}'
- '{{ printf "*.%s-headless.%s.svc.cluster.local" $fullname .Namespace }}'
- '{{ printf "*.%s-headless.%s.svc.%s" $fullname .Namespace $clusterDomain }}'
- '{{ printf "*.%s-headless.%s.svc" $fullname .Namespace }}'
- '{{ printf "*.%s-headless.%s" $fullname .Namespace }}'
- '{{ printf "*.%s-headless" $fullname }}'
Expand Down
41 changes: 41 additions & 0 deletions pkg/operator/operator_suite_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -360,6 +360,47 @@ var _ = Describe("Deploy Valkey", func() {
}
Expect(bindingSecret.Data).To(Equal(expectedSecretData))
})

It("should deploy Valkey with custom cluster domain", func() {
valkey := &operatorv1alpha1.Valkey{
ObjectMeta: metav1.ObjectMeta{
Namespace: namespace,
Name: "test",
},
Spec: operatorv1alpha1.ValkeySpec{
Replicas: 2,
ClusterDomain: "kube.prod",
},
}

err := cli.Create(ctx, valkey)
Expect(err).NotTo(HaveOccurred())
Eventually(func() error {
if err := cli.Get(ctx, types.NamespacedName{Namespace: valkey.Namespace, Name: valkey.Name}, valkey); err != nil {
return err
}
if valkey.Status.ObservedGeneration != valkey.Generation || valkey.Status.State != component.StateReady {
return fmt.Errorf("again")
}
return nil
}, "10s", "100ms").Should(Succeed())

authSecret := &corev1.Secret{}
err = cli.Get(ctx, types.NamespacedName{Namespace: valkey.Namespace, Name: fmt.Sprintf("valkey-%s", valkey.Name)}, authSecret)
Expect(err).NotTo(HaveOccurred())

bindingSecret := &corev1.Secret{}
err = cli.Get(ctx, types.NamespacedName{Namespace: valkey.Namespace, Name: fmt.Sprintf("valkey-%s-binding", valkey.Name)}, bindingSecret)
Expect(err).NotTo(HaveOccurred())
expectedSecretData := map[string][]byte{
"primaryHost": []byte(fmt.Sprintf("valkey-%s-primary.%s.svc.kube.prod", valkey.Name, valkey.Namespace)),
"primaryPort": []byte("6379"),
"replicaHost": []byte(fmt.Sprintf("valkey-%s-replicas.%s.svc.kube.prod", valkey.Name, valkey.Namespace)),
"replicaPort": []byte("6379"),
"password": authSecret.Data["valkey-password"],
}
Expect(bindingSecret.Data).To(Equal(expectedSecretData))
})
})

func createNamespace() string {
Expand Down