Create an internal load balancer in Azure Kubernetes Service (AKS)
As a cluster operator or developer, you may want to create a service in AKS that uses an internal Azure load balancer for enhanced security and without an external endpoint. This article shows you how to create and use an internal load balancer with AKS.
Before you begin
- This article assumes that you have an existing AKS cluster. If you need an AKS cluster, you can create one using Azure CLI, Azure PowerShell, or the Azure portal.
- You need the Azure CLI version 2.0.59 or later.
- If you want to use an existing subnet or resource group, the AKS cluster identity needs permission to manage network resources. For more information, see Use kubenet networking with your own IP address ranges in AKS or Configure Azure CNI networking in AKS.
Create an internal load balancer
- Create a service manifest named
internal-lb.yaml
with the service typeLoadBalancer
and theazure-load-balancer-internal
annotation.
apiVersion: v1
kind: Service
metadata:
name: internal-app
annotations:
service.beta.kubernetes.io/azure-load-balancer-internal: "true"
spec:
type: LoadBalancer
ports:
- port: 80
selector:
app: internal-app
- Deploy the internal load balancer using the
kubectl apply
command.
kubectl apply -f internal-lb.yaml
- View the service details using the
kubectl get service
command.
kubectl get service internal-app
The IP address of the internal load balancer is shown in the EXTERNAL-IP
column.
Specify an IP address
When you specify an IP address for the load balancer, the specified IP address must reside in the same virtual network as the AKS cluster, but it can’t already be assigned to another resource in the virtual network. You can use the az network vnet subnet list
Azure CLI command or the Get-AzVirtualNetworkSubnetConfig
PowerShell cmdlet to get the subnets in your virtual network.
You have two options for specifying an IP address:
- Set service annotations: Use
service.beta.kubernetes.io/azure-load-balancer-ipv4
for an IPv4 address andservice.beta.kubernetes.io/azure-load-balancer-ipv6
for an IPv6 address.
apiVersion: v1
kind: Service
metadata:
name: internal-app
annotations:
service.beta.kubernetes.io/azure-load-balancer-ipv4: 10.240.0.25
service.beta.kubernetes.io/azure-load-balancer-internal: "true"
spec:
type: LoadBalancer
ports:
- port: 80
selector:
app: internal-app
- Add the
LoadBalancerIP
property to the load balancer YAML manifest: This field is deprecated, and it can’t support dual-stack.
apiVersion: v1
kind: Service
metadata:
name: internal-app
annotations:
service.beta.kubernetes.io/azure-load-balancer-internal: "true"
spec:
type: LoadBalancer
loadBalancerIP: 10.240.0.25
ports:
- port: 80
selector:
app: internal-app
Connect Azure Private Link service to internal load balancer
You can use Azure Private Link service to connect to your Kubernetes service object via the internal load balancer. You need Kubernetes version 1.22.x or later and an existing resource group with a VNet and subnet.
- Create a Private Link service connection.
kubectl apply -f internal-lb-pls.yaml
- View the service details using the
kubectl get service
command.
kubectl get service internal-app
- View the details of the Private Link Service object using the
az network private-link-service list
command.
AKS_MC_RG=$(az aks show -g myResourceGroup --name myAKSCluster --query nodeResourceGroup -o tsv)
az network private-link-service list -g $AKS_MC_RG --query "[][].{Name:name,Alias:alias}" -o table
- Create a Private Endpoint to the Private Link service.
AKS_PLS_ID=$(az network private-link-service list -g $AKS_MC_RG --query "[].id" -o tsv)
az network private-endpoint create -g myOtherResourceGroup --name myAKSServicePE --vnet-name myOtherVNET --subnet pe-subnet --private-connection-resource-id $AKS_PLS_ID --connection-name connectToMyK8sService
PLS Customizations via Annotations
You can use annotations to customize the PLS resource.
Annotation | Value | Description | Required | Default |
---|---|---|---|---|
service.beta.kubernetes.io/azure-pls-create |
"true" |
Boolean indicating whether a PLS needs to be created. | Required | |
service.beta.kubernetes.io/azure-pls-name |
<PLS name> |
String specifying the name of the PLS resource to be created. | Optional | pls-<LB frontend config name> |
service.beta.kubernetes.io/azure-pls-resource-group |
Resource Group name |
String specifying the name of the Resource Group where the PLS resource will be created | Optional | MC_ resource |
service.beta.kubernetes.io/azure-pls-ip-configuration-subnet |
<Subnet name> |
String indicating the subnet to which the PLS will be deployed. This subnet must exist in the same VNET as the backend pool. PLS NAT IPs are allocated within this subnet. | Optional | If service.beta.kubernetes.io/azure-load-balancer-internal-subnet , this ILB subnet is used. Otherwise, the default subnet from config file is used. |
service.beta.kubernetes.io/azure-pls-ip-configuration-ip-address-count |
[1-8] |
Total number of private NAT IPs to allocate. | Optional | 1 |
service.beta.kubernetes.io/azure-pls-ip-configuration-ip-address |
"10.0.0.7 ... 10.0.0.10" |
A space separated list of static IPv4 IPs to be allocated. (IPv6 is not supported right now.) Total number of IPs should not be greater than the ip count specified in service.beta.kubernetes.io/azure-pls-ip-configuration-ip-address-count . If there are fewer IPs specified, the rest are dynamically allocated. The first IP in the list is set as Primary . |
Optional | All IPs are dynamically allocated. |
service.beta.kubernetes.io/azure-pls-fqdns |
"fqdn1 fqdn2" |
A space separated list of fqdns associated with the PLS. | Optional | [] |
service.beta.kubernetes.io/azure-pls-proxy-protocol |
"true" or "false" |
Boolean indicating whether the TCP PROXY protocol should be enabled on the PLS to pass through connection information, including the link ID and source IP address. Note that the backend service MUST support the PROXY protocol or the connections will fail. | Optional | false |
service.beta.kubernetes.io/azure-pls-visibility |
"sub1 sub2 sub3 \u2026 subN" or "*" |
A space separated list of Azure subscription ids for which the private link service is visible. Use "*" to expose the PLS to all subs (Least restrictive). |
Optional | Empty list [] indicating role-based access control only: This private link service will only be available to individuals with role-based access control permissions within your directory. (Most restrictive) |
service.beta.kubernetes.io/azure-pls-auto-approval |
"sub1 sub2 sub3 \u2026 subN" |
A space separated list of Azure subscription ids. This allows PE connection requests from the subscriptions listed to the PLS to be automatically approved. This only works when visibility is set to "*" . |
Optional | [] |
Use private networks
When you create your AKS cluster, you can specify advanced networking settings to deploy the cluster into an existing Azure virtual network and subnets. You don’t need to make any changes to the previous steps to deploy an internal load balancer that uses a private network in an AKS cluster.
Delete the load balancer
The load balancer is deleted when all of its services are deleted. You can directly delete a service, such as kubectl delete service internal-app
, which also deletes the underlying Azure load balancer.
Next steps
To learn more about Kubernetes services, see the Kubernetes services documentation.