20200104のAWSに関する記事は15件です。

インフラエンジニアがwebアプリ作ってみる#1

1. 初めに

令和2年になりました。社会人2年目で仕事にもある程度慣れてきて、今年も頑張ろうと思っていた時ふと「あれ?俺ってアプリ開発全然できなくね?」と気付いてしまいました。
というのは私はインフラSEとして入社して以来一貫してインフラ基盤の初期構築ばかりやってきました。Ansible、Python、Javaとかは使っているものの、アプリ側のエンジニアとしてはとても飯を食っていけないレベルです。
更にインフラSEのくせにクラウド触ったことないです…。
市場価格なくなってしまうんでね?と思い新年やる気あるうちに自分でスキル高めようと決意した次第です。
三日坊主にならないように、Qiitaに投稿します。

2. やりたいこと

とりあえずクオリティは置いといてwebアプリを作り切りたい!!!
ToDoアプリを作成し(Kotlin&Spring)期限ないに達成できないとLineBotから鬼責めされる三日坊主防止アプリを作りたいと思ってます。
(需要ないとか言わないで…)
フェーズ1としてローカルマシンにアプリを構築(キーワード:spring,Kotlin,Gradle,Postgres)
フェーズ2としてAWS上にアプリをデプロイ
フェーズ3としてCI/CD環境の整備
フェーズ4としてiOSアプリ化
をやってみたいです。

3. 今後について

作成していく過程で使う技術を自分なりの言葉でまとめて記事投稿していきたいと思います。

4. お願い

間違ったこと、ナンセンスなことやってたら優しく指摘していただけると幸いです。

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Cloud9にリモートデスクトップする方法

はじめに

AWSのCloud9は、AWSマネジメントコンソールからIDEとターミナルで開発や検証を進めますが、時々、ローカルのデスクトップ環境が欲しくなることがあります。

例えば、Webサイトやアプリケーションを開発すれば、ローカルのApache等に配置し、ブラウザから動作確認したいところです。
Pythonでrunserverを実行して、簡易的にWebサーバを起動して同様に動作確認したい場面もあるかと思います。
また、Cloud9にはdockerがプリインストールされているため、コンテナをbuildしたりupしたりすれば、ローカルで接続テストをしたい場面があるでしょう。
このような場面で、解説書やブログを参考にしていると、ブラウザで http://127.0.0.1:8000http://localhost 等に接続してGUIを確認する手順 (以下画像のようなこと) を指示される場合がありますが、Cloud9で開発していると手順通りに行かないため、先に進まなくなります。

image.png

もしCloud9にローカルのデスクトップ環境があれば、Cloud9でローカル上にテスト環境を作った後、ブラウザを開いて、さくっと接続確認できるので、生産性が上がります。

そこで、Cloud9にデスクトップ環境をインストールし、リモートデスクトップする手順を調査し、整理してみました。

前提環境

  • Cloud9: EC2環境 (OS: Ubuntu Server 18.04 LTS)
  • インスタンスタイプ: t3.micro以上を推奨
  • インストールするデスクトップ環境: MATE

※ 最後の接続確認はMacから実施しています。

構成図

image.png

Cloud9 (AWS) で実施する手順

1. Cloud9を構築する

環境の名前や説明はお好みで付ければOKです。
以下の画像の通り、Environment typeをEC2、PlatformをUbuntu Server 18.04 LTSとして構築します。
image.png

Point: 何故Amazon Linuxにしないのか

ここでAmazon Linuxを選んでも良いのですが、2020年1月の時点では、以下の理由で推奨しません。

  • ここでAmazon Linuxを選択しても、Amazon Linux 2にはなりませんので、公式チュートリアルの手順でデスクトップ環境を作ることができません。
    • Amazon Linux 2でCloud9を構築するにはSSH環境にする必要がありますが、SSH環境では一定時間操作がない時の自動停止機能が使えないので、私のようなズボラな方にはお勧めできません。
  • Amazon Linuxは、2020年6月にサポートが終了します。

Q: Amazon Linux AMI はどれくらいの期間、サポートされますか?
AWS では 2020 年 6 月 30 日まで、Amazon Linux AMI 2018.03 の最新バージョンに対するセキュリティ更新の提供を継続し、Amazon Linux 2 への移行を促進します。Amazon Linux 2 では、2023 年 6 月 30 日まで長期サポートを受けることができます。

2. デフォルトで作成されたEBSを拡張する

早速Cloud9に接続してデスクトップ環境をインストールしたいところですが、何もしないままにこの後紹介する手順でインストールを進めると、デフォルトで作成されるEBSボリュームの容量 (10GB) では不足してしまい、インストールが失敗します。

そこで、EBSボリュームを 10GB → 15GB に拡張します。
まずはAWSのマネジメントコンソールで、ボリュームの変更を行い、容量を拡張します。

image.png

次に、拡張したEBSの容量を、OS上でも認識させます。
Cloud9のマネジメントコンソールを開き、ターミナルのウインドウで操作します。

まずlsblkでパーティションを確認すると、拡張すべきパーティションが/dev/nvme0n1の1番目(MOUNTPOINTが/)だと分かりますので、sudo growpart /dev/nvme0n1 1を実行して拡張します。
上記の実行後、パーティションを拡張した結果をlsblkで確認すると、15GBになっていることが分かります。
次にdf -hでファイルシステムを確認し、拡張すべきファイルシステムが/dev/nvme0n1p1だと分かりますので、sudo resize2fs /dev/nvme0n1p1 を実行して拡張します。
上記の実行後、ファイルシステムを拡張した結果をdf -hで確認すると、15GBになっていることが分かります。

コマンドは以下の通りとなります。

bash
ubuntu:~/environment $ lsblk
NAME        MAJ:MIN RM  SIZE RO TYPE MOUNTPOINT
loop0         7:0    0 12.7M  1 loop /snap/amazon-ssm-agent/495
loop1         7:1    0 87.9M  1 loop /snap/core/5328
loop2         7:2    0 89.1M  1 loop /snap/core/8268
nvme0n1     259:0    0   15G  0 disk 
└─nvme0n1p1 259:1    0   10G  0 part /

ubuntu:~/environment $ sudo growpart /dev/nvme0n1 1
CHANGED: partition=1 start=2048 old: size=20969439 end=20971487 new: size=31455199,end=31457247

ubuntu:~/environment $ lsblk
NAME        MAJ:MIN RM  SIZE RO TYPE MOUNTPOINT
loop0         7:0    0 12.7M  1 loop /snap/amazon-ssm-agent/495
loop1         7:1    0 87.9M  1 loop /snap/core/5328
loop2         7:2    0 89.1M  1 loop /snap/core/8268
loop3         7:3    0   18M  1 loop /snap/amazon-ssm-agent/1480
nvme0n1     259:0    0   15G  0 disk 
└─nvme0n1p1 259:1    0   15G  0 part /

ubuntu:~/environment $ df -h
Filesystem      Size  Used Avail Use% Mounted on
udev            468M     0  468M   0% /dev
tmpfs            96M  764K   96M   1% /run
/dev/nvme0n1p1  9.7G  7.6G  2.1G  79% /
tmpfs           479M     0  479M   0% /dev/shm
tmpfs           5.0M     0  5.0M   0% /run/lock
tmpfs           479M     0  479M   0% /sys/fs/cgroup
/dev/loop0       13M   13M     0 100% /snap/amazon-ssm-agent/495
/dev/loop1       88M   88M     0 100% /snap/core/5328
tmpfs            96M     0   96M   0% /run/user/1000
/dev/loop2       90M   90M     0 100% /snap/core/8268
/dev/loop3       18M   18M     0 100% /snap/amazon-ssm-agent/1480
ubuntu:~/environment $ sudo resize2fs /dev/nvme0n1p1 
resize2fs 1.44.1 (24-Mar-2018)
Filesystem at /dev/nvme0n1p1 is mounted on /; on-line resizing required
old_desc_blocks = 2, new_desc_blocks = 2
The filesystem on /dev/nvme0n1p1 is now 3931899 (4k) blocks long.

ubuntu:~/environment $ df -h
Filesystem      Size  Used Avail Use% Mounted on
udev            468M     0  468M   0% /dev
tmpfs            96M  764K   96M   1% /run
/dev/nvme0n1p1   15G  7.6G  7.0G  53% /
tmpfs           479M     0  479M   0% /dev/shm
tmpfs           5.0M     0  5.0M   0% /run/lock
tmpfs           479M     0  479M   0% /sys/fs/cgroup
/dev/loop0       13M   13M     0 100% /snap/amazon-ssm-agent/495
/dev/loop1       88M   88M     0 100% /snap/core/5328
tmpfs            96M     0   96M   0% /run/user/1000
/dev/loop2       90M   90M     0 100% /snap/core/8268
/dev/loop3       18M   18M     0 100% /snap/amazon-ssm-agent/1480

ここまでの手順で、EBSの容量を 10GB → 15GB に拡張できました。

3. デスクトップ環境 (MATE) をインストールする

以下のコマンドを実行するだけです。

bash
ubuntu:~/environment $ sudo apt install ubuntu-mate-desktop

4. vnc4serverをインストールして設定する

Cloud9にリモートデスクトップするために、以下のコマンドで、vnc4serverをインストールします。

bash
ubuntu:~/environment $ sudo apt install vnc4server

インストールが完了したら、以下のコマンドvncserver :1を実行し、一度VNCサーバを起動します。
コマンドを実行すると、デスクトップ環境にログインするためのパスワードの設定を求められますので、入力して設定します。
このパスワードは6文字以上8文字以下となり、8文字以上入力した時は、8文字目までがパスワードとして設定されます。

bash
ubuntu:~/environment $ vncserver :1

You will require a password to access your desktops.

Password:
Verify:
Password too long - only the first 8 characters will be used
xauth:  file /home/ubuntu/.Xauthority does not exist

New 'ip-172-31-43-50:1 (ubuntu)' desktop is ip-172-31-43-50:1

Creating default startup script /home/ubuntu/.vnc/xstartup
Starting applications specified in /home/ubuntu/.vnc/xstartup
Log file is /home/ubuntu/.vnc/ip-172-31-43-50:1.log

起動が完了したら、すぐVNCサーバを停止します。

bash
ubuntu:~/environment $ vncserver -kill :1
Killing Xvnc4 process ID 1058

次に、一度起動したことによって、VNCサーバの設定ファイル/home/ubuntu/.vnc/xstartup が生成されていますので、この設定ファイルをMATE用に編集します。

bash
$ vi /home/ubuntu/.vnc/xstartup

設定ファイルの中身を、以下の内容に編集して保存します。

/home/ubuntu/.vnc/xstartup
#!/bin/sh

# Uncomment the following two lines for normal desktop:
# unset SESSION_MANAGER
# exec /etc/X11/xinit/xinitrc

unset DBUS_SESSION_BUS_ADDRESS
export XMODIFIERS="@im=fcitx"
fcitx

[ -x /etc/vnc/xstartup ] && exec /etc/vnc/xstartup
[ -r $HOME/.Xresources ] && xrdb $HOME/.Xresources
xsetroot -solid grey
# vncconfig -iconic &
# x-terminal-emulator -geometry 80x24+10+10 -ls -title "$VNCDESKTOP Desktop" &
# x-window-manager &
mate-session &

5. vnc4serverの自動起動を設定

Cloud9を起動した時に、vnc4serverも自動起動するようにします。
~/.bashrcを開き、最下行に起動コマンドを追記します。

bash
ubuntu:~/environment $ vi ~/.bashrc

