TL;DR
- Kubernetes has no built-in database GUI — the standard
kubectl port-forwardapproach dies when your terminal closes and must be re-established every session.- Deploying pgAdmin or phpMyAdmin as a pod inside your cluster adds 100-256 MB of RAM overhead, creates another workload to secure, and still requires Ingress or LoadBalancer configuration.
- DBEverywhere connects to K8s-hosted databases from outside the cluster through a static IP you whitelist once — full browser-based GUI, no kubectl required, no pods to manage.
- Free tier: 5 sessions/month, 20-minute timeout. Paid: $5/mo for unlimited sessions, saved connections, and SSH tunnel support.
Table of Contents
- The Kubernetes database GUI problem
- How databases run inside Kubernetes
- Method 1: kubectl port-forward + desktop client
- Method 2: Deploy a database GUI as a pod
- Method 3: Browser-based GUI with static IP whitelisting
- Comparison: all three approaches
- Step-by-step: Connecting to a K8s database with DBEverywhere
- When your database outgrows in-cluster management
- FAQ
Kubernetes Database Management: How to Browse Data in K8s-Hosted Databases
Running databases inside Kubernetes has gone from controversial to commonplace. The 2024 Data on Kubernetes Report found that 48% of organizations now run stateful workloads including databases on Kubernetes, up from 38% the year prior. Operators like CloudNativePG, Zalando's Postgres Operator, and Oracle's MySQL Operator have matured to the point where running PostgreSQL and MySQL on K8s is no longer a fringe choice. But there is a gap that none of these operators fill: giving you a Kubernetes database GUI to actually browse, query, and manage the data inside those databases.
Kubernetes is built around declarative manifests, CLI tools, and API access. That works well for application deployment. It does not work well when you need to look at a row in your orders table, debug a failing migration, or export a quick SQL dump before a schema change. For those tasks, you need a visual interface — and Kubernetes makes getting one surprisingly difficult.
This article walks through three approaches to K8s database management: the built-in CLI workaround, deploying a GUI tool as a pod, and connecting an external browser-based tool through a static IP. Each has real trade-offs in setup complexity, ongoing cost, and security posture.
How databases run inside Kubernetes
Before comparing GUI options, it helps to understand why database access inside Kubernetes is fundamentally different from a traditional VM setup.
On a standard VPS or managed database service, your database has an IP address. You point your GUI tool at that IP, authenticate, and you are in. Kubernetes adds three layers of abstraction between you and your database:
Pods are ephemeral. Your database runs inside a pod that can be rescheduled to a different node at any time. The pod's IP address changes when this happens. You never connect to a pod IP directly for persistent access.
Services provide stable endpoints — but only inside the cluster. A ClusterIP Service gives your database a stable DNS name (e.g., postgres.default.svc.cluster.local) and virtual IP, but this is only routable from within the cluster network. According to the Kubernetes documentation, ClusterIP is the default Service type and is intentionally not externally accessible.
Network policies restrict traffic. Production clusters commonly enforce network policies that limit which pods can communicate. Even if you deploy a GUI tool inside the cluster, it may not reach your database pod without explicit policy rules.
The result: your database is reachable from your application pods (which are configured with the right Service DNS and credentials) but not from your laptop, your browser, or any external tool.
Method 1: kubectl port-forward + desktop client
The most common way to get kubectl database access is port forwarding. You create a tunnel from your local machine to the database pod or Service:
# Forward local port 5432 to the postgres Service
kubectl port-forward svc/postgres 5432:5432 -n database
# Or for MySQL
kubectl port-forward svc/mysql 3306:3306 -n database
Then you connect a desktop client (pgAdmin, DBeaver, MySQL Workbench, TablePlus) to localhost:5432 or localhost:3306.
What works:
- No changes to your cluster configuration
- Traffic is encrypted through the Kubernetes API server
- Zero cost — uses existing kubectl access
What does not work:
The tunnel dies when your terminal closes. This is the single biggest complaint. Close your laptop lid, lose your WiFi for 30 seconds, or accidentally close the terminal tab — the port-forward drops and your database client disconnects. There is no built-in reconnection. A 2023 GitHub issue requesting persistent port-forwarding has 600+ thumbs-up reactions and remains open.
Every developer needs kubectl configured. To run kubectl port-forward, each person needs the Kubernetes CLI installed, a valid kubeconfig file with credentials for the target cluster, and the correct RBAC permissions. According to the 2024 CNCF Survey, organizations run an average of 3.4 Kubernetes clusters — which means managing kubeconfig contexts across multiple clusters for every developer who needs database access.
Every developer also needs a desktop client. On top of kubectl, you need pgAdmin, DBeaver, MySQL Workbench, or another GUI tool installed locally. That is two tools minimum, both with their own setup and update requirements.
It does not work on restricted devices. Corporate laptops with locked-down software policies, tablets, borrowed machines, or any device where you cannot install kubectl and a database client — no access. BYOD policies and remote work have made this a real constraint for 72% of organizations that now support hybrid or remote work arrangements (Gartner, 2024).
No shared access pattern. If five developers need database access, each one sets up port-forwarding independently. There is no centralized audit trail, no shared connection configuration, and no way to revoke access without modifying cluster RBAC.
Method 2: Deploy a database GUI as a pod
Since ClusterIP Services are reachable from within the cluster, you can deploy a database management tool as another pod. For MySQL databases, phpMyAdmin is common. For PostgreSQL, pgAdmin. For both, Adminer works as a lightweight alternative.
Here is a minimal Kubernetes deployment for pgAdmin:
apiVersion: apps/v1
kind: Deployment
metadata:
name: pgadmin
namespace: database
spec:
replicas: 1
selector:
matchLabels:
app: pgadmin
template:
metadata:
labels:
app: pgadmin
spec:
containers:
- name: pgadmin
image: dpage/pgadmin4:latest
env:
- name: PGADMIN_DEFAULT_EMAIL
value: "admin@yourcompany.com"
- name: PGADMIN_DEFAULT_PASSWORD
valueFrom:
secretKeyRef:
name: pgadmin-secret
key: password
resources:
requests:
memory: "256Mi"
cpu: "250m"
limits:
memory: "512Mi"
cpu: "500m"
ports:
- containerPort: 80
You then need a Service and either an Ingress or LoadBalancer to make it accessible from outside the cluster. Add TLS termination, authentication, and you have a browser-based database GUI.
What works: - Browser-based — accessible from any device with a web browser - Direct cluster network access to database Services - Familiar pgAdmin/phpMyAdmin interface with full feature set
What does not work:
Resource overhead. pgAdmin 4 is a Python web application that requires a minimum of 256 MB RAM to function reliably. The official Docker image documentation recommends 512 MB for production use. phpMyAdmin is lighter at roughly 128 MB, but both consume CPU cycles and memory that could serve your actual application. On managed Kubernetes services where you pay per node, this overhead translates directly to cost — roughly $3-8/month depending on your provider and resource allocation.
Another workload to secure. You have now deployed a web application with direct database access, exposed to the internet through your Ingress controller. According to the 2024 Kubernetes Security Report by Red Hat, 67% of organizations have experienced a security incident related to Kubernetes in the past 12 months, with misconfiguration being the leading cause. A pgAdmin deployment with weak credentials or misconfigured Ingress rules becomes an attack vector. The phpMyAdmin security risks we have documented apply equally to any self-hosted database GUI inside a cluster.
Another workload to maintain. Docker images need updating. Secrets need rotating. PersistentVolumeClaims need provisioning if you want pgAdmin to remember your server configurations across pod restarts. Network policies need updating to allow the GUI pod to reach your database pods. This is not a one-time setup — it is ongoing operational work.
Shared credential problem. If multiple developers use the same pgAdmin deployment, they either share the admin password (a security anti-pattern) or you configure LDAP/OAuth integration (adding significant complexity). There is no simple per-user isolation.
Method 3: Browser-based GUI with static IP whitelisting
DBEverywhere provides hosted phpMyAdmin and Adminer as a service — a Kubernetes database GUI you access from any browser without deploying anything into your cluster. It connects from a static IP address that you whitelist in your database's access configuration.
For K8s-hosted databases, this means exposing your database Service through a LoadBalancer or NodePort, restricted to DBEverywhere's static IP. Your database is not open to the internet — it accepts connections from exactly one known external address.
For databases in private clusters with no external exposure at all, DBEverywhere's paid tier supports SSH tunnel connections. You configure a bastion host (which can be another pod with SSH access) and DBEverywhere tunnels through it to reach your database.
What works: - Zero pods to deploy, zero cluster resources consumed - Browser-based — works from any device, any location - Each user has their own account — no shared credentials for the GUI itself - Static IP makes firewall rules simple and auditable
What does not work: - Requires exposing your database port externally (restricted to one IP) or setting up an SSH bastion - Database credentials are entered per session (unless saved on the paid tier) - Dependent on a third-party service — if DBEverywhere is down, you lose GUI access
Comparison: all three approaches
| Factor | kubectl port-forward | GUI pod (pgAdmin/phpMyAdmin) | DBEverywhere |
|---|---|---|---|
| Setup time | 5 min per developer, per session | 1-2 hours (Deployment + Ingress + TLS) | 10-15 min (one-time) |
| Monthly cost | Free | $3-8/mo (cluster resources) | Free / $5/mo |
| Cluster resources used | None | 256-512 MB RAM, 0.25-0.5 CPU | None |
| Requires CLI tools | Yes (kubectl + desktop client) | No (browser) | No (browser) |
| Works on any device | No | Yes | Yes |
| Persistent connection | No (dies with terminal) | Yes (always-on pod) | Yes (connect anytime) |
| Multi-user access | Each user sets up independently | Shared instance or complex auth | Each user has own account |
| Maintenance burden | None | Ongoing (updates, secrets, policies) | None |
| Supports MySQL + Postgres | Depends on desktop client | Separate tools per engine | Yes (phpMyAdmin + Adminer) |
Step-by-step: Connecting to a K8s database with DBEverywhere
Here is the process for exposing a Kubernetes database through a LoadBalancer Service restricted to a single IP.
Step 1: Create a LoadBalancer Service for your database.
apiVersion: v1
kind: Service
metadata:
name: postgres-external
namespace: database
annotations:
# For cloud providers that support load balancer source ranges:
service.beta.kubernetes.io/load-balancer-source-ranges: "<DBEverywhere-Static-IP>/32"
spec:
type: LoadBalancer
selector:
app: postgres
ports:
- port: 5432
targetPort: 5432
The load-balancer-source-ranges annotation restricts traffic at the cloud load balancer level. This is supported on AWS (ELB/NLB), GCP, Azure, and DigitalOcean managed Kubernetes services. Only traffic from DBEverywhere's static IP reaches your database.
Step 2: Apply the Service and get the external IP.
kubectl apply -f postgres-external-service.yaml
kubectl get svc postgres-external -n database
Wait for the EXTERNAL-IP field to populate. This is the address you will enter in DBEverywhere.
Step 3: Verify the restriction.
From your local machine, try connecting to the external IP on the database port. It should time out or be refused — confirming that only the whitelisted IP can connect.
Step 4: Connect through DBEverywhere.
- Go to dbeverywhere.com and sign up.
- Click Connect and select your database engine (PostgreSQL or MySQL).
- Enter the external IP from Step 2, port, credentials, and database name.
- Enable SSL/TLS if your database is configured for it (recommended).
- Click Connect.
You now have a full GUI — table browsing, data editing, SQL queries, data export — from any browser, on any device.
Alternative: SSH tunnel approach (paid tier).
If you do not want any external LoadBalancer, deploy a lightweight SSH bastion pod in your cluster and use DBEverywhere's SSH tunnel feature to reach the internal ClusterIP Service. This keeps your database completely private. See our SSH tunnel guide for the full walkthrough.
When your database outgrows in-cluster management
Running databases inside Kubernetes works well at small to medium scale. But as your data grows, many teams migrate to managed database services — AWS RDS, Google Cloud SQL, DigitalOcean Managed Databases — while keeping their applications on K8s. The 2024 Data on Kubernetes Report notes that 37% of organizations use a mix of in-cluster and managed databases, choosing the right tool for each workload.
When your database moves outside the cluster, the GUI access problem actually gets simpler. Managed database services typically provide a public endpoint (restricted by IP allowlist or VPC peering), which means connecting a browser-based tool like DBEverywhere is straightforward — add the static IP to your managed database's allowlist and connect. No kubectl, no pods, no LoadBalancer configuration.
The tooling you choose for K8s database management today should work regardless of where your database lives tomorrow. A browser-based approach that connects through a standard TCP connection — whether to an in-cluster LoadBalancer, a managed service endpoint, or through an SSH tunnel — avoids locking your workflow to Kubernetes-specific mechanisms like kubectl port-forward.
FAQ
Does DBEverywhere support both MySQL and PostgreSQL on Kubernetes?
Yes. DBEverywhere provides phpMyAdmin for MySQL/MariaDB databases and Adminer for PostgreSQL (plus other engines like SQLite and SQL Server). Since Kubernetes clusters commonly run both MySQL and PostgreSQL — often managed by different operators like CloudNativePG for Postgres and Oracle's MySQL Operator for MySQL — a single tool that handles both engines eliminates the need to deploy separate GUI pods for each database type.
Is it safe to expose my Kubernetes database through a LoadBalancer?
Exposing a database port to the entire internet is not recommended. But restricting the LoadBalancer to a single IP through load-balancer-source-ranges limits the attack surface to one known endpoint. Combined with strong database credentials, SSL/TLS encryption, and role-based database users (not the superuser), this is comparable in security to the kubectl port-forward approach. The connection is encrypted, authenticated, and restricted to a single source. For zero external exposure, use the SSH tunnel approach on DBEverywhere's paid tier.
Can I use the free tier for occasional debugging?
Yes. The free tier provides 5 sessions per month with a 20-minute timeout per session. For checking data after a deployment, debugging a migration issue, or verifying a backup — the typical "I just need to look at the database for a few minutes" scenario — 5 sessions is usually sufficient. Each session gives you full Adminer or phpMyAdmin access for up to 20 minutes. The paid tier ($5/month) provides unlimited sessions with an 8-hour timeout and saved connections so you do not re-enter credentials each time.
What about Kubernetes-native tools like Lens or k9s?
Lens and k9s are excellent tools for managing Kubernetes resources — pods, deployments, services, logs. They do not provide a database GUI. You can use them to inspect your database pod's logs or resource usage, but you cannot browse tables, run SQL queries, or export data through them. They solve a different problem (cluster management) than what a Kubernetes database GUI addresses (data management).
Do I need to modify my existing database deployment?
The database deployment itself stays unchanged. You only add a new Service resource (LoadBalancer type) that points to your existing database pods. Your application continues using the internal ClusterIP Service. The external LoadBalancer Service is a separate entry point restricted to DBEverywhere's static IP. You can delete it at any time without affecting your application's database connectivity.
Conclusion
Kubernetes is a powerful platform for running applications, and increasingly, for running databases. What it does not provide is a way to visually interact with the data inside those databases. The kubectl port-forward workflow is fragile and device-dependent. Deploying pgAdmin or phpMyAdmin as a pod adds resource overhead and operational complexity. Neither approach gives you the straightforward, browser-based database access that developers expect.
DBEverywhere connects to your K8s-hosted database from outside the cluster through a static IP you whitelist once. No pods to deploy, no kubectl to run, no desktop clients to install. It works from any browser, on any device, whether your database runs on PostgreSQL, MySQL, or MariaDB.
The free tier covers occasional debugging with 5 sessions per month. The paid tier at $5/month handles daily use with unlimited sessions, 8-hour timeouts, SSH tunnel support for fully private databases, and saved connections across all your clusters.
Kubernetes made deploying applications declarative and repeatable. Browsing the data behind those applications should not require a terminal that stays open.
Try DBEverywhere free — connect to your Kubernetes database in 60 seconds
Try DBEverywhere Free
Access your database from any browser. No installation, no Docker, no SSH tunnels.
Get Started