DATABASE_URL. The copy happens inside the cluster, and Ankra never sees the values. An application on another cluster is not connected for you: give it the values yourself, as in Connect from another cluster.
How your application receives the connection
Every application environment a service was set up for, on the service’s cluster, receives the service’s connection in two parts:- A Secret named
<service>-connectionin the application’s namespace, with<service>standing for the service name. Ankra copies its values inside the cluster from the service’s own credentials Secret. - A reference to that Secret, which a deploy of the application adds to every container and init container of its Deployments, StatefulSets and DaemonSets through
envFrom, so each of the Secret’s keys becomes an environment variable. The names are listed under Variable names. A deploy adds the reference while the service is still being set up too. The reference is optional, so the application starts while the Secret does not exist yet.
- The workloads reference the Secret but none of their pods runs, for example because they are scaled to zero: Ankra writes the Secret, and each pod reads the variables when it starts.
- The workloads do not reference the Secret, because the application was deployed before the service was connected: Ankra writes the Secret, and the application reads it after its next deploy adds the reference.
- Running pods reference the Secret, for example because the application was deployed while the service was being set up: Ankra leaves the Secret to a deploy. Deploy the application once the service is ready: the deploy writes the Secret and rolls the workloads that reference it together onto it.
- Running pods read the Secret but started before it existed: they run without its variables until they restart. Ankra never restarts them by itself.
- A variable the connection would add is defined twice, by the connection and by another source the workloads read, such as one of the application’s environment secrets: the connection is not delivered, by Ankra on its own or by a deploy, until you remove the other definition or choose another service, or none, to provide those names, as under Variable names.
pickup, described below, when the platform sent one, and the delivery’s state when it did not:
A deploy usually connects the workloads, but not every one: see the note on Jobs, CronJobs and
ankra.io/deploy-overrides below.
The same state is in the API, on each of consumers in Get a managed service instance, as connection_delivery with the secret_name, the variables the application receives and a reason. Its pickup says how far the environment is from running with the connection, and reason says what to do:
pickup is absent when Ankra could not read it, and for a consumer it does not connect, such as one on another cluster.
A workload annotated ankra.io/deploy-overrides: "none" keeps the manifest you committed, so it gets no envFrom reference. The <service>-connection Secret is still written to its namespace: reference it from the workload yourself. Jobs and CronJobs are not given the reference either.
When a service is deleted, the application’s next deploy removes its <service>-connection Secret and the reference to it.
To take one application off a service that keeps running for its other applications, disconnect it. Its next deploy removes the reference and rolls its workloads, and Ankra removes the <service>-connection Secret once no pod reads it.
Variable names
Each service delivers the variables its kind of client conventionally reads:
Every service also delivers each variable under its own prefix: the service name in capitals, with hyphens as underscores. A PostgreSQL service named
orders-db delivers ORDERS_DB_DATABASE_URL, ORDERS_DB_PGHOST and so on.
The names without a prefix go to one service of each kind per application environment: the one connected first, recorded the first time a deploy gives it those names. An application with one database reads DATABASE_URL. When a second PostgreSQL service is added for the same environment, DATABASE_URL keeps pointing at the first, and the second is read through its prefixed names only. Valkey and any other Redis-compatible service count as one kind, as they share REDIS_URL.
The names without a prefix never move to another service by themselves. If the service that provides DATABASE_URL is retired while another PostgreSQL service still serves the environment, the application’s next deploy is refused and nothing is deployed: giving DATABASE_URL to the other database would make the application read and write a different database without anyone choosing that. The service’s page shows the same warning on the application. Choose which service provides the names, or choose none so the application reads only the prefixed names, then deploy again:
- Ankra AI or MCP:
set_service_connection_defaultwith the application, cluster, namespace, the kind (postgres,redis,nats,opensearch,s3,victorialogsorvictoriametrics) and the service’s instance id, ornone: true. - API:
PUT /api/v1/org/service-admission/connection-defaultswithapplication_id,cluster_id,namespace,protocolandinstance_id(nullfor none).
DATABASE_URL, the deploy is refused in the same way and says so; choose the new service explicitly once you have moved the data. Removing the application’s deployment from the namespace forgets which service Ankra recorded as providing the names, so a new deployment there starts fresh; a service you chose yourself stays chosen.
Find the connection details
Open the service in My services. Its Connect section shows:- the namespace, which is the service name;
- each address, with a Copy button;
- the name of the Secret that holds the credentials;
- under Read a credential yourself, for each key in that Secret, an Ankra CLI command that prints its value, with a Copy button. The command names the service’s cluster and also uses
jq, as in Read a value.
connection on Get a managed service instance: the namespace, the named endpoints and the secret with its name and keys. They follow a fixed pattern for each service, below, with <service> standing for the service name.
Addresses and Secrets
The addresses resolve from any namespace on the service’s cluster, and not from outside it. On a cluster with a custom DNS domain, use the shorter
<name>.<service>.svc form, for example valkey.<service>.svc:6379. Of the delivered variables, DATABASE_URL, JDBC_DATABASE_URL, PGHOST, S3_ENDPOINT, AWS_ENDPOINT_URL_S3 and OPENAI_BASE_URL, and their prefixed copies, use the full svc.cluster.local form, so on such a cluster they do not resolve: give the application short-form values for them yourself, as in Connect from another cluster, under variable names the delivery does not use. The other delivered addresses, in REDIS_URL, REDIS_HOST, NATS_URL, OPENSEARCH_URL, VICTORIA_LOGS_URL and VICTORIA_METRICS_URL, already use the short form and resolve there.
Resolving is not reaching: on their current package versions, PostgreSQL, Valkey, NATS, OpenSearch and SeaweedFS admit their client port only from the service’s own namespace, the namespace of the cluster’s Ankra agent and the namespaces of the applications connected to the service, where the cluster’s network plugin enforces NetworkPolicy. See How a service runs.
Read a value
You need a value only to connect something Ankra does not connect for you. Select the service’s cluster, then read the Secret by name with--reveal, using the Secret and namespace from the table:
--reveal, every value comes back as a sha256: digest. --reveal needs the kubernetes.secrets_reveal permission on the cluster, which the operator, admin and owner roles carry, and every reveal is recorded in the organisation’s audit log. Values under data stay base64-encoded.
For a PostgreSQL service named orders-db, this prints its password:
ca.crt, works the same way:
Connect from another cluster
An application on another cluster than the service is not connected for you, and the service’s addresses do not resolve there. Reaching the service from another cluster needs a network path between the clusters that you provide, and the address that path exposes. A service whose client port admits only the namespaces named under Addresses and Secrets also needs a NetworkPolicy of your own in its namespace that admits the traffic of that path. Give the application the values as environment secrets, from the service page’s Use it in <application> button, which opens the application’s Settings › Secrets, or from the CLI. Piping the value keeps it out of your shell history:env-secrets apply seals the stored values into the application’s deployments and rolls them. The URL keys, such as PostgreSQL’s fqdn-uri, name the in-cluster address, so build the URL your application uses from your own network path’s address rather than copying them.
For a workload that is not an Ankra application, keep the Secret in Git and encrypt it with SOPS.
A value you copy this way is yours: deleting the service does not remove it from the application. Delete it yourself once the application no longer uses the service.
Notes per service
- PostgreSQL.
DATABASE_URLandJDBC_DATABASE_URLcarry the operator’sfqdn-uriandfqdn-jdbc-uri. The operator also writesuri,jdbc-uriandhostkeys, but they name the short hostpostgresql-rw, which resolves only inside the service’s own namespace. You connect asapp, the owner of the databaseapp, and superuser access is off. The read-only address reaches replicas only, so it answers only wheninstancesis above 1, and no variable names it. The image includes the pgvector and pgaudit extensions. - Valkey. Authenticate as the
appuser, whichREDIS_USERNAMEcarries, withREDIS_PASSWORD;REDIS_URLis a completeredis://URL that carries both. Write to the primary address. The read-replicas address serves reads from every pod. - NATS. Connect as
app.NATS_URLcarries no credentials, so passNATS_USERandNATS_PASSWORDseparately. JetStream is on; memory-backed streams are disabled. - OpenSearch. Use HTTPS with basic auth as
admin, the only user. The certificate is signed by a private CA generated in the cluster: have your client trustOPENSEARCH_CA_CERT, which holds that CA’s certificate. - SeaweedFS. Use the S3 API over plain HTTP inside the cluster, with path-style addressing. The admin key pair, the one delivered, can read, write, list and administer buckets. The read-only key pair can only read, and is in the service’s Secret only.
- VictoriaLogs. Send logs over HTTP with basic auth, as JSON lines, Loki push, OpenTelemetry or Elasticsearch bulk, and query them with LogsQL. No log collector is installed, so ship logs with your own agent.
- VictoriaMetrics. Push metrics with basic auth using Prometheus
remote_write, OpenTelemetry, InfluxDB or another supported protocol, and query with PromQL or MetricsQL on the Prometheus HTTP API. It scrapes nothing itself, so push from vmagent, a Prometheus agent or an OpenTelemetry Collector.
OpenAI-compatible inference
Agpu-chat service speaks the OpenAI API, so any OpenAI client library or tool that accepts a base URL works against it unchanged. A connected application receives:
Most OpenAI SDKs read
OPENAI_BASE_URL and OPENAI_API_KEY from the environment by themselves. From a pod in a connected namespace:
embeddings set to 1, the same endpoint also answers POST /v1/embeddings with the bge-m3 model. The endpoint is not exposed outside the cluster. api-key is a client key the service creates for its consumers; it cannot mint, change or revoke keys. With chat_ui set to 1 the service also runs the Open WebUI chat UI, reachable from inside the service’s namespace only. See Managed Service Settings for the models each model_tier runs.
Check that the service answers
A finished deployment is not yet a ready service. The service’s Service health section says whether its workload runs as planned, which does not prove a client can connect. Ankra checks that a client can connect for every service it publishes, about every five minutes, and shows the result as the service’s Readiness: see Health and readiness. Until readiness reads Ready, or while it reads Not verified because the cluster’s agent is too old to run the check, check the service yourself before you rely on it. Its pods run in its namespace:Ready condition is True:
app.kubernetes.io/name=ankra-postgres-connection-test for PostgreSQL, and app.kubernetes.io/name=ankra-service-canary for every other service. That is Ankra’s readiness check, which connects the way an application would; it is deleted when it finishes.
Next steps
Managed service settings
What each setting changes, with its range and default.
Managed services
How the services run, their health and readiness, and their current limits.
Disconnect an application
Take one application off a service that keeps running for the others.
Delete a managed service
What deleting removes and keeps, and how to confirm it.