---
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です。

```
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になり(遅い)、

[https://nginx.ik.am](https://nginx.ik.am)にアクセスできるようになります。
---
Ingressを設定するだけでCloudFlareにAレコードが登録されることを確認できました。運用が少し楽になります。
Let's Encryptでも試してみたいところです。