以下のように、最下行に起動コマンドを追記して保存します。
オプションの-geometryは解像度、-depthはビットカラー (8: 256色、16: 最大65536色、24: 最大16777216色)を示しますので、リモートデスクトップするクライアントの環境に合わせて変えてください。

~/.bashrc
# .bashrc

export PATH=$PATH:$HOME/.local/bin:$HOME/bin

(中略)

# Add RVM to PATH for scripting. Make sure this is the last PATH variable change.
export PATH="$PATH:$HOME/.rvm/bin"

# ここから追記
vncserver :1 -geometry 1280x800 -depth 24

保存後、OSを再起動します。

bash
ubuntu:~/environment $ sudo shutdown -r now

Cloud9のマネジメントコンソール上に 「Connecting...」と表示されますので、自然に消えるのを待った後、次の手順に進みます。

6. SSHポートフォワードするため、パスワード認証を有効にする

デスクトップ環境にはインターネット経由で接続することになりますので、SSHポートフォワードを利用して、暗号化されたセキュアな接続にします。
Cloud9をubuntuユーザで利用する場合が殆どだと思いますので、デスクトップ環境もubuntuユーザで接続できるようにします。

まず、ubuntuユーザのパスワードを設定します。

bash
$ sudo passwd ubuntu
Enter new UNIX password: 

Retype new UNIX password: 

passwd: password updated successfully

次に、/etc/ssh/sshd_configファイルを編集し、PasswordAuthenticationのパラメータをyesに更新して保存します。

bash
ubuntu:~/environment $ sudo vi /etc/ssh/sshd_config
/etc/ssh/sshd_config
(中略)

# To disable tunneled clear text passwords, change to no here!
PasswordAuthentication yes
#PermitEmptyPasswords no

(中略)

保存後、SSHのサービスを再起動します。

bash
ubuntu:~/environment $ sudo service ssh restart

7. Security Groupで22番ポートを開放

クライアントPCからSSHポートフォワードを利用してリモートデスクトップするために、Cloud9のEC2インスタンスにアタッチされているSecurity Groupで22番ポートを開放します。
必ずクライアント側のグローバルIPを指定して/32で開放します。
開放すべきIPアドレスが分からない場合は、プルダウンで「マイIP」を選ぶと自動的に入力されます。
image.png

ここまでがCloud9側 (AWS側) の設定です。

クライアントPC側の設定

1. ターミナルからSSHポートフォワードする

AWSマネジメントコンソールでCloud9のEC2インスタンスにアタッチされたパブリックIPアドレスを確認し、クライアントPC側のターミナルで以下のコマンドを実行します。
以下のコマンドを実行した後、localhostの8888番ポートに接続すると、SSH経由でxxx.xxx.xxx.xxx(Cloud9)の5901番ポートに接続されます。

bash
$ ssh -L 8888:localhost:5901 ubuntu@xxx.xxx.xxx.xxx

2. リモートデスクトップする

Macでは、Finderで「サーバへ接続」を開き、以下の通り入力して接続します。
image.png
接続すると、以下のようにデスクトップが開きます。
image.png

ここまでの手順で、Cloud9にデスクトップ環境をインストールして、クライアントからリモートデスクトップ接続ができました。

Cloud9でWebサーバを起動し、リモートデスクトップで動作確認する

Cloud9のMATEデスクトップ環境上のブラウザ (Firefox) を利用して、localhostに接続して動作確認できるかどうか試してみます。
まず、Cloud9でhttpd (Apache) を起動して、/var/www/htmlにテストファイルを置きます。
image.png

その後、リモートデスクトップでCloud9に接続して、ブラウザを開いて接続します。

image.png

このように、ブラウザを必要とする動作確認も、Cloud9のEC2インスタンス内だけで完結しますので、Cloud9で開発や検証を進める際の不便が一つ解消します。

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Cloud9にDesktop (GUI) 環境をインストールする方法

はじめに

AWSのCloud9は、AWSマネジメントコンソールからIDEとターミナルで開発や検証を進めますが、時々、ローカルのデスクトップ環境が欲しくなることがあります。

例えば、Webサイトやアプリケーションを開発すれば、ローカルのApache等に配置し、ブラウザから動作確認したいところです。
Pythonでrunserverを実行して、簡易的にWebサーバを起動して同様に動作確認したい場面もあるかと思います。
また、Cloud9にはdockerがプリインストールされているため、コンテナをbuildしたりupしたりすれば、ローカルで接続テストをしたい場面があるでしょう。
このような場面で、解説書やブログを参考にしていると、ブラウザで http://127.0.0.1:8000http://localhost 等に接続してGUIを確認する手順 (以下画像のようなこと) を指示される場合がありますが、Cloud9で開発していると手順通りに行かないため、先に進まなくなります。

image.png

もしCloud9にローカルのデスクトップ環境があれば、Cloud9でローカル上にテスト環境を作った後、ブラウザを開いて、さくっと接続確認できるので、生産性が上がります。

そこで、Cloud9のEC2インスタンスを構築し、デスクトップ環境をインストールし、リモートデスクトップする手順を調査し、整理してみました。

前提環境

  • Cloud9: EC2環境 (OS: Ubuntu Server 18.04 LTS)
  • インスタンスタイプ: t3.micro以上を推奨
  • インストールするデスクトップ環境: MATE

※ 最後の接続確認はMacから実施しています。

構成図

image.png

Cloud9 (AWS) で実施する手順

1. Cloud9を構築する

環境の名前や説明はお好みで付ければOKです。
以下の画像の通り、Environment typeをEC2、PlatformをUbuntu Server 18.04 LTSとして構築します。
image.png

Point: 何故Amazon Linuxにしないのか

ここでAmazon Linuxを選んでも良いのですが、2020年1月の時点では、以下の理由で推奨しません。

  • ここでAmazon Linuxを選択しても、Amazon Linux 2にはなりませんので、公式チュートリアルの手順でデスクトップ環境を作ることができません。
    • Amazon Linux 2でCloud9を構築するにはSSH環境にする必要がありますが、SSH環境では一定時間操作がない時の自動停止機能が使えないので、私のようなズボラな方にはお勧めできません。
  • Amazon Linuxは、2020年6月にサポートが終了します。

Q: Amazon Linux AMI はどれくらいの期間、サポートされますか?
AWS では 2020 年 6 月 30 日まで、Amazon Linux AMI 2018.03 の最新バージョンに対するセキュリティ更新の提供を継続し、Amazon Linux 2 への移行を促進します。Amazon Linux 2 では、2023 年 6 月 30 日まで長期サポートを受けることができます。

2. デフォルトで作成されたEBSを拡張する

早速Cloud9に接続してデスクトップ環境をインストールしたいところですが、何もしないままにこの後紹介する手順でインストールを進めると、デフォルトで作成されるEBSボリュームの容量 (10GB) では不足してしまい、インストールが失敗します。

そこで、EBSボリュームを 10GB → 15GB に拡張します。
まずはAWSのマネジメントコンソールで、ボリュームの変更を行い、容量を拡張します。

image.png

次に、拡張したEBSの容量を、OS上でも認識させます。
Cloud9のマネジメントコンソールを開き、ターミナルのウインドウで操作します。

まずlsblkでパーティションを確認すると、拡張すべきパーティションが/dev/nvme0n1の1番目(MOUNTPOINTが/)だと分かりますので、sudo growpart /dev/nvme0n1 1を実行して拡張します。
上記の実行後、パーティションを拡張した結果をlsblkで確認すると、15GBになっていることが分かります。
次にdf -hでファイルシステムを確認し、拡張すべきファイルシステムが/dev/nvme0n1p1だと分かりますので、sudo resize2fs /dev/nvme0n1p1 を実行して拡張します。
上記の実行後、ファイルシステムを拡張した結果をdf -hで確認すると、15GBになっていることが分かります。

コマンドは以下の通りとなります。

bash
ubuntu:~/environment $ lsblk
NAME        MAJ:MIN RM  SIZE RO TYPE MOUNTPOINT
loop0         7:0    0 12.7M  1 loop /snap/amazon-ssm-agent/495
loop1         7:1    0 87.9M  1 loop /snap/core/5328
loop2         7:2    0 89.1M  1 loop /snap/core/8268
nvme0n1     259:0    0   15G  0 disk 
└─nvme0n1p1 259:1    0   10G  0 part /

ubuntu:~/environment $ sudo growpart /dev/nvme0n1 1
CHANGED: partition=1 start=2048 old: size=20969439 end=20971487 new: size=31455199,end=31457247

ubuntu:~/environment $ lsblk
NAME        MAJ:MIN RM  SIZE RO TYPE MOUNTPOINT
loop0         7:0    0 12.7M  1 loop /snap/amazon-ssm-agent/495
loop1         7:1    0 87.9M  1 loop /snap/core/5328
loop2         7:2    0 89.1M  1 loop /snap/core/8268
loop3         7:3    0   18M  1 loop /snap/amazon-ssm-agent/1480
nvme0n1     259:0    0   15G  0 disk 
└─nvme0n1p1 259:1    0   15G  0 part /

ubuntu:~/environment $ df -h
Filesystem      Size  Used Avail Use% Mounted on
udev            468M     0  468M   0% /dev
tmpfs            96M  764K   96M   1% /run
/dev/nvme0n1p1  9.7G  7.6G  2.1G  79% /
tmpfs           479M     0  479M   0% /dev/shm
tmpfs           5.0M     0  5.0M   0% /run/lock
tmpfs           479M     0  479M   0% /sys/fs/cgroup
/dev/loop0       13M   13M     0 100% /snap/amazon-ssm-agent/495
/dev/loop1       88M   88M     0 100% /snap/core/5328
tmpfs            96M     0   96M   0% /run/user/1000
/dev/loop2       90M   90M     0 100% /snap/core/8268
/dev/loop3       18M   18M     0 100% /snap/amazon-ssm-agent/1480
ubuntu:~/environment $ sudo resize2fs /dev/nvme0n1p1 
resize2fs 1.44.1 (24-Mar-2018)
Filesystem at /dev/nvme0n1p1 is mounted on /; on-line resizing required
old_desc_blocks = 2, new_desc_blocks = 2
The filesystem on /dev/nvme0n1p1 is now 3931899 (4k) blocks long.

ubuntu:~/environment $ df -h
Filesystem      Size  Used Avail Use% Mounted on
udev            468M     0  468M   0% /dev
tmpfs            96M  764K   96M   1% /run
/dev/nvme0n1p1   15G  7.6G  7.0G  53% /
tmpfs           479M     0  479M   0% /dev/shm
tmpfs           5.0M     0  5.0M   0% /run/lock
tmpfs           479M     0  479M   0% /sys/fs/cgroup
/dev/loop0       13M   13M     0 100% /snap/amazon-ssm-agent/495
/dev/loop1       88M   88M     0 100% /snap/core/5328
tmpfs            96M     0   96M   0% /run/user/1000
/dev/loop2       90M   90M     0 100% /snap/core/8268
/dev/loop3       18M   18M     0 100% /snap/amazon-ssm-agent/1480

ここまでの手順で、EBSの容量を 10GB → 15GB に拡張できました。

3. デスクトップ環境 (MATE) をインストールする

以下のコマンドを実行するだけです。

bash
ubuntu:~/environment $ sudo apt install ubuntu-mate-desktop

4. vnc4serverをインストールして設定する

Cloud9にリモートデスクトップするために、以下のコマンドで、vnc4serverをインストールします。

bash
ubuntu:~/environment $ sudo apt install vnc4server

インストールが完了したら、以下のコマンドvncserver :1を実行し、一度VNCサーバを起動します。
コマンドを実行すると、デスクトップ環境にログインするためのパスワードの設定を求められますので、入力して設定します。
このパスワードは6文字以上8文字以下となり、8文字以上入力した時は、8文字目までがパスワードとして設定されます。

