0
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

StylezAdvent Calendar 2024

Day 6

PowerDNSとPowerDNS-AdminをDockerで動かして、Kubernetesの外部DNSサーバーにする(1)

Last updated at Posted at 2024-12-05

毎度、ググっても出てこない小ネタを取り扱っております。
本記事は個人的な見解であり、筆者の所属するいかなる団体にも関係ございません。

0. はじめに

「インターネットにはまずDNSサーバー」と誰かが言ったかもしれませんが、DNSサーバーはそれだけ重要なものです。
オンプレで動かすKubernetesでも重要で、特にIngressリソースとかで動かす時に、自動的にDNSサーバーにホスト名を登録し、TLS証明書を発行する必要があります。

その時に自動的にレコードをDNSに登録できるDNSサーバーが必要です。

Kubernetesには、ExternalDNSというIngressリソースのホスト名をDNSサーバーに登録する仕組みがあります。

kubernetes-sigs/external-dns: Configure external DNS servers (AWS Route53, Google CloudDNS and others) for Kubernetes Ingresses and Services
https://github.com/kubernetes-sigs/external-dns

しかし、これで利用できるDNSサーバーは、クラウドなどのDNSサービスばかりでオンプレで利用できるDNSサーバーは多くありません。

ExternalDNSからオンプレミスで利用できるDNSサーバーは以下の4つです。

  • PowerDNS
  • CoreDNS
  • RFC2136
  • Pi-hole

しかし、RFC2136はBINDで動きますが、今更BINDとか見たくありません。。
CoreDNSはetcdでの連携が必要で、etcdを外にさらすのも気が引けます。
Pi-holeはRaspberry PiのAd Blockingツールですが、そこまでの機能は不要です。

となると、PowerDNS一択になるわけで、こいつを動かすしかないという結論になります。

本記事は、OpenAIのChatGPT GPT-4oの力を借りて作成しています。

1. PowerDNSの概要

PowerDNSは、オープンソースのDNSサーバーで、動的なDNSセットアップや高可用性のニーズに応える強力な機能を持っています。PowerDNSは大きく2つに分かれており、権威サーバー(Authoritative Server)は権威あるDNS応答を提供し、リカーサー(Recursor)はクライアント側のDNS解決を行います。このガイドでは、Dockerを使用してPowerDNS権威サーバーをSQLiteバックエンドでセットアップする方法を説明します。

主な機能としては:

  • MySQL、PostgreSQL、SQLiteなど、複数のバックエンドデータソースに対応。
  • DNSSECとの統合による安全なドメインネームサービス。
  • REST APIによる簡単な管理が可能。

2. Dockerを使用したUbuntuでのPowerDNSのセットアップ

ステップ1: Dockerをインストール

まずはDockerとDocker Composeをインストールします。

sudo apt update
sudo apt install -y docker.io

Dockerが自動的に起動するようにし、インストールを確認します。

sudo systemctl start docker
sudo systemctl enable docker
docker --version

ステップ2: Docker Composeのインストール

Docker Composeがデフォルトでインストールされていない場合は、次のコマンドでインストールします。

# Add Docker's official GPG key:
sudo apt-get update
sudo apt-get install -y ca-certificates curl
sudo install -m 0755 -d /etc/apt/keyrings
sudo curl -fsSL https://download.docker.com/linux/ubuntu/gpg -o /etc/apt/keyrings/docker.asc
sudo chmod a+r /etc/apt/keyrings/docker.asc

# Add the repository to Apt sources:
echo \
  "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.asc] https://download.docker.com/linux/ubuntu \
  $(. /etc/os-release && echo "$VERSION_CODENAME") stable" | \
  sudo tee /etc/apt/sources.list.d/docker.list > /dev/null
sudo apt-get update
sudo apt install -y docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin

ステップ3: Ubuntu のスタブリゾルバーを止める

Ubuntuのスタブリゾルバーを止めます。

そのためには、/etc/systemd/resolved.confを編集して、DNSStubListener=noを追加します。

sudo sed -i 's/^#DNSStubListener=yes/DNSStubListener=no/' /etc/systemd/resolved.conf

resolv.confも編集します。

cd /etc
sudo ln -s ../run/systemd/resolve/resolv.conf resolv.conf

その後、サービスを再起動します。

sudo systemctl restart systemd-resolved

53番ポートのListenが止まっているか確認します。

sudo ss -tuln | grep 53

ステップ4: PowerDNSのセットアップ

PowerDNS用の設定ディレクトリを作成します。

mkdir ~/powerdns && cd ~/powerdns

docker-compose.ymlファイルを作成し、SQLiteをバックエンドに設定します。

services:
  auth:
    image: powerdns/pdns-auth-master:latest
    container_name: pdns_auth
    environment:
      - PDNS_AUTH_API_KEY
    volumes:
      - type: bind
        source: ./data/powerdns-auth/pdns.sqlite
        target: /var/lib/powerdns/pdns.sqlite
      - ./pdns.d/pdns.conf:/etc/powerdns/pdns.d/pdns.conf
    ports:
      - "53:53/udp"
      - "53:53/tcp"
      - "8081:8081"

volumes:
  powerdns:
    driver: local

ステップ5: PowerDNSの起動

Docker Composeを実行し、PowerDNSを起動します。

docker-compose up -d

サービスが実行中かどうかを確認します。

docker ps

PowerDNSのAuthorityが起動したか確認します。

まだ何もレコードを入れていないので、何も返ってきませんが、確認しておきましょう。

dig @127.0.0.1 example.com +short

以下のように何も返ってこなければOKです。

; <<>> DiG 9.18.1-1ubuntu1-Ubuntu <<>> @127.0.0.1 example.com
; (1 server found)
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: REFUSED, id: 29047
;; flags: qr rd; QUERY: 1, ANSWER: 0, AUTHORITY: 0, ADDITIONAL: 1
;; WARNING: recursion requested but not available

