- 投稿日:2020-11-26T23:30:47+09:00
serverless framework DE typescript for AWS Lambda開発
既に作ったserverlessプロジェクトにTypescriptを入れたい
現在AWSでSlack Botを動かすために、開発環境を作れるserverless絶賛勉強中です。
プロジェクトを作る時にtypescript対応するのは見つかったのですが、
もう作っちゃったプロジェクトに追加する方法は見当たらなかったのでまとめます。プロジェクト作成時の場合はcreateするときに
-t aws-nodejs-typescript
というテンプレートを指定すればいいらしい。次はそっちでやってみます。
参考:ServerlessでTypeScriptの開発環境を作るserverlessプラグインを追加
https://www.serverless.com/plugins/serverless-plugin-typescript/
serverless-plugin-typescriptという素敵なプラグインを見つけたので使います。Features
・Zero-config: Works out of the box without the need to install any other compiler or plugins
・Supports ES2015 syntax + features (export, import, async, await, Promise, ...)
・Supports sls package, sls deploy and sls deploy function
・Supports sls invoke local + --watch mode
・Integrates nicely with serverless-offlineローカル環境構築に使うserverless-offlineとの連携に自信ありとのことで、良いですね。
実際この後serverless-offlineも導入しましたが大体問題なく変換されています。インストール
npm install -D serverless-plugin-typescript typescriptした後に、お約束の
serverless.yml
のpluginsに下記を追加plugins: - serverless-plugin-typescripttsconfig.json
minimum exampleを見る限り、デフォルトで良ければtsconfig.json作らなくても動くっぽい。
tsconfig.json{ "compilerOptions": { "preserveConstEnums": true, "strictNullChecks": true, "sourceMap": true, "allowJs": true, "target": "es5", "outDir": ".build", "moduleResolution": "node", "lib": ["es2015"], "rootDir": "./" } }これがデフォルトで、
outDir
とrootDir
以外は上書きしていいよ!とのことです。
私はTypescript、細かいとこまで気が付くデキるやつだなぁ…くらいのノリで使ってるので、今のところ特に何も変更してません。あとはsls deploy時に勝手にトランスパイルしてくれます。
(ディレクトリ含むファイル分割しても勝手に上手いことしてくれるのかはこれから検証…)serverless-offlineと使う
時はserverless-plugin-typescriptが先に来るように
serverless.yml
に記述しないとダメらしいです。serverless.ymlplugins: ... - serverless-plugin-typescript ... - serverless-offline ...
serverless-dynamodb-local
を使う時もなんか順番があるみたいですが、私はまだ使ってないのでよくわかりません。各自ご確認くださいaws-sdkの型定義ファイルを使う
他で使われていたので@types/aws-sdkというパッケージを見に行ったら、もう公式が提供してるから使わなくていいよと言われてしまったので公式を見に行きます。
https://docs.aws.amazon.com/AWSJavaScriptSDK/latest/#Usage_with_TypeScript
まずは、というか実際@types/node
をインストールするだけです。npm install --save-dev @types/nodeあとは.tsファイルからの読み込みを書き換えて完了!
import AWS from 'aws-sdk';なぜかSlack Botが動かなくなった…
動かなくなりました。公式の言う通りimportした後、こんな感じで
AWS
オブジェクトの中のLambdaメソッドを呼び出していたのですが、
Lambdaはundifinedを参照していますみたいなエラーが出て、なぜかAWS
の中身がからっぽということに…どうして、さっきまでこれで動いていたのに。handler.tsimport AWS from 'aws-sdk'; const lambda = new AWS.Lambda()serverless-offlineを使うと?distフォルダにコンパイル後のjsファイルが生成されているので、そこを見てみるとこんなことになってました。
勝手に入ってきた.default
君、何?handler.jsvar aws_sdk_1 = require("aws-sdk"); var lambda = new aws_sdk_1.default.Lambda();
.default
君がどこから何のために来たのか全然分からないんですが、とりあえずimport時に直接Lambdaメソッドを分割代入したら無事動いてくれました。handler.tsimport { Lambda } from 'aws-sdk'; const lambda = new Lambda()型定義を付けた値にserverless.ymlの環境変数を入れる時の注意
Lambda.invoke()に渡すパラメーターを設定する変数に型定義
AWS.Lambda.InvocationRequest
を付けた時のことです。const params: AWS.Lambda.InvocationRequest = { FunctionName: process.env.INVOKE_FUNCTION, InvocationType: "RequestResponse", Payload: JSON.stringify({ msg: "Hello" }), };
process.env.INVOKE_FUNCTION
のとこで下記のような、エラーがコンソールに湧き出ました。api-lambda.ts (13,17): Argument of type '{ FunctionName: string | undefined; InvocationType: string; Payload: string; }' is not assignable to parameter of type 'InvocationRequest'. Types of property 'FunctionName' are incompatible. Type 'string | undefined' is not assignable to type 'string'. Type 'undefined' is not assignable to type 'string'.ちなみにinvokeする関数のFunctionNameは、
serverless.yml
で定義している「サービス名-ステージ名-functionsで定義した関数名」で生成されるので、serverless.yml
でファイル内参照しながら書く方が楽なんですよね。こんな感じで。
"${self:service}-${self:provider.stage}-<functions内で定義した関数名>"
まぁそれはともかく、エラーは「string型で定義したところに'string | undefined'の値は入れられません」とか言ってます。
どうやら.yml内から持ってきた値はtypescriptの方で中身がある無しを判断できないので自動的に'string | undefined'型と判定されるようです。しかしそんなときの為にTypescriptさんが解決策を用意してくれていました
const params: AWS.Lambda.InvocationRequest = { FunctionName: process.env.INVOKE_FUNCTION!, ... };これで解決です。
!
つけるだけ。
Non-null assertion operator
要するにこれは末尾に付けた変数がnullでもundefinedでもありませんよというのを明示的に指定できる演算子のようです。?を付ければOptional chaining
そういえば
?
をオブジェクトの末尾に付けると、途中でundifinedの中身を参照しようとしてもエラーを出さずにnullが帰ってくるというめちゃくちゃ良い感じの機能がありますね。
slackのレスポンスはオブジェクトがネストしてることも多いので、私が今のところそこまでよく分かってないtypescriptを入れたい理由の一つです。
https://www.typescriptlang.org/docs/handbook/release-notes/typescript-3-7.html#optional-chaining以上です。
- 投稿日:2020-11-26T23:15:46+09:00
AWS EC2でサーバー構築①
概要
簡単にAWSでサーバー構築をしてアプリケーションをデプロイさせる
今回は ネットワークの構築 まで進めようと思います!リージョンの変更
右上のリージョンから アジアパシフィック (東京) ap-northeast-1
VPC領域の作成
VPC とは(Virtual Private Cloud)の略
VPC を作成すると ユーザー毎に隔離されたネットワーク空間が作れますAWS上のVPC領域はプレフィックス長が16以上を指定する必要があるので
CIDR ブロックは 10.0.0.0/16 にする必要があるトップ画面 から 「VPC」 を選択 「名前タグ-オプション」 :好きな名前を入力 「IPv4 CIDR ブロック」: 今回は 「10.0.0.0/16」 「IPv6 CIDR ブロック」: 「IPv6 CIDR ブロックなし」 を選択 「テナンシー」:デフォルト を選択(専有にすると追加料金がかかる) 「VPCを作成」 を選択サブネットの分割
CIDRブロックを更に小さく分割して使うのが一般的であり、細分化されたブロックを「サブネット」と呼ぶ
今回は「/16」で作成したブロックを「/24」の大きさで256分割にする「VPC ダッシュボード」 から 「サブネット」 を選択 「サブネットの作成」 を選択 「VPC ID」 から 先ほど作成した「VPC」を選択 「サブネット名」: 好きな名前を入力 「アベイラビリティーゾーン」: 指定なし 「IPv4 CIDR ブロック」: 今回は 10.0.1.0/24 を指定 「サブネットを作成」 を選択インターネットゲートウェイ
サブネットをインターネットに接続するには、「インターネットゲートウェイを設定する必要がある
「VPC ダッシュボード」 から 「インターネットゲートウェイの作成」 を選択 「名前タグ」: 好きな名前を入力 「インターネットゲートウェイの作成」 を選択 VPCアタッチ画面が表示されるので 作成した「VPC」を選択ルートテーブルの作成
宛先IPアドレスの値により、どのネットワークに流すべきか区別する設定
「VPC ダッシュボード」 から 「ルートテーブルの作成」 を選択 「名前タグ」: 好きな名前を入力 「VPC*」: 作成した「VPC」を選択 「作成」を選択ルートテーブル(インターネットゲートウェイ)の設定
作成したルートテーブルを選択 「ルートタブ」 を選択し、 「ルートの編集」を選択 「ルートの追加」 から 送信先:「0.0.0.0/0」 ターゲット:「internet Gateway」を選択すると 作成されたインターネットゲートウェイが表示されるルートテーブル(サブネット)の設定
作成したルートテーブルを選択 「サブネットの関連付け」 を選択し、 「サブネットの関連付けの編集」を選択 作成したサブネットを選択し、「保存」今回はネットワークの設定まで終わったので
続きは次の会で説明しようと思います!
- 投稿日:2020-11-26T23:15:46+09:00
AWS でサーバー構築、アプリをデプロイ①
概要
簡単にAWSでサーバー構築をしてアプリケーションをデプロイさせる
今回は ネットワークの構築 まで進めようと思います!リージョンの変更
右上のリージョンから 「アジアパシフィック(東京)ap-northeast-1」 に変更VPC領域の作成
VPC とは(Virtual Private Cloud)の略
VPC を作成すると ユーザー毎に隔離されたネットワーク空間が作れますAWS上のVPC領域はプレフィックス長が16以上を指定する必要があるので
CIDR ブロックは 10.0.0.0/16 にする必要があるトップ画面 から 「VPC」 を選択 「名前タグ-オプション」 :好きな名前を入力 「IPv4 CIDR ブロック」: 今回は 「10.0.0.0/16」 「IPv6 CIDR ブロック」: 「IPv6 CIDR ブロックなし」 を選択 「テナンシー」:デフォルト を選択(専有にすると追加料金がかかる) 「VPCを作成」 を選択サブネットの分割
CIDRブロックを更に小さく分割して使うのが一般的であり、細分化されたブロックを「サブネット」と呼ぶ
今回は「/16」で作成したブロックを「/24」の大きさで256分割にする「VPC ダッシュボード」 から 「サブネット」 を選択 「サブネットの作成」 を選択 「VPC ID」 から 先ほど作成した「VPC」を選択 「サブネット名」: 好きな名前を入力 「アベイラビリティーゾーン」: 指定なし 「IPv4 CIDR ブロック」: 今回は 10.0.1.0/24 を指定 「サブネットを作成」 を選択インターネットゲートウェイ
サブネットをインターネットに接続するには、「インターネットゲートウェイを設定する必要がある
「VPC ダッシュボード」 から 「インターネットゲートウェイの作成」 を選択 「名前タグ」: 好きな名前を入力 「インターネットゲートウェイの作成」 を選択 VPCアタッチ画面が表示されるので 作成した「VPC」を選択ルートテーブルの作成
宛先IPアドレスの値により、どのネットワークに流すべきか区別する設定
「VPC ダッシュボード」 から 「ルートテーブルの作成」 を選択 「名前タグ」: 好きな名前を入力 「VPC*」: 作成した「VPC」を選択 「作成」を選択ルートテーブル(インターネットゲートウェイ)の設定
作成したルートテーブルを選択 「ルートタブ」 を選択し、 「ルートの編集」を選択 「ルートの追加」 から 送信先:「0.0.0.0/0」 ターゲット:「internet Gateway」を選択すると 作成されたインターネットゲートウェイが表示されるルートテーブル(サブネット)の設定
作成したルートテーブルを選択 「サブネットの関連付け」 を選択し、 「サブネットの関連付けの編集」を選択 作成したサブネットを選択し、「保存」今回はネットワークの設定まで終わったので
続きは次の章で説明しようと思います!
- 投稿日:2020-11-26T23:08:58+09:00
TerraformでAmazon API Gatewayを構築する(リソースポリシー編)
はじめに
API Gateway+Terraform記事第4弾。
TerraformのAWSプロバイダの3.16.0で2020/11/18にリソースポリシーの Terraform リソースが使えるようになったので、今回は、IPアドレスによる制限をさっそく試してみる。Terraform
とはいっても、普通にIAMポリシーを書くだけである。
Condition(IpAddress)を使って許可をしてするよう、こんな感じで定義しよう。
resource "aws_api_gateway_rest_api_policy" "test" { rest_api_id = aws_api_gateway_rest_api.test.id policy = data.aws_iam_policy_document.test.json } data "aws_iam_policy_document" "test" { statement { effect = "Allow" principals { type = "*" identifiers = [ "*", ] } actions = [ "execute-api:Invoke", ] resources = [ "arn:aws:execute-api:${data.aws_region.current.name}:${data.aws_caller_identity.self.account_id}:${aws_api_gateway_rest_api.test.id}/*", ] condition { test = "IpAddress" variable = "aws:SourceIp" values = [ "xxx.xxx.xxx.xxx/32", ] } } }なお、
resources
の部分については、AWS公式の開発者ガイドでは、execute-api:/[ステージ名]/[メソッド]/[リソース名]
にすれば良い感じに ARN に変換してくれるよ、と書いてあるのだが、良い感じに変換してもらえるがために、毎回 Terraform の差分として検出されるようになってしまうため、素直に↑のように ARN 形式で書いておこう。"*" の部分については、上記の通り
[ステージ名]/[メソッド]/[リソース名]
で書くことも可能。これで許容されていないIPアドレスでアクセスすると、
{"Message":"User: anonymous is not authorized to perform: execute-api:Invoke on resource: arn:aws:execute-api:ap-northeast-1:************:xxxxxxxxxx/prod/GET/xxxxxxxx"}な感じでエラーが応答される。
アクセスログを設定している場合は、以下のように 403 応答を返したログが出力される。
{ "requestId": "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx", "ip": "xxx.xxx.xxx.xxx", "caller": "-", "user": "-", "requestTime": "26/Nov/2020:13:51:55 +0000", "httpMethod": "GET", "resourcePath": "/xxxxxxxx", "path": "/prod/xxxxxxxx", "status": "403", "protocol": "HTTP/1.1", "responseLength": "168", "integrationLatency1": "-", "integrationRequestId": "-", "integrationStatus1": "-", "integrationErrorMessage": "-", "integrationLatency2": "-", "integrationStatus2": "-", "responseLatency": "1", "errorMessage": "User: anonymous is not authorized to perform: execute-api:Invoke on resource: arn:aws:execute-api:ap-northeast-1:************:xxxxxxxxxx/prod/GET/xxxxxxxx" }あとは、AWS公式の開発者ガイドに書いてある
API 作成後にリソースポリシーを更新する場合は、更新後のポリシーをアタッチしてから API をデプロイし、変更を伝達する必要があります。ポリシーのみ、更新または保存した場合、API のランタイム動作が変更されることはありません。API のデプロイの詳細については、「Amazon API Gateway での REST API のデプロイ」を参照してください。
が注意点といったところか。
これで、API Gatewayをよりセキュアに運用できるようになった!
- 投稿日:2020-11-26T23:02:40+09:00
【AWS】Windows10にAWS-CLI ver.2をインストールしてみた
はじめに
AWSを勉強するために、ノートPCにAWS-CLIをインストールしてみたので、備忘として残しておきます。
PCスペック
- OS:Windows 10 Home(バージョン 20H2(OSビルド 19042.630))
- CPU:Intel Core i7-10510U 1.80GHz(2.30GHz)
- RAM:16.0GB
目次
- インストール
- 設定
1. インストール
基本的には以下の公式サイトの通りインストールを進めればOKです。
Windows での AWS CLI バージョン 2 のインストール、更新、アンインストール前提条件
インストールする前に事前に以下の確認が必要です。
* 64ビットバージョンのWindows XP以降のOS
* ソフトウェアインストール用の管理者権限MSIインストーラをダウンロードする
最新版のインストーラをダウンロードします。
※特定のバージョンが欲しい場合はバージョンを指定してください。(公式サイトのリンクを参照してください。)
CLIv2(最新版)のインストーラインストールする
ダウンロードしたMSIインストールを実行し、ウィザードに沿ってインストールを進めます。
インストールが完了したら、スタートメニューからコマンドプロンプト(cmd)を開き、以下のコマンドを入力して確認します。aws --versionaws-cli/2.1.4 Python/3.7.9 Windows/10 exe/AMD64
のように出力されればOKです。
インストールはこれだけです。
非常に簡単にインストールが出来ました。2. 設定
インストールが完了したら、AWSに接続できるように諸々の設定を行います。
ここからは実際にコンソール画面から必要情報を取得したり、それをCLIのconfigに設定していきます。アクセスキー/シークレットキーの取得
AWSコンソール画面から、IAMを検索しIAMサービスページに遷移してください。
IAMページから「アクセス管理」>「ユーザー」を選択してください。
任意の(CLIで利用したい)ユーザーを選択し、タブから「認証情報」を選択してください。
「アクセスキー」の欄にある、「アクセスキーの作成」ボタンを押します。
※アクセスキーとシークレットキーは絶対に外部に出ないように注意してください。アクセスキー/シークレットキーがcsvファイルでダウンロードされます。
これを用いてCLIに設定をしていきます。CLIの設定
スタートメニューから「cmd」を起動し、以下のコマンドを入力してください。
C:\> aws configure AWS Access Key ID [None]:取得したアクセスキーを入力 AWS Secret Access Key [None]:取得したシークレットキーを入力 Default region name [None]:デフォルトで使用するリージョンを入力(東京の場合は、ap-northeast-1) Default output format [None]:出力フォーマットを入力(json,yaml,yaml-stream,text,tableのいずれかを入力(今回はjsonを指定)。変更も可能)出力フォーマットの説明は以下の通りです。(2020/11/26時点)
実行コマンドに--outputオプションを指定すれば、コマンド実行時に変更もできます。
形式 説明 json JSON 文字列形式で出力されます。 yaml YAML 文字列形式で出力されます。(AWS CLI バージョン 2 でのみ利用できます。) yaml-stream 出力はストリーミングされ、YAML 文字列としてフォーマットされます。ストリーミングにより、大きなデータ型の処理を高速化できます。(AWS CLI バージョン 2 でのみ利用できます。) text 複数行のタブ区切り文字列値の形式で出力されます。これは、grep、sed、または awk などのテキストプロセッサに出力を渡すのに役立ちます。 table セルの罫線を形成する文字列 +| - を使用して表形式で出力されます。通常、情報は他の形式よりも読みやすい「わかりやすい」形式で表示されますが、プログラムとしては役立ちません。 接続確認
cmdにて接続できるか確認してみます。
今回は、IAMユーザーの一覧を表示するコマンドを実行します。C:\>aws iam list-users { "Users":[ { ...ここに作成済みのユーザが表示されます。 } ] }と出力されれば完了です。
S3バケットの確認コマンドも念のため実行しておきます。
C:\>aws s3 ls作成済みのS3バケットが表示されれば完了です。
プロファイル設定
CLIではプロファイルと呼ばれる設定のコレクションがあります。
デフォルトでは「default」プロファイルを使用しますが、実行コマンドに--profileオプションを指定すれば、作成済の各プロファイルにて実行が可能になります。プロファイル作成
基本的に先ほどの設定手順と同じです。
今回は「devuser」というプロファイルを作成してみます。
出力フォーマットを変更してもらえると、差がわかりやすいかと思います。(json⇒textに変更しました。)C:\> aws configure --profile devuser AWS Access Key ID [None]:取得したアクセスキーを入力 AWS Secret Access Key [None]:取得したシークレットキーを入力 Default region name [None]:デフォルトで使用するリージョンを入力(東京の場合は、ap-northeast-1) Default output format [None]:出力フォーマットを入力(json,yaml,yaml-stream,text,tableのいずれかを入力。変更も可能)設定を確認してみます。
C:\>aws iam list-users --profile devuser USERS arn:...先ほどと表示されるフォーマットが変わっていれば完了です。
さいごに
今回は、Win10端末にAWS CLI2をインストールし、接続確認までを行いました。
今後CLIを用いた構築などを更新していければと思います。
また、CLIについてのユーザーガイドは以下をご確認ください。
AWS コマンドラインインターフェイスのドキュメント
- 投稿日:2020-11-26T20:54:42+09:00
Amazon Elasticsearch Serviceを使ってみての所感
この記事はLivesense AdvendCalendar 5日目の記事です。
背景・機運
転職会議では、口コミや求人データを扱う際にElasticsearchを使っています。
その際に、ElasticCloudというElastic社が提供するマネージドサービスを利用してきました。
Kibanaなどの周辺サービスも充実しており導入当初は良かったのですが、課題が徐々に露呈してきました1. ネットワークがボトルネック
外部サービスのためVPC外にリクエストを投げることになり、場合によってはレスポンスが悪くなる。特に大量のリクエストを投げると顕著。
メルマガ配信時も使っており、配信時にリクエストのタイムアウトが頻発。2. コスト・運用面
料金に応じたCPUやメモリのスペックが確保されるため運用用途にあった料金を設定できず、AWS NATの転送量による支払いもあり、総合してみると多額の支払いが発生。
移行すれば「1年でプリウスくらいは買えるくらい浮きそう」という結果に
また、転職会議ではDatadogでサービス・ミドルウェアの監視・通知を行っているのですが、ElasticCloudだけマネージドされた監視ツールを使っていたため独立しており、雑多な状態になっていました。3. カスタムプラグインが特定のプラン以上でしか使えない
ElasticCloudでは料金プランがいくつか用意されていて、用途に合わせて契約することが可能です。
転職会議では最小プランのスタンダードを利用していましたが、カスタムプラグインが更に上のプランでしか利用できず、ユーザ辞書を追加して検索の精度改善を実施することができない状態でした。
プランを変更してもよいのですがコスト面が見合わず、しばらく使わない状態で運用していました。4. パフォーマンス
辞書が使えなかったのでtermクエリを使うと想定外のドキュメントが取れてしまうので、それっぽいことをするためにAPIで取得する際にquery_stringで大量のドキュメントを取得し、そこからアプリ側でゴリッと色々とやっていました。。。。
結果APIのレイテンシーが徐々に悪化。ときにリクエストがタイムアウトを起こすこともありました。
またSLO改善の一環で、アプリ改修を含めこちらにも手を入れる必要がありました。これらの課題を解決するためにElasticCloudを脱却することを決定。
当初はEKS上に自前でElasticsearchを立てる動きでした。4月、AWSからのアナウンス
今年のはじめから少しずつ移行対応の検討と対応を行ってきましたが、なんとAmazon Elasticserch Service(以下 Amazon ES)側でカスタム辞書をサポート
Amazon ESではkuromojiしかサポートしておらず、kuromojiの辞書は更新がほとんどされてないため、想定とは異なる言語処理結果になってしまうことが多いです。これはかなり嬉しいアナウンスでした。
他にも調査してみると、EKSで自前で立てるのと彩色無く利用できそうだったのと、スロークエリログをCloudWatch Logsに流せるなど、他のAWSのサービスと親和性が高い。
また費用面でも自前よりは劣るが、それでも安くなるので急遽利用することに。やったこと
- Amazon ES側にインデックスを作成、ElasticCloudと並行して差分インデクシングさせる
- アプリ側からもドキュメントの更新を行う処理があるので、差分が出ないように先に実施しておく
- バッチでAmazon ES側に作成し、aliasを書き換える
- アプリやサービスで参照しているエンドポイントの切り替え
- ElasticCloudを脱却
大きなことはやっておらず、負荷も考慮しながら少しずつ移行対応していきました。
運用してみて
移行してしばらく経ちますが問題なく動いています。辞書も使えてaggregationによるキャッシュも効かせられ、レイテンシーも改善。(オレンジの線の前後でレイテンシーが変わっていることが分かります。嬉しい、、、!)
しかしAmazon ES特有の問題(癖というべきか、、)があり、かゆいところに手が届かない感じです。。。。1. カスタム辞書の関連付けがterraform管理できない
Amazon ESで辞書を使うには、S3に指定のフォーマットでアップロードしてそれをパッケージとして紐付けます。
紐付けた際に発行されたリファレンスパスをuser_dictionaryとして追記し、インデックスを作り直す必要があります。"analysis": { "tokenizer" : { "sample_kuromoji_tokenizer" : { "type":"kuromoji_tokenizer", "user_dictionary": "analyzers/F123456789" } }上記のanalyzers/F123456789が発行されたリファレンスパスに当たります。
AWSのリソースをterraformを使って管理してるのでまとめたかったのですが、aws_elasticsearch_domainリソースでは提供されてないようです。
頻繁に辞書を更新する場合はスクリプトで管理するか、7.4以降からはuser_dictionary_rulesという、synonymと同様に直接辞書を追加できる設定があるのでそちらを使うと良いかもしれません。2. 一部のAPIが利用できない
OSSで提供されているElasticsearchとは異なり、許可されていないAPI(rerouteなど)が存在します。
自前で立てた場合と同じ想定で運用すると思いもよらない落とし穴にハマるかもしれません。
利用用途に合うかリファレンスを読んでから利用することをおすすめします。3. ElasticCloud独自の機能やサポートが利用できなくなる
これは当たり前なのですが、管理画面からボタン一つでローリングアップグレードやマイナーバージョンアップグレード、スケールアップが容易にできたのはありがたかったですね。
まとめ
移行してよかったと思う一方で、やはりサービスで提供されてるって良いなぁと思うときもあります。
通常運用する分には申し分ないかと思うので、自前で運用を考えてるならこちらも検討材料に入れてはいかがでしょうか。
- 投稿日:2020-11-26T20:44:38+09:00
ancestryはawsにデプロイしただけでは使えない
1.どんな状態だったか
ancestryを利用して、カテゴリー機能を実装、ローカルでは動くのに本番環境で反映されないという状態
2原因
ancestryを使うためには、本番環境でもローカルと同じ様に
db migrateし、seedを読み込まなくてはならない3解決方法
まずdb migrateします
$ cd var/www/app名/current $ rake db:migrate RAILS_ENV=production上手くいかない時はdbをドロップしもう一度クリエイトし直す
$ RAILS_ENV=production DISABLE_DATABASE_ENVIRONMENT_CHECK=1 bundle exec rake db:drop $ rake db:create RAILS_ENV=productionもう一度migrateします。
次にseedを反映させます。
$ rake db:seed RAILS_ENV=production以上になります。
4最後に
自動デプロイをしている場合はcurrentディレクトリで操作を行う必要があるそうです
そうでない場合は~ディレクトリで大丈夫みたいです参考にした記事
[aws,rails]ancestryをawsにデプロイした時に反映されない状況の解決方法
本番環境でrake db:seedを実行する際の注意点
- 投稿日:2020-11-26T18:07:47+09:00
Athenaからクエリ出来てCSVダウンロードやS3から直接ダウンロード禁止する
ただのメモです。
AthenaとGlueのリストと読み取り権限ポリシー作ってアタッチ
S3の読み取り権限ポリシーを、calledviaを使いAthenaからだけ許可する形で作成してアタッチ
{ "Version": "2012-10-17", "Statement": [ { "Sid": "VisualEditor0", "Effect": "Allow", "Action": [ "s3:PutObject", "s3:GetObject", "s3:ListBucketMultipartUploads", "s3:AbortMultipartUpload", "s3:CreateBucket", "s3:ListBucket", "s3:GetBucketLocation", "s3:ListMultipartUploadParts" ], "Resource": [ "arn:aws:s3:::aws-athena-query-results-xxxxxxxxxxxx-ap-northeast-1/*", "arn:aws:s3:::aws-athena-query-results-xxxxxxxxxxxx-ap-northeast-1" ], "Condition": { "ForAnyValue:StringEquals": { "aws:CalledVia": "athena.amazonaws.com" } } }, { "Sid": "VisualEditor1", "Effect": "Allow", "Action": [ "s3:GetObject", "s3:ListBucket" ], "Resource": [ "arn:aws:s3:::test", "arn:aws:s3:::test/*" ], "Condition": { "ForAnyValue:StringEquals": { "aws:CalledVia": "athena.amazonaws.com" } } } ] }
- 投稿日:2020-11-26T18:02:34+09:00
サルでもできる!? Rails6アプリをAWS EC2にデプロイするまでの全手順【後半】(独自ドメイン, HTTPS化, S3, CloudFront)
この記事では,画像投稿機能の付いた
Rails 6
のアプリをAWS EC2
にデプロイするまでの全過程を解説します。【前半】 でRailsアプリのデプロイはひとまず完了しましたが,まだまだすべきことがたくさんあります。続きも気を抜かずに頑張りましょう!
章 タイトル 【前半】 1章 はじめに 2章 VPC 3章 RDS 4章 EC2 5章 サーバー構築 6章 デプロイ(Capistrano) 【後半】 <-- こちら 7章 独自ドメイン 8章 HTTPS化(ACM, ALB) 9章 デプロイ関連事項 10章 S3 11章 CloudFront 12章 削除方法 7. 独自ドメイン
Railsアプリを公開することができましたが,現状では2つ大きな問題を抱えています。
- サイトの URL が不自然
google.com
のような独自ドメイン
ではない- HTTPSではない
- Google Chrome で「このサイトへの接続は保護されていません」という警告が出る
まずは前者から解決していきましょう。
aws-sample-app.com
のような URL でアクセスできるようにするには,ドメイン
を取得する必要があります。
ドメイン
は有料ですが,こだわらなければ初年度は数百円程度で取得できます。この記事では昔から代表的な
レジストラ
である「お名前.com」で取得する前提で解説します。7.1 ドメインの購入
「お名前.com」にアクセス
検索窓に取得したいドメイン名を入力し,「検索」ボタンをクリック
- ドメインに使用できる文字は「半角英数字」と「ハイフン
-
」です- 「アンダースコア
_
」 は使用できません
.com
などのドメインを選択し,「料金確認へ進む」ボタンをクリック
- 自動選択されているチェックを外し忘れないように注意しましょう
- こだわりがなければ初年度の安いドメインを取得してもよいでしょう
購入処理を行って下さい。「Whois情報公開代行」は必須ですが,その他のオプションは全て不要です
- 「サーバー」は「利用しない」をチェック
- 「Whois情報公開代行メール転送オプション」などは全てチェック不要
「お申し込みを受け付けました。」と表示されたら「ドメインの設定はこちら」のリンクをクリック
【備考】後に続きの操作をおこないますので,他のタブで続きの作業を進めて下さい
自動更新の解除
初期設定では,ドメインの更新期限日を過ぎますと自動更新・自動課金されます。
2年目以降は料金が高くなるドメインが多いですので,自動更新を解除したい場合は以下の操作を行ってください。
「お名前.com」のページ上側にあるタブの「ドメイン」を選択
「更新画面から移動する」をクリック
アプリで使用するドメインを選択
- 「自動更新」ボタンをクリック
「確認画面へ進む」をクリック
「自動更新設定申込内容」の項目が「解除する」になっていることを確認の上,「規約に同意し、上記内容を申し込む」ボタンをクリック
「解除する」ボタンをクリック
「ドメイン一覧」のタブをクリック
【備考】後に続きの操作をおこないますので,続きの作業は他のタブで進めて下さい
7.2 IPアドレスとドメインの関連付け
Route 53
を利用することで,先ほど購入したドメイン
をIPアドレス
に変換することができます。通常の使用範囲内ならば月100円もかかりません。
AWS
の画面左上の「サービス」を開き、検索欄に「route」と入力し、「Route 53」を選択「ホストゾーンの作成」ボタンをクリック
キー 値 ドメイン名 取得したドメインを記載 説明 - オプション アプリ名_domain タイプ パブリックホストゾーン
「ホストゾーンの作成」ボタンをクリック
タイプが「NS」の方の「値/トラフィックのルーティング先」に表示されている4つを
ネームサーバー
としてメモしておいて下さい
- 【要注意】メモする際に,それぞれの最後についている「ドット
.
」は削除して下さい!7.3 ネームサーバーの変更
先ほど残しておいた「お名前.com」に移動して下さい
(タブを閉じてしまった場合は,再度「お名前.com」にアクセスし,ログインして下さい)
「ドメイン一覧」の中から取得した「ドメイン名」を選択
「ネームサーバー情報」の項目の「ネームサーバーの変更」をクリック
「2.ネームサーバーの選択」をクリック
「その他」タブをクリックし,「その他のネームサーバーを使う」の方にチェックを入れ,先ほどメモした4つの
ネームサーバー
をコピペして下さい
- 先ほど注意しました通り,最後についている「ドット
.
」は入力しないで下さい7.4 ネームサーバーの確認
ローカル環境のターミナルから以下を実行して下さい。
ローカル環境のターミナルdig ドメイン名 NS +short登録した4つのドメインが入っていればOKです。(順番が入れ替わっていてもOK)
デフォルトの2つしか入っていない場合は,しばらく待ってから再度先ほどのコマンドを実行しましょう。
7.5 ドメインの適用
AWS
のRoute 53
の先ほどの続きの画面から,「レコードを作成」をクリック「シンプルルーティング」にチェックを入れた状態で「次へ」ボタンをクリック
「シンプルなレコードを定義」ボタンをクリック
キー 値 レコード名 ※入力しない 値/トラフィックのルーティング先 「レコードタイプに応じた IP アドレス または別の値」をクリックし, Elastic IP
を入力レコードタイプ A これで準備が完了です。まずは,ローカル環境のターミナルから以下を実行して下さい。
ローカル環境のターミナルcurl -I ドメイン名
最初に
HTTP/1.1 200 OK
もしくはHTTP/1.1 302
が出れば正常です。前回は
Elastic IP
でなければアクセスできませんでしたが,今度はドメイン名
でアクセスできる状態になっています。ブラウザから
ドメイン名
でアクセスし,スーパーリロード
して下さい。(ショートカットキーはcommand + shift + r
)8. HTTPS化(ACM, ALB)
次はこちらの問題に対処していきましょう。
- HTTPSではない
- Google Chrome で「このサイトへの接続は保護されていません」という警告が出る
【備考】
ELB
のApplication Load Balancer(ALB)
を利用しますので,月2000円程度の費用がかかります。8.1 ACM
HTTPS化
には,まず,SSL/TLS サーバー証明書
を取得する必要があります。
Let's Encrypt
で取得する方法が有名ですが,AWSを利用する場合はSSL/TLS サーバー証明書
をACM
で取得し,ALB
に関連付けるのが一般的な手法です。作業が楽で,更新の手間も不要になります。
ALB
と関連付けますので,ACM
自体は無料で利用できます。
AWS
の画面左上の「サービス」を開き、検索欄に「acm」と入力し、「Certificate Manager」を選択「証明書のプロビジョニング」の「今すぐ始める」ボタンをクリック
「パブリック証明書のリクエスト」を選択した状態で「証明書のリクエスト」ボタンをクリック
「この証明書に別の名前を追加」をクリック
取得した「ドメイン名」と「*.ドメイン名」を入力
「次へ」ボタンをクリック
- 「DNS の検証」を選択した状態で「次へ」ボタンをクリック
タグ名 値 Name アプリ名_alb
「確認」ボタンをクリック
「確定とリクエスト」ボタンをクリック
「続行」ボタンをクリック
8.2 DNS検証用の CNAME レコード追加
- ドメインの欄のプルダウンを開き,「Route 53 でのレコードの作成」ボタンをクリック
- 2つ表示されていますが,どちらか片方のみでOKです
- プルダウンが表示されない場合は,一度リロードして下さい
- 「作成」ボタンをクリック
【注意】
8.3
は先に行っても問題ありませんが,8.4
以降の作業は,状況が「検証保留中」から「発行済み」に変わってから行って下さい8.3 ALB 用のセキュリティグループの作成
【構成内容】
クライアント
--(HTTP or HTTPS)-->ALB
--(HTTP)-->EC2
ELB
の内のALB
(Application Load Balancer) を使用し,先ほど取得したSSL/TLS サーバー証明書
を使用できるように設定していきましょう。
ALB
はEC2
の前にリクエストを受け,(一般には複数の)EC2
に分散します。このことを踏まえたセキュリティグループを作成しましょう。
画面左上の「サービス」を開き、検索欄に「ec2」と入力し、「EC2」を選択
EC2
画面左のメニューバーの「セキュリティグループ」を選択し,「セキュリティグループを作成」ボタンをクリック
キー 値 セキュリティグループ名 アプリ名_alb_security_group 説明 アプリ名_alb_security_group VPC アプリ名_vpc 「インバウンドルール」の「ルールを追加」を2回クリック
キー 値 タイプ HTTP プロトコル TCP ※自動選択 ポート範囲 80 ※自動選択 ソース 任意の場所 (0.0.0.0/0 と ::/0 が表示) 説明 ※空白でOK
キー 値 タイプ HTTPS プロトコル TCP ※自動選択 ポート範囲 443 ※自動選択 ソース 任意の場所 (0.0.0.0/0 と ::/0 が表示) 説明 ※空白でOK 「アウトバウンドルール」は
デフォルトの設定を削除した後
「ルールを追加」をクリックし,以下を追加
キー 値 タイプ HTTP プロトコル TCP ※自動選択 ポート範囲 80 ※自動選択 ソース カスタム: アプリ名_ec2_security_group 説明 ※空白でOK 作成後に次の図のようにルールが定まっているかどうかを確認して下さい。
8.4 ロードバランサーの設定
画面左のメニューバーの「ロードバランサー」を選択
「ロードバランサーの作成」ボタンをクリック
「HTTP, HTTPS」の方の「作成」ボタンをクリック
■ 手順 1: ロードバランサーの設定
- 【基本的な設定】
キー 値 名前 アプリ名-alb ※ ハイフンに変更 他はデフォルト
- 【リスナー】
「リスナーの追加」ボタンをクリックし,「HTTPS」を選択
- 【アベイラビリティゾーン】
キー 値 VPC アプリ名_vpc アベイラビリティーゾーン 「ap-northeast-1a」を選択し「アプリ名_public_1a_subnet」を選択 アベイラビリティーゾーン 「ap-northeast-1c」を選択し「アプリ名_public_1c_subnet」を選択 「次の手順: セキュリティ設定の構成」ボタンをクリック
■ 手順 2: セキュリティ設定の構成
- 「証明書の名前」がアプリ用のドメインであることを確認し,「セキュリティグループの設定」をクリック
■ 手順 3: セキュリティグループの設定
- 「アプリ名_alb_security_group」を選択し,「次の手順: ルーティングの設定」ボタンをクリック
■ 手順 4: ルーティングの設定
- ターゲットグループ
キー 値 ターゲットグループ 新しいターゲットグループ 名前 アプリ名-target-group ※ ハイフンに変更 ターゲットの種類 インスタンス ※デフォルト プロトコル HTTP ※自動設定 ポート 80 ※自動設定
- ヘルスチェック
デフォルト設定でOK
「次の手順: ターゲットの登録」ボタンをクリック
■ 手順 5: ターゲットの登録
- 「インスタンス」欄から、「アプリ名_instance」にチェックを入れた状態で「登録済みに追加」ボタンをクリック
「次の手順: 確認」をクリック
「作成」ボタンをクリック
8.5 Route 53の設定を修正
ドメインを
EC2
から先ほど作成したALB
に割り当てるように設定を変更しましょう。
AWS
の画面左上の「サービス」を開き、検索欄に「route」と入力し、「Route 53」を選択「ホストゾーン」をクリック
アプリで使用するドメインをクリック
- 「タイプA」の「ドメイン名」のレコードをクリックし,「編集」ボタンをクリック
- 「値/トラフィックのルーティング先」の箇所を変更して下さい
- 「Application Load Balancer と Classic Load Balancer へのエイリアス」を選択
- 「アジアパシフィック (東京) [ap-northeast-1]」を選択
- 「アプリ名-alb」を含むロードバランサーを選択
- 「変更を保存」ボタンをクリック
8.6 セキュリティグループの修正
ALB
経由でアクセスされるように変更したため,EC2
はALB
からのアクセスに限定すべきです。そのため,EC2
用のセキュリティグループを修正します。
AWS
の画面左上の「サービス」を開き、検索欄に「ec2」と入力し、「EC2」を選択画面左のメニューバーの「セキュリティグループ」を選択
「アプリ名_ec2_security_group」にチェックを入れ,「アクション」ボタンをクリックし,「インバウンドルールを編集」ボタンをクリック
- タイプが
HTTP
のものを全て削除し,「ルールを追加」をクリックし,以下を設定
SSH
は削除しないこと
キー 値 タイプ HTTP ソース カスタム: アプリ名_alb_security_group 説明 ※空白でOK
- 「ルールを保存」ボタンをクリック
8.7 Nginx の設定ファイルを修正
ALB
への接続に使用するプロトコルがHTTPS
であることを識別できるよう,Nginx
の設定ファイルを修正し,再起動しておきましょう。(こちらを実行しないと,例えば POST リクエスト時にエラーが発生します)
サーバー環境のターミナルsudo sed -i s/X-Forwarded-Proto\ http/X-Forwarded-Proto\ https/g /etc/nginx/conf.d/$APP_NAME.conf sudo service nginx restartそれでは,
HTTPS
でアクセスできるかを確認しましょう。まずはターミナルから以下を実行して下さい。ターミナル(ローカル側でもサーバー側でもOK)curl -I https://ドメイン名
最初に
HTTP/2 200
もしくはHTTP/2 302
が表示されれば正常です。次にブラウザからhttps://ドメイン名
にアクセスし,スーパーリロード
して下さい。(ショートカットキーはcommand + shift + r
)ブラウザのURLの左隣に「鍵マーク」が表示され,アプリが問題なく開けばOKです!
8.8 HTTPS にリダイレクト
【参考】 https://aws.amazon.com/jp/premiumsupport/knowledge-center/elb-redirect-http-to-https-using-alb/
最後に,
HTTP
でのアクセスをHTTPS
にリダイレクトするように設定しましょう。
EC2
の画面左のメニューバーの「ロードバランサー」をクリック(「アプリ名-alb」を選択した状態で)「リスナー」タブをクリック
HTTP : 80
の方の 「ルールの表示/編集」をクリック
- 上の「鉛筆」マークをクリックし,下に出現した「鉛筆」マークをクリック
- 「THEN」の項目の転送先にある「ゴミ箱」マークをクリックして削除
「アクションの追加」を選択し,「リダイレクト先」をクリック
「HTTPS」になっていることを確認し,ポートに
443
を入力「チェックマーク」をクリック
右上の「更新」ボタンをクリック
これで
http
でアクセスした場合もhttps
に自動変換されるようになりました。ターミナルから以下を実行してみましょう。ターミナル(ローカル側でもサーバー側でもOK)curl -I http://ドメイン名
最初に
HTTP/1.1 301 Moved Permanently
が表示され,最後にLocation: https://アプリ名:443/
が表示されていればOKです。ブラウザでも
http://ドメイン名
でアクセスしてみましょう。URLの左隣に鍵マークが付いていればOKです!お疲れ様でした!
8.9 最後に
グローバル変数の削除
作業が終わりましたので,ローカル環境で定義したグローバル変数
$APP_NAME
は消しておくこととしましょう。ローカル環境のターミナル# zsh の場合 vi ~/.zshrc # bash の場合 vi ~/.bash_profile一番最後の行にある
export APP_NAME=アプリ名
を削除して下さい。EC2のパスワード設定
次に,EC2のユーザーにパスワードを設定し,
sudo
コマンド実行時にパスワードを求められるように変更しましょう。(作業を楽にするため,EC2のユーザーはパスワード無しで
sudo
コマンドを使用できる状態にしていました)サーバー環境のターミナルsudo passwd `whoami` 設定したいEC2のパスワードを入力 EC2のパスワードを再入力【注意】「EC2のパスワード」は必ずメモしておいて下さい。
サーバー環境のターミナルsudo visudo
Vim
で開かれたら,一番最後の行のNOPASSWD:
の箇所のみ削り,次の状態にして下さい。sudoersユーザー名 ALL=(ALL) ALL【注意】
ユーザー名 ALL=(ALL) NOPASSWD: ALL
を「全て」削ってはいけません!編集を間違えると,二度と sudo コマンドを実行できなくなる恐れがありますので,慎重に行ってください。これで
sudo
コマンドを実行した際に今後はパスワードを尋ねられるようになります。以下を実行し,パスワードを求められるかどうか,パスワードを入力してコマンドを実行できるかどうかを確かめて下さい。
サーバー環境のターミナルsudo ls
9. デプロイ関連事項
この章は必要な場合のみご覧ください。
9.1 アプリ修正時の反映方法
以下のコマンドで「GitHub」の master ブランチをAWS側に反映させることができます。
ローカル環境のターミナル# Railsアプリのルートディレクトリに移動してから bundle exec cap production deploy【注意】 Heroku のデプロイで使用する
git push heroku master
は「ローカル」の master ブランチを反映させるコマンドです。bundle exec cap production deploy
コマンドは「ローカル」ではなく「GitHub」である点に注意しましょう。9.2 master以外のブランチを反映させたい
config/deploy.rbset :branch, ENV['BRANCH'] || "master"を追加すれば,例えば以下のコマンドで「GitHub」の
hoge
ブランチを反映できます。ローカル環境のターミナルbundle exec cap production deploy BRANCH=hoge例えば,現在のブランチをAWS側で動作確認したい場合は次の手順になります。
ローカル環境のターミナル# add, commit の実行後 git push origin HEAD bundle exec cap production deploy BRANCH=HEAD9.3 AWS側で Rails コマンドや rake タスクを実行する方法
サーバー側のアプリは
/var/www/$APP_NAME/current
に入っています。まずはここまで移動し,必要に応じて
yarn install --check-files
を実行して下さい。サーバー環境のターミナルcd /var/www/$APP_NAME/current yarn install --check-filesその上で,必要なコマンドを実行しましょう。コマンド例を紹介します。
- サーバー側で
rails db:seed
を実行したい場合サーバー環境のターミナル(/var/www/$APP_NAME/current)bin/rails db:seed RAILS_ENV=production
bin/rails
はbundle exec rails
でも問題ありませんが,rails
ではダメです。また,RAILS_ENV=production
が必要である点に注意して下さい。
- サーバー側で
rails db:migrate:reset
を実行したい場合サーバー環境のターミナル(/var/www/$APP_NAME/current)bin/rails db:migrate:reset RAILS_ENV=production DISABLE_DATABASE_ENVIRONMENT_CHECK=1本番環境のデータベースを削除(リセットを含む)したい場合は,
DISABLE_DATABASE_ENVIRONMENT_CHECK=1
が必要です。
- サーバー側で
rails console
を実行したい場合サーバー環境のターミナル(/var/www/$APP_NAME/current)bin/rails c -e production
オプションが
RAILS_ENV=production
ではなく-e production
の書き方になります。
- サーバー側で
rake
タスクを実行したい場合サーバー環境のターミナル(/var/www/$APP_NAME/current)bundle exec rake タスク名 RAILS_ENV=productionタスク名は
bundle exec rake -T
で確認できます。bundle exec rake
はbin/rails
でもOKですがrake
ではダメです。9.4 サーバー側で ログ を確認する方法
サーバー側の
ログ
は/var/www/$APP_NAME/shared/log
に入っています。サーバー環境のターミナルcd /var/www/$APP_NAME/shared/log lsでログファイルの一覧を確認できます。
エラーが出た場合は,
nginx.error.log
かpuma_error.log
を確認しましょう。サーバー環境のターミナル(/var/www/$APP_NAME/shared/log)# ログを全て表示したい場合 cat nginx.error.log # 最後の30行を表示したい場合 tail -n 30 nginx.error.log # ログの追加分のみを自動表示したい場合(control + c で終了) tail -f nginx.error.log10. S3
【注意】10章, 11章は,
CarrierWave
やActiveStorage
などで画像の投稿機能を実装している場合のみ,実行して下さい。現状でも画像の投稿は可能ですが,
AWS S3
を使用することで,Webサーバー(EC2
)のストレージが画像で圧迫されるのを防いだり,負荷分散ができるなど複数のメリットがあります。さらに,
CloudFront
を用いることで画像転送を高速化するところまでを解説します。10.1 S3バケットの作成
S3
は,クラウド型のオブジェクトストレージサービスです。画像に限らずいろいろなデータを保存することができ,簡単なWebサイトの公開にも使用できます。セキュリティ・耐久性共に優れ,価格も安いのが特徴です。ポートフォリオの画像投稿機能に使用する程度であれば,大抵の場合は無料利用枠内でおさまるでしょう。
S3
を利用するには,まず,バケット
を作成する必要があります。
画面左上の「サービス」を開き、検索欄に「s3」と入力し、「S3」を選択
「バケットの作成」を選択
一般的な設定
タイトル 内容 バケット名 任意 ※世界ですでに存在する名前は付けられません リージョン アジアパシフィック (東京) ap-northeast-1 【注】 バケット名とリージョン
ap-northeast-1
を忘れないようにメモしておいて下さい。
- ブロックパブリックアクセスのバケット設定
下の2つ(ACL以外)のみをチェックし,注意喚起にもチェック
「バケットを作成」をクリック
10.2 アプリ用のIAMユーザーを作成
次に,アプリ側から
S3
にアクセスするためのアクセスキー
などを入手しましょう。
画面左上の「サービス」を開き、検索欄に「iam」と入力し、「IAM」を選択
左のメニューから「ユーザー」を選択
青いボタン「ユーザーを追加」をクリック
タイトル 内容 ユーザ名 アプリ名_user アクセスの種類 「プログラムによるアクセス」にチェック
「次のステップ:アクセス権限」をクリック
「既存のポリシーを直接アタッチ」ボタンをクリック
AmazonS3FullAccess
をチェックして,「次のステップ: タグ」ボタンをクリック
- 「参考」のようにより権限を厳しくしたポリシーをアタッチするとより安全です
「次のステップ: 確認」ボタンをクリック
「ユーザーの作成」をクリック
「.csvのダウンロード」ボタンをクリック
「ユーザー名」「アクセスキーID」「シークレットアクセスキー」をメモしておいて下さい。
- 「閉じる」ボタンをクリック
参考: 権限の少ないポリシーを作成
AmazonS3FullAccess
はS3
の全ての操作ができる権限ですので,アプリに持たせる権限としては過剰すぎます。最低限必要な権限をもつポリシーを作成し,
AmazonS3FullAccess
の代わりにこちらをIAMユーザーにアタッチしておくと,万一の場合の被害を軽減することができます。IAMポリシー{ "Version": "2012-10-17", "Statement": [ { "Sid": "VisualEditor0", "Effect": "Allow", "Action": [ "s3:PutObject", "s3:GetObject", "s3:DeleteObject", "s3:PutObjectAcl", "s3:ListAllMyBuckets" ], "Resource": "*" } ] }さらに安全を求めるならば,バケットまで制限することも可能ですが,ここでは省略します。
10.3 CarrierWaveの設定
※ 以下,画像投稿機能に
CarrierWave
を使用していることを前提としますまず,Railsアプリに
fog-aws
をGemfile
に追加し,インストールしておきましょう。ローカル環境のターミナルbundle add fog-aws本番環境のみで
AWS S3
を使用する場合は次のように修正しましょう。(開発環境でも使用したい場合は,条件分岐せず
storage :fog
のみにして下さい)app/uploaders/image_uploader.rb# 「storage :file」を以下に置き換える if Rails.env.production? storage :fog else storage :file end次に,
S3
の「アクセスキーID」などを読み込む設定を追加しましょう。特に「シークレットアクセスキー」は,GitHubに公開してはならないので,
credentials.yml.enc
から読み込む形式とします。「リージョン」と「バケット名」は公開しても問題ありませんので,直接記載することとします。
ローカル環境のターミナルtouch config/initializers/carrier_wave.rb
(開発環境でもS3を使用したい場合は,最初の行
if Rails.env.production?
と最後の行end
を削りましょう)config/initializers/carrier_wave.rbif Rails.env.production? CarrierWave.configure do |config| config.fog_credentials = { provider: "AWS", aws_access_key_id: Rails.application.credentials.dig(:aws, :access_key_id), aws_secret_access_key: Rails.application.credentials.dig(:aws, :secret_access_key), region: "ap-northeast-1" } config.fog_directory = "S3のバケット名" end end
credentials.yml.enc
を開くため,次のコマンドを実行ターミナルEDITOR=vi rails credentials:edit
- アプリが
S3
にアクセスするために必要な情報をcredentials.yml.enc
に記載しましょう
yaml
形式なので,インデント幅にはくれぐれも注意して下さい- 例えば,
access_key_id:
の後に「半角スペース1個」がないだけでエラーになりますconfig/credentials.yml.encdb: password: RDSのパスワード hostname: RDSのエンドポイント # 以下を追加 aws: access_key_id: IAMユーザーのアクセスキーID secret_access_key: IAMユーザーのシークレットアクセスキー10.4. 動作確認
念のため以下を実行し,「アクセスキーID」などが取得できることを確認しておいた方がよいでしょう。
ローカル環境のターミナルrails c # コンソール起動後 Rails.application.credentials.dig(:aws, :access_key_id) Rails.application.credentials.dig(:aws, :secret_access_key) # IAMユーザーのアクセスキーID, シークレットアクセスキーが表示されることを確認後 exitコミット・プッシュ(必要があればプルリク・マージ)などを行い,GitHub の master ブランチに変更を反映した上で,
AWS
にデプロイを行いましょう。ローカル環境のターミナルbundle exec cap production deploy
【補足】
9.2
に記載した方法で,masterブランチにマージする前に確認するのが理想的ですこれで本番環境では
S3
に画像を投稿し,読み込みができるようになりました。ブラウザから
https://ドメイン名
にアクセスし,画像を投稿してみましょう。問題なく画像が投稿・表示できていればOKです。念のため,AWSにログインし
S3
のバケットに画像が保存されているかどうかも確認しておくとよいでしょう。バケットを選択し,ディレクトリを選択していき,「オブジェクト URL」をクリックして投稿した画像が表示されていればOKです。
11. CloudFront
最後に
CloudFront
を用いて画像の表示を高速化できるようにし,さらに画像のURLを独自ドメインに変更しましょう。
CloudFront
も1年間は無料利用枠があり,料金も安いのであまり気にしなくてよいでしょう。11.1 ACM
CloudFront
で ACM 証明書を使用するには、「米国東部」リージョンで証明書をリクエストする必要があります。
AWS
の画面左上の「サービス」を開き、検索欄に「acm」と入力し、「Certificate Manager」を選択【重要!】右上の「東京」を「米国東部 (バージニア北部)us-east-1」に変更
「証明書のプロビジョニング」の「今すぐ始める」ボタンをクリック
「パブリック証明書のリクエスト」を選択した状態で「証明書のリクエスト」ボタンをクリック
static.ドメイン名
を入力
static
の箇所は任意ですが,変更する場合は以降も合わせて変更して下さい
「次へ」ボタンをクリック
「DNS の検証」を選択した状態で「次へ」ボタンをクリック
タグ名 値 Name アプリ名_cloudfront
「確認」ボタンをクリック
「確定とリクエスト」ボタンをクリック
「続行」ボタンをクリック
DNS検証用の CNAME レコードを追加(8.2参照)
11.3
の作業は,状況が「検証保留中」から「発行済み」に変わってから行う必要があるため,ブラウザのタブは残しておきましょう11.2 CarrierWaveの設定
次に,Railsアプリ側のCarrierWaveの設定に追記しましょう。
config/initializers/carrier_wave.rbif Rails.env.production? CarrierWave.configure do |config| config.fog_credentials = { provider: "AWS", aws_access_key_id: Rails.application.credentials.dig(:aws, :access_key_id), aws_secret_access_key: Rails.application.credentials.dig(:aws, :secret_access_key), region: "ap-northeast-1" } config.fog_directory = "S3のバケット名" # ***** 以下を追加 ***** config.asset_host = "https://static.ドメイン名" # ***** 以上を追加 ***** end endコミット・プッシュ(必要があればプルリク・マージ)などを行い,GitHub の master ブランチに変更を反映した上で,
AWS
にデプロイを行いましょう。ローカル環境のターミナルbundle exec cap production deploy
11.3 CloudFront
【注意】
ACM
の状況が「検証保留中」から「発行済み」に変わってから行って下さい
画面左上の「サービス」を開き、検索欄に「cloudfront」と入力し、「CloudFront」を選択
「Create Distribution」ボタンをクリック
「Web」の方の「Get Started」を選択
【Origin Settings】
キー 値 Origin Domain Name S3のバケット名を選択 Restrict Bucket Access Yes 【Default Cache Behavior Settings】
キー 値 Viewer Protocol Policy Redirect HTTP to HTTPS 【Distribution Settings】
キー 値 Alternate Domain Names static.ドメイン名 SSL Certificate Custom SSL Certificate をチェックし,自分のドメインを選択 他はデフォルト設定のまま,右下の「Create Distribution」ボタンをクリック
【注意】 続きの作業は「Status」が「Deployed」になってから行ってください。
11.4 Route 53
最後に
CloudFront
用のAレコードを作成しましょう。
AWS
の画面左上の「サービス」を開き、検索欄に「route」と入力し、「Route 53」を選択「ホストゾーン」をクリック
アプリで使用するドメインをクリック
「レコードを作成」ボタンをクリック
「シンプルルーティング」にチェックを入れた状態で「次へ」ボタンをクリック
「シンプルなレコードを定義」ボタンをクリック
キー 値 レコード名 static 値/トラフィックのルーティング先 CloudFront ディストリビューションへのエイリアス 米国東部 (バージニア北部) CloudFrontのドメイン名を選択 レコードタイプ A
- 「シンプルなレコードを定義」ボタンをクリック
これで全ての設定が完了です。
ブラウザから
https://ドメイン名
にアクセスし,再度画像を投稿してみましょう。問題なく画像が投稿・表示できていればOKです。念のため,AWSにログインし
S3
のバケットに画像が保存されているかどうかも確認しておくとよいでしょう。「無事全てが完了した!!」という方は是非 LGTM もお願いいたします!
12. 削除方法
AWS
は有料ですので,アプリの公開が不要となったタイミングで削除することをお勧めします。以下,削除の手順を解説しますが,特に有料となっている以下の削除を忘れないようにしましょう。
- RDSインスタンス【高額!】
- ALB(ロードバランサ)【高額!】
- EC2インスタンス【高額!】
- Elastic IP(EC2を削除すると課金対象)
- Route 53
- ACM
- S3(画像投稿機能を付けた場合)
- CloudFront(画像投稿機能を付けた場合)
12.1 Route 53 の削除
Route 53 ダッシュボードに移動
- (画面左上の「サービス」を開き、検索欄に「route」と入力し、「Route 53」を選択)
画面左のメニューバーの「ホストゾーン」をクリック
アプリで使用したドメインをクリック
タイプが
A
とCNAME
のものにチェックを入れ,「削除」ボタンをクリックし,さらに「削除」ボタンをクリック右上の「削除」ボタンをクリック
「削除」と入力し,「削除」ボタンをクリック
12.2 ALB の削除
EC2 ダッシュボードに移動
- (画面左上の「サービス」を開き、検索欄に「ec2」と入力し、「EC2」を選択)
画面左のメニューバーの「ロードバランサー」をクリック
「アクション」ボタンをクリックし,「削除」をクリック
- 使用しているロードバランサーが表示されない場合は,右上のリージョンが「東京」になっているか確認
「削除」をクリック
12.3 CloudFront の削除
【備考】画像投稿機能を付けていない場合は,次に進んで下さい。
CloudFront ダッシュボードに移動
- (画面左上の「サービス」を開き、検索欄に「cloudfr」と入力し、「CloudFront」を選択)
使用している
Distribution
にチェックを入れて,「Disable」ボタンをクリック「Yes, Disabled」ボタンをクリック
「Status」が「Disabled」になるまで待ちましょう
使用している
Distribution
にチェックを入れて,「Delete」ボタンをクリック「Yes, delete」ボタンをクリック
「Close」ボタンをクリック
12.4 SSL証明書 の削除
Certificate Manager ダッシュボードに移動
- (画面左上の「サービス」を開き、検索欄に「acm」と入力し、「Certificate Manager」を選択)
アプリで使用したドメインを選択し,「アクション」ボタンをクリックし,「削除」をクリック
「削除」ボタンをクリック
【備考】画像投稿機能を付けている場合は,「東京」リージョンだけでなく「バージニア北部」リージョンのACMも削除して下さい。
12.5 EC2 の削除
- EC2 ダッシュボードに移動
- (画面左上の「サービス」を開き、検索欄に「ec2」と入力し、「EC2」を選択)
ターゲットグループの削除
画面左のメニューバーの「ターゲットグループ」をクリック
アプリで使用していたものを選択した状態で「Action」のプルダウンの「Delete」をクリック
「Yes, delete」ボタンをクリック
EC2 インスタンスの削除
- 画面左のメニューバーの 「インスタンス」をクリック
- 削除したいインスタンスを選択した状態で「アクション」ボタンをクリックし,「インスタンスの状態」「インスタンスを終了」をクリック(「停止」ではない)
- 「終了」ボタンをクリック
Elastic IP の解放
- 画面左のメニューバーの
Elastic IP
をクリック- 削除したい
Elastic IP
を選択した状態で「アクション」ボタンをクリックし,「Elastic IPアドレスの解放」をクリック
- EC2終了後少し待たないと解放できません
- 削除したい
Elastic IP
が消えたことを確認その他
- 「キーペア」も削除しましょう
- 「セキュリティグループ」は
VPC
削除時に自動的に削除されます12.6 RDS の削除
- RDS ダッシュボードに移動
- (画面左上の「サービス」を開き、検索欄に「rds」と入力し、「RDS」を選択)
s RDS インスタンスの削除
- 画面左のメニューバーの「データベース」をクリック
- 削除したい DB を選択し,「アクション」ボタンをクリックし,「削除」をクリック
- 「最終スナップショットを作成しますか?」のチェックを外し,「インスタンスの削除後、システムスナップショットとポイントインタイムの復元を含む自動バックアップが利用不可となることを了承しました。」にチェックを入れ,フィールドに「delete me」を入力して「削除」ボタンをクリック
その他
- 「サブネットグループ」を削除
- RDSが削除されるまで削除できません
- 「パラメータグループ」は残してよいでしょう。
12.7 VPC の削除
VPC ダッシュボードに移動
- (画面左上の「サービス」を開き、検索欄に「vpc」と入力し、「VPC」を選択)
削除したい VPC を選択し,「アクション」ボタンをクリックし,「VPC を削除」をクリック
フィールドに「削除」と記入して「削除」ボタンをクリック
サブネット,インターネットゲートウェイ,ルートテーブルも同時に削除されます。
12.8 S3/IAM の削除
【備考】画像投稿機能を付けていない場合は,次に進んで下さい。
S3 の削除
S3 ダッシュボードに移動
- (画面左上の「サービス」を開き、検索欄に「s3」と入力し、「S3」を選択)
アプリで使用したバケットを選択し,「空にする」ボタンをクリック
「完全に削除」と入力し「空にする」ボタンをクリック
「終了」ボタンをクリック
「削除」ボタンをクリック
「バケット名」を入力し,「バケットを削除」ボタンをクリック
IAM の削除
IAM ダッシュボードに移動
- (画面左上の「サービス」を開き、検索欄に「iam」と入力し、「IAM」を選択)
画面左のメニューバーの「ユーザー」をクリック
「アプリ名_user」にチェックを入れ,「ユーザーの削除」ボタンをクリック
- アプリと関係ないものを削除しないように注意!
「はい,削除します」ボタンをクリック
12.9 キーペアの削除
GitHub の公開鍵を削除
- ブラウザでGitHubにアクセス
- 右上のサムネイル画像をクリック
- 「Settings」をクリック
- 左メニューバーから「SSH and GPG keys」をクリック
- 「アプリ名_git_rsa/pub」の箇所で「Delete」ボタンをクリック
- 「I understand, please delete this SSH key」ボタンをクリック
ローカル環境のキーペアの削除
最後に,ローカル環境の秘密鍵と設定を削除しておきましょう。
ローカル環境のターミナルcd ~/.ssh rm -f アプリ名.pem vi config # Host アプリ名 の設定を削除
- 投稿日:2020-11-26T18:00:43+09:00
サルでもできる!? Rails6アプリをAWS EC2にデプロイするまでの全手順【前半】(VPC, RDS, EC2, Capistrano)
この記事では,画像投稿機能の付いた
Rails 6
のアプリをAWS EC2
にデプロイするまでの全過程を解説します。Railsアプリのデプロイに関する記事はたくさん見かけますが,初学者にとっては
「具体的に何をすればよいかが分からない」
記事がほとんどで,ましてや「独自ドメインの設定方法」や「投稿画像を独自ドメインでCloudFrontから配信する方法」まで網羅的に解説を行っている記事は見当たらない状態です。
そこで,「Rails初学者が初めてAWSにデプロイする際に本当に参考となる記事」を目指して書かせていただきました。
「
Heroku
にデプロイしたことはあるけれど,AWS
にデプロイしたことがない」という方を対象としますので,AWS
の操作は,直感的に操作できるAWS マネジメントコンソール
で行います。
AWS CLI
やTerraform
などのツールは使用しませんので,あらかじめご了承下さい。
章 タイトル 【前半】 <-- こちら 1章 はじめに 2章 VPC 3章 RDS 4章 EC2 5章 サーバー構築 6章 デプロイ(Capistrano) 【後半】 7章 独自ドメイン 8章 HTTPS化(ACM, ALB) 9章 デプロイ関連事項 10章 S3 11章 CloudFront 12章 削除方法 1. はじめに
1.1 注意事項
この記事における注意事項を列記します。
料金
AWS
は有料のサービスで,いわゆる従量課金制です(サービスの使用量に応じて料金が決まります)。この記事の構成で
AWS
を利用した場合,ポートフォリオのようにあまりアクセスが来ないアプリであっても,(無料利用枠を使用する前提で)月におよそ3000円前後かかります。
RDS
,ALB
などを使用せず,EC2
にデータベースシステムをインストールする構成にすればもっと安く済ませることができますが,ポートフォリオのアピール材料としては弱くなるでしょう。なお,エラーが発生した際に原因を特定しやすくするため,
AWS
へのデプロイはアプリの完成後ではなく
,開発初期の段階
から行うことをお勧めします。ただ,料金の問題がありますので,アプリの開発初期は
Heroku
にデプロイし,仕上げの段階でAWS
にデプロイするという手法もありでしょう。Railsアプリの条件
AWSにデプロイ予定のアプリが,以下の条件を満たすことを前提とします。
アプリの Rails のバージョンが
6
であること(5
でも多分OK)データベースは
MySQL 5.7
もしくはPostgreSQL
を使用画像投稿機能がある場合は
CarrierWave
を使用
6.1
に画像投稿機能の付いたサンプルアプリを作成する方法を紹介しておりますので,必要がございましたらご利用下さい。構成図
以下のような一般的な構成を目指します。(料金の都合上,冗長化は行いません)
サーバー環境
- 【Web サーバー】 Nginx
- 【アプリケーションサーバー】 Puma
使用する AWS のサービス
- VPC(Amazon Virtual Private Cloud)
- RDS(Amazon Relational Database Service)
- EC2(Amazon Elastic Compute Cloud)
- Route 53
- ACM(Certificate Manager)
- ALB(Application Load Balancer)
- S3(Amazon Simple Storage Service)
- IAM(AWS Identity and Access Management)
- CloudFront
基礎知識の解説
この記事は,「画像投稿機能の付いた Rails アプリを AWS EC2 にデプロイし,独自ドメインでアクセスできるようにする」ことを主目的としております。
最低限度知っておくべき内容は触れますが,インフラの基礎知識は解説しません。
AWS に必要な基礎知識を学べる本はたくさんありますし,Udemyにも丁寧な解説動画が存在します。デプロイの完了後でもよいですので,是非学習されることをお勧めします。
注意点
理解が不十分な状態で進められる場合は,
絶対にミスをしない
ように気を付けて下さい。1つのミスで最初からやり直すことになり,数時間の作業が無駄になる可能性があります。コメントについて
記事内の改善点・間違いなどございましたら,遠慮なくご指摘下さい。可能な限りで記事にも反映させていただきます。
Qiita上の質問には原則お答えする時間が取れませんので,あらかじめ了解いただいた上でご質問下さい。
メモ
作業中にパスワードなど各自設定が異なる部分が複数存在します。メモ帳に以下を貼り付け,決まり次第埋めていくようにされるとよいでしょう。
メモ【アプリ名】 【RDS】 ●マスターユーザー名 ●マスターパスワード ●エンドポイント 【EC2】 ●Elastic IP ●sshでサインインするときのコマンド ssh アプリ名 ●ユーザー名 ●パスワード 【ドメイン】 ●ドメイン名 ●ネームサーバー情報 【S3】 ●バケット名 ●リージョン 【IAM】 ●ユーザー名 ●アクセスキーID ●シークレットアクセスキー 【CloudFront】 static.ドメイン名まずは,AWSで使用する
アプリ名
を決め,上記にメモして下さい。ただし,「aws_sample_app」のようにスネークケース
表記であることを前提とします。(アルファベット大文字は使わないで下さい)「(AWSで使用する)アプリ名」は,「Railsのアプリ名」「GitHubのリポジトリ名」と合わせる方が混乱しづらいと思いますが,同じでなくても問題ありません。
以下,
アプリ名
と記載している箇所は,全てこのメモ通りにして下さい。1.2 AWSアカウントの作成・初期設定
要点のみ記載します。
AWSアカウントの作成
- https://portal.aws.amazon.com/billing/signup
- メールアドレス・パスワードは超重要です。絶対に忘れないようにし,また他人に知られないように注意しましょう。不正利用されると高額の料金を請求される可能性があります。
- パスワードは,大文字・小文字・数字・記号を含む16文字以上の強固なものを設定しましょう。
- サポートプランは特に用事がなければ「ベーシックプラン」でOK
「セキュリティステータス」に全てチェックが入るように設定を進めましょう。
【お勧め参考記事】 https://qiita.com/tmknom/items/303db2d1d928db720888
- ルートアカウントの MFA を有効化
- セキュリティ向上のため2段階認証を導入
- 個々の IAM ユーザーの作成
- 最初に発行される「ルートアカウント」は,セキュリティの都合上,今後サインインに使用しないようにします
- 普段のサインインに使用する
IAM
ユーザーを作成- 「パスワードのリセットが必要」は不要なのでチェックを外しましょう
- 今後のサインインに必要となる「アカウントID」「ユーザー名」「パスワード」を忘れないようにしましょう
- グループを使用してアクセス許可を割り当て
- ほぼ全ての権限を持つ「AdministratorAccess」のポリシーを持つグループを作成し,作成した
IAM
ユーザーを追加- IAMパスワードポリシーの適用
最後に「請求アラーム」を作成し,課金状況を確認できるようにしておくことをお勧めします。
【お勧め参考記事】 https://www.kakiyoro.com/archives/2198
2. VPC
Amazon VPC
とはAmazon Virtual Private Cloud
の略称で,ユーザー専用のプライベートなネットワーク空間を構築できるサービスです。RailsアプリをAWSで動作させるために,Webサーバーを配置する
EC2
とデータベースシステムを動かすRDS
を使用しますが,これらを配置するには先にVPC
を設定する必要があります。
Amazon VPC
は追加料金なしで使用できます。(参考:https://docs.aws.amazon.com/ja_jp/vpc/latest/userguide/what-is-amazon-vpc.html)2.1 VPC の作成
2章では以下の部分を作成していきます。
【注意】 メニューバー右側の真ん中に「米国」などと表示されている場合は,「東京(アジアパシフィック(東京) ap-northeast-1)」に変更して下さい
- 画面左上の「サービス」を開き、検索欄に「VPC」と入力し、「VPC」を選択
【注意】 以下,左上の「New VPC Experience」をONにしていることを前提とします。
- 画面左のメニューバー(もしくは,ダッシュボード内の)の「VPC」をクリック
- 「VPCを作成」ボタンをクリック
キー 値 名前タグ アプリ名_vpc IPv4 CIDR ブロック 10.0.0.0/16 【注意】1章で注意しましたとおり,「アプリ名」の箇所はあらかじめ
メモ
しておいた「アプリ名」を使用して下さい
- 他はデフォルトのままで「VPCを作成」ボタンをクリック
2.2 サブネット の作成
VPCの中に,「インターネットから直接通信できる
EC2用
のサブネット」と「インターネットから直接通信できないRDS用
のサブネット」を2つずつ作成していきましょう。(許可する接続方法は後に設定します)
- 画面左のメニューバーから「サブネット」を選択
EC2 用のサブネット
HTTPS化
する際にALB
を使用するため,異なるアベイラビリティーゾーン
に属するサブネットを2つ
用意する必要があります。
- 「サブネットの作成」ボタンをクリック
キー 値 VPC アプリ名_vpc ※リストから選択
キー 値 名前タグ アプリ名_public_1a_subnet アベイラビリティーゾーン ap-northeast-1a ※リストから選択 IPv4 CIDR ブロック 10.0.0.0/24
- 「新しいサブネットを追加」ボタンをクリック
キー 値 名前タグ アプリ名_public_1c_subnet アベイラビリティーゾーン ap-northeast-1c ※リストから選択 IPv4 CIDR ブロック 10.0.1.0/24 ※ まだ作成しますので,「サブネットを作成」ボタンをクリックしないこと!
RDS 用のサブネット
RDS
を利用するには異なるアベイラビリティーゾーン
に属するサブネットを2つ
用意する必要があります。
- 「新しいサブネットを追加」ボタンをクリック
キー 値 名前タグ アプリ名_private_1a_subnet アベイラビリティーゾーン ap-northeast-1a IPv4 CIDR ブロック 10.0.10.0/24
- 「新しいサブネットを追加」ボタンをクリック
キー 値 名前タグ アプリ名_private_1c_subnet アベイラビリティーゾーン ap-northeast-1c IPv4 CIDR ブロック 10.0.11.0/24
「サブネットを作成」ボタンをクリック
下図の状態になっていることを確認しておきましょう
2.3 インターネットゲートウェイ の作成
VPC
内からインターネット
に接続するための「出入口」に相当するインターネットゲートウェイ
を作成しましょう。
- 画面左のメニューバーから「インターネットゲートウェイ」を選択
- 「インターネットゲートウェイの作成」ボタンをクリック
キー 値 名前タグ アプリ名_gateway
- 他はデフォルトのままで「インターネットゲートウェイの作成」ボタンをクリック
- フラッシュで表示されている「VPCへアタッチ」をクリック
- (「アクション」を選択し、「VPCにアタッチ」を選択してもOK)
キー 値 使用可能なVPC アプリ名_vpc
- 「インターネットゲートウェイのアタッチ」ボタンをクリック
2.4 ルートテーブル の作成
インターネットゲートウェイ
をアタッチしただけでは,サブネットからインターネットにアクセスすることはできません。
インターネットゲートウェイ
へ転送する経路であるルートテーブル
を設定する必要があります。
- 画面左のメニューバーから「ルートテーブル」を選択
- 「ルートテーブルの作成」ボタンをクリック
キー 値 名前タグ アプリ名_table VPC アプリ名_vpc
- 「作成」ボタンをクリック
「閉じる」ボタンをクリック
作成したルートテーブルを選択し,「アクション」ボタンをクリックし,「ルートの編集」を選択
- 「ルートの追加」ボタンをクリック
local
を消さないこと!
キー 値 送信先 0.0.0.0/0 ターゲット 「Internet Gateway」を選択し,先ほど作成した「アプリ名_gateway」を選択
- 「ルートの保存」をクリック
「閉じる」ボタンをクリック
(作成したルートテーブルを選択したまま)「アクション」ボタンをクリックし,「サブネットの関連付けの編集」を選択
「アプリ名_public_1a_subnet」「アプリ名_public_1c_subnet」のみを選択し,「保存」ボタンをクリック
2.5 セキュリティグループ の作成
インスタンスごとに許可する通信を設定するため,
セキュリティグループ
を作成しておきましょう。(
EC2
やRDS
に適用する作業は,後で行います)EC2 用のセキュリティグループ
【構成内容】 クライアント --(HTTP or SSH)-->
EC2
- 画面左のメニューバーの「セキュリティグループ」を選択
- 「セキュリティグループを作成」ボタンをクリック
キー 値 セキュリティグループ名 アプリ名_ec2_security_group 説明 アプリ名_ec2_security_group VPC アプリ名_vpc 「インバウンドルール」の「ルールを追加」を2回クリック
キー 値 タイプ HTTP ※「HTTPS」ではありません! プロトコル TCP ※自動選択 ポート範囲 80 ※自動選択 ソース 任意の場所 (0.0.0.0/0 と ::/0 が表示) 説明 ※空白でOK
キー 値 タイプ SSH プロトコル TCP ※自動選択 ポート範囲 22 ※自動選択 ソース マイIP (自分のグローバルIPが表示) 説明 ※空白でOK 【注意】ソースを
マイIP
とすることで,SSH接続できるIPアドレスを制限できます。ただし,自宅以外でEC2
にアクセスする可能性がある場合は,他のIPアドレスも登録が必要です。(意味が分からない場合は,SSH
のソースも任意の場所
に設定して下さい)RDS 用のセキュリティグループ
【構成内容】
EC2
--(TCP)-->RDS
データベースは
EC2
からのリクエストのみを受け付けるように設定しておきます。画面左のメニューバーの「セキュリティグループ」を選択し,「セキュリティグループを作成」ボタンをクリック
キー 値 セキュリティグループ名 アプリ名_db_security_group 説明 アプリ名_db_security_group VPC アプリ名_vpc 「インバウンドルール」の「ルールを追加」をクリック
【注意】アプリで使用するデータベースシステムを確認し,「いずれか一方」のルールを追加して下さい
MySQL
の場合
キー 値 タイプ MySQL/Aurora プロトコル TCP ※自動選択 ポート範囲 3306 ※自動選択 ソース カスタム : アプリ名_ec2_security_group 説明 ※空白でOK 「セキュリティグループを作成」をクリック
PostgreSQL
の場合
キー 値 タイプ PostgreSQL プロトコル TCP ※自動選択 ポート範囲 5432 ※自動選択 ソース カスタム : アプリ名_ec2_security_group 説明 ※空白でOK 「セキュリティグループを作成」をクリック
3. RDS
Amazon RDS
とはAmazon Relational Database Service
の略称で,MySQL
やPostgreSQL
のようなデータベース管理システム(DBMS
)を最適な動作条件で利用できるサービスです。
RDS
は運用負荷が低く非常に便利なのですが,コストが高い
ため注意が必要です。AWSアカウント作成後,1年間は一定の条件で無料となりますが,不要になった時点で削除することをお勧めします。
3.1. サブネットグループの作成
2.2
で作成したRDS
用のサブネット2つをグループ化しましょう。
画面左上の「サービス」を開き、検索欄に「RDS」と入力し、「RDS」を選択
画面左のメニューバーの「サブネットグループ」を選択し,右上の「DB サブネットグループを作成」ボタンをクリック
サブネットグループの詳細
キー 値 名前 アプリ名_subnet_group_db 説明 アプリ名_subnet_group_db VPC アプリ名_vpc
- サブネットの追加
- 異なる
アベイラビリティーゾーン
に属するサブネットを2つ以上選択する必要がありますマルチ AZ
構成時に必要となるため,今回のようにマルチ AZ
を使用しない場合にも必須となります
キー 値 アベイラビリティーゾーン ap-northeast-1a, ap-northeast-1c サブネット 10.0.10.0/24, 10.0.11.0/24 の2つを選択 「作成」ボタンをチェック
3.2 パラメータグループの作成(MySQL限定)
【注意】
PostgreSQL
の場合はスキップして下さい
RDS
のMySQL
のデフォルト文字コードはlatin1
であり,日本語に対応していません。文字コードを変更するためのパラメータグループを先に作成しておきましょう。
(1度作成すれば使い回しが可能です)
- 画面左のメニューバーの「パラメータグループ」を選択
「パラメータグループの作成」ボタンをクリック
- パラメータグループの詳細
キー 値 パラメータグループファミリー mysql5.7 グループ名 mysql57-supported-in-ja 説明 parameter group for mysql5.7 supported in ja
作成した「mysql57-supported-in-ja」をクリック
「パラメータの編集」ボタンをクリック
検索窓にキーをコピペして値を変更
キー 値 character_set_client utf8 character_set_connection utf8 character_set_database utf8mb4 character_set_results utf8 character_set_server utf8mb4 skip-character-set-client-handshake 1
- 「変更の保存」ボタンをクリック
3.3 DBインスタンスの作成
画面左のメニューバーの「データベース」を選択
「データベースを作成」ボタンをクリック
「MySQL」の場合と「PostgreSQL」の場合で設定が異なりますので,いずれか片方を実行して下さい。
3.3.1 MySQLの場合
- データベース作成方法を選択
「標準作成」を選択
- エンジンのオプション
キー 値 エンジンのタイプ MySQL バージョン MySQL 5.7.* (*の箇所は最新のものを推奨)
- テンプレート
「無料利用枠」を選択
- 設定
【注意】ここの「アプリ名」の
_
は ハイフン-
とすること
【注意】マスターユーザー名・パスワードをメモしておくこと
キー 値 DB インスタンス識別子 アプリ名-db マスターユーザー名 root マスターパスワード 任意
- DB インスタンスサイズ
db.t2.micro(デフォルト)
- ストレージ
※デフォルト設定で
- 可用性と耐久性
※デフォルト設定で
- 接続
「アプリ名_vpc」を選択
- 「追加の接続設定」のドロップダウンをクリック
キー 値 サブネットグループ アプリ名_subnet_group_db ※2.1で作成 セキュリティグループ アプリ名_db_security_group ※1.5で作成, default は外す アベイラビリティーゾーン ap-northeast-1a
- データベース認証
※デフォルト設定で
「追加設定」をクリック
データベースの選択肢
キー 値 最初のデータベース名 アプリ名_production DB パラメータグループ mysql57-supported-in-ja オプショングループ ※デフォルト設定
- バッグアップ以降
※デフォルト設定で
- 「データベースの作成」ボタンをクリック
3.3.2 PostgreSQLの場合
まず,ターミナルでローカルで使用している
PostgreSQL
のバージョンを確認しておきましょう。psql -V
- データベース作成方法を選択
「標準作成」を選択
- エンジンのオプション
PostgreSQL
のバージョンは,上記で確認したローカルのバージョンに合わせた方が無難です。メジャーバージョンを合わせれば十分なので,例えばローカルが
12.3
ならば,12.* (*の箇所は最新のもの) をお勧めします。2020年11月時点ではバージョンが
13
に対応していないので,ローカルのバージョン13
の場合は最新のバージョンでよいでしょう。
キー 値 エンジンのタイプ PostgreSQL バージョン ※上記を参考に設定
- テンプレート
「無料利用枠」を選択
- 設定
【注意】ここの「アプリ名」の
_
は ハイフン-
とすること
【注意】マスターユーザー名・パスワードをメモしておくこと
キー 値 DB インスタンス識別子 アプリ名-db マスターユーザー名 postgres マスターパスワード 任意
- DB インスタンスサイズ
db.t2.micro(デフォルト)
- ストレージ
※デフォルト設定で
- 可用性と耐久性
※デフォルト設定で
- 接続
「アプリ名_vpc」を選択
- 「追加の接続設定」のドロップダウンをクリック
キー 値 サブネットグループ アプリ名_subnet_group_db ※2.1で作成 セキュリティグループ アプリ名_db_security_group ※1.5で作成, default は外す アベイラビリティーゾーン ap-northeast-1a
- データベース認証
※デフォルト設定で
「追加設定」をクリック
データベースの選択肢
キー 値 最初のデータベース名 アプリ名_production DB パラメータグループ ※デフォルト設定 オプショングループ ※デフォルト設定
- バッグアップ以降
※デフォルト設定で
- 「データベースの作成」ボタンをクリック
3.4 エンドポイントの確認
アプリ名を選択
「接続とセキュリティ」の「エンドポイント」をメモ
- データベースが作成されるまで待つ必要がありますので,別タブで次の
EC2
の設定に進めるとよいでしょう4. EC2
Amazon EC2
とはAmazon Elastic Compute Cloud
の略称で,コンピューティング性能をクラウド内で提供するサービスです。サーバーに必要なものをクラウド内で借りることができます。Railsのアプリをこの
EC2
にデプロイし,ブラウザからアクセスできるように準備を行います。EC2 も運用に料金がかかりますので,不要になったインスタンスなどは削除するようにしましょう。
4.1 インスタンスの作成
画面左上の「サービス」を開き、検索欄に「EC2」と入力し、「EC2」を選択
画面左のメニューバーの「インスタンス」を選択し,「インスタンスを起動」ボタンをクリック
ステップ 1: Amazon マシンイメージ (AMI)
「無料利用枠の対象」タグの付いた「Amazon Linux 2 AMI (HVM), SSD Volume Type」「64ビット (x86)」の「選択」ボタンをクリック
ステップ 2: インスタンスタイプの選択
- 「無料利用枠の対象」タグの付いた「t2.micro」が選択されていることを確認した上で,「次のステップ」ボタンをクリック
- 「確認と作成」ボタンをクリックしないこと。クリックした場合は,「戻る」ボタンをクリックしてステップ3まで移動しましょう
ステップ 3: インスタンスの詳細の設定
キー 値 ネットワーク アプリ名_vpc サブネット アプリ名_public_1a_subnet 他はデフォルト設定のまま「次のステップ」ボタンをクリック
ステップ 4: ストレージの追加
「次のステップ」ボタンをクリック
ステップ 5: タグの追加
「タグの追加」ボタンをクリック
キー 値 Name 「アプリ名_instance」を選択 「次のステップ」ボタンをクリック
ステップ 6: セキュリティグループの設定
「既存のセキュリティグループを選択する」にチェック
「アプリ名_ec2_security_group」にチェック
「確認と作成」ボタンをクリック
ステップ 7: インスタンス作成の確認
- セキュリティグループの「名前」が「アプリ名_ec2_security_group」になっていることを確認した上で,「起動」ボタンをクリック
既存のキーペアを選択するか、新しいキーペアを作成します。
「新しいキーペアの作成」を選択
「キーペア名」は「アプリ名」を入力
メモ
しているアプリ名と全く同じにして下さい(ハイフン-
を使用せず,アンダースコア_
を使用)「キーペアのダウンロード」を選択
アプリ名.pem
をダウンロードできます。後にEC2
のログインで利用します「インスタンスの作成」ボタンをクリック
作成ステータス
「インスタンスの表示」ボタンをクリック
4.2 Elastic IPの作成、紐付け
インターネットに接続するには
グローバルIPアドレス
が必須です。現状ではこの
グローバルIPアドレス
は固定化されておらずEC2インスタンス
を再起動した際に変更されてしまいます。(URLが変化してしまう!)
Elastic IP
設定することで,グローバルIPアドレス
を固定化することができます。
Elastic IP
はこれから行うEC2インスタンス
との関連付けを行っている状態では無料ですが,関連付けたEC2インスタンス
を削除したり停止させると料金が発生するようになります。
EC2インスタンス
を削除する際はElastic IP
の開放を忘れないように注意しましょう。Elastic IPの作成
画面左のメニューバーの「Elastic IP」を選択
「Elastic IP アドレスの割り当て」ボタンをクリック
「割り当て」ボタンをクリック
Elastic IPの紐付け
- 先ほど割り当てた
Elastic IP
を選択した状態で、「アクション」ドロップダウンを選択し、「Elastic IP アドレスの関連付け」をクリックここで,表示されている
Elastic IP
は必ずメモしておいて下さい。
キー 値 インスタンス アプリ名_instance プライベート IP アドレス ※クリックして表示されるIPを選択 再関連付け チェックを入れる
- 「関連付ける」ボタンをクリック
4.3 EC2へのログイン
アプリ名を定義(ローカル環境)
作業ミスを減らすため,ターミナルで頻出する
アプリ名
を一時的にグローバル変数として定義しておきましょう。
アプリ名
の箇所は,各自がメモしているものに置き換えて実行して下さい。ターミナルAPP_NAME=アプリ名 echo $APP_NAME(例)APP_NAME=aws_sample_app echo $APP_NAME最後のコマンドで,「アプリ名」が正しく表示されていることを確認した上で,以下を実行して下さい。
【補足】間違った場合は再度上記を実行し直してから進めて下さい。また,コマンドは原則コピペして下さい。1文字間違っただけで大きく時間をロスする可能性があります。
ターミナル# zsh の場合 echo "export APP_NAME=$APP_NAME" >> ~/.zshrc source ~/.zshrc # bash の場合 echo "export APP_NAME=$APP_NAME" >> ~/.bash_profile source ~/.bash_profile【備考】 使用しているシェルスクリプトが
zsh
かbash
か分からない場合はecho $SHELL
を実行して確認して下さいキーペアの移動・アクセス権の付与
【参考】 https://docs.aws.amazon.com/ja_jp/AWSEC2/latest/UserGuide/ec2-key-pairs.html
4.1 でダウンロードしたキーペア
アプリ名.pem
は.ssh
ディレクトリに移動し,利用できる状態にしておきましょう。ターミナルcd mkdir .ssh mv Downloads/$APP_NAME.pem .ssh chmod 400 .ssh/$APP_NAME.pem ls -l .ssh/$APP_NAME.pem最後のコマンドで
-r-------- (略) .ssh/アプリ名.pem
が表示されていればOKです。【補足】
mv
コマンド実行時にNo such file or directory
が表示された場合は,Google Chrome の下に現れているアプリ名.pem
のドロップダウンメニューから,キーペアの場所を確認して,直接,ホームディレクトリの.ssh
ディレクトリに移動させて下さい。キーペアのファイル名がアプリ名.pem
になっているかどうかも確認しましょう。EC2 インスタンスの状態を確認
EC2
の画面左のメニューバーの「インスタンス」をクリックし,作成した EC2インスタンスの「インスタンスの状態」が実行中
となっているか確認して下さい
実行中
になっていない場合はしばらく待ってからブラウザをリロードして下さい【補足】4.2で
Elastic IP
をメモし忘れた人は,作成した EC2インスタンス を選択し,Elastic IP
をメモして下さいssh接続の設定ファイルを作成
EC2インタスタンス
にログインするには,「ホスト名」「ユーザー名」「AWSからダウンロードしたキーペア(秘密鍵)」が必要になります。これらをログインの度に毎回記述するのは面倒なので,設定ファイルに記載し,使える状態にしましょう。
ローカル環境のターミナルvi ~/.ssh/config
Vim
エディタでファイルが開かれますので,以下を記述して下さい。(デフォルトでec2-user
という名前のユーザーが用意されています)ローカル環境のターミナル(~/.ssh/config)Host アプリ名 Hostname ElasticIPを記入 User ec2-user IdentityFile ~/.ssh/アプリ名.pem【参考】 「アプリ名」が
aws_sample_app
, 「Elastic IP」が172.217.161.46
の場合は,次の形式となります。(例)Host aws_sample_app Hostname 172.217.161.46 User ec2-user IdentityFile ~/.ssh/aws_sample_app.pem【補足】 Vimの基本
一般のテキストエディタは,ファイルを開いてすぐに文字が入力できます。
Vim
はインサートモード
に変更しなければキー入力ができません。ここは初学者が非常に混乱しやすいところですので,くれぐれもご注意下さい。
以下は最低限覚えておきましょう。
Vim
の起動時は「ノーマルモード」- 文字をキー入力したいときは
i
を入力し,「インサートモード」に変更する必要がある
- 「かな」入力モードでは
i
を入力しても効果が出ないので,「英数」入力モードに切り替えてから行うこと- 「ノーマルモード」への移行は,
esc
- 保存終了は「ノーマルモード」にしてから
:wq
- (保存せずに)強制終了は「ノーマルモード」にしてから
:q!
EC2にログイン
それでは,
EC2インタスタンス
にログインしてみましょう。ターミナルssh アプリ名
Are you sure you want to continue connecting (yes/no/[fingerprint])
と表示されたら,yes
と入力してEnterキーを押しましょう。これで,
EC2インタスタンス
にログインできます。
【備考】ここでSSH接続できない場合は,以下の可能性があります。
先ほど作成した
~/.ssh/config
にミスがある4.3で,キーペアが指定箇所に移動できていない or パーミッションを適切に変更できていない(
ls -l ~/.ssh/$APP_NAME.pem
で確認)
Elastic IP
をメモし間違えている2.5で作成した「EC2 用のセキュリティグループ(アプリ名_ec2_security_group)」の設定を間違えている
- SSHのソースが
マイIP
の場合は,IPアドレスが変わっていないかも確認しましょう(不明な場合は任意の場所
に変更)4.1で設定したEC2 用のセキュリティグループが「アプリ名_ec2_security_group」になっていない
2.4で作成したルートテーブルの「サブネットの関連付け」を間違えている
4.4 EC2の初期設定
(参考)Amazon Linux インスタンスでユーザーアカウントを管理する
要注意
今後,EC2にログインした状態の
サーバー環境のターミナル
と,通常のローカル環境のターミナル
のどちらで操作するかを「必ず」確認して下さい。1度でも間違えると,エラー解決に大きく時間を取られる可能性があります。なお,一定時間が経過しますと,EC2からログアウトしますので,その点にも注意しましょう。
新規ユーザーアカウントの作成
今後
EC2
での作業やCapistrano
で利用するユーザーを作成しましょう。作業を楽にするため,しばらくパスワード無しで sudo コマンドを使える状態にしておきます。EC2にログインした状態の
サーバー環境のターミナル
で以下を実行しましょう。「ユーザー名」の箇所は自由に決め,
メモ
しておいて下さい。サーバー環境のターミナルAPP_USER=ユーザー名 echo $APP_USER最後のコマンドで,「ユーザー名」が正しく表示されていることを確認した上で,以下を実行して下さい。
サーバー環境のターミナルsudo adduser $APP_USER echo "$APP_USER ALL=(ALL) NOPASSWD: ALL" | sudo EDITOR='tee -a' visudo > /dev/null sudo su - $APP_USER sudo ls最初の表示が
ec2-user
から「自分の決めたユーザー名」に変更され,最後のコマンドでパスワードを求められなければOKです。【補足】2番目の操作は
sudo visudo
実行後,一番最後の行にユーザー名 ALL=(ALL) NOPASSWD: ALL
を追加する操作ですアプリ名を定義(サーバー環境)
作業ミスを減らすため,サーバー環境でも「アプリ名」をグローバル変数として定義しておきましょう。
サーバー環境のターミナルAPP_NAME=アプリ名 echo $APP_NAME最後のコマンドで,「アプリ名」が正しく表示されていることを確認した上で,以下を実行して下さい。
(間違っている場合は再度上記を実行し直してから進めて下さい)
サーバー環境のターミナルecho "export APP_NAME=$APP_NAME" >> ~/.bash_profile source ~/.bash_profile新規ユーザーでssh接続するための設定
新規ユーザーでssh接続できるようにするには,
アプリ名.pem
(秘密鍵)に対応する公開鍵
をEC2
の~/.ssh/authorized_keys
に配置し,適切な権限を与えておく必要があります。サーバー環境のターミナルmkdir .ssh -m 700 vi .ssh/authorized_keysサーバー側でVimエディタが開かれます。
ここで,新しく
ローカル
環境のターミナルを用意して下さい。(command + n
もしくはcommand + t
)そして,
ローカル
環境のターミナルで秘密鍵(アプリ名.pem)
から公開鍵
をコピーして下さい。ローカル環境のターミナルssh-keygen -y -f ~/.ssh/$APP_NAME.pem | pbcopy(コマンドを実行するだけでコピーされますので,
command + c
は不要です。もしpbcopy: command not found
が表示される場合は| pbcopy
を削って実行し,直接コピーして下さい)その後,サーバー環境のターミナルに戻って以下の操作を行ってください。
サーバー環境のターミナル# 公開鍵を貼り付け,保存終了 chmod 600 .ssh/authorized_keys exit exitこれで,新しく作成したユーザーでもログインができるようになりました。
ログイン時のユーザー名を変更しましょう。
ローカル環境のターミナルvi ~/.ssh/config
- 「ユーザー名」を
ec2-user
からメモしたユーザー名
に変更しましょう。ローカル環境のターミナル(~/.ssh/config)Host アプリ名 Hostname ElasticIP User ユーザー名 ★ここを変更★ IdentityFile ~/.ssh/アプリ名.pem
yml:(ユーザー名が take の場合)
Host aws_sample_app
Hostname 172.217.161.46
User take
IdentityFile ~/.ssh/aws_sample_app.pem
4.5 今後のEC2のログイン方法
再度,以下のコマンドで
EC2インスタンス
にログインしてみましょう。ローカル環境のターミナルssh アプリ名
ec2-user
ではなく各自が決めたユーザー名でログインできるはずです。デフォルトユーザーは必要なくなりましたので,削除しておきましょう。
サーバー環境のターミナルsudo userdel -r ec2-user5. サーバー構築
Railsアプリを実行できるようにするための環境構築を行っていきます。
EC2インスタンス
にログインしていない場合は,次でログインして下さい。ローカル環境のターミナルssh アプリ名5.1 Nginx の設定
以下の順序で実行していきます。
- サーバーをアップデート
Nginx
のインストールNginx
の起動とインスタンス起動時自動起動の設定サーバー環境のターミナルsudo yum -y update sudo amazon-linux-extras install -y nginx1 sudo systemctl start nginx sudo systemctl enable nginxブラウザに
Elastic IP
を入力してアクセスしましょう。
Welcome to nginx on Amazon Linux!
が表示されればOKです。【補足】ここでアクセスできない場合は,以下の可能性があります
- 2.5で作成した「EC2 用のセキュリティグループ(アプリ名_ec2_security_group)」の設定を間違えている
- 「タイプが HTTP, ソースが
0.0.0.0/0
と::/0
」のものが含まれているかを確認。「HTTP」を「HTTPS」にしているミスを見かけます- 4.1で設定したEC2 用のセキュリティグループが「アプリ名_ec2_security_group」になっていない
5.2 必要なプラグインのインストール
- 各種プラグインのインストール
- 1行のコマンドです
サーバー環境のターミナルsudo yum -y install git make gcc-c++ patch openssl-devel libyaml-devel libffi-devel libicu-devel libxml2 libxslt libxml2-devel libxslt-devel zlib-devel readline-devel ImageMagick ImageMagick-devel【注意】上記はあくまで「画像投稿可能なアプリ」のデプロイを想定したものです。アプリに導入されている gem や ライブラリ次第では,依存関係にある他のプラグインもインストールしておく必要があります。
5.3 データベースにログイン
まず,
EC2
にプリインストールされているMariaDB
を削除しておきましょう。サーバー環境のターミナルsudo yum -y remove mariadb-libsMySQLの場合
以下の順序で実行していきます。
MySQL
のリポジトリを追加MySQL
の5.7がインストールされるように変更MySQL
をインストールサーバー環境のターミナルsudo yum localinstall -y https://dev.mysql.com/get/mysql80-community-release-el7-3.noarch.rpm sudo yum-config-manager --disable mysql80-community sudo yum-config-manager --enable mysql57-community sudo yum -y install mysql-community-client mysql-server mysql-devel次のコマンドでRDSの
MySQL
にログインできます。サーバー環境のターミナルmysql -h エンドポイント -u root -p # RDS の パスワード を入力
mysql>
という表示が出た後に次を実行して下さい。サーバー環境のターミナル(mysql)show databases; # 表示されたデータベース一覧に,「アプリ名_production」が存在していればOK exit【参考】「エンドポイント」は
2.4
で確認したものです。確認できていない場合はRDS
の「データベース」をクリックし,アプリを選択して出てくる「エンドポイント」を確認しましょう。
【補足】もし,データベース一覧に,「アプリ名_production」が存在しない場合は,
exit;
で終了する前に以下を実行してデータベースを作成して下さい。サーバー環境のターミナル(mysql)# 「アプリ名_production」が存在しない場合のみ,次を実行して下さい CREATE DATABASE アプリ名_production;
【参考】 Sequel Proで MySQL に接続する方法
Sequel Pro
(nightly
バージョン) をインストールしていない場合は,次を実行してインストールしましょう。ローカル環境のターミナルbrew cask install homebrew/cask-versions/sequel-pro-nightly
これで,アプリケーションディレクトリに
Sequel Pro.app
が入ります。
- SSHのタブを選択
キー 値 MySQL Host RDSのエンドポイントを記載 Username root Password RDSのパスワードを記載 Database アプリ名_production Port 3306 SSH Host Elastic IPを記載 SSH User EC2のユーザー名を記載 SSH Password 右側の鍵マークボタンをクリックし「~/.ssh/アプリ名.pem」を選択 【参考】
.ssh
は隠しファイルです。隠しファイルを表示するショートカットキーはcommand + shift + .
です。PostgreSQLの場合
単純にインストールするとバージョンが低すぎるので,
amazon-linux-extras
リポジトリからPostgreSQL
のバージョン11を入れることにしましょう。サーバー環境のターミナルsudo amazon-linux-extras install -y postgresql11 yum list | grep postgresql sudo yum -y install postgresql-devel
【補足】PostgreSQLのバージョン12以上を強引に入れることも可能ですが,
postgresql-devel
のインストールが難しいのでお勧めしません。なお,インストール可能な最新バージョンは,amazon-linux-extras | grep postgresql
で確認できます。
次のコマンドでRDSの
PostgreSQL
にログインできます。サーバー環境のターミナルpsql -h エンドポイント -U postgres # RDS の パスワード を入力
postgres=>
という表示が出た後に次を実行して下さい。サーバー環境のターミナル(PostgreSQL)\l # 表示されたデータベース一覧に,「アプリ名_production」が存在していればOK exit;【補足】もし,データベース一覧に,「アプリ名_production」が存在しない場合は,
exit;
で終了する前に以下を実行してデータベースを作成して下さい。サーバー環境のターミナル(PostgreSQL)# 「アプリ名_production」が存在しない場合のみ,次を実行 CREATE DATABASE アプリ名_production;【参考】 Postico で PostgreSQL に接続する方法
インストールしていない場合は,上記サイトの
Download
ボタンをクリックし,zipファイルを解凍して出てくるPostico
をアプリケーションに移動した上で,実行して下さい。
Postico
を起動し,左下の「New Favorite」をクリック
Options
のドロップダウンを開き,Connect via SSH
をクリック
キー 値 Nickname ※任意 (アプリ名_production など) Host RDS のエンドポイントを記載 Port ※不要 User postgres Password RDSのパスワードを記載 Database アプリ名_production SSH Host Elastic IPを記載 User EC2のユーザー名を記載 Password ※不要 Private Key 「Choose」をクリックし,「~/.ssh/アプリ名.pem」を選択 「Connect」を選択し,再度「Connect」を選択
5.4 Node, Yarn のインストール
Node
のインストールサーバー環境のターミナルcurl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.34.0/install.sh | bash . ~/.nvm/nvm.sh nvm install node node -e "console.log('Running Node.js ' + process.version)"最後のコマンドで
Running Node.js バージョン
が表示されればOKです。
Yarn
のインストールサーバー環境のターミナルcurl -o- -L https://yarnpkg.com/install.sh | bash5.5 Rubyのインストール
rbenv
のインストールサーバー環境のターミナルgit clone https://github.com/sstephenson/rbenv.git ~/.rbenv echo 'export PATH="$HOME/.rbenv/bin:$PATH"' >> ~/.bash_profile echo 'eval "$(rbenv init -)"' >> ~/.bash_profile source ~/.bash_profile
ruby-build
のインストールサーバー環境のターミナルgit clone https://github.com/sstephenson/ruby-build.git ~/.rbenv/plugins/ruby-build
Ruby
のインストールまず,デプロイするアプリの
Ruby
のバージョンを確認して下さい。(
ローカル環境のターミナル
でアプリのディレクトリまで移動しruby -v
で確認できます)以下は,バージョンが
2.6.6
の場合の例です。バージョンはアプリに「必ず」合わせて下さい。サーバー環境のターミナルrbenv install 2.6.6 rbenv global 2.6.6 rbenv rehash
Ruby
のインストールには時間がかかります。
Bundler
のインストールサーバー環境のターミナルgem install bundler
完了後に以下を実行し,全てバージョンが表示されればOKです。
サーバー環境のターミナルrbenv -v ruby -v yarn -v bundler -v5.6 デプロイ先ディレクトリの設定
(デフォルト設定の場合)
Capistrano
によるアプリのデプロイ先は/var/www/アプリ名
ディレクトリになります。そこで,このディレクトリをあらかじめ作成しておき,必要な権限を与えておきましょう。
サーバー環境のターミナルsudo mkdir -p /var/www/$APP_NAME sudo chown `whoami`:`whoami` /var/www/$APP_NAME ls -l /var/www最後のコマンドで
drwxr-xr-x 2 ユーザー名 ユーザー名 日付 アプリ名
が表示されればOKです。5.7 Git の初期設定
次に,サーバー環境で
GitHub
の操作ができるようにしていきましょう。まずは,サーバー環境の
Git
の初期設定を行いましょう。ここでは,ローカル環境と同じ「ユーザー名」「メールアドレス」を登録することとしておきます。まず, Git に登録した名前とメールアドレスを確認しましょう。
ローカル環境のターミナルcat ~/.gitconfig
次の箇所をコピーして下さい。
出力内容の一部[user] name = ~~~~~ email = ~~~~~@~~~.~~~
.gitconfig
ファイルの生成サーバー環境のターミナルcd vi .gitconfig
- Vimが開いたら先ほどコピーしたものをペーストしましょう。
5.8 GitHub連携
サーバー環境に GitHub へのアクセス権限を持たせるため,必要な公開鍵・秘密鍵を生成しましょう。
サーバー環境のターミナルcd .ssh ssh-keygen -t rsa -f "${APP_NAME}_git_rsa" -N ""
これで,以下のファイルが作成されます
- 公開鍵(GitHubに配置する鍵)
アプリ名_git_rsa.pub
- 秘密鍵(EC2に残しておく鍵)
アプリ名_git_rsa
config
ファイルの生成サーバー環境のターミナルvi config
- Vimでファイルが開かれたら次を追加
- 「アプリ名」の箇所は各自の設定に合わせること
~/.ssh/configHost github github.com Hostname github.com User git IdentityFile ~/.ssh/アプリ名_git_rsa
- GitHubに公開鍵を登録
以下を実行し,値をコピーしておきましょう。
サーバー環境のターミナル(~/.ssh)cat "${APP_NAME}_git_rsa.pub"
- ブラウザでGitHubにアクセス
- 右上のサムネイル画像をクリック
- 「Settings」をクリック
- 左メニューバーから「SSH and GPG keys」をクリック
- 「SSH Keys」の「New SSH key」をクリック
キー 値 Title アプリ名_git_rsa.pub Key サーバー環境のターミナルからコピーした値をペースト 「Add SSH key」ボタンをクリック
- サーバーから GitHub に接続できるか確認
サーバー環境のターミナル(~/.ssh)chmod 600 config ssh github
yes
を入力し,次の赤枠の内容が出力されればOKです。6. デプロイ(Capistrano)
Capistrano
を使い,1コマンドで Rails アプリをAWS EC2
にデプロイできる状態にしていきましょう。サンプルのアプリをデプロイされたい場合は
6.1
から進めて下さい。オリジナルのアプリをデプロイされる場合は6.2
から進めて下さい。なお,オリジナルアプリのデプロイについては,以下の条件を改めて確認しておいて下さい。
- Rails
6
であること- アプリで使用するデータベースシステムの指定が
RDS
と一致していること
- 他のデータベースを指定している場合は
config/database.yml
を修正して下さい。rails db:system:change --to=mysql
もしくはrails db:system:change --to=postgresql
コマンドが便利です- アプリで使用する gem やライブラリ次第では
EC2
に他にもあらかじめインストールしておく必要がある可能性があります6.1 Railsのサンプルアプリを作成
【注】 「サンプルのアプリ」で AWS のデプロイに挑戦されたい方以外はスキップして下さい。
CarrierWave
を用いた画像投稿機能を持つアプリを簡単に実装しましょう。アプリの作成(MySQLの場合)
ターミナルrails new aws_sample_app -d mysql -C -M -T --skip-active-storageアプリの作成(PostgreSQLの場合)
ターミナルrails new aws_sample_app -d postgresql -C -M -T --skip-active-storage※ 以下は MySQL, PostgreSQL 共通です
ターミナルcd aws_sample_app git add . git commit -m "init" bundle remove jbuilder bundle add carrierwave rails g scaffold Post title:string image:string --skip-assets --skip-helper rails db:migrate:reset rails g uploader Image echo "/public/uploads/" >> .gitignore
- トップページを設定
config/routes.rbRails.application.routes.draw do # ********** 以下を追加 ********** root to: 'posts#index' # ********** 以上を追加 ********** resources :posts end
- 画像投稿機能を付けるための準備
app/models/post.rbclass Post < ApplicationRecord # ********** 以下を追加 ********** mount_uploader :image, ImageUploader # ********** 以上を追加 ********** end
- 投稿する画像の選択ボタンを作成
app/views/posts/_form.html.erb<!-- 略 --> <div class="field"> <%= form.label :image %> <!-- ********** 「<%= form.text_field :image %>」を変更 ********** --> <%= form.file_field :image, accept: "image/png,image/jpeg,image/gif" %> <!-- ********** 以上を変更 ********** --> </div> <!-- 略 -->
- 投稿詳細ページで,投稿した画像が表示されるように設定
app/views/posts/show.html.erb<p id="notice"><%= notice %></p> <p> <strong>Title:</strong> <%= @post.title %> </p> <!-- ********** 以下を編集 ********** --> <% if @post.image? %> <p> <%= image_tag @post.image.url %> </p> <% end %> <!-- ********** 以上を編集 ********** --> <%= link_to 'Edit', edit_post_path(@post) %> | <%= link_to 'Back', posts_path %>動作確認を行った上で,GitHubにリポジトリを作成し,add, commit を行い, GitHub に push しましょう。
さらに,画像を
AWS S3
に保存できるようにすべきですが,ひとまず画像投稿は可能ですのでデプロイ完了後の10章・11章で設定を行うこととしましょう。6.2. データベースの設定
※以下は自作アプリの場合の場合も実行して下さい。必要があれば作業前にブランチを切るようにしましょう。
ファイル名 ファイルのイメージ config/master.key 鍵 config/credentials.yml.enc 錠付きファイル まず,本番環境用の
config/database.yml
を修正しておきましょう。
RDS
のパスワードとエンドポイントはGitHub
から見られないようにするため,credentials.yml.enc
に記載し,これを読み込むように設定することとします。(
dotenv-rails
を導入し.env
にパスワードなどを記載する方法もあります)MySQLの場合
config/database.ymlproduction: <<: *default # ***** 以下を修正 ***** database: アプリ名_production password: <%= Rails.application.credentials.db[:password] %> host: <%= Rails.application.credentials.db[:hostname] %>PostgreSQLの場合
config/database.ymlproduction: <<: *default # ***** 以下を修正 ***** database: アプリ名_production username: postgres password: <%= Rails.application.credentials.db[:password] %> host: <%= Rails.application.credentials.db[:hostname] %>※ 以下は MySQL, PostgreSQL 共通です
database.yml
で読み込むパスワードとエンドポイントをcredentials.yml.enc
に記載しましょう
yaml
形式ですので,インデント幅にはくれぐれも注意して下さい- 例えば,
password:
の後に「半角スペース1個」がないだけでエラーになりますローカル環境のターミナルEDITOR=vi rails credentials:editconfig/credentials.yml.encdb: password: RDSのパスワード hostname: RDSのエンドポイントさらに,本番環境で
master.key
が存在しない場合はエラーが出るように設定しておきます。config/environments/production.rb# 次のコメントアウトを解除 config.require_master_key = true念のため以下を実行し,パスワードとエンドポイントが取得できることを確認しておいた方がよいでしょう。
ローカル環境のターミナルrails c # コンソール起動後 Rails.application.credentials.db[:password] Rails.application.credentials.db[:hostname] # RDSのパスワード, エンドポイントが表示されることを確認後 exit確認ができれば,add, commit を行い, GitHub に push しましょう。
master(main) ブランチ以外で作業をされている場合は,プルリクを出し,GitHubの master(main) ブランチにマージするところまでは行ってください。
6.3. Capistrano
1コマンドで Rails アプリをデプロイできるよう
Capistrano
を導入しましょう。Gemfilegroup :development do # 略 # ***** 以下を追加 ***** gem "capistrano", "~> 3.10", require: false gem "capistrano-rails", "~> 1.6", require: false gem 'capistrano-rbenv', '~> 2.2' gem 'capistrano-rbenv-vars', '~> 0.1' gem 'capistrano3-puma' # ***** 以上を追加 ***** endローカル環境のターミナルbundle install bundle exec cap install STAGES=production
Capfile
の# require "capistrano/passenger"
の下に以下を追加Capfilerequire 'capistrano/rbenv' require 'capistrano/bundler' require 'capistrano/rails/assets' require 'capistrano/rails/migrations' require 'capistrano/puma' install_plugin Capistrano::Puma install_plugin Capistrano::Puma::Nginx
- デプロイの設定ファイルを修正・追記しましょう
- 「アプリ名」「GitHubリポジトリURL」は各自のものに置き換えて下さい
- 「GitHubリポジトリURL」は
HTTPS
でなくSSH
のURLをコピペして下さいconfig/deploy.rb# config valid for current version and patch releases of Capistrano lock "~> 3.14.1" # ***** 以下を修正 ***** set :application, "アプリ名" set :repo_url, "GitHubのリポジトリURL" set :rbenv_ruby, File.read('.ruby-version').strip # Nginxの設定ファイル名と置き場所を修正 set :nginx_config_name, "#{fetch(:application)}.conf" set :nginx_sites_enabled_path, "/etc/nginx/conf.d" append :linked_files, "config/master.key" append :linked_dirs, "log", "tmp/pids", "tmp/cache", "tmp/sockets", "node_modules" # ***** 以上を追加 *****
production.rb
の一番上に,EC2サーバーにログインするユーザー名、サーバーのロールを記述
- 「ElatsticIP」「アプリ名」「ユーザー名」は各自のものに置き換えること
config/deploy/production.rbserver "ElatsticIP", user: "ユーザー名", roles: %w{app db web} set :ssh_options, { keys: %w(~/.ssh/アプリ名.pem), forward_agent: true, auth_methods: %w(publickey), }master.key の配置と Rails アプリのデプロイ
準備が整いましたので,Railsアプリのデプロイを行いましょう。
初回の実行では
master.key
がないためデプロイに失敗しますが,master.key
を配置するために必要なディレクトリが生成されます。デプロイ失敗後に
scp
コマンドでmaster.key
をサーバー側に追加し,再度実行すればデプロイに成功するでしょう。ローカル環境のターミナル# Railsアプリのルートディレクトリに移動してから bundle exec cap production deploy # 「ERROR linked file /var/www/アプリ名/shared/config/master.key does not exist on ElasticIP」が出ればOK scp config/master.key $APP_NAME:/var/www/$APP_NAME/shared/config bundle exec cap production deploy最後から2行目に
Command restart sent success
が表示されていればOKです。【備考】ここでデプロイに失敗した場合は,まずエラー文を確認しましょう。いろいろなケースがありますが,アプリで使用されている gem 次第では,先に依存関係にあるプラグインを EC2 にインストールしておく必要があります。
Nginx の設定
Nginx
用の設定ファイルを追加するため,先に必要なディレクトリをサーバー側で作成しておきましょう。サーバー環境のターミナルcd /etc/nginx sudo mkdir sites-available
ローカル環境
のターミナルで,Railsアプリのルートディレクトリまで移動した後,以下を実行しましょう。
これでNginx
用の設定が生成されます。ローカル環境のターミナル# Railsアプリのルートディレクトリに移動してから bundle exec cap production puma:nginx_configこれで,サーバー側の
/etc/nginx/conf.d
に設定ファイルアプリ名.conf
が入ります。
Nginx
を再起動しましょう。サーバー環境のターミナル(/etc/nginx)sudo service nginx restart
ブラウザのアドレスバーに
Elastic IP
を入力してアクセスし,スーパーリロード
して下さい。(ショートカットキーはcommand + shift + r
)アプリが表示されればOKです!
【補足】アプリが表示されない場合は,以下を試して下さい
- ローカル環境のターミナルから
curl -I ElasticIP
を実行したとき,最初にHTTP/1.1 301 Moved Permanently
が出力される場合
config/environments/production.rb
のconfig.force_ssl = true
をコメントアウトして下さい9.4
にログの確認方法を記載していますので,確かめてみましょう!!
これでひとまずデプロイは完了です!……が,他にもすべきことがありますので, 【後半】 に進みましょう。
「無事デプロイに成功した!!」という方は是非 LGTM もお願いいたします!
- 投稿日:2020-11-26T15:06:03+09:00
ECRリポジトリから最新のタグを取得する
目的
- ECRリポジトリに保存されたDockerイメージの最新のタグを取得する
使うもの
- AWS CLI
手法
--query
を利用してAWS CLIの結果をフィルタ、抽出できます。aws ecr describe-images --repository-name 【リポジトリ名】 \ --query "reverse(sort_by(imageDetails[*], &imagePushedAt))[0].imageTags[0]" \ | sed -e 's/"//g'
--query
は JMESPath の文法が使えます。上記の例では、リポジトリのイメージ一覧を取得して、imagePushedAt(日付)で降順ソートを行い、1つ目の imageTagsを取得します。
配列になっているので、そのままでは以下のように扱いづらいため、imagePushedAt[0] で値だけ取り出します。
# imageTags で取得 [ "005d6f6" ] # imageTags[0] で取得 "005d6f6"最後に
sed
でダブルクォートを取り除き、再利用可能にします。参考
AWS CLI からのコマンド出力の制御 - AWS Command Line Interface
--query オプションを使用して出力をフィルタリングする方法
AWS CLI は、--query オプションによって、組み込みの JSON ベースの出力フィルタリング機能を提供します。--query パラメータは、JMESPath の仕様に準拠している文字列を受け入れます。
- 投稿日:2020-11-26T13:21:26+09:00
【AWS初心者向け】AWS学習方法まとめ【15時間で達成できる】
AWS学習を始めようと考えている人
「AWSとは、概要や全体像、メリットデメリットが知りたい」
「AWSの学習方法が知りたい」
こういった疑問に答えます。本記事のテーマ
【AWS初心者向け】AWS学習方法まとめ【15時間で達成できる】
AWS学習の始め方
AWSやクラウド初心者の方がAWSを学ぶための方法を纏めました。
①クラウドを学ぶ
②AWSの概要を学ぶ
③知識の定着(AWS公式ハンズオン実施)
④AWS運用の現場に参画残念ながらIT基礎知識(基本情報技術者レベル)がある前提になってしまいました。
(ない場合はもっと時間かかると思います)
知識定着のため、インプット、アウトプットのバランスを考えてまとめています。記事の信頼性
筆者はAWS経験5年程度です。AWS資格は5冠達成しました。
現在は大規模ECサイトのAWS運用を任されるようになっています。今回紹介している記事は全てAWS公式ページにあったもので、その中から初心者向けのものをピックアップしています。(公式ページがこれだけ分かりやすいことにAWSの本気度を感じました)
読者さんへの前置きメッセージ
本記事では「IT経験あるけどクラウド経験ない、クラウド勉強したいけど、どのように勉強していけば良いか分からない」方向けに書いています。
この記事を読むことで、「AWS学習の具体的なやり方、その後のキャリア」までをイメージできるようになると思います。
15時間で終わるので仕事しながらでも1か月もあれば完了できると思います。①クラウドを学ぶ
クラウド (クラウドサービス) とは?(30分程度)
https://aws.amazon.com/jp/cloud/
まずはクラウドについて知るために上記の記事を読みます。
クラウドの専門用語たくさん出てきますが、調べながら読むと良い勉強になる。
量は多くないので30分程度を目標に読み切りましょう。読んだ後に下記が説明できればOKです。
クラウドのメリット
クラウドの種類
クラウドネイティブとは
クラウド活用の場面②AWSの概要を学ぶ
はじめてのアマゾン ウェブ サービス(動画40分程度)
https://pages.awscloud.com/hajimete-ondemand-jp.html?trk=aws_introduction_page
下記についてIT初心者でもわかりやすく解説してくれています。
AWSの企業理念
マネージドサービス(価値を生みずらい重労働の話)
クラウドの利点(早く、安く、楽に)
セキュリティ
クラウドジャーニー(オンプレからの移行)理解が深まるように画像も合わせて貼っておきます。
『AWS ご利用開始時に最低限おさえておきたい10のこと』資料と解説動画(動画60分程度)
https://pages.awscloud.com/event_JAPAN_at-least-10-ondemand.html?trk=aws_introduction_page
初心者には難しいかもしれません。
初回はざっくりで良いので目を通す程度でも大丈夫です。何度も見返すべき資料かなと思います。
AWS Well-Architected Frameworkがどんなものなのか理解できていればOKです。
『AWS 設計のベストプラクティスで最低限知っておくべき 10 のこと』資料と解説動画(動画60分程度)
読むのには高いインフラ知識が必要です。
これも初回は目を通す程度で構いません。超重要なので何度も見返すべき資料です。
(AWS経験者でも理解していないことが多いと感じています。)目次を見て何を言っていたかぼんやり思い返せれば良い感じです。
AWS 初心者向け Webinar 〜料金編〜(動画30分程度×2本)
https://pages.awscloud.com/event_JAPAN_cost-ondemand.html?trk=event_webinar_page
ハンズオンを行う上で利用料金が気になる場合は読んでおく程度です。
今回紹介するハンズオン程度であればほぼ料金はかからないので、気にならなければ読まなくても構いません。
気になる方は上記URLにある7つの動画のうち『AWS 支払いと請求』と『AWS 無料利用枠のご案内』を見ておけば良いです。上記の動画を見ることで下記が理解できます。
コスト確認方法(請求ダッシュボード)
無料利用枠の種類(ずっと無料、1年無料、トライアル期間だけ無料)※無料利用枠については「AWS 無料利用枠」でググると一覧で見れます。
③知識の定着(AWS公式ハンズオン実施)
正直なところ、何もわかってなくても動画の通りにやるだけで、ハンズオンのシステムは完成します。
クラウドのメリットやAWSの設計原則みたいな大枠を理解して実施することが
知識の定着や応用を効かせる意味で重要なことだと考えています。ここではアカウント作成と代表的な2つのアーキテクチャパターンを学ぶハンズオンの
合わせて3つを紹介します。ハンズオンはじめの一歩: AWS アカウントの作り方 & IAM 基本のキ(動画40分(5分程度×8本))
まずはアカウントの作成です。
理解ポイントとしては下記の2点です。
ルートユーザーと IAM ユーザー
IAM (ポリシー、グループ、ロール)について
スケーラブルウェブサイト構築編(動画2時間程度(10分程度×10本)))
AWSで利用される基礎的で一般的な構成です。
ハンズオン後に下図の各種サービスの役割や機能を理解していればOKです。サーバーレスアーキテクチャで翻訳 Web API を構築する(動画2時間程度(10分程度×10本)))
スケーラブルウェブサイト構築編に比べ設定項目が少ないことがわかります。(楽に構築できます)
新規サービスを作る際はなるべくサーバーレスで作れないかを考えるようになるのが目的です。
ハンズオン後に下図の各種サービスの役割や機能を理解していればOKです。
④AWS運用の現場に参画
本記事で書いた程度の知識があれば運用案件に潜り込める可能性が高いです。
(それだけ手が足りていない。自分の現場なら来てほしい)
AWS運用ができれば月額70~80万は稼ぐことが可能です。
運用経験を積んだ後は、より単価の高い設計や提案案件、専門性の高い案件を目指せます。複数の現場でAWS運用していて思うことですが、ベストプラクティスに沿った運用ができている現場はほとんどありません。
なので、運用しながら下記の資料をダウンロードして、繰り返し見て原則を忘れないようにしましょう。
『AWS 設計のベストプラクティスで最低限知っておくべき 10 のこと』資料と解説動画
https://pages.awscloud.com/JAPAN-event-OE-At-least-10-Architecting-2020-reg-event-LP.html?aws_introduction_pageさいごに
資格の勉強だけだと知識定着しないのは、アウトプット(ハンズオンの部分)が足りないからだという結論に行き着いたのが、本記事を執筆しようと思った経緯です。
ベストプラクティスは時代で変わるので、5年前のベストプラクティスが今はバッドプラクティスだったりします。
AWSベテラン経験者になっても改めて本ページに戻ってきてもらえるような使い方をしてもらえると嬉しいです。
(本記事も最新化していかないといけないですが。。)出展
下記ページから最低限必要な知識をピックアップして紹介しています。
興味ある分野引き続きアウトプットしながら学んでみてください。AWS 初心者向け資料
https://aws.amazon.com/jp/aws-jp-introduction/aws-jp-webinar-level-100/
AWS で最低限知っておきたい 10 のことシリーズ
それぞれの分野別に9つの資料がまとめられている
10種類の概要資料がある。本記事では2つの資料を紹介。AWS 初心者向けハンズオン
https://aws.amazon.com/jp/aws-jp-introduction/aws-jp-webinar-hands-on/
13種類のハンズオンがある。本記事では3つのハンズオンを紹介。
- 投稿日:2020-11-26T12:57:21+09:00
EC2で自動デプロイが反映されなくなったときの対処法
はじめに
現象
いつもどおり自動デプロイしたはずがまったく反映されない
やってみて
EC2インスタンスがおかしいのかなと思って再起動してみたら無事解決。
再起動に必要なコマンドを備忘します。手順
EC2インスタンスを再起動
AWSコンソールからEC2インスタンスを再起動します。
DBを起動させる
EC2を再起動するとDBが停止状態になるので起動させます。
(私はMariaDBを使用しています)確認コマンド
ターミナル(EC2)$ sudo systemctl status mariadb結果
ターミナル(EC2)● mariadb.service - MariaDB database server Loaded: loaded (/usr/lib/systemd/system/mariadb.service; disabled; vendor preset: disabled) Active: inactive (dead)死んじゃってるのが確認できます。
DB起動コマンド
ターミナル(EC2)$ sudo systemctl start mariadbこれで確認するとActiveになっているはずです。
Nginxを起動させる
同じようにNginxも起動させます。
Nginx起動コマンド
ターミナル(EC2)$ sudo systemctl start nginx改めて自動デプロイを行う
これが本当に正解なのかわからないところがありますが(1度目の自動デプロイの内容をEC2が読み込めているなら、Unicornの起動だけでいいような気がします)
とりあえず自動デプロイを行えばEC2に反映されますし、Unicornも起動されるのでもう一度コマンドを打ちます。
ターミナル(ローカル)% bundle exec cap production deployこれにて一件落着です。
おわりに
本当にこの画面が嫌いです。
✔︎
- 投稿日:2020-11-26T12:13:49+09:00
boto3 の DEBUG ログを表示しない
Python コードのデバッグのために以下のようにログレベルを DEBUG に設定していると、boto3 関連のログがたくさん流れてきて邪魔なときがある。
import logging logging.basicConfig(level=logging.DEBUG) logger = logging.getLogger(__name__)boto3 関連の DEBUG ログを表示しないようにしたいときは、いくつかのロガーのログレベルを INFO 以上に引き上げればよい。
import logging for name in ["boto3", "botocore", "s3transfer", "urllib3"]: logging.getLogger(name).setLevel(logging.WARNING)ただし、boto3 以外のモジュールが urllib3 に依存していた場合はそのログも見えなくなってしまうので注意。
- 投稿日:2020-11-26T12:05:10+09:00
AWSとオンプレミスの疎通確認に使えるコマンド
- 投稿日:2020-11-26T11:47:38+09:00
[AWS] AWSだけで完結する定期処理の作り方 [Lambda・CloudWatch]
概要
アプリ開発などでサーバレスな環境構築をすることがあると思います。
そう言った場合にAWSでだけで実装することができるバッチ処理の簡単な作り方をご紹介します。
色々やり方はありますが、今回はLambdaとCloudWatchに焦点を当ててご紹介します。また解説する内容は必要最低限のプログラムなどになりますので全体的には15分程で試すことが出来るかと思います。
1. Lambdaで処理を作ろう
まず定期処理が行われた際の実際の処理が行われるプログラムを作成していきます。
AWSのLambdaのトップページより"Create function"ボタンを押下しファンクション作成のページに遷移します。
今回は"Author from scratch"を選択し、Function name(関数名)、Runtime(言語)をそれぞれ入力・選択し"Create function"ボタンを押下します。(筆者は関数名"qiitaBatchFunction"、Runtime"Python3.7"をそれぞれ入力・選択)
上記のページに遷移すればLambda関数の作成は完了です。
実際に行いたい処理を"lambda_function.py"を記述します。
またnpmなどでライブラリを導入したい場合や別途ソースコードの管理をしたい場合は、"Actions ▼"を押下し、"Upload zip file."を選択することで外部のソースコードを利用することができます。実際に作成したソースコードが動くのか確認する場合はページ上部の"Test"ボタンを押下することで確認することが可能です。
では次に定期実行させる仕組みを作っていきましょう!
2. CloudWatchで定期実行させよう
次にCloudWatchで先ほど作成したLambda関数を定期実行させてみましょう。
CloudWatchのサイドバーより"Rules"をクリックします。
そして"Create rule"のボタンを押下します。
まず今回は"Event Source"より"Schedule"を選択します。
そして"Fixed rate of -"を選択し定期実行させたい間隔を設定します。(筆者は5分間隔で起動させる予定なので5を入力し"Minutes"を選択)
もし細かい設定を行いたい場合は、"Cron expression"を選択しスケジュールを設定して下さい。
こちらに関しては検索エンジンで"Cron 書き方"などと調べて頂くと筆者が説明するよりも分かりやすい内容が出てくると思います。次に"Targets"より"Add target"を押下します。
すると何を実行させるか選択できるので"Lambda function"を選択し先ほど作成したLambda関数を選択します。(ここでは筆者が作成した"qiitaBatchFunction"を選択)"Configure details"を押下します。
最後に"Rules"の一覧ページに表示される際のName(表示名)とDescription(説明)を記載して"Create rule"ボタンを押下するだけです。
もし作成と同時に定期実行を行いたくない方は"Stete"のチェックを外して下さい。以上で定期実行の実装は完了です。
あとはサイドバーのLog groupsなどで定期実行されているかログを確認するなどして動作確認を行なって下さい。3. 最後に
今回は必要最低限の動作ということでご紹介致しましたが基本的にはLambdaの処理部分を変えるだけでお好みの動作を行うことが出来るかと思います。
もしzipファイルを作りたい場合は検索エンジンで"lambda zip 外部"と検索して頂くと丁寧に紹介されているサイトが出てくると思います。
筆者自身もまた別の機会にLambdaで使用する外部ソースコードのzipファイル作成方法を投稿する予定です。最後まで見ていただきありがとうございました。
- 投稿日:2020-11-26T11:39:11+09:00
ECSタスクへの機密情報の環境変数の設定
概要
Twelve-Factor Appでも述べられているように、アプリケーションの設定は環境変数にしておいた方が色々と取り回しが効きやすいです。
問題は、パスワードなどの機密情報をどう管理してどうデプロイするかにあります。
AWSとECSには機密情報を環境変数として管理する問題を解決するサービスと機能が存在します。
その利用方法を解説します。アーキテクチャ
環境変数を
AWS Systems Manager
のパラメータストア
で管理します。
ECSタスク定義はdocker-compose
を利用します。
ECSとパラメータストアを連携させて環境変数を埋め込みます。環境変数管理
環境変数はGithubやGitlabで設定できる機能もありますが、AWSを使っているのであれば
Systems Manager
のパラメータストア
を使うのが便利です。理由としては以下が挙げられます。
- 機密情報管理とECSへの展開が容易でセキュア
- S3のようなパスで値を管理できる
- IAMポリシーを使ってアクセス制限をかけられる
機密情報以外の環境変数設定方法
AWS Systems Manager > パラメータストア
画面を開くとパラメータの作成
ボタンがあるのでそれを実行します。作成画面が開くので、各項目を埋めていきます。
項目 説明 名前 パス形式で環境変数名を設定します
パスの先頭とかどこかに環境名(dev/stg/prdなど)を入れておくと良いです説明 説明を記入します。入力なしでも問題ないです 利用枠 通常は 標準
で問題ありません。詳細を使う場合はよく説明を読んで下さいタイプ 通常の利用の場合は 文字列
を選択します。機密情報を利用する場合は安全な文字列
を選択しますデータ型 通常の利用の場合は text
で十分だと思います。詳細はAWSドキュメントを参照してください値 環境変数に設定する値を入力します 各項目を入力して
パラメータを作成
を実行するとパラメータが作成されます。機密情報の環境変数
パラメータを作成画面で項目
タイプ
で安全な文字列
を指定します。
項目 説明 KMSキーソース 暗号化復号化のためのKMSキーのソースを指定 KMSキーID 使用するKMSキーIDを指定 通常は
現在のアカウント
のデフォルトのKMSキーIDで問題ないと思います。
各項目を入力してパラメータを作成
を実行するとパラメータが作成されます。機密情報をECSタスク定義に設定する
docker-compose形式でタスク定義する場合、
- docker-compose.yml
- ecs_params.yml
の2つのファイルを用意します。
docker-compose形式を使ったタスク定義などに関しては以前書いた記事などを参照してください。
docker-compose.ymlには機密情報の環境変数は設定しません。
機密情報の環境変数はecs_params.yml
に設定します。docker-compose.ymlversion: '3' services: app: image: nginx ports: - "80:80" : #機密情報の環境変数は設定しないecs_params.ymlversion: 1 task_definition: services: app: : # ここで機密情報の環境変数を設定 secrets: # value_fromにパラメータストアで設定した環境変数名を設定 - value_from: /dev/DB_USER # nameにアプリケーションで参照する環境変数名を設定 name: DB_USER - value_from: /dev/DB_PASSWORD name: DB_PASSWORD :
secrets
に機密情報の環境変数を設定します。
value_from
にパラメータストアで設定した環境変数名を設定します。
name
にアプリケーションで参照する環境変数名を設定します。https://docs.aws.amazon.com/ja_jp/AmazonECS/latest/developerguide/cmd-ecs-cli-compose-ecsparams.html
まとめ
パスワードなどの環境変数として埋め込む機密情報の管理は厄介な問題でしたが、AWSを利用している場合は簡単に解決できます。
また、PEMファイルなどの認証鍵もbase64エンコードしてパラメータストアに登録しておくことで、ファイルとしてサーバやコンテナに置いておく必要がなくなります。
こういうときにクラウドサービスはすごい便利だと感じます。
パラメータストアを是非活用してみてください。
- 投稿日:2020-11-26T11:33:22+09:00
Oracle DBのマネージメントサービスを使用したくなった時にOCIとAWSのどちらにするか
ちょっと使ってみた上での感想。
Oracle DBのエンジニアが余ってて稼働を確保したい→OCI
Oracle DBが大得意なエンジニアがいてOracle DBの機能を活用したい→OCI
EEの機能を使いたい→OCI
Oracle DBを使わないといけないけど、Oracleの機能をあまり知らないので運用面としては他DBと同じように扱いたい→AWS
Oracle DBを酷使しないといけないけど、Oracleの機能をあまり知らないのでチューニングとかは自動でやってほしい、あとお金はたくさんある→OCI
なんとなくOracle DBをユーザー目線で使ってみたい→AWS
Oracle DBをどうしても運用したい→OCI
規模がでかい→OCI
それ以外、もしくは初心者→AWS
- 投稿日:2020-11-26T08:43:21+09:00
Mysql2::Error: Table '○○_production.users' doesn't existを解消した話
表題が発生し、解消するまでの顛末をまとめました。原因は2つありました。
開発環境
ruby 2.6.5
Rails 6.0.3.2
capistrano 3.14.1
AWS EC2
webサーバーNginx
アプリケーションサーバーUnicorn事の発端
データベース関連の修正を行ったため、本番環境(EC2)で一度テーブルを落としてから再作成しました。
そしてマイグレーションを行った際、表題のエラーが発生しました。結論、原因は2つありました。原因その1 userを参照するreferencesメソッドが、userテーブルが作成される前に読み込まれていた
こちらの方がわかりやすくまとめられてます。
https://obel.hatenablog.jp/entry/20170719/1500456452rails db:migrate:statusで確認すると、確かにテーブルのステータスがdownになっていました。
タイトルの通り、エラーメッセージの指摘は何ら矛盾がありませんでしたね。
ただ、開発環境ではエラーにはならず?アプリも正常に動いていたので、気づくのにかなり時間を費やしました。こちらの記事の通り、マイグレーションファイルの日付を修正して、読み込まれる順序を変更しました。
そして、statusはupになりましたが、それでもエラー自体は解消されませんでした。原因その2 本番環境でgit pull origin masterをしていなかった
結論、これによって上の作業がEC2上に反映され、ようやく解消に至りました。
いやもう思い違いをしていたというか、今なお十分な理解に至っていないのですが、githubへpush(作業ブランチで開発していた場合はmergeしてmasterへpullまで)したら、このコマンドは必要ないと思っていました。
実際、それで自動デプロイのコマンドを打てば、本番環境に機能を実装させることはできていました。git pull origin masterは毎回必要なのだろうか?この辺りは宿題になっています。
git,githubは大分慣れたように思っていましたが、まだまだ知識が不足しているようです。
- 投稿日:2020-11-26T02:44:31+09:00
AWS 上でマルチアカウントで複数サービスをホストする場合のアーキテクチャパターン (2)
はじめに
AWS 上でマルチアカウントで複数サービスをホストする場合のアーキテクチャパターンを紹介します。
この記事は2つ目で、最初の記事ではシングルアカウントでのパターンについて紹介しています。マルチアカウントの場合
シングルアカウントパターンで紹介した構成がマルチアカウントでも可能なのかまず見てみましょう。
ALBがフロントパターン
まずはこちらです。
現時点では、ALBのアカウント間共有の機能はないので、ALBをアカウントAが持つ、App1をアカウントBが持つ、App2をアカウントCが持つ...といったことはできないです
HTTP APIがフロントパターン
次にこちらです。
HTTP API と 内部ALBの連携機能は、同一アカウント内のリソースである必要があるので、API GatewayをアカウントAが持つ、内部ALBをアカウントBが持つ...といったことはできなさそうです。
REST APIがフロントパターン
次にこちらです。
REST API と 内部NLBの連携機能も同様に、同一アカウント内のリソースである必要があるので、API GatewayをアカウントAが持つ、内部NLBをアカウントBが持つ...といったことはできなさそうです。
分が悪くなって来ました。
次を見てみましょう。
REST APIがフロントで 外部ALBをバックエンドに持つパターン
お、これはマルチアカウントできそうですね。
API GatewayをアカウントAで作成し、ALBはアカウントBで作成する。
API GatewayとALBとの接続は Publicにすると、API Gatewayだけを管理するアカウントと、ALBとそれに紐付くリソースを管理するアカウントに分けることができそうです。(ALBのアクセス制限は最初の記事を参照してください)
ただし、冒頭で述べたように、ALBのアカウント共有機能はないため、この構成図だと App1とApp2は必ず同一アカウントになってしまいます。
それをどうにかする方法を少し考えてみたいと思います。パスごとにALBを持つパターン
こちらだと、API Gateway、App1用のALB、App2用のALBをそれぞれ別アカウントで持つということができそうです。
(参考までにLambda(App3)も別アカウントに持ちたい場合は、フロントのAPI Gatewayの後ろに「ALB - Lambda」か「API Gateway - Lambda」になるかなと思います。あまりイケている気がしないですが、、)これを増やしていく、つまり、path3用のALB、path4用のALB...と増やしていけば、フロントをAPI Gatewayに統一し、バックエンドをそれぞれ別アカウントで作成するといったことはできそうです。
どうしても API Gateaway - ALB間の public接続が許容できない場合
REST APIの機能は必須だけど、ALBを使いたい。でも、public接続が許容できないというのも少なからずあると思います。
その場合のマルチアカウントパターンについて考えてみたいと思います。Appごとにアカウントを分けたい場合
構成図のうち、API gateway、内部NLBとリバースプロキシ(nginxなど)を作成するフロントアカウントと、ELBとAppを持つアプリケーションアカウントに別れます。そして、アプリケーションの数だけアプリケーションアカウントが存在することになります。
複数のVPC間は、VPC peeringもしくは Transit Gatewayで互いに接続します。こうすることで、API Gatwayから実際のアプリケーションまでの経路は、VPCから外に出ないprivateな通信になります。
考慮が点としては、アプリケーションが増えるごとに、nginxの設定を追加変更する必要がある点です。Appごとにアカウントを分けない場合
Appごとにアカウントを分けなくてもいい、つまり、フロント用アカウントとアプリ用アカウントさえ別れていればOKな場合は、
前述の「アプリケーションが増えるごとに、nginxの設定を追加変更する必要がある」という手間はなくなります。具体的には構成図のように、nginxをシンプルなリバースプロキシ(来たリクエストは全て単一のALBに流す)として設定し、実際のルーティングはALBに任せることで、アプリケーションが増えても、基本的にはNginxの設定を変更する必要はなく、アプリケーション用アカウントのALB周りだけイジればいいことになります。
アプリごとにアカウントを分けなくてもいい場合は、意外とシンプルになるのではないでしょうか。
(余談) API Gatewayではなく、ELBをフロントに置くパターン
考え方は全く同じですが、アプリ用のアカウントをどうするかで、同様に以下の2パターンがあるかなーと思います。
まとめ
フロントとアプリケーションでAWSアカウントを分けたい場合は、現時点でのAWS側の制約などもあり、なかなか一筋縄ではいかなそうです。
個人的には、API Gatewayが必須かどうか、アプリケーション用のAWSアカウントの分け方をどうするかで取りうる選択が変わってきそうです。API Gatewayの機能は魅力的なので、使いたい人は多いのではないかと個人的には思っています。
なので、アプリケーション用のアカウントを分けたい場合はこのパターン(再掲)。ただし、アプリケーション追加時のNginxの設定変更をどうにかして頑張ることを許容する。
アプリケーション用のアカウントを分けなくてもいい場合はこのパターン(再掲)、というのがいいのではないかと思っています
次の話
今回は、/path1 や /path2 でアプリケーションを分けたい。つまり、ルーティングが主目的だったため、ALBやAPI Gatewayでルーティングさせるアーキテクチャをメインで紹介しましたが、通常のルーティング以外に、リトライや接続数制限、サーキットブレーカーといった機能も求めたくなってしまうこともあるかもしれません。
その場合は、ALBでは対応できないため、AWSのサービスであれば、App Meshを使うことになるかと思います。
次回は、App Meshを使ったマルチアカウントパターンについて紹介したいと思います。
- 投稿日:2020-11-26T00:12:14+09:00
開発環境で更新したGithubのコードを本番環境でpull
git fetch origin master
↓
git reset --hard origin/master(強制的にpullする)
↓
EC2インスタンス再起動(これをしないとunicornの起動時にエラー)
↓
unicorn_rails -c /var/www/rails/mumu(アプリの名前)/config/unicorn.conf.rb -D -E production(unicornの起動)
↓
sudo nginx -s reload(Nginxの再起動)
↓
sudo service mysqld start(mysqlを起動していなかったら)