bash
ubuntu:~/environment $ vncserver :1

You will require a password to access your desktops.

Password:
Verify:
Password too long - only the first 8 characters will be used
xauth:  file /home/ubuntu/.Xauthority does not exist

New 'ip-172-31-43-50:1 (ubuntu)' desktop is ip-172-31-43-50:1

Creating default startup script /home/ubuntu/.vnc/xstartup
Starting applications specified in /home/ubuntu/.vnc/xstartup
Log file is /home/ubuntu/.vnc/ip-172-31-43-50:1.log

起動が完了したら、すぐVNCサーバを停止します。

bash
ubuntu:~/environment $ vncserver -kill :1
Killing Xvnc4 process ID 1058

次に、一度起動したことによって、VNCサーバの設定ファイル/home/ubuntu/.vnc/xstartup が生成されていますので、この設定ファイルをMATE用に編集します。

bash
$ vi /home/ubuntu/.vnc/xstartup

設定ファイルの中身を、以下の内容に編集して保存します。

/home/ubuntu/.vnc/xstartup
#!/bin/sh

# Uncomment the following two lines for normal desktop:
# unset SESSION_MANAGER
# exec /etc/X11/xinit/xinitrc

unset DBUS_SESSION_BUS_ADDRESS
export XMODIFIERS="@im=fcitx"
fcitx

[ -x /etc/vnc/xstartup ] && exec /etc/vnc/xstartup
[ -r $HOME/.Xresources ] && xrdb $HOME/.Xresources
xsetroot -solid grey
# vncconfig -iconic &
# x-terminal-emulator -geometry 80x24+10+10 -ls -title "$VNCDESKTOP Desktop" &
# x-window-manager &
mate-session &

5. vnc4serverの自動起動を設定

Cloud9を起動した時に、vnc4serverも自動起動するようにします。
~/.bashrcを開き、最下行に起動コマンドを追記します。

bash
ubuntu:~/environment $ vi ~/.bashrc

以下のように、最下行に起動コマンドを追記して保存します。
オプションの-geometryは解像度、-depthはビットカラー (8: 256色、16: 最大65536色、24: 最大16777216色)を示しますので、リモートデスクトップするクライアントの環境に合わせて変えてください。

~/.bashrc
# .bashrc

export PATH=$PATH:$HOME/.local/bin:$HOME/bin

(中略)

# Add RVM to PATH for scripting. Make sure this is the last PATH variable change.
export PATH="$PATH:$HOME/.rvm/bin"

# ここから追記
vncserver :1 -geometry 1280x800 -depth 24

保存後、OSを再起動します。

bash
ubuntu:~/environment $ sudo shutdown -r now

Cloud9のマネジメントコンソール上に 「Connecting...」と表示されますので、自然に消えるのを待った後、次の手順に進みます。

6. SSHポートフォワードするため、パスワード認証を有効にする

デスクトップ環境にはインターネット経由で接続することになりますので、SSHポートフォワードを利用して、暗号化されたセキュアな接続にします。
Cloud9をubuntuユーザで利用する場合が殆どだと思いますので、デスクトップ環境もubuntuユーザで接続できるようにします。

まず、ubuntuユーザのパスワードを設定します。

bash
$ sudo passwd ubuntu
Enter new UNIX password: 

Retype new UNIX password: 

passwd: password updated successfully

次に、/etc/ssh/sshd_configファイルを編集し、PasswordAuthenticationのパラメータをyesに更新して保存します。

bash
ubuntu:~/environment $ sudo vi /etc/ssh/sshd_config
/etc/ssh/sshd_config
(中略)

# To disable tunneled clear text passwords, change to no here!
PasswordAuthentication yes
#PermitEmptyPasswords no

(中略)

保存後、SSHのサービスを再起動します。

bash
ubuntu:~/environment $ sudo service ssh restart

7. Security Groupで22番ポートを開放

クライアントPCからSSHポートフォワードを利用してリモートデスクトップするために、Cloud9のEC2インスタンスにアタッチされているSecurity Groupで22番ポートを開放します。
必ずクライアント側のグローバルIPを指定して/32で開放します。
開放すべきIPアドレスが分からない場合は、プルダウンで「マイIP」を選ぶと自動的に入力されます。
image.png

ここまでがCloud9側 (AWS側) の設定です。

クライアントPC側の設定

1. ターミナルからSSHポートフォワードする

AWSマネジメントコンソールでCloud9のEC2インスタンスにアタッチされたパブリックIPアドレスを確認し、クライアントPC側のターミナルで以下のコマンドを実行します。
以下のコマンドを実行した後、localhostの8888番ポートに接続すると、SSH経由でxxx.xxx.xxx.xxx(Cloud9)の5901番ポートに接続されます。

bash
$ ssh -L 8888:localhost:5901 ubuntu@xxx.xxx.xxx.xxx

2. リモートデスクトップする

Macでは、Finderで「サーバへ接続」を開き、以下の通り入力して接続します。
image.png
接続すると、以下のようにデスクトップが開きます。
image.png

ここまでの手順で、Cloud9にデスクトップ環境をインストールして、クライアントからリモートデスクトップ接続ができました。

Cloud9でWebサーバを起動し、リモートデスクトップで動作確認する

Cloud9のMATEデスクトップ環境上のブラウザ (Firefox) を利用して、localhostに接続して動作確認できるかどうか試してみます。
まず、Cloud9でhttpd (Apache) を起動して、/var/www/htmlにテストファイルを置きます。
image.png

その後、リモートデスクトップでCloud9に接続して、ブラウザを開いて接続します。

image.png

このように、ブラウザを必要とする動作確認も、Cloud9のEC2インスタンス内だけで完結しますので、Cloud9で開発や検証を進める際の不便が一つ解消します。

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

AWS CloudWatch Logsで例外のログを取得する

現在勤めている企業ではDjangoで開発したアプリケーションをDocker Composeを利用して運用しています。

Dockerのログは以下のコマンドで確認することができます。

# appコンテナのログエントリーを表示し続ける(-fオプションでtail)
$ docker-compose logs -f app

# appコンテナの直近の500件のログエントリーを表示する
$ docker-compose logs --tail=500 app

しかし、運用していると、様々なトラブルがあって、トラブルの都度コンテナを実行しているサーバーにログインして、コンテナのログを確認するのが面倒臭い。

また、コンテナを破棄すると、今までのログも破棄してしまうため、運用環境では外部のログ保存ソフトウェアにログを送って保存します。Docker Composeではlog driverを利用することで、fluentdやAWS、GCPにログの送信・保存を行うことができます。

現在アプリケーションはAWSで運用しているので、以下の1〜3を行い、AWS CloudWatch Logsにログを送ることにします。

1. EC2インスタンスにIAMロールを設定
2. CloudWatch Logsでロググループを作成
3. docker-compose.ymlを修正

1. EC2インスタンスにIAMロールを設定

コンテナを実行しているEC2インスタンスに以下のIAMロールを作成し設定する。

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Action": [
        "logs:CreateLogStream",
        "logs:PutLogEvents"
      ],
      "Effect": "Allow",
      "Resource": "*"
    }
  ]
}

参考:
Amazon CloudWatch Logs ロギング・ドライバ

2. CloudWatch Logsでロググループを作成

AWSのコンソールでCloudWatchにアクセスし、ログ-->ロググループで「アクション」ボタンを押下します。そして、表示したダイアログにロググループ名を入力し、「ロググループの作成」ボタンを押下し作成します。

aws-cloudwatch-logs-action.png

3. docker-compose.ymlを修正

以下の設定をdocker-compose.ymlに追記します。

docker-compose.yml
version: '3'
services:
  app:
    ・・・(中略)・・・
    logging:
      driver: "awslogs"
      options:
        awslogs-region: "us-east-2" # オハイオリージョン
        awslogs-group: "/sample-app/dev/"
        awslogs-create-group: "true" # グループがない場合は作成
        awslogs-stream: "web"

以下のようにCloudWatch logsに保存できるようになりました。

aws-cloudwatch-logs.png

ログをCloudWatch logsに保存できるようになったのは良いですが、例外が発生した場合、ログが以下のように1行ずつ分割してしまい非常に見づらくなってしまいました。例外が発生したスタックトレースも1行ずつ分割しないで1行で保存するようにします。

aws-cloudwatch-logs.png

docker-compose.ymlに「awslogs-multiline-pattern」を追加します。またログを構造化してCloudWatch上で検索しやすくするために、django-structlogというモジュールをインストールします。django-structlogについては参考をご参照下さい。

docker-compose.yml
version: '3'
services:
  app:
    ・・・(中略)・・・
    logging:
      driver: "awslogs"
      options:
        awslogs-region: "us-east-2" # オハイオリージョン
        awslogs-group: "/sample-app/dev/"
        awslogs-create-group: "true" # グループがない場合は作成
        awslogs-stream: "web"
        awslogs-multiline-pattern: '^{"request_id":'

以下のように例外も1行のログとしてCloudWatch Logsに保存できるようになりました。

aws-cloudwatch-logs-after-1.png

aws-cloudwatch-logs-after-2.png

参考:
Djangoでロギング(logging)を行う方法

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

AWS Cognitoで認証したユーザのID トークンを Java で検証する

やりたいこと

AWS Amplify の Authentication で認証したクライアントが id_tokenをサーバに送信し、Javaで実装したサーバで id_token を検証します。

TL;DR

  • 発行者(ペイロードのiss) が対象にしている Cognitoのユーザプールであることを確認する。
  • 署名の検証は https://github.com/auth0/java-jwt に丸投げ。
  • com.auth0.jwt.JWTVerifier はスレッドセーフなのを前提にして、Cognitoが署名に使用した RSA鍵ペアを取得する回数を減らすために自前でキャッシュする。

実装

IdTokenValidator.java
IdTokenValidator.java
package com.exampleawsCognito.jwt;

import java.net.MalformedURLException;
import java.net.URL;
import java.security.interfaces.RSAPublicKey;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.GregorianCalendar;

import com.auth0.jwk.GuavaCachedJwkProvider;
import com.auth0.jwk.Jwk;
import com.auth0.jwk.JwkException;
import com.auth0.jwk.UrlJwkProvider;
import com.auth0.jwt.JWT;
import com.auth0.jwt.JWTVerifier;
import com.auth0.jwt.algorithms.Algorithm;
import com.auth0.jwt.interfaces.DecodedJWT;


/**
 * Cognitoで認証して得られるid tokenを扱う
 *
 * <p>
 * 実装の参考にしたソース
 * https://github.com/awslabs/cognito-proxy-rest-service/blob/master/src/main/kotlin/com/budilov/cognito/services/CognitoService.kt
 * </p>
 *
 * @ThreadSafe
 *
 */
public class IdTokenValidator {
    private static final String AWS_REGION = "ap-northeast-1";
    private static final String AWS_COGNITO_USER_POOL_ID = "my_userpool_id";

    private static JWTVerifier verifier = null;
    private static long verifierExpire = -1;
    private static final long VERIFIER_LIVE_MILISEC = 10 * 60 * 1000; //10分
    private static final JWT JWT = new JWT();

    /**
     * コンストラクタ
     */
    public IdTokenValidator() {
    }

