Magento Advent Calender 2016のネタを探していたところGoogle Cloud Platformのトライアルが60日間$300まで無料が目に入ったのと11月から東京リージョンが正式運用されたことが気になっていたのでこれ幸いと構築してみました
ゴール
インターネット - Load Balancing(負荷分散) - [Magento2 - Redis] - Cloud SQL
VM インスタンスの作成
ベースとなるVMインスタンスを作成
BitnamiのMagento2をCompute Engine上で起動してベースとなるインスタンスを作成します。
構成(2016/12/15時点・抜粋)
- Debian (8)
- Apache (2.4.23)
- Magento (2.1.2)
- Memcached (1.4.31)
- MySQL (5.7.15)
- PHP (7.0.11)
- Varnish (4.1.0)
Zoneはasia-northeast1-a,b,cのいずれか(東京リージョン)を選んでください。Magento2はメモリを結構消費するのでn1-standard-2を選択しています。Cloud SQLを使うのでディスクI/Oは気にしないということでDisk typeはStandard Persistent Diskを選んでいます。External IPはEphemeral(静的IPじゃないやつ)を割り当てます。
起動してわかったのですが、Varnishが80番ポートで待ち受けていました。apacheは81番と443番ですね。ロードバランサでSSL Terminationして80番に渡せられれば良いですね。
デプロイ直後の画面です。管理画面のパスワードも自動生成されているのでこのままでもSite Addressからアクセス可能です。Magento2に最適化された構成になっているためストレスなく動作していますが、少しづつ高速化していきます。
作成したVMインスタンスの設定を確認すると、デフォルトのアクセス権が適用されているためCloud API アクセス範囲がほとんど無効化されていました。今回の手順的にはCloud SQLとストレージを有効化する必要があります。Cloud SQL Proxyのリファレンスにも書いてありますがアクセス範囲を変更できるのはインスタンス作成時なので、完全に無駄な作業ですが作成したVMインスタンスをベースに再作成します。
VMインスタンスのコピー
VMインスタンスを停止します。
続いてメニューからスナップショットを選んで「スナップショットを作成」します。
ソースディスクに先程作成したVMインスタンスを選んでください。
スナップショットが取得できたら、VMインスタンスを新しく作成します。
ブートディスクを先程作成したスナップショットに変更してください。IDとAPIへのアクセスについて「すべての Cloud API に完全アクセス権を許可」を選択してください。ファイアウォールにはHTTPとHTTPSのトラフィックを許可しておいてください。
これでようやくCloud APIが使えるMagento2インスタンスが手に入りました。
Redis
Redisサーバの作成
BitnamiのRedisをCompute Engine上で起動してRedisサーバを作成します。
RedisなのでCPUは1コアで良いと思います。あとは6379番ポートが空いていることを確認してください。
RedisとMagento2インスタンスを連携
Redisサーバのファイアウォールを設定
Magento2インスタンスの内部IPを調べます。
上のスクリーンショットだと内部IPに10.146.0.7が割り当てられています。そのままファイアウォールの設定に移るためネットワークのdefaultをクリックします。ファイアウォールルール一覧が表示されるので、6379番ポートの設定(Redis用)を見つけて編集します。今回はRedisインスタンス名-tcp-6379
という名前で生成されていました。
Magento2インスタンスの内部IPのみを指定するためソースIPの範囲をMagento2の内部IP/32
に変更して保存してください(スクリーンショット参考)。Magento2インスタンスを追加する度に範囲指定を追加する必要があります。
Magento2の設定を変更
SSHでMagento2インスタンスに接続します。
VMインスタンスの詳細画面からSSHボタンをクリックするとブラウザでコンソールが起動します。
/opt/bitnami/apps/magento/htdocs/
がMagento2のドキュメントルートなので、設定ファイルenv.php
を開いてsession
の設定を変更、cache
の設定を追記します。
$ sudo vim /opt/bitnami/apps/magento/htdocs/app/etc/env.php
// ここから変更.
// 'session' =>
// array (
// 'save' => 'files',
// ),
'session' =>
array (
'save' => 'redis',
'redis' =>
array (
'host' => '10.146.0.8',
'port' => '6379',
'password' => 'v1TJnCNf',
'timeout' => '2.5',
'persistent_identifier' => '',
'database' => '0',
'compression_threshold' => '2048',
'compression_library' => 'gzip',
'log_level' => '1',
'max_concurrency' => '6',
'break_after_frontend' => '5',
'break_after_adminhtml' => '30',
'first_lifetime' => '600',
'bot_first_lifetime' => '60',
'bot_lifetime' => '7200',
'disable_locking' => '0',
'min_lifetime' => '60',
'max_lifetime' => '2592000'
)
),
// ここまで変更.
// (省略)
// ここから追記.
'cache' =>
array(
'frontend' =>
array(
'default' =>
array(
'backend' => 'Cm_Cache_Backend_Redis',
'backend_options' =>
array(
'server' => '10.146.0.8',
'password' => 'v1TJnCNf',
'port' => '6379'
),
),
'page_cache' =>
array(
'backend' => 'Cm_Cache_Backend_Redis',
'backend_options' =>
array(
'server' => '10.146.0.8',
'port' => '6379',
'password' => 'v1TJnCNf',
'database' => '1',
'compress_data' => '0'
)
)
)
),
// ここまで追記.
);
'server(host)'と'password'はそれぞれ3箇所ありますが、Redisサーバの内部IPとパスワードを指定してください。Redisサーバ構築時に自動生成されたパスワードは、カスタムメタデータのbitnami-base-passwordで確認できます。
設定できたら動作確認のためRedisサーバにSSHで接続してモニタします。
$ redis-cli -a v1TJnCNf monitor
モニタしている状態でMagento2にブラウザからアクセスするとRedisが動作しているのが確認できると思います。
参考: Redis for session storage Redis for page caching
Cloud SQL
Google Cloud Storage
MySQLダンプをCloud SQLに転送するためにGoogle Cloud Storageを利用します。
Magento2インスタンスからgsutilでGoogle Cloud Storageにアクセスしてバケットを作成します。
$ gsutil mb -l ASIA-NORTHEAST1 gs://magento2-sql-backup-bucket
バケット名はグローバルに一意なので409エラーが返却されたときは別の名前にしてください。
成功するとオブジェクトのないバケットが作成されます。
ダンプファイルの作成・転送
Magento2が利用しているMySQLデータベース・ユーザ・パスワードを設定ファイル/opt/bitnami/apps/magento/htdocs/app/etc/env.php
を開いて確認します。
$ sudo vim /opt/bitnami/apps/magento/htdocs/app/etc/env.php
公式ドキュメント:mysqldump ファイルの作成を参考にダンプファイルを作成します。
$ mysqldump --databases bitnami_magento -h localhost -u bn_magento -p --hex-blob --skip-triggers --default-character-set=utf8 > magento_backup
.sql
作成したダンプファイルを先程作成したGoogle Cloud Storageのバケットに転送します。
$ gsutil cp ./magento_backup.sql gs://magento2-sql-backup-bucket
Google Cloud Storageにアクセスして転送されたことを確認してください。
Cloud SQLの起動
Google Cloud SQLにアクセスします。第2世代はMySQLデータベースです。サポートバージョンは5.6,5.7、エンジンはInnoDBのみなので、Magento2には必要十分だと思います。
ロケーションはMagento2インスタンスと同じにしておくと良いでしょう。通常時やHAな構成にした時の性能など未検証ですが、定期バックアップが取れるだけでも幸せですね。
作成されたインスタンスにはIPv4アドレスが割り当てられています。内部IPでアクセスできないの?ってなったのですが、ネットの声を拾ってみるとみんな思うところは同じみたいですね。
インスタンス接続名はMagento2の設定に使用するので覚えておいてください。
MySQLダンプのインポート
インスタンスの詳細から「インポート」をクリックして、Cloud Storageファイルを選択します。
初期データのみなので、インポートは1分もかからずに終わります。
MySQLユーザの作成
Magento2用のユーザを作成します。アクセス制御/ユーザー/ユーザーアカウントを作成をクリックするとダイアログが開くのでユーザー名・パスワードを入力して作成してください。既存の設定から変えない場合は、ダンプファイル作成時に確認したMagento2の設定ファイルenv.php
のユーザー名とパスワードを指定します。ホスト名は「すべてのホストを許可する」を選択してください。ついでにrootのパスワードも変更しておくと良いと思います。
Cloud SQL接続用のソケットを作成
Cloud SQL Proxyを使用してMySQLクライアントに接続するを参考にCloud SQL接続用のソケットを作成していきます。
APIを利用するためCloud SQL Administration API を有効にします。認証情報の設定は不要です。
続いてMagento2インスタンスにSSHで接続します。ほぼチュートリアルからのコピペですが、下記コマンドを順に実行してCloud SQL Proxyを開始します。
# 1.プロキシをダウンロードします。
$ wget https://dl.google.com/cloudsql/cloud_sql_proxy.linux.amd64
# 2.プロキシの名前を変更して標準のファイル名を使用します。
$ mv cloud_sql_proxy.linux.amd64 cloud_sql_proxy
# 3.プロキシを実行できるようにします。
$ chmod +x cloud_sql_proxy
# 4.プロキシ ソケットを格納するディレクトリを作成します。
$ sudo mkdir /cloudsql; sudo chmod 777 /cloudsql
# 5.Cloud SDK認証と自動インスタンス検出を使用してプロキシを開始します。
$ sudo nohup ./cloud_sql_proxy -dir=/cloudsql &
Magento2の設定を変更
Cloud SQLにプロキシを利用して接続するには下記のようなコマンドを実行します。
$ mysql -u root -p -S /cloudsql/インスタンス接続名
そのためMagento2の設定ファイルenv.php
も'db'の'host'をプロキシを利用するように変更します。
$ sudo vim ./apps/magento/htdocs/app/etc/env.php
'db' =>
array (
'table_prefix' => '',
'connection' =>
array (
'default' =>
array (
// (変更前) 'host' => '/opt/bitnami/mysql/tmp/mysql.sock',
'host' => '/cloudsql/xxxxxx:asia-northeast1:magento2-cloud-sql',
'dbname' => 'bitnami_magento',
'username' => 'bn_magento',
'password' => '62...(省略)
以上でMagento2インスタンス上のMySQLサーバからCloud SQLに接続先が変更されました。
ロードバランサ(負荷分散)
事前準備
URLの変更
Magento2のURLを変更します。CertbotなどでSSL化済みの場合はこの作業は不要です。管理画面を開いて変更することもできますが、今回はこのままコンソールで作業を続けます。
# ドキュメントルートに移動
$ cd /opt/bitnami/apps/magento/htdocs
# ベースURLを変更
$ sudo php bin/magento setup:store-config:set --base-url="http://www.example.co.jp/"
# SSL接続URLを変更
$ sudo php bin/magento setup:store-config:set --base-url-secure="https://www.example.co.jp/"
確認のためCloud SQLにMySQLクライアントで接続して、設定テーブルcore_config_data
が書き換えられたことを確認します。
$ mysql -u bn_magento -p -D bitnami_magento -S /cloudsql/xxxxxx:asia-northeast1:magento2-cloud-sql
mysql> select * from core_config_data;
証明書の取得
SSL化するためのドメインとSSLサーバ証明書、中間CA証明書、秘密鍵の3点セットを手に入れておいてください。作成したMagento2インスタンス上でCertbotを利用して証明書を取得する場合は、ApacheやVarnishなどを停止してから--standalone
でCertbotを起動してください。
$ sudo /opt/bitnami/ctlscript.sh stop
$ sudo certbot certonly --standalone
$ sudo /opt/bitnami/ctlscript.sh start
ヘルスチェック対策
Magento2のURL設定を変更してドメイン名でHTTPアクセスできるようにすると、IPアドレスでアクセスするとドメイン名にリダイレクトされてしまうので、ヘルスチェックの結果がエラーになってしまいます。そこでヘルスチェック用のファイルを用意して該当ファイルにアクセスしたときだけは200番が返却されるようにしていきます。
- http://104.198.124.255 -> http://www.example.co.jp/ (302 Found)
- http://104.198.124.255/healthcheck.html -> http://104.198.124.255/healthcheck.html (200 OK)
Magento2インスタンスにSSHで接続します。/opt/bitnami/apps/magento/htdocs/
がMagento2のドキュメントルートなので直下にhealthcheck.html
を作成します。
$ sudo vim /opt/bitnami/apps/magento/htdocs/healthcheck.html
中身はなんでも良いので適当に編集して保存してください。
<!doctype html><html><body><h1>instance-1</h1></body></html>
参考: Redirect HTTP to HTTPS in Wordpress running behind a Google HTTP Load Balancer
HTTPS Termination時のリダイレクトループ対策
ロードバランサのバックエンドにMagento2インスタンスを配置するとSSLアクセスしたときにリダイレクトループが発生します。そのためX-Forwarded-Proto
がhttps
だったときにHTTPS=on
にします。通常.htaccess
を書き換えるわけですがファイルを開くと変更しても反映されない的なことが書いてあったのでhttpd.conf
を変えてしまいます。
$ sudo vim /opt/bitnami/apache2/conf/httpd.conf
...
# 追記
SetEnvIf X-Forwarded-Proto https HTTPS=on
Include "/opt/bitnami/apache2/conf/ssi.conf"
...
Includeで他のコンフィグファイルを読み込む前に追記しています。
参考: Magento SSL Offloading with Amazon ELB
バックエンドの準備
準備が終わったので、ロードバランサのバックエンドを構築していきます。
Compute Engineのインスタンス グループを選択して、インスタンス グループを作成しましょう。
ロケーションにシングルゾーンを選択して、既存のインスタンスとしてMagento2インスタンスを選びます。
続いてヘルスチェックの作成です。さくさく行きます。
リクエストパスに先程作成したhealthcheck.html
を指定します。
ロードバランサ(負荷分散)
ネットワーキングから負荷分散を選択して「ロードバランサを作成」します。
HTTP(S)負荷分散の「設定を開始」ボタンをクリックするとチュートリアル形式で設定が開始されます。
バックエンドサービスを作成します。
インスタンスグループとヘルスチェックに先程作成したものを指定します。
ついでにCloud CDNにもチェックを入れておくと(料金は発生しますが)さらなる高速化が望めて嬉しいかもしれません。
ホストとパスのルールはバックエンドが1つしかないのでそのままで良くて、フロントエンドを設定していきます。IPアドレスの作成を選んで静的IPを申請します。トライアルの枠内だと貴重な1個をここで使います。Magento2は管理画面からHSTSの設定などができるのですが、いったんHTTPとHTTPSの両方のリクエストを許可しています。
新しい証明書の作成では、事前に準備しておいたSSL証明書と中間証明書と秘密鍵を順に貼り付けてorアップロードしていきます。
全ての設定が終わって「作成」をクリックするとロードバランサが作成されます。
DNSの設定を変更
最後にロードバランサで設定したIPアドレスをDNSのAレコードに設定してあげればOKです。
HTTP2でアクセスできることが確認できました!
あとがき
Google Cloud Platformに初めて触れたので結構大変でした。特にCloud APIのアクセス範囲を有効化しておかないとAPIが利用できなかったり、ヘルスチェック用にIPアドレスでアクセスしたときに200番を返却するURLを準備する必要があったりと、Magento2と関係ないところで苦労した感じです。
一方で設定だけでRedisを利用できるようになったことには正直驚いてしまいました。しかもRedisの設定をした時が一番高速化の恩恵を感じたので、運用するときは軒並み設定したいところですね。いたるところでキャッシュを利用しているので不具合発生時の切り分けが大変そうなのはトレードオフということで。