なにかの技術メモ置き場

なにかの技術メモ置き場

@インフラエンジニア

Kubernetes環境でDNSサービスを構築してみた

全編目次

none06.hatenadiary.org

概要

  • Kubernetes環境でDNSサービスを構築する。
  • DNSサービスとしてCoreDNSを使用する。

環境

概要図

構成

ホスト名 IPアドレス OS 用途 備考
k8sctrpln01 172.16.0.11/24 CentOS 7.9.2009 コントロールプレーンノード QEMU+KVM仮想ゲスト
k8sworker01 172.16.0.12/24 CentOS 7.9.2009 ワーカノード QEMU+KVM仮想ゲスト
k8sworker02 172.16.0.13/24 CentOS 7.9.2009 ワーカノード QEMU+KVM仮想ゲスト
dns02 172.16.0.2/24 CoreDNS-1.9.3 DNSサービス MetalLB 仮想IP
file01 172.16.0.5/24 TrueNAS-12.0-U6 NFSサーバ -

前提

  • なるべく公式ドキュメントを参照するようにする。
  • マニフェストの作成やkubectlコマンドの実行は、クライアントマシン(Windows 10)上で行う。Windowsへのkubectlコマンドのインストールは以下を参照。 kubernetes.io
  • Pod間のデータ共有の手段として、NFSサーバを使用する。当環境では以下の領域を使用する。
NFSサーバホスト名 NFS公開領域 備考
file01 /mnt/data-pool0/nfs/k8s/coredns -

構築

Corefileの作成

NFSサーバ上に、CoreDNS起動時に読み込ませる設定ファイルを作成する。

. {
    whoami
    errors
    log . "{remote} is Request: {name} {type} {>id}"
    hosts /etc/coredns/hosts {
      fallthlough
    }
    reload
}
  • パラメータ(Plugins)の詳細はこちらを参照。 coredns.io

hostsファイルの作成

NFSサーバ上に、CoreDNSで名前解決に使用するファイルを作成する。

172.16.0.11     k8sctlpln011.tmpdomain.local    k8sctlpln01.tmpdomain.local     k8sctlpln011     k8sctlpln01
172.16.0.12     k8sworker011.tmpdomain.local    k8sworker01.tmpdomain.local     k8sworker011     k8sworker01
172.16.0.13     k8sworker021.tmpdomain.local    k8sworker02.tmpdomain.local     k8sworker021     k8sworker02
  • いわゆるhostsファイルの形式で記載できるのでわかりやすい。例えばBINDではAレコード(正引き)とPTRレコード(逆引き)とでそれぞれの定義ファイルが必要だったが、便利な時代になった。
  • 内容はサンプル。

PV、PVCの作成

Podにマウントする永続ボリューム(PV、PVC)を作成する。

apiVersion: v1
kind: PersistentVolume
metadata:
  name: pv-nfs-coredns
  labels:
    volume: volume-nfs-coredns
spec:
  capacity:
    storage: 10Gi
  volumeMode: Filesystem
  accessModes:
  - ReadWriteOnce
  persistentVolumeReclaimPolicy: Retain
  storageClassName: slow
  mountOptions:
  - hard
  - nfsvers=3
  nfs:
    path: "/mnt/data-pool0/nfs/k8s/coredns"
    server: file01
---
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: pvc-nfs-coredns
spec:
  accessModes:
  - ReadWriteOnce
  volumeMode: Filesystem
  resources:
    requests:
      storage: 2Gi
  storageClassName: slow
  selector:
    matchLabels:
      volume: volume-nfs-coredns
  • 容量は適当。
  • PV(PersistentVolume)、PVC(PersistentVolumeClaim)の詳細は公式ドキュメントを参照。 kubernetes.io

マニフェストを適用する。

$ kubectl apply -f pv-nfs-coredns.yaml
persistentvolume/pv-nfs-coredns created
persistentvolumeclaim/pvc-nfs-coredns created

PV、PVCが作成されていることを確認する。

$ kubectl get pv pv-nfs-coredns 
NAME             CAPACITY   ACCESS MODES   RECLAIM POLICY   STATUS   CLAIM                     STORAGECLASS   REASON   AGE
pv-nfs-coredns   10Gi       RWO            Retain           Bound    default/pvc-nfs-coredns   slow                    67s
$ kubectl get pvc pvc-nfs-coredns
NAME              STATUS   VOLUME           CAPACITY   ACCESS MODES   STORAGECLASS   AGE
pvc-nfs-coredns   Bound    pv-nfs-coredns   10Gi       RWO            slow           72s

Deploymentの作成

CoreDNSのPodをデプロイするDeploymentを作成する。

apiVersion: apps/v1
kind: Deployment
metadata:
  name: coredns-deployment
spec:
  selector:
    matchLabels:
      app: coredns
  replicas: 2
  template:
    metadata:
      labels:
        app: coredns
    spec:
      containers:
      - name: coredns
        image: coredns/coredns
        ports:
        - name: tcp
          containerPort: 53
          protocol: TCP
        - name: udp
          containerPort: 53
          protocol: UDP
        volumeMounts:
        - name: volume-nfs-coredns
          mountPath: /etc/coredns
        command: ["/coredns", "-conf", "/etc/coredns/Corefile"]
      volumes:
      - name: volume-nfs-coredns
        persistentVolumeClaim:
          claimName: pvc-nfs-coredns
  • corednsコマンドのオプションについては公式ドキュメントを参照。 coredns.io

