Skip to main content

Connecting to MySQL

How a developer reaches the in-cluster Percona MySQL from their laptop using Sequel Ace, an Auth0-backed kubeconfig, and kubectl port-forward.

The cluster MySQL is not exposed publicly. You tunnel through the Kubernetes API server, which authenticates you via Auth0 and authorises you via namespace-scoped RBAC.

Prerequisites​

  1. You're a member of the k8s-cluster-dev-group Auth0 group. Ask DevOps if you're not.

  2. You have access to the persona-mysql project in Infisical (at least the prod environment, scope /cluster/). That's where the user passwords live.

  3. Install the tooling:

    brew install kubectl
    brew install int128/kubelogin/kubelogin # provides `kubectl oidc-login`
    brew install --cask sequel-ace
  4. Drop the shared kubeconfig at ~/.kube/config:

    curl -o ~/.kube/config \
    https://gitlab.com/onyourmarks/k8s/oym-k8s-cluster/-/raw/main/k8s/kubeconfig

Log in​

The kubeconfig is configured to delegate authentication to Auth0 via kubectl oidc-login. The first command you run will pop a browser:

kubectl get pods -n percona-pxc-operator

Log in with your Auth0 account. The token is cached in your macOS Keychain; you won't be prompted again until it expires.

If the command lists pods, you're in. If you get Forbidden, your Auth0 account is not in the k8s-cluster-dev-group — ask DevOps to add you.

Start the tunnel​

kubectl -n percona-pxc-operator port-forward svc/persona-mysql-haproxy 3307:3306

Leave that command running. We use 3307 locally so it doesn't clash with a MySQL you might have running on 3306 for local dev.

Sequel Ace settings​

Create a new connection (Standard tab):

FieldValue
Host127.0.0.1
Usernamepersona-dev, persona-stg, or persona-prod
Passwordfrom Infisical (see below)
Port3307
Databaseleave empty — you'll pick after connecting

Each user is locked to its own database prefix and to data, not schema:

UserCan accessCan do
persona-devdatabases named dev-*read and write rows, export dumps
persona-stgdatabases named stg-*read and write rows, export dumps
persona-proddatabases named prod-*read and write rows, export dumps

The grant is SELECT, INSERT, UPDATE, DELETE, LOCK TABLES, SHOW VIEW, CREATE TEMPORARY TABLES. CREATE, ALTER, DROP, TRUNCATE and index changes are refused with command denied, and so is importing a dump in Sequel Ace, because a dump starts with CREATE TABLE. Schema work and imports go through the scripts below.

Where the passwords live​

Open Infisical → project persona-mysql → environment prod → folder /cluster/. The relevant keys:

UserInfisical key
persona-devPERSONA_MYSQL_PASSWORD_DEV
persona-stgPERSONA_MYSQL_PASSWORD_STAGING
persona-prodPERSONA_MYSQL_PASSWORD_PROD

Don't paste passwords into Slack, tickets, or commit them — Sequel Ace can store them in your macOS Keychain via "Add to Favorites".

Imports and schema changes​

The port-forward is for looking at and fixing data. Dumps and schema changes go through the scripts in scripts/, which talk to the cluster's write node as root and know the rules of a Galera cluster:

scripts/db-copy prod-my-project stg-my-project # refresh staging from production: drops every table in staging, streams production in
scripts/db-export prod-my-project # local gzip dump, for development or before a risky change
scripts/db-import stg-my-project dump.sql.gz # stream a dump in; add --replace to drop every table first
scripts/db-shell stg-my-project # root mysql shell for ad-hoc DDL

All of them read the root password from Infisical → project persona-mysql → prod → /cluster/ → root, talk to the cluster's write node directly, rewrite ENGINE=MyISAM to InnoDB on the way in, and refuse to write while the cluster is not whole. Writing into a prod-* database with db-copy or db-import --replace needs --force. Why not just import in Sequel Ace: see MySQL (Galera).

After copying production into staging for a Craft project nothing else is needed: the project config and site URLs come from the environment, and the next deploy's craft up (or php craft project-config/apply in the pod) applies the staging config.

Production access​

Only DevOps and people with a current operational need should hold the persona-prod password. If you find yourself reaching for it for a one-off read-only query, ask whether the same answer is available in Grafana or a staging copy first.

Troubleshooting​

Forbidden when running kubectl: your Auth0 group membership isn't flowing through. Log out (kubectl oidc-login clean) and back in.

bind: address already in use: something is already on local 3307. Either kill the other process or pick a different local port (3308:3306).

Connection refused in Sequel Ace: the port-forward command stopped. Check the terminal you started it in — it dies if the pod is rescheduled. Restart it.

Access denied for user 'persona-dev': wrong password, or you're trying to query a database the user doesn't have grants on (e.g. persona-dev opening a stg-* schema).