    /**
     * IDトークン を検証します
     *
     * @param idToken 検証対象のIDトークン
     * @return 検証に成功した場合は ID Tokenのペイロード
     *
     * @throws InvalidTokenException ID Tokenの値が不正なので認証に失敗した
     */
    public DecodedJWT verify(String idToken) throws InvalidTokenException {
        DecodedJWT decodedToken = JWT.decodeJwt(idToken);

        // cognitoのユーザプールで署名された事を確認する
        String iss = decodedToken.getIssuer();
        if (!jwtTokenIssuer().equals(iss)) {
            throw new InvalidTokenException("ID トークンの発行者が対象のシステムではありません。iss=" + iss, idToken);
        }

        //  ID トークンの用途が「ID」であることを確認します。
        String tokenUse = decodedToken.getClaim("token_use").asString();
        if (!"id".equals(tokenUse)) {
            throw new InvalidTokenException("ID トークンの用途が ID ではありません。token_use=" + tokenUse, idToken);
        }

        // 署名のアルゴリズムを確認します。
        String alg = decodedToken.getAlgorithm();
        if (!"RS256".equals(decodedToken.getAlgorithm())) {
            throw new InvalidTokenException("ID トークンの署名アルゴリズムが対応していないものです。alg =" + alg, idToken);
        }

        // payloadと署名を検証します。
        DecodedJWT decodedJWT = null;
        if ((decodedJWT = tokenVerify(decodedToken)) == null) {
            throw new InvalidTokenException("ID Tokenの検証に失敗しました。", idToken);
        }

        return decodedJWT;
    }

    /**
     * auth0の のライブラリを利用して 検証を行う
     *
     * @param kid ID トークンのヘッダーにある キーID
     * @return nullでなければ デコードされた ID トークン
     *
     * @throws InvalidTokenException 検証に失敗した
     */
    private DecodedJWT tokenVerify(DecodedJWT jwToken) throws InvalidTokenException {

        try {
            DecodedJWT verified = getVerifier(jwToken.getKeyId()).verify(jwToken);
            return verified;
        } catch (Exception e) {
            throw new InvalidTokenException(e);
        }
    }

    /**
     * JWTVerifier のインスタンスを取得する。
     *
     * <p>
     * JWTVerifier は ver.3 からスレッドセーフになったので再利用する。
     * ただし、署名に使われた RSAキーペアが更新される可能性を考えて、定期的に更新する
     * </p>
     *
     * @param kid 署名に使われたキーID
     *
     * @return
     *
     * @throws MalformedURLException
     * @throws JwkException
     */
    private JWTVerifier getVerifier(String kid) throws MalformedURLException, JwkException {
        if (verifier != null && System.currentTimeMillis() < verifierExpire) {
            // 有効期限内ならそのまま使う
            return verifier;
        }
        synchronized (JWT) {
            // ロックを獲得したので念のためにもう一度確認してからインスタンスを生成する
            if (verifier != null && System.currentTimeMillis() < verifierExpire) {
                return verifier;
            }

            UrlJwkProvider http = new UrlJwkProvider(new URL(jwksUrl()));
            GuavaCachedJwkProvider provider = new GuavaCachedJwkProvider(http);
            Jwk jwk = provider.get(kid);

            Algorithm algorithm = Algorithm.RSA256((RSAPublicKey) jwk.getPublicKey(), null);
            verifier = JWT.require(algorithm)
                    .withIssuer(jwtTokenIssuer())
                    .build();

            // JWTVerifier の寿命を延ばす
            verifierExpire = System.currentTimeMillis() + VERIFIER_LIVE_MILISEC;

            Calendar expire = GregorianCalendar.getInstance();
            expire.setTimeInMillis(verifierExpire);
            Logger.info("JWTVerifierのインスタンスを生成しました。期限は"
                    + new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS").format(expire.getTime()));

        }

        return verifier;

    }

    /**
     * ID トークンの発行者を取得します
     *
     * @return
     */
    private String jwtTokenIssuer() {
        return String.format("https://cognito-idp.%s.amazonaws.com/%s", AWS_REGION, AWS_COGNITO_USER_POOL_ID);
    }

    /**
     * JSON Web トークン (JWT) セットのURLを取得します。
     *
     * @return
     */
    private String jwksUrl() {
        return jwtTokenIssuer() + "/.well-known/jwks.json";
    }

}

InvalidTokenException.java
InvalidTokenException.class
public class InvalidTokenException extends Exception {

    public InvalidTokenException(String message, String idToken) {
        super(message + " token is " + idToken);
    }

    public InvalidTokenException(Throwable e) {
        super(e);
    }
}

使う側
    try{
        // TODO IdTokenValidator はスレッドセーフなので static にする
        DecodedJWT payload = new IdTokenValidator().verify(idToken);
        String cognitoUserName = payload.getClaim("cognito:username").asString();

        // 必要な処理

    }catch (InvalidTokenException e) {
        Logger.error("ID トークンの検証に失敗しました", e);
        badRequest("IdTokenの値が不正ですよ");
    }

参考

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

[初心者コピペ用]LaravelをAWSのEC2へデプロイ

前提

  • 2020年1月4日に確認したものです。
  • AWSのアカウント作成済
  • プロジェクトをGitHubにpush済

環境

  • macOS Catalina 10.15.2
  • Apache 2.4
  • PHP 7.1.33
  • MySQL 5.7
  • Laravel 5.8

1. EC2インスタンスの起動

  • EC2コンソールで作成(「公式チュートリアル」が分かりやすかったです)
  • 基本的に無料利用枠(下記の項目以外はデフォルト値)
設定項目 設定した内容
Amazon マシンイメージ (AMI) Amazon Linux 2でなく、Amazon Linux
インスタンスタイプ t2.micro
  • Linux2だと、手順が異なる公式ドキュメント

  • インスタンス作成の最後に、SSH接続に必要なキーペアを生成or設定

  • キーペア(pemファイル)は、~/.sshフォルダに入れておくと良い

2. EC2内で作業

2-1. SSHでEC2に接続

SSHとは. SSH(Secure Shell)とは、安全に通信を行って、ネットワークに接続された機器を遠隔操作するための通信手段(プロトコル)の1つ

※ 参照:初心者がSSHについて学ぶ(´・ω・`)

$ ssh -i [キーペア(pemファイル)を置いた場所のパス] ec2-user@[パブリックDNS or パブリックIP]
  • iオプションで、上記で生成or設定したpemファイルを指定する
  • ec2-userは、デフォルトのユーザー名。最初はこのユーザー名を使う
  • パブリックDNS or パブリックIPは、EC2コンソール画面で確認できる
  • 初回接続時のみ、yes/noを聞かれる

2-2. Apache, PHP, MySQLのインストール

  • yumのアップデートは忘れずに!(パッケージを最新にする)
  • yumはyオプションを付けることで、問い合わせ全てにYesと答えるため、yes/noがいちいち聞かれなくなります。
$ sudo yum update -y
$ sudo yum install -y httpd24 php71 php71-mbstring php71-zip php71-fpm php71-mysqlnd mysql57-server

Laravel 5.8のサーバ要件

2-3. Apacheを起動

$ sudo service httpd start

※ Linux2だと、systemctlコマンドが使える

この時点で、ブラウザでパブリック IPにアクセスすると、Apacheの画面が表示される。
EC2コンソール画面のセキュリティグループのインバウンドで、httpの80ポートを空けておくことを忘れずに
スクリーンショット 2020-01-04 18.42.21.png

# システムが再起動するたびにApacheが起動するように設定
$ sudo chkconfig httpd on

# 設定の確認
$ chkconfig --list httpd

2-4. ec2-userのファイル操作の許可を設定

参照:公式チュートリアル

Amazon Linux Apache ドキュメントルートは /var/www/html であり、デフォルトでは root によって所有されます。

そのため、ec2-userにファイル操作の権限を設定する必要がある。

# ec2-userをapacheグループに追加
$ sudo usermod -a -G apache ec2-user

# いったんログアウトして、再度ログイン
$ exit
$ ssh -i [キーペアのpemファイルを置いた場所のパス] ec2-user@[パブリックDNS or パブリックIP]

# /var/www とそのコンテンツのグループ所有権を apache グループに変更
$ sudo chown -R ec2-user:apache /var/www

# グループに、/var/wwwの書き込み許可追加
$ sudo chmod 2775 /var/www

# /var/www とサブディレクトのディレクトリ許可を変更
$ find /var/www -type d -exec sudo chmod 2775 {} \;

# /var/www とサブディレクトリのファイル許可を変更
$ find /var/www -type f -exec sudo chmod 0664 {} \;

2-5. composer自身のインストール

& curl -sS https://getcomposer.org/installer | php

# composerコマンドのパスを通す
$ sudo mv composer.phar /usr/local/bin/composer

# パス確認(/usr/local/bin/composerと表示されればOK)
$ which composer

2-6. Laravelプロジェクトをgit clone

sudo yum install git
cd /var/www
git clone [URL]

2-7. Apacheの設定変更

http.confファイルのDocumentRootの変更

Laravelでは、プロジェクト内のpublicディレクトリをドキュメントルートに指定する必要がある

$ sudo vi /etc/httpd/conf/httpd.conf

DocumentRoot “/var/www/html”の箇所をDocumentRoot “/var/www/プロジェクト名/public”に変更

http.confファイルに以下のDirectoryを追加(.htaccessの有効化)

<Directory /var/www/プロジェクト名/public>
 AllowOverride All
</Directory>

Apacheの設定変更後は、再起動を忘れずに!

$ sudo service httpd restart

2-8. パッケージのインストール

$ cd /var/www/[プロジェクトのフォルダ名]

# composer.jsonファイルがない場合
$ composer init

# vendorディレクトリが生成される
$ composer install

2-9. Laraveプロジェクトの設定

ディレクトリのパーミッション変更

Laravelでは、storage下とbootstrap/cacheディレクトリをWebサーバから書き込み可能にする必要がある

$ sudo chmod -R 777 /var/www/[プロジェクト名]/storage
$ sudo chmod -R 775 /var/www/[プロジェクト名]/bootstrap/cache

.envファイルの作成

cp .env.example .env

# .envファイルにある「APP_KEY」(アプリケーションキー)の生成
php artisan key:generate
APP_NAME=Laravel
APP_ENV=production
APP_KEY=base64:xxxxxxx(php artisan key:generateで生成される)
APP_DEBUG=false
APP_URL=http://[パブリックIP]

2-10. DBの設定、作成

MySQL側

# MySQL起動
$ sudo service mysqld start

# MySQLの初期設定
$ sudo mysql_secure_installation

# システムが再起動するたびにMySQLが起動するように設定
$ sudo chkconfig mysqld on

# データベース作成
$ mysql -u root -p
> 設定したパスワード入力
> create database [データベース名];
> show databases;
mysql_secure_installationコマンドで聞かれること
  • パスワード検証プラグインのセットアップ
  • パスワード
  • 匿名ユーザーアカウントの削除
  • rootユーザーのリモートログインの許否
  • testデータベースの削除

Laravel側

# 「DB_DATABASE」など、DB情報を設定しておく
$ sudo vi .env

DB_DATABASE=[作成したデータベース名]
DB_USERNAME=root
DB_PASSWORD=[設定したパスワード]
$ php artisan migrate
$ php artisan db:seed

参考にさせて頂いた記事

【Laravel】AWSにLaravelをインストールする
Laravel:EC2-PHP72-Apacheで環境を作成する
MySQL5.7 にて root のパスワード変更などの初期設定をする

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

LaravelをAWSのEC2へデプロイしてみた

前提

  • 2020年1月4日に確認したものです。
  • AWSのアカウント作成済
  • プロジェクトをGitHubにpush済

環境

  • macOS Catalina 10.15.2
  • Apache 2.4
  • PHP 7.1.33
  • MySQL 5.7
  • Laravel 5.8

1. EC2インスタンスの起動

  • EC2コンソールで作成(「公式チュートリアル」が分かりやすかったです)
  • 基本的に無料利用枠(下記の項目以外はデフォルト値)
設定項目 設定した内容
Amazon マシンイメージ (AMI) Amazon Linux 2でなく、Amazon Linux
インスタンスタイプ t2.micro
  • Linux2だと、手順が異なる公式ドキュメント

  • インスタンス作成の最後に、SSH接続に必要なキーペアを生成or設定

  • キーペア(pemファイル)は、~/.sshフォルダに入れておくと良い

2. EC2内で作業

2-1. SSHでEC2に接続

SSHとは. SSH(Secure Shell)とは、安全に通信を行って、ネットワークに接続された機器を遠隔操作するための通信手段(プロトコル)の1つ

※ 参照:初心者がSSHについて学ぶ(´・ω・`)

$ ssh -i [キーペア(pemファイル)を置いた場所のパス] ec2-user@[パブリックDNS or パブリックIP]
  • iオプションで、上記で生成or設定したpemファイルを指定する
  • ec2-userは、デフォルトのユーザー名。最初はこのユーザー名を使う
  • パブリックDNS or パブリックIPは、EC2コンソール画面で確認できる
  • 初回接続時のみ、yes/noを聞かれる

2-2. Apache, PHP, MySQLのインストール