マニフェストを適用する。

$ kubectl apply -f coredns-deployment.yaml 
deployment.apps/coredns-deployment created

Podが作成されていることを確認する。

$ kubectl get pods 
NAME                                     READY   STATUS    RESTARTS   AGE
coredns-deployment-5bc79b5c88-4bdd5      1/1     Running   0          18s
coredns-deployment-5bc79b5c88-9fn7h      1/1     Running   0          17s

PodのログからCoreDNSが起動していることを確認できる。

$ kubectl logs coredns-deployment-5bc79b5c88-4bdd5
.:53
[INFO] plugin/reload: Running configuration SHA512 = d433a10a6209646b978eee6a091811a1a8779e9f06a96524a2b55b702985c2f1820f17c5990fc38cb2fc14926f241ee50b07d7fffe3352ef979d98ac74973581   
CoreDNS-1.9.3
linux/amd64, go1.18.2, 45b0a11

補足だが、Podを作成したタイミングでワーカノード上にPVがNFSマウントされていることを確認できる。

[root@k8sworker01 ~]# df -t nfs
ファイルシス                              1K-ブロック      使用     使用可 使用% マウント位置
file01:/mnt/data-pool0/nfs/k8s/coredns     2163180544 357269504 1805911040   17% /var/lib/kubelet/pods/2fc83d0c-3884-4eab-b59e-3c5b265821f3/volumes/kubernetes.io~nfs/pv-nfs-coredns
[root@k8sworker01 ~]# ls -l /var/lib/kubelet/pods/2fc83d0c-3884-4eab-b59e-3c5b265821f3/volumes/kubernetes.io~nfs/pv-nfs-coredns
合計 9
-rw-r--r--. 1 root 65533   136  6月  7 23:46 Corefile
-rw-r--r--. 1 root 65533 13147  6月  8 00:05 hosts

Serviceの作成

CoreDNSのPodをKubernetesクラスタ外部に公開するためのServiceを作成する。当環境ではServiceのtypeLoadBalancerとし、ソフトウェアロードバランサであるMetalLBを使用する。

apiVersion: v1
kind: Service
metadata:
  name: coredns-service-tcp
  annotations:
    metallb.universe.tf/allow-shared-ip: "coredns-service-ip"
spec:
  type: LoadBalancer
  loadBalancerIP: 172.16.0.2
  ports:
    - name: tcp
      port: 53
      targetPort: 53
      protocol: TCP
  selector:
    app: coredns
---
apiVersion: v1
kind: Service
metadata:
  name: coredns-service-udp
  annotations:
    metallb.universe.tf/allow-shared-ip: "coredns-service-ip"
spec:
  type: LoadBalancer
  loadBalancerIP: 172.16.0.2
  ports:
    - name: udp
      port: 53
      targetPort: 53
      protocol: UDP
  selector:
    app: coredns
  • MetalLBは1つのServiceにおけるマルチプロトコルTCP/UDP)動作に非対応のため、TCPUDPとで別々のServiceを作成し、metallb.universe.tf/allow-shared-ipannotationを設定することで対処する。このannotationを定義しないと、TCPUDPとで別々のIPアドレスが割り当てられてしまう(loadBalancerIPで固定IPを宣言した場合は、例えばTCPにはIPが割り当てられるがUDPにはPendingになる)。詳細は公式ドキュメントを参照。 metallb.universe.tf

マニフェストを適用する。

$ kubectl apply -f coredns-service-loadbalancer.yaml 
service/coredns-service-tcp created
service/coredns-service-udp created

サービスが作成されていることを確認する。EXTERNAL-IPTCP/UDPとも172.16.0.2であることが確認できる。

$ kubectl get services
NAME                    TYPE           CLUSTER-IP       EXTERNAL-IP   PORT(S)                    AGE
coredns-service-tcp     LoadBalancer   10.99.184.19     172.16.0.2    53:31670/TCP               33s
coredns-service-udp     LoadBalancer   10.108.126.55    172.16.0.2    53:31803/UDP               32s

動作確認

任意のマシンから名前解決できることを確認する。

$ nslookup.exe k8sctrpln01 172.16.0.2
サーバー:  dns021.tmpdomain.local
Address:  172.16.0.2

名前:    k8sctrpln01
Address:  172.16.0.11

CoreDNSのログにリクエストが記録されていることが確認できる。

$ kubectl logs -f coredns-deployment-5bc79b5c88-4bdd5
.:53
[INFO] plugin/reload: Running configuration SHA512 = d433a10a6209646b978eee6a091811a1a8779e9f06a96524a2b55b702985c2f1820f17c5990fc38cb2fc14926f241ee50b07d7fffe3352ef979d98ac74973581
CoreDNS-1.9.3
linux/amd64, go1.18.2, 45b0a11
[INFO] 10.244.0.0 is Request: k8sctrpln01. A 5587

あとがき

あれ、53/TCPって必要なんだっけ・・・?

参考記事

coredns.io github.com zenn.dev blog.vpantry.net