タグ別アーカイブ: Linux

WSL (Windows Susystem for Linux) を本格的に開発で使い始めた話

とある理由から WSL (Windows Susystem for Linux) を本格的に開発で使い始めました。その環境や手順、所感など。

前提: これまでの開発環境

  • PHP (Windows版)、メインで使うバージョンだけパスを通し、それ以外のバージョンは手打ちという方法で簡単に複数バージョン共存できます。WebサーバーもPHPのビルトインサーバを使います。
  • Composer(Windows版)、こちらもWindows版が有りあります。
  • MySQL (Windows版)、MySQL / MariaDB を使っている環境の開発用。唯一Linux向けと明確に異なる点としてDB名やテーブル名の大文字小文字を区別しませんが、小文字しか使わないので特に問題になりません。
  • PostgreSQL(Windows版)、PostgreSQLを使っている環境の開発用。特に何も困らず動きます。
  • Node.js、Windows版を利用。Node.js向けのアプリを書くのではなく各種ツールを利用するために導入。npmやwebpackなど特に問題なく動きます。
  • Redis(Windows版)、Windows向けのRedisは若干バージョンが古いものしか見つかりませんがまぁ普通に動きます。
  • Git for Windows、どちらかというとmingwを利用するための導入。実際のGitクライアントとしてはSource TreeのWindows版を利用しています。

前提: これまでのノウハウなど

Windows環境にちゃんと動くComposerを導入する

Windows環境のComposerを複数PHPバージョンで使い分ける

WindowsのコマンドプロンプトからOS標準のsshやtarやcurlコマンドを使う

上記を雑にまとめるとPHPの複数バージョン共存はWindowsでも簡単だし、ごく一部でLinux環境に依存しているComposerパッケージもGit Bashから実行すれば問題無いという話です。

発生した課題

この環境で長らく問題が無かったのですが、Symfony 4 + Flex の環境で開発するにあたって、/bin/console からのコマンドがコマンドプロンプトからは上手く動作しません。これは consoleがWin32なバイナリではなくshebang でPHPを実行しているからなので、ちょっと工夫すれば動くかと思われるのですが、せっかくLinuxに依存する物の実行環境としてgit bashを用意しているのでそれを使ってみます。

実際git bashで問題なく動くのですが、git bash(の利用しているmingw)の限界としてCtrl + Cでビルトインサーバーを止める事が出来ませんでした。どちらも制限アリで使えるのですが、この際せっかくなので本格的なLinux環境としてWSL (Windows Subsystem for Linux)を導入してみます。

WSLはかつてのバージョンではソケット通信が出来なかったりPostgreSQLなどの高度なツールが使う一部の機能に対応せず動作しなかったりデーモンとしてのプログラム起動が出来なかったりしましたが、2018年10月13日現在のWindows 10 リリース1803においては問題ない状態となっているようです。

導入方法

ググればいくらでも情報は出てくるので簡単に。ただしWSLリリース初期は今とは若干異なる手順でしたので古い情報にはお気を付けください。

  1. 「プログラムと機能」→「Windowsの機能の有効かと無効化」→「Windows Subsystem for Linux」を有効化。OS再起動を求められるので再起動します。

  2. Microsoft StoreでUbuntu 18.04 LTSをインストール。他のバージョンやUbuntu以外にもいくつかディストリビューションが選べます。
  3. スタートメニューからUbuntuを起動する。初回起動はインストールの続きが行われるので長めです。一般ユーザー名とsudo時に使うパスワードを求められますがどちらもWindowsのログインに使っているものと同じでにしました。
  4. フォント指定やデフォルトウィンドウサイズの変更はタイトルバー右クリック→「プロパティ」から。個人的にターミナル向けフォントとして長年使っているVLゴシックを指定。
  5. インストールしたままだと一部パッケージが最新でないのでaptコマンドで初回のパッケージ更新を行います。
    sudo apt update
    sudo apt upgrade
  6. あとはほぼ普通のUbuntu Linux環境ですのでaptコマンドなりなんなりで必要なツールチェーンを入れます。私はUbuntu公式のレポジトリからPHP 7.2を導入しました。Windows上のドライブは /mnt/ 配下にマウントされているので開発中リソースはそのままWSL上からも見えますのでどちらからも編集できます。

