本稿は、さくらのアドベントカレンダー2022 24日目の投稿です。
さくらインターネットの相馬です。
今回は、さくらのクラウド DNSアプライアンスに対応させたExternalDNSの使い方を紹介させていただきます。
ExternalDNSはDNSゾーンを操作するため、環境に影響が出ないことを保証できません。
実際にお試しになる場合は自己責任でお願いします。
ExternalDNSとは
ExternalDNSは、Kubernetesにおいてサービス公開のために Ingress
リソースや Service
リソースを作成/更新した際にDNSレコードを動的に設定してくれるアドオンです。
例えば、以下のような Ingress
リソースを作成することで、ドメイン名 example.com
に対するAレコードを登録することができます。
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: example
namespace: example
spec:
ingressClassName: traefik
rules:
- host: "example.com"
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: example
port:
number: 80
現状のExternalDNS(v0.13.1現在)は、DNSプロバイダとしてさくらのクラウドは対応しておりません。
したがって今回、さくらのクラウド DNSアプライアンスをExternalDNSに対応させて使ってみました。
ExternalDNSにおけるプロバイダの開発方法につきましては下記の記事で紹介しておりますのでご興味がありましたら参照してください。
デプロイ
まず、下記マニフェストをKubernetesクラスタに適用し、ネームスペースの作成、RBACの設定を行います。
---
apiVersion: v1
kind: Namespace
metadata:
name: external-dns
---
apiVersion: v1
kind: ServiceAccount
metadata:
name: external-dns
namespace: external-dns
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
name: external-dns
rules:
- apiGroups: [""]
resources: ["services","endpoints","pods"]
verbs: ["get","watch","list"]
- apiGroups: ["networking.k8s.io"]
resources: ["ingresses"]
verbs: ["get","watch","list"]
- apiGroups: [""]
resources: ["nodes"]
verbs: ["list","watch"]
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
name: external-dns-viewer
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
name: external-dns
subjects:
- kind: ServiceAccount
name: external-dns
namespace: external-dns
---
次に、さくらのクラウドのAPIキー情報を持った Secret
リソースとさくらのクラウドに対応したExternalDNSをデプロイします。
(実際にAPIキーなどの機密情報を保管する際はSealed Secretsといった Secret
リソースをセキュアに管理する方法を利用してください。)
Secret
リソースにおいて、SAKURACLOUD_ACCESS_TOKEN
にはAPIキーのアクセストークンを、SAKURACLOUD_ACCESS_TOKEN_SECRET
にはAPIキーのアクセストークンシークレットを指定します。
---
apiVersion: v1
kind: Secret
metadata:
name: sakuracloud
namespace: external-dns
type: Opaque
data:
SAKURACLOUD_ACCESS_TOKEN: "<your sakuracloud access token>"
SAKURACLOUD_ACCESS_TOKEN_SECRET: "<your sakuracloud access token secret>"
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: external-dns
namespace: external-dns
spec:
strategy:
type: Recreate
selector:
matchLabels:
app: external-dns
template:
metadata:
labels:
app: external-dns
spec:
serviceAccountName: external-dns
containers:
- name: external-dns
image: sosomasox/external-dns:latest
args:
- --source=service
- --source=ingress
- --domain-filter=example.com
- --provider=sakuracloud
#- --log-level=debug # debug only
env:
- name: SAKURACLOUD_ACCESS_TOKEN
valueFrom:
secretKeyRef:
name: sakuracloud
key: SAKURACLOUD_ACCESS_TOKEN
- name: SAKURACLOUD_ACCESS_TOKEN_SECRET
valueFrom:
secretKeyRef:
name: sakuracloud
key: SAKURACLOUD_ACCESS_TOKEN_SECRET
---
APIキー作成時には適切なアクセスレベル(作成・削除
の権限が必要)を設定する必要があります。
APIキーの作成方法につきましては下記のドキュメントを参照ください。
下記はさくらのクラウドに対応したExternalDNSを稼働させるDeployment
リソースの spec
の部分を抜粋したものです。
spec.containers.args
の --domain-filter
にはさくらのクラウド DNSアプライアンスで作成したDNSゾーンを指定してください。
また、--provider
にはDNSプロバイダとしてさくらのクラウドを利用することを表す sakuracloud
を指定します。
(ログにおいてデバッグメッセージが不必要な場合は --log-level
をコメントアウト、またはその他のログレベルにしてください。)
spec:
serviceAccountName: external-dns
containers:
- name: external-dns
image: sosomasox/external-dns:latest
args:
- --source=service
- --source=ingress
- --domain-filter=example.com
- --provider=sakuracloud
- --log-level=debug # debug only
env:
- name: SAKURACLOUD_ACCESS_TOKEN
valueFrom:
secretKeyRef:
name: sakuracloud
key: SAKURACLOUD_ACCESS_TOKEN
- name: SAKURACLOUD_ACCESS_TOKEN_SECRET
valueFrom:
secretKeyRef:
name: sakuracloud
key: SAKURACLOUD_ACCESS_TOKEN_SECRET
動作確認
まず、下記マニフェストをKubernetesクラスタに適用し、Nginxのコンテナを稼働させ、Ingress
リソースでサービス公開します。
(本環境ではIngressコントローラーとしてtraefikを利用しています。)
---
apiVersion: v1
kind: Namespace
metadata:
name: test-web
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: test-web
namespace: test-web
spec:
replicas: 1
selector:
matchLabels:
app.kubernetes.io/name: test-web
template:
metadata:
labels:
app.kubernetes.io/name: test-web
spec:
containers:
- name: test-web
image: nginx:1.23
ports:
- containerPort: 80
---
apiVersion: v1
kind: Service
metadata:
name: test-web
namespace: test-web
spec:
ports:
- protocol: TCP
port: 80
targetPort: 80
selector:
app.kubernetes.io/name: test-web
---
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: test-web
namespace: test-web
spec:
ingressClassName: traefik
rules:
- host: test.sosomasox.com
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: test-web
port:
number: 80
---
次に、Kuberneteクラスタ上にリソースが作成されたことを確認します。
$ kubectl -n test-web get all,ingress
NAME READY STATUS RESTARTS AGE
pod/test-web-586cc45d97-njrvw 1/1 Running 0 5s
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
service/test-web ClusterIP 10.96.207.16 <none> 80/TCP 5s
NAME READY UP-TO-DATE AVAILABLE AGE
deployment.apps/test-web 1/1 1 1 5s
NAME DESIRED CURRENT READY AGE
replicaset.apps/test-web-586cc45d97 1 1 1 5s
NAME CLASS HOSTS ADDRESS PORTS AGE
ingress.networking.k8s.io/test-web traefik test.sosomasox.com 172.18.255.1 80 5s
ExternalDNSによって、Ingress
リソースの情報に対応したDNSレコードがさくらのクラウド DNSアプライアンス上に設定されているか、クラウドのコントロールパネルから確認してみます。
また、ExternalDNSのコンテナログにもDNSレコードの作成が行われていることが確認できました。
time="2022-12-22T07:06:07Z" level=debug msg="No endpoints could be generated from service test-web/test-web"
time="2022-12-22T07:06:07Z" level=debug msg="Endpoints generated from ingress: test-web/test-web: [test.sosomasox.com 0 IN A 172.18.255.1 []]"
time="2022-12-22T07:06:07Z" level=debug msg="change.Create: iaas.DNSRecord{Name:\"test\", Type:\"A\", RData:\"172.18.255.1\", TTL:300}"
time="2022-12-22T07:06:07Z" level=debug msg="change.Create: iaas.DNSRecord{Name:\"test\", Type:\"TXT\", RData:\"heritage=external-dns,external-dns/owner=default,external-dns/resource=ingress/test-web/test-web\", TTL:300}"
time="2022-12-22T07:06:07Z" level=debug msg="change.Create: iaas.DNSRecord{Name:\"a-test\", Type:\"TXT\", RData:\"heritage=external-dns,external-dns/owner=default,external-dns/resource=ingress/test-web/test-web\", TTL:300}"
最後に
本稿では、さくらのクラウド DNSアプライアンスに対応させたExternalDNSの使い方を紹介させていただきました。
現状、さくらのクラウドに対応させたExternalDNSは私個人でメンテナンスしております。
もし、さくらのクラウド対応ExternalDNSに需要がありそうでしたら、さくらインターネットでメンテナンスし、Helmチャート化とリポジトリの公開、ひいてはExternalDNSのupstreamへのマージなどできればと思います。