20200702のAWSに関する記事は21件です。

AWSのみで構築する独自ドメイン/SSL/WordPressサイト

はじめに

技術系の記事を書くだけならQiitaで良いかと思うんですが、もう少し自由な情報発信もしたいなと考えたときに、他のブログサイトを利用するとか、SNSで情報発信などが気楽に始められてよいのかもしれません。ただ、そこは昔ながらのITエンジニア「自前サーバーを立ててホームページを運営してみよう!」ということにしました。学生時代(20世紀末)にフリーのホームページ提供サービス上にサイトを作って運営していたのを少し思い出します。HTMLをテキストエディタで書いてFTPでアップロードするといった、本当に今考えると嘘みたいな時代です。今どきは月々数百円で立派なサーバーが運用でき、ホームページを作成するにも高機能なCMSを動かしてそこで簡単に豪華なサイトができてしまうのですから進化していますよね。考えようによっては20年たってもやってること変わってないな・・・、という見方もできますが。

では、本題に入ります。今回はAWSのみですべてを実現します。色々組み合わせればもっと低価格で便利なサーバーを運用できるよといった声があるかもしれませんが、ワンストップ実現することにこだわりました。また、すでに先人が同じようなことをやっているので記事も検索すれば色々と出てきます。ただ、以下のすべてが網羅されているサイトが見つからなかったので、各所から情報を集めながら最新情報でまとめ直して環境を構築していきます。

構築する環境

  1. Amazon Route 53で独自ドメイン取得
  2. Amazon LightsailでWordPressを構築する
  3. Amazon Certificate ManagerでSSL証明書を発行・管理
  4. Amazon CloudFrontによるSSL化

今回は見送る環境

AWS SESは自由に送信できるようにするには審査が必要で、なんの実績もない新規サイトでこれを通すのは少し厳しいかなという印象です。ということでまずはいったん以下を見送ります。おいおいやっていきたいと思います。
1. Amazon SESを使った独自ドメインメールでWordPressのメール送信を設定

完成したサイト

本記事の手順で立ち上げたサーバーは以下になります。

makotomi's Tech Blog

Route53で独自ドメイン取得

まず最初に、独自ドメインの取得を行いたいと思います。独自ドメインは自前でサーバーを運用するメリットでもあります。費用はドメインによって様々ですが、AWSで登録する場合、.comや.netなどのドメインであればおおむね年間千数百円程度にしかなりません。

それでは早速、独自ドメインの取得を行います。AWSマネージメントコンソールでRoute53を開き、ドメインの登録今すぐ始めるを押下します。

1.png

登録済みドメインドメインの登録を押下します。

2.png

ドメイン名の選択で希望する名称、私の場合makotomiを入力し、.comチェックを押下します。希望するドメインが空いていれば使用可否に出てきますので、カートに入れるを押下し、続行で次に進みます。

3.png

2.連絡先の紹介で必要事項を入力します。登録者、管理者、および技術的な連絡先はすべて同じですはいを選び、入力を簡易にします。次に、連絡先のタイプは必ず**個人**を選択し、プライバシーの保証`を有効化しましょう。これを選択しておかないと、DNSの登録情報に個人情報が掲載されてしまい、whoisで問い合わせると世界中に情報が公開されてしまいます。画像ではぼかしてありますが必須項目に個人情報の入力が必要になります。
3-1.png

入力を完了し次に進むと、以下のようなダイアログが表示されます。このタイミングで連絡先に入力したEメールに検証用のメールが送信されています。
3-2.png

メールは以下のような文面で届きますので、URLのリンクをクリックし、メールの検証を完了します。
4.png

URLのリンクをクリックすると、Eメールの検証成功画面が表示されます。

5.png

'3.確認と購入'画面では今まで入力した情報、ドメインをどう更新するか否かの選択(今回は有効にしてありますので、1年後に自動的にドメインが更新されるようになるます)、規約への同意確認、先ほど実施したEメールアドレスが検証済みか否かといった情報が出ます。規約に同意し、注文を完了を押下することで独自ドメインの購入作業は終了です。
6.png

しばらく時間がかる旨のメッセージが表示されます。

7.png

ドメイン登録完了のけ画面に表示されます。最大3日かかると画面ででも明日がそこまで時間はかからず、即日で登録は完了しました。ドメインに移動を押下し次の画面に進みます。

8.png

今購入したドメインが保留中のリクエストに入り登録作業が進行中であることが表示されます。

9.png

ここで、しばらく待つ(この時は30分未満くらいで登録されましたが、いつもそうなのかは不明です)と保留中のリクエストから登録済みドメインに移動します。

10.png

登録済みドメインの設定を開き。今回登録したmakotomi.comの移管のロックを有効化しておきました。AWSから他に名前移管する予定もないので念のためです。

11.png

Amazon LightsailによるWordPress構築

Amazon Lightsailは細かい設定なしにサーバーやインフラが適切に設定され、簡単に様々なアプリケーションがのったサーバーを起動できます。さらには、最もリーズナブルなサーバーは3.50 USD/月なので月々400円くらいです。メモリ512MB、1CPU、20GBSSD、1TBのデータ転送がコミコミでこの価格になります。普通に同程度のEC2サーバーを起動すると、t2.nanoのインスタンスで5.472USD/月(0.0076USD/時間 x 24 x 30)、SSD 20GBは2.4USD/月(0.12USD/GB月 x 20) 、ネットワーク転送は1TBで113USD(0.114USD/GBx999GB)となるので、圧倒的に低価格です。
仕事ではCloudformationを使ってEC2ベースでサーバーを細かく構成して運用しているので、LightSailの話を始めて聞いた時にも関心を全く持っていなかったのですが、改めてみるとライトな利用用途だと至れり尽くせりな感じを受けました。

今回はこの最安値のサーバーで、Wordpressを立ち上げてみたいと思います。

まずは、AWSにアカウントを作りましょう。アカウントの作り方は公式ページを参考に作成してください。

AWSのコンソールでログインしたらLightsailの画面に入ります。

1.png

AWSの画面の中でもかなり特徴的なUIです。明らかに他の機能とターゲットが違うんだろうなというデザインでシンプルなUIになっています。早速インスタンスの作成ボタンを押下してサーバーを構築します。

2.png

インスタンスのロケーションですが、東京なら、A,C,Dのアベイラビリティゾーン(以下AZ)から選択できます。今回は1台のサーバー構成なのでどこを選択しても違いはありません。サーバーを複数台用意して高可用性な構成を作る場合に初めて気にすればよい設定項目です。次にプラットフォームですが、Linux/Unixを選択します。次に設計図ですが、目的のWordPressを選択します。

3.png

次にインスタンスプランを選択します。先に述べた通り。3.5USDのインスタンスを選択します。ただでさえ低価格なのに最初の1カ月は無料で使用できます。

4.png

最後に任意のリソース名をつけてインスタンスの作成ボタンを押下すれば完了です。これでWordPressサーバーが起動してしまいます。わずか数分作業です。
引き続きインスタンスの設定を続けます。

4-2.png

作製したしたインスタンスの管理画面に入り、ネットワーキングの設定ページを開きます。

5.png

このページのIPアドレスではパブリックIPとプライベートIPの設定値が確認できます。パブリックIPがインターネットからアクセスできるIPアドレス、プライベートIPは内部ネットワークで利用するIPアドレスになります。この段階ではパブリックIPアドレスはインスタンス起動時にランダムで振られるIPアドレスが設定されています。つまり再起動すると毎回変わってしまいます。インターネット上でサイトを公開するためには変わらないIPアドレスを設定する必要があるので、静的IPの作成ボタンから設定を行います。

6.png

静的IPの作成画面では、作成する静的IPをどのインスタンスにアタッチするかを選択します。作成したWordPressサーバのインスタンスを選択し作成を行います。

7.png

作製が完了すると、IPアドレスが割り当てられます。以降このIPアドレスを使えばサーバーにアクセスできます。早速このIPアドレスをWebブラウザで
開いてみると下記の通り、WordPressのアプリケーションが動いていることが確認できます。

8.png

Webブラウザでのアクセス確認以外は、すべてマウスで選択してボタンを押下しただけです。実に簡単にサーバーが構築できてしまいました。

最後にSSHでつないで二つの作業を実施しておきます。
9.png
まず、インスタンスに対してSSHでログインします。

  1. 管理者のIDとパスワードの取得

WordPressの管理画面(http://[IPアドレス]/wp-admin/)へのログインをするためのクレデンシャルを取得しておきます。
10.png
ホームディレクトリのbitnami_credentialsファイルにユーザー名とパスワードが書かれています。これを使ってWordPressの管理画面にアクセスすることができます。
2. bitnamiのアイコンを削除
Wordpressの画面の右下に表示されれている以下のアイコンを表示しないように設定変更します。
11.png
Shellで以下のコマンドを実行します。

sudo /opt/bitnami/apps/wordpress/bnconfig --disable_banner 1
sudo /otp/bitnami/ctlscript.sh restart apache

12.png

管理画面にログインできるか、画面からアイコンが消えたかを確認して完了です。

Amazon Certificate ManagerでSSL証明書を発行・管理

SSL証明書をAmazon Certificate Manager(以下ACM)で発行して管理します。無料でSSL証明書が発行できるうえに、期限が切れしないように自動で更新してAWSのELBやCloudFront、API Gwatewayなどへも自動で設定してくれるのでAWSでサービス運用している個人にとってはベストな選択です。普通のクライアント(PCやスマホなど)であれば、AmazonのRoot CAは検証できるので、DigiCertやGlobalSignなどのメジャーな証明書を何万円も出して買わなくても十分に通用します。ちなみに、本日段階でQiitaや本家AWSの証明書もAWSの証明書だったりするので安心できますよね。それでも心配でもう少し調べてみようといくつか回った時にちょっと面白いなと思ったのは、www.amazon.co.jpの証明書はDigiCert製でした。ECサイトとしては少しのスキが販売機会損失につながるかもしれないからと安心を買っているのかもしれません。

前置き長くなりましたが証明書を発行していきたいと思います。

まず最初に一番重要なことは、今回作成するSSLの証明書はCloudFrontで利用する点です。CloudFrontにACMの証明書を設定する場合には、バージニア北部(us-easst-1)で作成する必要があります。
AWSマネージメントコンソールでCertificate Manaerを開き、バージニア北部に変更してから、証明書のプロビジョニング今すぐ始めるを押下します。
1.png

証明書のリクエストパブリック証明書のリクエストを選択し、証明書のリクエストを押下します。

2.png

ドメイン名の追加*.makotomi.comとし、先ほど取得したドメインのワイルドカード証明書を要求します。ワイルドカード証明書とはサブドメイン部が自由になり、www.makotomi.comのサーバーでもhogehoge.makotomi.comのサーバーでも利用できる証明書になります。もちろんサブドメイン毎に別の証明書を発行するのも問題ありません。無料なのでたくさん証明書を発行しても、それをワイルドカード証明書で集約してもコストメリットがでるわけではありませn。
3.png

検証方法の選択ではDNSの検証を選択します。今回はドメインもAWSで購入していますし、Route53で管理されているので、この検証方式が最も簡単になっています。
4.png

タグを追加では必要であればタグを追加できますが今回は何もつけないで次に進みます。
5.png

確認とリクエストでは、先ほど入力したドメインと検証方法が正しいことを確認し確認とリクエストボタンを押下します。
6.png

検証ではドメイン名をクリックし検証作業を行います。
7.png

ドメイン部を開くとRoute 53でのレコードの作成ボタンが出てきます。これもAWSのみで作業しているメリットです。検証用のレコード設定をボタン1個押すだけでDNSに登録できます。
8.png

ボタンを押下したら以下の確認画面が表示されるので作成ボタン
を押下します。
8-2.png

結果画面が表示されます。Certification Managerが今登録されたレコードの名前解決ができるかをチェックすることで証明書が有効になります。これには最大30分かかるということなのでしばらく時間を待つ必要があります。
9.png

なお、このタイミングでRoute53のドメイン情報を確認すると以下のようにレコードが追加されていることが見て取れます。
10.png

しばらく後、Certification Managerを確認すると以下のように証明書の検証状況が確認できます。検証状態成功、'状況'が発行済みになっていれば完了です。

11.png

Amazon CloudFrontによるSSL化

いよいよWordPressをSSL化します。

まず、Route53にドCloudFrontからLightsail上のWordPressにアクセスするために、WordPressのドメイン名を設定します。
AWSマネージメントコンソールでRoute53を開き、ホストゾーン対象となるドメインを選択します。
1.png

対象のドメインで、レコードセットの作成ボタンを押下し、名前にblog、タイプをAレコード、値にWordpressのサーバーに割り当てた静的IPを入力し作成ボタンを押下します。これで、ドメイン名の登録が完了したのでhttp://blog.makotomi.com/ でアクセスしサーバーが開けるか確認してみてください。登録してからアクセスできるようになるまで少し時間差がある場合がありますので、すぐに開かなくても慌てず少し待ってからアクセスしてみましょう。
2.png

次にCloudFrontでDistributionの作成を行います。AWSマネージメントコンソールでCloudFrontを開き、Create Distributionボタンを押下します。
3.png

Select delivery methodWebGet Startedボタンを押下します。
4.png

Create distributionOrigin Settingsを入力していきます。Origin Domain NameにWordpressのドメイン名blog.makotomi.comを入力します。残りはデフォルトトの値のままとしています。
5.png

次に、'Default Cache Behavior Settings'を入力していきます。Viwer Protocol PollicyRedirect Http to Httpsを、Allowed HTTP Method`で__GET,HEAD,OPTIONS,PUT,POST,PATCH,DELETEを、Cace Based on Selected Request HeadersAllを、Forward CookiesAllを、Query String Forwarding and CachingForward all, cache based on allをそれぞれ設定し、残りはデフォルトの値のままとしています。
6.png

