Amazon AuroraのヘッドレスDBクラスターを作成してみた

DBインスタンスを長期間停止したいのであれば、一時的に削除するのも選択肢に
2024.03.24

当分の間DBを使用する予定はないのでDBインスタンスはしばらく停止し続けたい

こんにちは、のんピ(@non____97)です。

皆さんはAmazon Auroraを使用していて「当分の間DBを使用する予定はないのでDBインスタンスはしばらく停止し続けたい」と思ったことはありますか? 私はあります。

RDSやAuroraのDBインスタンス、DBクラスターを停止できるのは最大7日です。7日経過すると自動で起動してきます。直接7日以上停止することはできません。もし7日以上停止し続けたいのであれば、DBインスタンスやDBクラスターが起動してきたら停止するというEventBridge RuleとLambda関数 or Step Functionsが必要だと考えます。

Auroraを使っている場合、そんなお悩みはヘッドレスDBクラスターとすることで問題を解決できるかもしれません。

Auroraではストレージとコンピューティングが分離しています。

AuroraArch001

抜粋 : Amazon Aurora DB クラスター - Amazon Aurora

そのため、AuroraのDBインスタンスを削除して、DBクラスター内に何もインスタンスが存在しない状態(ヘッドレスDBクラスター)としても、ストレージ内にデータは残り続けます。データを取り出したい、DBとして動作させたい場合はDBインスタンスを起動すれば良いだけです。

実際にやってみました。

いきなりまとめ

  • 全てのAurora DBインスタンスを削除しても、DBインスタンスを再作成すれば、DBクラスター内のデータにアクセスできる
  • ヘッドレスDBクラスターでもDBクラスターのスナップショットは取得できる
  • 以下の操作はマネジメントコンソールから行えない
    • ヘッドレスDBクラスターへのDBインスタンスの作成
  • ヘッドレスDBクラスターの状態では以下の操作はできない
    • Data APIを使ったクエリ実行
    • Global Databaseの作成
    • クローンの作成
    • PITR
    • S3へのエクスポート
  • 正直、長期間起動させないのであれば、スナップショットからリストアした方が良いように思える
    • バックアップストレージの料金 : 0.023 USD/GB
    • Aurora Standardのストレージの料金 : 0.12 USD/GB

やってみた

検証環境

検証環境は以下のとおりです。Aurora PostgreSQLと操作用のEC2インスタンスを1つづつ作成します。

Amazon RDS Blue:Green Deployments で Amazon Aurora PostgreSQL のメジャーバージョンアップをしてみた検証環境構成図

なお、構成は以下記事で紹介しているものです。

検証環境はAWS CDKでデプロイしました。使用したコードは以下リポジトにあります。

Aurora DBクラスターの作成

それではAurora DBクラスターの作成をします。

npx cdk deployでデプロイして10分ほどでAurora DBクラスターとDBインスタンスが起動完了しました。

Aurora DBクラスターが起動したことを確認

DBへのデータの投入

DBへデータを投入します。

下準備としてSecrets Managerに保存されている認証情報を環境変数に保存します。

$ get_secrets_value=$(aws secretsmanager get-secret-value \
    --secret-id AuroraSecret7ACECA7F-BLZxpBZDcJDq \
    --region us-east-1 \
    | jq -r .SecretString)

$ export PGHOST=$(echo "${get_secrets_value}" | jq -r .host)
$ export PGPORT=$(echo "${get_secrets_value}" | jq -r .port)
$ export PGDATABASE=$(echo "${get_secrets_value}" | jq -r .dbname)
$ export PGUSER=$(echo "${get_secrets_value}" | jq -r .username)
$ export PGPASSWORD=$(echo "${get_secrets_value}" | jq -r .password)

PostgreSQLが提供しているサンプルデータを投入します。

$ curl https://ftp.postgresql.org/pub/projects/pgFoundry/dbsamples/iso-3166/iso-3166-1.0/iso-3166-1.0.tar.gz \
  -s \
  -o iso-3166-1.0.tar.gz

$ tar zxvf iso-3166-1.0.tar.gz
iso-3166/
iso-3166/iso-3166.sql

$ createdb iso

$ psql -f iso-3166/iso-3166.sql iso
BEGIN
SET
CREATE TABLE
COPY 242
CREATE TABLE
COPY 3995
COMMIT
ANALYZE
ANALYZE

サンプルデータ投入後、DBに接続してレコードが登録されていることを確認します。

$ psql iso
psql (15.6, server 14.10)
SSL connection (protocol: TLSv1.3, cipher: TLS_AES_256_GCM_SHA384, compression: off)
Type "help" for help.

iso=> \dt
           List of relations
 Schema |    Name    | Type  |  Owner
--------+------------+-------+----------
 public | country    | table | postgres
 public | subcountry | table | postgres
(2 rows)

iso=> SELECT count(*) FROM country;
 count
-------
   242
(1 row)

iso=> SELECT count(*) FROM subcountry;
 count
