This post will show you the steps you’ll have to take to deploy an Azure Files Storage with a Private Endpoint and use it to create volumes for an Azure Kubernetes Service cluster:
Create a bicep file to declare the Azure resources
You’ll have to declare the following resources:
- A VNET with 2 subnets. One for the private endpoint and the other for the AKS cluster.
- An Azure Files storage.
- A Private Endpoint for the storage.
- A Private DNS Zone and Private DNS Zone Group.
- A link between the Private DNS Zone to the VNET.
- An AKS cluster.
- A role assignment to add the kubelet identity of the cluster as a Contributor to the Storage Account.
in a main.bicep file with the following contents:
1param sa_name string = 'akscsisa'
2param aks_name string = 'akscsimsft'
3
4// Create the VNET
5resource vnet 'Microsoft.Network/virtualNetworks@2020-11-01' = {
6 name: 'private-network'
7 location: 'westeurope'
8 properties: {
9 addressSpace: {
10 addressPrefixes: [
11 '10.0.0.0/8'
12 ]
13 }
14 subnets: [
15 {
16 name: 'endpoint'
17 properties: {
18 addressPrefix: '10.241.0.0/16'
19 serviceEndpoints: []
20 delegations: []
21 privateEndpointNetworkPolicies: 'Disabled'
22 privateLinkServiceNetworkPolicies: 'Enabled'
23 }
24 }
25 {
26 name: 'aks'
27 properties: {
28 addressPrefix: '10.240.0.0/16'
29 serviceEndpoints: []
30 delegations: []
31 privateEndpointNetworkPolicies: 'Enabled'
32 privateLinkServiceNetworkPolicies: 'Enabled'
33 }
34 }
35 ]
36 enableDdosProtection: false
37 }
38}
39
40// Create the File Storage Account
41resource sa 'Microsoft.Storage/storageAccounts@2021-01-01' = {
42 name: sa_name
43 location: 'westeurope'
44 sku: {
45 name: 'Premium_LRS'
46 tier: 'Premium'
47 }
48 kind: 'FileStorage'
49 properties: {
50 minimumTlsVersion: 'TLS1_0'
51 allowBlobPublicAccess: false
52 isHnsEnabled: false
53 networkAcls: {
54 bypass: 'AzureServices'
55 virtualNetworkRules: []
56 ipRules: []
57 defaultAction: 'Deny'
58 }
59 supportsHttpsTrafficOnly: true
60 accessTier: 'Hot'
61 }
62}
63
64// Create the Private Enpoint
65resource private_endpoint 'Microsoft.Network/privateEndpoints@2020-11-01' = {
66 name: 'sa-endpoint'
67 location: 'westeurope'
68 properties: {
69 privateLinkServiceConnections: [
70 {
71 name: 'sa-privateserviceconnection'
72 properties: {
73 privateLinkServiceId: sa.id
74 groupIds: [
75 'file'
76 ]
77 }
78 }
79 ]
80 subnet: {
81 id: '${vnet.id}/subnets/endpoint'
82 }
83 }
84}
85
86// Create the Private DNS Zone
87resource dns 'Microsoft.Network/privateDnsZones@2018-09-01' = {
88 name: 'privatelink.file.core.windows.net'
89 location: 'global'
90}
91
92// Link the Private DNS Zone with the VNET
93resource vnet_dns_link 'Microsoft.Network/privateDnsZones/virtualNetworkLinks@2018-09-01' = {
94 name: '${dns.name}/test'
95 location: 'global'
96 properties: {
97 registrationEnabled: false
98 virtualNetwork: {
99 id: vnet.id
100 }
101 }
102}
103
104// Create Private DNS Zone Group
105resource dns_group 'Microsoft.Network/privateEndpoints/privateDnsZoneGroups@2020-11-01' = {
106 name: '${private_endpoint.name}/default'
107 properties: {
108 privateDnsZoneConfigs: [
109 {
110 name: 'privatelink-file-core-windows-net'
111 properties: {
112 privateDnsZoneId: dns.id
113 }
114 }
115 ]
116 }
117}
118
119// Create AKS cluster
120resource aks 'Microsoft.ContainerService/managedClusters@2021-02-01' = {
121 name: aks_name
122 location: 'westeurope'
123 identity: {
124 type: 'SystemAssigned'
125 }
126 properties: {
127 kubernetesVersion: '1.19.9'
128 dnsPrefix: aks_name
129 agentPoolProfiles: [
130 {
131 name: 'default'
132 count: 1
133 vmSize: 'Standard_D2s_v3'
134 osDiskSizeGB: 30
135 osDiskType: 'Ephemeral'
136 vnetSubnetID: '${vnet.id}/subnets/aks'
137 type: 'VirtualMachineScaleSets'
138 orchestratorVersion: '1.19.9'
139 osType: 'Linux'
140 mode: 'System'
141 }
142 ]
143 servicePrincipalProfile: {
144 clientId: 'msi'
145 }
146 addonProfiles: {
147 kubeDashboard: {
148 enabled: false
149 }
150 }
151 enableRBAC: true
152 networkProfile: {
153 networkPlugin: 'kubenet'
154 networkPolicy: 'calico'
155 loadBalancerSku: 'standard'
156 podCidr: '10.244.0.0/16'
157 serviceCidr: '10.0.0.0/16'
158 dnsServiceIP: '10.0.0.10'
159 dockerBridgeCidr: '172.17.0.1/16'
160 }
161 apiServerAccessProfile: {
162 enablePrivateCluster: false
163 }
164 }
165}
166
167// Built-in Role Definition IDs
168// https://docs.microsoft.com/en-us/azure/role-based-access-control/built-in-roles
169var contributor = '/subscriptions/${subscription().subscriptionId}/providers/Microsoft.Authorization/roleDefinitions/b24988ac-6180-42a0-ab88-20f7382dd24c'
170
171// Set AKS kubelet Identity as SA Contributor
172resource aks_kubelet_sa_contributor 'Microsoft.Authorization/roleAssignments@2020-04-01-preview' = {
173 name: guid('${aks_name}_kubelet_sa_contributor')
174 scope: sa
175 properties: {
176 principalId: reference(aks.id, '2021-02-01', 'Full').properties.identityProfile['kubeletidentity'].objectId
177 roleDefinitionId: contributor
178 }
179}
Deploy the Azure resources
Run the following commands to deploy the Azure resources:
1az group create -n private-pvc-test -l westeurope
2
3az deployment group create -f ./main.bicep -g private-pvc-test
After 10 minutes or so you’ll have all resources up and running.
Install Azure CSI Driver
The Azure Files Container Storage Interface (CSI) driver can be installed on the cluster so Azure Kubernetes Service (AKS) can manage the lifecycle of Azure Files shares.
To install the driver run:
1az aks get-credentials -n akscsimsft -g private-pvc-test --overwrite-existing
2
3curl -skSL https://raw.githubusercontent.com/kubernetes-sigs/azurefile-csi-driver/v1.5.0/deploy/install-driver.sh | bash -s v1.5.0 --
and check the pods status:
1kubectl -n kube-system get pod -o wide --watch -l app=csi-azurefile-controller
2kubectl -n kube-system get pod -o wide --watch -l app=csi-azurefile-node
You should find instances of csi-azurefile-controller and csi-azurefile-node running without issues.
Create a Storage Class
Create a file named: storageclass-azurefile-csi.yaml with the following yaml:
1apiVersion: storage.k8s.io/v1
2kind: StorageClass
3metadata:
4 name: azurefile-csi
5provisioner: file.csi.azure.com
6allowVolumeExpansion: true
7parameters:
8 resourceGroup: <resourceGroup> # optional, only set this when storage account is not in the same resource group as agent node
9 storageAccount: <storageAccountName>
10 # Check driver parameters here:
11 # https://github.com/kubernetes-sigs/azurefile-csi-driver/blob/master/docs/driver-parameters.md
12 server: <storageAccountName>.privatelink.file.core.windows.net
13reclaimPolicy: Delete
14volumeBindingMode: Immediate
15mountOptions:
16 - dir_mode=0777
17 - file_mode=0777
18 - uid=0
19 - gid=0
20 - mfsymlinks
21 - cache=strict # https://linux.die.net/man/8/mount.cifs
22 - nosharesock # reduce probability of reconnect race
23 - actimeo=30 # reduce latency for metadata-heavy workload
Remember to replace the values of <resourceGroup>
and <storageAccountName>
with the ones used in the previous deployment. (i.e. private-pvc-test and akscsisa)
Now deploy the Storage Class to the cluster:
1kubectl apply -f storageclass-azurefile-csi.yaml
Create a Private Volume Claim
Create a Private Volume Claim that uses the storage class. Create pvc.yaml with the following contents:
1apiVersion: v1
2kind: PersistentVolumeClaim
3metadata:
4 name: my-azurefile
5spec:
6 accessModes:
7 - ReadWriteMany
8 storageClassName: azurefile-csi
9 resources:
10 requests:
11 storage: 100Gi
Deploy the Private Volume Claim to the cluster and check that everything is ok:
1kubectl apply -f pvc.yaml
2k get pvc
Now feel free to try and mount a volume using the Private Volume Claim: my-azurefile
Hope it helps!!!
Please find a bicep based sample here or if you prefer terraform here
References:
Comments