技術

おうち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

---
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
---
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ファイルまで公開してる人が居なかったため、誰かのお役に立てれば嬉しいですね...

-技術