0
0

More than 1 year has passed since last update.

TerraformでEKS+ExternalDNSでサービスを公開する方法

Last updated at Posted at 2021-05-29

はじめに

お名前.comで取得したドメインを利用して、
EKSにExternalDNS用のポッドを作成して、指定のFQDNでサービスにアクセスする方法について記載します。

前提

  • AWSのリソースはterraformを利用してデプロイします。
    • terraformバージョン: v0.15.1
  • kubernetesはkubectlのcliを利用して操作します。
    • kubernetesバージョン: 1.19
  • EKSは作成済みとします。
  • ドメインは既に取得できているものとします。
    • 本ページでは取得したドメインをsample.comとします。

ドメインをドメインをroute53に割り当て

ドメイン名は取得したドメインそのまま記載してデプロイする

resource "aws_route53_zone" "main" {
  name = "sample.com"
}

ポリシーを作成

ExternalDNSからroute53を操作するためのポリシーを設定します。
以下ポリシーを作成します。

resource "aws_iam_policy" "external-dns-policy" {
  name   = "external-dns-policy"
  policy = <<POLICY
{
"Version": "2012-10-17",
 "Statement": [
   {
     "Effect": "Allow",
     "Action": [
       "route53:ChangeResourceRecordSets"
     ],
     "Resource": [
       "arn:aws:route53:::hostedzone/*"
     ]
   },
   {
     "Effect": "Allow",
     "Action": [
       "route53:ListHostedZones",
       "route53:ListResourceRecordSets"
     ],
     "Resource": [
       "*"
     ]
   }
 ]
}
POLICY
}

また、EKSが発行したトークンを信頼させるため、IAMのOIDCプロバイダーというエンティティを利用したjson形式のポリシーを作成する。

data "aws_iam_policy_document" "external-dns-assume-role-policy" {
  statement {
    actions = ["sts:AssumeRoleWithWebIdentity"]
    effect  = "Allow"

    condition {
      test     = "StringEquals"
      variable = "${replace(aws_eks_cluster.eks-cluster.identity[0].oidc[0].issuer, "https://", "")}:sub"
      values   = ["system:serviceaccount:default:external-dns"]
    }

    principals {
      identifiers = ["arn:aws:iam::${data.aws_caller_identity.current.account_id}:oidc-provider/${replace(aws_eks_cluster.<eksクラスタのリソース名>.identity[0].oidc[0].issuer, "https://", "")}"]
      type        = "Federated"
    }
  }
}

IAMロールの作成とポリシーのアタッチ

ExternalDNS用のIAMロールを作成し、
先ほど作成したポリシーを適用する。

resource "aws_iam_role" "external-dns-role" {
  name               = "external-dns-role"
  assume_role_policy = data.aws_iam_policy_document.external-dns-assume-role-policy.json
}

resource "aws_iam_role_policy_attachment" external-dns-policy-attachment" {
  policy_arn = aws_iam_policy.external-dns-policy.arn
  role       = aws_iam_role.external-dns-role.name
}

作成したロールにポリシーが適用されているか確認
ポリシー確認.png

信頼されたエンティティが登録されているか確認
oidc-provider.png

ExternalDNSをデプロイ

ServiceAccountの作成

ExternalDNSを操作するためのsaを作成します。
annotationsには先ほど作成したロール(external-dns-role)のarnをアタッチします。

以下コマンドでデプロイを実行
kubectl apply -f external_dns_sa.yml

  • external_dns_sa.yml
apiVersion: v1
kind: ServiceAccount
metadata:
  name: external-dns
  namespace: default
  annotations:
      eks.amazonaws.com/role-arn: <external-dns-roleのarn>
---
apiVersion: rbac.authorization.k8s.io/v1beta1
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/v1beta1
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: default

ExternalのDeploymentの作成

ExternalDNSをデプロイするためのマニフェストファイルを作成します。
annotationsに先ほど作成したロール(external-dns-role)のarnをアタッチします。

以下コマンドでExternalDNSをデプロイします。
kubectl apply -f external_dns_deployment.yml

  • external_dns_deployment.yml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: external-dns
  namespace: default
spec:
  strategy:
    type: Recreate
  selector:
    matchLabels:
      app: external-dns
  template:
    metadata:
      labels:
        app: external-dns
      annotations:
        iam.amazonaws.com/role: <external-dns-roleのarn>
    spec:
      serviceAccountName: external-dns
      containers:
      - name: external-dns
        image: k8s.gcr.io/external-dns/external-dns:v0.8.0
        args:
        - --source=service
        - --source=ingress
        - --domain-filter=sample.com
        - --provider=aws
        - --policy=sync
        - --aws-zone-type=public
        - --registry=txt
        - --txt-owner-id=<samplr.comのホストゾーンID>
      securityContext:
        fsGroup: 65534

正常にデプロイできたか確認

$ kubectl get pods
NAME                            READY   STATUS    RESTARTS   AGE
external-dns-xxxxxxxxxx   1/1     Running   0          10m

コマンドを実行して以下のような最後の方にログが出力されていれば正常に終了している

$ kubectl logs external-dns-xxxxxxxxxx
-------
time="2020-05-05T02:57:31Z" level=info msg="All records are already up to date"

サンプルアプリケーションのデプロイ

以下マニフェストファイルを基にサンプルアプリケーションをデプロイして
名前解決できるか確認する

  • sample_deployment.yml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: sample-deployment
spec:
  selector:
    matchLabels:
      app: sample-app
  replicas: 2
  template:
    metadata:
      labels:
        app: sample-app
    spec:
      containers:
      - name: nginx-container
        image: nginx:latest
        ports:
        - containerPort: 80
  • sample_service.yml
    annotationsに任意のサブドメインを設定する。
apiVersion: v1
kind: Service
metadata:
  name: sample-service
  annotations:
    external-dns.alpha.kubernetes.io/hostname: test.sample.com
spec:
  type: LoadBalancer
  selector:
    app: sample-app
  ports:
  - protocol: TCP
    port: 80
    targetPort: 80

以下コマンド実行してwebブラウザから
http://test.sample.comにアクセスできるか確認

kubectl apply -f sample_deployment.yml
kubectl apply -f sample_service.yml

以下のようなnginxのトップ画面が表示されていれば、設定完了です。
nginx.png

参考

0
0
1

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0