Bahriya Tersane

Documentation / mysql

NetworkPolicy

The chart renders a Calico projectcalico.org/v3 NetworkPolicy, so it requires Calico, which is the network fabric the Bahriya Kubernetes Engine installs. It is additive to your namespace’s existing policies. Where a namespace blocks cross-namespace ingress by default, this chart adds targeted Allow rules for MySQL pods so traffic from the right sources gets through.

The allowFrom escape hatch keeps the familiar Kubernetes NetworkPolicyPeer input shape (ipBlock / namespaceSelector / podSelector); the chart translates each entry into the equivalent Calico source rule.

Three allow channels, each independently toggleable:

Channel Always-on? Field Purpose
Same-namespace yes (when enabled: true) (built-in) App pods in the same namespace can reach MySQL. Required for the chart’s own phpMyAdmin client and for app workloads colocated with their database.
Ingress controller opt-in allowFromIngressController Kong (or other ingress controller) can route external traffic to MySQL. Required for TCPIngress and any phpMyAdmin ingress that routes from Kong’s namespace.
Arbitrary peers opt-in allowFrom[] Full NetworkPolicyPeer escape hatch — cross-namespace tenants, specific labelled pods, IP blocks.

Same-namespace (default)

When networkPolicy.enabled: true (the default), every pod in the same namespace can connect to MySQL on port 3306 (and the metrics port, if enabled). The rule renders as:

- action: Allow
  protocol: TCP
  source:
    selector: all()
  destination:
    ports: [...]

A Calico source.selector with no namespaceSelector matches every pod and is implicitly scoped to the NetworkPolicy’s own namespace. This covers:

  • App pods deployed alongside MySQL in the same project namespace.
  • GR member-to-member traffic in HA mode.
  • The chart’s own phpMyAdmin client (when client.enabled: true).

No configuration needed.


Ingress controller (Kong)

Enable when MySQL needs to be reachable through Kong — typically for one of:

  • TCPIngress for external MySQL access. Customers connecting their app to MySQL from outside the cluster (over TLS) via a Kong TCP route.
  • phpMyAdmin via Kong from a different namespace. If Kong terminates HTTP for db-foo.example.com and the resulting upstream pod is in your MySQL release’s namespace, Kong needs to be able to reach it.
networkPolicy:
  enabled: true
  allowFromIngressController:
    enabled: true
    namespace: kong              # the namespace Kong runs in
    podLabels:
      app.kubernetes.io/name: kong   # selector for Kong pods

The rule renders as:

- action: Allow
  protocol: TCP
  source:
    namespaceSelector: kubernetes.io/metadata.name == "kong"
    selector: app.kubernetes.io/name == "kong"
  destination:
    ports: [...]

namespaceSelector + selector in the same Calico source are ANDed — only pods matching BOTH the namespace label and the pod labels.

How to find your Kong pod label

# Check what labels Kong pods carry in your install
kubectl get pods -n kong --show-labels
# Look for: app.kubernetes.io/name=kong, app=kong, or a release-specific label

For Konghq Operator installs the labels may include app.kubernetes.io/instance: <KongCluster-name>. Adjust podLabels accordingly — you can list as many key/value pairs as you need; all are ANDed.


Arbitrary cross-namespace peers (allowFrom)

For anything the two convenience channels don’t cover — cross-namespace tenants, shared-services databases, specific pods labelled across the cluster — use the allowFrom escape hatch. Each entry is a standard Kubernetes NetworkPolicyPeer.

Allow an entire namespace

networkPolicy:
  allowFrom:
    - namespaceSelector:
        matchLabels:
          kubernetes.io/metadata.name: shared-services

The well-known label kubernetes.io/metadata.name is set automatically by the kubelet on every namespace, so you don’t have to label namespaces manually. (Requires Kubernetes 1.22+.)

Allow specific pods across the cluster

networkPolicy:
  allowFrom:
    - namespaceSelector: {}      # any namespace
      podSelector:
        matchLabels:
          mysql.bahriya.cloud/access: "yes"

This lets ops label individual pods anywhere in the cluster to grant them MySQL access without changing the chart’s values.

Allow an IP block (e.g. CI runner subnet)

networkPolicy:
  allowFrom:
    - ipBlock:
        cidr: 10.42.0.0/16
        except:
          - 10.42.99.0/24

All three together

A realistic production config might look like:

networkPolicy:
  enabled: true

  allowFromIngressController:
    enabled: true
    namespace: kong
    podLabels:
      app.kubernetes.io/name: kong

  allowFrom:
    - namespaceSelector:
        matchLabels:
          kubernetes.io/metadata.name: monitoring
      podSelector:
        matchLabels:
          app.kubernetes.io/name: netdata
    - namespaceSelector:
        matchLabels:
          kubernetes.io/metadata.name: tenant-foo-production

This permits:

  • Anything in the same namespace (built-in).
  • Kong ingress controller pods.
  • Netdata pods in the monitoring namespace.
  • Everything in tenant-foo-production.

Everything else is blocked by the chart’s NetworkPolicy + the namespace’s default-deny.


Disabling

Two ways:

# (a) Don't render any NetworkPolicy — defer to whatever your namespace ships
networkPolicy:
  enabled: false
# (b) Render the NetworkPolicy but with NOTHING allowed — strict deny mode
networkPolicy:
  enabled: true
  allowFromIngressController:
    enabled: false
  allowFrom: []
# (Note: same-namespace allow is hard-coded when enabled is true; if you
# want strict deny including same-namespace, set enabled: false and write
# your own NetworkPolicy alongside the release.)

Debugging

If a client can’t reach MySQL after upgrade:

# 1. Confirm the policy exists and what it selects
kubectl get networkpolicy -n <NS> <release>-mysql -o yaml

# 2. Spin up a debug pod in the suspect source namespace
kubectl run -it --rm dbg --image=busybox -n <SOURCE_NS> --restart=Never -- sh
nc -zv <release>-mysql.<NS>.svc.cluster.local 3306
# Connection times out → policy is blocking; success → policy is OK, look elsewhere

# 3. Check that the source pod's namespace has the expected label
kubectl get namespace <SOURCE_NS> --show-labels
# Look for kubernetes.io/metadata.name=<SOURCE_NS> (auto-set on 1.22+)

# 4. If using podLabels in allowFromIngressController, verify Kong's labels
kubectl get pods -n kong --show-labels