ExternalDNS란?
ExternalDNS는 kubernetes dns(kube-dns)와 상반되는 개념으로 내부 도메인서버가 아닌 Public한 도메인서버(AWS Route53, GCP DNS 등)를 사용하여 쿠버네티스의 리소스를 쿼리할 수 있게 해주는 오픈소스 솔루션입니다.
ExternalDNS를 사용하면 public도메인 서버가 무엇이든 상관없이 쿠버네티스 리소스를 통해서 DNS레코드를 동적으로 관리 할 수 있습니다. 많은 기업들이 두려워하는 Vendor Lock-In에 좀 더 자유로워 질 수 있게 되는 것이죠.
사용가능한 public DNS 제공 업체들
ExternalDNS를 사용할 수 있는 public DNS서버들은 다음 URL을 https://github.com/kubernetes-sigs/external-dns#the-latest-release-v08 참고하면 자세히 확인이 가능하며 대표적인 몇개만 나열해보도록 하겠습니다.
- Google Cloud DNS
- AWS Route 53
- AzureDNS
- BlueCat
- CloudFlare
- RcodeZero
- DigitalOcean
- Hetzne
- Oracle Cloud Infrastructure DNS
... 등등 (처음 보는 업체들도 많이 있네요)
역시 우리의 오픈소스 쿠버네티스는 관대합니다만 역시나 오픈소스이기 때문에 모든 업체를 stability 한 레벨로 지원해주고 있지는 않습니다. 차츰 개선되겠지만 그 기간이 얼마나 걸릴지는 파악하기가 힘들죠. (오픈소스의 최대 단점 중 하나입니다.)
현재 2021.09 기준으로 GCP DNS, AWS Route53이 stable단계 이며 나머지는 모두 Alpha, Beta 단계 입니다.
ExternalDNS 설치
ExternalDNS설치는 AWS EKS클러스터 기준으로 설명드리겠습니다.
쿠버네티스 Namespace생성
논리적으로 구분하여 관리하기위해 ExternalDNS용도의 namespace를 생성합니다.
kubectl create namespace external-dns
IAM Policy 생성
ExternalDNS가 AWS Route53를 제어해야 하기 때문에 그에 대한 권한 정책을 생성 하는 작업입니다.
조금 자세히 설명드리면 쿠버네티스는 OIDC(OpenID Connect)를 통해 인증을 할 수 있도록 설계되어있습니다. OIDC 기술은 IDP(Idetytity Providers)에 의해 제공되며 사용자가 어떤 행위를 할 수 있는지를 인증해주게 됩니다.
AWS EKS 또한 OIDC를 지원하하는데, AWS IAM의 IDP에서 OIDC를 생성하여 사용할 수 있습니다.
아래의 json형식의 policy를 AllowExternalDNSUpdates
라는 이름으로 으로 생성하겠습니다.
(aws cli를 사용 하며 aws cli설치 및 aws configure 설정은 생략하였습니다.)
cat > AllowExternalDNSUpdates.json << EOF
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"route53:ChangeResourceRecordSets"
],
"Resource": [
"arn:aws:route53:::hostedzone/*"
]
},
{
"Effect": "Allow",
"Action": [
"route53:ListHostedZones",
"route53:ListResourceRecordSets"
],
"Resource": [
"*"
]
}
]
}
EOF
aws iam create-policy --policy-name AllowExternalDNSUpdates --policy-document file://AllowExternalDNSUpdates.json
Create IAM Role
쿠버네티스 문에는 kiam 또는 kube2iam 으로 생성했을 경우와 1.13버전 이상의 EKS Cluster의 경우가 있는데 저희는 후자인 1.13버전 이상의 EKS Cluster의 경우만 보도록 하겠습니다.
(eksctl을 사용하며 설치방법은 생략하겠습니다.)
service_account_name
: ExternalDNS service account명 입력 (=external-dns)
service_account_namespace
: ExternalDNS namespace명 입력 (=external-dns)
cluster_name
: EKS클러스터명
IAM_policy_ARN
: 위에서 생성한 policy arn (예시: arn:aws:iam::AWS_ACCOUNT_ID:policy/AllowExternalDNSUpdates)
eksctl create iamserviceaccount \
--name <service_account_name> \
--namespace <service_account_namespace> \
--cluster <cluster_name> \
--attach-policy-arn <IAM_policy_ARN> \
--approve \
--override-existing-serviceaccounts
External DNS 배포 (RBAC을 사용하는 경우)
apiVersion: v1
kind: ServiceAccount
metadata:
name: external-dns
# If you're using Amazon EKS with IAM Roles for Service Accounts, specify the following annotation.
# Otherwise, you may safely omit it.
annotations:
# Substitute your account ID and IAM service role name below.
eks.amazonaws.com/role-arn: arn:aws:iam::ACCOUNT-ID:role/IAM-SERVICE-ROLE-NAME
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
name: external-dns
rules:
- apiGroups: [""]
resources: ["services","endpoints","pods"]
verbs: ["get","watch","list"]
- apiGroups: ["extensions","networking.k8s.io"]
resources: ["ingresses"]
verbs: ["get","watch","list"]
- apiGroups: [""]
resources: ["nodes"]
verbs: ["list","watch"]
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
name: external-dns-viewer
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
name: external-dns
subjects:
- kind: ServiceAccount
name: external-dns
namespace: external-dns ## 이부분 공식문서와 다릅니다. 공식문서는 default
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: external-dns
spec:
strategy:
type: Recreate
selector:
matchLabels:
app: external-dns
template:
metadata:
labels:
app: external-dns
spec:
serviceAccountName: external-dns
containers:
- name: external-dns
image: k8s.gcr.io/external-dns/external-dns:v0.7.6
args:
- --source=service
- --source=ingress
- --domain-filter=external-dns-test.my-org.com # will make ExternalDNS see only the hosted zones matching provided domain, omit to process all available hosted zones
- --provider=aws
- --policy=upsert-only # would prevent ExternalDNS from deleting any records, omit to enable full synchronization
- --aws-zone-type=public # only look at public hosted zones (valid values are public, private or no value for both)
- --registry=txt
- --txt-owner-id=my-hostedzone-identifier
securityContext:
fsGroup: 65534 # For ExternalDNS to be able to read Kubernetes and AWS token files
여기서 몇가지 변수값에 대해 설명 드리겠습니다.
eks.amazonaws.com/role-arn
: 위에서 생성한 IAM Role의 arndomain-filter
: Route53에 생성되어있는 hostzone 명policy
: Route53을 제어하는 정책 설정
- upsert-only : 레코드셋 생성,업데이트 (삭제 불가능)
- sync : 레코듯셋 생성,업데이트,삭제
- create-only: 레코드셋 생성 (삭제, 업데이트 불가능)
txt-owner-id
: Route53 에 hostzone을 생성하면 Z로 시작하는 ID 할당되며 해당 ID를 입력
여기서 policy 타입 설정이 중요합니다. 도메인은 실제 고객이 서비스를 사용하기 위한 최상단의 접점이기 때문에 엄격하게 관리되어야 합니다. 예제에서도 upsert-only 로 되어있듯이 삭제는 관리자가 직접 눈으로 보고 삭제할 것을 권장 합니다.
ExternalDNS 동작확인 예제
external-dns.alpha.kubernetes.io/hostname
부분은 실제 테스트할 도메인으로 변경
apiVersion: v1
kind: Service
metadata:
name: nginx
annotations:
external-dns.alpha.kubernetes.io/hostname: test.kimdragon50.ml
spec:
type: LoadBalancer
ports:
- port: 80
name: http
targetPort: 80
selector:
app: nginx
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx
spec:
selector:
matchLabels:
app: nginx
template:
metadata:
labels:
app: nginx
spec:
containers:
- image: nginx
name: nginx
ports:
- containerPort: 80
name: http
externaldns 로그 확인하여 실제 레코드 생성되는지 확인
kubectl logs -f external-dns-75c947bf69-v8qdc -n external-dns
'IT > DevOps' 카테고리의 다른 글
자주 사용하는 도커(Docker) 명령어 정리 (0) | 2021.10.08 |
---|---|
[kubnernetes] 디스크 볼륨 타입 유형 비교 (emptyDir vs hostPath) (1) | 2021.10.06 |
Pod Anti-Affinity를 사용한 Kubernetes pod Multi-AZ 배포 (2) | 2021.09.14 |
Locust 부하테스트 사용하기(Locust란?/Locust설치/예제) (0) | 2021.09.13 |
Kubernetes PVC를 Amazon EFS로 구성하기 (0) | 2021.09.13 |