Deploy Azure SQL with Private Endpoint and Test Connectivity from AKS
Source: Dev.to
This tutorial demonstrates how to:
- Create networking for AKS
- Deploy an AKS cluster using Azure CNI Overlay
- Deploy Azure SQL Database
- Secure it using a Private Endpoint
- Fix DNS resolution using a Private DNS Zone
- Verify connectivity from Kubernetes using debugging pods
Goal: Allow AKS pods to securely connect to Azure SQL using private networking only.
1. Define Environment Variables
LOCATION=southeastasia
RG_NETWORK=rg-aks-network
RG_OVERLAY=rg-aks-overlay
RG_UNDERLAY=rg-aks-underlay
VNET_NAME=vnet-aks-lab
SUBNET_OVERLAY=subnet-overlay
SUBNET_UNDERLAY=subnet-underlay
AKS_OVERLAY=aks-overlay
AKS_UNDERLAY=aks-underlay
2. Create Resource Groups
az group create --name $RG_NETWORK --location $LOCATION
az group create --name $RG_OVERLAY --location $LOCATION
az group create --name $RG_UNDERLAY --location $LOCATION
3. Create Virtual Network
az network vnet create \
--resource-group $RG_NETWORK \
--name $VNET_NAME \
--address-prefix 10.0.0.0/16
4. Create Subnets
Overlay subnet (AKS nodes)
az network vnet subnet create \
--resource-group $RG_NETWORK \
--vnet-name $VNET_NAME \
--name $SUBNET_OVERLAY \
--address-prefix 10.0.1.0/24
Underlay subnet
az network vnet subnet create \
--resource-group $RG_NETWORK \
--vnet-name $VNET_NAME \
--name $SUBNET_UNDERLAY \
--address-prefix 10.0.2.0/24
Retrieve subnet IDs
OVERLAY_SUBNET_ID=$(az network vnet subnet show \
--resource-group $RG_NETWORK \
--vnet-name $VNET_NAME \
--name $SUBNET_OVERLAY \
--query id -o tsv)
UNDERLAY_SUBNET_ID=$(az network vnet subnet show \
--resource-group $RG_NETWORK \
--vnet-name $VNET_NAME \
--name $SUBNET_UNDERLAY \
--query id -o tsv)
echo $OVERLAY_SUBNET_ID
echo $UNDERLAY_SUBNET_ID
5. Deploy AKS Cluster (Azure CNI Overlay)
az aks create \
--resource-group $RG_OVERLAY \
--name $AKS_OVERLAY \
--location $LOCATION \
--node-count 2 \
--network-plugin azure \
--network-plugin-mode overlay \
--pod-cidr 192.168.0.0/16 \
--service-cidr 172.16.0.0/16 \
--dns-service-ip 172.16.0.10 \
--vnet-subnet-id $OVERLAY_SUBNET_ID \
--generate-ssh-keys
6. Connect kubectl to the Cluster
az aks get-credentials \
--resource-group $RG_OVERLAY \
--name $AKS_OVERLAY
Verify cluster status:
kubectl get nodes -o wide
kubectl get pods -o wide
7. Create Subnets for Services
Service subnet
az network vnet subnet create \
--resource-group $RG_NETWORK \
--vnet-name $VNET_NAME \
--name subnet-service \
--address-prefix 10.0.3.0/24
Private Endpoint subnet
az network vnet subnet create \
--resource-group $RG_NETWORK \
--vnet-name $VNET_NAME \
--name subnet-private-endpoint \
--address-prefix 10.0.4.0/24
8. Create Azure SQL Server
Generate a unique server name:
SQL_SERVER=aks-lab-sql-$RANDOM
Create the server:
az sql server create \
--name $SQL_SERVER \
--resource-group $RG_NETWORK \
--location $LOCATION \
--admin-user sqladmin \
--admin-password 'StrongPass123!'
Ensure the provider is registered:
az provider register --namespace Microsoft.Sql
az provider show --namespace Microsoft.Sql --query "registrationState"
9. Create SQL Database
az sql db create \
--resource-group $RG_NETWORK \
--server $SQL_SERVER \
--name demo-db \
--service-objective Basic
Retrieve the SQL server resource ID:
SQL_ID=$(az sql server show \
--name $SQL_SERVER \
--resource-group $RG_NETWORK \
--query id -o tsv)
echo $SQL_ID
10. Create Private Endpoint for Azure SQL
az network private-endpoint create \
--name sql-private-endpoint \
--resource-group $RG_NETWORK \
--vnet-name $VNET_NAME \
--subnet subnet-private-endpoint \
--private-connection-resource-id $SQL_ID \
--group-id sqlServer \
--connection-name sqlConnection
11. Verify Private Endpoint IP
NIC_ID=$(az network private-endpoint show \
--name sql-private-endpoint \
--resource-group $RG_NETWORK \
--query "networkInterfaces[0].id" \
-o tsv)
echo $NIC_ID
Retrieve the private IP address:
az network nic show \
--ids $NIC_ID \
--query "ipConfigurations[0].privateIpAddress" \
-o tsv
12. Create Private DNS Zone (Optional but recommended)
az network private-dns zone create \
--resource-group $RG_NETWORK \
--name "privatelink.database.windows.net"
Link the DNS zone to the VNet:
az network private-dns link vnet create \
--resource-group $RG_NETWORK \
--zone-name "privatelink.database.windows.net" \
--name sql-dns-link \
--virtual-network $VNET_NAME \
--registration-enabled false
Create an A record that points to the private endpoint IP:
PRIVATE_IP=$(az network private-endpoint show \
--name sql-private-endpoint \
--resource-group $RG_NETWORK \
--query "customDnsConfigs[0].ipAddresses[0]" \
-o tsv)
az network private-dns record-set a add-record \
--resource-group $RG_NETWORK \
--zone-name "privatelink.database.windows.net" \
--record-set-name $SQL_SERVER \
--ipv4-address $PRIVATE_IP
13. Test Connectivity from AKS
Deploy a debugging pod:
apiVersion: v1
kind: Pod
metadata:
name: sql-test
spec:
containers:
- name: curl
image: mcr.microsoft.com/azure-cli
command: ["sleep"]
args: ["infinity"]
Apply the manifest:
kubectl apply -f sql-test.yaml
Enter the pod:
kubectl exec -it sql-test -- /bin/bash
Inside the pod, test the connection:
# Install sqlcmd (optional)
apt-get update && apt-get install -y mssql-tools unixodbc-dev
# Connect using the private DNS name
/opt/mssql-tools/bin/sqlcmd -S $SQL_SERVER.privatelink.database.windows.net,1433 \
-U sqladmin -P 'StrongPass123!' -Q "SELECT TOP (1) name FROM sys.databases;"
If the query returns a result, the private networking is working correctly.
14. Clean‑up (Optional)
az group delete --name $RG_NETWORK --yes --no-wait
az group delete --name $RG_OVERLAY --yes --no-wait
az group delete --name $RG_UNDERLAY --yes --no-wait
Congratulations! You have successfully set up an AKS cluster that connects securely to an Azure SQL Database using private endpoints and Azure CNI Overlay networking.
Retrieve Private IP
az network nic show \
--ids $NIC_ID \
--query "ipConfigurations[0].privateIPAddress" \
-o tsv
Example output
10.0.4.4
12. Test Network from AKS Pod
Launch a debugging pod using the nicolaka/netshoot image:
kubectl run net-test \
--image=nicolaka/netshoot \
-it --rm -- bash
Inside the pod you can test DNS and networking.
13. Test SQL Client Pod
Run a SQL client container:
kubectl run sql-client \
--image=mcr.microsoft.com/mssql-tools \
-it --rm -- bash
14. Create Private DNS Zone
Azure SQL private endpoints require DNS mapping.
Create the private DNS zone:
az network private-dns zone create \
--resource-group $RG_NETWORK \
--name privatelink.database.windows.net
Link the DNS zone to the virtual network:
az network private-dns link vnet create \
--resource-group $RG_NETWORK \
--zone-name privatelink.database.windows.net \
--name sql-dns-link \
--virtual-network $VNET_NAME \
--registration-enabled false
Attach the private endpoint to the DNS zone:
az network private-endpoint dns-zone-group create \
--resource-group $RG_NETWORK \
--endpoint-name sql-private-endpoint \
--name sql-zone-group \
--private-dns-zone privatelink.database.windows.net \
--zone-name sql
15. Verify DNS Resolution from AKS
Run another debug pod:
kubectl run net-test \
--image=nicolaka/netshoot \
-it --rm -- bash
Test DNS resolution:
nslookup .database.windows.net
Expected result
10.0.4.4
16. Connect to Azure SQL
Run the SQL client pod:
kubectl run sql-client \
--image=mcr.microsoft.com/mssql-tools \
-it --rm -- bash
Connect using sqlcmd:
sqlcmd \
-S aks-lab-sql-31445.database.windows.net \
-U sqladmin \
-P 'StrongPass123!' \
-d demo-db
If successful you will see:
1>
You are now connected to the SQL server.
Example query
SELECT @@VERSION;
GO
Final Architecture
AKS Pod
│
│ DNS Query
▼
Private DNS Zone
(privatelink.database.windows.net)
│
▼
Private Endpoint (10.0.4.4)
│
▼
Azure SQL Database
✅ You now have Azure SQL accessible privately from AKS pods.
