Skip to content

Commit e5d9587

Browse files
committed
Welcome to Stack Simplify
1 parent 3e84608 commit e5d9587

File tree

58 files changed

+1950
-16
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

58 files changed

+1950
-16
lines changed
Lines changed: 4 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,7 @@
1-
apiVersion: networking.k8s.io/v1
2-
kind: Ingress
1+
apiVersion:
2+
kind:
33
metadata:
4-
name: nginxapp1-ingress-service
5-
annotations:
6-
kubernetes.io/ingress.class: nginx
4+
75
spec:
8-
rules:
9-
- http:
10-
paths:
11-
- path: /
12-
pathType: Prefix
13-
backend:
14-
service:
15-
name: app1-nginx-clusterip-service
16-
port:
17-
number: 80
18-
6+
197

Lines changed: 258 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,258 @@
1+
# Kubernetes ExternalDNS to create Record Sets in Azure DNS from AKS
2+
3+
## Step-01: Introduction
4+
- Create External DNS Manifest
5+
- Provide Access to DNZ Zones using **Azure Managed Service Identity** for External DNS pod to create **Record Sets** in Azure DNS Zones
6+
- Review Application & Ingress Manifests
7+
- Deploy and Test
8+
[![Image](https://www.stacksimplify.com/course-images/azure-aks-ingress-external-dns.png "Azure AKS Kubernetes - Masterclass")](https://www.udemy.com/course/aws-eks-kubernetes-masterclass-devops-microservices/?referralCode=257C9AD5B5AF8D12D1E1)
9+
10+
## Step-02: Create External DNS Manifests
11+
- External-DNS needs permissions to Azure DNS to modify (Add, Update, Delete DNS Record Sets)
12+
- We can provide permissions to External-DNS pod in two ways in Azure
13+
- Using Azure Service Principal
14+
- Using Azure Managed Service Identity (MSI)
15+
- We are going to use `MSI` for providing necessary permissions here which is latest and greatest in Azure as on today.
16+
17+
18+
### Gather Information Required for azure.json file
19+
```t
20+
# To get Azure Tenant ID
21+
az account show --query "tenantId"
22+
23+
# To get Azure Subscription ID
24+
az account show --query "id"
25+
```
26+
27+
### Create azure.json file
28+
```json
29+
{
30+
"tenantId": "c81f465b-99f9-42d3-a169-8082d61c677a",
31+
"subscriptionId": "82808767-144c-4c66-a320-b30791668b0a",
32+
"resourceGroup": "dns-zones",
33+
"useManagedIdentityExtension": true,
34+
"userAssignedIdentityID": "404b0cc1-ba04-4933-bcea-7d002d184436"
35+
}
36+
```
37+
38+
### Review external-dns.yml manifest
39+
```yaml
40+
apiVersion: v1
41+
kind: ServiceAccount
42+
metadata:
43+
name: external-dns
44+
---
45+
apiVersion: rbac.authorization.k8s.io/v1
46+
kind: ClusterRole
47+
metadata:
48+
name: external-dns
49+
rules:
50+
- apiGroups: [""]
51+
resources: ["services","endpoints","pods", "nodes"]
52+
verbs: ["get","watch","list"]
53+
- apiGroups: ["extensions","networking.k8s.io"]
54+
resources: ["ingresses"]
55+
verbs: ["get","watch","list"]
56+
- apiGroups: [""]
57+
resources: ["nodes"]
58+
verbs: ["list"]
59+
---
60+
apiVersion: rbac.authorization.k8s.io/v1
61+
kind: ClusterRoleBinding
62+
metadata:
63+
name: external-dns-viewer
64+
roleRef:
65+
apiGroup: rbac.authorization.k8s.io
66+
kind: ClusterRole
67+
name: external-dns
68+
subjects:
69+
- kind: ServiceAccount
70+
name: external-dns
71+
namespace: default
72+
---
73+
apiVersion: apps/v1
74+
kind: Deployment
75+
metadata:
76+
name: external-dns
77+
spec:
78+
strategy:
79+
type: Recreate
80+
selector:
81+
matchLabels:
82+
app: external-dns
83+
template:
84+
metadata:
85+
labels:
86+
app: external-dns
87+
spec:
88+
serviceAccountName: external-dns
89+
containers:
90+
- name: external-dns
91+
image: k8s.gcr.io/external-dns/external-dns:v0.11.0
92+
args:
93+
- --source=service
94+
- --source=ingress
95+
#- --domain-filter=example.com # (optional) limit to only example.com domains; change to match the zone created above.
96+
- --provider=azure
97+
#- --azure-resource-group=externaldns # (optional) use the DNS zones from the specific resource group
98+
volumeMounts:
99+
- name: azure-config-file
100+
mountPath: /etc/kubernetes
101+
readOnly: true
102+
volumes:
103+
- name: azure-config-file
104+
secret:
105+
secretName: azure-config-file
106+
```
107+
108+
## Step-03: Create MSI - Managed Service Identity for External DNS to access Azure DNS Zones
109+
110+
### Create Manged Service Identity (MSI)
111+
- Go to All Services -> Managed Identities -> Add
112+
- Resource Name: aksdemo1-externaldns-access-to-dnszones
113+
- Subscription: Pay-as-you-go
114+
- Resource group: aks-rg1
115+
- Location: Central US
116+
- Click on **Create**
117+
118+
### Add Azure Role Assignment in MSI
119+
- Opem MSI -> aksdemo1-externaldns-access-to-dnszones
120+
- Click on **Azure Role Assignments** -> **Add role assignment**
121+
- Scope: Resource group
122+
- Subscription: Pay-as-you-go
123+
- Resource group: dns-zones
124+
- Role: Contributor
125+
126+
### Make a note of Client Id and update in azure.json
127+
- Go to **Overview** -> Make a note of **Client ID"
128+
- Update in **azure.json** value for **userAssignedIdentityID**
129+
```
130+
"userAssignedIdentityID": "de836e14-b1ba-467b-aec2-93f31c027ab7"
131+
```
132+
133+
## Step-04: Associate MSI in AKS Cluster VMSS
134+
- Go to All Services -> Virtual Machine Scale Sets (VMSS) -> Open aksdemo1 related VMSS (aks-agentpool-27193923-vmss)
135+
- Go to Settings -> Identity -> User assigned -> Add -> aksdemo1-externaldns-access-to-dnszones
136+
137+
138+
139+
## Step-05: Create Kubernetes Secret and Deploy ExternalDNS
140+
```t
141+
# Create Secret
142+
cd kube-manifests/01-ExteranlDNS
143+
kubectl create secret generic azure-config-file --from-file=azure.json
144+
145+
# List Secrets
146+
kubectl get secrets
147+
148+
# Deploy ExternalDNS
149+
cd kube-manifests/01-ExteranlDNS
150+
kubectl apply -f external-dns.yml
151+
152+
# Verify ExternalDNS Logs
153+
kubectl logs -f $(kubectl get po | egrep -o 'external-dns[A-Za-z0-9-]+')
154+
```
155+
156+
```log
157+
# Error Type: 400
158+
time="2020-08-24T11:25:04Z" level=error msg="azure.BearerAuthorizer#WithAuthorization: Failed to refresh the Token for request to https://management.azure.com/subscriptions/82808767-144c-4c66-a320-b30791668b0a/resourceGroups/dns-zones/providers/Microsoft.Network/dnsZones?api-version=2018-05-01: StatusCode=400 -- Original Error: adal: Refresh request failed. Status Code = '400'. Response body: {\"error\":\"invalid_request\",\"error_description\":\"Identity not found\"}"
159+
160+
# Error Type: 403
161+
Notes: Error 403 will come when our Managed Service Identity dont have access to respective destination resource
162+
163+
# When all good, we should get log as below
164+
time="2020-08-24T11:27:59Z" level=info msg="Resolving to user assigned identity, client id is 404b0cc1-ba04-4933-bcea-7d002d184436."
165+
```
166+
167+
168+
## Step-06: Deploy Application and Test
169+
- When dns record set got created in DNS Zone, the log in external-dns should look as below.
170+
171+
### Deploy Application
172+
```t
173+
# Deploy Application
174+
kubectl apply -f kube-manifests/02-NginxApp1
175+
176+
# Verify Pods and Services
177+
kubectl get po,svc
178+
179+
# Verify Ingress
180+
kubectl get ingress
181+
```
182+
183+
### Verify logs in External DNS Pod
184+
- Wait for 3 to 5 minutes for Record Set update in DNZ Zones
185+
```t
186+
# Verify ExternalDNS Logs
187+
kubectl logs -f $(kubectl get po | egrep -o 'external-dns[A-Za-z0-9-]+')
188+
```
189+
- External DNS Pod Logs
190+
```log
191+
time="2020-08-24T11:30:54Z" level=info msg="Updating A record named 'eapp1' to '20.37.141.33' for Azure DNS zone 'kubeoncloud.com'."
192+
time="2020-08-24T11:30:55Z" level=info msg="Updating TXT record named 'eapp1' to '\"heritage=external-dns,external-dns/owner=default,external-dns/resource=ingress/default/nginxapp1-ingress-service\"' for Azure DNS zone 'kubeoncloud.com'."
193+
```
194+
195+
### Verify Record Set in DNZ Zones -> kubeoncloud.com
196+
- Go to All Services -> DNS Zones -> kubeoncloud.com
197+
- Verify if we have `eapp1.kubeoncloud.com` created
198+
```t
199+
# Template Command
200+
az network dns record-set a list -g <Resource-Group-dnz-zones> -z <yourdomain.com>
201+
202+
# Replace DNS Zones Resource Group and yourdomain
203+
az network dns record-set a list -g dns-zones -z kubeoncloud.com
204+
```
205+
- Perform `nslookup` test
206+
```t
207+
# nslookup Test
208+
Kalyans-MacBook-Pro:01-ExternalDNS kdaida$ nslookup eapp1.kubeoncloud.com
209+
Server: 192.168.0.1
210+
Address: 192.168.0.1#53
211+
212+
Non-authoritative answer:
213+
Name: eapp1.kubeoncloud.com
214+
Address: 20.37.141.33
215+
216+
Kalyans-MacBook-Pro:01-ExternalDNS kdaida$
217+
```
218+
219+
### Access Application and Test
220+
```t
221+
# Access Application
222+
http://eapp1.kubeoncloud.com
223+
http://eapp1.kubeoncloud.com/app1/index.html
224+
225+
# Note: Replace kubeoncloud.com with your domain name
226+
```
227+
228+
## Step-07: Clean-Up
229+
```t
230+
# Delete Application
231+
kubectl delete -f kube-manifests/02-NginxApp1
232+
233+
# Verify External DNS pod to ensure record set got deleted
234+
kubectl logs -f $(kubectl get po | egrep -o 'external-dns[A-Za-z0-9-]+')
235+
236+
# Verify Record set got automatically deleted in DNS Zones
237+
# Template Command
238+
az network dns record-set a list -g <Resource-Group-dnz-zones> -z <yourdomain.com>
239+
240+
# Replace DNS Zones Resource Group and yourdomain
241+
az network dns record-set a list -g dns-zones -z kubeoncloud.com
242+
```
243+
244+
```log
245+
time="2020-08-24T12:08:52Z" level=info msg="Deleting A record named 'eapp1' for Azure DNS zone 'kubeoncloud.com'."
246+
time="2020-08-24T12:08:53Z" level=info msg="Deleting TXT record named 'eapp1' for Azure DNS zone 'kubeoncloud.com'."
247+
```
248+
249+
## References
250+
- https://github.com/kubernetes-sigs/external-dns/blob/master/docs/tutorials/azure.md
251+
- Open Issue and Break fix: https://github.com/kubernetes-sigs/external-dns/issues/1548
252+
- https://github.com/kubernetes/ingress-nginx/tree/master/charts/ingress-nginx#configuration
253+
- https://github.com/kubernetes/ingress-nginx/blob/master/charts/ingress-nginx/values.yaml
254+
- https://kubernetes.github.io/ingress-nginx/
255+
256+
## External DNS References
257+
- https://github.com/kubernetes-sigs/external-dns
258+
- https://github.com/kubernetes-sigs/external-dns/blob/master/docs/faq.md
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
{
2+
"tenantId": "c81f465b-99f9-42d3-a169-8082d61c677a",
3+
"subscriptionId": "82808767-144c-4c66-a320-b30791668b0a",
4+
"resourceGroup": "dns-zones",
5+
"useManagedIdentityExtension": true,
6+
"userAssignedIdentityID": "97e867dc-ee8c-4f89-bb81-db7c36dca3dc"
7+
}
Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
apiVersion: v1
2+
kind: ServiceAccount
3+
metadata:
4+
name: external-dns
5+
---
6+
apiVersion: rbac.authorization.k8s.io/v1beta1
7+
kind: ClusterRole
8+
metadata:
9+
name: external-dns
10+
rules:
11+
- apiGroups: [""]
12+
resources: ["services","endpoints","pods"]
13+
verbs: ["get","watch","list"]
14+
- apiGroups: ["extensions","networking.k8s.io"]
15+
resources: ["ingresses"]
16+
verbs: ["get","watch","list"]
17+
- apiGroups: [""]
18+
resources: ["nodes"]
19+
verbs: ["list"]
20+
---
21+
apiVersion: rbac.authorization.k8s.io/v1beta1
22+
kind: ClusterRoleBinding
23+
metadata:
24+
name: external-dns-viewer
25+
roleRef:
26+
apiGroup: rbac.authorization.k8s.io
27+
kind: ClusterRole
28+
name: external-dns
29+
subjects:
30+
- kind: ServiceAccount
31+
name: external-dns
32+
namespace: default
33+
---
34+
apiVersion: apps/v1
35+
kind: Deployment
36+
metadata:
37+
name: external-dns
38+
spec:
39+
strategy:
40+
type: Recreate
41+
selector:
42+
matchLabels:
43+
app: external-dns
44+
template:
45+
metadata:
46+
labels:
47+
app: external-dns
48+
spec:
49+
serviceAccountName: external-dns
50+
containers:
51+
- name: external-dns
52+
image: registry.opensource.zalan.do/teapot/external-dns:latest
53+
args:
54+
- --source=service
55+
- --source=ingress
56+
#- --domain-filter=example.com # (optional) limit to only example.com domains; change to match the zone created above.
57+
- --provider=azure
58+
#- --azure-resource-group=externaldns # (optional) use the DNS zones from the specific resource group
59+
volumeMounts:
60+
- name: azure-config-file
61+
mountPath: /etc/kubernetes
62+
readOnly: true
63+
volumes:
64+
- name: azure-config-file
65+
secret:
66+
secretName: azure-config-file
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
apiVersion: apps/v1
2+
kind: Deployment
3+
metadata:
4+
name: app1-nginx-deployment
5+
labels:
6+
app: app1-nginx
7+
spec:
8+
replicas: 1
9+
selector:
10+
matchLabels:
11+
app: app1-nginx
12+
template:
13+
metadata:
14+
labels:
15+
app: app1-nginx
16+
spec:
17+
containers:
18+
- name: app1-nginx
19+
image: stacksimplify/kube-nginxapp1:1.0.0
20+
ports:
21+
- containerPort: 80
22+
23+
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
apiVersion: v1
2+
kind: Service
3+
metadata:
4+
name: app1-nginx-clusterip-service
5+
labels:
6+
app: app1-nginx
7+
spec:
8+
type: ClusterIP
9+
selector:
10+
app: app1-nginx
11+
ports:
12+
- port: 80
13+
targetPort: 80

0 commit comments

Comments
 (0)