external-dnsを試してみたメモ。
前回AWS Load Balancer Controllerを試したクラスターをそのまま使う。
コンポーネント | バージョン | 備考 |
---|---|---|
eksctl | 0.30.0 | |
Kubernetes バージョン | 1.18 | |
プラットフォームのバージョン | eks.1 | |
aws-load-balancer-controller | 2.0.0 | |
external-dns | 1.7.3 |
以下に従って導入する。
準備
パブリックホストゾーンを作成する。
aws route53 create-hosted-zone --name "sotoiwa.dev." --caller-reference "external-dns-test-$(date +%s)"
お名前.comの側にて、ここで出力されたネームサーバーを設定する。
導入
IAM ポリシーを作成する。
cat <<EOF > 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": [ "*" ] } ] } EOF aws iam create-policy \ --policy-name ExternalDNSIAMPolicy \ --policy-document file://iam-policy.json
IAMロールとServiceAccountを作成する。
eksctl create iamserviceaccount \ --cluster=mycluster \ --namespace=kube-system \ --name=external-dns \ --attach-policy-arn=arn:aws:iam::XXXXXXXXXXXX:policy/ExternalDNSIAMPolicy \ --override-existing-serviceaccounts \ --approve
ServiceAccountを確認する。
$ kubectl get sa external-dns -n kube-system -o yaml | kubectl neat apiVersion: v1 kind: ServiceAccount metadata: annotations: eks.amazonaws.com/role-arn: arn:aws:iam::XXXXXXXXXXXX:role/eksctl-mycluster-addon-iamserviceaccount-kub-Role1-AQ9HDHDEEAMI name: external-dns namespace: kube-system secrets: - name: external-dns-token-s8pn8
external-dnsをデプロイする。
Helmチャートもある。公式のは非推奨となり、Bitnamiが作成しているものが推奨のよう。
$ helm search repo external-dns NAME CHART VERSION APP VERSION DESCRIPTION bitnami/external-dns 3.5.0 0.7.4 ExternalDNS is a Kubernetes addon that configur... stable/external-dns 2.20.4 0.7.0 DEPRECATED ExternalDNS is a Kubernetes addon th...
今回はチュートリアルに記載のあるマニフェストを適用する。チュートリアルで公開されているものから以下を変更する。
- ServiceAccountは作成済みでアノテーションも設定済みなので、その記載に合わせる
--domain-filter
を作成したホストゾーンのドメイン名に合わせる- ClusterRoleBindingで
default
Namespaceが指定されているので、今回デプロイするNamespaceに合わせる - レコードの削除もさせるため、
--policy
をsync
にする - IRSAを使用するためDeploymentでのIAMロールのアノテーションは削除
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::XXXXXXXXXXXX:role/eksctl-mycluster-addon-iamserviceaccount-kub-Role1-AQ9HDHDEEAMI --- 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: kube-system --- 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.3 args: - --source=service - --source=ingress - --domain-filter=sotoiwa.dev # will make ExternalDNS see only the hosted zones matching provided domain, omit to process all available hosted zones - --provider=aws - --policy=sync # 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
デプロイする。Namespaceは専用に作ってもよいかも知れないが、今回はkube-system
Namespaceにデプロイする。
$ kubectl apply -f external-dns.yaml -n kube-system Warning: kubectl apply should be used on resource created by either kubectl create --save-config or kubectl apply serviceaccount/external-dns configured clusterrole.rbac.authorization.k8s.io/external-dns created clusterrolebinding.rbac.authorization.k8s.io/external-dns-viewer created deployment.apps/external-dns created
Podが起動していることを確認する。
$ kubectl get pod -n kube-system NAME READY STATUS RESTARTS AGE aws-load-balancer-controller-6c4d8d8f64-6gsw7 1/1 Running 0 3d1h aws-node-chr59 1/1 Running 0 10d aws-node-xzsx5 1/1 Running 0 7d14h coredns-86f7d88d77-d4969 1/1 Running 0 10d coredns-86f7d88d77-fntwt 1/1 Running 0 10d external-dns-869d587bf7-pvf89 1/1 Running 8 26m kube-proxy-bmp9g 1/1 Running 0 7d14h kube-proxy-r7hwz 1/1 Running 0 10d
動作確認
準備
default
Namespaceで試す。
Deploymentのyamlを用意する。
apiVersion: apps/v1 kind: Deployment metadata: name: echoserver spec: replicas: 1 selector: matchLabels: app: echoserver template: metadata: labels: app: echoserver spec: containers: - image: gcr.io/google_containers/echoserver:1.4 imagePullPolicy: Always name: echoserver ports: - containerPort: 8080
Deploymentを作成する。
$ kubectl apply -f echoserver-deployment.yaml deployment.apps/echoserver created
Podの起動を確認する。
$ kubectl get pod NAME READY STATUS RESTARTS AGE echoserver-7c48fd4b7c-9jkq4 1/1 Running 0 70s
Service
Serviceのyamlを用意する。
apiVersion: v1 kind: Service metadata: name: echoserver annotations: external-dns.alpha.kubernetes.io/hostname: test1.sotoiwa.dev spec: type: LoadBalancer ports: - port: 80 name: http targetPort: 8080 selector: app: echoserver
Serviceを作成する。
$ kubectl apply -f echoserver-service-lb.yaml service/nginx created
Serviceを確認する。
$ kubectl get svc NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE echoserver LoadBalancer 10.100.243.210 a7ef2970caed5415088bba5a7f3e9dc9-1308473638.ap-northeast-1.elb.amazonaws.com 80:30046/TCP 42s kubernetes ClusterIP 10.100.0.1 <none>
$ curl a7ef2970caed5415088bba5a7f3e9dc9-1308473638.ap-northeast-1.elb.amazonaws.com CLIENT VALUES: client_address=192.168.78.38 command=GET real path=/ query=nil request_version=1.1 request_uri=http://a7ef2970caed5415088bba5a7f3e9dc9-1308473638.ap-northeast-1.elb.amazonaws.com:8080/ SERVER VALUES: server_version=nginx: 1.10.0 - lua: 10001 HEADERS RECEIVED: accept=*/* host=a7ef2970caed5415088bba5a7f3e9dc9-1308473638.ap-northeast-1.elb.amazonaws.com user-agent=curl/7.54.0 BODY: -no body in request-
マネジメントコンソールでレコードが作成されていることを確認する。
$ curl test1.sotoiwa.dev CLIENT VALUES: client_address=192.168.78.38 command=GET real path=/ query=nil request_version=1.1 request_uri=http://test1.sotoiwa.dev:8080/ SERVER VALUES: server_version=nginx: 1.10.0 - lua: 10001 HEADERS RECEIVED: accept=*/* host=test1.sotoiwa.dev user-agent=curl/7.54.0 BODY: -no body in request-
Serviceを削除する。
$ kubectl delete svc echoserver service "echoserver" deleted
Ingress
Ingressで試す。
ServiceをClusterIPで作り直す。yamlを用意する。
apiVersion: v1 kind: Service metadata: name: echoserver spec: ports: - port: 8080 name: http targetPort: 8080 selector: app: echoserver
Serviceを作成する。
$ kubectl apply -f echoserver-service.yaml service/echoserver created
Serviceを確認する。
$ kubectl get svc NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE echoserver ClusterIP 10.100.39.29 <none> 8080/TCP 24s kubernetes ClusterIP 10.100.0.1 <none> 443/TCP 10d
apiVersion: networking.k8s.io/v1beta1 kind: Ingress metadata: name: echoserver annotations: kubernetes.io/ingress.class: alb alb.ingress.kubernetes.io/scheme: internet-facing alb.ingress.kubernetes.io/target-type: ip spec: rules: - host: test2.sotoiwa.dev http: paths: - path: /* backend: serviceName: echoserver servicePort: 8080
Ingressを作成する。
$ kubectl apply -f echoserver-ingress.yaml ingress.networking.k8s.io/echoserver created
Ingressを確認する。
$ kubectl get ingress NAME CLASS HOSTS ADDRESS PORTS AGE echoserver <none> test2.sotoiwa.dev k8s-default-echoserv-91c6428909-23022959.ap-northeast-1.elb.amazonaws.com 80 80s
マネジメントコンソールでレコードが作成されていることを確認する。
リスナーのルールは以下のようになっている。ホストヘッダーを限定するルールが入ることに注意が必要。
curlでALBのドメイン名でアクセスしてみる。ホストヘッダーを指定しないとリスナールールによって404となる。
$ curl -H "Host: test2.sotoiwa.dev" k8s-default-echoserv-91c6428909-23022959.ap-northeast-1.elb.amazonaws.com CLIENT VALUES: client_address=192.168.12.31 command=GET real path=/ query=nil request_version=1.1 request_uri=http://test2.sotoiwa.dev:8080/ SERVER VALUES: server_version=nginx: 1.10.0 - lua: 10001 HEADERS RECEIVED: accept=*/* host=test2.sotoiwa.dev user-agent=curl/7.54.0 x-amzn-trace-id=Root=1-5f9b0580-28ae7d2723400d580d0e7a61 x-forwarded-for=27.0.3.145 x-forwarded-port=80 x-forwarded-proto=http BODY: -no body in request-
$ curl -H "Host: test2.sotoiwa.dev" test2.sotoiwa.dev CLIENT VALUES: client_address=192.168.12.31 command=GET real path=/ query=nil request_version=1.1 request_uri=http://test2.sotoiwa.dev:8080/ SERVER VALUES: server_version=nginx: 1.10.0 - lua: 10001 HEADERS RECEIVED: accept=*/* host=test2.sotoiwa.dev user-agent=curl/7.54.0 x-amzn-trace-id=Root=1-5f9b05b3-5a3242ae4294f5327c88c281 x-forwarded-for=27.0.3.145 x-forwarded-port=80 x-forwarded-proto=http BODY: -no body in request-