技術

おうちKubernetes上にnsdとunboundを建てておうちDNSする

この記事を4行で

  • おうちKubernetesのIngressリソース数が増えてきた
  • LAN内端末からIngress経由でアクセスする為にhostsファイルを書いて回るのが面倒になってきた
  • Kubernetes上にnsdとunboundを立ててLAN内名前解決を任せる
  • 成果物manifest: https://gitlab.chatagiriii.com/open/nsd-unbound-on-k8s

おうちKubernetes作ってから1年

chatagiriです。

おうちKubernetesの構成考えて、実際に運用を始めておおよそ1年が経ちました。

(書く、書くと言いながら未だに構築手順書いてないのはごめんなさい)

運用から1年も経つと有象無象のPod達が無造作に動きっぱなしになっており、2021/12/22現在で104Pod、54Service, 20Ingressが稼働中です。

$ kubectl get pods --all-namespaces | grep -v NAMESPACE | wc -l
104
$ kubectl get svc --all-namespaces | grep -v NAMESPACE | wc -l
54
$ k get ingress --all-namespaces | grep -v NAMESPACE | wc -l
20

hostsファイル弄るの面倒...

動いているものが多いと嬉しい一方で問題が。増えたIngressの数だけ手元端末たちのhostsを編集する必要があるのです。。

自分の家には日常使いのPC2台、Androidスマホ1台、AndroidTV1台があり、Ingressを1個追加したときにはそれぞれのhostsを弄らないとLAN内名前解決が出来ないのです。

特にAndroidのhostsを弄る為には基本的にrootを取る必要があり、折角作った自宅ファイルサーバにLAN内Wi-Fi経由で入れない等の問題が出てきてしまいました。

これを機におうちDNS鯖を建て、新しくIngressリソースを入れた時には権威DNSの更新1本で全端末から名前解決できるようにする試みです。

nsdとunbound

NSDはdnsの権威DNSサーバ用のOSSで、unboundはキャッシュDNSサーバ用のOSSです。詳細はリンク先を追ってみてください。。

ここがこうなる

こう変わる、を図にしてみました。

  • 前提:
    • metallb導入済みKubernetes cluster
    • nginx-ingress-controller導入済みKubnernetes cluster
    • (「nginx-ingress-controller使ってるなら図のServiceのIP回りおかしくない?」と気づくと思いますが、例として分かりやすいように図中のIP回りは都度変更しています。)
    • ご自身の環境に合わせて読み替え下さい
  • びふぉー:
    • 流れ
      • webapp01のPod/Service(192.168.1.210)/Configmap/PVなどを作成
      • webapp01.example.jp でingress リソースを作成して、外部に公開
      • LAN内からもingressの名前でアクセスしたいので、各端末のhostsファイルを編集(webapp01.example.jp,192.168.1.210)
    • メリットデメリット
      • 新しくingressを追加したとき、各端末のhostsファイルを編集してまわる必要がある
      • DNS回りが一元管理されていないので、漏れだったり、今どのレコードが有るか無いかをいちいち確認の必要がある場合がある
  • あふたー
    • 流れ
      • webapp01のPod/Service(192.168.1.210)/Configmap/PVなどを作成
      • webapp01.example.jp でingress リソースを作成して、外部に公開
      • nsdのpodのconfigmapを編集して、 (webapp01.example.jp 192.168.1.210) のレコードを追加
      • 各端末のDNSサーバの向け先をunboundに設定して、webapp01.exmaple.jpを問い合わせる
      • unboundはnsdに対してwebapp01.example.jpを問い合わせ、192.168.1.210の応答を貰い、各端末に返す
    • メリットデメリット
      • 新しくingressを追加したとき、nsdのレコード設定を編集するだけでよい
      • DNS回りが一元管理され、登録漏れや確認が楽になる
これが
こうなる

nsdとunboundのk8s manifestを書く

脳死でダーーッと書きます。意外とkubernetesでnsdとunboundして、manifestファイルまで公開してる人が居なかったため色々試してみましょう。