-------
  3995
(1 row)

DBインスタンスの削除

DBインスタンスを削除します。AWS CDKでAurora DBクラスターを作成したので、DBインスタンスの削除もAWS CDKから行います。

具体的には以下のようにDBクラスターからDBインスタンスを探してきて、tryRemoveChild()で削除するコードを追加します。

./lib/construct/aurora.ts

    this.dbCluster.node.children.forEach((child) => {
      if (child.node.defaultChild instanceof cdk.aws_rds.CfnDBInstance) {
        this.dbCluster.node.tryRemoveChild(child.node.id);
      }
    });

npx cdk diffをすると、確かにDBインスタンスのみを削除してくれそうです。

$ npx cdk diff
Stack AuroraStack
Hold on while we create a read-only change set to get a diff with accurate replacement information (use --no-change-set to use a less accurate but faster template-only diff)
Resources
[-] AWS::RDS::DBInstance Aurora/Default/Writer AuroraWriter14FF9353 destroy


✨  Number of stacks with differences: 1

npx cdk deployを叩いて15分弱でDBクラスター内からのDBインスタンスの削除が完了しました。

ヘッドレスDBクラスターとなっていることを確認

DBへ接続しようとしても当然ながら弾かれます。

$ psql iso
psql: error: could not translate host name "db-cluster.cluster-cicjym7lykmq.us-east-1.rds.amazonaws.com" to address: Name or service not known

そもそも、DBクラスターエンドポイントを名前解決しても、DBインスタンスが存在しないため結果が返ってきません。

$ dig db-cluster.cluster-cicjym7lykmq.us-east-1.rds.amazonaws.com

; <<>> DiG 9.16.48-RH <<>> db-cluster.cluster-cicjym7lykmq.us-east-1.rds.amazonaws.com
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NXDOMAIN, id: 2256
;; flags: qr rd ra; QUERY: 1, ANSWER: 1, AUTHORITY: 1, ADDITIONAL: 1

;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags:; udp: 4096
;; QUESTION SECTION:
;db-cluster.cluster-cicjym7lykmq.us-east-1.rds.amazonaws.com. IN        A

;; ANSWER SECTION:
db-cluster.cluster-cicjym7lykmq.us-east-1.rds.amazonaws.com. 5 IN CNAME db-instance-writer.cicjym7lykmq.us-east-1.rds.amazonaws.com.

;; AUTHORITY SECTION:
us-east-1.rds.amazonaws.com. 10 IN      SOA     ns-1420.awsdns-49.org. awsdns-hostmaster.amazon.com. 1 7200 900 1209600 86400

;; Query time: 0 msec
;; SERVER: 10.1.1.2#53(10.1.1.2)
;; WHEN: Sun Mar 24 08:31:31 UTC 2024
;; MSG SIZE  rcvd: 216

ちなみにマネジメントコンソールからDBインスタンスを削除してもヘッドレスDBクラスターになります。

DBクラスターのスナップショットを取得できることを確認

DBクラスターのスナップショットが取得できるか気になったので試してみます。データの変化は発生しませんが、自動バックアップがコケ続けることにより、最後に正常に取得できたスナップショットの有効期限が切れるのは避けたいです。

マネジメントコンソールからDBクラスターのスナップショットを取得します。

DBスナップショットの取得

すると、1分ほどでスナップショットの取得が完了しました。

DBクラスターのスナップショットが完了したことを確認

DBクラスターのスナップショットを取得できるのであれば、自動バックアップがコケてしまうこともなさそうです。

ヘッドレスDBクラスターでできない操作を確認

続いて、ヘッドレスDBクラスターでできない操作を確認してみます。

マネジメントコンソールでDBクラスターのアクションをクリックすると、以下のようにグレーアウトされている項目がいくつかあります。

マネジメントコンソール上からDBインスタンスの追加はできない

また、WriterのDBインスタンスを作成することも出来なさそうです。

実際にいくつか操作してみます。

Global Databaseを作成しようとすると、このクラスターおよび関連付けられたインスタンスは現在作成中です。作成が完了しクラスターが使用可能になると、グローバルデータベースを作成してリージョンを追加できるようになります。とDBインスタンスが存在しないのは、DBインスタンスを作成していると判断して作成させてくれませんでした。

グローバルデータベースの作成およびリージョンの追加ができません

レプリカを追加しようとすると、DBInstance db-instance-writer not found.とDBインスタンスがないため弾かれました。

DBInstance db-instance-writer not found

クローンの作成やPITRをしようとすると、The parameter Filter: dbi-resource-id is not a valid DbiResourceId. The DbiResourceId must begin with db- prefix; remaining part must contain only ASCII letters and digits; and must not be empty.とDBインスタンスがないため怒られました。

The parameter Filter- dbi-resource-id is not a valid DbiResourceId. The DbiResourceId must begin with db- prefix

