Skip to content

Commit 3143f6c

Browse files
Kalyan Reddy DaidaKalyan Reddy Daida
authored andcommitted
Welcome to Stack Simplify
1 parent 66d1283 commit 3143f6c

File tree

7 files changed

+380
-1
lines changed

7 files changed

+380
-1
lines changed

11-Delegate-Domain-from-AWS-Route53-to-Azure-DNS/README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
# Deletegate Domain to Azure DNS
1+
# Delegate Domain to Azure DNS
22

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

0 commit comments

Comments
 (0)