Documentation / valkey
Network and exposure
How the chart’s NetworkPolicy interacts with a namespace’s existing policies, and how to open ValKey up to other namespaces or external clients.
The policies you’re layering on
The chart’s NetworkPolicy is a Calico projectcalico.org/v3 resource, so it requires Calico, which is the network fabric the Bahriya Kubernetes Engine installs. It adds Allow rules; it never subtracts. Where a namespace already has a baseline policy, the result is the union of the two: if either matches, traffic flows, and there is nothing to disable on the baseline side.
The chart does not restrict egress, so a calling app in app-prod can dial vk-valkey.valkey-prod.svc.cluster.local:6379 without any configuration on the calling side, unless its own namespace restricts egress.
Three reachability scenarios
1. Same-namespace clients
Default state, no values needed. Both the baseline NP and the chart NP (networkPolicy.openByDefault: true) allow ingress from any Pod in ValKey’s namespace.
2. Cross-namespace clients
Add the calling namespace(s) to networkPolicy.allowFromNamespaces. Each entry is a matchLabels block used as a namespaceSelector:
networkPolicy:
allowFromNamespaces:
- kubernetes.io/metadata.name: app-prod
- kubernetes.io/metadata.name: app-staging
The auto-managed kubernetes.io/metadata.name label is available on every namespace in K8s ≥ 1.21 — no platform-side labelling is required. To allowlist by some other label scheme:
networkPolicy:
allowFromNamespaces:
- team: orders
- environment: production
matchLabels is AND-combined within an entry, so combine if needed:
networkPolicy:
allowFromNamespaces:
- team: orders
environment: production # this entry matches namespaces with BOTH labels
That’s it on the receiving side. The calling app dials <release>.<valkey-namespace>.svc.cluster.local:6379 and the connection succeeds because:
- Nothing in the chart restricts egress from
app-prod. - Even where a baseline policy in
valkey-prodblocks cross-namespace ingress by default, the chart’s NP adds an allow rule forapp-prod, and Calico NetworkPolicies are additive, so the traffic is allowed.
3. External clients via Kong
Enable when external systems (CI runners, ops tooling, partners, mobile/edge clients) need to reach ValKey from outside the cluster. The chart renders a Kong TCPIngress resource that routes SNI-based traffic to ValKey’s primary Service, with IP allowlisting via the Kong ip-restriction plugin.
tls:
enabled: true # REQUIRED — Kong does SSL passthrough; ValKey terminates
exposure:
external:
enabled: true
host: "valkey.example.com"
ingressClassName: "kong"
ipAllowlist: # REQUIRED — empty list is refused at render time
- "203.0.113.0/24"
- "198.51.100.42/32"
Three guards fire at template time if you forget any of these:
| Missing value | Error |
|---|---|
exposure.external.host |
“host is required when exposure.external.enabled” |
exposure.external.ipAllowlist empty |
“must be a non-empty list — ValKey on the public internet without an IP allowlist is unsafe” |
tls.enabled: false |
“tls.enabled must be true — Kong uses SSL passthrough so ValKey itself must terminate TLS” |
The chart renders:
- A
configuration.konghq.com/v1beta1TCPIngressmatching the SNI hostname to the primary Service on the data port. - A
configuration.konghq.com/v1KongPluginof typeip-restrictionwith the allowlist, attached to the TCPIngress via thekonghq.com/plugins: ip-whitelist-<release>annotation. - An additional ingress rule on the chart’s NetworkPolicy allowing the Kong proxy Pods to reach ValKey.
- The external hostname is added to the chart-generated TLS certificate’s SAN list so client TLS handshakes succeed.
Kong cluster prerequisites
The chart renders the resources but Kong must be configured to handle them:
-
Stream listener — Kong proxy needs
KONG_STREAM_LISTENto include a TLS port inssl_prereadmode. Typical config in the Kong Helm release:env: stream_listen: "0.0.0.0:6379 ssl ssl_preread"ssl_prereadmeans Kong reads the SNI from ClientHello without terminating TLS; it then forwards the raw encrypted bytes to ValKey, which decrypts. No certificate is configured on the Kong side for that listener. -
TCPIngress watching — the Kong Ingress Controller must be configured to watch
TCPIngressresources. This is on by default in KIC ≥ 2.0. -
DNS — point
valkey.example.comat Kong’s external LB, using the same record pattern as your other services. -
Cluster-mode caveat —
TCPIngressroutes to a single Service. In cluster mode, the primary Service load-balances across cluster Pods, which is fine for the data port (any Pod redirects via MOVED), but clients must be cluster-aware. Sentinel-aware clients should NOT route writes via Kong/TCPIngress — use a Sentinel SDK over the cross-namespace path instead.
Client connection (external)
valkey-cli --tls \
--cacert /path/to/valkey-ca.crt \
-h valkey.example.com \
-p 6379 \
-a "$VALKEY_PASSWORD" \
PING
Self-signed cert generated by the chart has the external hostname in its SAN list, so client cert verification just works. If you prefer a publicly trusted cert, set tls.existingSecret to a cert-manager-issued Secret whose cert covers exposure.external.host.
Disabling
exposure:
external:
enabled: false
The TCPIngress + KongPlugin are removed on helm upgrade. The auto-added NP rule for Kong is removed too. ValKey reverts to in-cluster-only reachability.
Manual escape hatch — raw peer entries
For anything not covered by the shortcuts (IP blocks, label-AND-podSelector combinations, cross-cluster CIDRs), use networkPolicy.allowFrom. Entries keep the familiar Kubernetes NetworkPolicyPeer shape (ipBlock / namespaceSelector / podSelector) and the chart translates each one into an equivalent Calico source rule (ipBlock → nets/notNets, selectors → Calico selector expressions):
networkPolicy:
allowFrom:
- ipBlock:
cidr: 10.42.0.0/16
except:
- 10.42.99.0/24
- namespaceSelector:
matchLabels:
tier: trusted
podSelector:
matchLabels:
allowed-to-talk-to-valkey: "true"
Each entry is rendered as one additional Calico ingress rule (source: + destination.ports) covering the data port (and sentinel/metrics ports as relevant).
Debugging “I can’t reach ValKey”
Walk the path in order:
- DNS —
kubectl exec -n <caller-ns> <pod> -- nslookup vk-valkey.<valkey-ns>.svc.cluster.local. If DNS fails, the chart’s Services aren’t matching Pods — check Pod labels. - Network reachability —
kubectl exec -n <caller-ns> <pod> -- nc -zv vk-valkey.<valkey-ns>.svc.cluster.local 6379. If this hangs, a NetworkPolicy is dropping packets. - Confirm caller’s egress — the caller’s namespace may have its own egress-restricting policy.
kubectl get netpol -n <caller-ns>. - Confirm ValKey’s ingress —
kubectl describe netpol -n <valkey-ns> vk-valkey. TheAllowing ingress traffic:section lists every accepted source. Cross-reference the caller’s labels. - TLS — if connection establishes but
valkey-clireturnsunable to verifyorbad handshake, the caller’s CA bundle is wrong. Mount the chart’s<release>-tls-caConfigMap (ca.crt). - Auth —
WRONGPASSmeans password mismatch;NOAUTHmeans auth is on but the client didn’t send a password.