S3へのエクスポートを行おうとすると、The source cluster DBクラスターのARN can't be exported because it doesn't have an instance.と怒られました。

The_source_cluster_arn-aws-rds-us-east-1-AWSアカウントID-cluster-db-cluster_can_t_be_exported_because_it_doesn_t_have_an_instance

Data APIからのリクエストを行おうとすると、DBインスタンスがないと怒られました。

$ aws rds-data execute-statement \
  --resource-arn arn:aws:rds:us-east-1:<AWSアカウントID>:cluster:db-cluster \
  --secret-arn arn:aws:secretsmanager:us-east-1:<AWSアカウントID>:secret:AuroraSecret7ACECA7F-BLZxpBZDcJDq-sGEKy7 \
  --database iso \
  --sql 'SELECT count(*) FROM country;'

An error occurred (DatabaseNotFoundException) when calling the ExecuteStatement operation: Cannot find DBInstance in DBCluster arn:aws:rds:us-east-1:<AWSアカウントID>:cluster:db-cluster.

よくよくドキュメントを見てみると、Data APIのクエリはWriterインスタンスで実行されると記載されていますね。

Data API クエリは、DB クラスターのライターインスタンスでのみ実行できます。ただし、ライターインスタンスは書き込みクエリと読み取りクエリの両方を受け入れることができます。

RDS Data API の使用 - Amazon Aurora

ちなみにData APIの有効化/無効化はヘッドレスDBクラスターでも行えました。

RDS Data API の有効化

DBインスタンスの再作成

DBインスタンスの再作成を行います。

RDS Data API の無効化

DBインスタンスを削除するために追加したコードを削除して、再度デプロイします。

npx cdk diffをすると、DBインスタンスが追加されることが分かります。

$  npx cdk diff
Stack AuroraStack
Hold on while we create a read-only change set to get a diff with accurate replacement information (use --no-change-set to use a less accurate but faster template-only diff)
Resources
[+] AWS::RDS::DBInstance Aurora/Default/Writer AuroraWriter14FF9353 


✨  Number of stacks with differences: 1

npx cdk deploy後、10分弱でDBインスタンスの起動が完了しました。

DBインスタンスの再作成が完了したことを確認

DBインスタンス削除前に投入したデータにアクセスできるか確認

それでは、DBインスタンス削除前に投入したデータにアクセスできるか確認してみましょう。

$ psql iso
psql (15.6, server 14.10)
SSL connection (protocol: TLSv1.3, cipher: TLS_AES_256_GCM_SHA384, compression: off)
Type "help" for help.

iso=> \dt
           List of relations
 Schema |    Name    | Type  |  Owner
--------+------------+-------+----------
 public | country    | table | postgres
 public | subcountry | table | postgres
(2 rows)

iso=> SELECT count(*) FROM country;
 count
-------
   242
(1 row)

iso=> SELECT count(*) FROM subcountry;
 count
-------
  3995
(1 row)

iso=> SELECT * FROM country LIMIT 10;
        name         | two_letter | country_id
---------------------+------------+------------
 Afghanistan         | AF         |          4
 Albania             | AL         |          8
 Algeria             | DZ         |         12
 American Samoa      | AS         |         16
 Andorra             | AD         |         20
 Angola              | AO         |         24
 Anguilla            | AI         |        660
 Antarctica          | AQ         |         10
 Antigua and Barbuda | AG         |         28
 Argentina           | AR         |         32
(10 rows)

iso=> SELECT * FROM subcountry LIMIT 10;
 country | subcountry_name |      subdivision      | subcountry_level
---------+-----------------+-----------------------+------------------
 AD      | AN              | Andorra la Vella      |
 AD      | CA              | Canillo               |
 AD      | EE              | Escaldes-Engordany    |
 AD      | EN              | Encamp                |
 AD      | JL              | Sant Julià de Lòria   |
 AD      | MA              | La Massana            |
 AD      | OR              | Ordino                |
 AE      | AJ              | Ajman                 |
 AE      | AZ              | Abu Z¸aby [Abu Dhabi] |
 AE      | DU              | Dubayy [Dubai]        |
(10 rows)

確かにDBインスタンスを削除しても、ストレージ内にあるデータは削除されずに残っていることが分かりました。

DBインスタンスを長期間停止したいのであれば、一時的に削除するのも選択肢に

Amazon AuroraのヘッドレスDBクラスターを紹介しました。

Auroraがコンピューティングとストレージが分離していることがよく分かりますね。

なお、DBインスタンスの停止がコスト削減であり、長期間起動させないのであればスナップショットからリストアした方がコスト効率が良いように思えます。

料金を比較すると以下のとおりです。

  • バックアップストレージの料金 : 0.023 USD/GB
  • Aurora Standardのストレージの料金 : 0.12 USD/GB

Autoraのバックアップ料金の考え方は以下記事にまとまっています。

この記事が誰かの助けになれば幸いです。

以上、AWS事業本部 コンサルティング部の のんピ(@non____97)でした!