본문 바로가기
클라우드/Azure

[DNS] External DNS 연동 테스트

by worldcenter 2025. 1. 23.

 

 

Azure Kubernetes에서 Azure Application Gateway Ingress Controller를 사용할 때 AKS 내부에서 Ingress 생성 시 자동적으로 Azure Private DNS에 Record가 등록되도록 하는 테스트를 진행합니다.

이 때 External DNS 플러그인을 사용하여 구성해보도록 하겠습니다.

 

 

테스트 환경

  • Azure Kubernetes 1.27.3
  • AGIC 생성
  • 테스트를 위해 nginx deployment, ClusterIP Service 생성

  • Azure Private DNS 생성

 

 

External DNS 배포

1. External DNS Deployment가 Azure Private DNS에 접근 가능하도록 권한 생성 및 권한 부여가 필요합니다. Azure는 다음의 3가지 방식을 제공합니다.

1) Service Principal

2) Kubelet Identity(Managed Identity)

3) Pod Identity(deprecated)

 

2. 금번 테스트에서는 Managed Identity를 사용하여 테스트 합니다. 먼저 kubelet identity ID 값을 조회합니다.

PRINCIPAL_ID=$(az aks show --resource-group $CLUSTER_GROUP --name $CLUSTERNAME \
  --query "identityProfile.kubeletidentity.objectId" --output tsv)

 

3. 또는 Kubenetes Node에 Debug Pod로 접속 후 /etc/kubernetes/azure.json 파일에서 조회 가능합니다.

 

4. Kubelet Identity에 대해 Azure Private DNS Zone 접근 권한을 부여합니다.

AZURE_DNS_ZONE="example.com" # DNS zone name like example.com or sub.example.com
AZURE_DNS_ZONE_RESOURCE_GROUP="MyDnsResourceGroup" # resource group where DNS zone is hosted

# fetch DNS id used to grant access to the kublet identity
DNS_ID=$(az network dns zone show --name $AZURE_DNS_ZONE \
  --resource-group $AZURE_DNS_ZONE_RESOURCE_GROUP --query "id" --output tsv)

az role assignment create --role "DNS Zone Contributor" --assignee $PRINCIPAL_ID --scope $DNS_ID

 

5. Local PC에 다음 값을 저장합니다.

cat <<-EOF > /local/path/to/azure.json
{
  "tenantId": "$(az account show --query tenantId -o tsv)",
  "subscriptionId": "$(az account show --query id -o tsv)",
  "resourceGroup": "$AZURE_DNS_ZONE_RESOURCE_GROUP",
  "useManagedIdentityExtension": true
  "userAssignedIdentityID": "<Managed Identity ID>"
}
EOF

 

6. 인증 정보를 Secret으로 생성합니다.

kubectl create secret generic azure-config-file --namespace "kube-system" --from-file /local/path/to/azure.json

 

7. External DNS manifest를 배포합니다.

apiVersion: v1
kind: ServiceAccount
metadata:
  name: externaldns
  namespace: kube-system
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
  name: externaldns
rules:
- apiGroups: [""]
  resources: ["services"]
  verbs: ["get","watch","list"]
- apiGroups: [""]
  resources: ["pods"]
  verbs: ["get","watch","list"]
- apiGroups: ["networking","networking.k8s.io"]
  resources: ["ingresses"]
  verbs: ["get","watch","list"]
- apiGroups: [""]
  resources: ["nodes"]
  verbs: ["get","watch","list"]
- apiGroups: [""]
  resources: ["endpoints"]
  verbs: ["get","watch","list"]
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
  name: externaldns-viewer
roleRef:
  apiGroup: rbac.authorization.k8s.io
  kind: ClusterRole
  name: externaldns
subjects:
- kind: ServiceAccount
  name: externaldns
  namespace: kube-system
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: externaldns
  namespace: kube-system
spec:
  selector:
    matchLabels:
      app: externaldns
  strategy:
    type: Recreate
  template:
    metadata:
      labels:
        app: externaldns
    spec:
      serviceAccountName: externaldns
      containers:
      - name: externaldns
        image: registry.k8s.io/external-dns/external-dns:v0.13.5
        args:
        - --source=service
        - --source=ingress
        - --domain-filter=<DNS Domain>
        - --provider=azure-private-dns
        - --azure-resource-group=<Azure DNS가 배포된 Resource Group>
        - --azure-subscription-id=<SubscriptionID>
        - --txt-owner-id=<String>
        volumeMounts:
        - name: azure-config-file
          mountPath: /etc/kubernetes
          readOnly: true
      volumes:
      - name: azure-config-file
        secret:
          secretName: azure-config-file

 

8. ExternalDNS 생성 후 Ingress를 생성합니다.

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  annotations:
    appgw.ingress.kubernetes.io/backend-protocol: http
    appgw.ingress.kubernetes.io/use-private-ip: "true"
  name: nginx-ingress
spec:
  ingressClassName: azure-application-gateway
  rules:
  - host: nginx.gaonnuri.site
    http:
      paths:
      - backend:
          service:
            name: nginx-ap-deploy
            port:
              number: 80
        path: /
        pathType: Prefix

 

9. Ingress 생성이 완료되면 Applicatin Gateway에 자동으로 반영되고 Azure Private DNS도 Record가 자동으로 반영됩니다.