はじめに
Autonomous Database (ADB)には、Autonomous Data Guardという機能が存在し、障害、災害などの際にもデータベースを継続的に使用することが可能です
Autonomous Data Guardは、完全に分離された2つのデータベース・コピー(アプリケーションが接続して使用するプライマリ・データベースと、プライマリ・データベースの同期コピーであるスタンバイ・データベース)を作成してメンテナンスします。その後、なんらかの理由でプライマリ・データベースが使用できなくなった場合、Autonomous Data Guardは自動的にスタンバイ・データベースをプライマリ・データベースに変換することで、アプリケーションへのサービス提供を開始します。
ただ、Autonomous Data Guard では、 ADB しかディザスタ・リカバリ(以下 DR)に対応できません
そこで、Web/AP層も、 トラフィック管理 機能を用いて、耐障害性を高めた構成を検証してみたいと思います
なお、VCN、サブネット、SL、NSG、ロードバランサ、Web/APサーバ、ADB の作成などは割愛させていただき、本記事に必要な箇所のみを対象として記載させて頂きます
構成
ロードバランサ、Web/AP サーバ、ADB の構成を東京・大阪リージョンにそれぞれ作成しています
ADB に関しては、個別にインスタンスを作成するのではなく、 クロスリージョン Autonomous Data Guard を用いて作成し、大阪リージョン側はスタンバイ・データベースとなります
また、それぞれのロードバランサへは FQDN でアクセスできるように DNS を設定し、障害検知用にヘルスチェックも設定を行います
スペック
- ロードバランサ
- 最小接続: 10 Mbps
- 最大接続: 10 Mbps
- Compute (Web/APサーバ)
- シェイプ: VM.Standard.E4.Flex
- OCPU数: 1
- メモリー: 16 GB
- ADB
- ワークロード・タイプ: データ・ウェアハウス
- ECPU数: 2
- ストレージ: 1TB
事前準備
1. スタンバイ・データベースの作成
a. 左リソースメニュー > ディザスタ・リカバリを選択し、ピア・データベースの追加をクリック
b. 以下内容を設定し、ピア・データベースの追加をクリック
- リージョン: 大阪リージョンを選択
- コンパートメントの選択: ピア・データベースのコンパートメントを選択
- ディザスタ・リカバリ・タイプの選択: Autonomous Data Guard を選択
- ディザスタ・リカバリ・ピアへのクロスリージョン・バックアップ・レプリケーションの有効化: 任意(本記事ではオフ)
- 仮想クラウド・ネットワーク: ピア・データベースの VCN を選択
- サブネット: ピア・データベースのサブネットを選択
- プライベートIPアドレス: 任意(本記事では未指定)
- ホスト名接頭辞: 任意(本記事では未指定)
- ネットワーク・セキュリティ・グループ(NSG): 任意(本記事では未指定)
c. スタンバイ・データベース追加完了
作成が完了すると、ピア・ロールが スタンバイ
、リージョンが ap-osaka-1
、DR タイプが Autonomous Data Guard
となっていることが確認できます
その際のデータベース名は、スタンバイ・データベースを作成したデータベース名に _Remote
が付与された名前に自動的になります
2. クライアント資格証明(ウォレット)のダンロード・配置
a. クライアント資格証明(ウォレット)をダウンロードします
b. Web/AP サーバにウォレットを配置します
本記事では、 /opt/oracle/network/admin/ 以下に配置しています
1 2 3 4 5 6 7 8 9 10 11 12 |
# ls -l /opt/oracle/network/admin/ total 76 -rw-r--r-- 1 root root 2957 Feb 19 01:08 README -rw-r--r-- 1 root root 21964 Feb 19 10:08 Wallet_J1FN4JNQG0LP9LKL.zip -rw-r--r-- 1 root root 5349 Feb 19 01:08 cwallet.sso -rw-r--r-- 1 root root 5304 Feb 19 01:08 ewallet.p12 -rw-r--r-- 1 root root 5710 Feb 19 01:08 ewallet.pem -rw-r--r-- 1 root root 3193 Feb 19 01:08 keystore.jks -rw-r--r-- 1 root root 691 Feb 19 01:08 ojdbc.properties -rw-r--r-- 1 root root 113 Feb 19 01:08 sqlnet.ora -rw-r--r-- 1 root root 840 Feb 19 01:08 tnsnames.ora -rw-r--r-- 1 root root 2056 Feb 19 01:08 truststore.jks |
3. ヘルスチェック用URLとindex.htmlを準備する
a. Apache, mod_fcgid, python3.11, python3.11-oracledb をインストール
1 |
# dnf install -y httpd mod_fcgid python3.11 python3.11-oracledb |
b. python3.11 をデフォルトで使用するように変更
デフォルトでインストールされている python のバージョンが 3.6 と古いため、 3.11 をインストールし、使用するように変更します
1 2 3 4 5 6 7 8 9 10 11 12 13 |
# update-alternatives --config python3 There are 2 programs which provide 'python3'. Selection Command ----------------------------------------------- *+ 1 /usr/bin/python3.6 2 /usr/bin/python3.11 Enter to keep the current selection[+], or type selection number: 2 # python -V Python 3.11.5 |
c. ヘルスチェック・スクリプトを作成
以下のスクリプトを /var/www/html/health.py
として作成します
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 |
#!/usr/bin/python3 import datetime import oracledb def connect_check(): result = '' exec_dt = '' message = '' config = None try: connection = oracledb.connect( config_dir = '/opt/oracle/network/admin', user = '<ヘルスチェック用DBユーザー>', password = '<パスワード>', dsn = '<DB接続文字列>', wallet_location = '/opt/oracle/network/admin', wallet_password = '<ウォレットをダウンロードする際に指定したパスワード>', ) cur = connection.cursor() cur.execute("SELECT TO_CHAR(SYSDATE, 'YYYY/MM/DD HH24:MI:SS') FROM DUAL") sysdate = cur.fetchone() cur.close() connection.close() result = 'OK' exec_dt = sysdate[0] message = '' except Exception as e: result = 'NG' exec_dt = datetime.datetime.now().strftime('%Y/%m/%d %H:%M:%S') message = str(e) return (result, exec_dt, message) if __name__ == '__main__': result, exec_dt, message = connect_check() print("Content-Type: text/html") print() htmlText = ''' <html> <head> <title>Connect Check to ADB</title> </head> <body> <p>%s</p> <p>CHECK: %s</p> <p>MESSAGE: %s</p> </body> </html> '''%(exec_dt, result, message) print(htmlText) |
d. fcgi で実行するため、ヘルスチェック・スクリプトに実行権を付与します
1 |
# chmod +x /var/www/html/health.py |
e. index.htmlを作成します
以下のファイルを /var/www/html/index.html
として作成します
1 2 3 4 5 6 7 8 |
<html> <head> <title>test</title> </head> <body> <p>test nrt</p> </body> </html> |
※body部分の nrt
は大阪リージョンでは、 osk
など、区別できる文字列に変更して作成します
f. fcgi の設定を行います
以下のファイルを /etc/httpd/conf.d/python.conf
として作成します
1 2 3 4 5 6 7 8 9 10 11 |
<VirtualHost *:80> DocumentRoot /var/www/html Timeout 120 <Directory "/var/www/html"> AllowOverride None Options ExecCGI Require all granted AddHandler cgi-script .cgi .py </Directory> </VirtualHost> |
g. Apache を起動します
1 2 3 4 5 6 7 8 9 10 |
# systemctl enable --now httpd.service # curl http://localhost/ <html> <head> <title>test</title> </head> <body> <p>test nrt</p> </body> </html> |
4. ロードバランサのヘルスチェックを設定します
a. ロードバランサのヘルスチェックを、3で作成したヘルスチェック用スクリプトに対して実行するようにします
- URLパス: /health.py
- レスポンス本体の正規表現: CHECK: OK
とします
5. DNSのゾーンを設定します
www-nrt.kblog.smartstyle.ne.jp と www-osk.kblog.smartstyle.ne.jp の A レコードをそれぞれ作成しておきます
A レコードとして登録する IP アドレスは、ロード・バランサのパブリック IP とします
6. トラフィック管理のフェイルオーバー・ポリシーを作成します
a. 左上のハンバーガーメニュー > ネットワーク > DNS 管理 > トラフィック管理ステアリング・ポリシーをクリック
b. トラフィック管理ステアリング・ポリシーの作成をクリック
c. 以下内容を設定し、ポリシーの作成をクリック
- ポリシー・タイプ: フェイルオーバー
- ポリシー名: 任意(本記事では
DR確認
) - ポリシーTTL: 任意(本記事ではデフォルト値の
60
) - 回答プール1
- 回答プール名: 任意(本記事では
NRT-Pool
、 ただしポリシー内で一意である必要があります ) - 回答
- 名前: 任意(本記事では
www-nrt
、 ただしポリシー内で一意である必要があります ) - タイプ: 任意(本記事では
CNAME
) - Rdata: 上記タイプに対する値(本記事では
www-nrt.kblog.smartstyle.ne.jp
)
- 名前: 任意(本記事では
- 回答プール名: 任意(本記事では
- 回答プール2
- 回答プール名: 任意(本記事では
OSK-Pool
、 ただしポリシー内で一意である必要があります ) - 回答
- 名前: 任意(本記事では
www-osk
、 ただしポリシー内で一意である必要があります ) - タイプ: 任意(本記事では
CNAME
) - Rdata: 上記タイプに対する値(本記事では
www-osk.kblog.smartstyle.ne.jp
)
- 名前: 任意(本記事では
- 回答プール名: 任意(本記事では
- プールの優先度
- 1: プール1 – NRT-Pool
- 2: プール2 – OSK-Pool
- ヘルス・チェックのアタッチ
- 新規追加
- ヘルス・チェック名: 任意(本記事では
DR-Check
) - 間隔: 任意(本記事では
30
) - プロトコル: 任意(本記事では
HTTPS
) - ポート: 任意(本記事では未指定)
- パス: 任意(本記事では未指定)
- メソッド: 任意(本記事では
GET
) - タイムアウト: 任意(本記事では未指定)
- ヘッダー: 任意(本記事では未指定)
- アタッチ済ドメイン
- サブドメイン: 任意(本記事では
www
、このサブドメインが最終的な URL となります ) - コンパートメント: 5で設定したDNSゾーンのコンパートメントを選択
- ゾーン: 4で設定したDNSゾーン名を選択
- サブドメイン: 任意(本記事では
アタッチ済ドメインで設定したサブドメインと、ゾーンで指定した DNS ゾーン(ドメイン)を用いて、 FQDN が決定されます
本記事では、 www.kblog.smartstyle.ne.jp
となります
d. 確認
東京リージョン側のヘルス・ステータスが 正常
になっていることを確認します
大阪リージョン側が異常判定ですが、これはデータベースへ接続できないことに起因していますがこの状態が正常な状態です
データベースへ接続できない理由は下記に記載している通り、リモート・スタンバイ・データベースは接続不可であるためです
リモート・スタンバイには接続できず、リモート・スタンバイ・データベースを読取り専用操作に使用することはできません。
リモート・リージョン・データベースに接続できるのは、スイッチオーバーまたは手動フェイルオーバーの後にプライマリ・ロールを引き継いだときです。
引用: クロスリージョン・スタンバイでのAutonomous Data Guard
動作確認
1. 通常状態でアクセス
ブラウザで、www.kblog.smartstyle.ne.jp へアクセスすると、test nrt
と東京リージョン側のページが表示されます
2. フェイルオーバー
実際に OCI でリージョン障害を起こすことはできないため、今回は手動で ADW を大阪リージョンへフェイルオーバーすることとします
a. リモート・スタンバイ側でスイッチオーバーをクリックします
ここで、プライマリ側でスイッチオーバーしようとしても、下記のようにスイッチオーバーすることはできませんので、リモート側で実施願います
b. データベース名を入力し、ピアへのスイッチオーバーの確認をクリックします
使用可能になれば、スイッチオーバー完了です
3. 確認
大阪リージョン側のヘルス・ステータスが 正常
になっていることを確認します
ブラウザで、www.kblog.smartstyle.ne.jp へアクセスすると、test osk
と大阪リージョン側のページが表示されます
まとめ
Autonomous Database だけでなくWeb/AP層まで行おうとすると、DNSなどの設定が必要になりますが、通常のアプリケーションを想定すると、DNSなどはすでに設定済みで有ることが想像できます
そのため、実際に必要な設定はトラフィック管理のフェイルオーバー・ポリシーを作成するぐらいと思われますので、それほどハードルは高くないのではないでしょうか
ただし、本記事の構成では大阪の Web/AP サーバが起動しているホット・スタンバイ状態ですので、不必要な課金が発生してしまいますので、注意は必要となります
また、今回の検証では ADW のスイッチオーバー
をトリガーとしてフェイルオーバーしていますが、Web/AP サーバ側の障害時には ADW はスイッチオーバーしませんので、Web/AP サーバの冗長化など構成の検討はまだまだ必要となります
その際には、 自動スケーリング も検討いただければと思います