動作状況

Symfony 4 + Flex の /bin/console CLIなど特に問題なく動作します。/bin/console server:run によるビルトインサーバ起動も問題なく動き、Ctrl + C による終了も問題ありません。

今回PHPを実行する環境としてWSL上でPHPを動かしていますが、DBへの接続はlocalhost指定であろうとTCP/IP接続なので、これまで使っていたWindows版のMySQLやPostgreSQLに普通に接続できます。今はWSL上でもPostgreSQLなどが動きますが速度的にもとりあえずWindows版のまま使おうと思います。

また、ソースをWindows上で動くPHP Stormで編集する事も、それらをWindows版のSource TreeでGit管理する事も特に問題有りません。必要な部分だけをWSL上から実行する事が出来ます。

速度は気持ち程度遅いですが、PHPビルトインサーバを使っている分には特に困らないです。

所感

以前は辛い部分も多かったようですが、今の所思っていた以上に普通のLinux環境として使えます。普段からLinuxサーバーを触っている身としては独自の文化やしきたりを求められないのは使いやすいです。各種アプリパッケージの導入も apt コマンドなど「Linuxディストリビューションとして普通の方法」で行う事が出来ます。Virtual Machineのような環境ではなく、あくまでWindowsのまま必要なツールだけをWSL上から実行できるのも使い勝手が良いですね。

動作速度的にもWSL上でRDBを起動し巨大なテーブルを幾つも載せる、といったような使い方にはあまり向いていないと思われるので、RDBはWindows版を使ったまま「これまで以上にリッチかつナチュラルに使えるLinuxツールチェーン環境」として使うのが良いんじゃないかと思います。


Amazon.co.jpアソシエイト

Amazon.co.jpアソシエイト

WindowsのコマンドプロンプトからOS標準のsshやtarやcurlコマンドを使う

かつては色々な方法が有りましたが、Windows 10 (April 2018 Update以降) 現在においては特に追加で入れなくてもOS標準で以下のコマンドが使えるようになっています。

    • ssh (ssh-keygen等も含む)
    • sftp
    • scp
    • tar
    • curl

Windows 10にはLinuxのほぼフル機能が使えるWSL(Windows Subsystem for Linux)が有りますがそれを導入せずとも利用できます。唐突にLinux/Unixサーバーに接続してあれこれしたくなった時にも十分対応できそうな感じですね。

コマンドプロンプトのコードページ設定が932(ANSI/OEM 日本語 Shift-JIS)のままでもUTF-8なサーバーに接続してUTF-8なテキストファイルは普通に編集できるので普通に実用可能かと思います。

whereコマンドで探してみると C:\Windows\System32\OpenSSH\ssh.exe が存在している事が分かる。
※2行目に有るものはGitBashで導入されたsshコマンド。

Windows 10 RS4に追加された「curl」と「tar」コマンド
http://ascii.jp/elem/000/001/630/1630041/


Amazon.co.jpアソシエイト

東京リージョンで使えるようになったAmazon EFSを使って手軽なWordPress冗長化

WordPressをはじめとした管理者が自由に投稿できるタイプのCMS冗長化は、DBを Amazon RDS などに向けてもテーマの編集やアップロードした画像、各種ファイルの扱いなどが面倒でした。

Amazon S3 に画像をアップロードするようにするWordPressプラグインなども有りますし、複数サーバー間のrsync、lsyncdでファイルの内容を同期するなどの方法も有りますが、先日東京リージョンでもリリースされた Amazon EFS を利用すると簡単に「複数サーバーで共用のドキュメントルート」を実現する事が出来ます。

