External database
| Enterprise | ||||
|---|---|---|---|---|
| Available in these plans | Free | Dev | Prod | Scale |
| External Database | ||||
| External Database Kerberos Authentication | ||||
| External Database RDS IAM Authentication | ||||
This feature is an Enterprise feature. See our pricing plans or contact our sales team for more information.
Introduction​
This guide explains how to configure an external database as the backing store for a tenant cluster. A backing store is a persistent storage solution that maintains the state and data of the tenant cluster. Using an external database can provide better performance, scalability, and data persistence compared to the default embedded storage.
Configure this feature to use an external database such as MySQL or PostgreSQL for your tenant cluster's backing store.
controlPlane:
backingStore:
database:
external:
enabled: true
dataSource: CONNECTION_STRING
connector: CONNECTOR_STRING
Prerequisites​
Before configuring an external database for your tenant cluster, ensure you have the following prerequisites based on your chosen method:
Data source (direct connection)​
- A running MySQL or PostgreSQL database server
- admin credentials and connection string for the database
- Network connectivity from the tenant cluster to the database server
Connector (platform-managed)​
The connector method requires the vCluster Platform to be installed and properly configured. This must be completed by an administrator before using external databases.
- vCluster Platform installation: The platform must be installed and accessible in your Kubernetes cluster
- Database connector secret: A platform administrator must create a database connector secret
- Platform API key: Your tenant cluster must be connected to the platform
The connector option provides automatic database provisioning, credential management, and cleanup when the tenant cluster is deleted. The dataSource option gives you direct control but requires manual database and user management.
Connector and data source​
There are two mutually exclusive options for using an external backing store.
dataSource: assign a connection string to dataSource that the tenant cluster uses for its control plane backing store.
connector: assign a name of a connector secret that exists in an instance of the platform in the installed namespace. The platform uses the secret to automatically provision a separate database within the database server for the tenant cluster. It also creates a non-privileged user that can only interact with the tenant cluster's database. The tenant cluster receives a connection string built from the user and database.
| Connector | DataSource | |
|---|---|---|
| MySQL Support | Yes | Yes |
| PostgreSQL Support | Yes | Yes |
| Share Across tenant clusters | Yes | No |
| Automatic DB Cleanup | Yes | No |
| Credential stored in secret | Yes | No |
Datasource configuration​
Replace CONNECTION_STRING with the connection string for your database. Examples:
- PostgreSQL:
postgres://username:password@hostname:5432/vcluster-db - MySQL:
mysql://root:password@tcp(192.168.86.9:3306)/vcluster
For passwordless authentication to PostgreSQL with a mounted keytab, see Authenticate to PostgreSQL with Kerberos.
Connector configuration​
After completing the prerequisites, reference the connector secret in your tenant cluster configuration:
controlPlane:
backingStore:
database:
external:
enabled: true
connector: my-database-connector # Name of the connector secret created above
The tenant cluster must be connected to the platform to use the connector. This enables centralized management and monitoring of tenant clusters.
Authenticate to PostgreSQL with Kerberos (GSSAPI)​
When you use an external PostgreSQL dataSource, the tenant cluster's kine connects to your PostgreSQL backend. Instead of a static password in the connection string, that connection can authenticate with Kerberos/GSSAPI using a mounted keytab. This suits enterprises that already operate a Kerberos realm (an MIT KDC or Active Directory) and require Kerberos for all database access.
Authentication relies on existing vcluster.yaml values. A passwordless dataSource carries the client principal and points at a mounted keytab. The generic controlPlane.statefulSet volume, mount, and environment values mount the keytab and krb5.conf into the control plane pod. No Kerberos-specific fields are required.
This applies to the data source path against PostgreSQL only. Kerberos is not used by the connector path, and GSSAPI is a PostgreSQL feature, so it does not apply to MySQL.
GSSAPI support ships in the kine binary carried by the stock Kubernetes distro image from v1.36 onward. The vCluster release itself is unchanged: set controlPlane.distro.k8s.image to a v1.36 or later tag, as shown in Step 4. Earlier distro images carry a kine build without GSSAPI and fail against a Kerberos data source.
Prerequisites​
Before you begin, ensure you have:
- A tenant cluster running the Kubernetes distro image at v1.36 or later (see the admonition above).
- An existing Kerberos environment:
- A KDC and realm (for example
EXAMPLE.COM). - A client principal for the tenant cluster, for example
krb5-db-user@EXAMPLE.COM, that you can export to a keytab.
- A KDC and realm (for example
- A PostgreSQL server built with GSSAPI support, reachable from the control plane cluster at a stable fully qualified domain name (FQDN), with:
- The service principal
postgres/<postgres-fqdn>@REALMpresent in the server's keytab and referenced bykrb_server_keyfile. - A
pg_hba.confrule that authenticates the connection withgss. - A login role and database that the client principal maps to (see Step 2).
- The service principal
Step 1 - Create the database principal and export a keytab​
Create the client principal in your KDC and export it to a keytab file. With MIT Kerberos, use kadmin:
kadmin -q "addprinc -randkey krb5-db-user@EXAMPLE.COM"
kadmin -q "ktadd -k krb5-db-user.keytab krb5-db-user@EXAMPLE.COM"
This produces a krb5-db-user.keytab file containing credentials for the principal. Keep this file secure. Anyone holding it can authenticate as the principal.
Step 2 - Create the PostgreSQL role and database​
Create a passwordless login role whose name matches the principal's short name and a database the role can use. Because the pg_hba.conf rule below uses include_realm=0, PostgreSQL strips the @REALM suffix, so the principal krb5-db-user@EXAMPLE.COM maps to the role krb5-db-user.
CREATE ROLE "krb5-db-user" LOGIN;
CREATE DATABASE kubernetes OWNER "krb5-db-user";
Point PostgreSQL at its service keytab in postgresql.conf:
krb_server_keyfile = '/etc/postgres-keytab/krb5.keytab'
Add a gss rule to pg_hba.conf so remote TCP connections from the tenant cluster authenticate over Kerberos. PostgreSQL uses the first matching pg_hba.conf rule, so place this rule before broader host rules that use another authentication method. Scope the address range to the tenant cluster network where possible:
host all all 0.0.0.0/0 gss include_realm=0 krb_realm=EXAMPLE.COM
krbsrvname in the data source (Step 4) selects the postgres service principal, and krb_realm restricts which realm's principals the rule accepts. Keep include_realm=0 and the role name aligned, otherwise the mapped role will not match and the connection is rejected.
Step 3 - Create the keytab Secret and krb5.conf ConfigMap​
Create a Kubernetes Secret holding the client keytab and a ConfigMap holding the client krb5.conf, both in the tenant cluster's host namespace (for example vcluster-my-vcluster). The control plane pod mounts them in Step 4.
kubectl create secret generic kine-keytab \
--from-file=krb5.keytab=krb5-db-user.keytab \
--namespace vcluster-my-vcluster
Write a local krb5.conf file that points at your KDC. When your service DNS names lack matching PTR records, disable DNS canonicalization and reverse lookups so the service principal name matches the host the tenant cluster connects to:
[libdefaults]
default_realm = EXAMPLE.COM
dns_lookup_realm = false
dns_lookup_kdc = false
dns_canonicalize_hostname = false
rdns = false
[realms]
EXAMPLE.COM = {
kdc = kdc.example.com
admin_server = kdc.example.com
}
Create the ConfigMap from that file:
kubectl create configmap krb5-conf \
--from-file=krb5.conf=krb5.conf \
--namespace vcluster-my-vcluster
Step 4 - Configure the vcluster.yaml file​
Pin the distro image to a GSSAPI-capable build, set the passwordless Kerberos data source, and mount the keytab and krb5.conf into the control plane pod through controlPlane.statefulSet. The data source carries no password. The principal lives in the user part of the connection string, krb5_keytab points at the mounted keytab, and krbsrvname selects the PostgreSQL service principal.
controlPlane:
distro:
k8s:
image:
registry: ghcr.io
repository: loft-sh/kubernetes
# GSSAPI-capable kine ships in the stock distro from v1.36.
tag: v1.36.1
backingStore:
database:
external:
enabled: true
# Passwordless GSSAPI data source. The principal in the user part is
# URL-encoded (@ becomes %40); krb5_keytab points at the mounted keytab.
dataSource: "postgres://krb5-db-user%40EXAMPLE.COM@postgres.example.com:5432/kubernetes?sslmode=disable&krbsrvname=postgres&krb5_keytab=/etc/kine-keytab/krb5.keytab"
statefulSet:
# KRB5_CONFIG tells the GSSAPI client where to read the realm configuration.
env:
- name: KRB5_CONFIG
value: /etc/krb5.conf
# Mount the client keytab and krb5.conf into the control plane pod.
persistence:
addVolumes:
- name: kine-keytab
secret:
secretName: kine-keytab
- name: krb5-conf
configMap:
name: krb5-conf
addVolumeMounts:
- name: kine-keytab
mountPath: /etc/kine-keytab
readOnly: true
- name: krb5-conf
mountPath: /etc/krb5.conf
subPath: krb5.conf
readOnly: true
The principal in the data source user part must be URL-encoded. Write the @ between the principal and the realm as %40 (for example krb5-db-user%40EXAMPLE.COM). The data source host must exactly match the host in the PostgreSQL service principal (postgres/<host>@REALM) baked into the server keytab. A mismatch makes the GSSAPI handshake fail even when every other value is correct.
Kerberos authenticates the database connection, but it does not replace TLS. The example uses sslmode=disable for simplicity. For production, add the PostgreSQL TLS options your environment requires to the data source, such as sslmode=verify-full.
Step 5 - Create the tenant cluster and confirm authentication​
Create the tenant cluster with your configuration:
vcluster create my-vcluster --namespace vcluster-my-vcluster -f vcluster.yaml
The tenant cluster becomes ready once kine completes the GSSAPI handshake and connects to PostgreSQL. The data source carries no password, so Kerberos is the only authentication path available.
If the tenant cluster stays unready, inspect the control plane pod logs:
kubectl logs -n vcluster-my-vcluster -l app=vcluster --tail=100
A working setup logs the GSSAPI provider registration for the principal, followed by a successful connection. A wrong or absent principal logs the provider registration followed by failed GSS auth, which proves Kerberos is enforced rather than bypassed. Confirm that the principal in the data source exactly matches the one exported into the mounted keytab, and that the data source host matches the PostgreSQL service principal.
Network policies​
If you are using network policies, the tenant cluster control plane traffic to the external database must be allowed.
policies:
networkPolicy:
controlPlane:
egress:
# Allow outgoing traffic to the mysql database server.
- to:
- ipBlock:
cidr: 192.168.86.9/32
ports:
- port: 3306
protocol: TCP
# Allow outgoing traffic to the postgres database server private subnets.
- to:
- ipBlock:
cidr: 10.0.0.0/24
- ipBlock:
cidr: 10.0.1.0/24
- ipBlock:
cidr: 10.0.2.0/24
ports:
- port: 5432
protocol: TCP
Config reference​
external required object ​
External defines that an external database should be used as the backend for the virtual cluster
external required object ​enabled required boolean false ​
Enabled defines if the database should be used.
enabled required boolean false ​dataSource required string ​
DataSource is the kine dataSource to use for the database. This depends on the database format.
This is optional for the external database. Examples:
- mysql: mysql://username:password@tcp(hostname:3306)/vcluster
- postgres: postgres://username:password@hostname:5432/vcluster
dataSource required string ​identityProvider required string ​
IdentityProvider is the kine identity provider to use when generating temporary authentication tokens for enhanced security.
This is optional for the external database. Examples:
- aws: RDS IAM Authentication
identityProvider required string ​keyFile required string ​
KeyFile is the key file to use for the database. This is optional.
keyFile required string ​certFile required string ​
CertFile is the cert file to use for the database. This is optional.
certFile required string ​caFile required string ​
CaFile is the ca file to use for the database. This is optional.
caFile required string ​extraArgs required string[] [] ​
ExtraArgs are additional arguments to pass to Kine.
extraArgs required string[] [] ​connector required string ​
Connector specifies a secret located in a connected vCluster Platform that contains database server connection information
to be used by Platform to create a database and database user for the vCluster.
and non-privileged user. A kine endpoint should be created using the database and user on Platform registration.
This is optional.
connector required string ​