example.jpな部分を置き換えたり、DNSレコード回りはご自分の環境に合わせて変更してみてください。

また、ServiceのserviceTypeはLoadBalancerに設定していますが、ご家庭のKubernetesに乗っているものに合わせてご変更ください。

manifestファイルはこちらにも置いてあります。: https://gitlab.chatagiriii.com/open/nsd-unbound-on-k8s

nsd
--- apiVersion: v1 kind: Namespace metadata: name: nsd --- apiVersion: apps/v1 kind: Deployment metadata: labels: app: nsd name: nsd namespace: nsd spec: replicas: 2 selector: matchLabels: app: nsd template: metadata: labels: app: nsd spec: containers: - image: ghcr.io/the-kube-way/nsd:latest name: nsd ports: - name: udp containerPort: 53 volumeMounts: - name: nsd-zones mountPath: /zones - name: nsd-conf mountPath: /etc/nsd/nsd.conf subPath: nsd.conf volumes: - name: nsd-zones configMap: name: nsd-zones items: - key: db.example.jp path: example.jp.zone mode: 0644 - name: nsd-conf configMap: name: nsd-conf items: - key: nsd.conf path: nsd.conf mode: 0644 --- apiVersion: v1 kind: Service metadata: name: nsd namespace: nsd labels: app: nsd spec: ports: - name: dns port: 53 protocol: UDP selector: app: nsd type: LoadBalancer --- apiVersion: v1 kind: ConfigMap metadata: name: nsd-zones namespace: nsd data: db.example.jp: | $ORIGIN example.jp. $TTL 800 ; SOA @ IN SOA ns1.example.jp. example.jp. ( 1 ; Serial 3200 ; Refresh 1800 ; Retry 96000 ; Expire 86400 ) ; Minimum ; NAMESERVERS @ IN NS ns.example.jp. ; A RECORDS @ IN A 192.168.1.XX k8s-master00 IN A 192.168.1.10 k8s-worker00 IN A 192.168.1.20 k8s-worker00 IN A 192.168.1.21 k8s-worker00 IN A 192.168.1.22 webapp00 IN A 192.168.1.200 webapp01 IN A 192.168.1.210
unbound
--- apiVersion: v1 kind: Namespace metadata: name: unbound --- apiVersion: apps/v1 kind: Deployment metadata: labels: app: unbound name: unbound namespace: unbound spec: replicas: 2 selector: matchLabels: app: unbound template: metadata: labels: app: unbound spec: containers: - image: mvance/unbound name: unbound ports: - name: udp containerPort: 53 volumeMounts: - name: unbound-conf mountPath: /opt/unbound/etc/unbound/unbound.conf subPath: unbound.conf volumes: - name: unbound-conf configMap: name: unbound-conf items: - key: unbound.conf path: unbound.conf mode: 0644 --- apiVersion: v1 kind: Service metadata: name: unbound namespace: unbound labels: app: unbound spec: ports: - name: dns port: 53 protocol: UDP selector: app: unbound type: LoadBalancer --- apiVersion: v1 kind: ConfigMap metadata: name: unbound-conf namespace: unbound data: unbound.conf: | server: interface: 0.0.0.0 access-control: 192.168.1.0/24 allow # pod network access-control: 10.244.1.0/24 allow access-control: 10.244.2.0/24 allow access-control: 10.244.3.0/24 allow do-not-query-localhost: no cache-max-ttl: 10 stub-zone: name: example.jp stub-addr: 192.168.1.100@53 # example.jp 以外のドメインについてはgoogleに聞く forward-zone: name: "." forward-addr: 8.8.8.8 forward-addr: 8.8.4.4

k8sでもdns回りを構築できました

出来るかなー?ぐらいで調べていったdns on k8sですが、案外すんなり動きました。

意外とkubernetesでnsdとunboundして、manifestファイルまで公開してる人が居なかったため、誰かのお役に立てれば嬉しいですね...

-技術

S