2018/02/15(木)Google Compute Engine のVMからCloud SQLにつないでみる。

はてブ数 2018/02/15 04:01 Web開発::GoogleCloudPlatformつーさ
うーん、勉強しないといけないことがたくさんありゅ……

今回はCygwinじゃなくて、
GCP上のGCEのVMにCentOS7を入れて、
CloudSQLに作ったPostgreSQLにつないでみます。


Cloud SQLインスタンスの準備。

特に注意点はないかな?
PostgreSQL サーバのバージョンは、2018.02.12時点では 9.6.1 だった。

CloudSQLは、Compute Engine のVMと同じような料金が掛かるらしい。
料金表のHAはHigh Availabilityの略かな。
高可用性オプションは隣のゾーンにVM待機させておく感じっぽいので倍。
ただし、PostgreSQLの場合は、
ゾーンごとネットワークがダウンした場合に限って切り替わってくれるだけで、
単にサーバが落ちただけでは切り替わってはくれない、という理解。微妙。

Compute Engine のインスタンスの準備。

VMインスタンス作る。

マシンタイプはとりあえずmicroで作る。
OSは、なんとなくCentOS 7 にしてみる。
※ インスタンス作成時に CloudSQL APIを有効にしておくと後でちょっと楽。

ssh してみる。

sshキーは、ssh-keygen で普通に作ってから、
プロジェクト全体で利用できる公開鍵として登録しておけば、sshできるようになる。
https://cloud.google.com/compute/docs/instances/adding-removing-ssh-keys#project-wide

ただ、ログイン用のユーザ名は鍵のコメントからとってくるっぽい。
Webのダッシュボードと同じユーザ名にするにはコメント欄を書き換えておく必要がある。
変なコメントにしてるとログインできないかも。

外部IPアドレスに向けて公開鍵でsshすればいい。
$ ssh -i ~/.ssh/id_rsa_gcp.pri 203.0.113.111
[tu3@login ~]$
つながった。

とりあえず初回ログインしたら、
$ sudo yum update
しろって聞いたことある。
やっておく。

VMにPostgreSQLのクライアントを入れる。

ここで、yum install postgresql すると、
インストールされるバージョンは 9.2。

CentOSにPostgreSQL9.6をyumでインストール
https://qiita.com/purini-to/items/702565733a03c202d98e

に倣って、9.6を入れようと思う。

とりあえず、アーキテクチャとディストリのバージョン調べる。
$ uname -a
Linux login 3.10.0-693.17.1.el7.x86_64 #1 SMP Thu Jan 25 20:13:58 UTC 2018 x86_64 x86_64 x86_64 GNU/Linux

$ cat /etc/redhat-release
CentOS Linux release 7.4.1708 (Core)
7.4ってことは、この辺から探せばいいのかしら。
https://yum.postgresql.org/9.6/redhat/rhel-7.4-x86_64/

とりあえず、localinstallしようとしたら、wgetがないと言われたので、wget先に入れておく。
$ sudo yum install -y wget

$ sudo yum localinstall https://yum.postgresql.org/9.6/redhat/rhel-7.4-x86_64/pgdg-centos96-9.6-3.noarch.rpm
...
$ sudo yum install postgresql96
...
$ psql --version
psql (PostgreSQL) 9.6.7
入った気がする。

つないでみる。

Compute Engineからの繋ぎ方
https://cloud.google.com/sql/docs/postgres/connect-compute-engine

基本はこの通りやれば繋がった。

ドキュメントにも書いてあるけど接続経路は、
tcp -> localhost:5432 [CLOUD SQL PROXY] -> cloud sql
な感じで、cloud_sql_proxy をダウンロードしてきて、起動しておく必要があるっぽい。
$ wget https://dl.google.com/cloudsql/cloud_sql_proxy.linux.amd64 -O cloud_sql_proxy
$ ./cloud_sql_proxy -instances=nantoka-kantoka-123456:asia-northeast1:testdb=tcp:5432 &
$ psql -h localhost -U postgres postgres
Password for user postgres: 
とりまいけてそうなので、前記事に倣って、ユーザ作ったりDB作ったりしておく。

しかし、これってProxyが死亡するとDB接続も死亡するってことだよな。
普通にSSLクライアント認証鍵を作ってSSL接続した方がいいのかな。
しかし、開発環境でもそれ準備するのはめんどくさいな……。

とりあえず、デーモン化してみるか

と思ってプロセスをデーモンにする方法を調べてみる。

お世話になります。
http://cameong.hatenablog.com/entry/2016/10/18/121400
https://qiita.com/kumanoryo/items/ef3fbec70b4138ffe1c2

/usr/local/bin と /usr/local/etc にでもおく。
$ sudo mv ./cloud_sql_proxy /usr/local/bin
/etc/systemd/system/cloudsqlproxy.service つくる
$ sudo vim /etc/systemd/system/cloudsqlproxy.service
[Unit]
Description = CloudSQL Proxy
After = network.target

[Service]
Type = simple
EnvironmentFile = /usr/local/etc/cloud_sql_proxy.conf
ExecStart = /usr/local/bin/cloud_sql_proxy ${INSTANCE_ID}
ExecStop = /bin/kill ${MAINPID}
ExecReload = /bin/kill -HUP ${MAINPID}
Restart = always

