0
# Private Endpoints
1
2
Private networking configuration for AKS clusters including private endpoint connections, private link resources, network security management, and secure communication patterns. This enables AKS clusters to operate within private networks without exposure to public internet, enhancing security and compliance for enterprise workloads.
3
4
## Capabilities
5
6
### Private Endpoint Connection Management
7
8
Manage private endpoint connections for secure, private communication with AKS clusters over Azure's backbone network.
9
10
```python { .api }
11
def update(
12
resource_group_name: str,
13
resource_name: str,
14
private_endpoint_connection_name: str,
15
parameters: PrivateEndpointConnection
16
) -> PrivateEndpointConnection:
17
"""
18
Updates a private endpoint connection.
19
20
Args:
21
resource_group_name: Azure resource group name
22
resource_name: Cluster name
23
private_endpoint_connection_name: Private endpoint connection name
24
parameters: Updated connection configuration
25
26
Returns:
27
PrivateEndpointConnection: Updated connection details
28
"""
29
30
def begin_delete(
31
resource_group_name: str,
32
resource_name: str,
33
private_endpoint_connection_name: str
34
) -> LROPoller[None]:
35
"""
36
Deletes a private endpoint connection.
37
38
Args:
39
resource_group_name: Azure resource group name
40
resource_name: Cluster name
41
private_endpoint_connection_name: Private endpoint connection name
42
43
Returns:
44
LROPoller[None]: Long-running operation poller
45
"""
46
```
47
48
### Private Endpoint Connection Discovery
49
50
List and retrieve private endpoint connections to understand current network connectivity.
51
52
```python { .api }
53
def list(resource_group_name: str, resource_name: str) -> ItemPaged[PrivateEndpointConnection]:
54
"""
55
Lists private endpoint connections for the cluster.
56
57
Args:
58
resource_group_name: Azure resource group name
59
resource_name: Cluster name
60
61
Returns:
62
ItemPaged[PrivateEndpointConnection]: Paginated connection list
63
"""
64
65
def get(
66
resource_group_name: str,
67
resource_name: str,
68
private_endpoint_connection_name: str
69
) -> PrivateEndpointConnection:
70
"""
71
Gets a specific private endpoint connection.
72
73
Args:
74
resource_group_name: Azure resource group name
75
resource_name: Cluster name
76
private_endpoint_connection_name: Private endpoint connection name
77
78
Returns:
79
PrivateEndpointConnection: Connection configuration and status
80
"""
81
```
82
83
### Private Link Resource Management
84
85
Manage private link resources that define the linkable resources within the AKS cluster.
86
87
```python { .api }
88
def list_private_link_resources(
89
resource_group_name: str,
90
resource_name: str
91
) -> PrivateLinkResourcesListResult:
92
"""
93
Lists private link resources for the cluster.
94
95
Args:
96
resource_group_name: Azure resource group name
97
resource_name: Cluster name
98
99
Returns:
100
PrivateLinkResourcesListResult: Available private link resources
101
"""
102
```
103
104
### Private Link Service ID Resolution
105
106
Resolve private link service IDs for network configuration and connectivity planning.
107
108
```python { .api }
109
def resolve_private_link_service_id(
110
resource_group_name: str,
111
resource_name: str,
112
parameters: PrivateLinkResource
113
) -> PrivateLinkResource:
114
"""
115
Resolves private link service ID for the cluster.
116
117
Args:
118
resource_group_name: Azure resource group name
119
resource_name: Cluster name
120
parameters: Private link resource configuration
121
122
Returns:
123
PrivateLinkResource: Resolved private link service details
124
"""
125
```
126
127
## Core Types
128
129
```python { .api }
130
class PrivateEndpointConnection:
131
"""
132
Private endpoint connection configuration and status.
133
134
Attributes:
135
id: Connection resource ID (read-only)
136
name: Connection name (read-only)
137
type: Resource type (read-only)
138
private_endpoint: Private endpoint details
139
private_link_service_connection_state: Connection state
140
provisioning_state: Current provisioning state (read-only)
141
"""
142
id: Optional[str]
143
name: Optional[str]
144
type: Optional[str]
145
private_endpoint: Optional[PrivateEndpoint]
146
private_link_service_connection_state: Optional[PrivateLinkServiceConnectionState]
147
provisioning_state: Optional[str]
148
149
class PrivateEndpoint:
150
"""
151
Private endpoint details for network connectivity.
152
153
Attributes:
154
id: Private endpoint resource ID
155
"""
156
id: Optional[str]
157
158
class PrivateLinkServiceConnectionState:
159
"""
160
Private link service connection state and configuration.
161
162
Attributes:
163
status: Connection status ('Pending', 'Approved', 'Rejected', 'Disconnected')
164
description: Connection state description
165
actions_required: Required actions for connection
166
"""
167
status: Optional[str]
168
description: Optional[str]
169
actions_required: Optional[str]
170
171
class PrivateLinkResource:
172
"""
173
Private link resource definition.
174
175
Attributes:
176
id: Resource ID (read-only)
177
name: Resource name (read-only)
178
type: Resource type (read-only)
179
group_id: Private link resource group identifier
180
required_members: Required member names for private link
181
private_link_service_id: Private link service ID
182
"""
183
id: Optional[str]
184
name: Optional[str]
185
type: Optional[str]
186
group_id: Optional[str]
187
required_members: Optional[List[str]]
188
private_link_service_id: Optional[str]
189
190
class PrivateLinkResourcesListResult:
191
"""
192
List of private link resources.
193
194
Attributes:
195
value: List of private link resources
196
"""
197
value: Optional[List[PrivateLinkResource]]
198
```
199
200
## Usage Examples
201
202
### Enable Private Cluster
203
204
```python
205
from azure.identity import DefaultAzureCredential
206
from azure.mgmt.containerservice import ContainerServiceClient
207
from azure.mgmt.containerservice.models import (
208
ManagedCluster,
209
ManagedClusterAPIServerAccessProfile,
210
ManagedClusterAgentPoolProfile
211
)
212
213
credential = DefaultAzureCredential()
214
client = ContainerServiceClient(credential, subscription_id)
215
216
# Create private AKS cluster
217
private_cluster = ManagedCluster(
218
location="eastus",
219
api_server_access_profile=ManagedClusterAPIServerAccessProfile(
220
enable_private_cluster=True,
221
private_dns_zone="system", # Uses system-managed private DNS zone
222
enable_private_cluster_public_fqdn=False # No public FQDN
223
),
224
agent_pool_profiles=[
225
ManagedClusterAgentPoolProfile(
226
name="nodepool1",
227
count=3,
228
vm_size="Standard_DS2_v2",
229
os_type="Linux",
230
mode="System"
231
)
232
]
233
)
234
235
# Create cluster
236
operation = client.managed_clusters.begin_create_or_update(
237
"myResourceGroup",
238
"myPrivateCluster",
239
private_cluster
240
)
241
result = operation.result()
242
print(f"Private cluster created: {result.name}")
243
```
244
245
### Custom Private DNS Zone
246
247
```python
248
# Private cluster with custom DNS zone
249
custom_dns_cluster = ManagedCluster(
250
location="eastus",
251
api_server_access_profile=ManagedClusterAPIServerAccessProfile(
252
enable_private_cluster=True,
253
private_dns_zone="/subscriptions/sub-id/resourceGroups/dns-rg/providers/Microsoft.Network/privateDnsZones/privatelink.eastus.azmk8s.io",
254
authorized_ip_ranges=[
255
"10.0.0.0/8", # Corporate network
256
"172.16.0.0/12" # VPN range
257
]
258
),
259
agent_pool_profiles=[
260
ManagedClusterAgentPoolProfile(
261
name="nodepool1",
262
count=3,
263
vm_size="Standard_DS2_v2",
264
os_type="Linux",
265
mode="System",
266
vnet_subnet_id="/subscriptions/sub-id/resourceGroups/network-rg/providers/Microsoft.Network/virtualNetworks/myVNet/subnets/aks-subnet"
267
)
268
]
269
)
270
```
271
272
### Manage Private Endpoint Connections
273
274
```python
275
# List all private endpoint connections
276
connections = client.private_endpoint_connections.list(
277
"myResourceGroup",
278
"myPrivateCluster"
279
)
280
281
for conn in connections:
282
print(f"Connection: {conn.name}")
283
if conn.private_link_service_connection_state:
284
state = conn.private_link_service_connection_state
285
print(f" Status: {state.status}")
286
print(f" Description: {state.description}")
287
288
# Get specific connection
289
connection = client.private_endpoint_connections.get(
290
"myResourceGroup",
291
"myPrivateCluster",
292
"connection-name"
293
)
294
295
# Approve pending connection
296
if connection.private_link_service_connection_state.status == "Pending":
297
from azure.mgmt.containerservice.models import (
298
PrivateEndpointConnection,
299
PrivateLinkServiceConnectionState
300
)
301
302
connection.private_link_service_connection_state = PrivateLinkServiceConnectionState(
303
status="Approved",
304
description="Approved for production use"
305
)
306
307
updated_connection = client.private_endpoint_connections.update(
308
"myResourceGroup",
309
"myPrivateCluster",
310
"connection-name",
311
connection
312
)
313
print("Connection approved")
314
```
315
316
### Private Link Resource Discovery
317
318
```python
319
# Discover available private link resources
320
private_resources = client.private_link_resources.list(
321
"myResourceGroup",
322
"myPrivateCluster"
323
)
324
325
for resource in private_resources.value:
326
print(f"Private link resource: {resource.name}")
327
print(f" Group ID: {resource.group_id}")
328
print(f" Required members: {resource.required_members}")
329
if resource.private_link_service_id:
330
print(f" Service ID: {resource.private_link_service_id}")
331
332
# Resolve private link service ID
333
from azure.mgmt.containerservice.models import PrivateLinkResource
334
335
resolve_request = PrivateLinkResource(
336
group_id="management"
337
)
338
339
resolved = client.resolve_private_link_service_id.post(
340
"myResourceGroup",
341
"myPrivateCluster",
342
resolve_request
343
)
344
print(f"Resolved service ID: {resolved.private_link_service_id}")
345
```
346
347
### Network Security Configuration
348
349
```python
350
# Configure authorized IP ranges for private cluster
351
authorized_ranges = [
352
"10.0.0.0/8", # Corporate network
353
"192.168.0.0/16", # Office networks
354
"172.16.0.0/12", # VPN ranges
355
"20.0.0.0/24" # Management subnet
356
]
357
358
# Update cluster with IP restrictions
359
cluster = client.managed_clusters.get("myRG", "myPrivateCluster")
360
cluster.api_server_access_profile.authorized_ip_ranges = authorized_ranges
361
362
update_op = client.managed_clusters.begin_create_or_update(
363
"myRG", "myPrivateCluster", cluster
364
)
365
update_op.wait()
366
print("Authorized IP ranges updated")
367
```
368
369
### Hybrid Connectivity Setup
370
371
```python
372
# Private cluster with public FQDN for hybrid scenarios
373
hybrid_cluster = ManagedCluster(
374
location="eastus",
375
api_server_access_profile=ManagedClusterAPIServerAccessProfile(
376
enable_private_cluster=True,
377
enable_private_cluster_public_fqdn=True, # Keep public FQDN
378
private_dns_zone="system",
379
authorized_ip_ranges=[
380
"203.0.113.0/24" # Office public IP range
381
]
382
),
383
agent_pool_profiles=[
384
ManagedClusterAgentPoolProfile(
385
name="nodepool1",
386
count=3,
387
vm_size="Standard_DS2_v2",
388
os_type="Linux",
389
mode="System"
390
)
391
]
392
)
393
```
394
395
### Multi-Region Private Connectivity
396
397
```python
398
# Setup private connectivity across regions
399
regions = ["eastus", "westus", "northeurope"]
400
dns_zones = {
401
"eastus": "/subscriptions/sub/resourceGroups/dns/providers/Microsoft.Network/privateDnsZones/privatelink.eastus.azmk8s.io",
402
"westus": "/subscriptions/sub/resourceGroups/dns/providers/Microsoft.Network/privateDnsZones/privatelink.westus.azmk8s.io",
403
"northeurope": "/subscriptions/sub/resourceGroups/dns/providers/Microsoft.Network/privateDnsZones/privatelink.northeurope.azmk8s.io"
404
}
405
406
for region in regions:
407
cluster = ManagedCluster(
408
location=region,
409
api_server_access_profile=ManagedClusterAPIServerAccessProfile(
410
enable_private_cluster=True,
411
private_dns_zone=dns_zones[region],
412
enable_private_cluster_public_fqdn=False
413
),
414
agent_pool_profiles=[
415
ManagedClusterAgentPoolProfile(
416
name="nodepool1",
417
count=3,
418
vm_size="Standard_DS2_v2",
419
os_type="Linux",
420
mode="System",
421
vnet_subnet_id=f"/subscriptions/sub/resourceGroups/{region}-network/providers/Microsoft.Network/virtualNetworks/{region}-vnet/subnets/aks-subnet"
422
)
423
]
424
)
425
426
operation = client.managed_clusters.begin_create_or_update(
427
f"{region}-rg",
428
f"private-cluster-{region}",
429
cluster
430
)
431
print(f"Creating private cluster in {region}")
432
```
433
434
### Connection State Management
435
436
```python
437
def manage_private_endpoint_connection(client, rg, cluster_name, connection_name, action):
438
"""Manage private endpoint connection state."""
439
440
connection = client.private_endpoint_connections.get(rg, cluster_name, connection_name)
441
442
from azure.mgmt.containerservice.models import PrivateLinkServiceConnectionState
443
444
if action == "approve":
445
connection.private_link_service_connection_state = PrivateLinkServiceConnectionState(
446
status="Approved",
447
description="Approved by administrator"
448
)
449
elif action == "reject":
450
connection.private_link_service_connection_state = PrivateLinkServiceConnectionState(
451
status="Rejected",
452
description="Rejected due to policy violation"
453
)
454
elif action == "disconnect":
455
# Delete the connection
456
delete_op = client.private_endpoint_connections.begin_delete(
457
rg, cluster_name, connection_name
458
)
459
delete_op.wait()
460
return "Disconnected"
461
462
if action in ["approve", "reject"]:
463
updated = client.private_endpoint_connections.update(
464
rg, cluster_name, connection_name, connection
465
)
466
return updated.private_link_service_connection_state.status
467
468
# Usage
469
status = manage_private_endpoint_connection(
470
client, "myRG", "myCluster", "connection1", "approve"
471
)
472
print(f"Connection status: {status}")
473
```
474
475
## Error Handling
476
477
```python
478
from azure.core.exceptions import HttpResponseError, ResourceNotFoundError
479
480
try:
481
connection = client.private_endpoint_connections.get(
482
"myRG", "myCluster", "nonexistent-connection"
483
)
484
except ResourceNotFoundError:
485
print("Private endpoint connection not found")
486
except HttpResponseError as e:
487
if e.status_code == 403:
488
print("Insufficient permissions to access private endpoint")
489
else:
490
print(f"HTTP error: {e.status_code}")
491
492
# Handle private cluster configuration errors
493
try:
494
operation = client.managed_clusters.begin_create_or_update(
495
"myRG", "myCluster", private_cluster
496
)
497
result = operation.result()
498
except HttpResponseError as e:
499
if "PrivateClusterNotSupported" in str(e):
500
print("Private clusters not supported in this region")
501
elif "InvalidPrivateDNSZone" in str(e):
502
print("Invalid private DNS zone configuration")
503
else:
504
print(f"Cluster creation failed: {e}")
505
```
506
507
## Best Practices
508
509
### Network Security
510
511
```python
512
# Implement defense in depth for private clusters
513
security_config = {
514
# Network segmentation
515
"subnet_nsg": "/subscriptions/sub/resourceGroups/security/providers/Microsoft.Network/networkSecurityGroups/aks-nsg",
516
517
# Authorized IP ranges (least privilege)
518
"authorized_ranges": [
519
"10.1.0.0/16", # Management subnet only
520
"10.2.100.0/24" # Jump box subnet
521
],
522
523
# Private DNS configuration
524
"private_dns_zone": "system", # Use system-managed zone
525
526
# Disable public FQDN
527
"enable_public_fqdn": False
528
}
529
530
# Apply security configuration
531
secure_cluster = ManagedCluster(
532
location="eastus",
533
api_server_access_profile=ManagedClusterAPIServerAccessProfile(
534
enable_private_cluster=True,
535
private_dns_zone=security_config["private_dns_zone"],
536
enable_private_cluster_public_fqdn=security_config["enable_public_fqdn"],
537
authorized_ip_ranges=security_config["authorized_ranges"]
538
)
539
)
540
```
541
542
### Connection Monitoring
543
544
```python
545
def monitor_private_connections(client, rg, cluster_name):
546
"""Monitor private endpoint connection health."""
547
548
connections = client.private_endpoint_connections.list(rg, cluster_name)
549
550
health_report = {
551
"total_connections": 0,
552
"approved": 0,
553
"pending": 0,
554
"rejected": 0,
555
"disconnected": 0
556
}
557
558
for conn in connections:
559
health_report["total_connections"] += 1
560
561
if conn.private_link_service_connection_state:
562
status = conn.private_link_service_connection_state.status.lower()
563
if status in health_report:
564
health_report[status] += 1
565
566
return health_report
567
568
# Usage
569
health = monitor_private_connections(client, "myRG", "myCluster")
570
print(f"Connection health: {health}")
571
```