AWS EKS에서 동작중인 컨테이너에 External DNS로 도메인 연결하기

김철기·2022년 6월 15일
2

Kubernetes

목록 보기
3/5
post-thumbnail

안녕하세요. Gameeye에서 deeplol.gg 서비스를 개발 중인 김철기입니다.
클라우드 서버 인프라 구축, 백엔드 개발, 딥러닝 모델 연구를 담당하고 있습니다.

목차

External DNS

  • External DSN란?
  • External DNS 설치
  • External DNS 배포

서비스 배포

  • 컨테이너에 도메인 연결하기

이전 포스팅에서 AWS EKS로 쿠버네티스를 구축하고 예제 컨테이너를 배포하는 작업을 해보았습니다. 이번 포스팅에서는 external-dns를 사용해 Route53에서 관리중인 도메인에 연결하는 작업을 해보겠습니다🖕
(기본적인 Route53의 사용법, ssl의 개념은 숙지되었다는 가정하에 진행되는 포스팅입니다.)
AWS EKS로 Kubernetes를 사용해보자
Kubernetes에 Docker 컨테이너 배포하기

External DNS

External DNS란?

Public한 도메인서버를 사용하여 쿠버네티스의 리소스를 쿼리할 수 있게 해주는 오픈소스 솔루션입니다. 도메인서버에 종속되지 않고 쿠버네티스 리소스를 통해 DNS레코드를 동적으로 관리할 수 있는 장점이 있습니다.

사용가능한 public 도메인서버 제공 업체는 아래 링크를 참고해주세요
https://github.com/kubernetes-sigs/external-dns#the-latest-release-v08

External DNS 설치

쿠버네티스 서비스 계정에 IAM 역할을 사용하려면 OIDC 공급자가 필요합니다. IAM OIDC 자격 증명 공급자를 생성합니다.

eksctl utils associate-iam-oidc-provider --cluster {cluster name} --approve

External DNS용도의 구분된 namespace를 생성합니다.

kubectl create namespace external-dns

External DNS가 Route53을 제어할 수 있도록 정책을 생성해줍니다. IAM Policy json 파일을 생성해줍니다.

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Action": [
        "route53:ChangeResourceRecordSets"
      ],
      "Resource": [
        "arn:aws:route53:::hostedzone/*"
      ]
    },
    {
      "Effect": "Allow",
      "Action": [
        "route53:ListHostedZones",
        "route53:ListResourceRecordSets"
      ],
      "Resource": [
        "*"
      ]
    }
  ]
}

생성한 json파일로 IAM Policy를 생성합니다.

aws iam create-policy --policy-name AllowExternalDNSUpdates --policy-document file://{json file name}.json

eksctl을 이용하여 iam service account를 생성합니다.

eksctl create iamserviceaccount \
    --name <service_account_name> \ ### Exteranl DNS service account명 = external-dns
    --namespace <service_account_namespace> \ ### External DNS namespace명 = external-dns
    --cluster <cluster_name> \ ### AWS EKS 클러스터명
    --attach-policy-arn <IAM_policy_ARN> \ ### 앞서 생성한 Policy arn
    --approve \
    --override-existing-serviceaccounts

주의사항
클러스터 노드 IAM Role에 Route53 접근권한이 설정되지 않는 경우 배포가 되지 않습니다. 확인해보시고 적용이 안되었으면 IAM Role 콘솔에서 직접 적용해주시면 됩니다.

External DNS 배포

공식 문서를 참고하여 yaml파일을 작성하고 배포합니다.
https://aws.amazon.com/ko/premiumsupport/knowledge-center/eks-set-up-externaldns/

apiVersion: v1
kind: ServiceAccount
metadata:
  name: external-dns
  namespace: 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
  namespace: 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
  namespace: external-dns
roleRef:
  apiGroup: rbac.authorization.k8s.io
  kind: ClusterRole
  name: external-dns
subjects:
- kind: ServiceAccount
  name: external-dns
  namespace: external-dns
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: external-dns
  namespace: 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과 domain-filter만 정확하게 입력해주시면 됩니다.
policy의 경우 Route53에서 레코드 업데이트를 제어하는 정책입니다.

  • upsert-only: 생성, 업데이트
  • sync: 생성, 업데이트, 삭제
  • create-only: 생성

레코드를 갱신하는 민감한 부분입니다. 삭제가 가능한 sync 인자를 사용시 유의하시기 바랍니다.

서비스 배포

컨테이너에 도메인 연결하기

이전 포스팅에서 배포했었던 mario 컨테이너에 도메인을 연결해보겠습니다.
mario.yaml 파일을 수정합니다.

apiVersion: apps/v1
kind: Deployment
metadata:
  name: mario
  labels:
    app: mario
spec:
  replicas: 1
  selector:
    matchLabels:
      app: mario
  template:
    metadata:
      labels:
        app: mario
    spec:
      containers:
      - name: mario
        image: {}.amazonaws.com/mario-test ### ecr URI를 입력하세요.
---
apiVersion: v1
kind: Service
metadata:
   name: mario
   annotations:
     external-dns.alpha.kubernetes.io/hostname: test.mario.org ### 보유중인 도메인을 입력하세요.
    service.beta.kubernetes.io/aws-load-balancer-ssl-cert: arn:aws:acm:ap-northeast-2:{accountId}:certificate/{} ### 보유중인 ssl cert의 arn을 입력하세요.
    service.beta.kubernetes.io/aws-load-balancer-backend-protocol: http
    service.beta.kubernetes.io/aws-load-balancer-ssl-ports: https
spec:
  selector:
    app: mario
  ports:
  - name: http
	protocol: TCP
	port: 80
	targetPort: 8080
  - name: https
	port: 443
	targetPort: 8080
  protocol: TCP
  type: LoadBalancer

배포된 external-dns의 로그를 확인해서 레코드가 정상적으로 생성되는지 확인할 수 있습니다.

kubectl logs -f {external-dns pod name} -n external-dns

마무리

어느덧 클러스터 구축, 서비스 배포, 도메인 연결까지 완료했습니다. 추후 운영에 필요한 모니터링과 CI/CD 내용으로 포스팅을 이어가도록 하겠습니다💪
잘못된 내용이 있거나 궁금한 부분이 있으시면 댓글남겨주시면 답변 드리겠습니다🙂

참고

https://kim-dragon.tistory.com/146
https://zigispace.net/1160

profile
Deepveloper, deeplol.gg, fleaman.shop

0개의 댓글