Amazon EFS (Elastic File System)はマネージドなNFSサービスで複数のEC2インスタンスからマウント・アクセスする事が可能です。

以下手順

AWSマネジメントコンソールにログイン。

新しいVPCを作ります。

作成したVPCに新しいサブネットを2つ作ります。ここではAZ冗長化の為に1a AZと1c AZにサブネットを作成します。

インターネットゲートウェイを作成します。

作成したインターネットゲートウェイをVPCにアタッチします。

作成したVPCのデフォルトルートテーブルにルーティングを追加。
0.0.0.0/0 を先ほど作成したインターネットゲートウェイに向けます。

Webアクセス用のセキュリティグループを追加。VPCの選択ミスに注意。

SSH/HTTP/HTTPSをまとめて許可。SSHは本来はセキュリティグループを分けてより適切に制御した方が好ましいです。

Webサーバ用のEC2インスタンスを起動していく。Amazon Linux 2 インスタンスを選択。

インスタンスタイプの選択。

VPCの選択を忘れない事。サブネットはとりあえず1aの方を選択する。自動割り当てパブリックIPは有効にする。

ストレージの設定。

セキュリティグループは「既存のセキュリティグループ」からWeb用に作成した物を適用。

キーペアが無ければ新しく作成して手元にダウンロードする。

 

 

マシンの起動を待つ。

起動したらダウンロードしたキーペアを鍵ファイルにSSH接続。

PHP関連とApacheを導入。
yum install php php-common php-opcache php-gd php-mysqlnd php-mbstring php-fpm httpd

データベース冗長化の為にAmazon RDS for MySQL のインスタンスを作成する。RDSの画面からMySQLを起動していく。

MySQL 5.7.21を選択。

マルチAZ設定を有効化。これでDB側が複数AZに冗長化されます。

DB名やユーザー、パスワードなどを適当に設定。メモしておく事。

作成したVPCを選択。DBサブネットグループは新規作成。

DBパラメータグループ、オプショングループはデフォルトのまま。本来は別で作成しておいた方がいいです。後から設定を変更する際にデフォルトのままだと面倒です。

EC2インスタンスにmysql (mysql-serverではない)をインストール。パッケージとしてはmariadbが降ってきます。

RDSのエンドポイント名をメモ。

RDSに適用されているセキュリティグループにWeb用セキュリティグループからのTCP: 3306許可を追加。

mysqlコマンドからRDSに接続が出来る事を確認。

ドキュメントルート冗長化の為のEFSを起動していきます。

作成したVPCとサブネットを選択。セキュリティグループはとりあえずデフォルトのまま。

パフォーマンスモードはとりあえずそのまま。

EFSが利用可能になるのを待ちます。

EFS用のセキュリティグループを作成。

EFS用セキュリティグループにWeb用セキュリティグループからの全許可を追加して保存。

EFSインスタンスの画面からマウント方法を確認する。必要なEFSマウントヘルパーを導入する。
sudo yum install -y amazon-efs-utils

現在のVPCの設定ではDNS名でアクセスできないという警告が出ているので対応する。

VPCの設定で「DNSホスト名の編集」を「はい」に変更。

EFSにDNS名でアクセスできるようになります。

先ほどのEFS接続方法がより具体的な内容に変化している。

EFSのセキュリティグループの設定を先ほど作成したEFS用のセキュリティグループに変更。これでWebサーバからのNFSアクセスが通るようになります。

手順通りにコマンドを実行しEFSがマウントできたことを確認。今回は手動で叩いていますが、EC2のユーザーデータに仕込んでおくと起動時にマウントしてくれるようになります。

Apacheを起動。

EC2のDNS名で接続できることを確認。

EFSマウント配下にドキュメントルート用のディレクトリを作成、Apacheのドキュメントルート設定もそこを参照するように変更。今回は /efs/wp に実態を配置、 /var/www/html/wp をそこへのシンボリックリンクにして、/var/www/html/wp をドキュメントルートにしています。

