前回(以下記事)からの続きです。
プライベートサブネットからインターネットへ出るために
アプリケーションサーバ(EC2)をプライベートサブネットに置くと、yum updateや、パッケージのダウンロード等でインターネットに出ていくことができません。
そこで、プライベートサブネットのEC2インスタンスをインターネットと通信させるために、NATインスタンスをパブリックサブネットに設置し、NAT経由で外部でに出れるようにします。
NAT用セキュリティグループの設定
踏み台・NATサーバ用(sg-ssh-nat)セキュリティグループに以下を追加します。
Inbound
Type | Protocol | Port | Source |
---|---|---|---|
HTTP(80) | TCP(6) | 80 | ap server のセキュリティグループ |
HTTPS(443) | TCP(6) | 443 | ap server のセキュリティグループ |
全てのICMP -IPv4 | ICMP(1) | 全て | ap server のセキュリティグループ |
カスタムTCPルール* | TCP(6) | 587 | ap server のセキュリティグループ |
ここで注意することとして、サイトからお問い合わせフォーム入力時などのメール送信する場合は、ポート587(又は465)もNATしてあげる必要があります。その場合は踏み台・NATサーバは常時立ち上げておく必要があります。
その他にも、プライベートサブネット内のEC2インスタンスから外部のサービスにアクセスするような場合は、以下のように、NATインスタンスのセキュリティーグループにこのインスタンスからの接続許可を追加します。
以下の追加設定が考えられる。
- 問い合わせフォームからメール送信するために、ポート587(又は465)を許可
- AWS CodeCommit にSSHでアクセスするために、22番ポートを許可
- 外部サイトから、git clone でソースコードを取得するためにGitプロトコル 9418番ポートを許可
NATインスタンスの作成
AMIからインスタンスを立ち上げる
AWSのサイトによると、以下のようにNATインスタンスとして設定されたAMIが用意されているようです。
Amazon では、NAT インスタンスとして実行されるように設定された Amazon Linux AMI を提供しています。これらの AMI の名前には文字列 amzn-ami-vpc-nat が含まれているので、Amazon EC2 コンソールで検索できます。NAT AMI からインスタンスを起動すると、次の設定がインスタンスで発生します。
- IPv4 転送が有効になり、ICMP リダイレクトが /etc/sysctl.d/10-nat-settings.conf で無効になります
- /usr/sbin/configure-pat.sh にあるスクリプトが起動時に実行され、iptables IP マスカレードが設定されます
このAMIでNATインスタンスを作成します。また、このインスタンスは踏み台サーバとしても利用します。
AMI選択画面で「amzn-ami-vpc-nat 2017(現在の西暦)」を検索して一番新しいAMIを選択して、インスタンスを立ち上げます。
今回作成したVPCを設定し、サブネットは Availability Zone ap-northeast-1a のパブリックサブネット「public-subnet-front1」を指定します。
送信元/送信先チェックを無効にする
AWSのサイトによると、以下の理由によりインスタンスの「送信元/送信先チェック」を無効にする必要があります。
EC2 インスタンスは、送信元/送信先チェックをデフォルトで実行します。つまり、そのインスタンスは、そのインスタンスが送受信する任意のトラフィックの送信元または送信先である必要があります。しかし、NAT インスタンスは、送信元または送信先がそのインスタンスでないときにも、トラフィックを送受信できなければなりません。したがって、NAT インスタンスでは送信元/送信先チェックを無効にする必要があります。
このNATインスタンスには、外部からアクセスしますのでEIPを割り当て、Route53のDNSレコードに追加しておきます。
アプリケーションサブネット用 Route Table への追加設定
アプリケーションサーバーサブネット用 Route Table へ、インターネット向け通信(0.0.0.0/0)をNATサーバのインスタンスへ向ける「ルート」を追加します。
NAT接続する側のインスタンス(アプリケーションサーバ)作成
NATサーバに接続する側のアプリケーションサーバのインスタンスを作成します。
今回作成したVPCを設定し、サブネットは Availability Zone ap-northeast-1a のプライベートサブネット「private-subnet-ap1」を指定します。
アプリケーションサーバは「KUSANAGI」で構築しますが、ここでは構築手順は割愛します。以下の記事にてKUSANAGIでアプリケーションサーバ構築の手順を記載しています。
NAT経由での外部接続の確認
アプリケーションサーバのインスタンスが作成できたら、NATインスタンスを経由して外部のインターネットにアクセスができるか確認します。
ここで、アプリケーションサーバはプライベートサブネットに設置しているため、ローカルPCから直接ログインできません。
AWSコンソール画面で発行したキーペア( *****.pem )をWinSCP等で踏み台/NATサーバに転送し、以下のコマンドでアプリケーションサーバへログインします。(pemファイルのパーミッションは600にしておく)
$ ssh -i *****.pem centos@10.0.100.214
__ ____ _______ ___ _ _____ __________
/ //_/ / / / ___// | / | / / | / ____/ _/
/ ,< / / / /\__ \/ /| | / |/ / /| |/ / __ / /
/ /| / /_/ /___/ / ___ |/ /| / ___ / /_/ // /
/_/ |_\____//____/_/ |_/_/ |_/_/ |_\____/___/
Version 7.8.3, Powered by Prime Strategy.
[centos@ip-10-0-100-214 ~]$
踏み台サーバから無事アプリケーションサーバにログインできました。
では、プライベートサブネットに設置されたアプリケーションサーバから、外部インターネットへアクセスできるか確かめます。
ping を打ってみます。
$ ping google.co.jpPING google.co.jp (172.217.24.131) 56(84) bytes of data.
WordPressでのタスクスケジュール実行機能
WordPressでは、予約投稿などを実現する為にアクセスがあった際にwp-cron.phpを実行して、予約時間を経過しているかチェックし経過している場合は記事を公開するといった仕組みを実装しています。いわば疑似cronというわけです。
誰もアクセスしなければ、いつまでも処理が実行されませんし、逆にアクセスの度にwp-cron.phpが実行されてしまう為、負荷も考慮しないといけません。
そこで、まず、wordpressでアクセスされる度に実行されるのを無効化し、サーバのcronで定期的に実行するようにします。
wordpress側でのwp-cron.phpの無効化
wp-config.php に以下を追加します。
define('DISABLE_WP_CRON', true);
サーバ側でのwp-cron.phpのcron設定
/etc/crontab に以下のスケジュール実行を登録します。
*/10 で10分毎の実行。実行ユーザーは httpd としています。
# Example of job definition:
# .---------------- minute (0 - 59)
# | .------------- hour (0 - 23)
# | | .---------- day of month (1 - 31)
# | | | .------- month (1 - 12) OR jan,feb,mar,apr ...
# | | | | .---- day of week (0 - 6) (Sunday=0 or 7) OR sun,mon,tue,wed,thu,fri,sat
# | | | | |
# * * * * * user-name command to be executed
*/10 * * * * httpd /bin/php -q /home/kusanagi/xxx/DocumentRoot/wp-cron.php > /dev/null 2>&1
実行ユーザーは環境により異なるかと思います。(httpd/apache/nignx等)
また、php の絶対パスは、サーバ上でwhich php などして確認してください。
ここで注意ですが、必ずWebサーバーのユーザーで実行します。そうでないとWebサーバーが書き込む際にパーミッションエラーになってしまう危険性があります。
root で crontab -e でcron設定などしないように注意してください。
2018/03/26追記 KUSANAGI環境での問題
KUSANAGI環境で、気付くと /var/log/cron に以下のようなエラーが出ていました。
(CRON) ERROR chdir failed (/home/httpd): No such file or directory
実行ユーザー httpd に関して /etc/passwd には以下のように記載されています。
httpd:x:1001:1001::/home/httpd:/bin/false
確かに /home/httpd というディレクトリは存在していません。このあたりはKUSANAGIのセットアップのままだったのですが・・・
以下のように、/home/httpd を作成して所有者・パーミッションを設定して、正常にCRONが動作するようになりました。
cd /home
sudo mkdir httpd
sudo chown httpd:www httpd
sudo chmod 750 httpd