2026年6月9日

2026年6月9日

Google Cloud DNS を API で操作する手順|gcloud・REST・Python でのレコード変更と権限の絞り方

Google Cloud DNS のレコードをプログラムから変更するには、Cloud DNS API を有効にし、DNS の操作だけを許可した認証情報を用意したうえで、gcloud コマンド、REST API、またはクライアントライブラリから「変更(change)」を送ります。この記事では、手作業の代わりに gcloud で操作する方法から、REST API の呼び方、Python で「今の値と違うときだけ書き換える」スクリプトまでを順に説明します。WordPress サーバーの IP 変更やサブドメインの追加を自動化したい人を想定しています。

コマンドのオプションや API の仕様は更新されることがあります(2026年10月現在)。ここで示すコマンドは自分の環境に合わせて読み替え、本番のゾーンに対して実行する前に、テスト用のゾーンや影響のないレコードで動きを確かめてください。ゾーンそのものの作り方は別の記事で扱っているため、この記事ではゾーンがすでにある前提で進めます。

押さえておく仕組み:レコードは「変更」でまとめて書き換える

Cloud DNS の API では、レコードを1行ずつ編集するのではなく、同じ名前・同じタイプのレコードの集まり(リソースレコードセット)を単位に扱います。たとえば www.example.com. の A レコードに IP が2つあれば、それで1つのレコードセットです。

書き換えは「変更」というリクエストで行い、1回の変更に「削除するレコードセット」と「追加するレコードセット」を並べて送ります。1回の変更に含めた削除と追加はまとめて適用されるので、「古い値を消してから新しい値を入れる」間に名前が引けなくなる時間は生じません。

もう1つの約束事として、名前は www.example.com. のように末尾にドットを付けた完全修飾名で書きます。

手順1:API を有効にして、権限を絞った認証情報を用意する

まず、対象のプロジェクトで Cloud DNS API を有効にします。

gcloud config set project my-project
gcloud services enable dns.googleapis.com

次に、自動化に使う認証情報を用意します。個人のアカウントでスクリプトを動かすと、そのアカウントが持つすべての権限で動いてしまうため、DNS 専用のサービスアカウントを作ります。

gcloud iam service-accounts create dns-updater \
  --display-name="Cloud DNS updater"

gcloud projects add-iam-policy-binding my-project \
  --member="serviceAccount:dns-updater@my-project.iam.gserviceaccount.com" \
  --role="roles/dns.admin"

roles/dns.admin はプロジェクト内のすべてのゾーンを操作できるロールです。読み取りだけでよい監視用途なら roles/dns.reader を使います。特定のゾーンだけに権限を限りたい場合は、ゾーン単位で IAM を設定できるかを公式ドキュメントで確認してください。DNS 用のプロジェクトを分けておくのも、影響範囲を絞る現実的な方法です。

このサービスアカウントを使う方法は、実行する場所によって選びます。

  • Compute Engine などの Google Cloud 上: VM にサービスアカウントを割り当てれば、鍵ファイルなしで認証できます。
  • GitHub Actions など外部の CI: Workload Identity 連携を使うと、長期間有効な鍵を発行せずに済みます。
  • 手元の PC で試す: gcloud auth application-default login で自分の認証情報を使えますが、本番の自動化には使いません。

サービスアカウントの鍵ファイル(JSON)を発行する方法もありますが、漏えいしたときの影響が大きいため、ほかの方法が使えない場合に限り、Git に入れない・権限を絞る・定期的に作り直すといった管理を徹底します。

手順2:gcloud で読み書きしてみる

API を直接呼ぶ前に、gcloud で同じ操作をしてみると、レコードセットの考え方がつかみやすくなります。

# ゾーンの一覧と、ゾーンのネームサーバー
gcloud dns managed-zones list
gcloud dns managed-zones describe example-com --format="value(nameServers)"

# レコードの一覧
gcloud dns record-sets list --zone=example-com

# 追加・更新・削除
gcloud dns record-sets create staging.example.com. --zone=example-com \
  --type=A --ttl=300 --rrdatas=203.0.113.10
gcloud dns record-sets update staging.example.com. --zone=example-com \
  --type=A --ttl=300 --rrdatas=203.0.113.20
gcloud dns record-sets delete staging.example.com. --zone=example-com --type=A

# TXT は値を二重引用符で囲む
gcloud dns record-sets create example.com. --zone=example-com --type=TXT --ttl=300 \
  --rrdatas='"v=spf1 include:_spf.example.net ~all"'

--zone に指定するのはゾーンの名前(Google Cloud 内の識別子)で、ドメイン名ではありません。一覧の NAME 列で確かめます。TXT の値は引用符ごと渡す点と、すでに同じ名前・タイプのレコードセットがあると create は失敗する点がつまずきやすいところです。既存のレコードセットに値を足したい場合は、既存の値も含めて update で指定し直します。

作業の前には、ゾーンをファイルに書き出して控えておくと戻すときに役立ちます。

gcloud dns record-sets export backup-example-com.zone \
  --zone=example-com --zone-file-format

手順3:REST API を直接呼ぶ

