はじめに
お名前.comで取得したドメインを利用して、
EKSにExternalDNS用のポッドを作成して、指定のFQDNでサービスにアクセスする方法について記載します。
前提
- AWSのリソースはterraformを利用してデプロイします。
- terraformバージョン:
v0.15.1
- terraformバージョン:
- kubernetesはkubectlのcliを利用して操作します。
- kubernetesバージョン:
1.19
- kubernetesバージョン:
- 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
}
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のトップ画面が表示されていれば、設定完了です。