  • yumのアップデートは忘れずに!(パッケージを最新にする)
  • yumはyオプションを付けることで、問い合わせ全てにYesと答えるため、yes/noがいちいち聞かれなくなります。
$ sudo yum update -y
$ sudo yum install -y httpd24 php71 php71-mbstring php71-zip php71-fpm php71-mysqlnd mysql57-server

Laravel 5.8のサーバ要件

2-3. Apacheを起動

$ sudo service httpd start

※ Linux2だと、systemctlコマンドが使える

この時点で、ブラウザでパブリック IPにアクセスすると、Apacheの画面が表示される。
EC2コンソール画面のセキュリティグループのインバウンドで、httpの80ポートを空けておくことを忘れずに
スクリーンショット 2020-01-04 18.42.21.png

# システムが再起動するたびにApacheが起動するように設定
$ sudo chkconfig httpd on

# 設定の確認
$ chkconfig --list httpd

2-4. ec2-userのファイル操作の許可を設定

参照:公式チュートリアル

Amazon Linux Apache ドキュメントルートは /var/www/html であり、デフォルトでは root によって所有されます。

そのため、ec2-userにファイル操作の権限を設定する必要がある。

# ec2-userをapacheグループに追加
$ sudo usermod -a -G apache ec2-user

# いったんログアウトして、再度ログイン
$ exit
$ ssh -i [キーペアのpemファイルを置いた場所のパス] ec2-user@[パブリックDNS or パブリックIP]

# /var/www とそのコンテンツのグループ所有権を apache グループに変更
$ sudo chown -R ec2-user:apache /var/www

# グループに、/var/wwwの書き込み許可追加
$ sudo chmod 2775 /var/www

# /var/www とサブディレクトのディレクトリ許可を変更
$ find /var/www -type d -exec sudo chmod 2775 {} \;

# /var/www とサブディレクトリのファイル許可を変更
$ find /var/www -type f -exec sudo chmod 0664 {} \;

2-5. composer自身のインストール

& curl -sS https://getcomposer.org/installer | php

# composerコマンドのパスを通す
$ sudo mv composer.phar /usr/local/bin/composer

# パス確認(/usr/local/bin/composerと表示されればOK)
$ which composer

2-6. Laravelプロジェクトをgit clone

sudo yum install git
cd /var/www
git clone [URL]

2-7. Apacheの設定変更

http.confファイルのDocumentRootの変更

Laravelでは、プロジェクト内のpublicディレクトリをドキュメントルートに指定する必要がある

$ sudo vi /etc/httpd/conf/httpd.conf

DocumentRoot “/var/www/html”の箇所をDocumentRoot “/var/www/プロジェクト名/public”に変更

http.confファイルに以下のDirectoryを追加(.htaccessの有効化)

<Directory /var/www/プロジェクト名/public>
 AllowOverride All
</Directory>

Apacheの設定変更後は、再起動を忘れずに!

$ sudo service httpd restart

2-8. パッケージのインストール

$ cd /var/www/[プロジェクトのフォルダ名]

# composer.jsonファイルがない場合
$ composer init

# vendorディレクトリが生成される
$ composer install

2-9. Laraveプロジェクトの設定

ディレクトリのパーミッション変更

Laravelでは、storage下とbootstrap/cacheディレクトリをWebサーバから書き込み可能にする必要がある

$ sudo chmod -R 777 /var/www/[プロジェクト名]/storage
$ sudo chmod -R 775 /var/www/[プロジェクト名]/bootstrap/cache

.envファイルの作成

cp .env.example .env

# .envファイルにある「APP_KEY」(アプリケーションキー)の生成
php artisan key:generate
APP_NAME=Laravel
APP_ENV=production
APP_KEY=base64:xxxxxxx(php artisan key:generateで生成される)
APP_DEBUG=false
APP_URL=http://[パブリックIP]

2-10. DBの設定、作成

MySQL側

# MySQL起動
$ sudo service mysqld start

# MySQLの初期設定
$ sudo mysql_secure_installation

# システムが再起動するたびにMySQLが起動するように設定
$ sudo chkconfig mysqld on

# データベース作成
$ mysql -u root -p
> 設定したパスワード入力
> create database [データベース名];
> show databases;
mysql_secure_installationコマンドで聞かれること
  • パスワード検証プラグインのセットアップ
  • パスワード
  • 匿名ユーザーアカウントの削除
  • rootユーザーのリモートログインの許否
  • testデータベースの削除

Laravel側

# 「DB_DATABASE」など、DB情報を設定しておく
$ sudo vi .env

DB_DATABASE=[作成したデータベース名]
DB_USERNAME=root
DB_PASSWORD=[設定したパスワード]
$ php artisan migrate
$ php artisan db:seed

参考にさせて頂いた記事

【Laravel】AWSにLaravelをインストールする
Laravel:EC2-PHP72-Apacheで環境を作成する
MySQL5.7 にて root のパスワード変更などの初期設定をする

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

AWSサービスの要点まとめ EC2編

はじめに

AWSの認定試験を受験するにあたって、各AWSのサービスを幅広く理解する必要があったためサービスごとに抑えるべきポイント等をまとめてみました。
今回はEC2についてです。

※情報は2019年12月31日時点のものになります。ご了承ください。

概要

  • AWS上で起動する仮想サーバー
  • 購入時に起動するインスタンスタイプを選択できる
  • インスタンスタイプによって仮想サーバーのスペックが変わる(CPUやメモリなど)
  • sshなどでログインする際にはキーペア(pemキー)が必要

料金

選択されたインスタンスタイプ、購入方法によって異なる
基本はインスタンスを起動させている時間(秒単位)に応じて料金が発生する

購入方法

購入方法は以下になります。

オンデマンドインスタンス

  • 割引なしでインスタンスを購入する方法
  • 処理が中断して落ちない

リザーブドインスタンス

  • オンデマンドよりも安い値段でインスタンスを購入する方法
  • 処理が中断して落ちる可能性がある

ハードウェア占有インスタンス(Dedicated Instance)

  • 独立したハードウェアを購入する方法 オンデマンドなどでは同じハードウェアで複数インスタンスが同居して購入される可能性がある
  • 物理サーバーの選択は不可能

専用ホスト(Dedicated Hosts)

  • 独立したハードウェアを購入する方法
  • 物理サーバーの選択は可能
  • BYOL(Bring Your Own License)型のソフトウェアライセンスを持ち込める

Saving Plan

  • 1~3年で一定のCPU使用料で契約する方法

AMI

EC2を起動するためのテンプレートのようなもの
この事前にソフトウェアなどをインストールしたインスタンスを立ち上げたいときに便利

  • AMIリストを取得するにはDescribeImagesを実行する
  • 別のリージョンでAMIを使用する場合は、AMIを別のリージョンにコピーする必要がある
  • AMIはS3に作成される

ネットワーク

ネットワーク関連についてまとめます。

プライベートIP

  • EC2インスタンスを起動したサブネット内で割り当てられたIPアドレス
  • 起動時に指定することができる

パブリックIP

  • AWSによって割り当てられるグローバルIPアドレス
  • EC2インスタンスが停止→起動をすると新しいグローバルIPアドレスが割り当てられる
  • EC2インスタンスが再起動してもグローバルIPアドレスは変わらない
  • EC2インスタンスからインターネットにアクセスする場合はパブリックIPが割り当てられるように設定する必要がある

Elastic IP

  • AWSが用意したグローバルIPアドレス
  • EC2インスタンスにアタッチする必要がある
  • EC2インスタンスが再起動(停止→起動)しても同一のグローバルIPアドレスを利用できる

ENI(Elastic Network Interface)

  • 仮想ネットワークインターフェース
  • 複数のIPアドレスが割り当てられる

プレイスメントグループ

EC2同士の通信を高速化できるEC2のグループ設定

  • EC2インスタンスは同じアベイラリティゾーンである必要がある

セキュリティグループ

EC2インスタンスのアクセス制限を行う機能

  • EC2インスタンスへのアクセスの許可のみを管理する(拒否の指定はできない)
  • インバウンドが許可されると自動的にアウトバウンドも許可される
  • デフォルト設定ではインバウンドの許可がされていない状態(つまり、すべてのインバウンドは拒否される)

インスタンスメタデータ

curlで取得できるインスタンスの情報

curl http://(IPアドレス)/latest/meta-data/instance-id

ストレージ関連

EC2のストレージ関連についてまとめます。

インスタンスストア

EC2のローカルディスク

  • EC2インスタンスが停止または削除されるとデータが削除される
  • EC2インスタンスが休止中のときはデータが保持される
  • インスタンスストアのデータを引き続き保持したい場合は、その時点のAMIを取得する方法が有効

EBS(Elastic Block Store)

EC2にアタッチできるブロックストレージ

  • EC2を停止してもEBSは削除されない
  • 同じリージョンであれば同じEC2インスタンスに複数のEBSをアタッチできる
  • 同じEBSを複数のインスタンスに同時にアタッチできない
  • EBS-backedインスタンスはインスタンスの停止と再開ができるが、Instance store-backedインスタンスではできない
  • ボリュームを暗号化できる
  • EBSスナップショットでバックアップを作成できる

EBSのボリュームタイプ

Provisioned IOPS SSD

  • I/Oの負荷が大きくても耐えられる(データベース用途など)
  • IOPSの性能を指定したボリュームを作成可能(追加料金)

汎用SSD

  • コスパがいい汎用的なSSD

スループット最適化HDD

  • 高いスループットが期待できるHDD

コールドHDD

  • 性能は低いが安い
  • 古いデータのバックアップなどに向いてる

マグネティック

  • 旧世代のボリュームタイプ

※IOPSとスループットの違い

IOPSとは

  • ストレージが1秒あたりに処理できるI/O(書き込み・読み込み)アクセスの数。
  • 一般的にHDDは1分あたりの回転数(PRM)に制限があるためIOPSは低い

スループットとは

  • 1秒間の最大データ転送量

EBS最適化インスタンス

EC2、EBS間の回線が専用回線で繋がっているインスタンス

ネットワークがボトルネックになっているときに有効

特定のインスタンスタイプでのみ対応しているので、すべてのインスタンスで利用可能なわけではない

その他の豆知識

  • OSを再起動させたい時はReboot(再起動)を行う
  • EC2インスタンスを起動する際に実行したいシェルスクリプトを指定することができる(ユーザーデータ)
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

AWSメモ

AWSメモ

初期設定

AWSのアカウントを作成できる
料金アラート設定

VPCネットワークを構築

  • 全体像

