Kubernetes applications often start with simple networking. A service runs inside a cluster, another service calls it through an internal Kubernetes Service, and an ingress controller handles HTTP or HTTPS traffic.
The architecture becomes more complicated when applications need to communicate with resources outside the cluster while keeping that communication private.
A common example is an internal application hosted in Azure Kubernetes Service that needs to receive traffic from another Azure network, an internal application gateway, a corporate network, or a private client environment. The application should be reachable, but it should not be exposed through a public IP address.
This is where private ingress becomes useful.
Private ingress means that the Kubernetes ingress endpoint is reachable only through private network connectivity. The application can still use normal HTTP or HTTPS routing, host-based routing, TLS termination, and Kubernetes service discovery, but the entry point is not publicly exposed.
This article explains how to design private ingress for internal Kubernetes applications in Azure, how traffic moves through the architecture, what Azure networking components are involved, and what commonly causes connectivity problems.
What Is Private Ingress?
Ingress is the HTTP or HTTPS entry point into Kubernetes applications.
Without an ingress layer, clients may need to communicate directly with individual Kubernetes Services.
For example:
Client
|
+---- Service A
+---- Service B
+---- Service C
As the number of applications grows, this becomes difficult to manage.
An ingress controller provides a central HTTP or HTTPS routing layer:
Client
|
v
Ingress
|
+---- Service A
+---- Service B
+---- Service C
The ingress controller examines information such as:
- Host name
- URL path
- HTTP method
- TLS configuration
- Backend service
It then sends the request to the appropriate Kubernetes Service.
Private ingress adds another requirement:
Client
|
Private network
|
v
Private ingress
|
v
Kubernetes Service
|
v
Application Pod
The important difference is that the ingress endpoint itself is private.
Why Keep Kubernetes Ingress Private?
Not every application should be reachable from the public internet.
Examples include:
- Internal administration portals
- Enterprise APIs
- Internal dashboards
- Back-office applications
- Microservices consumed by other private systems
- Internal AI services
- Data processing APIs
- Applications used by corporate networks
Making these applications public just to make networking easier creates unnecessary exposure.
A private ingress design lets the organization preserve normal HTTP application behavior while keeping network access restricted.
For example:
Internet
|
X
|
Private application
Instead, an approved private client can access it:
Corporate Network
|
Private connectivity
|
Azure VNet
|
Private ingress
|
AKS application
This provides network-level isolation before application-level authentication is even considered.
The Basic Azure Architecture
A common architecture looks like this:
Private Client
|
v
Private DNS
|
v
Private IP
|
v
Azure Application Gateway
|
v
AKS Ingress Controller
|
v
Kubernetes Service
|
v
Application Pod
The exact components depend on the Azure and Kubernetes implementation.
The important concept is that the traffic never needs to enter the application through a public endpoint.
The client resolves a private hostname to a private IP address, connects through private Azure networking, and eventually reaches the Kubernetes workload.
AKS Is Not Automatically Private
Running an application inside Azure Kubernetes Service does not automatically make its ingress private.
There are several different concepts involved:
- Private AKS cluster
- Private Kubernetes Service
- Internal LoadBalancer
- Private ingress controller
- Private Application Gateway
- Private DNS
- VNet connectivity
These concepts solve different problems.
For example, a private AKS API server controls how administrators and tools communicate with the Kubernetes control plane.
It does not automatically mean that every application deployed inside the cluster has a private ingress endpoint.
Likewise, making a Kubernetes Service internal does not automatically provide the complete HTTP routing and TLS architecture required by the application.
You need to design the entire traffic path.
Kubernetes Service and Ingress Are Different
This distinction is important.
A Kubernetes Service provides stable networking for a group of Pods.
For example:
Service
|
+---- Pod 1
+---- Pod 2
+---- Pod 3
An ingress controller provides HTTP-level routing to those Services.
For example:
Private Client
|
v
Ingress
|
+---- /orders → Orders Service
|
+---- /payments → Payments Service
|
+---- /users → Users Service
The Service handles Kubernetes-level connectivity.
The ingress layer handles HTTP routing.
Private ingress therefore needs both networking and Kubernetes configuration to work correctly.
Internal Load Balancer
One common approach is to expose the ingress controller through an Azure internal load balancer.
Instead of receiving a public IP, the ingress endpoint receives a private IP from the Azure virtual network.
Conceptually:
Public Load Balancer
|
Public IP
|
Internet
versus:
Internal Load Balancer
|
Private IP
|
VNet
The second design prevents direct internet access to the ingress endpoint.
This is useful when all expected clients are already connected to private networks.
The private IP can then be associated with a private DNS name such as:
orders.internal.example.com
The exact domain is determined by the organization's DNS architecture.
Private DNS Is Part of the Design
Private ingress is not complete just because the endpoint has a private IP.
Clients still need to resolve the application hostname correctly.
For example:
orders.internal.example.com
|
v
Private DNS
|
v
10.20.10.25
The client then connects to the private address.
Without the correct DNS configuration, clients may:
- Resolve the public address
- Fail to resolve the hostname
- Resolve an incorrect private address
- Reach the wrong environment
This is one of the most common sources of confusion in private application networking.
Split-Horizon DNS
Many organizations use the same application hostname internally and externally but return different addresses depending on where the request originates.
For example:
Internal client
|
v
app.example.com
|
v
10.20.10.25
An external client might receive:
app.example.com
|
v
Public IP
This is often called split-horizon DNS.
It allows organizations to maintain familiar application names while controlling which network path clients use.
However, this design requires careful DNS management.
If an internal client unexpectedly receives the public IP, the request may bypass the private architecture entirely.
Private Connectivity From Other Azure VNets
An application does not have to be consumed from the same VNet.
For example:
VNet A
Corporate Application
|
|
VNet Peering
|
v
VNet B
AKS + Private Ingress
The private ingress endpoint can be reachable from another connected VNet when routing and network security rules allow it.
This is useful when different teams or environments use separate VNets.
However, VNet connectivity alone does not guarantee application connectivity.
You still need to verify:
- Route propagation
- Network security groups
- Firewall rules
- DNS resolution
- Load balancer configuration
- Ingress configuration
- Backend health
Connectivity From On-Premises Networks
The same concept can extend to corporate data centers.
A simplified architecture is:
Corporate Network
|
VPN / ExpressRoute
|
Azure VNet
|
Private Ingress
|
AKS
|
Application
The application remains private while authorized corporate clients can access it.
This can be useful for internal enterprise applications where internet exposure is not required.
The network team must ensure that the private address range is reachable from the corporate network and that return traffic follows a valid route.
Network Security Groups Still Matter
Private does not mean unrestricted.
A private ingress endpoint should still be protected with appropriate network controls.
For example:
Corporate subnet
|
| TCP 443
v
Private ingress
The network should not necessarily allow:
Any internal subnet
|
| TCP 443
v
Private ingress
unless that broad access is intentional.
Use network security controls to restrict which network sources can reach the ingress endpoint.
The exact placement of those controls depends on the Azure architecture.
The important principle is to define who should be able to reach the private endpoint.
Application Authentication Still Matters
Private ingress is not a replacement for application authentication.
A private IP reduces network exposure, but it does not automatically prove that the caller is authorized.
For example:
Private Network
|
v
Private Ingress
|
v
Application Authentication
|
v
Application
The application may still require:
- Entra ID authentication
- OAuth tokens
- API keys
- Mutual TLS
- Service identity
- Application-level authorization
Use network controls and application authentication together.
TLS Configuration
Private applications should normally still use HTTPS.
A common misunderstanding is:
"The traffic is private, so HTTP is enough."
Private network traffic can still be intercepted or misused if the network boundary is compromised or incorrectly configured.
TLS provides encryption and server identity at the application layer.
The architecture can therefore look like:
Client
|
HTTPS
|
Private IP
|
Ingress
|
HTTPS or internal routing
|
Application
TLS termination can occur at the Application Gateway or ingress controller depending on the architecture.
The important part is to decide where TLS terminates and where encryption continues.
Where Should TLS Terminate?
There are several possible designs.
TLS at the Application Gateway
Client
|
HTTPS
|
Application Gateway
|
HTTP/HTTPS
|
Ingress
|
Application
The gateway handles the public-facing or private-facing TLS connection.
This can simplify certificate management for the backend.
TLS at the Ingress Controller
Client
|
HTTPS
|
Application Gateway
|
HTTPS
|
Ingress
|
Application
The ingress controller terminates TLS.
This provides encryption farther into the application path.
TLS at Multiple Layers
Some organizations use TLS at more than one layer:
Client
|
HTTPS
|
Gateway
|
HTTPS
|
Ingress
|
HTTPS
|
Application
This provides stronger encryption boundaries but increases certificate-management complexity.
Choose the design based on security requirements, operational capability, and application architecture.
Host-Based Routing
Private ingress is especially useful when multiple internal applications share the same entry point.
For example:
orders.internal.example.com
payments.internal.example.com
reports.internal.example.com
The ingress layer can route each hostname to a different Kubernetes Service.
Conceptually:
Private IP
|
v
Ingress
|
+-- orders.internal.example.com
| |
| v
| Orders Service
|
+-- payments.internal.example.com
|
v
Payments Service
This avoids creating a separate network endpoint for every application.
Path-Based Routing
The same concept can be used with paths.
For example:
internal.example.com/orders
internal.example.com/payments
internal.example.com/reports
The ingress controller routes the request based on the URL path.
Path-based routing is useful when the applications are logically related, but it requires careful handling of:
- URL rewriting
- Authentication
- Cookies
- Redirects
- API documentation
- Application-generated URLs
Host-based routing is often easier to reason about when applications are independently owned.
Health Checks Are Critical
A private ingress endpoint can be reachable while the backend application is unhealthy.
For example:
Client
|
v
Private IP
|
v
Gateway
|
X
Unhealthy backend
The client may receive errors even though DNS and network connectivity are correct.
Health checks should therefore be monitored separately from endpoint reachability.
Check:
- Gateway health
- Ingress controller health
- Kubernetes Service endpoints
- Pod readiness
- Application health
- TLS certificate validity
- Backend response codes
This creates a layered troubleshooting model.
Troubleshooting Private Ingress
When an internal application cannot be reached, troubleshoot from the client toward the application.
Step 1: Check DNS
Verify that the hostname resolves to the expected private address.
nslookup app.internal.example.com
or an equivalent DNS diagnostic tool.
If the hostname resolves incorrectly, Kubernetes troubleshooting is premature.
Step 2: Check Network Reachability
Verify that the client can reach the private IP.
Check:
- Routing
- VNet connectivity
- VPN or ExpressRoute
- Network security rules
- Azure Firewall rules
Step 3: Check the Gateway
If Application Gateway is part of the architecture, verify:
- Listener configuration
- Backend pool
- Health probes
- Routing rules
- TLS configuration
Step 4: Check the Ingress Controller
Verify:
- Controller health
- Ingress resource
- Hostname
- Path
- Backend Service
- TLS secret
- Events
Step 5: Check the Kubernetes Service
Confirm that the Service has healthy endpoints.
If the Service points to no ready Pods, the ingress layer cannot successfully route traffic.
Step 6: Check the Application
Finally, inspect the application itself.
Look at:
- Application logs
- HTTP status codes
- Startup errors
- Dependency failures
- Authentication failures
This order prevents teams from jumping directly into application debugging when the real problem is DNS or routing.
Common Mistakes
Making the AKS Cluster Private and Assuming the Application Is Private
A private Kubernetes control plane and a private application ingress solve different problems.
Forgetting DNS
A private IP is not useful if clients cannot resolve the application hostname to it.
Allowing Too Much Internal Traffic
Private does not mean trusted.
Restrict access to the networks and applications that actually need it.
Mixing Public and Private Endpoints
Be clear about which clients should use which endpoint.
Ambiguous DNS can cause internal traffic to leave the intended private path.
Ignoring Return Routes
The client may reach the private ingress, but the response path may fail because the return route is missing.
Treating Gateway Health as Application Health
A healthy gateway does not mean the Kubernetes application is healthy.
Check the entire chain.
Using HTTP Because the Network Is Private
Private routing reduces exposure but does not replace TLS.
Production Checklist
Before exposing an AKS application through private ingress, verify:
- Application requirement for private access is documented.
- Private IP address range is planned.
- Ingress controller architecture is defined.
- Internal load balancing is configured where required.
- Private DNS is configured.
- DNS resolution is tested from every required client network.
- VNet routing is configured.
- VNet peering or private connectivity is verified.
- VPN or ExpressRoute routing is verified where applicable.
- Network security rules are reviewed.
- Application Gateway configuration is validated if used.
- Ingress routing rules are tested.
- TLS certificates are configured.
- TLS termination points are documented.
- Backend health checks are working.
- Kubernetes Services have healthy endpoints.
- Pod readiness checks are working.
- Application authentication remains enabled.
- Logs are available at every important layer.
- Public access is disabled when it is not required.
- Failure scenarios have been tested.
Advantages and Disadvantages
Advantages
Private ingress provides:
- Reduced internet exposure
- Private application access
- Centralized HTTP routing
- Better separation between public and internal workloads
- Support for internal DNS
- Compatibility with enterprise network architectures
- Ability to combine network and application-level security
Disadvantages
It also introduces additional networking requirements:
- Private DNS must be managed correctly.
- Routing becomes more important.
- Multiple Azure components may need to be configured.
- Troubleshooting spans Azure and Kubernetes.
- TLS management requires planning.
- Cross-VNet and on-premises access needs explicit connectivity.
The complexity is manageable when each network layer has a clearly defined responsibility.
Summary
Private ingress for Azure Kubernetes applications is more than assigning a private IP address to a Kubernetes Service.
The complete architecture includes the client network, DNS, Azure routing, private load balancing or Application Gateway, ingress controller, Kubernetes Service, and application Pods.
The most important design principle is to keep these layers separate in your troubleshooting and security model.
DNS determines where the client goes. Network routing determines whether the client can reach that destination. Network security controls determine whether the connection is permitted. The gateway and ingress controller determine how HTTP traffic is routed. Kubernetes Services connect that traffic to application Pods.
When these responsibilities are designed together, internal applications can use normal HTTP and HTTPS routing while remaining inaccessible from the public internet.
Private ingress is therefore a useful architecture for enterprise Kubernetes workloads that need controlled access without exposing application endpoints publicly.
KubernetesAzure Kubernetes Serviceprivate ingressAzure Application Gatewayinternal load balancerprivate DNSAKS networking
Join the conversation! Your thoughts help the community grow.