最後に、'Distribution Settinsを入力していきます。'Alternate Domain Names(CNAMEs)に今回のWordPressを公開したいドメイン名としてwww.makotomi.comを入力します。SSL CerfiticateCustom SSL Certificate(example.com)を選択し、ドロップダウンから前段で登録した、*.makotomi.comのワイルドカード証明書を選択します。ここで、Custom SSL Certificate(example.com)が選択できない場合は、バージニア北部に証明書ちゃんと登録されているか今一度確認してみてください。残りはデフォルトトの値のままとして、Create Distributionボタンを押下します。
7.png

登録が完了すると一覧に表示されます。StateEnabledに変わるまで少しかかりますので待ちましょう。ここでRoute53へ登録を行うために、Domain Nameを記録してください。
8.png

AWSマネージメントコンソールでRoute53を開き、ホストゾーン対象となるドメインを選択します。対象のドメインで、レコードセットの作成ボタンを押下し、名前にwww、タイプをCNAME、値にCloudFrontのDistributionのドメイン名を入力し作成ボタンを押下します。これで、ドメイン名の登録が完了したのでhttps://www.makotomi.com/ でアクセスしサーバーが開けるか確認してみてください。ここでも登録してからアクセスできるようになるまで少し時間差がある場合がありますので、すぐに開かなくても慌てず少し待ってからアクセスしてみましょう。また、http://www.makotomi.com/ でアクセスしてもhttps://www.makotomi.com/ にリダイレクトされることも確認しましょう。

なお、この段階では画面のスタイルが崩れて適切な表示にならないと思います。それを修正するためにWordPressの設定を変更します。SSL Insecure Content Fixerプラグインを使う方法が一番簡単そうでしたのでそれで進めます。