    • パブリックサブネット(ワードプレス等)とはインターネットと通信できるサブネットのこと。一般的にブラウザで展開される申し込みフォームのWebサーバー等
    • プライベートサブネット(DB等)とはインターネットと通信できないサブネットのこと。
  • AWSネットワークの概念

    • リージョンの選択
    • リージョンによって使えるサービスが異なる(アメリカが機能大い、日本の場合は東京がおすすめ(通信が早い))
    • アベイラビリティゾーン
    • 独立したデータセンターのこと
    • 複数設置されている
    • VPC
    • インターネット上に仮想ネットワークを作成できるサービス
    • とても重要なサービス
    • サブネット
    • VPCを細かく区切ったネットワーク
  • ネットワークのIPアドレスを決める

    • IPアドレスとはインターネット上の住所
    • 一意性
    • 32ビットの整数値(2進数)→読みにくいので8ビットずつの4つの組みにわけ10進数で表示 2進数とは パソコン初心者講座
    • IPアドレスにはパブリックとプライベートがある
    • パブリックはインターネットに接続する際利用する。ICANNという団体が管理していて全て一意のアドレス
    • プライベートはインターネットで使用されないアドレス。範囲が決まっていて一意でなくても良い
    • IPアドレスの範囲
    • ネットワーク部・ホスト部(可変)に区分けすることで範囲を表現できる
  • VPCを作成する

  • サブネットを作成

  • ルーティングを設定

    • ルーターを通じてネットワークがどのIPアドレスにあるかを管理
    • ルートテーブルは「宛先のIPアドレス」と「次のルーター(AWSではターゲット)」という書式で設定する
    • local→自身のネットワーク(インターネットに接続できない)
    • インターネットの接続にはインターネットゲートウェイの作成が必要
    • ルートテーブルは各サブネットに対して設定できる。
    • サブネットやインターネットゲートウェイ間にはルーターが動いている
  • ネットワーク設計で考慮すべきポイント

    • プライベートIPアドレス範囲から指定する
    • 作成後は変更できないので、大きめの設定(/28~/16、/16が推薦)
    • オンプレミスや他VPCのレンジと重複いないように気をつける。
    • 異なるシステムの場合はアカウントを分ける
    • 同一システムの各環境は、VPCとアカウントどちらを分けるか?→同一アカウントで、VPCとリージョンを分けるのがよい(どちらでもよい)

参考
パブリックサブネットとプライベートサブネットの違い | システム担当の教科書

【EC2】Webサーバーを構築

  • EC2インスタンスを設置する

    • EC2とは
    • AWSクラウド上の仮想サーバー。インスタンスというのはEC2から立てられたサーバーの事。
    • 特徴
      • 数分で起動し、1時間または秒単位の従量課金。
      • サーバーの追加・削除、マシンスペック変更も数分で可能。
      • OSより上のレイヤについては自由に設定できる。
    • 作成手順
      • AMIの選択
      • AMIとは
        • AmazonMachineImageの略。インスタンスに必要な情報が入ったOSのイメージ。
      • インスタンスタイプの選択
      • インスタンスタイプとは
        • サーバーのスペックを定義したもの- インスタンスタイプにより、料金が異なる
      • ストレージの追加
      • サーバーにくっつけるデータの保管場所。EC2のストレージには2種類ある。
        • 1.EBS(高い可用性と耐久力を持つストレージ、他のインスタンスに付け替え可能、EC2インスタンスをStop/TerminateしてもEBSは保持可能、Snapshotを取得しS3に保存可能、EBSの費用が別途発生、OSやDBなどの永続性と耐久性が必要なデータを置く)
        • 2.インスタンスストア(インスタンス専用の一時的なストア、他のインスタンスに付け替えることができない、EC2インスタンスをStop/Terminateするとクリアされる、追加費用なし、なくなってはいけないデータは置かない、一時ファイル・キャッシュなどなど失われても問題ないデータを置く)
      • セキュリティグループの設定
      • SSHキーペアの設定
  • SSHについて

    • サーバーにログインするとは
    • 離れたところにあるサーバーにはいって、自分のパソコンから操作すること
    • SSHでログインすると自分がまるでWebサーバーの目の前にいるかの様に自分のコンピューターからWebサーバーを操作できる。
    • SSHとは
      • サーバーにセキュアに接続する仕組み - 暗号化されている
  • 公開会議認証について

    • 誰でもサーバーに入れると困るので、サーバーの作成者本人だけがログインできるよう、EC2ではSSHログイン時に公開鍵認証を行なっている
    • 公開鍵認証とは
    • サーバーへのログイン時に認証を行う仕組み。
    • ユーザー名とパスワード使用した認証と比べ、よりセキュリティが高い
    • 公開鍵暗号(秘密鍵と公開鍵)を用いて認証を行う。
    • 公開鍵はサーバーが保有。秘密鍵を持っているユーザーだけログイン可能。
    • 公開鍵暗号の「暗号」とは?
    • イメージは南京錠
  • SSHでECインスタンスに接続する

  • ポート番号について

    • SSHでログインしてサーバーを操作できるのはなぜ?→ サーバー状でSSHぜつ族を受け入れコマンドを受け付けるプログラム(sshd)が動いているから
    • サーバーにはたくさん起動しているプログラムがSSHのリクエストを受け付けるがどうやって選別しているのか?→ポート番号で選別している
    • ポート番号はプログラムのアドレス。同一コンピューターで通信を行うプログラムを識別するときに利用される。
    • 例)SSH:22
    • どうやってポート番号を決めるか
    • 2つキメ方がある。
    • 1.標準で決められている番号
      • ウェルノウンポート番号
      • 代表的なプログラムが使うポート番号はあらかじめ決められている。
    • 2.動的に決められている番号
      • サーバーを提供する側(サーバー)はポート番号が決まっている必要があるが、クライアント側のポート番号は決まっていなくて良い
      • クライアントのポート番号は、OSが他のポート番号と被らない様にランダムに決める。
[ec2-user@ip-10-0-10-10 ~]$ sudo lsof -i -n -P
COMMAND   PID     USER   FD   TYPE DEVICE SIZE/OFF NODE NAME
rpcbind  2689      rpc    6u  IPv4  16847      0t0  UDP *:111 
rpcbind  2689      rpc    7u  IPv4  16848      0t0  UDP *:736 
rpcbind  2689      rpc    8u  IPv4  16849      0t0  TCP *:111 (LISTEN)
rpcbind  2689      rpc    9u  IPv6  16850      0t0  UDP *:111 
rpcbind  2689      rpc   10u  IPv6  16851      0t0  UDP *:736 
rpcbind  2689      rpc   11u  IPv6  16852      0t0  TCP *:111 (LISTEN)
chronyd  2698   chrony    1u  IPv4  17108      0t0  UDP 127.0.0.1:323 
chronyd  2698   chrony    2u  IPv6  17109      0t0  UDP [::1]:323 
dhclient 2919     root    6u  IPv4  17829      0t0  UDP *:68 
dhclient 3036     root    5u  IPv6  18138      0t0  UDP [fe80::4ab:97ff:fe52:17c]:546 
master   3173     root   13u  IPv4  19031      0t0  TCP 127.0.0.1:25 (LISTEN)
sshd     3390     root    3u  IPv4  20731      0t0  TCP *:22 (LISTEN)
sshd     3390     root    4u  IPv6  20740      0t0  TCP *:22 (LISTEN)
sshd     4829     root    3u  IPv4 108709      0t0  TCP 10.0.10.10:22->114.191.10.30:51866 (ESTABLISHED)
sshd     4846 ec2-user    3u  IPv4 108709      0t0  TCP 10.0.10.10:22->114.191.10.30:51866 (ESTABLISHED)

(LISTEN)は待ち受けているポート
(ESTABLISHD)は通信中相手と通信中のポート

  • Apacheをインストールする

Apacheとは
- 世界中で使用されているWebサーバーソフトウェア
- サーバーのにApacheをインストールすることでWebサーバーとしての機能(レスポンス等)ができる

Apacheとは?Webサーバーの仕組みと人気サーバーソフトを徹底解説 | カゴヤのサーバー研究室
アパッチ (Apache)とは|「分かりそう」で「分からない」でも「分かった」気になれるIT用語辞典

[ec2-user@ip-10-0-10-10 ~]$ sudo yum update -y

yumの更新
yum linuxのパッケージ管理ツール(インストールや更新等)
-y はyesオプション。

[ec2-user@ip-10-0-10-10 ~]$ sudo yum -y install httpd

httpdはアパッチを構成する実行コマンド

[ec2-user@ip-10-0-10-10 ~]$ sudo systemctl start httpd.service

起動の確認

[ec2-user@ip-10-0-10-10 ~]$ sudo systemctl enable httpd.service

アパッチを自動起動設定する
- ファイアウォールを設定する

  • ファイアウォールとは
    • ネットワークを不正アクセスから守る為に「通してよい通信だけを通して、それ以外は通さない」機能の略称。

Elastic IPアドレスでIPアドレスを固定する

  • ElasticIPアドレスとは EC2インスタンスのパブリックIPは、起動・停止すると別のIPアドレスが割り当てられる。ElasticIPアドレスを利用すると、IPアドレスを固定できる。
  • 特徴
    • そのインスタンスを削除するまでは、ずっとそのIPアドレスを使用することができる。
    • ElasticIPアドレスは、EC2に関連付けられていて、そのインスタンスが起動中であれば無料。逆に起動してなければ課金される。

【Route53】ドメインを登録する

構築するもの

ドメイン名でWebサーバーにアクセスできるようにする

ドメインについて

www.example.co.jp
第4レベルドメイン.第3レベルドメイン.第2レベルドメイン.トップドメイン

ドメインレベルに応じて各組織が管理している。

ドメイン名でアクセスできる理由

DNSについて
  • DNSとはドメイン名をIPアドレスに変換するもの
  • ネームサーバーとフルリゾバの2つから構成されている
    • ①ネームサーバー
    • ドメイン名とそれに紐づくIPアドレスが登録されているサーバー
    • ドメインの階層ごとにネームサーバーが配置され、そのネームサーバーが配置された階層のドメインに関する情報を管理する。
    • ②フルリゾバ(秘書の様なもの)
    • 「どのドメインに紐づくサーバーか教えて」とおい合わせると、色々なネームサーバーに聞いてIPアドレスを調べて教えてくれる。
Route53について
  • Route53とは
    • AWSのDNSサービス。ネームサーバーの役割を果たす。
    • 重要概念
    • ホストゾーン
      • DNSのリソースレコードの集合。ゾーンファイルの様なもの
    • ルーティングポリシー
      • Route53がRecordSetに対してどの様にルーティングを行うかを決める
      • シンプル、加重、レイテンシー、位置情報、フェイルオーバー等がある
    • ヘルスチェック
      • サーバーの稼働状況をチェック。
Route53でDNSを設定する
mbair:~ okadaatsuyoshi$ ssh -i ~/Desktop/aws-and-infra-ssh-key.pem ec2-user@52.196.118.157

ec2へログイン

[ec2-user@ip-10-0-10-10 ~]$ dig aws-and-infraa.work NS +short

で現在のネームサーバーを確認。
現在はデフォルトでお名前.comのネームサーバーになっているので変更する。

【RDS】DBサーバーを構築する