gcloud が使えない環境や、ほかのツールから呼びたい場合は REST API を使います。変更の作成は、ゾーンの changes に対する POST です。

TOKEN="$(gcloud auth print-access-token)"
curl -s -X POST \
  -H "Authorization: Bearer ${TOKEN}" \
  -H "Content-Type: application/json" \
  "https://dns.googleapis.com/dns/v1/projects/my-project/managedZones/example-com/changes" \
  -d '{
    "additions": [
      {"name": "staging.example.com.", "type": "A", "ttl": 300, "rrdatas": ["203.0.113.10"]}
    ]
  }'

応答には変更の ID と状態(pending または done)が含まれます。pending の場合は、同じゾーンの changes/{変更ID} を GET して done になるのを待ちます。

既存のレコードセットを書き換えるときは、deletions に今の内容を、additions に新しい内容を入れます。このとき deletions に書く内容(TTL と値)は、今登録されている内容と一致していなければなりません。一致しないとエラーになり、変更は適用されません。手で書くと間違えやすいので、次の手順のように「今の値を読んでからそのまま削除側に入れる」形にします。

手順4:Python で「違うときだけ書き換える」スクリプトにする

WordPress サーバーの IP が変わったときにレコードを追従させる、といった用途では、何度実行しても同じ結果になるスクリプトにしておくと安心です。Google API の Python クライアント(google-api-python-client と google-auth)を使った例です。

import os
import time

import google.auth
from googleapiclient.discovery import build

PROJECT = os.environ["GCP_PROJECT"]   # 例: my-project
ZONE = os.environ["DNS_ZONE"]         # 例: example-com(ゾーンの名前)
NAME = "www.example.com."
RTYPE = "A"
NEW_TTL = 300
NEW_VALUES = ["203.0.113.20"]

credentials, _ = google.auth.default(
    scopes=["https://www.googleapis.com/auth/ndev.clouddns.readwrite"]
)
dns = build("dns", "v1", credentials=credentials, cache_discovery=False)

current = dns.resourceRecordSets().list(
    project=PROJECT, managedZone=ZONE, name=NAME, type=RTYPE
).execute().get("rrsets", [])

if current and current[0]["ttl"] == NEW_TTL and sorted(current[0]["rrdatas"]) == sorted(NEW_VALUES):
    print("変更不要: 現在の値と同じです")
    raise SystemExit(0)

body = {
    "deletions": current,  # 今の内容をそのまま削除側に入れる
    "additions": [{"name": NAME, "type": RTYPE, "ttl": NEW_TTL, "rrdatas": NEW_VALUES}],
}
change = dns.changes().create(project=PROJECT, managedZone=ZONE, body=body).execute()

while change["status"] != "done":
    time.sleep(2)
    change = dns.changes().get(
        project=PROJECT, managedZone=ZONE, changeId=change["id"]
    ).execute()

print("反映しました: change id", change["id"])

認証は google.auth.default() に任せているので、VM のサービスアカウント、Workload Identity 連携、手元の application-default のいずれでも、コードを変えずに動きます。プロジェクト名やゾーン名は環境変数で渡し、スクリプトに認証情報を書き込まないようにします。

先に今の値を読み、同じなら何もせず終わるので、cron などで定期的に実行しても無駄な変更が積み重なりません。読み取りから書き込みまでの間に別の誰かが同じレコードを変えた場合は、削除側の内容が一致せずにエラーになるため、意図しない上書きも防げます。

手順5:反映を確かめる

変更が done になったら、Cloud DNS のネームサーバーに直接問い合わせて、新しい値が返るかを確認します。

dig +short www.example.com A @ns-cloud-a1.googledomains.com

ネームサーバー名はゾーンごとに割り当てられるので、手順2の describe で表示されたものを使います。権威サーバーで新しい値が返っていれば Cloud DNS 側の作業は完了で、利用者の手元に届くまでの時間は変更前の TTL に左右されます。IP の切り替えを予定しているなら、事前に TTL を短くしておきます。

つまずきやすい点

  • 末尾のドットを忘れる: name や CNAME の値は完全修飾名で書きます。
  • 長い TXT: 255 文字を超える値(DKIM の公開鍵など)は、"前半" "後半" のように複数の文字列に分けて1つの値として渡します。
  • 割り当て(クォータ): 変更の回数やレコード数には上限があります。大量に変更する場合は1回の変更にまとめ、上限は Google Cloud コンソールの割り当て画面で確認します。
  • 変更の記録: API による変更は監査ログに残るので、トラブル時はどのサービスアカウントが変えたかを確認できます。

まとめ

  • Cloud DNS の API は、名前とタイプごとのレコードセットを単位に、削除と追加をまとめた「変更」で書き換えます。
  • 自動化には DNS 用のサービスアカウントを使い、鍵ファイルより VM への割り当てや Workload Identity 連携を優先します。
  • 既存のレコードを書き換えるときは、今の内容を読んでそのまま削除側に入れると、不一致によるエラーと意図しない上書きを防げます。
  • 作業前にゾーンを書き出して控え、変更後は Cloud DNS のネームサーバーへ直接問い合わせて確かめます。

お気軽にご相談ください

お見積りへ お問い合わせへ
▲