2017年10月18日水曜日

db2bak.pl の結果を知りたい

389 Directory Server の db2bak.pl の中身を見る限り、どうやらこれは
 "cn=backup, cn=tasks, cn=config" にエントリを追加するだけで、後は task プラグイン
にお任せのようだ。

エントリの追加後タスクの実行を待っていたりしないので非同期で、その結果は db2bak.pl
だけでは得ることができない。同期モードを作るべきな気がするが。
# 自分で作れってw

ちなみに db2bak.pl の終了コードは perl の DSUtil:ldapmod() の返り値と同じなので、
エントリ追加が出来たかどうかしか取れない。

じゃぁ終了判断やその結果をどうやって知るかってことになるが、errors ログファイル
を見るのが一番確実ではあるが行parseするのが面倒。

db2bak.pl を実行すると以下のように標準出力にエントリの DN が表示される。

# db2bak.pl -Z testinst -D "cn=Directory Manager" -w password
Back up directory: /var/lib/dirsrv/slapd-testinst/bak/rhds1-2017_10_18_2_15_12
Successfully added task entry "cn=backup_2017_10_18_2_15_12, cn=backup, cn=tasks, cn=config"

そのエントリを参照すると以下のよう。


dn: cn=backup_2017_10_18_2_20_7,cn=backup,cn=tasks,cn=config
objectClass: top
objectClass: extensibleObject
cn: backup_2017_10_18_2_20_7
nsarchivedir: /var/lib/dirsrv/slapd-testinst/bak/hoge
nsdatabasetype: ldbm database
nstaskcurrentitem: 0
nstasktotalitems: 1
nstasklog:: xxxxxx
  :
nstaskstatus: Backup finished.
nstaskexitcode: 0

nstasklog 属性に base64 で詳細ログが記録されてる。終了したか否かの判断は
nstaskstatus と nstaskexitcode ですれば良いっぽい。ただ、このエントリは終了後
その結果にかかわらず 2 分で消える。2 分という設定がどこにあるかわからないが、
以下で 2 分と言っている人がいた。cn=config にはそれらしき設定は無かった。

http://www.databaseusers.com/article/7985099/backup+monitor

Once a task has finished (good or bad), the entry will stay visible for 2 minutes. By viewing the nstaskstatus and nstaskexitcode attributes you can find out how far it has gone and if the task has finished successfully or with an error.
Here is an example using a persistent search filtering on nstaskexitcode so you only get a response back once the job has completed:

これをぐるぐる回して同期なスクリプトを作るか。終了後 2 分で消えるということは、
db2bak.pl 実行後にぐるぐる回す間隔を 2 分以内にすればとりあえずはなんとか消える
前に結果が取れるってことかな。

めんどくさっ
今から python で作り変えてみる。

2017年10月10日火曜日

389 Directory MemberOf Plugin は refint 不要ぽい

389 Directory の MemberOf プラグインは、あるメンバーの実エントリの DN を modrdn して書き換えると、
何もしなくても(refint overlay 使わなくても)ちゃんと groupOfNames 側の member を書き換えてくれる。

その逆の、ある groupOfNames のグループの実エントリで、グループの DN を modrdn で書き換えても
ちゃんとユーザエントリ側の memberOf を書き換えてくれた。

しかしながら groupOfNames の owner 属性は対象外っぽい。こちらは refint するしかないかも。

2017年10月7日土曜日

389 Directory Server リストア失敗 → 成功

くだらないミスだったんだけど、同じことでハマる人がいるかもしれないので役に立てばのメモ。

まぁ、タイトルは 389 Directory にしたけど本当は RHDS なんだけどね。おそらく同じだろうからまぁいいかな(違ってたらコメントで教えて下さい)。

bak2db.pl を使って、db2back.pl で取得したバックアップディレクトリからリストアを試みたが、/var/log/dirsrv/slapd-<instance>/errors には以下のエラーが。

ERR - ldbm_back_archive2ldbm - No back up "/home/ryo/rhds1-2017_10_7_3_20_46" exists.
ERR - task_restore_thread - Restore failed (error -1)