RDSについて
  • AWSがフルマネージメントでDBの管理やってくれるので運用が楽。
  • 複数のアベイラビリティーゾーンにプライベートサブネットを作成することが推奨されている。

    • RDSとは
    • フルマネージドなリレーショナルデータベース(いわゆるDB)のサービス。
    • メリット
    • - 構築の手間の軽減 - 運用の手間の軽減 - AWSエンジニアによるデータベース設計のベストプラクティスを適用 - ➡️コア機能の開発に注力できる
    • 各種設定グループ
    • DBパラメータグループ:DB設定値を制御
    • DBオプショングループ:RDSへの機能追加を制御
    • DBサブネットグループ:RDSを起動させるサブネットを制御
    • 特徴
    • 可用性の向上
      • 複数のアベイラビリティゾーンを設定することで簡単にリスクを軽減
    • パフォーマンスの工場が楽
      • リードレプリカを簡単に構築
      • 書き込みようのマスターと読み込み用のリードレプリカを別々で作成できるので読み込みの速度が向上向上
    • 運用不可の軽減
      • 自動バックアップ(1日1回スナップショット)
      • リストア(スナップショットを元にDBインスタンスを作成)
      • 自動的なソフトウェアメンテナンス
      • メンテナンスウィンドウで指定した曜日・時間帯にアップデートを自動実施
      • 各種メトリクスを60秒間隔で取得・確認可能
プライベーサブネットを作成
RDSを設置

RDSの作成準備
- セキュリティグループの作成(EC2)
- DBサブネットグループの作成
- DBパラメータグループの作成
- DBオプショングループの作成(機能を設定)

参考教材
https://www.udemy.com/course/aws-and-infra/

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

技術ブログはじめました

みなさん、はじめまして!
音楽とアニメとハイボールが大好きな Web エンジニアの yasu と申します!

このたび、超個人的嗜好で厳選したお気に入りの音楽を Apple Music のプレイリスト形式で紹介していく音楽ブログ「Fav Music」の構築・運用過程で得た技術的知見を qiita にアウトプットさせていただくことにしました。

僕がここでアウトプットした技術情報がいつか誰かの助けになったら嬉しいです :)

今回はご挨拶がわりに僕が Fav Music を構築・運用するために使用している技術や製品をご紹介させていただきます。

なお、Fav Music の全てのソースコードは GitHub でも公開してますので興味のある方は合わせてご参照ください。
<(*_ _)>

Fav Music を構築するために使用している技術や製品

使用した技術や製品をいろいろ列挙しましたけど、重要なのは Jekyll だけですね笑

今流行りの静的サイトジェネレーターってやつですw

最初は WordPress でサイトを構築したんですけど、静的サイトジェネレーターをいろいろ試してみて最終的に Jekyll にしました。

Jekyll の他にも

を試してみましたが、Jekyll を採用した決め手は、タグの一覧ページのページング機能が割と簡単に実現できたことです(各静的サイトジェネレーターのデフォルトの機能では意外と実現するのが難しい部分です)。

静的サイトジェネレーターで生成した静的サイトは WordPress で構築した動的サイトと比較してページングと検索の機能が弱い(というか自分で実装しないといけない)ので、これから静的サイトジェネレーターを使おうと思っている方はまず最初にその辺の使い勝手を徹底的に調査しておいた方がいいかもしれません。

ちなみに、Fav Music ではまだ検索機能は実装してません?

Adobe XD はキャッチアイ画像を作成するのに使ってるだけです。僕はデザインツールには詳しくないのでアレですが、Adobe XD はサクサク動いて使ってて気持ちいいですv

Visual Studio Code はコード(HTML, CSS, JavaScript, YAML, Ruby, Liquid)と記事(Markdown)を編集するのに使ってるのと、Git とか Shell コマンドも内臓ターミナルから叩いてるので、ぶっちゃけほとんどこの中にいますw

Google Chrome は、もちろん表示の確認とデバッグ(スタイルの調整)に使ってます。

Fav Music を運用するために使用している技術や製品

最初に WordPress でサイトを構築したときは EC2RDSALB を使ってガチで半年ほど運用してましたが、そもそも静的なコンテンツしかないんだから S3 で十分じゃね?ということに気付き、先日 S3 に切り替えました (笑)

これで万が一 Yahoo 砲が来ても耐えれますw

WordPress から S3 の静的 Web サイトホスティングに切り替える時にちょっと困ったことは、S3 ではページ URL の拡張子(.html)を省略できないっていうことでした(ディレクトリ URL の index.html は省略できます)。

対策はいくつかあるみたいですが、僕は単純に内部リンクは拡張子(.html)付きで書いて、WordPress の時に使われていた拡張子なしの URL は新しい URL に Rewrite (S3 側に Redirection rules として登録) するようにしました。

このやり方が一番良いやり方だったとは思えないので、もう少し調べて別の記事にまとめたいと思ってます。

S3CloudFront でブログを運用した場合の実際のコスパについてもみなさん気になるところだと思うので近々公開したいと思ってますが、幸か不幸か全くアクセスがないサイトなので (恥)、参考になる数字が出せる日が来るかどうかは怪しいものです (笑)

まとめ

以上、僕が Fav Music を構築・運用するために使用している技術や製品をご紹介させていただきましたがいかがだったでしょうか。

今回は技術情報としてはほとんど価値のない記事だったと思うので、次回はもう少し役に立つ情報をアウトプットしたいと思います?

ではまた ( ⸝⸝•ᴗ•⸝⸝ )੭⁾⁾

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

AWS+NodeJSでサーバレスな環境構築④

はじめに

今回は前回の続きで、DELETE(対象ユーザーの削除), GET(全ユーザーの取得) PATCH(対象ユーザーの更新)を作っていきます。

DELETE(対象ユーザーの削除)

指定されたidを元に、対象のユーザーが削除されるようにしていきます。

Lambda関数の作成と設定

スクリーンショット 2020-01-04 15.20.08.png

ソース

index.js
'use strict';
const AWS = require('aws-sdk');
const myRegion = "us-east-2";

AWS.config.update({ region: myRegion});

exports.handler = async (event, context) => {
  const documentClient = new AWS.DynamoDB.DocumentClient({ region: myRegion});

  let responseBody = "";
  let statusCode = 0;

  const { id } = event.pathParameters;

  const params = {
    TableName: "Users",
    Key: {
      id: id
    }
  };

  try {
    const data = await documentClient.delete(params).promise();
    responseBody = JSON.stringify(data);
    statusCode = 204;
  } catch (err) {
    responseBody = `Unable to delete user: ${err}`;
    statusCode = 403;
  }

  const response = {
    statusCode: statusCode,
    headers: {
      "Content-Type": "application/json"
    },
    body: responseBody
  };

  return response;
};

メソッド作成と設定

スクリーンショット 2020-01-03 23.23.55.png
スクリーンショット 2020-01-03 23.32.59.png

テスト実行と確認

テストボタン
スクリーンショット 2020-01-03 23.42.51.png
削除されていることを確認
スクリーンショット 2020-01-04 15.36.19.png

GET(全ユーザーの取得)

GETメソッドを実行したとき、全ユーザーが取得されるようにする。

Lambda関数の作成と設定

スクリーンショット 2020-01-04 11.47.15.png
ソース

index.js
'use strict';
const AWS = require('aws-sdk');
const myRegion = "us-east-2";

AWS.config.update({ region: myRegion});

exports.handler = async (event, context) => {
  const documentClient = new AWS.DynamoDB.DocumentClient({ region: myRegion});

  let responseBody = "";
  let statusCode = 0;

  const params = {
    TableName: "Users"
  };

  try {
    const data = await documentClient.scan(params).promise();
    responseBody = JSON.stringify(data);
    statusCode = 200;
  } catch (err) {
    responseBody = `Unable to get users: ${err}`;
    statusCode = 403;
  }

  const response = {
    statusCode: statusCode,
    headers: {
      "Content-Type": "application/json"
    },
    body: responseBody
  };

  return response;
};

メソッド作成と設定

スクリーンショット 2020-01-04 11.48.16.png
スクリーンショット 2020-01-04 11.49.15.png

 テスト実行と確認

何も入力せつ、テストボタン。
スクリーンショット 2020-01-04 15.50.36.png

PATCH(対象ユーザーの更新)

PATCHメソッドを実行したとき、対象のユーザが更新されるようにする。

Lambda関数の作成と設定

スクリーンショット 2020-01-04 12.11.31.png

メソッド作成と設定

スクリーンショット 2020-01-04 12.12.22.png
以下のように設定、赤枠使うのが面倒になったので察して
スクリーンショット 2020-01-04 12.14.32.png

 テスト実行と確認

スクリーンショット 2020-01-04 12.20.18.png

リクエスト本文
{
    "id": "02",
    "firstname": "update_firstname",
    "lastname": "update_lastname"
}

更新されることを確認
スクリーンショット 2020-01-04 12.24.17.png

終わりに

これでサーバレスでREST APIを使ったCRUD作成の環境構築をしました。
次はAPI Gateway+Lambda(NodeJS)+S3を組み合わせていこうと思います。
kinesisやauroraあたりを組み合わせてやりたいです。

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Fargate及びECSでコンテナからAWSのIAM認証を利用する

概要

AWSでコンテナを利用する場合、FargateやECSが候補に上がると思います。
コンテナからAWSの各種サービスを利用する場合、IAMのCredentialsを利用する必要があります。
いつも意識せずに利用しているIAMですが、裏ではどういう構成になっているのか確認していきます。

確認方法

Fargateでsshできるようにして、コンテナ内でCredentialsを探します。

Fargateでsshするには以下の記事を参考にしてください

結果

FargateではAWS_CONTAINER_CREDENTIALS_RELATIVE_URIという環境変数にCredentialsへのファイルファイルパスが入っているようです。

rootユーザでコンテナにログインしても環境変数が設定されていない

実は、この環境変数はPIDが1のプロセスに設定されているようです

確認方法

$ strings /proc/1/environ

例えば、Dockerfileで以下のようになっている場合。
この場合、環境変数はPIDが1の/bin/shに設定されます。
そして、bundle exec rails sには親プロセスの/bin/shから環境変数が引き継がれます。

CMD ["/bin/sh", "-c", "bundle exec rails s"]

ちなみに、以下のようにデーモンプロセスを動かす場合。
この場合は起動するデーモンの親プロセスは/bin/shにはならないので環境変数は引き継がれません。

CMD ["/bin/sh", "-c", "service ssh start"]

環境変数に設定されているIAMはどこから設定するのか

このIAMはTask Roleを参照しているようです。
なので、taskRoleArnに設定しているIAMから権限を変更可能です。

RubyライブラリでIAM認証を使う場合

aws-sdk-rubyでは以下のように、AWS_CONTAINER_CREDENTIALS_RELATIVE_URIがあればECSCredentials.newするようにしているみたいです。
ちなみに、instance_profile_credentialsはprivateなので外から呼び出しはできないみたいです。
普段、ライブラリを使う場合は特に意識することなくことなく、Credentialsが使われているようですね。

# https://github.com/aws/aws-sdk-ruby/blob/704c4a2afbee1bb20a6c47545305684a92771f7e/gems/aws-sdk-core/lib/aws-sdk-core/credential_provider_chain.rb#L110

    def instance_profile_credentials(options)
      if ENV["AWS_CONTAINER_CREDENTIALS_RELATIVE_URI"]
        ECSCredentials.new(options)
      else
        InstanceProfileCredentials.new(options)
      end
    end
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

【AWS完全に理解したへの道】VPC 基本編

【AWS完全に理解したへの道】 IAM 基本編
に続く、VPC 基本編(項目の然るべき順序的なものは後で整理するかも)

VPCの作成

ある特定のリージョンを選択してプライベートネットワーク空間を作成する。
プライベートネットワーク空間は /16(65,536個のIPアドレス)から /28(16個のIPアドレス)のCIDR(Classless Inter-Domain Routing)ブロック範囲で作成できる。

