Skip to content

Commit fd7fd1d

Browse files
authored
Add configurable cluster domain support for non-standard Kubernetes environments (#1)
* Initial plan * Add configurable cluster domain support to API and binding * Add custom cluster domain test and documentation * Add example configuration for custom cluster domain
1 parent 11c9d88 commit fd7fd1d

File tree

7 files changed

+111
-12
lines changed

7 files changed

+111
-12
lines changed

README.md

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -109,6 +109,32 @@ In that go template, the following variables may be used:
109109
- `.tlsEnabled` (whether TLS encryption is enabled or not)
110110
- `.caData` (CA certificate that clients may use to connect to valkey)
111111

112+
### Custom cluster domain
113+
114+
By default, Valkey services are accessed using DNS names with the `cluster.local` domain suffix (e.g., `valkey-test.namespace.svc.cluster.local`).
115+
If your Kubernetes cluster uses a custom cluster domain, you can configure it using the `spec.clusterDomain` field:
116+
117+
```yaml
118+
apiVersion: cache.cs.sap.com/v1alpha1
119+
kind: Valkey
120+
metadata:
121+
name: test
122+
spec:
123+
clusterDomain: kube.prod
124+
replicas: 3
125+
sentinel:
126+
enabled: true
127+
```
128+
129+
This will result in DNS names like:
130+
- `valkey-test.namespace.svc.kube.prod` instead of `valkey-test.namespace.svc.cluster.local`
131+
132+
The cluster domain value is used for:
133+
- Service DNS names in the binding secret
134+
- TLS certificate DNS names (when using cert-manager)
135+
136+
If not specified, the default value `cluster.local` is used for backward compatibility.
137+
112138
### Customize pod settings
113139

114140
The following attributes allow to tweak the created pods/containers:

api/v1alpha1/types.go

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -30,8 +30,11 @@ type ValkeySpec struct {
3030
TLS *TLSProperties `json:"tls,omitempty"`
3131
Persistence *PersistenceProperties `json:"persistence,omitempty"`
3232
Binding *BindingProperties `json:"binding,omitempty"`
33-
ExtraEnvVars []corev1.EnvVar `json:"extraEnvVars,omitempty"`
34-
ExtraFlags []string `json:"extraFlags,omitempty"`
33+
// +kubebuilder:validation:Pattern=`^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$`
34+
// +kubebuilder:default="cluster.local"
35+
ClusterDomain string `json:"clusterDomain,omitempty"`
36+
ExtraEnvVars []corev1.EnvVar `json:"extraEnvVars,omitempty"`
37+
ExtraFlags []string `json:"extraFlags,omitempty"`
3538
}
3639

3740
// SentinelProperties models attributes of the sentinel sidecar

crds/cache.cs.sap.com_valkeys.yaml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -967,6 +967,10 @@ spec:
967967
template:
968968
type: string
969969
type: object
970+
clusterDomain:
971+
default: cluster.local
972+
pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$
973+
type: string
970974
extraEnvVars:
971975
items:
972976
description: EnvVar represents an environment variable present in
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
apiVersion: cache.cs.sap.com/v1alpha1
2+
kind: Valkey
3+
metadata:
4+
name: valkey-custom-domain
5+
spec:
6+
# Custom cluster domain for environments that don't use the default cluster.local
7+
clusterDomain: kube.prod
8+
replicas: 3
9+
sentinel:
10+
enabled: true
11+
metrics:
12+
enabled: true
13+
tls:
14+
enabled: true
15+
certManager: {}

pkg/operator/binding.go

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -23,17 +23,23 @@ import (
2323
func reconcileBinding(ctx context.Context, client client.Client, valkey *operatorv1alpha1.Valkey) error {
2424
params := make(map[string]any)
2525

26+
// Use cluster domain from spec, defaulting to "cluster.local" for backward compatibility
27+
clusterDomain := valkey.Spec.ClusterDomain
28+
if clusterDomain == "" {
29+
clusterDomain = "cluster.local"
30+
}
31+
2632
if valkey.Spec.Sentinel != nil && valkey.Spec.Sentinel.Enabled {
2733
params["sentinelEnabled"] = true
28-
params["host"] = fmt.Sprintf("valkey-%s.%s.svc.cluster.local", valkey.Name, valkey.Namespace)
34+
params["host"] = fmt.Sprintf("valkey-%s.%s.svc.%s", valkey.Name, valkey.Namespace, clusterDomain)
2935
params["port"] = 6379
30-
params["sentinelHost"] = fmt.Sprintf("valkey-%s.%s.svc.cluster.local", valkey.Name, valkey.Namespace)
36+
params["sentinelHost"] = fmt.Sprintf("valkey-%s.%s.svc.%s", valkey.Name, valkey.Namespace, clusterDomain)
3137
params["sentinelPort"] = 26379
3238
params["primaryName"] = "myprimary"
3339
} else {
34-
params["primaryHost"] = fmt.Sprintf("valkey-%s-primary.%s.svc.cluster.local", valkey.Name, valkey.Namespace)
40+
params["primaryHost"] = fmt.Sprintf("valkey-%s-primary.%s.svc.%s", valkey.Name, valkey.Namespace, clusterDomain)
3541
params["primaryPort"] = 6379
36-
params["replicaHost"] = fmt.Sprintf("valkey-%s-replicas.%s.svc.cluster.local", valkey.Name, valkey.Namespace)
42+
params["replicaHost"] = fmt.Sprintf("valkey-%s-replicas.%s.svc.%s", valkey.Name, valkey.Namespace, clusterDomain)
3743
params["replicaPort"] = 6379
3844
}
3945

pkg/operator/data/parameters.yaml

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,8 @@ fullnameOverride: {{ $fullname }}
1414
{{- $bindingSecretName = printf "%s-binding" $fullname }}
1515
{{- end }}
1616

17+
{{- $clusterDomain := (dig "clusterDomain" "cluster.local" .) }}
18+
1719
image:
1820
repository: bitnamilegacy/valkey
1921
{{- with .Version}}
@@ -232,6 +234,8 @@ tls:
232234
{{- end }}
233235
{{- end }}
234236

237+
clusterDomain: {{ $clusterDomain }}
238+
235239
networkPolicy:
236240
enabled: true
237241
extraEgress:
@@ -256,27 +260,27 @@ extraDeploy:
256260
secretName: {{ printf "%s-tls" $fullname }}
257261
commonName: {{ $fullname }}
258262
dnsNames:
259-
- '{{ printf "%s.%s.svc.cluster.local" $fullname .Namespace }}'
263+
- '{{ printf "%s.%s.svc.%s" $fullname .Namespace $clusterDomain }}'
260264
- '{{ printf "%s.%s.svc" $fullname .Namespace }}'
261265
- '{{ printf "%s.%s" $fullname .Namespace }}'
262266
- '{{ printf "%s" $fullname }}'
263-
- '{{ printf "*.%s.%s.svc.cluster.local" $fullname .Namespace }}'
267+
- '{{ printf "*.%s.%s.svc.%s" $fullname .Namespace $clusterDomain }}'
264268
- '{{ printf "*.%s.%s.svc" $fullname .Namespace }}'
265269
- '{{ printf "*.%s.%s" $fullname .Namespace }}'
266270
- '{{ printf "*.%s" $fullname }}'
267-
- '{{ printf "%s-primary.%s.svc.cluster.local" $fullname .Namespace }}'
271+
- '{{ printf "%s-primary.%s.svc.%s" $fullname .Namespace $clusterDomain }}'
268272
- '{{ printf "%s-primary.%s.svc" $fullname .Namespace }}'
269273
- '{{ printf "%s-primary.%s" $fullname .Namespace }}'
270274
- '{{ printf "%s-primary" $fullname }}'
271-
- '{{ printf "*.%s-primary.%s.svc.cluster.local" $fullname .Namespace }}'
275+
- '{{ printf "*.%s-primary.%s.svc.%s" $fullname .Namespace $clusterDomain }}'
272276
- '{{ printf "*.%s-primary.%s.svc" $fullname .Namespace }}'
273277
- '{{ printf "*.%s-primary.%s" $fullname .Namespace }}'
274278
- '{{ printf "*.%s-primary" $fullname }}'
275-
- '{{ printf "%s-headless.%s.svc.cluster.local" $fullname .Namespace }}'
279+
- '{{ printf "%s-headless.%s.svc.%s" $fullname .Namespace $clusterDomain }}'
276280
- '{{ printf "%s-headless.%s.svc" $fullname .Namespace }}'
277281
- '{{ printf "%s-headless.%s" $fullname .Namespace }}'
278282
- '{{ printf "%s-headless" $fullname }}'
279-
- '{{ printf "*.%s-headless.%s.svc.cluster.local" $fullname .Namespace }}'
283+
- '{{ printf "*.%s-headless.%s.svc.%s" $fullname .Namespace $clusterDomain }}'
280284
- '{{ printf "*.%s-headless.%s.svc" $fullname .Namespace }}'
281285
- '{{ printf "*.%s-headless.%s" $fullname .Namespace }}'
282286
- '{{ printf "*.%s-headless" $fullname }}'

pkg/operator/operator_suite_test.go

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -360,6 +360,47 @@ var _ = Describe("Deploy Valkey", func() {
360360
}
361361
Expect(bindingSecret.Data).To(Equal(expectedSecretData))
362362
})
363+
364+
It("should deploy Valkey with custom cluster domain", func() {
365+
valkey := &operatorv1alpha1.Valkey{
366+
ObjectMeta: metav1.ObjectMeta{
367+
Namespace: namespace,
368+
Name: "test",
369+
},
370+
Spec: operatorv1alpha1.ValkeySpec{
371+
Replicas: 2,
372+
ClusterDomain: "kube.prod",
373+
},
374+
}
375+
376+
err := cli.Create(ctx, valkey)
377+
Expect(err).NotTo(HaveOccurred())
378+
Eventually(func() error {
379+
if err := cli.Get(ctx, types.NamespacedName{Namespace: valkey.Namespace, Name: valkey.Name}, valkey); err != nil {
380+
return err
381+
}
382+
if valkey.Status.ObservedGeneration != valkey.Generation || valkey.Status.State != component.StateReady {
383+
return fmt.Errorf("again")
384+
}
385+
return nil
386+
}, "10s", "100ms").Should(Succeed())
387+
388+
authSecret := &corev1.Secret{}
389+
err = cli.Get(ctx, types.NamespacedName{Namespace: valkey.Namespace, Name: fmt.Sprintf("valkey-%s", valkey.Name)}, authSecret)
390+
Expect(err).NotTo(HaveOccurred())
391+
392+
bindingSecret := &corev1.Secret{}
393+
err = cli.Get(ctx, types.NamespacedName{Namespace: valkey.Namespace, Name: fmt.Sprintf("valkey-%s-binding", valkey.Name)}, bindingSecret)
394+
Expect(err).NotTo(HaveOccurred())
395+
expectedSecretData := map[string][]byte{
396+
"primaryHost": []byte(fmt.Sprintf("valkey-%s-primary.%s.svc.kube.prod", valkey.Name, valkey.Namespace)),
397+
"primaryPort": []byte("6379"),
398+
"replicaHost": []byte(fmt.Sprintf("valkey-%s-replicas.%s.svc.kube.prod", valkey.Name, valkey.Namespace)),
399+
"replicaPort": []byte("6379"),
400+
"password": authSecret.Data["valkey-password"],
401+
}
402+
Expect(bindingSecret.Data).To(Equal(expectedSecretData))
403+
})
363404
})
364405

365406
func createNamespace() string {

0 commit comments

Comments
 (0)