📝 BLOG.IK.AM

@making's memo
(🗃 Categories 🏷 Tags)

ExternalDNSを使ってGKEからCloudFlareにIngressのDNSレコードを登録

🗃 {Dev/CaaS/Kubernetes/ExternalDNS}

🏷 CloudFlare 🏷 GKE 🏷 Kubernetes

🗓 Updated at 2018-01-08T15:12:48+09:00 by Toshiaki Maki  🗓 Created at 2018-01-08T15:12:48+09:00 by Toshiaki Maki  {✒️️ Edit  ⏰ History}


⚠️ Caution: This content is a bit old. Please be careful to read.

ExternalDNSについて

ExternalDNSはKubernetesから外部のDNSサービスにServicetype: LoadBalancerやIngressのIPアドレスのDNSレコードを登録してくれます。

v0.4の段階では次のサービスに対応しています。

このブログの証明書を見てもらえば分かりますが、私はCloudFlareを使ってSSL対応をしており、有償オプション($10/month)でDedicatedな証明書を使用しています。

SANでマルチドメインを登録しまくっています。

Kubernetesでtype: LoadBalancerなサービスやIngressを作る時にAレコードを毎回CloudFlareに登録していて面倒だと思ってたので、このExternalDNSの仕組みはありがたいのです。
(自分でCloudFlareのAPIを叩く何かを作ろうと思っていました...)

ExternalDNSのデプロイ

まずはExternalDNSのデプロイを使うために、external-dns.ymlを作成します。

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_KEYCF_API_EMAILの内容はcloudflare-secret.ymlに設定しておきます。

apiVersion: v1
kind: Secret
metadata:
  name: cloudflare-secret
  namespace: kube-system
type: Opaque
data:
  cloudflare-api-key: ********** # echo -n <CF_API_KEY> | base64
  cloudflare-api-email: ********** # echo -n <CF_API_EMAIL> | base64

これらをデプロイします。

kubectl apply -f cloudflare-secret.yml
kubectl apply -f external-dns.yml

これでExternalDNSのデプロイ完了です。

動作確認

動作確認としてnginxをデプロイしてCloudFlareと連携できるか試します。次のnginx.ymlを作成します。

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モードを使っているので、Ingress側でもSSLの設定が必要です。Strictモードでなければ、Ingress側は自己証明書でOKです。

image

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管理化のドメインにします。

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://nginx.ik.amにアクセスできるようになります。


Ingressを設定するだけでCloudFlareにAレコードが登録されることを確認できました。運用が少し楽になります。
Let's Encryptでも試してみたいところです。