VPCを作成する場合は、RFC1918に指定されているように、以下のプライベートIPv4アドレス範囲からCIDRブロックを指定することを推奨されている。

  • 10.0.0.0 - 10.255.255.255
  • 172.16.0.0 - 172.31.255.255
  • 192.168.0.0 - 192.168.255.255

サブネット作成

サブネットを作成時、AZごとに1つ以上のサブネットを追加する必要がある。
サブネットはAZをまたがって作成することはできない。
また、VPC CIDRブロックのサブセットである、サブネットのCIDRブロックを指定する。

オプション

IPv6 CIDRブロックをVPCに割り当てて、IPv6 CIDRブロックをサブネットに割り当てることができる。

ゲートウェイの作成

インターネットゲートウェイ(IGW)

できること
  • インターネットでルーティング可能なトラフィックの送信先をVPCのルートテーブルに追加することができる。
  • パブリックIPv4アドレスが割り当てられているインスタンスに対してNAT(ネットワークアドレス変換)を行うことができる。

バーチャルプライベートゲートウェイ(VGW)

VPNやオンプレのデータセンタなどと通信するための出入り口となるゲートウェイ。

EC2インスタンスのIPアドレス

VPCサブネット内で起動するEC2インスタンスにはそのサブネット内のプライベートIPアドレスが少なくとも一つ割り振られる。
そのEC2インスタンスにインターネットからアクセスしたい場合、さらにグローバルIPアドレスを割り振る必要がある。AWSのグローバルIPアドレスには以下の2種類がある。

  • Public IP : EC2インスタンスが起動した際にランダムに割り振られる動的なグローバルIPアドレス。
  • Elastic IP : アカウントに割り当てられる固定のグローバルIPアドレスでEC2インスタンスにアタッチ/デタッチする。 固定のグローバルIPアドレスでの運用が必要な場合に使用する。

※EC2インスタンスのプライベートIPアドレスとグローバルIPアドレスの紐付けはVPCの仮想ネットワークで行われる。
よって、EC2インスタンスのOSにログインしてifconfigコマンドなどでネットワークの設定を見てもプライベートIPアドレスの値しか表示されない。

ルートテーブルの作成

各サブネットがパブリックなのか、プライベートなのかは各サブネットに適用されているルートテーブルによって決定される。
また、VPC内の通信はルートテーブルでは制御できない。

パブリックサブネット

インターネットのアクセスを許可するサブネット
デフォルトゲートウェイのターゲットにIGW(インターネットゲートウェイ)が設定されたルートテーブルが適用されているサブネット。

プライベートサブネット

インターネットのアクセスを許可しないサブネット
デフォルトゲートウェイのターゲットにIGWが設定されたルートテーブルが適用されていないサブネット。

NATインスタンス

インターネットからのアクセスを受け付けないまま、プライベートサブネット内からインターネットやリージョンサービスにアクセスさせたいときに使用する。

  • NATインスタンスの実態はEC2インスタンス。
  • プライベートサブネット内のEC2インスタンスからトラフィックを受け付ける。
  • そのEC2インスタンスのプライベートIPアドレスをNATインスタンスに割り振られたグローバルIPアドレスに変換し、インターネットへのアクセスを可能にする。

セキュリティグループ

EC2やELBやRDSなどのインスタンスごとのファイアーウォール。
各インスタンスごとに1つ以上のセキュリテイグループを適用する必要がある。

ネットワークアクセスコントロール(ACL)

サブネットごとのファイアーウォール。

セキュリティグループとネットワークACLの違い

セキュリティグループ ネットワークACL
適用単位 EC2、ELB、RDSなどのインスタンス単位 サブネット単位
作成、追加可能なルール 許可のみ 許可/拒否
デフォルトルール インバウンド:全て拒否
アウトバンド:全て許可
インバウンド:全て許可
アウトバンド:全て許可
特徴 ステートフル ステートレス

VPCピア接続

2つのVPCを接続する機能。
2つのVPC間でVPCピア接続を確立すると、双方のVPCにPCXというゲートウェイに相当するものが作成される。
VPCピア接続の制約条件は以下となる。

  • 接続するVPCは同じリージョンに存在する必要がある。
  • 接続するVPCのプライベートネットワークアドレス空間は重複しないようにする必要がある。
  • 1 対 1の接続にする必要がある。
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

AWS+NodeJSでサーバレスな環境構築③

はじめに

前回の記事ではDynamoDBのテーブルと項目作成、Lambda関数で使うロールやインラインポリシーの設定を行いました。今回はその続きで、API Gateway(REST APIでCRUD実装)をトリガーにし、Lambda(NodeJS)関数呼び出して、DynamoDBに参照や更新をできるようにします。
表現等が不適切の場合はご指摘いただければ、幸いです。
※サーバレスに関してよくわからない方は、こちらをご覧いただければと思います。

アーキテクチャ図

serverless.png

流れ

  • ソースで直接(Api gatewayを使わず)参照や更新ができるかを確認
  • POST(ユーザーの登録)
    • domain.com/users/{id}
  • DELETE(対象ユーザーの削除)
    • domain.com/users/{id}
  • GET(全ユーザーの取得)
    • domain.com/users
  • PATCH(対象ユーザーの更新)
    • domain.com/users/{id}

ソースで直接(Api gatewayを使わず)参照や更新ができるかを確認

まずはLambda(NodeJS)でDynamoDBテーブルが参照・更新できるか確認
Lambdaダッシュボード>関数の作成>一から作成>以下の通り入力>関数の作成ボタン
※既存のロール設定は前回の記事で作成したものを使用しています。
スクリーンショット 2020-01-03 19.43.16.png

データの参照ができるよう、ソース編集
こちらのリファレンスを参考にしました。

index.js
'use strict';

const AWS = require('aws-sdk');
const myRegion = "us-east-2";

AWS.config.update({ region: myRegion});

exports.handler = async (event, context) => {
  const documentClient = new AWS.DynamoDB.DocumentClient({ region: myRegion});

  //読込用のデータ
  const params1 = {
    TableName: "Users",
    Key: {
      id: "01"
    }
  };
  //書込用のデータ
  const params2 = {
    TableName: "Users",
    Item: {
      id: "02",
      firstname: "first02",
      lastname: "last02"
    }
  };

  try {
    const readData = await documentClient.get(params1).promise();
    const writeData = await documentClient.put(params2).promise();
    console.log(readData);
    console.log(writeData);
  } catch (err) {
    console.log(err);
  }
};

⚠️ 必ず、DynamoDBとLambdaは同じリージョンで作成するように気をつける。また上記ソースのmyRegion変数値も合わせるように気をつける。いずれが満たない場合、AccessDeniedExceptionという意味不明なエラーが発生する可能性があります。

テストイベントの設定(今回はgetUserData)>テストボタン>取得結果が表示されれば、OK
スクリーンショット 2020-01-03 19.58.10.png

DynamoDBにデータ作成されていることを確認
ちなみに、params2でidをそのまま、firstnameやlastnameを変更すると更新される仕様です。
スクリーンショット 2020-01-03 20.00.54.png

API Gatewayトリガー追加と設定

API Gatewayダッシュボード>APIを作成ボタン>REST APIの構築ボタン(Privateじゃない方)
以下のように入力>APIの作成ボタン
スクリーンショット 2020-01-03 20.32.20.png

エッジ最適化について(AWS公式より引用)

エッジ最適化 API は、API ゲートウェイによって作成および管理される CloudFront ディストリビューション経由でアクセスするエンドポイントです。以前は、エッジ最適化 API は、API ゲートウェイを使用して API を作成する際のデフォルトオプションでした。

参考記事
0からREST APIについて調べてみた
エッジ最適化について説明

リクエスト、レスポンスマッピングのモデルを作成及び設定

参考
モデル名、コンテンツタイプ、スキーマ(ソース)を設定します。
スクリーンショット 2020-01-03 21.41.42.png

スキーマのソース
{
  "$schema": "http://json-schema.org/draft-04/schema#",
  "title": "UsersInputModel",
  "type": "object",
  "properties": {
      "id": {"type": "string"},
      "firstname": {"type": "string"},
      "lastname": {"type": "string"}
  }
}

アクション>リソースの作成
リソースは2つ作成します。
スクリーンショット 2020-01-03 21.13.48.png
スクリーンショット 2020-01-03 21.15.55.png

POSTメソッド実装(ユーザーの登録)

ここではAPI GatewayでPOSTメソッドを作成して、レコードが登録されるかを確認する。

API Gatewayと紐付けるLambda関数を作成と設定

関数名はputUsersで、その他の設定は前回と一緒(察して)(冒頭のLambda関数作成のスクリーンショット参照)

以下のソースを貼り付けます。
DynamoDBの構成に関しては、こちらの記事を参考にしてください。(DynamoDBテーブルの作成部分)

index.js
'use strict';
const AWS = require('aws-sdk');
const myRegion = "us-east-2";

AWS.config.update({ region: myRegion});

exports.handler = async (event, context) => {
  const documentClient = new AWS.DynamoDB.DocumentClient({ region: myRegion});

  let responseBody = "";
  let statusCode = 0;

  const { id, firstname, lastname } = JSON.parse(event.body);

  const params = {
    TableName: "Users",
    Item: {
      id: id,
      firstname: firstname,
      lastname: lastname
    }
  };

  try {
    const data = await documentClient.put(params).promise();
    responseBody = JSON.stringify(data);
    statusCode = 201;
  } catch (err) {
    responseBody = `Unable to put user ${err}`;
    statusCode = 403;
  }

  const response = {
    statusCode: statusCode,
    headers: {
       "Content-Type": "application/json"
    },
    body: responseBody
  };

  return response;
}

POSTメソッド作成と設定

アクション>メソッドの作成
スクリーンショット 2020-01-03 21.24.17.png

メソッドリクエストの設定
モデルの追加には上記の作成したモデルを追加する
スクリーンショット 2020-01-03 21.46.26.png

API Gatewayで確認テスト

下の方にテストボタンあるので、それを押すとテスト結果(ログも含めて)画面右側に表示されると思います。
スクリーンショット 2020-01-03 22.12.05.png

スクリーンショット 2020-01-03 22.23.42.png

リクエスト本文
{
    "id": "03",
    "firstname": "first03",
    "lastname": "last03"
}

テストステータスで201が返ってこれば、成功みたいです。
⚠️ ちなみに本来DynamoDBテーブルにない項目論理名(例えばfirstnameではなく、あえてnickname)をリクエスト本文に設定された場合、問題なくテスト処理は実行されます。対象のレコードfirstnameには空白が入る仕様になっています。

DynamoDBテーブルにレコードが作成されていることを確認
スクリーンショット 2020-01-03 22.27.09.png

to be continued

ちょっと長くなりそうなので、続きを次回出します。
あとはDELETE(対象ユーザーの削除), GET(全ユーザーの取得) PATCH(対象ユーザーの更新)のメソッドを作成して、最後までCRUD機能を実装していきます。

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

AWS Cloud9に繋がらなくなった場合の対処

Cloud9を使用していてenvironmentに接続しようとしたら「connecting...」と表示されたまま繋がらなくなった。
ブラウザのポップアップブロックの設定やキャッシュ・Cookieの削除などいろいろやってみたが下記の対処をやったら直った。

前提

Cloud9の開発環境作成後の状態(“Create environment”実行後)
使用ブラウザ:Google Chrome

対処法

インスタンスを一旦停止する。

<停止方法>
サービス → コンピューティングの「EC2」をクリック
スクリーンショット 2020-01-04 2.10.30.png

インスタンス → インスタンス → 対象のインスタンスにチェックを入れる
アクション → インスタンスの状態 → 停止
スクリーンショット 2020-01-04 2.09.57.png

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む