[Install]
WantedBy = multi-user.target
EnvironmentFile つくる
$ sudo vim /usr/local/etc/cloud_sql_proxy.conf
INSTANCE_ID="-instances=nantoka-kantoka-123456:asia-northeast1:testdb=tcp:5432"

最大ファイルディスクリプタ数を設定する。
1コネクションでいくつfdが消費されるのかわからんが、、多めにしておく。
ん、でも ulmit -f したら unlimited って言われる。やらなくてもいいのかもな。
$ sudo mkdir /etc/systemd/system/cloudsqlproxy.service.d
$ sudo vim   /etc/systemd/system/cloudsqlproxy.service.d/limits.conf
[Service]
LimitNOFILE=65536
設定済んだはずなので、デーモンとして起動してみる。
リロード
sudo systemctl daemon-reload
サービスとして見えているか?
$ sudo systemctl list-unit-files --type=service | grep cloud
手動で起動してみる。
$ sudo systemctl start cloudsqlproxy.service
$ sudo systemctl status cloudsqlproxy.service
Active: active (running) になっていればよい。

OS起動時に自動的に起動するようにする。
$ sudo systemctl enable cloudsqlproxy.service
$ sudo systemctl list-unit-files --type=service | grep cloudsqlproxy
enable になっていればよい。

pdoからつないでみる。

その前にhttpdとphpをインストールしなくちゃ。

httpd 入れる

$ sudo yum install httpd

php 7.2 を入れる。

sudo yum install すると、php 5.4 が来るので、新しいPHPの入れ方を調べてみる。
Remi's RPM repository の中の人が、新しめのPHPをビルドしてくれているらしいのでありがたく使わせていただく。
$ sudo yum install http://rpms.famillecollet.com/enterprise/remi-release-7.rpm
$ sudo yum install --enablerepo=remi,remi-php72 php{,-pdo,-mbstring,-xml,-pear,-pgsql}
remi-safe から php72 を入れると httpd用のモジュールが入らないみたい。
remi-php72 リポジトリから php を入れると、libphp7.so 来る。
php5がいない場合に限りLoadModuleされる的なconfも一緒にインストールされるので、
他のphp入れてなければいきなり php 7.2 が使える状態になっているはず、っぽい。

httpd.confをいじる

Options から Indexes とって、
AllowOverride をAllにしておく。

httpd起動する。

$ sudo systemctl enable httpd
PDOでDBにつないで、適当にSELECTしてくるだけの test.php をおいてアクセスしてみる。
<?php
$pdo = new PDO('pgsql:host=localhost;port=5432;dbname=testapp', 'testapp', 'testapp');
echo $pdo->query('SELECT now()')->fetchColumn();
500 Internal Server Error
ふご……。

error_log 見ると、
Uncaught PDOException: SQLSTATE[08006] [7] could not connect to server: Permission denied とか書いてある。
psqlコマンドからなら普通に繋がるのに……うーん、これは、、きいたことあるぞ、SELinux的な何かじゃね……?

SELinux

SELinuxって言葉は聞いたことあるけど、レベルの知識しかもってないので調べてみます。

https://blog.fenrir-inc.com/jp/2016/09/selinux.html
わかりやすい。

SELinux は、ファイルパーミッションの他に、付随的なアクセス権チェックをしてるもの。
コンテキストによって、操作が許可されたり許可されなかったりする。
Windowsの「特権」みたいなもんか?
$ getenforce
Enforcing
Encorcingということは、SELinuxは有効になっている状態なので、
一時的に無効にして現象が解決するかどうかを見てみると切り分けられる。
$ sudo setenforce 0
してブラウザでF5するとDBに接続できた。のを確認して、とりあえず、戻しておく。
$ sudo setenforce 1
Windowsでいうところのグループポリシーの構成テンプレート的なノリで、
あらかじめいくつかのルールは定義されているらしい。
目当てのルールが定義済みであればそれの有効・無効の切り替えだけで済む。

その一覧を見たり設定したりするには、setools-console パッケージのコマンドを使うっと。
$ sudo yum install setools-console
httpdに関係ありそうな設定を眺めていたところ、それっぽいものを発見したので、有効にしてみる。
$ getsebool -a | grep httpd
...
httpd_can_network_connect_db --> off
...
これかなー?
$ sudo setsebool httpd_can_network_connect_db on
再度ブラウザでhttpアクセスしてみると……無事SELECTできた。

なるほどー。

うーん、勉強しないといけないことがたくさんありゅ……(本日2回目)

次回予告:

ソースコードのデプロイは、 Google Cloud Source Repositories を使ってみたいと思います。
その前に、git と composer を入れておこう。

git

yum install git だと、1.8 とかが落ちてくるので、
yum install gcc して 2.16.1をソースコードからビルドして /usr/local に入れました。

composer

yum install unzip が必要だったので入れました。
sudo yum install unzip
curl -sS https://getcomposer.org/installer | sudo php -- --install-dir=/usr/local/bin --filename=composer
実作業より日記書く方が時間掛かってる気がするけど、
書いておかないとたぶん明日には忘れているからなぁ……

きょうはここまで。