WordPressの管理画面に入り、プラグインより‘SSL Insecure Content Fixer今すぐインストール`し、'有効化'します。10.png

設定画面に入り、HTTPSの検出方法でHTTP_CLOUDFRONT_FORWARDED_PROTO (Amazon CloudFront HTTPS キャッシュ済みコンテンツ)を選択します。
11.png

以上で、httpsでアクセスした際も正常動作するようになります。

まとめ

以上で独自ドメインのWordPresサイトの構築が完了しました。CloudFrontを通さずHTTPでも直接アクセスすることができてしまうんですが、そのルートを閉じて厳密にSSLのみで運用しなくても良いかなと考えています。
この後のWordPressの設定に関しては、Qiitaの記事っぽくないかなと考えていますし、せっかく立ち上げたのでmakotomi's Tech Blogここに記事として書いていこうと思います。

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

AWS EC2でWebサーバーを構築する話 その1

皆さんこんにちは。
今回はちょっとEC2でWebサーバーを構築してみたいと思います。

概要

  • クライアント側のOSはWin10
  • 無料の範囲内で収める
  • OSはUbuntu 18.04 LTS
  • Apache2を使う
  • (AWSのアカウント作成については割愛します)

やってみる

EC2 インスタンスの作成

まず、AWSのページに行き、「コンピューティング」の中にある「EC2」をクリックします。
image.png

するとEC2の管理画面(EC2 コンソール)を開くことができます。
左側にメニューがあるので、「インスタンス」を選択します。
image.png
インスタンスの作成をクリックします。

image.png
ここではUbuntu 18.04 LTSを使います。

image.png
無料利用枠の対象のインスタンスタイプを選択します。

image.png
右下の起動をクリックします。

image.png
キーペアの選択画面が表示されるので、「新しいキーペアの作成」を選択し、キーペア名を入力し、「キーペアのダウンロード」をクリックします。
注意:キーペアは安全でアクセス可能な自分がわかりやすい場所に保存してください。(紛失しないように!)

キーペアの作成が済んだら「インスタンスの作成」をクリックします。

接続

SSHを使って接続します。

ssh -i "キーペアファイル.pem" ubuntu@パブリックホスト名

キーペアは先程作成したものを、インスタンス管理画面から確認できます。(IPv4 パブリックIP)

わお

接続が済んだら、とりあえずrootのパスワードを変更しておきます。

$ sudo passwd su

ついでにデフォルトユーザーのパスワードも変えておきましょう。

$ passwd

aptの更新

aptの更新も済ませます。

$ sudo apt update
アップデートできるパッケージはアップデートしておきましょう
$ sudo apt upgrade

パッケージのインストール

Apache2

まず、Apacheをインストールします。

$ sudo apt install apache2

そして起動

$ sudo systemctl start apache2

ここでセキュリティルールのお話です。

EC2のページに移動します
image.png
左側メニューのセキュリティグループを選択します。

image.png
するとこのような画面が表示されるので、現在自分が使っているインスタンスのセキュリティグループ名をクリックします。

下の方へ行くとインバウンドルールについてのタブがあるので選択します。
image.png
右側のインバウンドルールを編集をクリックします。

image.png
するとインバウンドルールの編集をすることができます。
例として現在、
「22番ポートを0.0.0.0/0(すべての場所)から接続を許可する」
というルールがあるのが確認できますね。
これはSSHのためのルールなので、HTTPのためのルールを新しく追加していきます。

「ルールを追加」をクリックし、画像のように設定します。
image.png
設定が完了したら、「ルールを保存」をクリックします。
これで80番ポートが解放されました。

ついでにElastic IPの設定もしておきましょう。
先程の左側のメニューに Elastic IP という項目があるのでクリックします。
image.png
Elastic IP アドレスの割り当てをクリックします。
image.png
右下の「割り当て」をクリックします。

image.png
アクション メニューより、Elastic IPアドレスの関連付けをクリックします。
コメント 2020-07-01 004732.png
実行中のインスタンスとプライベートIPアドレスを選択し、右下の「関連付ける」ボタンをクリックします。

では

早速ページが表示されるか試してみましょう。
インターネットブラウザのURL欄に先程関連付けたIPアドレスを入力し、Enterキーを押します。
コメント 2020-07-01 005104.png

どうやらApache2は正常に稼働しており、正常に接続できたようです!

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

AWS EC2でWebサーバーを構築する話 その1

初投稿です。
皆さんこんにちは。
今回はちょっとEC2でWebサーバーを構築してみたいと思います。

概要

  • クライアント側のOSはWin10
  • 無料の範囲内で収める
  • OSはUbuntu 18.04 LTS
  • Apache2を使う
  • (AWSのアカウント作成については割愛します)

やってみる

EC2 インスタンスの作成

まず、AWSのページに行き、「コンピューティング」の中にある「EC2」をクリックします。
image.png

するとEC2の管理画面(EC2 コンソール)を開くことができます。
左側にメニューがあるので、「インスタンス」を選択します。
image.png
インスタンスの作成をクリックします。

image.png
ここではUbuntu 18.04 LTSを使います。

image.png
無料利用枠の対象のインスタンスタイプを選択します。

image.png
右下の起動をクリックします。

image.png
キーペアの選択画面が表示されるので、「新しいキーペアの作成」を選択し、キーペア名を入力し、「キーペアのダウンロード」をクリックします。
注意:キーペアは安全でアクセス可能な自分がわかりやすい場所に保存してください。(紛失しないように!)

キーペアの作成が済んだら「インスタンスの作成」をクリックします。

接続

SSHを使って接続します。

ssh -i "キーペアファイル.pem" ubuntu@パブリックホスト名

キーペアは先程作成したものを、インスタンス管理画面から確認できます。(IPv4 パブリックIP)

わお

接続が済んだら、とりあえずrootのパスワードを変更しておきます。

$ sudo passwd su

ついでにデフォルトユーザーのパスワードも変えておきましょう。

$ passwd

aptの更新

aptの更新も済ませます。

$ sudo apt update
アップデートできるパッケージはアップデートしておきましょう
$ sudo apt upgrade

パッケージのインストール

Apache2

まず、Apacheをインストールします。

$ sudo apt install apache2

そして起動

$ sudo systemctl start apache2

ここでセキュリティルールのお話です。

EC2のページに移動します
image.png
左側メニューのセキュリティグループを選択します。

image.png
するとこのような画面が表示されるので、現在自分が使っているインスタンスのセキュリティグループ名をクリックします。

下の方へ行くとインバウンドルールについてのタブがあるので選択します。
image.png
右側のインバウンドルールを編集をクリックします。

image.png
するとインバウンドルールの編集をすることができます。
例として現在、
「22番ポートを0.0.0.0/0(すべての場所)から接続を許可する」
というルールがあるのが確認できますね。
これはSSHのためのルールなので、HTTPのためのルールを新しく追加していきます。

「ルールを追加」をクリックし、画像のように設定します。
image.png
設定が完了したら、「ルールを保存」をクリックします。
これで80番ポートが解放されました。

ついでにElastic IPの設定もしておきましょう。
先程の左側のメニューに Elastic IP という項目があるのでクリックします。
image.png
Elastic IP アドレスの割り当てをクリックします。
image.png
右下の「割り当て」をクリックします。

image.png
アクション メニューより、Elastic IPアドレスの関連付けをクリックします。
コメント 2020-07-01 004732.png
実行中のインスタンスとプライベートIPアドレスを選択し、右下の「関連付ける」ボタンをクリックします。

では

早速ページが表示されるか試してみましょう。
インターネットブラウザのURL欄に先程関連付けたIPアドレスを入力し、Enterキーを押します。
コメント 2020-07-01 005104.png

どうやらApache2は正常に稼働しており、正常に接続できたようです!

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

AWS Webinar「お待たせしました!Amazon Elasticsearch Service 怒涛のアップデート」に参加したので学習メモ

AWS 主催の Webinar のうち、2020年7月2日に実施された お待たせしました!Amazon Elasticsearch Service 怒涛のアップデート に参加しましたので、学習メモです。

Amazon ES (Elasticsearch Service) とは

Elasticsearch は OSS の、Lucene 基盤の分散処理マルチテナント対応検索エンジン、だそうです。全文検索に特化しているとか。先日、体験メモ を投稿したばかり。

Elasticsearch を AWS 上のマネージドサービスとして提供するのが、Amazon ES (Elasticsearch Service) です。ただし素の Elasticsearch ではなく、エンタープライズ向けに拡張された Open Distro for Elasticsearch を用いているのが特徴のようです。

Open Distro for Elasticsearch
An Apache 2.0-licensed distribution of Elasticsearch enhanced with enterprise security, alerting, SQL, and more

Amazon ES の最新アップデート解説 (40分)

今回、説明された2020年以降のアップデート内容は以下の9つ。

検索・分析に関する機能追加

検索・分析に関する機能追加

前提知識

これらですが、AWS Black Belt Online Seminar で2020年6月23日に今回と同じ志村 誠さんが説明した 「Amazon Elasticsearch Service」 回をふまえて理解するのが良さそう。資料は こちら

といいますか、今回の説明にあるアップデート内容は全て、上記の Black Belt にも含まれています。でも今回はアップデートに特化した内容のため、説明もより詳しく、デモもあり、更にわかりやすかった印象があります。なので本Webinarが公開されたら、上記と連続して視聴することをお勧めします。

Ultrawarm について

今回のアップデートの内容は基本 Open Distro 由来のものが多いようなのですが、Ultrawarm は AWS 独自の機能のようです。

実データを S3 上に配置して実行するため、コスト的にかなり有利とのこと。Elasticsearch は本来、レプリカで可用性を確保していますが、もともと可用性の高い S3 を利用することで、データの重複を避けることができる、らしいです。

S3 上にデータを保持、ということで、Redshift Spectrum を連想しますね。認定試験とかで「Amazon ES Spectrum」とか並んでいたら、間違えて選んでしまいそうですw

Ultrawarm に移行するのは簡単ですが、force_merge してからの移行になるので処理コストがかかることと、移行後は Read Only になるのが注意点とのこと。元の状況 (Hot というらしい) の状態にも戻せますが、force_merge したデータは以後の更新コストが上昇するので、あまりお勧めできないとのこと。

Amazon ES を活用した SIEM の実現方法 (40分)

Amazon ES (Elasticsearch Service) を用いた SIEM の実現方法に関する説明とデモでした。

SIEM (Security Information and Event Management) は、セキュリティやネットワークに関するデータを収集して一元管理し、相関分析によって脅威検出とインシデントレスポンスをサポートするためのソリューションです。

Web のセキュリティと言えば AWS WAF (Web Application Firewall) による防御や、脅威検出サービスの Amazon GuardDutyを連想します。

脅威検出に対して、その脅威の影響を判断し対応する「インシデントレスポンス」があり、それに Amazon ES を活用するのが今回の説明内容でした。

インシデント・レスポンス実施にはより詳細なログの分析が必要で、アプリケーション独自のものもあり、AWS の標準サービスだけでの対応は難しい。なのでより多彩なデータを収集し、正規化(ETL: Extract,Transform,Load)したうえで、Elasticsearch で管理したうえで、Kibana 等で可視化するとのこと。

なるほど、と感じました。

また実際に何度かログオンに失敗した結果を、Kibana で表示するデモも実施されました。これすごく、わかりやすかったです。ただ時間の関係か、操作がすごく早くてわからない部分もあったので、Webinar の動画が公開された後に、あらためてゆっくり眺めて理解したいと思います!

というわけで

短い時間でしたが、内容がギュッと詰まった、学びの時間でした。この投稿はそのほんの一部をまとめたメモです。

AWS はサービス数が多く、また更新も速いので学習やスキルの維持が大変だと感じます。しかしこういったアップデートのセッションで、それぞれの更新の理由やメリットを理解でき、それを積み重ねていければ、理解もしやすいですし忘れない気もします。

まだ私は学習の途上なので覚えることも多いですが、積極的に学んでいきたいな、と。

それではまた!

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

EventBridge+LambdaでAMIを定期取得して世代管理を実装するCloudFormationテンプレート作成

本当はAWS BackupでAMIを定期取得して世代管理を実装したかったのですが下記理由により断念しました。

  • スケジューリングした際、●●時●●分に取得開始という設定ができない
  • AMI取得の際、「再起動あり」の設定ができない

解消する方法は色々あったのですが、今回は先人のノウハウを参考にEventBridge+LambdaでAMIを定期取得して世代管理を実装するCloudFormationテンプレートを作成しました。

今回参考にさせていただいた記事

AMI を定期的に取得して世代管理する

かなり参考にさせていただいたので本記事の不明点はこちらの記事を参照いただけるとよいかと思います。

CloudFormationテンプレートによる実装概要

CloudFormationテンプレートでスタックを作成すると下記のような構成が出来上がります。CloudTrailについてはCloudFormationテンプレートに含んでいませんので別途有効化が必要となります。

概要.png

この構成は下記2つのCloudFormationテンプレートで構築しています。

  • AMI定期取得用CloudFormationテンプレート(schedule_create-ami-generations.yml)
  • AMI登録削除後に対象AMIのスナップショット削除用CloudFormationテンプレート(event_ec2-snapshot-delete-after-ec2-ami-deregister.yml)
    • CloudTrail有効化前提

AMI定期取得用CloudFormationテンプレート(schedule_create-ami-generations.yml)

CloudFormationのスタック作成時に決定したEC2タグ(初期値:Create-ami-generations)が付いているEC2のAMIを定期的にバックアップするものです。
EventBridgeで指定した時間にAMI取得を行うLambda関数を呼び出します。Lambdaでは下記処理を行います

  • 指定のEC2タグ(初期値:Create-ami-generations)があるEC2のAMIを取得
  • 指定のEC2タグ(初期値:Create-ami-generations)の値の世代管理を実施
  • 古いEC2についてはAMI登録解除(DeregisterImage) ※AMI取得時のスナップショットはもう一つのLambdaで削除

AMI定期取得用CloudFormationテンプレート(schedule_create-ami-generations.yml)の内容は下記となります。
CloudFormationスタック作成時に入力が必要となるパラメータは下記のとおりです。

  • EC2TagName : AMI定期取得対象となるEC2タグ名 (初期値:Create-ami-generations)
  • EventName :Event名(初期値:Create-ami-generations_schedule)
  • FunctionName:Lambda関数名(初期値:Create-ami-generations)
  • NoReboot:AMI取得時の「再起動しない」の指定(初期値:false) ※初期は「再起動する」としています
  • RoleName : Lambda関数で利用するIAMロール名(初期値:Create-ami-generations)
  • Schedule : EventBridgeのcron指定(初期値:cron(0 18 * * ? *)) ※03:00(JST)

snip_20200702185900.png

schedule_create-ami-generations.yml
AWSTemplateFormatVersion: 2010-09-09
Parameters:
  RoleName:
    Type: String
    Default: Create-ami-generations
  EC2TagName:
    Type: String
    Default: Create-ami-generations
  FunctionName:
    Type: String
    Default: Create-ami-generations
  NoReboot:
    Type: String
    Default: False
  EventName:
    Type: String
    Default: Create-ami-generations_schedule
  Schedule:
    Type: String
    Default: cron(0 18 * * ? *)
Resources:
  LambdaRole:
    Type: 'AWS::IAM::Role'
    Properties:
      RoleName: !Sub '${RoleName}'
      AssumeRolePolicyDocument:
        Statement:
          - Action:
              - 'sts:AssumeRole'
            Effect: Allow
            Principal:
              Service:
                - lambda.amazonaws.com
        Version: 2012-10-17
      ManagedPolicyArns:
        - 'arn:aws:iam::aws:policy/AWSLambdaExecute'
        - 'arn:aws:iam::aws:policy/AmazonEC2FullAccess'
      Path: /
  Lambda:
    Type: 'AWS::Lambda::Function'
    Properties:
      Code:
      Code:
        ZipFile: |
          import os
          import boto3
          import distutils.util
          import collections

          from time import sleep

          from datetime import datetime, timedelta

          from botocore.client import ClientError

          from logging import getLogger, INFO

          logger = getLogger()

          ec2_client = boto3.client('ec2')

          def lambda_handler(event, context):
              descriptions = create_image()
              delete_old_images(descriptions)

          def create_image():
              instances = get_instances([os.environ['TAG_NAME']])
              descriptions = {}
              for instance in instances:
                  tags = { tag['Key']: tag['Value'] for tag in instance['Tags'] }
                  generation = int( tags.get(os.environ['TAG_NAME'], 0) )

                  if generation < 1:
                      continue

                  no_reboot = bool( distutils.util.strtobool( os.environ['NO_REBOOT'] ) )
                  instance_id = instance.get('InstanceId')
                  create_data_jst = (datetime.now() + timedelta(hours=9)).strftime("%Yy%mm%dd_%Hh%Mm%Ss")
                  ami_name = '%s_%s' % (tags['Name'], instance_id)
                  ami_name = ami_name + "_" + create_data_jst
                  description = instance_id

                  image_id = _create_image(instance_id, ami_name, description, no_reboot)
                  logger.info('Create Image: ImageId:%s (%s) ' % (image_id['ImageId'], ami_name))
                  print('Create Image: ImageId:%s (%s) ' % (image_id['ImageId'], ami_name))       
                  descriptions[description] = generation

              return descriptions

          def get_instances(tag_names):
              reservations = ec2_client.describe_instances(
                  Filters=[
                      {
                          'Name': 'tag-key',
                          'Values': tag_names
                      }
                  ]
              )['Reservations']

              return sum([
                  [instance for instance in reservation['Instances']]
                  for reservation in reservations
              ], [])

          def _create_image(instance_id, ami_name, description, no_reboot):
              for i in range(1, 3):
                  try:
                      return ec2_client.create_image(
                          Description = description,
                          NoReboot = no_reboot,
                          InstanceId = instance_id,
                          Name = ami_name
                          )
                  except ClientError as e:
                      logger.exception(str(e))
                      print(str(e))
                  sleep(2)
              raise Exception('cannot create image ' + ami_name)

          def delete_old_images(descriptions):
              images_descriptions = get_images_descriptions(list(descriptions.keys()))
              for description, images in images_descriptions.items():
                  delete_count = len(images) - descriptions[description]
                  if delete_count <= 0:
                      continue

                  images.sort(key=lambda x:x['CreationDate'])
                  old_images = images[0:delete_count]

                  for image in old_images:
                      _deregister_image(image['ImageId'])
                      logger.info('Deregister Image: ImageId:%s (%s)' % (image['ImageId'], image['Description']))
                      print('Deregister Image: ImageId:%s (%s)' % (image['ImageId'], image['Description']))

          def get_images_descriptions(descriptions):
              images = ec2_client.describe_images(
                  Owners = [
                      os.environ['AWS_ACCOUNT']
                  ],
                  Filters = [
                      {
                          'Name': 'description',
                          'Values': descriptions,
                      }
                  ]
              )['Images']

              groups = collections.defaultdict(lambda: [])
              { groups[ image['Description'] ].append(image) for image in images }

              return groups

          def _deregister_image(image_id):
              for i in range(1, 3):
                  try:
                      return ec2_client.deregister_image(
                          ImageId = image_id
                      )
                  except ClientError as e:
                      logger.exception(str(e))
                      print(str(e))
                  sleep(2)

              raise Exception('Cannot Deregister image: ' + image_id)
      Description: !Sub EC with the EC2 tag " ${EC2TagName} = n (number of generations) " Create a 2-instance image (AMI+Snapshot) on a regular basis.
      FunctionName: !Sub ${FunctionName}
      Handler: index.lambda_handler
      MemorySize: 128
      Role: !Sub 'arn:aws:iam::${AWS::AccountId}:role/${RoleName}'
      Runtime: python3.6
      Timeout: 300
      Environment:
        Variables:
          'AWS_ACCOUNT': !Sub ${AWS::AccountId}
          'NO_REBOOT': !Sub ${NoReboot}
          'TAG_NAME': !Sub ${EC2TagName}
      Tags:
        - Key: Name
          Value: !Sub ${FunctionName}
        - Key: CloudformationArn
          Value: !Ref 'AWS::StackId'
  Rule:
    Type: 'AWS::Events::Rule'
    Properties:
      Description: !Sub ${EventName}
      Name: !Sub ${EventName}
      ScheduleExpression: !Sub '${Schedule}'
      State: ENABLED
      Targets:
        - Arn: !GetAtt 
            - Lambda
            - Arn
          Id: lambda
  LambdaEvent:
    Type: 'AWS::Lambda::Permission'
    Properties:
      Action: 'lambda:InvokeFunction'
      FunctionName: !Ref Lambda
      Principal: events.amazonaws.com
      SourceArn: !GetAtt 
        - Rule
        - Arn

AMI登録削除後に対象AMIのスナップショット削除用CloudFormationテンプレート(event_ec2-snapshot-delete-after-ec2-ami-deregister.yml)

AMI登録解除時にDeregisterImageというAWS API Call が呼び出されたときにEventBridge経由にてAMI登録解除対象のスナップショット削除するものです。Lambdaでは下記の処理を行います。

  • AMI登録解除対象のスナップショット削除

AMI定期取得用CloudFormationテンプレート(schedule_create-ami-generations.yml)の内容は下記となります。
CloudFormationスタック作成時に入力が必要となるパラメータを説明します。

  • EventName :Event名(初期値:Delete-ec2-snapshot-after-ami-deregister_event)
  • FunctionName:Lambda関数名(初期値:Delete-ec2-snapshot-after-ami-deregister)
  • RoleName : Lambda関数で利用するIAMロール名(初期値:Delete-ec2-snapshot-after-ami-deregister)

snip_20200702191646.png

event_ec2-snapshot-delete-after-ec2-ami-deregister.yml
AWSTemplateFormatVersion: 2010-09-09
Parameters:
  RoleName:
    Type: String
    Default: Delete-ec2-snapshot-after-ami-deregister
  FunctionName:
    Type: String
    Default: Delete-ec2-snapshot-after-ami-deregister
  EventName:
    Type: String
    Default: Delete-ec2-snapshot-after-ami-deregister_event
Resources:
  LambdaRole:
    Type: 'AWS::IAM::Role'
    Properties:
      RoleName: !Sub '${RoleName}'
      AssumeRolePolicyDocument:
        Statement:
          - Action:
              - 'sts:AssumeRole'
            Effect: Allow
            Principal:
              Service:
                - lambda.amazonaws.com
        Version: 2012-10-17
      ManagedPolicyArns:
        - 'arn:aws:iam::aws:policy/AWSLambdaExecute'
        - 'arn:aws:iam::aws:policy/AmazonEC2FullAccess'
      Path: /
  Lambda:
    Type: 'AWS::Lambda::Function'
    Properties:
      Code:
      Code:
        ZipFile: |
          import os
          import boto3

          from logging import getLogger, INFO
          from time import sleep
          from botocore.exceptions import ClientError

          logger = getLogger()
          logger.setLevel(INFO)

          client = boto3.client('ec2')

          def lambda_handler(event, context):
              detail = event['detail']
              requestParameters = detail['requestParameters']
              imageID = requestParameters['imageId']

              response = client.describe_snapshots(
                  OwnerIds = [
                      os.environ['AWS_ACCOUNT']
                  ],
                  Filters = [
                      {
                          'Name': 'description',
                          'Values': [ 'Created by CreateImage(*) for ' + imageID + ' from *' ]
                      }
                  ]
              )
              for snapshot in response['Snapshots']:
                  logger.info(imageID)
                  logger.info("delete_snapshot: " + snapshot['SnapshotId'])
                  print("delete_snapshot: " + snapshot['SnapshotId'])
                  _delete_snapshot(snapshot['SnapshotId'])
          def _delete_snapshot(snapshotid):
              try:
                  return client.delete_snapshot(SnapshotId=snapshotid)
              except ClientError as e:
                  logger.exception("Received error: %s", e)
                  sleep(2)
      Description: Once the AMI has been unregistered (the AWS API Call on DeregisterImage is Lambda to delete all snapshots associated with that AMI ID (if called). Execute function delete_snapshot_after_ami_deregister.
      FunctionName: !Sub ${FunctionName}
      Handler: index.lambda_handler
      MemorySize: 128
      Role: !Sub 'arn:aws:iam::${AWS::AccountId}:role/${RoleName}'
      Runtime: python3.6
      Timeout: 300
      Environment:
        Variables:
          'AWS_ACCOUNT': !Sub ${AWS::AccountId}
      Tags:
        - Key: Name
          Value: !Sub ${RoleName}
        - Key: CloudformationArn
          Value: !Ref 'AWS::StackId'
  Rule:
    Type: 'AWS::Events::Rule'
    Properties:
      Description: !Sub ${EventName}
      Name: !Sub ${EventName}
      EventPattern: 
        source: 
          - "aws.ec2"
        detail-type: 
          - "AWS API Call via CloudTrail"
        detail: 
          eventSource: 
            - "ec2.amazonaws.com"
          eventName: 
            - "DeregisterImage"
      State: "ENABLED"
      Targets:
        - Arn: !GetAtt 
            - Lambda
            - Arn
          Id: lambda
  LambdaEvent:
    Type: 'AWS::Lambda::Permission'
    Properties:
      Action: 'lambda:InvokeFunction'
      FunctionName: !Ref Lambda
      Principal: events.amazonaws.com
      SourceArn: !GetAtt 
        - Rule
        - Arn
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

最低限押さえておくべきAWSアカウント開設時のセキュリティ対策4つ

1. rootユーザーを利用せず、IAMユーザーを利用する

rootユーザーは権限が非常に強い。
なので、IAMユーザーを作成する。
IAMでユーザーを作成すればrootユーザーと同じようにAWSを利用でき、かつ権限管理が可能。

2. AWS CloudTrailを有効化する

AWSに対する各種APIアクセスについてロギングするサービス。
AWS上で行われた操作はこのサービスで記録される。

3. AWS Configを有効化する

AWSリソースの変更履歴を管理するサービス。
何がどのように変更された追随できる。

AWS Configは各リージョンごとに設定する必要がある。

4. Amazon GuardDutyを有効化する

AWS上のさまざまな脅威を検知するサービス。
AWS上で非常に発生しやすいアクセスキーの漏洩事故や、その結果起きる不正なコインマイニングを検知したり、外部からのブルートフォースアタックを検知したりと非常に強力。
本番環境だけでなく、開発環境でよく発生するため、すべてのAWSアカウントで有効化が必須。

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

RDSのインスタンス変更をキャンセルする

tl;dr

AWS CLIで以下コマンドを叩く。

aws rds modify-db-instance --db-instance-identifier {DBインスタンス名} --db-instance-class {変更前のインスタンスクラス} --apply-immediately

経緯

手が滑ってRDSのインスタンスタイプを変更してしまった、、、
スクリーンショット 2020-07-02 19.18.46.png

こんな感じで「保留中の変更」が表示されるようになったが、キャンセル方法が分からない。もう一度もとのインスタンスタイプに変更すればいいのかと思ったが、Webコンソールではできない。
次のメンテナンスウィンドウまでにどうにかしないとまずいのでサポートケースを上げたところ、CLIなら可能とのこと。コマンド再掲。

aws rds modify-db-instance --db-instance-identifier {DBインスタンス名} --db-instance-class {変更前のインスタンスクラス} --apply-immediately

焦っていて見つけられなかったが、ドキュメントにもちゃんと書いてあった。
https://docs.aws.amazon.com/ja_jp/AmazonRDS/latest/UserGuide/Overview.DBInstance.Modifying.html

次のメンテナンスウィンドウで保留中の変更を適用しない場合は、変更を元に戻すように DB インスタンスを変更できます。これを行うには、AWS CLI を使用し、--apply-immediately オプションを指定します。

スケジュールされている変更は以下コマンドで確認可能。空で返ってくればインスタンス変更はちゃんとキャンセルされたということ。これはWebコンソールでも確認可能。実際キャンセル後に見てみたら↑の画像の「保留中の変更」が消えていた。

aws rds describe-db-instances --db-instance-identifier {DBインスタンス名} --query 'DBInstances[].[PendingModifiedValues]'


教訓: Webコンソールでいじった内容をWebコンソールで戻せると思ったら負け。

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

AWS認定デベロッパー受験

AWS認定 デベロッパーアソシエイトの勉強メモ

  • そもそも概要すら分からないAWSサービス、似ているので使い所の違いが分からないAWSサービス、疑問に思った点についてメモしておきます。あやふやだなと思った時に何だっけ?と思い出すためのメモです。

  • なお、勉強に使わせていただいた多くの資料はAWSさんのBlackBeltと公式ドキュメントです。
    個人の方の資料も使わせていただいておりますが、その場合は元のwebページのリンクを貼らせていただきました。

  • 読んでいただいた方のお役に立てれば嬉しいです。

1.SAM、BeanStalk、Lightsail

SAM(Serverless Application Model)

  • サーバレス実行環境をSAMテンプレートから構築する(SAMテンプレートはCloudFormationテンプレートに変換される、SAMテンプレートの方が可読性が高いらしい)
  • sam(CLI)コマンドで設定する image.png

Elastic Beanstalk

  • ビーン・ストーク(豆・茎)
  • EC2上にWordPressなどのアプリケーション実行環境を構築する
  • eb(CLI)コマンド image.png

LightSail

  • EC2上にWordPressやDrupal(コンテンツ管理システム)、Redmine(チームコミュニケーション)などのwebアプリケーションを構築するサービス(目的のアプリケーションが見つかれば便利なのかもしれませんが...) image.png

2.Beanstalk, CloudFormation, OpsWorks

  • 現場で使う局面(違い)をしっかり覚える! image.png

3.CDK(Cloud Development Kit)

  • コードでAWSリソースが作れるとは... image.png

様々なツールによりCode化しているけど、結局はCloudFormationが使用されていることが分かりました(cfnの上で成り立っている)。

 ==============================
 | SAM | Beanstalk | StepFunctions | CDK |
 ==============================
 | CloudFormation(cfn) |
 ==============================

4.CloudTrail

image.png

5.Config

image.png

6.Step Functions

7.SWF(Amazon Simple Workflow)

8.API Gateway

REST, WebSocket
image.png

9.AppSync

GraphQL

10.Cognito sync

11.ACM(AWS Certificate Manager)とIAMのサーバ証明書管理

ALB構築時にACMかIAMを選べるけど今はACM一択。昔はIAMだけだった事の名残だって。
image.png

12.Secret Manager

  • DBなどのIDとパスワード管理

13.KMS(Key Management Service)、CloudHSM

  • 保管データの暗号化

14.SQSとMQの違い

  • 既存のアプリケーションで処理しているメッセージング機能をクラウドにすばやく簡単に移したい場合、Amazon MQ の使用をお勧めします。業界標準の API とプロトコルがサポートされているため、どのような標準に準拠したメッセージブローカーからでも、アプリケーション内のメッセージングコードを書き換えることなく Amazon MQ に切り替えられます。クラウド上でまったく新しいアプリケーションを構築される場合は、Amazon SQS と Amazon SNS のご検討をお勧めします。Amazon SQS と SNS は、ほぼ無制限にスケーリングでき、シンプルで使いやすい API を提供する、軽量な完全マネージド型のメッセージキューサービスおよびトピックサービスです。

15.データウェアハウスとデータレークの違い

image.png
image.png

16.Auto Scaling

  • EC2 Auto Scaling と Application Auto Scaling
    image.png

  • 希望容量=最大容量と最小容量の間に収まる変数のイメージ
    image.png

17.DynamoDB

プライマリキー=インデックスとLSIGSIイメージ図

image.png

スクリーンショット 2020-05-05 15.51.53.png

18.DynamoDB Stream

  • 用途はポイントインタイムリカバリ、キャッシュ image.png

19.SQS

  • キューに保存できるメッセージの最大数は、前者(バックログ)と後者(インフライト)で異なる。 image.png

20.Cognito

  • ユーザープールとIDプールの違い image.png

image.png

21.S3 暗号化

image.png

22.Route53

ルーティングポリシー

23.IDフェデレーション

image.png

24.PFS

Perfect Forward Secrecy→p42
image.png

25.IAM

  • 以下の全体像は俯瞰して見えるのでとっても良いです image.png

26.KMS

GenerateDataKey
GenerateDataKeyWithoutPlaintext

27.AWS Elastic Beanstalkのデプロイメントポリシー(デプロイ方法の種類)

28.ECSタスク配置戦略

29.透過的暗号化

30.インスタンスプロファイル,IAMロール

31.DB オプティミスティックロックとペシミスティックロック

32.DynamoDB バージョン番号を使用したオプティミスティックロック

33.DynamoDB アトミックカウンタ

34.utube of DynamoDB

35.API Gateway 統合タイプ

36.SQS リトライ

37.STS AssumeRole GetSessionToken

38.STS API

出来るだけ記憶に定着させる勉強を心掛けました。
楽しみつつ日々精進です:smiley:

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

AWS認定デベロッパーアソシエイトの勉強メモ

  • そもそも概要すら分からないAWSサービス、似ているので使い所の違いが分からないAWSサービス、疑問に思った点についてメモしておきます。あやふやだなと思った時に何だっけ?と思い出すためのメモです。

  • なお、勉強に使わせていただいた多くの資料はAWSさんのBlackBeltと公式ドキュメントです。
    個人の方の資料も使わせていただいておりますが、その場合は元のwebページのリンクを貼らせていただきました。

  • 読んでいただいた方のお役に立てれば嬉しいです。

1.SAM、BeanStalk、Lightsail

  • SAM(Serverless Application Model)
  • サーバレス実行環境をSAMテンプレートから構築する(SAMテンプレートはCloudFormationテンプレートに変換される、SAMテンプレートの方が可読性が高いらしい)
  • sam(CLI)コマンドで設定する
    image.png

  • Elastic Beanstalk

  • ビーン・ストーク(豆・茎)

  • EC2上にWordPressなどのアプリケーション実行環境を構築する

  • eb(CLI)コマンド
    image.png

  • LightSail

  • EC2上にWordPressやDrupal(コンテンツ管理システム)、Redmine(チームコミュニケーション)などのwebアプリケーションを構築するサービス(目的のアプリケーションが見つかれば便利なのかもしれませんが...)
    image.png

2.Beanstalk, CloudFormation, OpsWorks

  • 現場で使う局面(違い)をしっかり覚える! image.png

3.CDK(Cloud Development Kit)

  • コードでAWSリソースが作れるとは... image.png

様々なツールによりCode化しているけど、結局はCloudFormationが使用されていることが分かりました(cfnの上で成り立っている)。

 ==============================
 | SAM | Beanstalk | StepFunctions | CDK |
 ==============================
 | CloudFormation(cfn) |
 ==============================

4.CloudTrail

image.png

5.Config

image.png

6.Step Functions

7.SWF(Amazon Simple Workflow)

8.API Gateway

REST, WebSocket
image.png

9.AppSync

GraphQL

10.Cognito sync

11.ACM(AWS Certificate Manager)とIAMのサーバ証明書管理

ALB構築時にACMかIAMを選べるけど今はACM一択。昔はIAMだけだった事の名残だって。
image.png

12.Secret Manager

  • DBなどのIDとパスワード管理

13.KMS(Key Management Service)、CloudHSM

  • 保管データの暗号化

14.SQSとMQの違い

  • 既存のアプリケーションで処理しているメッセージング機能をクラウドにすばやく簡単に移したい場合、Amazon MQ の使用をお勧めします。業界標準の API とプロトコルがサポートされているため、どのような標準に準拠したメッセージブローカーからでも、アプリケーション内のメッセージングコードを書き換えることなく Amazon MQ に切り替えられます。クラウド上でまったく新しいアプリケーションを構築される場合は、Amazon SQS と Amazon SNS のご検討をお勧めします。Amazon SQS と SNS は、ほぼ無制限にスケーリングでき、シンプルで使いやすい API を提供する、軽量な完全マネージド型のメッセージキューサービスおよびトピックサービスです。

15.データウェアハウスとデータレークの違い

image.png
image.png

16.Auto Scaling

  • EC2 Auto Scaling と Application Auto Scaling
    image.png

  • 希望容量=最大容量と最小容量の間に収まる変数のイメージ
    image.png

17.DynamoDB

プライマリキー=インデックスとLSIGSIイメージ図

image.png

スクリーンショット 2020-05-05 15.51.53.png

18.DynamoDB Stream

  • 用途はポイントインタイムリカバリ、キャッシュ image.png

19.SQS

  • キューに保存できるメッセージの最大数は、前者(バックログ)と後者(インフライト)で異なる。 image.png

20.Cognito

  • ユーザープールとIDプールの違い image.png

image.png

21.S3 暗号化

image.png

22.Route53

ルーティングポリシー

23.IDフェデレーション

image.png

24.PFS

Perfect Forward Secrecy→p42
image.png

25.IAM

  • 以下の全体像は俯瞰して見えるのでとっても良いです image.png

26.KMS

GenerateDataKey
GenerateDataKeyWithoutPlaintext

27.AWS Elastic Beanstalkのデプロイメントポリシー(デプロイ方法の種類)

28.ECSタスク配置戦略

29.透過的暗号化

30.インスタンスプロファイル,IAMロール

31.DB オプティミスティックロックとペシミスティックロック

32.DynamoDB バージョン番号を使用したオプティミスティックロック

33.DynamoDB アトミックカウンタ

34.utube of DynamoDB

35.API Gateway 統合タイプ

36.SQS リトライ

37.STS AssumeRole GetSessionToken

38.STS API

出来るだけ記憶に定着させる勉強を心掛けました。
楽しみつつ日々精進です:smiley:

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

DocumentDBって何?出身は?現在付き合っている彼氏は⁈

はじめに

この記事はMongoDBをまったく知らない筆者がゼロからDocumentDBを学んでまとめたものになります。
今までのDBの経験といえば
- MySQL(2年とか)
- Redis(半年とか)
- DynamoDB(3ヶ月とか)
- Spanner(1瞬)
ぐらいでNoSQLよリRDBMSの方が歴も長く、得意といった感じです。
DB設計はいくつかのサービスで経験しましたが、設計&運用をした経験がほとんどないので、
スケールにめっちゃ自信があるわけではないですが、スケールを考えたキーの命名とかはRedis、DynamoDBあたりでは徹底的に議論した覚えがあります。それでは徒然なるままに始めていきたいと思います。

MongoDBとは

NoSQLといえば、シンプルな検索機能が大きなメリットといえます。
KVSのNoSQLであれば、データをキーバリューの連想配列で保持して検索のスピードが速いです。
RedisはKVSで私は主にC向けのサービスを作っていた時はランキング機能に使っていました。
データが単純だが、件数が多いとRedisを使うと良いという認識でした。
また、Redisはキャッシュとしても有名ですよね。
今回のMongoDBはドキュメント指向データベースと呼ばれる種類のデータベースです。
DynamoDBと同じ種類ですね。
ドキュメント指向データベースでは、文字通りデータをドキュメントとして扱います。
ドキュメントのデータ構造は自由で、スキーマレスでスケールがしやすいのがメリットといえます。

そもそもNoSQLってなんで生まれたん?

最後にDynamoDBを触ったのが半年近く前なのでNoSQLについて忘れてしまいました。
簡単に復習します。
NoSQLが生まれた理由はビッグデータの登場が大きいらしいです。
ビッグデータの定義は様々ですが、ここでのビッグデータは3V(Volume,Velocity,Variety)を満たしたデータということにして起きます。
ビッグデータの登場以前は、構造化されたデータを扱うクライアント・サーバサイド型のアプリケーションが主流でした。
古典的なRDMSはACIDプロパティに従います。
Atomic、Consistent、Isolated、Durableでしたね確か。
一貫性を保証するよってことです。
複数の書き込み処理や変更の処理が走ってもどのトランザクションを通してデータが一貫していることが大切です。
ビッグデータの3Vの2つ、Volume(大量のデータ)、Velocity(高頻度で高速)に対応するにはスケールを考える必要があります。
スケールは2種類あって、スケールアップ、スケールアウトの2つです。
スケールアップは個々のDBサーバの性能をあげること(メモリ容量、CPUのスペック上げるorCPUの数を増やす)で、スケールアウトはDBサーバの数を増やして全体の処理性能を上げることです。
並列処理が行われるような設計にする必要がありますが、今のクラウドだと負荷を検知して自動でスケールしてくれるサービスもあるのであまり意識しなくても良いのかもしれません。

DynamoDBと何が違うの?

DynamoDBもDocumentDBと同様にNoSQLです。
1番の違いと言えば、アクセスパターンが多いことです。
具体的にDynamoDBとの1番の優位性はindexに依存しないクエリが可能なことと菊池さんもおっしゃっています。

https://www.slideshare.net/skikuchi/jaws-days-2019-amazon-documentdbwith-mongodb-compatibility

また、DocumentDBではネストしたデータのフィールドにもインデックスが貼れるらしいです。

DocumentDBのプロコン

プロ

高速&スケーラブル

ストレージの量がすっごい 64TB

高可用性

可用性が99.99%
インスタンスに障害が発生したらインスタンスを30秒以内で再起動
マスターインスタンスが死んだらリードレプリカに自動でフェイルオーバー

コン

トランザクションがない

MongoDBのバージョン4以降ではトランザクションの処理が加わるらしいですが、
現在DocumentDBが対応しているMongoDBのバージョンは3.6です。

データ量が多くなりがち

RDBと比べるとデータ量が多くなりがちらしいです。なんでだろう保存の仕方が問題なのか。DB設計上データ量が多くなる?知っている方がいたら教えて欲しいです。

まとめ

DocumentDBは2019年1月に発表されて現在は東京リージョンもあるAWSの完全マネージド型のドキュメント指向データベースです。
インデックスの貼り方をミスらなければかなり良いDBな気がしました。
これから具体的なサービスに落とし込んでいきたいと思います。いい感じにTipsを共有していきっます

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

Axios で Node.js で発行した S3 の署名付き URL へアップロードすると 403 エラーになる

Nuxt.js から Node.js に S3 の署名付き URL をリクエストするような状況でつまったところの忘備録です。

s3 の Bucket の CORS 設定をする

s3 のドメインとサイトのドメインが異なるなら設定しておきましょう。
アップロードのみできれば良いなら許可は PUT だけで良いと思います。

<?xml version="1.0" encoding="UTF-8"?>
<CORSConfiguration xmlns="http://s3.amazonaws.com/doc/2006-03-01/">
  <CORSRule>
    <AllowedOrigin>*</AllowedOrigin>
    <AllowedMethod>PUT</AllowedMethod>
    <AllowedHeader>*</AllowedHeader>
  </CORSRule>
</CORSConfiguration>

リージョンを指定する

署名バージョンを 4 に指定する

無いと失敗するようです…?

AWS_DEFAULT_REGION などは内部で勝手に使ってくれると思っていたのですが指定したほうが良さそうです。

// on server
const sts = new STS({
  accessKeyId: process.env.ACCESS_KEY_ID,
  secretAccessKey: process.env.SECRET_ACCESS_KEY,
  region: process.env.AWS_DEFAULT_REGION, // ★
})
app.get('/get-signed-url', async (req, res) => {
  const { Credentials } = await sts
    .assumeRole({
      RoleArn: process.env.STS_ROLE_ARN,
      RoleSessionName: process.env.STS_ROLE_SESSION_NAME,
    })
    .promise()
  if (!Credentials) return Promise.reject(new Error('failed to get credencials'))
  const s3 = new S3({
    accessKeyId: Credentials.AccessKeyId,
    secretAccessKey: Credentials.SecretAccessKey,
    sessionToken: Credentials.SessionToken,
    region: process.env.AWS_DEFAULT_REGION, // ★
    signatureVersion: 'v4', // ★
  })
  const Key = randomString(128)
  const putUrl = await s3.getSignedUrlPromise('putObject', {
    Bucket,
    Key,
    ContentType: req.query.mimetype,
    Metadata: { 'user-name': 'hogehoge' },
    Expires: 60,
  })
  res.json({ putUrl, Key })
})

余計なヘッダーを送らないようにする

put するときに余計なヘッダーをつけて送ると 403 SignatureDoesNotMatch が返ってきます。
Axios のデフォルトの headers に Authorization を入れている場合などは注意が必要だと思います。

// front
export default Vue.extend({
  methods: {
    async upload(rawFile: File) {
      const prepareUrl = new URL(process.env.API_URL + '/get-signed-url')
      prepareUrl.searchParams.append('filename', rawFile.name)
      prepareUrl.searchParams.append('mimetype', rawFile.type)
      this.$axios.setToken(this.$store.getters['auth/accessToken'], 'Bearer')
      const { putUrl } = await this.$axios.$get(prepareUrl.toString())

      this.$axios.setToken(false) // ★ Authorization ヘッダーが送られないように
      await this.$axios.$put(putUrl, rawFile, {
        headers: {
          'Content-Type': rawFile.type,
          // 'X-Amz-Acl': 'private', // ★ 間違えてつけてると 403 になります
        }
      })
    }
  }
})

参考

https://qiita.com/kochizufan/items/444b7e1dfcf568945410
https://docs.aws.amazon.com/ja_jp/AmazonS3/latest/dev/cors.html
https://qiita.com/kyasbal_1994/items/774be5624e4d90c5cf38
https://qiita.com/segur/items/7746ac352afb5152cf46

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

Cloud9のMySQLをバージョンアップする方法

mysql.png

現時点でのMySQLバージョンを確認

$ mysql --version

旧バージョン(5.5)パッケージを削除

$ sudo yum -y remove mysql-config mysql55-server mysql55-libs mysql55

新バージョン(5.7)パッケージをインストール

$ sudo yum -y install mysql57-server mysql57

日本語文字化け対策

$ sed -e "/utf8/d" -e "/client/d" -e "/^\[mysqld_safe\]$/i character-set-server=utf8\n\n[client]\ndefault-character-set=utf8" /etc/my.cnf |sudo tee /etc/my.cnf

MySQLの起動

$ sudo service mysqld start

設定を読み込み直すために再起動

$ sudo service mysqld restart

MySQLのバージョンを確認

$ mysql --version

バージョンが5.7になっていれば成功です。

MySQLコンソールに接続して動作確認

$ mysql -u root

データベースに接続してみて問題がないか確認します。

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

Cloud9でLaravelの開発環境を構築する方法

laravel.jpg

AWSマネジメントコンソールからCloud9を選択

img1.png

Create environmentを選択

img2.png

プロジェクト名を入力し、Next stepを選択

ここではlaravel_projectとします。

img3.png

特にこだわりがなければデフォルトのままNext stepを選択

img4.png

設定に変更がなければCreate environmentを選択

すると画面が切り替わってCloud9が起動しますので、操作できるようになるまでしばらく待ちます。

img5.png

PHPをアップデート

$ sudo yum -y update
$ sudo yum -y install http://rpms.famillecollet.com/enterprise/remi-release-6.rpm
$ sudo yum -y install php73 php73-mbstring php73-pdo php73-mysqlnd // PHP7.3をインストール
$ sudo unlink /usr/bin/php // リンクがPHP5.6に貼られているので解除
$ sudo ln -s /etc/alternatives/php7 /usr/bin/php // リンクをPHP7.3に張り替え
$ php -v

バージョンを確認して下記のように表示されればリンク設定まで完了です。

PHP 7.3.17 (cli) (built: May  7 2020 21:04:09) ( NTS )
Copyright (c) 1997-2018 The PHP Group
Zend Engine v3.3.17, Copyright (c) 1998-2018 Zend Technologies

Composerをインストール

ComposerはPHPのライブラリ管理ツールです。RubyでいうところのGemに該当します。

$ curl -sS https://getcomposer.org/installer | php // composer.pharが自動で生成される
$ sudo mv composer.phar /usr/local/bin/composer // composer.pharを移動させる

Composerが正常にインストールされたか、下記のコマンドにて確認します。

$ composer

「Composer」という文字の、大きなアスキーアートが表示されれば完了です。

スワップファイルを作成

現時点でLaravelプロジェクトを作成しようとすると、メモリ不足で失敗します。そこでスワップファイルを作成します。

$ sudo /bin/dd if=/dev/zero of=/var/swap.1 bs=1M count=1024
$ sudo /sbin/mkswap /var/swap.1
$ sudo /sbin/swapon /var/swap.1

Laravelプロジェクトを作成

$ composer create-project laravel/laravel ./myapp --prefer-dist

ディレクトリ内にmyappが作成されます。

Laravelサーバの起動

$ cd myapp
$ php artisan serve --port=8080

上記のコマンドを実行後、次のように表示されれば起動は完了です。

$ Laravel development server started: http://127.0.0.1:8080

Cloud9画面上のメニューのPreviewを押し、「Preview Running Application」を実行すると下の画面のように表示されます。

img6.png

無事Cloud9にLaravelを導入することができました。

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

AWS EC2 AmazonLinux 2でGitHubからクローンしたdocker-compose.ymlを動かす

お気軽検証環境を作る必要があったのでその時のメモ。
プルするときに毎回パスワード聞いてくるようにしたかったのでcloneは意図的にhttpsを使っています。

EC2

前準備

$ sudo yum update

Gitのインストール

$ sudo yum install git
...
$ git version
git version 2.23.3

GitHubからクローン

$ git clone https://github.com/xxxx/xxxx.git
Cloning into 'xxxx'...
Username for 'https://github.com': // ユーザー名の入力
Password for 'https://xxxx@github.com': // パスワードの入力

Dockerのインストール

$ sudo amazon-linux-extras install docker
...
$ sudo service docker start

docker-compose のインストール

$ sudo curl -L "https://github.com/docker/compose/releases/download/1.23.2/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose
...
$ sudo chmod +x /usr/local/bin/docker-compose
...
$ docker-compose --version

起動

$ docker-compose up -d

「ERROR: Couldn't connect to Docker daemon」が発生する場合

DockerでCouldn’t connect to Docker daemonが出る場合の原因と解決方法
ユーザをdockerグループに入れる

$ sudo usermod -aG docker $USER

起動時に「no space left on device」が発生する場合

EC2のボリュームを増やす

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

EC2のEBSのボリュームを増やす手順

aws console

  • ボリュームを拡張したいEC2インスタンスに紐づいているEBSを確認
  • EBSのボリュームを変更する"in-use - optimizing (0%)"になっていることを確認する

EC2

ボリュームサイズ変更後の Linux ファイルシステムの拡張

ボリュームのファイルシステムの識別

$ sudo file -s /dev/xvd*
/dev/xvda:  x86 boot sector; partition 1: ID=0xee, starthead 0, startsector 1, 16777215 sectors, extended partition table (last)\011, code offset 0x63
/dev/xvda1: SGI XFS filesystem data (blksz 4096, inosz 512, v2 dirs)

パーティションの拡張

確認

xvdaとxvda1のサイズが違うの拡張する必要あり

$ lsblk
NAME    MAJ:MIN RM SIZE RO TYPE MOUNTPOINT
xvda    202:0    0  16G  0 disk
└─xvda1 202:1    0   8G  0 part /

拡張

$ sudo growpart /dev/xvda 1
CHANGED: partition=1 start=4096 old: size=16773087 end=16777183 new: size=33550303 end=33554399

再確認

xvdaとxvda1が同じサイズであれば拡張成功

$ lsblk
NAME    MAJ:MIN RM SIZE RO TYPE MOUNTPOINT
xvda    202:0    0  16G  0 disk
└─xvda1 202:1    0  16G  0 part /

ファイルシステムの拡張

確認

まだファイルシステムのサイズは拡張前のままであることを確認

$ df -h
ファイルシス   サイズ  使用  残り 使用% マウント位置
devtmpfs         474M     0  474M    0% /dev
tmpfs            492M     0  492M    0% /dev/shm
tmpfs            492M  436K  492M    1% /run
tmpfs            492M     0  492M    0% /sys/fs/cgroup
/dev/xvda1       8.0G  4.6G  3.5G   58% /
tmpfs             99M     0   99M    0% /run/user/1000

拡張

AWSのドキュメントではresize2fsコマンドを使用しているが、CentOS7からはxfs_growfsを使用する必要がある。

resize2fs: Bad magic number in super-blockとなった時の対応方法

$ sudo xfs_growfs /dev/xvda1
meta-data=/dev/xvda1             isize=512    agcount=4, agsize=524159 blks
         =                       sectsz=512   attr=2, projid32bit=1
         =                       crc=1        finobt=1 spinodes=0
data     =                       bsize=4096   blocks=2096635, imaxpct=25
         =                       sunit=0      swidth=0 blks
naming   =version 2              bsize=4096   ascii-ci=0 ftype=1
log      =internal               bsize=4096   blocks=2560, version=2
         =                       sectsz=512   sunit=0 blks, lazy-count=1
realtime =none                   extsz=4096   blocks=0, rtextents=0
data blocks changed from 2096635 to 4193787

再確認

サイズが拡張されていることを確認する

$ df -h
ファイルシス   サイズ  使用  残り 使用% マウント位置
devtmpfs         474M     0  474M    0% /dev
tmpfs            492M     0  492M    0% /dev/shm
tmpfs            492M  436K  492M    1% /run
tmpfs            492M     0  492M    0% /sys/fs/cgroup
/dev/xvda1        16G  4.6G   12G   29% /
tmpfs             99M     0   99M    0% /run/user/1000
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

aws tips

Tips

調べたことを、自分用にメモ

VPCから、他VPCへのアクセス

VPCエンドポイント -> ルートテーブル -> サービス
S3バケットの利用などは使用前提でいるべし

ホスト名にアクセスをVPCへ

route53 -> alb -> サービス

自動デプロイ

ECR -> codeCmmit -> codeBuild
・buildspecをつかって、aclにてzipファイルのアップロード

Lambdaで共通関数を利用

Lambda Layer

ログ検知メール

CloudWatch(サブスクリプション -> lambda -> SNS

lambda 15分超える場合

ECR -> ECS

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

爆速でAWS EC2(Amazon Linux)環境でHTTPS環境を建てる方法 (Caddy)

EC2でHTTPS化するの面倒

HTTPSは人権!
でもEC2環境だと。ロードバランサーやCDNをつけてやるのはお金がかかる!
かといって、Let’s Encryptのコマンド叩きたくない! Nginxを触るのも面倒!
そういうことよくありませんか?

そんなお悩みCaddyなら解決します!

Caddyを使えば、Let’s Encryptの証明書をとってきて、自動でリダイレクトまでやってくれる!
HTTP/2対応! Golangで書かれててなんかすごい気がする!
さああなたも試しましょう!

環境

マシン: EC2 t2.micro インスタンス

OS: Amazon Linux (Amazon Linux 2 AMI (HVM), SSD Volume Type - ami-0a1c2ec61571737db)

How to

ドメインの購入と、EC2のIP固定と、ドメインのAレコードをEC2のIPに向けるのは省略!
あともちろんセキュリティグループの設定で、ポート80と443はパブリックアクセスするのを忘れずに!

できた人は、SSHでEC2に入ります。

その後以下のコマンドを実行!

$ sudo amazon-linux-extras install epel

$ sudo yum install caddy

$ cd /etc/caddy/conf.d

$ sudo vim xxx.conf

以下の通りに編集!

example.jp {
  # 公開するディレクトリのパスを書くだけ
  root /var/www/public
}
$ sudo service caddy start

$ sudo service caddy status

なんとこれだけで対応したドメインでHTTPS化をして、HTTPからのリダイレクトもやってくれる...
つよい...

リバースプロキシしたい!

Node.jsとかで書いたAPIをHTTPSで出したいけど、リバースプロキシは面倒!
そんなお悩みもCaddyで解決!
さきほどのxxx.confを以下の通りにするだけ!

example.jp {
  # proxy パス プロキシするアドレスとポート
  proxy / localhost:8080

  # socket.ioを使用する場合は、websocketを追記するだけ!
  proxy /socket.io localhost:8080 {
        websocket
  }
}

※conf書き換えたら、ちゃんとリスタートしよう

$ sudo service caddy restart

Nginxなら数行書かないと対応しないWebSocketも一行で対応!
これは便利!

インスタンスが再起動しても動かしたい

このままだとインスタンスの再起動を行うと自動的に上がってこないので、その方法も紹介

$ sudo systemctl enable caddy

ちゃんと確認も...
$ systemctl is-enabled caddy

まとめ

これなら、AWSの無料枠のEC2でも気軽にHTTPS化!
タノシイ!

※ プロダクション環境では、もう少しちゃんとした方がいいです
※ Caddyのドキュメントわかりずらいと思うの自分だけ?
※ Amazon Linuxの例がなかったので書いてみた

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

爆速! AWS EC2(Amazon Linux)環境でHTTPS環境を建てる方法 (Caddy)

EC2でHTTPS化するの面倒

HTTPSは人権!
でもEC2環境だと。ロードバランサーやCDNをつけてやるのはお金がかかる!
かといって、Let’s Encryptのコマンド叩きたくない! Nginxを触るのも面倒!
そういうことよくありませんか?

そんなお悩みCaddyなら解決します!

Caddyを使えば、Let’s Encryptの証明書をとってきて、自動でリダイレクトまでやってくれる!
HTTP/2対応! Golangで書かれててなんかすごい気がする!
さああなたも試しましょう!

環境

マシン: EC2 t2.micro インスタンス

OS: Amazon Linux (Amazon Linux 2 AMI (HVM), SSD Volume Type - ami-0a1c2ec61571737db)

How to

ドメインの購入と、EC2のIP固定と、ドメインのAレコードをEC2のIPに向けるのは省略!
あともちろんセキュリティグループの設定で、ポート80と443はパブリックアクセスするのを忘れずに!

できた人は、SSHでEC2に入ります。

その後以下のコマンドを実行!

$ sudo amazon-linux-extras install epel

$ sudo yum install caddy

$ cd /etc/caddy/conf.d

$ sudo vim xxx.conf

以下の通りに編集!

example.jp {
  # 公開するディレクトリのパスを書くだけ
  root /var/www/public
}
$ sudo service caddy start

$ sudo service caddy status

なんとこれだけで対応したドメインでHTTPS化をして、HTTPからのリダイレクトもやってくれる...
つよい...

リバースプロキシしたい!

Node.jsとかで書いたAPIをHTTPSで出したいけど、リバースプロキシは面倒!
そんなお悩みもCaddyで解決!
さきほどのxxx.confを以下の通りにするだけ!

example.jp {
  # proxy パス プロキシするアドレスとポート
  proxy / localhost:8080

  # socket.ioを使用する場合は、websocketを追記するだけ!
  proxy /socket.io localhost:8080 {
        websocket
  }
}

※conf書き換えたら、ちゃんとリスタートしよう

$ sudo service caddy restart

Nginxなら数行書かないと対応しないWebSocketも一行で対応!
これは便利!

インスタンスが再起動しても動かしたい

このままだとインスタンスの再起動を行うと自動的に上がってこないので、その方法も紹介

$ sudo systemctl enable caddy

ちゃんと確認も...
$ systemctl is-enabled caddy

まとめ

これなら、AWSの無料枠のEC2でも気軽にHTTPS化!
タノシイ!

※ プロダクション環境では、もう少しちゃんとした方がいいです
※ Caddyのドキュメントわかりずらいと思うの自分だけ?
※ Amazon Linuxの例がなかったので書いてみた

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

AWSマネージメントコンソールでスイッチロールしてから時間が経った後の操作にはご注意を

はじめに

本記事では、AWSマネージメントコンソールの挙動によって生じた一見不可解な現象について紹介します。

自分は原因が分かるまでちょっとハマってしまいましたので、もし似たような事象に遭遇した方のお役に立てればと思い、投稿いたしました。

何が起こったのか

ACMで発行した証明書を更新するため、検証用Eメールの再送信コマンドを実行しました。実行すると以下の画面が表示されたので、成功して検証メールが送信されたものと思っていました。
ACM-成功.png
ところが、実際には検証メールは送信されていませんでした。

このドメインは自己保有ではなく、サブドメインを移譲してもらって運用していたため、検証メールも移譲元のドメイン宛てに送信され、先方で承認してもらう事になります。そのため、メールが実際に送信されていたかどうかはこちらでは確認出来ない状況でした。

証明書のステータスを確認してもなかなか検証済みにならないので、先方に問い合わせたところ、メールが届いていなかった事が判明しました。

原因

メールが送信されなかった原因は、マネージメントコンソールのセッションの期限切れでした。

当時は作業の1時間以上前にログインしてからACMの画面を開いたままにしていました。その状態で検証メールの再送信を実行すると前述の成功画面が表示されたのですが、実際にはロールセッションの持続時間(1時間)を超えていたため操作は失敗していました。

セッションが切れた状態でコマンドが実行でき、かつ実行出来ていないにも関わらず結果が成功と表示されてしまう挙動のため、なかなか原因にたどり着くことが出来ませんでした。

対策

今回の経験から、マネージメントコンソールでサインインやスイッチロールしてから時間が経過した後に重要な作業をする場合は、一旦サインインし直すかロールを切り替えて戻すなどして、セッションの持続時間を更新しておくのが無難だと思いました。

また、マネージメントコンソールの代わりにAWS CLIを使うのも良い対策だと思います。AWS CLIであれば、セッション切れの場合は自動的に認証情報を更新してくれるので、セッション切れのままコマンドが実行されてしまう(しかも成功したように見える)事はありません。

補足(原因調査〜再現まで)

原因解明に至る過程などを補足しておきます。

ACMの画面だけでは検証メールが実際に送信されたかどうか判断がつかなかったので、CloudTrailからイベント履歴を調査しました。すると、検証メールを再送信した場合に記録されるはずのResendValidationEmailイベントが記録されていませんでした。従って、検証メールは送信されていなかった事が分かりました。

さらに履歴を読み進めると、画面上で再送信を実行してからしばらく後の時刻にRenewRoleイベントが記録されているのがわかり、これが原因解明の鍵となりました。

このCloudTrailの記録と自分の記憶を頼りに、今回の現象を再現することが出来ました。

  1. マネージメントコンソールにログインし、スイッチロールしてACMの画面を開く
    このまま1時間以上放置してセッションが切れるようにします

  2. 検証メールの再送信を実行
    ACM-再送信.png
    この時点ですでにセッションが切れていますが、画面上では分かりません

  3. 再送信が成功したように見える
    ACM-成功、更新.png
    実際にはResendValidationEmailリクエストは行われていません

  4. 最新のステータスを確認するため更新
    ACM-更新中.png
    更新中のまま進行しません

  5. 更新が終わらないのでブラウザのタブごとリロード
    ACM-更新後.png
    このリロードによってセッション情報が更新されたようです

再現手順の4.〜5.がハマリポイントで、4の更新ボタンで画面が固まった事によりセッション切れを示すポップアップが出ない状態となり、5でタブごとリロードした事によって意識せずにセッションが更新されています。以降は普通に操作が出来るようになりますので、セッション切れが生じていたことに気が付きませんでした。

もし3の段階で更新ボタンを押さずにしばらく待っていれば、以下の画面が出てセッション切れに気がつく事ができていました。
ACM-セッション切れ.png

以上のように、結果を待たずに成功メッセージが画面に表示される事と、更新ボタンでセッション切れのポップアップが出なくなる事とが組み合わさった結果、「一見成功したように見えて、実際には処理が実行されていない」状態が発生したのでした。

さいごに

原因が分かってしまえば何でも無い内容でしたが、遭遇した時には訳が分からず困惑しました。
最後までお読み頂きありがとうございました。

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

AWS CDKをGitHub Actionsで実行するためのワークフロー書き方

GitHub ActionsからAWS CDKを実行できるようにします。CDKの利用言語はTypeScriptにしています。表記の中のNode.jsやCDKのバージョンは適宜変更してください。

BOTのためのシークレット作成

IAMでBOT用のIAMユーザを作成して、それに対して下記のマネージドポリシーをつけている。必要であればもっと権限を絞って良いと思う。

  • IAMFullAccess
  • AWSCloudFormationFullAccess

作成したBOTのIAMユーザのシークレットを作成し、GitHubリポジトリのSecretsに保存しておく。

  • AWS_ACCESS_KEY_ID
  • AWS_SECRET_ACCESS_KEY

リージョンについても、AWS_REGIONのシークレットに対象リージョンの文字列を登録します。しかし、認証情報そのものではないため、ここくらいはハードコードでも良いかもしれない。

プルリクエストを元にスタックの変更内容を出力する

プルリクエストが作成・更新された際に、既存のスタックと変更内容を比較して、CDK diffの結果を出力します。リポジトリ設定のブランチの項目で、必須チェックの対象にすれば、この処理が終わるまでマージをブロックすることができます。

name: Show CDK diff

on:
  pull_request:
    branches: ["*"]

jobs:
  diff:
    name: CDK diff
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v2
      - uses: actions/setup-node@v1
        with:
          node-version: "12"
      - name: Setup AWS CDK
        run: npm install -g aws-cdk@1.47.1
      - name: Setup Dependencies
        run: npm ci
      - name: Build
        run: npm run build
      - name: CDK diff
        run: cdk diff
        env:
          AWS_DEFAULT_REGION: ${{ secrets.AWS_REGION }}
          AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }}
          AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }}

プッシュを元にスタックの変更をデプロイする

指定のブランチに変更がプッシュされた際に、AWSへ変更をデプロイする。

name: CDK deploy

on:
  push:
    branches: ["master"]

jobs:
  deploy:
    name: CDK deoloy
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v2
      - uses: actions/setup-node@v1
        with:
          node-version: "12"
      - name: Setup AWS CDK
        run: npm install -g aws-cdk@1.47.1
      - name: Setup Dependencies
        run: npm ci
      - name: Build
        run: npm run build
      - name: CDK deploy
        run: cdk deploy
        env:
          AWS_DEFAULT_REGION: ${{ secrets.AWS_REGION }}
          AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }}
          AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

【AWS】EFSボリュームの自動マウント設定(AmazonLinux)

はじめに

EC2インスタンス(AmazonLinux)にてEFSボリュームを自動マウントする設定についてアウトプットしたいと思います。

環境

項目 説明
EC2 Amazon Linux 2 AMI (HVM), SSD Volume Type
Size t2.micro

作業前提

  • EFSボリュームの作成が完了している
  • ネットワーク環境の設定ができている(EC2からEFSボリュームへアクセス可能な状態)

※前提条件をクリアしていない場合は過去の記事をご覧下さい。
【AWS】AmazonLinuxにEFSボリュームのNFSマウントを実施してみる

手順

EC2インスタンスへログイン済みであることを前提としています。

手動マウント

※下記手順を実施済みの場合は飛ばして問題ないです。

①ルートユーザーへスイッチ

sudo su

②事前にディスク状態を確認

df -Ph

実行例

[root@ip-10-0-0-120 ec2-user]# df -Ph
Filesystem      Size  Used Avail Use% Mounted on
devtmpfs        474M     0  474M   0% /dev
tmpfs           492M     0  492M   0% /dev/shm
tmpfs           492M  400K  492M   1% /run
tmpfs           492M     0  492M   0% /sys/fs/cgroup
/dev/xvda1      8.0G  1.3G  6.8G  16% /
tmpfs            99M     0   99M   0% /run/user/1000
[root@ip-10-0-0-120 ec2-user]#

③amazon-efs-utilsパッケージインストール

yum -y install amazon-efs-utils

④EFSマウント

mkdir マウントしたいディレクトリ
mount -t efs <ファイルシステムID>:/ <マウントしたいディレクトリ>

実行例

[root@ip-10-0-0-120 ec2-user]# mkdir /test
[root@ip-10-0-0-120 ec2-user]# mount -t efs fs-7f41435e:/ /test
[root@ip-10-0-0-120 ec2-user]#

⑤マウント確認

df -Ph

実行例

[root@ip-10-0-0-120 ec2-user]# df -Ph
Filesystem                                      Size  Used Avail Use% Mounted on
devtmpfs                                        474M     0  474M   0% /dev
tmpfs                                           492M     0  492M   0% /dev/shm
tmpfs                                           492M  404K  492M   1% /run
tmpfs                                           492M     0  492M   0% /sys/fs/cgroup
/dev/xvda1                                      8.0G  1.3G  6.8G  16% /
tmpfs                                            99M     0   99M   0% /run/user/1000
fs-7f41435e.efs.ap-northeast-1.amazonaws.com:/  8.0E     0  8.0E   0% /test
[root@ip-10-0-0-120 ec2-user]#

⑥アンマウント

umount <マウント済みディレクトリ>
df -Ph

実行例

[root@ip-10-0-0-120 ec2-user]# umount /test
[root@ip-10-0-0-120 ec2-user]#
[root@ip-10-0-0-120 ec2-user]# df -Ph
Filesystem      Size  Used Avail Use% Mounted on
devtmpfs        474M     0  474M   0% /dev
tmpfs           492M     0  492M   0% /dev/shm
tmpfs           492M  400K  492M   1% /run
tmpfs           492M     0  492M   0% /sys/fs/cgroup
/dev/xvda1      8.0G  1.3G  6.8G  16% /
tmpfs            99M     0   99M   0% /run/user/1000
[root@ip-10-0-0-120 ec2-user]#

/testがアンマウントされている(dfの結果に存在しない)ことを確認

自動マウント設定

自動マウントの設定をしていきます。

 ①/etc/fstabバックアップ

cp -p /etc/fstab /etc/fstab_`date +'%Y%m%d'`

date +'%Y%m%d'はサーバ内の当日日付になります。(自動入力)

実行例

[root@ip-10-0-0-120 ec2-user]# cp -p /etc/fstab /etc/fstab_`date +'%Y%m%d'`
[root@ip-10-0-0-120 ec2-user]#
[root@ip-10-0-0-120 ec2-user]# ll /etc | grep fstab
-rw-r--r--  1 root root       91 May 27 00:48 fstab
-rw-r--r--  1 root root       91 May 27 00:48 fstab_20200701
[root@ip-10-0-0-120 ec2-user]#

②自動マウント設定追加

(ファイルシステムID):/ <マウントしたいディレクトリ> efs defaults,_netdev 0 0/etc/fstabに追記

echo "(ファイルシステムID):/ <マウントしたいディレクトリ>   efs    defaults,_netdev  0 0" >> /etc/fstab

※必ず>>として下さい。(>の場合、ファイル全体が上書きされてしまうため)

実行例

[root@ip-10-0-0-120 ec2-user]# echo "fs-7f41435e:/ /test   efs    defaults,_netdev  0 0" >> /etc/fstab
[root@ip-10-0-0-120 ec2-user]# cat /etc/fstab
#
UUID=be4f19b3-a8ae-4d74-a7a0-b12b49e21194     /           xfs    defaults,noatime  1   1
fs-7f41435e:/ /test   efs    defaults,_netdev  0 0
[root@ip-10-0-0-120 ec2-user]#

③バックアップファイルと比較

追記したファイルとバックアップファイルを比較し、差異が修正した箇所のみであることを確認。

/etc/fstab /etc/fstab_`date +'%Y%m%d'`

実行例

[root@ip-10-0-0-120 ec2-user]# diff /etc/fstab /etc/fstab_20200701
3d2
< fs-7f41435e:/ /test   efs    defaults,_netdev  0 0
[root@ip-10-0-0-120 ec2-user]#

④マウント確認

/etc/fstabの記述通りマウントできることを確認

mount <マウントしたいディレクトリ>
df -Ph

実行例

[root@ip-10-0-0-120 ec2-user]# mount /test
[root@ip-10-0-0-120 ec2-user]# df -Ph
Filesystem                                      Size  Used Avail Use% Mounted on
devtmpfs                                        474M     0  474M   0% /dev
tmpfs                                           492M     0  492M   0% /dev/shm
tmpfs                                           492M  404K  492M   1% /run
tmpfs                                           492M     0  492M   0% /sys/fs/cgroup
/dev/xvda1                                      8.0G  1.3G  6.8G  16% /
tmpfs                                            99M     0   99M   0% /run/user/1000
fs-7f41435e.efs.ap-northeast-1.amazonaws.com:/  8.0E     0  8.0E   0% /test ← マウントできている
[root@ip-10-0-0-120 ec2-user]#

自動マウント確認

①EC2の再起動実施

sudo reboot

②再起動後のマウント確認

再起動後にログインし、NFSボリュームがマウントされていることを確認

df -Ph

実行例

[ec2-user@ip-10-0-0-120 ~]$ df -Ph
Filesystem                                      Size  Used Avail Use% Mounted on
devtmpfs                                        474M     0  474M   0% /dev
tmpfs                                           492M     0  492M   0% /dev/shm
tmpfs                                           492M  408K  492M   1% /run
tmpfs                                           492M     0  492M   0% /sys/fs/cgroup
/dev/xvda1                                      8.0G  1.3G  6.8G  16% /
fs-7f41435e.efs.ap-northeast-1.amazonaws.com:/  8.0E     0  8.0E   0% /test ← マウントされている
tmpfs                                            99M     0   99M   0% /run/user/1000
[ec2-user@ip-10-0-0-120 ~]$

まとめ

  • AmazonLinuxにEFSボリュームを自動マウントさせるためには、/etc/fstabを修正する必要がある。
  • amazon-efs-utilsパッケージは必須

参考

AWS EFSの設定とマウント

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