Apacheを再起動して反映。閲覧テスト用のファイルをドキュメントルートに配置。

/etc/php.ini の設定で date.timezone を Asia/Tokyo に設定しておく。PHP設定変更後もApache再起動を実施。

testと書いたindex.html、<?php phpinfo(); が実行される info.php が閲覧できることを確認。

WordPressをセットアップしていきます。tar.gzでのアーカイブをwgetでダウンロード。

アーカイブをドキュメントルート配下に展開。この際にEFSは少しディスクI/Oが遅い事が分かります。ゆくゆくはCloudFrontなどでCDNキャッシュする事も検討した方がいいかもしれません。ファイル展開後はファイルの権限をApacheのものに変更。先ほど作成したindex.htmlとinfo.phpは削除しておきます。

WebブラウザでアクセスしWordPressのセットアップを進める。

DBの向き先はRDSのエンドポイント。その他WordPressのID・パスワードは適当に設定しメモしておく。

セットアップ完了。

現在起動しているEC2インスタンスのAMI(マシンイメージ)を取得。外部からのアクセスが有る状況でもないので「再起動しない」オプションは有効でOK。

作成したAMIから2つ目のEC2インスタンスを起動していく。サブネットはAZ冗長化の為に1cの方を選択。

マシン起動後にSSHログイン、先に1aで起動している方と同様にEFSマウント。先ほども書いたようにユーザーデータにしておくと最初からマウントされた状態になるかと思います。

1aで起動している方のDNS名、同1cのDNS名でどちらもWordPressサイトが閲覧できることを確認。

テーマを切り替えてみます。

もう片方にも反映されました。

画像アップロードを含む記事を作成してみます。

どちらのDNS名でも画像が見られることを確認。これで冗長化を実現できている事が分かります。同期用の設定などを組まなくていいのは楽ですね。

最後にロードバランサ―を立てます。Application Load Balancerを使います。

既存のサブネットを登録。

Web用のセキュリティグループを設定。本来このセキュリティグループにSSH許可は不要なのでALB用に別でセキュリティグループを作成した方がいいです。

ターゲットグループには起動済みのEC2インスタンス2つを追加。

作成したロードバランサーのDNS名をメモ。

ALBのDNS名でWordPressサイトが閲覧できることを確認。

以上でWebサーバー、DBサーバーが冗長化されただけでなく、コンテンツの同期も実現した環境が完成しました。ここまで所要時間は大体1時間強~2時間ほどでした。後は以下を検討していけばいいと思います。

セッション維持:
今回セッション維持は考えていません。WordPressに記事を投稿する際は起動している適当なインスタンスに直接アクセスするなど適当な方法を使います。

オートスケーリング:
AMI作成+ユーザーデータによるEFSマウント設定でオートスケーリングさせます。ファイルの同期はEFSをマウントするだけで完了します。

セキュリティグループ周り:
もうちょっと適切な内容で整理した方がいいです。

Apahce、PHPの設定、MySQLの設定:
今回は何も触っていないのでもちろん要チューニングです

CloudFront導入:
ファイルアクセスのレスポンスが気になるようであれば導入。実際どの程度の負荷まで耐えられるかは未知数。

AWS WAF導入:
既にALBが有るのでそこにAWS WAFを追加する事が出来ます。

あとはEFSを利用したドキュメントルートがどの程度のI/Oまで耐えられるかですね。ほぼ読み込みなら問題ない気がしていますが、これを実運用するならもちろん負荷テストは必要になるかと思います。場合によってはNFSからEC2ローカルに同期するような構成も検討が必要でしょう。以上、EFSでWordPressを冗長化してみた記事でした。

■ 2018年10月27日追記

Amazon Elastic File System (EFS) のプロビジョンドスループット機能が2018年 8月より利用できるようになっています。これを使えば I/O パフォーマンスは改善されるかも?

新機能 – Amazon Elastic File System (EFS) のプロビジョンドスループット | Amazon Web Services ブログ