2026年6月14日
2026年6月14日
CoreDNS でACL設定する手順|Kubernetes のクラスター DNS に acl を足すときの許可範囲の決め方と安全な反映
Kubernetes のクラスター DNS として動いている CoreDNS に ACL を設定するときは、Corefile に acl プラグインを書く前に「どのアドレスから問い合わせが届くのか」を洗い出すことが一番大切です。Pod のアドレス範囲だけでなく、ノードのアドレスや NodeLocal DNSCache を経由した問い合わせも CoreDNS には届くため、1つでも許可し忘れるとクラスター全体の名前解決が止まります。この記事では、許可範囲の調べ方、ConfigMap への安全な反映の手順、目的別の設定例、反映後の確認と切り戻しを説明します。単体サーバーとして動かす CoreDNS での acl の基本的な書き方は扱わず、Kubernetes 特有の注意点に絞ります。
Kubernetes で acl を使う場面
クラスター DNS の CoreDNS は通常、クラスター内部の Service(ClusterIP)でだけ公開されており、外から直接は届きません。それでも acl を検討するのは、次のような場面です。
- クラスターの外に CoreDNS を公開する:VPN 越しの社内端末からクラスター内の名前を引かせたいなど、LoadBalancer や NodePort で外に出す場合です。最も ACL が必要になる場面です。
- 社内ゾーンへの転送を特定の送信元に限る:
corp.example.comのような社内 DNS への転送を、決まったアドレス範囲からの問い合わせにだけ許可したい場合です。 - 特定のレコード種別を制限する:応答が大きくなりやすい ANY の問い合わせを制限したい場合などです。
一方で、「この Namespace の Pod には社内ゾーンを引かせない」といった Namespace 単位の制御は、acl では難しいことが多い点に注意が必要です。acl が判断に使えるのは送信元の IP アドレスとレコード種別で、Pod のアドレスは一般にノードごとの範囲から割り当てられ、Namespace とは対応していません。CNI によっては Namespace ごとにアドレスの範囲(IP プール)を割り当てられるものもありますが、そうでない環境では、NetworkPolicy で DNS への通信そのものを制御するなど、別の方法を検討してください。
問い合わせ元のアドレス範囲を洗い出す
acl で許可すべき範囲は、クラスターの構成によって変わります。次の3つを確認します。
# 1. Pod のアドレス範囲(ノードごとに割り当てられた範囲)
kubectl get nodes -o jsonpath='{range .items[*]}{.metadata.name}{"\t"}{.spec.podCIDR}{"\n"}{end}'
# 2. ノードのアドレス(hostNetwork の Pod や NodeLocal DNSCache の送信元になる)
kubectl get nodes -o wide
# 3. NodeLocal DNSCache が動いているか
kubectl -n kube-system get daemonset | grep -i node-local
1の結果が空になる環境もあります。Calico の独自のアドレス管理を使っている場合や、クラウドの CNI が VPC のアドレスを Pod に直接割り当てる場合などです。その場合は CNI の設定(IP プールの定義)や、クラウドのサブネットの範囲を確認します。
2のノードのアドレスを許可する理由は、hostNetwork: true で動く Pod はノードのアドレスから問い合わせるためです。NodeLocal DNSCache を導入している場合は、各ノードのキャッシュが CoreDNS に問い合わせるため、CoreDNS から見える送信元はノード側のアドレスになることが多くなります。導入済みの構成で Pod の範囲だけを許可すると、ほとんどの問い合わせが拒否されます。
ノードの追加やクラスターの拡張でアドレス範囲が増えることも想定し、許可範囲は個々のアドレスではなく、計画上の CIDR 全体で書いておくと安全です。
反映の前に準備すること
# 現在の設定をバックアップする
kubectl -n kube-system get configmap coredns -o yaml > coredns-backup.yaml
# Corefile に reload プラグインがあるか確認する(あれば ConfigMap の変更が自動で読み込まれる)
kubectl -n kube-system get configmap coredns -o jsonpath='{.data.Corefile}'
バックアップは、問題が起きたときにすぐ戻すためのものです。あわせて、次の点も事前に確かめておきます。
- 本番の前に検証用のクラスターで試す:許可漏れの影響がクラスター全体に及ぶため、同じ CNI・同じ構成の検証環境で一度試してから本番に反映します。
- マネージド Kubernetes の決まり:EKS のアドオン、AKS の
coredns-customのように、CoreDNS の設定を変える方法が独自に決められていることがあります。ConfigMap を直接書き換えると、アドオンの更新で元に戻されたり、サポートの対象外になったりする場合があるため、各サービスのドキュメントで変更方法を確認してください(2026年10月現在)。GKE のように、既定のクラスター DNS が CoreDNS ではない環境もあります。
設定例1:クラスター外に公開する CoreDNS を社内の範囲に限る
クラスター DNS そのものを外に公開するのではなく、外部向けの CoreDNS を別の Deployment として用意し、そちらに acl を書く構成が安全です。クラスター DNS の設定を変えずに済むため、ACL の誤りがクラスター内の名前解決に影響しません。
# 外部向け CoreDNS の Corefile(クラスター DNS とは別の Deployment で動かす)
.:53 {
errors
health
ready
acl {
allow net 10.8.0.0/16 192.168.0.0/16
block
}
kubernetes cluster.local {
pods disabled
}
cache 30
}
この例はクラスター内の名前だけを答える構成で、それ以外の名前には答えません。外部の名前も引かせる場合は forward を追加します。また、kubernetes プラグインは API サーバーから Service や Endpoints の情報を読むため、外部向けの Deployment にもクラスター DNS と同等の読み取り権限(ServiceAccount と RBAC)を与える必要があります。
外向けの Service では、送信元アドレスが CoreDNS まで届くかどうかが重要です。Service の externalTrafficPolicy が既定の Cluster のままだと、ノードを経由する際に送信元がノードのアドレスに置き換わることがあり、acl が端末の本来のアドレスで判断できません。externalTrafficPolicy: Local にすると送信元が保たれやすくなりますが、CoreDNS の Pod が動いていないノードには通信が振り分けられなくなるため、Pod の配置もあわせて確認します。
クラウドのロードバランサーを使う場合は、Service の loadBalancerSourceRanges やセキュリティグループで、届く範囲をあらかじめ絞っておきます。acl は CoreDNS に届いた後の判断なので、手前で止められるものは手前で止めるのが基本です。
設定例2:社内ゾーンへの転送を特定の範囲に限る
クラスター DNS の Corefile に、社内 DNS へ転送する専用のサーバーブロックを追加し、そのブロックにだけ acl を書きます。既存の .:53 のブロックには手を加えないため、ほかの名前解決への影響を抑えられます。
corp.example.com:53 {
errors
acl {
allow net 10.244.0.0/16 192.168.10.0/24
block
}
cache 30
forward . 172.16.0.53 172.16.0.54
}
ここでの 10.244.0.0/16 は Pod の範囲、192.168.10.0/24 はノードの範囲の例です。前の手順で調べた実際の値に置き換えてください。acl は書いたサーバーブロックの中でだけ効くため、corp.example.com 以外の問い合わせはこれまでどおり処理されます。
設定例3:ANY の問い合わせを制限する
既存の .:53 のブロックに acl を足す場合は、許可範囲を書き漏らすリスクを避けるため、種別の制限だけにとどめる方法があります。
acl {
block type ANY
}
送信元を指定していないため、ANY 以外の問い合わせはすべてこれまでどおり処理されます。拒否ではなく小さな応答を返したい場合は、ANY への応答を最小限にする any プラグインを使う方法もあります。どちらを選ぶかは、ANY を使うクライアントがクラスター内にないかを確かめてから決めます。
反映と確認
ConfigMap を変更すると、reload プラグインがある構成では、しばらくして CoreDNS が新しい Corefile を読み込みます。ConfigMap の内容が Pod に届くまでに時間がかかるため、すぐには反映されません。
# ConfigMap を編集する(または修正した YAML を kubectl apply する)
kubectl -n kube-system edit configmap coredns
# CoreDNS のログで、再読み込みとエラーの有無を確認する
kubectl -n kube-system logs -l k8s-app=kube-dns --tail=50
Corefile に誤りがあると、reload は新しい設定を読み込まず、古い設定のまま動き続けてログにエラーを出します。ログを見ずに「反映されたはず」と判断しないことが大切です。
動作の確認は、クラスター内の Pod から行います。Kubernetes の公式ドキュメントの DNS のデバッグ手順にある、dig や nslookup の入った確認用の Pod を使うと便利です。
# クラスター内の名前(status: NOERROR になる)
kubectl exec -it dnsutils -- dig kubernetes.default.svc.cluster.local
# 社内ゾーン(許可した範囲の Pod からは NOERROR、それ以外からは REFUSED)
kubectl exec -it dnsutils -- dig www.corp.example.com
hostNetwork の Pod や、NodeLocal DNSCache を経由する経路からも名前解決できるかを確認しておくと、許可漏れに早く気づけます。
問題が起きたときの切り戻し
名前解決が止まった場合は、原因を調べるより先にバックアップへ戻します。
kubectl apply -f coredns-backup.yaml
# reload で戻らない場合や急ぐ場合は、CoreDNS を再起動する
kubectl -n kube-system rollout restart deployment coredns
Deployment の名前は環境によって異なることがあるため、kubectl -n kube-system get deployment で確認してください。戻した後に、拒否された問い合わせの送信元をログで確かめ、許可範囲に何が足りなかったかを調べます。
まとめ
- Kubernetes の CoreDNS に acl を足す前に、Pod・ノード・NodeLocal DNSCache の送信元アドレスを洗い出します。
- acl はアドレスと種別で判断するため、Namespace 単位の制御には向きません。
- 外部に公開するなら、クラスター DNS とは別の CoreDNS に acl を書き、送信元が保たれるかを確認します。
- 変更前に ConfigMap をバックアップし、検証用クラスターで試し、反映後はログでエラーの有無を確認します。
- 名前解決が止まったら、まずバックアップに戻してから原因を調べます。