Connect public services and reach private databases through the cluster
Almost every connection error with RabbitMQ, Service Bus, MongoDB or Redis has one of two causes: the service firewall does not know Kubepier’s IPs, or the service is a private database (private endpoint, private IP) the internet cannot reach and that you reach through the cluster. This page shows where each connection starts and what to do in each case.
Kubepier Web egress IPs
The IP list shows up here and in the app, under the Network and security menu.
The same IPs apply to every Kubepier Web customer. Allow every IP on the list.
A real case
- Redis on Azure Cache: the cache firewall had old IPs, and the connection timed out. The fix was to allow Kubepier’s current egress IPs in the cache firewall rule and connect on port 6380 with TLS (port 6379, without TLS, is off on Azure Cache).
- MongoDB on a VM: the server name resolved to a private IP (172.16.x.x) and the VM had no public IP. The Direct route cannot reach it; the way in is the Through the cluster route, from inside the client network (or the desktop over the VPN).
- Redis on Azure Cache Premium: conexao_encerrada on both the Direct and the Through the cluster route, with the right firewall, port and TLS. The cause was the password saved on the client, from another cache. Since 2026-10-05 this case shows as an authentication error (WRONGPASS), no longer as a closed connection. Details in Troubleshooting.
Where Kubepier connects from
| Path | Where the connection starts | Reaches | What you need to do |
|---|---|---|---|
| Kubepier Web, Direct route (service menus, clusters) | Kubepier’s fixed egress IPs, straight to the service | Services with a public endpoint | Allow the egress IPs on the service firewall |
| Kubepier Web, Through the cluster route (service menus) | A restricted relay in one of the client’s clusters and namespaces, via the Kubernetes API | Whatever the cluster network reaches: private endpoints, private IPs, VPN | Pick the route in the service form and grant the Role in the namespace |
| Kubepier Desktop (service menus, clusters) | Your machine | Whatever your machine reaches, including over the VPN and the office network | Be on the right network or VPN |
| Bastion (web) and Secure tunnel (desktop) | Inside the client’s cluster | Whatever the cluster network reaches, usually the client’s private network | Grant Kubepier the namespace permissions; the cluster needs a route to the service |
Is your service public or private (private endpoint, private IP)?
- Public (has an internet endpoint): use the Direct route. Allow Kubepier’s egress IPs on the service firewall. Prefer allowing only Kubepier’s range over opening it to everyone.
- Private (private endpoint, private IP, VPN-only or on-premises): use the Through the cluster route, if one of the client’s clusters reaches the service. Nothing has to be opened to the internet.
- If no client cluster reaches the service: use Kubepier Desktop over your VPN.
- To test the network first, from inside the cluster: the web Bastion (nc, curl, dig) or the desktop Secure tunnel.
Connection route: Direct or Through the cluster
In the form of each client service (RabbitMQ, Service Bus, MongoDB and Redis), Connection route has two options. The service shows the route in use: "direct" or "via cluster <name>".
| Route | How it connects | When to use it |
|---|---|---|
| Direct (egress IPs) | The Kubepier Web API connects straight to the service, from the fixed egress IPs. | A service with a public endpoint and the IPs allowed on its firewall. |
| Through the cluster | The API creates a temporary, unprivileged pod (relay) in the chosen cluster and namespace and reaches the service through it, via the Kubernetes API. TLS stays end to end with the service, validating the real server name. | A service on a private network that one of the client’s clusters reaches. |
Route through the cluster: reaching the private database
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
name: kubepier-relay
namespace: <namespace>
rules:
- apiGroups: [""]
resources: ["pods"]
verbs: ["create", "get", "list", "delete"]
- apiGroups: [""]
resources: ["pods/exec", "pods/portforward"]
verbs: ["create", "get"]
---
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
name: kubepier-relay
namespace: <namespace>
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: Role
name: kubepier-relay
subjects:
- kind: User
name: <user-or-objectId-of-the-credential>
apiGroup: rbac.authorization.k8s.io - In the service form, under Connection route, pick Through the cluster, pick one of the client’s clusters and the namespace, and click Save route. Only admins change the route; members see a hint to ask an admin.
- Apply the Role below in the namespace (the same one the app shows under Network and security, in the cluster-route item), bound to the cluster credential identity.
- On first use, the screen shows "Preparing connection through the cluster…" while the relay starts (up to 120 seconds).
- When the direct connection fails with a private IP or a timeout, the screen suggests "Connect through the cluster".
Route through the cluster: how it works and limits
| Rule | Value |
|---|---|
| Relays | 1 per organization, cluster and namespace, shared by the services using that route |
| Targets per relay | up to 10 |
| First use | up to 120 seconds for the relay to be Running |
| Relay connection to the service | times out after 10 seconds |
| API local listeners | close after 5 minutes idle |
| Relay | deleted after 10 minutes idle, or at 2 hours; the next request creates another |
| Failed relay | retried after 30 seconds |
| Relay image and security | the same as the Bastion: netshoot pinned by digest, restricted profile, 50m/64 Mi requested and a 500m/256 Mi limit |
MongoDB: replica sets and mongodb+srv:// work; the SRV and TXT records are resolved inside the cluster. Service Bus: through the route, it uses AMQP over WebSocket on port 443. The route also works on the Free plan, for the read-only views.
Route through the cluster: audit
- Relay creation and removal (relay_criar, relay_remover) and every route change (rota_alterada) go to the organization audit log.
- Never the traffic or the credentials.
How to tell whether the address is private
Resolve the service name. If the IP is in 10.0.0.0/8, 172.16.0.0/12 or 192.168.0.0/16, it is private and the web cannot reach it.
# Does the name resolve to a public or a private IP?
dig +short mongo.cliente.com.br
nslookup mongo.cliente.com.br
# Does the port answer? (from the Bastion, inside the cluster)
nc -vz mongo.cliente.com.br 27017
# TLS: which certificate does the server present?
openssl s_client -connect meu-cache.redis.cache.windows.net:6380 -servername meu-cache.redis.cache.windows.net </dev/null Azure Cache for Redis
az redis firewall-rules create --resource-group <resource-group> --name <cache> \
--rule-name kubepier --start-ip 20.206.66.128 --end-ip 20.206.66.129 - Allow the egress IPs under the cache Firewall (in the portal) or with the command below. Remove old rules you no longer need.
- Connect on port 6380 with TLS: use rediss://, or tick TLS in the form. Port 6379 without TLS is off.
- The password is one of the cache access keys.
- A cache with a private endpoint only (public access off): the web cannot reach it. Use the Through the cluster route, or the desktop over the VPN.
Azure Cosmos DB for MongoDB (RU and vCore)
- In the portal, under Networking: keep public access on selected networks and add Kubepier’s egress IPs (on vCore, as firewall rules).
- With public access off and a private endpoint only, use the Through the cluster route, or the desktop over the VPN.
MongoDB Atlas
atlas accessLists create 20.206.66.128/31 --type cidrBlock --comment "Kubepier" - Under Network Access → IP Access List, add Kubepier’s range, or with the Atlas CLI:
A cluster with a private endpoint or peering and no public access: use the Through the cluster route, or the desktop over the VPN.
Azure Service Bus
- In the portal: the namespace → Networking → Selected networks, then add the egress IPs to the firewall.
- Not every tier supports IP rules: check the Azure documentation for your namespace tier.
- A namespace with a private endpoint only: use the Through the cluster route, or the desktop over the VPN.
RabbitMQ
- CloudAMQP and other managed services: add the IPs to the provider’s allowed IP list, in its dashboard.
- On a VM: allow the management API port (15672, or the one you publish) to Kubepier’s range in the NSG (Azure) or security group (AWS).
AWS
aws ec2 authorize-security-group-ingress --group-id <sg-id> \
--protocol tcp --port 5432 --cidr 20.206.66.128/31 - ElastiCache: no public endpoint; the web cannot reach it. Use the Through the cluster route with a cluster in the same VPC, or the desktop over the VPN.
- RDS: only with Publicly accessible on and the security group allowing the port to Kubepier’s range:
MSK: the web does not connect to Kafka today; the desktop Dependencies panel only reads pod variables and the ConfigMaps they reference.
Google Cloud
# Replaces the whole list: include the networks already there
gcloud sql instances patch <instance> --authorized-networks=20.206.66.128/31,<already-allowed-networks> - Memorystore (Redis): private IP only; use the Through the cluster route with a cluster in the same VPC, or the desktop over the VPN.
- Cloud SQL: under Authorized networks, add Kubepier’s range:
Self-hosted services on VMs
Allow the service port only to Kubepier’s range in the NSG or security group. Example on Azure, for MongoDB on 27017:
az network nsg rule create --resource-group <resource-group> --nsg-name <nsg> \
--name kubepier --priority 300 --direction Inbound --access Allow --protocol Tcp \
--source-address-prefixes 20.206.66.128/31 --destination-port-ranges 27017 On-premises
- With a public IP and NAT: allow Kubepier’s range on the edge firewall to the service port, with TLS.
- Not exposed to the internet: use the Through the cluster route with a cluster that has a route there, or the desktop over the VPN.
Error message → what to do
| What shows up | Likely cause | How to check | How to fix |
|---|---|---|---|
| Timeout (ETIMEDOUT) | The firewall drops the connection: Kubepier’s IPs are not allowed, or the IP is private | dig the name; nc -vz host port from the Bastion | Allow the egress IPs; if the IP is private, use the Through the cluster route, or the desktop over the VPN |
| Connection closed by the server (conexao_encerrada: ECONNRESET, EPIPE, socket hang up, TLS closed before the handshake) | Usually a firewall or IP allowlist that does not include Kubepier’s egress IPs (for example, the Azure Cache firewall); or the wrong TLS setting or port; or a server connection limit | Check the service IP list; openssl s_client -connect host:port | Allow the egress IPs or switch to Through the cluster (the screen suggests "Connect through the cluster"), and check TLS and port. If the failure is the same on both routes, check the password: until 2026-10-05 (web) and up to 2.2.0 (desktop), a wrong Redis password showed up this way too |
| Connection refused (ECONNREFUSED) | Nothing listening on that port, or the wrong port (6379 instead of 6380 on Azure Cache) | nc -vz host port | Fix the port; start the service |
| Name not found (ENOTFOUND) | The name does not exist in public DNS (an internal name or a typo) | dig +short name | Fix the name; internal names only resolve inside the network |
| TLS or handshake error | TLS off on one side, a non-TLS port, or a certificate for another name | openssl s_client -connect host:port -servername host | Use rediss:// or tick TLS; connect with the name on the certificate |
| Authentication error or no permission on the service (WRONGPASS, NOAUTH, NOPERM, 401, 403) | A wrong password (WRONGPASS), a missing password (NOAUTH), a user without permission or an ACL missing commands (NOPERM). On Redis, a wrong password shows this way on the web since 2026-10-05 and on desktop from 2.3.0 | Test the same credential with the official client (redis-cli, mongosh, the RabbitMQ API) | Fix the credential in the client form or the role (see each service page). On Azure Cache, paste the whole connection string from the portal |
| host_privado (RabbitMQ, Service Bus, MongoDB and Redis) | The name resolves only to private IPs (10/8, 172.16/12, 192.168/16, 100.64/10, fc00::/7): the Direct route cannot reach it. Kubepier checks this before trying to connect (result kept for 60 s), so the error shows right away instead of waiting for a timeout | dig +short name | Switch the route to Through the cluster, or use the desktop over the VPN |
| Needs the clusterMonitor role (MongoDB) | The Mongo user lacks clusterMonitor | The panel names the missing role | Grant clusterMonitor on admin and read on the database |
| Kubernetes 403 (Bastion, Secure tunnel) | The credential lacks the verbs in the namespace | The message names the missing verb | Apply the Role from the Bastion or Secure tunnel page |
On the Direct route, the web shows the service’s own message (for example connect ETIMEDOUT or getaddrinfo ENOTFOUND) under "service error", and credential failures as "no permission on the service". The Redis status card shows the server message, such as WRONGPASS invalid username-password pair. On the Through the cluster route, network errors carry the codes in the table below; credential errors are the same as on the Direct route.
Route-through-the-cluster errors
When the route through the cluster fails, the API answers 502 with the rota_cluster error and one of these codes:
| Code | What it means | How to fix |
|---|---|---|
| sem_permissao | The cluster credential lacks the verbs in the namespace | Apply the Role above |
| podsecurity, admissao | PodSecurity or an admission policy refused the relay | The relay is already restricted; check custom policies (Kyverno, Gatekeeper, webhook) |
| imagem | The cluster could not pull the relay image | Mirror nicolaka/netshoot (same digest) into the company registry |
| tempo_esgotado | The relay was not Running within 120 s | Check the namespace events |
| cota | The ResourceQuota cannot fit the relay | Allow 50m/64 Mi requested and a 500m/256 Mi limit |
| namespace_inexistente | The chosen namespace does not exist | Fix the route namespace |
| cluster_inexistente | The route cluster was deleted from Kubepier | Pick another cluster or go back to Direct |
| cluster_inacessivel | The route cluster did not answer | Check the cluster and the network to its API |
| alvo_recusado | The relay reached the service, but the connection was refused | Check host and port and whether the service accepts the cluster network |
| alvo_tempo | The relay did not reach the service within 10 s | Check NSG/Security Group, the service firewall and the namespace NetworkPolicy |
| alvo_inalcancavel | The cluster network has no route to the service | Check peering, VPN, NSG/Security Group and NetworkPolicy |
| alvo_dns | The DNS inside the cluster does not resolve the host | Check the name, the private zone linked to the cluster network and CoreDNS |
| limite_alvos | The relay already forwards 10 targets | Use another namespace for other services’ routes |
| srv_invalido, srv_vazio | An invalid mongodb+srv://, or no SRV records seen from inside the cluster | Check the connection string and the cluster DNS |
Accepted connection formats
- Redis: redis://user:password@host:port/db, rediss:// for TLS, or the host, port, user, password, TLS and database fields.
- Redis in the format the Azure portal shows (host:6380,password=...,ssl=True,abortConnect=False, with optional user= and defaultDatabase=). That format has no way to escape a comma, so a password containing one is refused. Prefer pasting the whole connection string, copied from Access keys of the right cache: host, port, password and TLS come together and a dev key does not end up on the prd client.
- Redis: TLS on without a port uses 6380 (6379 without TLS); the TLS box also applies to connection strings; TLS on port 6379 of a *.redis.cache.windows.net, or redis:// on 6380 without TLS, is refused with an explanation.
- MongoDB: the connection string (mongodb:// or mongodb+srv://) and, in a separate field, the database name. If you reach a replica set through a single node (one IP or a tunnel), add directConnection=true: otherwise the driver tries the other members by their internal names and fails.
- RabbitMQ: management API URL (https://host:15672 or the provider’s), user and password.
- Service Bus: the namespace connection string (Endpoint=sb://...;SharedAccessKeyName=...;SharedAccessKey=...).
Security practices
- Allow only Kubepier’s range (the /31 in the list above), never 0.0.0.0/0.
- Never expose a database to the internet without TLS.
- When IPs change, remove the old rules.
- Use least-privilege credentials; the IP allowlist adds a network layer on top of credentials, it does not replace them.