--- title: ExternalDNSを使ってGKEからCloudFlareにIngressのDNSレコードを登録 tags: ["Kubernetes", "GKE", "CloudFlare"] categories: ["Dev", "CaaS", "Kubernetes", "ExternalDNS"] date: 2018-01-08T15:12:48Z updated: 2018-01-08T15:12:48Z --- ### ExternalDNSについて [ExternalDNS](https://github.com/kubernetes-incubator/external-dns)はKubernetesから外部のDNSサービスにService`type: LoadBalancer`やIngressのIPアドレスのDNSレコードを登録してくれます。 v0.4の段階では次のサービスに対応しています。 * [Google CloudDNS](https://cloud.google.com/dns/docs/) * [AWS Route 53](https://aws.amazon.com/route53/) * [AzureDNS](https://azure.microsoft.com/en-us/services/dns) * [CloudFlare](https://www.cloudflare.com/de/dns) * [DigitalOcean](https://www.digitalocean.com/products/networking) * [DNSimple](https://dnsimple.com/) * [Infoblox](https://www.infoblox.com/products/dns/) このブログの証明書を見てもらえば分かりますが、私はCloudFlareを使ってSSL対応をしており、有償オプション($10/month)でDedicatedな証明書を使用しています。 SANでマルチドメインを登録しまくっています。 Kubernetesで`type: LoadBalancer`なサービスやIngressを作る時にAレコードを毎回CloudFlareに登録していて面倒だと思ってたので、このExternalDNSの仕組みはありがたいのです。 (自分でCloudFlareのAPIを叩く何かを作ろうと思っていました...) ### ExternalDNSのデプロイ まずはExternalDNSのデプロイを使うために、`external-dns.yml`を作成します。 ``` yaml apiVersion: extensions/v1beta1 kind: Deployment metadata: name: external-dns namespace: kube-system spec: strategy: type: Recreate template: metadata: labels: app: external-dns spec: containers: - name: external-dns image: registry.opensource.zalan.do/teapot/external-dns:v0.4.8 args: - --source=service - --source=ingress - --domain-filter=ik.am # your domain managed by cloud flare - --provider=cloudflare - --cloudflare-proxied env: - name: CF_API_KEY valueFrom: secretKeyRef: name: cloudflare-secret key: cloudflare-api-key - name: CF_API_EMAIL valueFrom: secretKeyRef: name: cloudflare-secret key: cloudflare-api-email ``` `CF_API_KEY`と`CF_API_EMAIL`の内容は`cloudflare-secret.yml`に設定しておきます。 ``` yaml apiVersion: v1 kind: Secret metadata: name: cloudflare-secret namespace: kube-system type: Opaque data: cloudflare-api-key: ********** # echo -n | base64 cloudflare-api-email: ********** # echo -n | base64 ``` これらをデプロイします。 ``` kubectl apply -f cloudflare-secret.yml kubectl apply -f external-dns.yml ``` これでExternalDNSのデプロイ完了です。 ### 動作確認 動作確認として`nginx`をデプロイしてCloudFlareと連携できるか試します。次の`nginx.yml`を作成します。 ``` yaml apiVersion: extensions/v1beta1 kind: Deployment metadata: name: nginx spec: template: metadata: labels: app: nginx spec: containers: - image: nginx name: nginx ports: - containerPort: 80 --- apiVersion: v1 kind: Service metadata: name: nginx spec: type: NodePort selector: app: nginx ports: - protocol: TCP port: 80 ``` 自分はCloudFlareの[Full SSLモード](https://support.cloudflare.com/hc/en-us/articles/200170416-What-do-the-SSL-options-mean-)を使っているので、Ingress側でもSSLの設定が必要です。Strictモードでなければ、Ingress側は自己証明書でOKです。 ![image](https://user-images.githubusercontent.com/106908/34675514-36adab56-f4cd-11e7-9486-faacc8c8fad6.png) ``` kubectl create secret tls tls-secret -n default --cert=public.crt --key=private.key # public.crtとprivate.keyは自己証明書でOK ``` > Flexibleモードを使えばGCP側でSSLの設定は不要になりますが、CloudFlare <-> GCP間の通信が平文になってしまい、イマイチです。 次にGCPでIngressのstatic ipを発行します。名前は`cloudflare-ingress`にします。 ``` gcloud compute addresses create cloudflare-ingress --global ``` 次にIngressの設定を書きます。次の`ingress.yml`を作成します。ホスト名はCloudFlare管理化のドメインにします。 ``` yaml apiVersion: extensions/v1beta1 kind: Ingress metadata: name: demo-ingress namespace: default annotations: kubernetes.io/ingress.global-static-ip-name: cloudflare-ingress ingress.kubernetes.io/rewrite-target: / spec: tls: - secretName: tls-secret rules: - host: nginx.ik.am http: paths: - backend: serviceName: nginx servicePort: 80 ``` これをデプロイします。 ``` kubectl apply -f ingress.yml ``` しばらくすると、CloudFlare側にTXTレコードとAレコードが作成されます。AレコードにはIngressに設定したstatic ipが設定されます。 Audit Logを見るとわかりやすいです。 しばらくするとGKE側のIngressのStatusがOKになり(遅い)、 ![image](https://user-images.githubusercontent.com/106908/34675183-1ff577c8-f4cc-11e7-9b42-4a5af2007556.png) [https://nginx.ik.am](https://nginx.ik.am)にアクセスできるようになります。 --- Ingressを設定するだけでCloudFlareにAレコードが登録されることを確認できました。運用が少し楽になります。 Let's Encryptでも試してみたいところです。