ぐぐっても情報が無いので、ソースから上記箇所を grep。すると servers/slapd/back-ldbm/archive.c に以下の箇所あり。

   48     return_value = dbversion_read(li, directory, &dbversion, &dataversion);
   49     if (return_value) {
   50         if (ENOENT == return_value) {
   51             slapi_log_err(SLAPI_LOG_ERR, "ldbm_back_archive2ldbm", "No back up \"%s\" exists.\n",
   52                           directory);
   53             return -1;
   54         }

どうも DB のバージョンを確認するファイルが無いと(ENOENT)。バックアップディレクトリ内のファイル名から考えると
DBVERSION ってのがあるんだけど... うーーん permission も問題なし... あ、SELinux ?バックアプファイルの context を見てみる。

# ls -Z
-rw-------. dirsrv dirsrv unconfined_u:object_r:user_home_t:s0 DBVERSION
-rw-------. dirsrv dirsrv unconfined_u:object_r:user_home_t:s0 dse_index.ldif
-rw-------. dirsrv dirsrv unconfined_u:object_r:user_home_t:s0 dse_instance.ldif
-rw-------. dirsrv dirsrv unconfined_u:object_r:user_home_t:s0 dse.ldif
   :

あぁぁ... てことで

# chcon -R system_u:object_r:dirsrv_var_lib_t:s0 rhds1-2017_10_7_3_20_46/

これで解決しますた。

2017年10月4日水曜日

389-consle (redhat-idm-console)が ssh の X Forward で動かん→動いた

redhat-idm-console (389-console)をリモート越しに起動して手元の X で表示しようと、
試みたところ以下のエラーで起動できない。

Exception in thread "main" java.awt.HeadlessException
        at java.awt.GraphicsEnvironment.checkHeadless(GraphicsEnvironment.java:204)
        at java.awt.Window.(Window.java:536)
        at java.awt.Frame.(Frame.java:420)
        at java.awt.Frame.(Frame.java:385)
        at javax.swing.JFrame.(JFrame.java:189)
        at com.netscape.management.client.console.Console.(Unknown Source)
        at com.netscape.management.client.console.Console.main(Unknown Source)
Headless というのがようわからんが、/etc/java/とredhat-389-console.conf で以下の
ようにとにかくこれを外してみた。


$ diff -u /etc/java/redhat-389-console.conf.dist /etc/java/redhat-389-console.conf
--- /etc/java/redhat-389-console.conf.dist      2016-10-10 01:45:11.000000000 +0000
+++ /etc/java/redhat-389-console.conf   2017-10-04 01:44:55.026633680 +0000
@@ -1,3 +1,3 @@
 mylang=${mylang:-en}
 ADDITIONAL_JARS=${ADDITIONAL_JARS:-redhat-idm-console_$mylang.jar}
-ADDITIONAL_OPTIONS=${ADDITIONAL_OPTIONS:-"-Dprogram.name=redhat-idm-console -Djava.util.prefs.systemRoot=$HOME/.redhat-idm-console -Djava.util.prefs.userRoot=$HOME/.redhat-idm-console"}
+ADDITIONAL_OPTIONS=${ADDITIONAL_OPTIONS:-"-Dprogram.name=redhat-idm-console -Djava.util.prefs.systemRoot=$HOME/.redhat-idm-console -Djava.util.prefs.userRoot=$HOME/.redhat-idm-console -Djava.awt.headless=false"}

すると、libawt_xawt.so が無いぞと怒られ調べたらこれは Headless でない
java-1.8.0-openjdk パッケージに含まれる模様

# yum install java-1.8.0-openjdk 

しかしなんで単なる設定をいじるのにこんなに重い GUI を起動せにゃあかんのか。しかも
激重な Java。Java は Windows 以上に嫌いだわ。どの OS とも相性が悪い。当初のコンセ
プトとは大違い。クソ言語。問題なのはプログラマが多いこと。だから糞システムが量産
される。Java の世界だけで OS 作って勝手にやってりゃいいのに。こっちくんな。

2017年9月7日木曜日

/etc/sudoers をいじらずに PATH を効かせる

RHEL系の /etc/sudoers には secure_path がデフォルトで定義されている。

デフォルトの /etc/sudoers をいじりたくないのだけど、secure_path を無効にして PATH を引き継ぎたい。
そんなことを思って /etc/sudoers.d/mysetting を以下のようにしてみようとした。が visudo  に怒られた。


Defaults    secure_path =
Defaults    env_keep +=  "PATH"
%mygroup ALL = (myuser) /path/to/target*
secure_path = "" も駄目。もうちょっと考えれば何かしら解法が見つかりそうなのだが、ちょっと時間がない。ただどうしても /etc/sudoers はいじりたくない。

とりあえず今は特定のパス(/path/to/target)だけ通せば良いから、/etc/sudoers.d/mysetting を以下のようにした。全部の PATH は無理だが、今回の要件は何とかクリア。

Defaults    secure_path = /path/to/target:/sbin:/bin:/usr/sbin:/usr/bin
Defaults    env_keep +=  "PATH"
%mygroup ALL = (myuser) /path/to/target*

RHEL デフォルト /etc/sudoers の secure_path は /sbin:/bin:/usr/sbin:/usr/bin なので、それに特定のパスの「/path/to/target」を追加しただけ。


ちなみに以下も試して全 PATH 通そうとしたが駄目だった。


Defaults    secure_path -= /sbin
Defaults    secure_path -= /bin
Defaults    secure_path -=/usr/sbin/
一旦定義したパラメータを無効にする命令は無いものか...


2017年9月5日火曜日

mysql で確保されたファイル領域を OS レベルで解放したい

MySQL であるフィールドに大きなデータが入っていたとして、それを update 文で
null にしたとする。が、当然 OS 的には空きデータは増えない。

OS に空き容量を反映させたい場合は innodb_file_per_table を ON にして、
OPTIMIZE TABLE すれば良いらしい。




2017年8月16日水曜日

MySQL 5.7 の root 初期パスワード

community 版の MySQL 5.7 を RPM でインストールしたらしょっぱなからログインできない。

何と mysqld のログファイル(Fedora だと /var/lib/mysqld.log)に root の初期パスワードがあるじゃないか。
grep 'temporary password' /var/log/mysqld.log

んで、以下コマンドで早速変更。
/usr/bin/mysql_secure_installation

2017年4月20日木曜日

libvirt からの xxx-nic っていう interface について

FAQ なんだろうけどメモ。

例えば libvirt のデフォルトのネットワークの場合、virbr0 というブリッジに
virbr0-nic っていう interface がアタッチされている。
これはなんぞやといつも不思議に思っていたものの気にせず、ホストからの接続のた
めのダミー NIC か何かかと勝手に決めつけて放置していた。が、いつも link down
してるのでやっぱり気持ち悪いので調べることに。

ソース読む ability も power も無く、ググッて見つけたのがこれ。↓

https://www.redhat.com/archives/libvirt-users/2012-September/msg00038.html

| It's a workaround for kernel bug/feature. The bridge's MAC is copied
| from the first NIC attached. So if one detach all interfaces from a
| bridge and then attach just one, the bridge will lost previous MAC and
| gain a new one - just the same as the attached interface has.
|
| So if libvirt has to ensure a MAC for virtual bridge - it creates this
| dummy device (no traffic is routed through though) and just attach it to
| the virtual bridge.

うぅ、これ Red Hat の中の人が言ってるし本当だよね?
なんと MAC アドレスを固定化させるためのダミーの NIC だったとは知らなんだ。








2017年4月12日水曜日

openstack baremetal import が返ってこない。

FAQ だろうけどメモ。表題の件、解決策は pm_password の指定方法に
あった...

https://access.redhat.com/solutions/1603243

RHOSP な環境で instackenv.json を作る時に

     "pm_type": "pxe_ssh",

にした際の pm_passwod の値をよく Web で見かける "$(cat ~/.ssh/id_rsa)"
にしちゃうと openstack baremetal import が返ってこない。長らく待って
返ってきてもエラー(エラー文字列は無くしてしまった)。

上記 URL に回避策あり。秘密鍵の値をそのまま記すが、改行の部分は「\n」
で表現する。以下例。

      "pm_password": "-----BEGIN RSA PRIVATE KEY-----\nMIIEpQIBAAKCAQEAwCz1ReNdQg5NxOx2ZZeOA4k+UaRAb4gobdL1lv/HJnNYlcrg\n.....................................\n6AJkDzAIQwQ1s1gjSdc7SYt1FcAPB/El0U6BAiI5lnYjWxfHAyMHkOs=\n-----END RSA PRIVATE KEY-----",


うーーん、なんちゅー仕様w。ま、ありか。

2017年3月14日火曜日

virsh, NetworkManager のエラーメッセージが日本語な件

日本語環境で virsh 使ってると、エラーメッセージが日本語になってしまう。
unset LC_ALL しても LANG=C LANGUAGE=en_US.UTF-8 してもダメ。

こりゃ libvirtd が握ってるなってことで /etc/sysconfig/libvirtd に以下を追加
して libvirtd 再起動したらエラーメッセージも全部日本語になった。

LANG=en_US.UTF-8

NetworkManager も同じ。/proc/<PID>/environ で確認すると LANG が日本語になっとる。
/usr/lib/systemd/system/NetworkManager.service の [Service] セクションに下記を追加して解決。

Environment=LANG=en_US.UTF-8

2017年3月3日金曜日

wildcard.fedoraproject.org の AAAA がかっこいい件

有名な話しなんだろうけど個人的に関心したのでメモ
dnf した後に ss したら気付いた。

[ryo@localhost ~]$ host -t AAAA wildcard.fedoraproject.org.
wildcard.fedoraproject.org has IPv6 address 2604:1580:fe00:0:dead:beef:cafe:fed1
wildcard.fedoraproject.org has IPv6 address 2605:bc80:3010:600:dead:beef:cafe:fed9
wildcard.fedoraproject.org has IPv6 address 2610:28:3090:3001:dead:beef:cafe:fed3

2017年2月19日日曜日

nmcli で MAC Address 固定

USB の NIC 使ってるんだけど、nmcli で connection を ifname 固定してたら再起動の時にそれが変わってしまった。下記で MAC 固定。

nmcli con modify usbeth0 connection.interface-name '' 802-3-ethernet.mac-address 'xx:xx:xx:xx:xx:xx'

まぁここにメモらなくても nmcli con show すれば属性名から適当に設定できるけど、誰かのお役に立てればと...

connection を add する時にやっちゃう方法については、Red Hat の RHEL7 のドキュメントに丁寧に記されていた。この場合は '*' というワイルドカードが使えるのね。以下一応コピペ。


プロファイルを特定の MAC アドレスにロックするには、以下の形式のコマンドを実行します。
nmcli connection add type ethernet con-name "connection-name" ifname "*" mac 00:00:5E:00:53:00

2017年2月14日火曜日

getent のエラー文字列日本語訳

# unset LC_ALL
# LANG=C getent netgroup
Enumeration not supported on netgroup

# getent netgroup
エミュレーションは netgroup 上ではサポートされていません

いやいや、Emulation じゃなくて Enumeration だから。
今仕事中だからあとでパッチを送ることにする。

2017年1月18日水曜日

GCE でクロスリージョン+オートスケーリング 第三回

GCE でクロスリージョン+オートスケーリング 第三回

前回までで,バックエンドとなる "インスタンスグループ" の作成が完了しました。これは,2 つのリージョンを跨る負荷分散を意識し,かつ "自動スケーリング" が可能な構成になっています。今回はこの続きで,"負荷分散(ロードバランサ)" の部分を作成していきます。


"バックエンドサービス" の作成

"バックエンドサービス" は,その中に "インスタンスグループ" と関連する "バックエンド"が含まれます。またその役割には,インスタンスに対するヘルスチェックの設定やセッションパーシステンスの設定,CDN の利用有無等があります。以下,このような "バックエンドサービス" を作成していきます。

"ヘルスチェック" の作成

"ヘルスチェック" のルールを個別のオブジェクトとして作成します。この作成した "ヘルスチェック" を,後に "バックエンドサービス" にアタッチします。これは複数のバックエンドサービスからアタッチすることができます。

"ヘルスチェック" のルールには,モニタする URL のパスやポート番号,チェック間隔,タイムアウト値等が含まれます。今回はチェックする URL のみ指定し,その他はデフォルトとします。また,"ヘルスチェック" を含む "負荷分散(ロードバランサ)" サービスからのリクエストをインスタンスが受け取れるようにするため,ファイアウォールルールも設定します。

  1.  site1 への "ヘルスチェック" を作成

    site1 では,チェックする URL を /site1/index.txt にします。ヘルスチェック名を「mygce-site1-health-check」とします。
  2. $ gcloud compute http-health-checks create mygce-site1-health-check \
      --request-path "/site1/index.txt"

  3. site2 への "ヘルスチェック" を作成

    site1 では,チェックする URL を /site2/index.txt にします。ヘルスチェック名を「mygce-site2-health-check」とします。
  4. $ gcloud compute http-health-checks create mygce-site2-health-check \
      --request-path "/site2/index.txt"

  5.  "ファイアウォールルール"

    "負荷分散(ロードバランサ)" サービスは,130.211.0.0/22 がソース IP アドレスとなります(このレンジについては,ここの「ヘルスチェックのソース IP とファイアウォール ルール」節をご覧ください)。これから 80 番ポートへのアクセスを下記コマンドで許可します。ファイアウォール名は「mygce-firewall-healthcheck」としました。
  6. $ gcloud compute firewall-rules create mygce-firewall-healthcheck \
      --source-ranges '130.211.0.0/22' \
      --allow tcp:80

site1 の "バックエンドサービス" の作成

  1. site1 の "バックエンドサービス" の作成

    セッションパーシステンスを一般的によく使われる cookie ベースとし,ヘルスチェックを上記で作成した「mygce-site1-health-check」に設定した "バックエンドサービス"「mygce-site1-bs」を作成します。
  2. $ gcloud compute backend-services create mygce-site1-bs \
      --session-affinity generated_cookie \
      --http-health-checks mygce-site1-health-check \
      --global

  3. "バックエンドサービス" に "バックエンド" を追加

    「mygce-site1-bs」に,前回作成した site1 の「mygce-site1-ig-asia」「mygce-site1-ig-us」の 2 つの "バックエンド" を追加します。
  4. $ gcloud compute backend-services add-backend mygce-site1-bs \
      --instance-group mygce-site1-ig-asia \
      --instance-group-zone asia-east1-b \
      --global
    
    $ gcloud compute backend-services add-backend mygce-site1-bs \
      --instance-group mygce-site1-ig-us \
      --instance-group-zone us-east1-b \
      --global

site2 の "バックエンドサービス" の作成

  1. site2 の "バックエンドサービス" の作成

    セッションパーシステンスを一般的によく使われる cookie ベースとし,ヘルスチェックを上記で作成した「mygce-site2-health-check」に設定した "バックエンドサービス"「mygce-site2-bs」を作成します。
  2. $ gcloud compute backend-services create mygce-site2-bs \
      --session-affinity generated_cookie \
      --http-health-checks mygce-site2-health-check \
      --global

  3. "バックエンドサービス" に "バックエンド" を追加

    「mygce-site2-bs」に,前回作成した site2 の「mygce-site2-ig-asia」「mygce-site2-ig-us」の 2 つの "バックエンド" を追加します。
  4. $ gcloud compute backend-services add-backend mygce-site2-bs \
      --instance-group mygce-site2-ig-asia \
      --instance-group-zone asia-east1-b \
      --global
    
    $ gcloud compute backend-services add-backend mygce-site2-bs \
      --instance-group mygce-site2-ig-us \
      --instance-group-zone us-east1-b \
      --global

"URL マップ" の作成

URL マップは,まずその本体を作成しその後にマッピングを設定します。今回は下記のルールで URL マップを作成します
  • mygce.fatriver.net というホストへのリクエストのみ下記ルールで振り分ける
    • /site1 から始まるパス → 「mygce-site1-bs」バックエンドサービスに振り分け
    • /site2 から始まるパス → 「mygce-site2-bs」バックエンドサービスに振り分け
  • 上記以外のリクエストは「mygce-site1-bs」に振り分け。
上記ルールの URL マップを以下のように作成します。
  1. "URL マップの作成"

    ここでは "URL マップ" の名前を「mygce-url-map」としています。
  2. $ gcloud compute url-maps create mygce-url-map \
      --default-service mygce-site1-bs

  3. "Path Matcher" 及び "Host Rules" の設定

    "URL マップ" は "Path Matcher" と "Host Rules" という 2 つのコンポーネントで構成されます。"Path Matcher" は,URL のパスと "バックエンドサービス" のマッピングを定義するものです。"Host Rules" は,ホスト名と "Path Matcher" のマッピング定義です。今回はホスト名は「mygce.fastriver.net」のひとつなのでこれらを一回のコマンドで定義できます。

    なお "Path Matcher" にも名前をつける必要があり,ここでは「mygce-path-matcher」としています。
  4. $ gcloud compute url-maps add-path-matcher mygce-url-map \
      --default-service mygce-site1-bs \
      --path-matcher-name mygce-path-matcher \
      --path-rules /site1=mygce-site1-bs,/site1/*=mygce-site1-bs,/site2=mygce-site2-bs,/site2/*=mygce-site2-bs \
      --new-hosts mygce.fastriver.net

"ターゲットプロキシ" の作成

今回は HTTPS "ターゲットプロキシ" を利用します。HTTPS "ターゲットプロキシ" では SSL 終端処理を行うので,その作成の際に SSL 証明書を登録する必要があります。ちゃんとした証明書を持っていないのでオレオレを使います。関係ありませんが,よく会社でオレオレ証明書の作り方を聞かれるのですが,意外と openssl req 一発で作れることを知らない人がいるので,一応その作り方も書いておきます。

  1. オレオレ SSL 証明書の作成

    秘密鍵を mygce.key, 証明書を mygce.crt として作成しています。作成した後,秘密鍵は暗号化されない生の状態にする必要があります。そのファイル名を mygce-nopass.key としています。
  2. $ openssl req -x509 -newkey rsa:2048 -keyout mygce.key -out mygce.crt
    $ openssl rsa -in mygce.key -out mygce-nopass.key # ← 秘密鍵のパスフレーズを解きます

  3. "SSL 証明書リソース" の登録

    上記で作成した SSL 証明書「mygce.crt」と秘密鍵「mygce.key」を "SSL 証明書リソース" として登録します。その名前を「mygce-cert」としています。
  4. $ gcloud compute ssl-certificates create mygce-cert \
      --certificate mygce.crt \
      --private-key mygce-nopass.key

  5. "ターゲットプロキシ" の作成

    上記で作成した "SSL 証明書リソース"「mygce-cert」と,"URL マップ" 「mygce-url-map」を使い "ターゲットプロキシ"「mygce-target-proxy」を作成します。
  6. $ gcloud compute target-https-proxies create mygce-target-proxy \
      --ssl-certificate mygce-cert \
      --url-map mygce-url-map

"グローバル転送ルール" の作成

最後に,フロントエンドの役割を受け持つ "グローバル転送ルール" を作成します。これは,待ち受けポートの定義やグローバル IP アドレスの保有有無等を定義します。"グローバル転送ルール" はリージョンを意識しません。
  • "グローバル転送ルール"の作成

    "グローバル転送ルール"の名前を「mygce-forwarding-rule」とします。今回は HTTPS(443) ポートでのみ待ち受けます。
  • $ gcloud compute forwarding-rules create mygce-forwarding-rule \
      --target-https-proxy mygce-target-proxy \
      --global-address \
      --global \
      --ports 443

上記コマンドを実行すると,付与されたグローバル IP アドレスが表示されますので,それを A レコード(!! CNAMEでない)で DNS サーバに登録すれば完成です(とりあえずの確認であれば hosts ファイルに登録すれば十分です)。

今回私は,mygce.fastriver.net というホスト名で A レコードを登録しました。そして以下の URL にブラウザからアクセスしてみます。
  • https://mygce.fastriver.net/site1/index.txt
  • https://mygce.fastriver.net/site2/index.txt
すると,前回でそれぞれの index.txt の中に記した「site1」または「site2」の文字がブラウザに表示されるはずです。セッションパーシステンスを確認したい場合は,一旦ブラウザを終了して新たな cookie でアクセスしてみるのも良いでしょう。

というわけで,これでクロスリージョンの負荷分散かつオートスケーリングな Web サーバが出来上がりました。今回の例は本当に簡易的な構成ですので,実際の運用ではもっと複雑な要件があり,複雑な設定をすると思います。その際は gcloud コマンドのヘルプやら Google が提供するドキュメント等を参考にしてください。

ではさようなら。

GCE でクロスリージョン+オートスケーリング 第三回

2017年1月17日火曜日

GCE でクロスリージョン+オートスケーリング 第一回

GCE でクロスリージョン+オートスケーリング 第一回

GCE ってすごいかも

Google Compute Engine(GCE) でグローバル IP アドレスを確保する際,大きな特徴としてリージョンを指定する・しないの選択が可能です("グローバル転送ルール" (後述) のときのみ)。リージョン指定しなくて良いってことは,例えばあるリージョンが戦争とかで壊滅状態になったときに何もしなくても同一 IP アドレスで別のリージョンで運用継続できるってこと?

だとすると,個人的にはこりゃすごいと関心してしまいます(違ってたらすみません,ご指摘ください)。オンプレだとマルチホーミングして AS 取得して BGP で... などとしていたことが,いとも簡単にコマンドやブラウザから椅子に座りながらチョイチョイで設定可能です。

ちょっと外れますが,おそらく AWS だとこのようなリージョンを超えた Elastic IP address の設定は出来ないと思われます。Multi AZ は可能ですが,disaster 対策や冗長化には Endpoints の CNAME で対処していると私は理解しています(間違ってたらごめんなさい, ご指摘いただけると助かります)。

また,この仕組みにより GCE では cross regional な負荷分散も可能にします。つまり異なるリージョンにある末端インスタンスノードにリクエストを分散できるようです。

これらについては,おそらく「今更」感バリバリと思いますが個人的には今更感動しています。そんなこんなで,仕事柄 AWS で Web システムを構築することが多い私が,そこでよくやる基本的なオートスケーリングなサーバ構成を GCE でも作ってみようか,しかもクロスリージョンで! という気になり,ちょっとやり方をメモしようとこれを書くことにしました(基本中の基本なことになっちゃいますが...)。

今回作るものの概要

こんな感じのものを作る

というわけで本当に基本的なものですが,今回は以下イメージのような基礎的な Web サーバのシステムを作ってみます。

よくある Web サーバシステムの図

よくある,DMZ に LB がいて,それが 2 本の足を持っていてその下の独立したプライベートネットワーク上に Web サーバが複数台いるというやつです。LB がその Web サーバ達にリクエストを振り分けるって感じです。

これを Google Compute Engine で表現してみます。末端ノードの Web サーバは,固定台数でなくオートスケーリングにします。GCE はインフラ的なネットワーク設計をある程度意識しなくて良いので下記のような感じです。

GCE ではこんな感じの図

必要な GCE 要素の概要

  • ネットワーク

    あまり意識せず 「default」のネットワークを使います。自動的に cross region なサブネットに切られているはずです。AWS とは根本的に考え方が違います。個人的には GCE の方が未来を感じます。

  • "負荷分散(Load Balancer)"

    GCE のロードバランサは AWS の ELB と違って,さぁロードバランサを作るぞ!って感じではなく,以下のような要素を組み立てていきます。

    • "グローバル転送ルール"

      待受の IP アドレスとポートを定義する(BIG-IP で言えば Virtual Server の部分か)。この IP アドレスは前述のリージョンを指定しないものを割り当てることができる。

    • "ターゲットプロキシ"

      その名の通りここは Reverse Proxy の役割だろう。どうもクライアントからの直接のリクエストは一旦ここで受け取ってるっぽい。SSL Termination もここでやる。その後リクエストを解釈して X-Forwarded-For 等の Proxy 用の HTTP ヘッダを追加している。

    • "URL マップ"

      URL により 振り先定義するところ(Apache とか NGINX とかで言えば、Location による振り分け)。

    • "バックエンドサービス"

      末端のインスタンスグループを取りまとめているところ。BIG-IP で言えば pool だろうか。ヘルスチェックや persistence はここでやってる。

  • "インスタンスグループ"

    インスタンスグループは,その名の通りインスタンスの集まりです。"自動スケーリング" を利用したい場合はここで定義できます。"インスタンスグループ" に含まれる各インスタンスの雛形は "インスタンステンプレート" で定義します。その中にインスタンスの "イメージ" も含まれ、これは以下の手順で作成することになります。

    1. "公開イメージ" から "ディスク" 作成
    2. 作成した "ディスク" をブートディスクとしてアタッチしてインスタンスを生成
    3. OS にログインしてお好きなようにカスタマイズ
    4. "ディスク" を消さないようにインスタンス削除
    5. 孤立したディスクから "イメージ" 作成

というわけで今回はここまでとします。次回は具体的に gcloud コマンドを使って実装していくことにします。

GCE でクロスリージョン+オートスケーリング 第一回

GCE でクロスリージョン+オートスケーリング 第二回

GCE でクロスリージョン+オートスケーリング 第二回

前回では,GCE でこんなものを作ってみようかな,ということについての概要を書きました。今回はそれを具体的に作っていきます。

構成



上図は,今回作成する構成を簡単に表したものです。"負荷分散(ロードバランサ)" で HTTPS(443)ポートでリクエストを受け付け,"ターゲットプロキシ" で SSL 終端処理を行います。その後 "URLマップ" で /site1 という URL と /site2 という URL へのリクエストを解釈して,それぞれ異なる "バックエンドサービス" に振り分けます。

"インスタンスグループ"はそれぞれの "バックエンドサービス" 内に 2 つづつ用意し,異なるリージョンに配置します。これはリージョンを跨ぐ負荷分散を実現するための準備です。

"インスタンスグループ" 内のインスタンスは "自動スケーリング" によりスケールイン/アウトを繰り返すよう設定します。この場合は "管理対象インスタンスグループ" として作成します。このため,インスタンスの雛形を定義する "イメージ" を作成し,さらにその起動設定を "インスタンステンプレート" で定義する必要があります。

では,まず "イメージ" の作成から具体的にやっていきましょう。今回は "負荷分散(ロードバランサ)" の "バックエンド" となる "インスタンスグループ" の作成まで行うこととします。

なお,以降 GCE の Web GUI コンソールは使わず,全て gcloud コマンドで行います。gcloud コマンドの操作方法についてはここでは触れません。gcloud からの認証(gcloud auth login)やプロジェクトの作成,およびデフォルトのプロジェクト設定についても既に行っていることとします。

また,GCE に作るオブジェクトの名前は全て「mygce-」というプレフィクスをつけたいと思います。

"イメージ" の作成まで

まず,インスタンスの雛形となる "イメージ" を作成します。今回は GCP が公開している CentOS 7 の "イメージ" をベースとし,その上に Apache (httpd)が稼働するようにします。また,前出の図のように機能が異なる Web サーバに URL で振り分けを行いますので,2 つの "イメージ" を作成します。今後、これらのサイトを便宜上「site1」「site2」と呼びます。

site1 の "イメージ" の作成

site1 の "イメージ" は,「"ディスク" 作成」→「インスタンス起動」→「Apache等インストール/設定」→「インスタンスを削除して "ディスク" 解放」→「"イメージ" 作成」といった手順で作成します。
  1. "公開イメージ" から "ディスク" 作成

    CentOS7 の "公開イメージ" から名前が「mygce-site1-disk」という "ディスク" を作成します。"ゾーン" は任意のものを設定しています。
  2. $ gcloud compute disks create mygce-site1-disk \
      --image-family=centos-7 \
      --image-project=centos-cloud \
      --zone asia-east1-b

  3. 作成した "ディスク" をブートディスクとしてアタッチしてインスタンスを生成

    1 で作成した "ディスク" からインスタンスを立ち上げます。この後,これにログインして好みの設定にしていきます。"ゾーン" は任意です。--metadata で「ryo」というユーザでログインする際に必要な ssh 公開鍵(~/.ssh/id_rsa.pub)を渡しています。インスタンス名を「mygce-site1-tmp-instance」としています。
  4. # Windows の人は ssh 鍵の渡し方を適当に工夫してください.
    # --metadata-from-file なんてオプションもありますよ。
    $ gcloud compute instances create mygce-site1-tmp-instance \
      --disk name=mygce-site1-disk,boot=yes \
      --metadata "ssh-keys=ryo:$(cat ~/.ssh/id_rsa.pub)" \
      --zone asia-east1-b

  5. OS にログインしてカスタマイズ

    上記 2 の実行が成功すると,作成されたインスタンスの IP アドレスが表示されます(下記では xxx.xxx.xxx.xxx で表示しています)。ssh でそれにログインします
  6. $ ssh ryo@xxx.xxx.xxx.xxx
    ログイン後,まず httpd をインストールします。また,今回は URL によりアクセスするサイトを振り分けますので,どちらのサーバにアクセスしたかブラウザからわかるようにします。Apache の DocumentRoot ディレクトリ以下に「site1」とだけ記した index.txt というファイルを配置します。
    [ryo@mygce-site1-tmp-instance]$ sudo yum install httpd -y
    [ryo@mygce-site1-tmp-instance]$ sudo mkdir /var/www/html/site1
    [ryo@mygce-site1-tmp-instance]$ echo "site1" | sudo tee /var/www/html/site1/index.txt
    [ryo@mygce-site1-tmp-instance]$ sudo systemctl enable httpd
    [ryo@mygce-site1-tmp-instance]$ exit

  7. "ディスク" を消さないようにインスタンス削除

    上記 2 で作成したインスタンス「mygce-site1-tmp-instance」を削除します。これは,インスタンスに関連付けられたディスクからはイメージの作成ができないためです。なお下記コマンド例では -q で削除の確認を行わないようにしていますのでご注意ください。
  8. $ gcloud compute instances delete mygce-site1-tmp-instance --zone asia-east1-b -q

  9. "ディスク" から "イメージ" 作成

    下記コマンドで,上記 1, 3 で作成/編集した "ディスク"「mygce-site1-disk」から「mygce-site1-image」という名前の "イメージ" を作成します。この際,--family というオプションが必要になりますが,これは任意の文字列を指定します。ここでは「mygce-site1-image-family」としました。
  10. $ gcloud compute images create mygce-site1-image \
      --source-disk-zone=asia-east1-b \
      --source-disk mygce-site1-disk \
      --family mygce-site1-image-family


site2 の "イメージ" の作成

site2 の "イメージ" は「site1 の "イメージ" から "ディスク" 作成」→「インスタンス起動」→「/var/www/html/index.txt の内容を変更」→「インスタンス削除」→「"イメージ" 作成」という手順で行います。
  1. site1 の "イメージ" から "ディスク" 作成

    これまでに作成した 1 つ目の "イメージ" を元に下記コマンドで "ディスク" 「mygce-site2-disk」を作成します。この際,--image-family オプションに上記 5 で指定した「mygce-site1-image-family」与えます。
  2. $ gcloud compute disks create mygce-site2-disk \
      --image-family=mygce-site1-image-family \
      --zone=asia-east1-b

  3. 作成した "ディスク" をブートディスクとしてアタッチしてインスタンスを生成

    上記 1 で作成した "ディスク"「mygce-site2-disk」からインスタンスを生成します。ssh 鍵は 1 つ目のインスタンスを作成したときと同じように指定します。インスタンス名は「mygce-site2-tmp-instance」としました。
  4. $ gcloud compute instances create mygce-site2-tmp-instance \
      --disk name=mygce-site2-disk,boot=yes \
      --metadata "ssh-keys=ryo:$(cat ~/.ssh/id_rsa.pub)" \
      --zone asia-east1-b

  5. OS にログインしてカスタマイズ

    上記 2 の実行が成功すると,作成されたインスタンスの IP アドレスが表示されます(下記では xxx.xxx.xxx.xxx で表示しています)。ssh でそれにログインします。
  6. $ ssh ryo@xxx.xxx.xxx.xxx
    ログイン後,Apache の DocumentRoot ディレクトリ下にある index.txt の内容を「site2」に変更します。
    [ryo@mygce-site2-tmp-instance]$ sudo mkdir /var/www/html/site2
    [ryo@mygce-site2-tmp-instance]$ echo "site2"  | sudo tee /var/www/html/site2/index.txt
    [ryo@mygce-site2-tmp-instance]$ sudo systemctl enable httpd
    [ryo@mygce-site2-tmp-instance]$ exit

  7. "ディスク" を消さないようにインスタンス削除

    上記 2 で作成したインスタンス「mygce-site2-tmp-instance」を削除します。これは,インスタンスに関連付けられた "ディスク" からは "イメージ" の作成ができないためです。なお下記コマンド例では -q で削除の確認を行わないようにしていますのでご注意ください。
  8. $ gcloud compute instances delete mygce-site2-tmp-instance --zone asia-east1-b -q

  9. ディスクからイメージ作成

    下記コマンドで,上記 1, 3 で作成/編集した "ディスク"「mygce-site2-disk」から「mygce-site2-image」という名前の "イメージ" を作成します。この際,--family というオプションが必要になりますが,これは任意の文字列を指定します。ここでは「mygce-site2-image-family」としました。
  10. $ gcloud compute images create mygce-site2-image \
      --source-disk-zone=asia-east1-b \
      --source-disk mygce-site2-disk \
      --family mygce-site2-image-family

"インスタンスグループ" の作成まで

"負荷分散(ロードバランサ)" の "バックエンド" となる "インスタンスグループ" を作成します。今回は,米国と日本の 2 つのリージョンに跨る負荷分散を行いますので,"インスタンスグループ" を site1, site2 のそれぞれで 2 つのリージョンに作成します。

site1 の "インスタンスグループ" の作成

  1. site1 の "インスタンステンプレート" の作成

    "インスタンスグループ" を作成する前に "インスタンステンプレート" 「mygce-site1-template」を作成します。この際,マシンタイプを小さな g1-small で指定します。"イメージ" の源泉は上記で作成した「mygce-site1-image」です。ログインできるように ssh の公開鍵も登録します。
  2. $ gcloud compute instance-templates create mygce-site1-template \
      --machine-type g1-small \
      --image-family mygce-site1-image-family \
      --metadata "ssh-keys=ryo:$(cat ~/.ssh/id_rsa.pub)"

  3. 日本のリージョンに site1 の "インスタンスグループ" を作成

    まず日本リージョンの "ゾーン"「asia-east1-b」に「mygce-site1-ig-asia」という "インスタンスグループ" を作成します。"インスタンステンプレート" は上記 1 で作成した「mygce-site1-template」を指定します。
  4. $ gcloud compute instance-groups managed create mygce-site1-ig-asia \
      --size 1 \
      --template mygce-site1-template \
      --zone asia-east1-b

  5. "オートスケーリング" の設定

    "インスタンスグループ"「mygce-site1-ig-asia」に "自動スケーリング" を設定します。ここでは,最小インスタンス数 1, 最大インスタンス数 3, スケールアウトの CPU 閾値を 80% とします。
  6. $ gcloud compute instance-groups managed set-autoscaling mygce-site1-ig-asia \
      --max-num-replicas 3 \
      --min-num-replicas 1 \
      --target-cpu-utilization 0.8 \
      --scale-based-on-cpu \
      --zone asia-east1-b

  7. 米国のリージョンに site1 の "インスタンスグループ" を作成

    米国リージョンの "ゾーン"「us-east1-b」に「mygce-site1-ig-us」という "インスタンスグループ" を作成します。"インスタンステンプレート" は上記 1 で作成した「mygce-site1-template」を指定します。
  8. $ gcloud compute instance-groups managed create mygce-site1-ig-us \
      --size 1 \
      --template mygce-site1-template \
      --zone us-east1-b

  9. "オートスケーリング" の設定

    "インスタンスグループ"「mygce-site1-ig-us」に "自動スケーリング" を設定します。ここでは,最小インスタンス数 1, 最大インスタンス数 3, スケールアウトの CPU 閾値を 80% とします。
  10. $ gcloud compute instance-groups managed set-autoscaling mygce-site1-ig-us \
      --max-num-replicas 3 \
      --min-num-replicas 1 \
      --target-cpu-utilization 0.8 \
      --scale-based-on-cpu \
      --zone us-east1-b

site2 の "インスタンスグループ" の作成

site2 のインスタンスグループの作成は site1 とほぼ同じですが,以下一応コマンドを全て記しておきます。
  1. site2 の "インスタンステンプレート" の作成

    "インスタンスグループ" を作成する前に "インスタンステンプレート" 「mygce-site2-template」を作成します。この際,マシンタイプを小さな g1-small で指定します。"イメージ" の源泉は上記で作成した「mygce-site2-image-family」です。ログインできるように ssh の公開鍵も登録します。
  2. $ gcloud compute instance-templates create mygce-site2-template \
      --machine-type g1-small \
      --image-family mygce-site2-image-family \
      --metadata "ssh-keys=ryo:$(cat ~/.ssh/id_rsa.pub)"

  3. 日本のリージョンに site2 の "インスタンスグループ" を作成

    まず日本リージョンの "ゾーン"「asia-east1-b」に「mygce-site2-ig-asia」という "インスタンスグループ" を作成します。"インスタンステンプレート" は上記 1 で作成した「mygce-site2-template」を指定します。
  4. $ gcloud compute instance-groups managed create mygce-site2-ig-asia \
      --size 1 \
      --template mygce-site2-template \
      --zone asia-east1-b

  5. "オートスケーリング" の設定

    "インスタンスグループ"「mygce-site2-ig-asia」に "自動スケーリング" を設定します。ここでは,最小インスタンス数 1, 最大インスタンス数 3, スケールアウトの CPU 閾値を 80% とします。
  6. $ gcloud compute instance-groups managed set-autoscaling mygce-site2-ig-asia \
      --max-num-replicas 3 \
      --min-num-replicas 1 \
      --target-cpu-utilization 0.8 \
      --scale-based-on-cpu \
      --zone asia-east1-b

  7. 米国のリージョンに site2 の "インスタンスグループ" を作成

    米国リージョンの "ゾーン"「us-east1-b」に「mygce-site2-ig-us」という "インスタンスグループ" を作成します。"インスタンステンプレート" は上記 1 で作成した「mygce-site2-template」を指定します。
  8. $ gcloud compute instance-groups managed create mygce-site2-ig-us \
      --size 1 \
      --template mygce-site2-template \
      --zone us-east1-b

  9. "オートスケーリング" の設定

    "インスタンスグループ"「mygce-site2-ig-us」に "自動スケーリング" を設定します。ここでは,最小インスタンス数 1, 最大インスタンス数 3, スケールアウトの CPU 閾値を 80% とします。
    $ gcloud compute instance-groups managed set-autoscaling mygce-site2-ig-us \
      --max-num-replicas 3 \
      --min-num-replicas 1 \
      --target-cpu-utilization 0.8 \
      --scale-based-on-cpu \
      --zone us-east1-b

これでリージョンを跨ぐ負荷分散を考慮した 2 つのサイトの "インスタンスグループ" を作成することができました。次回はこの続きで,"負荷分散(ロードバランサ)" の部分を作成していきます。

GCE でクロスリージョン+オートスケーリング 第二回

2017年1月9日月曜日

dnf group list で隠れグループ表示

Fedora の dnf で group list しても表示されないグループがある。隠れグループなの?

dnf group list -v hidden 

これで表示可能。

2017年1月4日水曜日

grub2 ブートオーダの Fedora 流変更メモ

以下私の環境の場合

#メニューエントリの取得 (コマンド無いんやね...)
egrep ^menuentry /etc/grub2-efi.cfg

#ブートデフォルトの設定 (/etc/default/grub に GRUB_DEFAULT=saved確認)
grub2-set-default 'Hoge Hoge Fuga Fuga'

#確認
grub2-editenv list