;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags:; udp: 1232
;; QUESTION SECTION:
;example.com.                   IN      A

;; Query time: 1 msec
;; SERVER: 127.0.0.1#53(127.0.0.1) (UDP)
;; WHEN: Thu Nov 21 09:22:29 UTC 2024
;; MSG SIZE  rcvd: 40

docker-compose.ymlの検証ができたので、一旦、PowerDNSのAuthorityを停止します。

docker compose down

3. PowerDNSのデータベースの初期化とPowerDNS起動設定

PowerDNSのデータベースのディレクトリを作成します。

mkdir -p ./data/powerdns-{auth,admin}
touch ./data/powerdns-admin/admin.sqlite

PowerDNSのデータベースのスキーマをダウンロードします。

wget https://github.com/PowerDNS/pdns/blob/master/modules/gsqlite3backend/schema.sqlite3.sql

スキーマーを適用して、pdns.sqliteファイルを作ります。

sqlite3 ./data/powerdns-auth/pdns.sqlite < ./schema.sqlite3.sql

sqlite3コマンドがインストールされていない場合は、インストールします。

sudo apt install -y sqlite3

pdns.dディレクトリを作成します。

mkdir ./pdns.d

./pdns.d/pdns.confを編集します。

./pdns.d/pdns.conf
local-address=0.0.0.0,::
launch=gsqlite3
gsqlite3-dnssec
gsqlite3-database=/var/lib/powerdns/pdns.sqlite3
include-dir=/etc/powerdns/pdns.d
primary=yes #
secondary=no #
version-string=powerdns
api=yes
allow-axfr-ips=

APIキーファイルを保存するファイル .envファイルを作ります。
パスワードは適時変更してください。

.env
PDNS_AUTH_API_KEY=password

4. PowerDNS APIを使用してDNSレコードを追加する

PowerDNSのAuthorityを起動します。

docker compose up -d

4-1. API接続確認

SQLiteデータベースに直接レコードを追加することも可能ですが、簡単な方法としてPowerDNS APIを使用するのがおすすめです。

まず、API接続でエラーが出ないか確認します。

curl -H 'X-API-Key: password' http://localhost:8081/api/v1/servers | jq

以下のように返ってきたらOKです。

[
  {
    "autoprimaries_url": "/api/v1/servers/localhost/autoprimaries{/autoprimary}",
    "config_url": "/api/v1/servers/localhost/config{/config_setting}",
    "daemon_type": "authoritative",
    "id": "localhost",
    "type": "Server",
    "url": "/api/v1/servers/localhost",
    "version": "5.0.0-alpha0.1988.master.g28654477d",
    "zones_url": "/api/v1/servers/localhost/zones{/zone}"
  }
]

4-2. DNSのZoneの追加

APIを使用してDNSレコードを追加するのに次のcurlコマンドを使用します(他の方法もあります)。passwordは適時、PDNS_AUTH_API_KEYで指定したパスワードに変更してください。

curl -sk -H 'X-API-Key: password' -H "Content-Type: application/json" -X POST \
-d '{
  "name": "example.jp.",
  "kind": "Native",
  "masters": [],
  "nameservers": [
    "ns1.example.jp.",
    "ns2.example.jp."
  ]
}' \
http://127.0.0.1:8081/api/v1/servers/localhost/zones

ゾーンが作成されたか確認します。

curl -H 'X-API-Key: password' http://127.0.0.1:8081/api/v1/servers/localhost/zones | jq .

jqが入っていない場合は、sudo apt install -y jqでインストールしてください。

以下のようにZoneが作成されれば成功です。

[
  {
    "account": "",
    "catalog": "",
    "dnssec": false,
    "edited_serial": 2024112601,
    "id": "example.jp.",
    "kind": "Native",
    "last_check": 0,
    "masters": [],
    "name": "example.jp.",
    "notified_serial": 2024112601,
    "serial": 2024112601,
    "url": "/api/v1/servers/localhost/zones/example.jp."
  }
]

4-3. レコードの追加

以下のコマンドでmail.example.jp のAレコードを追加します。
注意点は、メソッドがPATCHで、URLがゾーンのURLになっているところです。

curl -sk -X PATCH -H 'X-API-Key: password' -H "Content-Type: application/json" \
-d '{
    "rrsets": [
      {
        "name": "mail.example.jp.",
        "type": "A",
        "changetype": "REPLACE",
        "ttl": 86400,
        "records": [
          {
              "content": "192.168.9.9",
              "disabled": false
          }
        ]
      }
    ]
}' \
http://127.0.0.1:8081/api/v1/servers/localhost/zones/example.jp.

入ったかどうか確認します。

{
  "account": "",
  "api_rectify": true,
  "catalog": "",
  "dnssec": true,
  "edited_serial": 2024112602,
  "id": "example.jp.",
  "kind": "Master",
  "last_check": 0,
  "master_tsig_key_ids": [],
  "masters": [],
  "name": "example.jp.",
  "notified_serial": 2024112602,
  "nsec3narrow": false,
  "nsec3param": "",
  "rrsets": [
    {
      "comments": [],
      "name": "mail.example.jp.",
      "records": [
        {
          "content": "192.168.9.9",
          "disabled": false
        }
      ],
      "ttl": 86400,
      "type": "A"
    },
---後略---

5. DNSを引いてみる

mail.example.jpレコードが追加されているはずなので、digコマンドでテストしてみます。

dig @localhost mail.example.jp +short

以下のIPアドレスが返ってくればOKです。

192.168.9.9

6. つづく

ちょっと長くなったので、一旦ここまででこの記事は終わりにします。

0
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?