OP53B環境のK8sでcert-manager + Route 53(や他のクラウドDNS)を使う


対象となる環境

  • OP53B環境にKubernetesクラスタがある
    • セキュリティの都合やDDoS対策のためにクラスタから社内DNSにしか繋がらないなど
  • DNSの管理自体はAWS Route 53やGoogle Cloud DNSなどクラウドのサービスを使っている
  • Let's encryptでのSSL証明書の発行、管理をいい感じにしたい
    • cert-managerを使いたい

問題

Error preparing issuer for certificate default/hogehoge.net: read udp 10.100.4.67:35222->205.251.196.87:53: i/o timeout
とか出て動かない

そもそもcert-managerはどんな感じで動いてるのか(ACME DNS-01)

Route 53の場合

  1. Let's encryptサーバにリクエストしてDNSの所有者確認用のトークンをもらう
  2. Route 53のAPIを叩いて上でもらったトークンをDNSのTXTレコードに入れる
  3. TXTレコードがちゃんと引けるか実際に確認する
  4. Let's encryptサーバにトークンが入ったことを通知して、証明書をもらう

この3.においてcert-managerはクラスタが使用しているDNSではなく、Route 53ならRoute 53のDNSサーバを使って引こうとします。
反映の早さを考えると理にかなった実装ですが、前述の通りOP53B環境では確認ができずスタックします。

解決策

必要な環境

  • cert-manager v0.6.0-alpha.1以降

インストール

※この記事を書いている段階ではstableになっていないので、とりあえずな方法を使っています。
Helm Chartのv0.6.0以降がリリースされていればそちらをおすすめします。

とりあえず普通に入れる

$ helm install \
    --name cert-manager \
    --namespace kube-system \
    stable/cert-manager

v0.6.0から必要になるCRDを入れる

$ kubectl apply \
    -f https://raw.githubusercontent.com/jetstack/cert-manager/v0.6.0-alpha.1/deploy/manifests/00-crds.yaml

イメージをv0.6.0-alpha.1にする


$ kubectl edit deployment cert-manager -n kube-system
spec:
  template:
    spec:
      containers:
+       image: quay.io/jetstack/cert-manager-controller:v0.6.0-alpha.1
-       image: quay.io/jetstack/cert-manager-controller:v0.5.2

コンフィグ


$ kubectl edit deployment cert-manager -n kube-system
spec:
  template:
    spec:
      containers:
      - args:
+       - --dns01-recursive-nameservers=INTERNAL_DNS_SERVER:53
+       - --dns01-recursive-nameservers-only=true

これで、強制的に--dns01-recursive-nameserversで指定したDNSで引くようになって動くようになります(当然若干時間はかかるようになります)