20210225のAWSに関する記事は26件です。

AWS12ヶ月無料枠オススメ3選

始めに

プログラミング勉強をしていて、AWSの無料枠にはお世話になったのですが、そこで使って良かったもの・使用してみたいものを個人的に残しときたいなと思い書きました。

AWSの12ヶ月無料枠とは

AWSのアカウント登録をしてから、12ヶ月間のみ無料で使用できるサービスのことです。

AWS12ヶ月無料枠①Amazon EC2

AWSを使う大体の人が使うサービスだと思います。AWS上に仮想サーバーを構築して自由に利用できるのが特徴です。ユーザーの必要に応じてスペックを変更できるのがEC2の魅力です。

750時間の使用時間と20GBのディスク容量が無料で使用できます。

※Amazon Linuxが無料利用枠の対象である一方で、Windowsは対象とはなっていません。

AWS12ヶ月無料枠②Amazon RDS

データベース機能を提供するサービスです。RDSの場合はサーバの準備が不要で、構築後すぐにデータベースの利用が可能となります。
MySQL、PostgreSQL、MariaDBなどの一般的なデータベースを、簡単な操作で作成することができます。

750時間の使用時間と20GBのディスク容量および20GBのスナップショットが無料で使用できます。

※microインスタンスのみが対象となります。

AWS12ヶ月無料枠③Amazon S3

データ容量を気にすることなく保存することができるサービスです。その場に応じて自由な使い道が想定され、より柔軟なデータ保存が実行できるのが特徴となっています。
ウェブサイト、バックアップおよび復元、アーカイブなど、様々な用途に対応することができます。

5GBの標準ストレージと20000回のアップロード・2000回のダウンロードが無料で使用できます。

※僕自身この機能は使用したことがないので使用してみたいです。

参考

AWSの無料枠でできること3選|AWS無料枠を使用する際の注意点3つ
参考にさせていただきました!ありがとうございます!

最後に

12ヶ月間の有効期限が切れた後やサービス使用量が制限を超えた場合は、料金を支払う必要があるので注意してください!

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

autogluon.tabularのTabularDatasetによるデータの取得ができなくなってしまった件と解決方法について(2021/02/25に検知)

はじめに

先月、Google ColaboratoryでAutoGluonをinstall & importする方法という記事を書きました。しかし、改めてAutoGluon1を実行しようとしたところ以下のようなエラーが出てしまいました(2021/02/25)。具体的には、autogluon.tabularTabularDatasetによるデータの取得ができなくなってしましました。

from autogluon.tabular import TabularDataset, TabularPredictor

train_data = TabularDataset(file_path='https://autogluon.s3.amazonaws.com/datasets/Inc/train.csv')
test_data = TabularDataset(file_path='https://autogluon.s3.amazonaws.com/datasets/Inc/test.csv')
predictor = TabularPredictor(label='class').fit(train_data, time_limit=60)  # Fit models for 60s
leaderboard = predictor.leaderboard(test_data)

※一部マスク済み

---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
<ipython-input-1-XXXXXXXXXXXX> in <module>()
      1 from autogluon.tabular import TabularDataset, TabularPredictor
      2 
----> 3 train_data = TabularDataset(file_path='https://autogluon.s3.amazonaws.com/datasets/Inc/train.csv')
      4 test_data = TabularDataset(file_path='https://autogluon.s3.amazonaws.com/datasets/Inc/test.csv')
      5 predictor = TabularPredictor(label='class').fit(train_data, time_limit=60)  # Fit models for 60s

TypeError: __init__() missing 1 required positional argument: 'data'

結論

引数のfile_path=が不要になったようです。README2も気が付いたら更新されていたみたいです。

from autogluon.tabular import TabularDataset, TabularPredictor

train_data = TabularDataset('https://autogluon.s3.amazonaws.com/datasets/Inc/train.csv')
test_data = TabularDataset('https://autogluon.s3.amazonaws.com/datasets/Inc/test.csv')
predictor = TabularPredictor(label='class').fit(train_data, time_limit=60)  # Fit models for 60s
leaderboard = predictor.leaderboard(test_data)
(省略)

AutoGluon training complete, total runtime = 64.75s ...
TabularPredictor saved. To load, use: TabularPredictor.load("AutogluonModels/ag-20210225_133323/")
                  model  score_test  score_val  pred_time_test  pred_time_val   fit_time  pred_time_test_marginal  pred_time_val_marginal  fit_time_marginal  stack_level  can_infer  fit_order
0   WeightedEnsemble_L2    0.874706     0.8848        3.773335       1.229578  44.071734                 0.014430                0.005951           1.228042            2       True         11
1              LightGBM    0.873375     0.8800        0.076524       0.041000   1.121325                 0.076524                0.041000           1.121325            1       True          7
2              CatBoost    0.872351     0.8768        0.026494       0.017763   5.229808                 0.026494                0.017763           5.229808            1       True          9
3               XGBoost    0.870713     0.8756        0.131061       0.035778   1.921347                 0.131061                0.035778           1.921347            1       True         10
4            LightGBMXT    0.870202     0.8756        0.166172       0.062271   1.544986                 0.166172                0.062271           1.544986            1       True          8
5      RandomForestGini    0.859863     0.8600        0.830060       0.215768  10.372102                 0.830060                0.215768          10.372102            1       True          1
6      RandomForestEntr    0.858225     0.8612        0.820438       0.315851  12.771529                 0.820438                0.315851          12.771529            1       True          2
7        ExtraTreesGini    0.845839     0.8468        1.310977       0.315492   9.186114                 1.310977                0.315492           9.186114            1       True          3
8        ExtraTreesEntr    0.845737     0.8432        1.312058       0.315819   9.196487                 1.312058                0.315819           9.196487            1       True          4
9        KNeighborsUnif    0.773365     0.7752        0.108653       0.109507   0.389895                 0.108653                0.109507           0.389895            1       True          5
10       KNeighborsDist    0.762514     0.7660        0.288525       0.110196   0.306585                 0.288525                0.110196           0.306585            1       True          6

まとめ

autogluon.tabularTabularDatasetによるデータの取得ができなくなってしまった件と解決方法について紹介しました。引き続きAutoGluonをはじめとするAutoMLをどんどん体験していきましょう!

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

Amazon RDS for SQL Server の "Always on"

⬛️内容

Amazon RDS for SQL Server で Standard Edition で Always On Availability Group が利用可能に
[Feb 23, 2021]Amazon RDS for SQL Server now supports Always On Availability Groups for Standard Edition

普段、AWS RDS を利用する際は、MySQLを利用することが多いのですが、エンジンのタイプが異なると、マルチAZの選択がどうなるのかと気になり、多少やって見た系の記事です。

⬛️やって見た系

最新アップデート情報の内容の通り、
エンジンタイプには「Microsoft SQL Server」
エディションには「SQL Server Standard Edition」
を選択する。
スクリーンショット 2021-02-25 18.27.57.png

マルチAZ配置では「あり」もしくは「なし」しか選べないようになっている。
では、"Always on"か"Mirroring"どちらが指定されるのか?
こちらの説明にあるとおり、"Always On" とは SQL Server の「高可用性」を実現する機能であり、"Mirroring"に変わる機能。
"Mirroring"は非推奨のようであり、"Always On" に対応したMicrosoft SQL Server のマルチ AZ 配置を確認すべき。
スクリーンショット 2021-02-25 18.35.46.png

設定は自動的に行われ、RDS はデプロイする SQL Server のバージョンに基づいて、"Always on"か"Mirroring"かが選択され、マネージコンソールから確認することが可能なようです。
キャプチャ.PNG

フェイルオーバーで再起動をしてみると、40秒程度でフェイルオーバーしているようです。

二月 25, 2021, 12:34:33 午後 UTC
Multi-AZ instance failover started.
二月 25, 2021, 12:34:58 午後 UTC
Multi-AZ instance failover completed
二月 25, 2021, 12:35:13 午後 UTC
Multi-AZ failover to standby complete - DNS propagation may take a few minutes

なお、現在"Mirroring"から"Always on"に自動では変更されません。
"Mirroring"から"Always on"に変更したい場合は、シングル構成に変更して、再度マルチAZ構成変更する必要があるようです。

⬛️リンク

Amazon RDS

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

Amazon FSx for Lustre 使ってみた part2

プレロード

状態確認

S3にアップロードした後、ファイルストレージにロードされた状態だとexists archivedと表示される。

$ sudo lfs hsm_state /mnt/fsx/FSxLustre20210225T110202Z/test2.txt
/mnt/fsx/FSxLustre20210225T110202Z/test2.txt: (0x00000009) exists archived, archive_id:1

S3にアップロードした後、まだロードされていない状態だとreleased exists archivedと表示される。

$ sudo lfs hsm_state /mnt/fsx/FSxLustre20210225T110202Z/test3.txt
/mnt/fsx/FSxLustre20210225T110202Z/test3.txt: (0x0000000d) released exists archived, archive_id:1

この時間差は次節のプレロードによって解消されるらしい。

なお、フォルダの中身をまとめて確認できる。

$ sudo lfs hsm_state /mnt/fsx/FSxLustre20210225T110202Z/*
/mnt/fsx/FSxLustre20210225T110202Z/test2.txt: (0x00000009) exists archived, archive_id:1
/mnt/fsx/FSxLustre20210225T110202Z/test3.txt: (0x00000009) exists archived, archive_id:1
/mnt/fsx/FSxLustre20210225T110202Z/test4.txt: (0x00000009) exists archived, archive_id:1
/mnt/fsx/FSxLustre20210225T110202Z/test5.txt: (0x0000000d) released exists archived, archive_id:1

プレロード

Amazon FSx copies data from your Amazon S3 data repository when a file is first accessed. Because of this approach, the initial read or write to a file incurs a small amount of latency. If your application is sensitive to this latency, and you know which files or directories your application needs to access, you can optionally preload contents of individual files or directories.

日本語訳

Amazon FSxは、ファイルが最初にアクセスされたときにAmazon S3データリポジトリからデータをコピーする。このアプローチのため、ファイルへの最初の読み取りや書き込みには少量の遅延が発生します。アプリケーションがこの待ち時間に敏感で、アプリケーションがアクセスする必要のあるファイルやディレクトリがわかっている場合、オプションで個々のファイルやディレクトリのコンテンツをプリロードすることができます。

$ sudo lfs hsm_restore /mnt/fsx/FSxLustre20210225T110202Z/test2.txt

You can use the hsm_action command to verify that the file's contents have finished loading into the file system. A return value of NOOP indicates that the file has successfully been loaded. Run the following commands from a compute instance with the file system mounted.

日本語訳

hsm_actionコマンドを使用して、ファイルの内容がファイルシステムへのロードが終了したことを確認することができます。NOOPが返ってきた場合は、ファイルが正常にロードされたことを示します。

$ sudo lfs hsm_action /mnt/fsx/FSxLustre20210225T110202Z/test2.txt
/mnt/fsx/FSxLustre20210225T110202Z/test2.txt: NOOP

データリポジトリ

ディレクトリmydirをS3にアップロードする。ここでマウントポイントは/mnt/fsxである。

$ ls /mnt/fsx/mydir/
mytest1.txt  mytest2.txt

画像のようにマウントポイント配下のディレクトリを指定する。

image.png

  • ステータス

image.png

  • データリポジトリを使ったアップロード後のS3の状態

image.png

リリース

If you want to create storage space on your file system, you can release files from your file system. Releasing a file retains the file listing and metadata, but removes the local copy of that file's contents.

日本語訳

ファイルシステムにストレージスペースを作成したい場合は、ファイルシステムからファイルを解放することができます。ファイルをリリースすると、ファイルの一覧とメタデータは保持されますが、そのファイルのコンテンツのローカルコピーは削除されます。

$ sudo lfs hsm_release /mnt/fsx/test1.txt
$ sudo lfs hsm_state /mnt/fsx/test1.txt
/mnt/fsx/test1.txt: (0x0000000d) released exists archived, archive_id:1

リリースの後、プレロードによって再度ファイルシステムにロード可能である。

参考記事

Preloading files into your file system
https://docs.aws.amazon.com/fsx/latest/LustreGuide/preload-file-contents-hsm.html

Overview of data repositories
https://docs.aws.amazon.com/fsx/latest/LustreGuide/overview-data-repo.html

Releasing data from your file system
https://docs.aws.amazon.com/fsx/latest/LustreGuide/release-files.html

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

Mac (M1)にeksctlを上手くインストールできないときの解決策

最近、kubernetesの勉強をしております。
その際、EKSを使おうと、MacBook Air(M1)にeksctlを入れようとしたのですが、上手くインストールできませんでした。
具体的にはbrewでインストールしようとしました。

brew install weaveworks/tap/eksctl

しかし、下記エラーが出てしまいました。。。

Updating Homebrew...
==> Auto-updated Homebrew!
Updated 1 tap (homebrew/core).
==> New Formulae
go@1.15
==> Updated Formulae
Updated 23 formulae.

==> Installing eksctl from weaveworks/tap
==> Cloning https://github.com/kubernetes/kubernetes.git
Updating /Users/××××××/Library/Caches/Homebrew/kubernetes-cli--git
==> Checking out tag v1.20.4
HEAD is now at e87da0bd Release commit for Kubernetes v1.20.4
HEAD is now at e87da0bd Release commit for Kubernetes v1.20.4
==> Downloading https://github.com/weaveworks/eksctl/releases/download/0.38.0/eksctl_Dar
Already downloaded: /Users/×××××/Library/Caches/Homebrew/downloads/2f6b84c0a198a6a4fc02f1d9dfe0de667aea70e1e39795e724139d3a4aa3a26c--eksctl_Darwin_amd64.tar.gz
==> Installing dependencies for weaveworks/tap/eksctl: kubernetes-cli
==> Installing weaveworks/tap/eksctl dependency: kubernetes-cli
==> make WHAT=cmd/kubectl
Last 15 lines from /Users/×××××/Library/Logs/Homebrew/kubernetes-cli/01.make:
    ./vendor/k8s.io/code-generator/cmd/prerelease-lifecycle-gen
touch: _output/bin/go-bindata: No such file or directory
make[1]: *** [_output/bin/go-bindata] Error 1
make[1]: *** Waiting for unfinished jobs....
touch: _output/bin/prerelease-lifecycle-gen: No such file or directory
make[1]: *** [_output/bin/prerelease-lifecycle-gen] Error 1
touch: _output/bin/defaulter-gen: No such file or directory
make[1]: *** [_output/bin/defaulter-gen] Error 1
touch: _output/bin/deepcopy-gen: No such file or directory
make[1]: *** [_output/bin/deepcopy-gen] Error 1
touch: _output/bin/conversion-gen: No such file or directory
make[1]: *** [_output/bin/conversion-gen] Error 1
touch: _output/bin/openapi-gen: No such file or directory
make[1]: *** [_output/bin/openapi-gen] Error 1
make: *** [generated_files] Error 2

Do not report this issue to Homebrew/brew or Homebrew/core!

These open issues may also help:
kubernetes-cli: Add support for darwin/arm64 https://github.com/Homebrew/homebrew-core/pull/69931
kubernetes-cli: build for Apple Silicon https://github.com/Homebrew/homebrew-core/pull/68455

解決策

いろいろ調べましたが、まだ解決されていないのか、結局のところ、brewでインストールできませんでした。
AWSの公式ドキュメントを読んでいたとき、手動でダウンロードできるようなので、やってみました!

リリースのアーカイブを手動でダウンロードします https://github.com/weaveworks/eksctl/releases/download/0.36.0/eksctl_Darwin_amd64.tar.gz、eksctl を展開し、実行します。
参照元:https://docs.aws.amazon.com/ja_jp/eks/latest/userguide/eksctl.html

手順

1 上記URLから、フォルダを指定してダウンロードし、展開します。

2 下記コマンドでPATHの通っている場所を調べ、展開したコマンドをコピーしてください。私の場合は/usr/local/bin配下にコピーしました。

echo $PATH
sudo cp eksctl /usr/local/bin

3 下記コマンドを実行し、バージョンが表示されれば、無事完了です。

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

AWSを勉強しての備忘録

AWS Cloud Tech を通して学習した内容を備忘録として記述します。

AWSとは

Amazon.comにより提供されているクラウドコンピューティングサービス。
AWSとは、Amazon Web Servicesの略で、Amazonが提供している100以上のクラウドコンピューティングサービスの総称。
従来の「オンプレミス」とは違い、初期費用なし、メンテナンスなし、料金は使った分だけで今すぐ使用することができる便利なサービス。

主要サービス

  • VPC
    仮想プライベートクラウドを提供する商用クラウドコンピューティングサービス。AWSクラウド空間上に自分だけのクラウド空間を作れる。広いAWSさんの土地に自分だけの土地を確保するみたいなこと。

  • EC2
    安全でサイズ変更可能なコンピューティング性能をクラウド内で提供するウェブサービス。AWS上に自分がほしいスペックのサーバー自由に構築できる。VPCで確保した土地に自分の好みの家をつくるみたいなこと。

  • IAM
    AWS リソースへのアクセスを安全に管理するためのウェブサービス。VPCやEC2にアクセスできるユーザーを管理するもの。AWS上に確保した土地や作った家に入れる人を管理する機能みたいなこと。

  • RDS
    AWSのフルマネージドなリレーショナルデータベースのサービス。AWS上に確保した土地や作った家の中で必要な家具や家電を管理する機能みたいなこと。(←あまりいい例えじゃない気がする。)

基本的なAWS構成図

クロカワさんのレクチャー・資料を参考に「cacoo」で作ってみました。
AWS Design (updated) (1).png

主要サービス以外の解説

  • Availability Zone
    リージョンごとにアベイラビリティーゾーンと呼ばれる複数の独立した場所、つまりサーバーが置かれた建物がある。

  • インターネットゲートウェイ
    VPCのコンポーネント(部品)の1つ。VPC内部とインターネットを通信をする機能。

  • subnet
    大きいネットワーク(VPC)を小さく分割したネットワーク。
    Public subnetとPrivate subnetで分けてVPC外部とやり取りするものとVPC内部でのみやり取りするネットワークという感じで分けて使う場合もある。 

  • Security group
    VPCインスタンスの仮想ファイアウォールとして機能している。

  • レプリケーション
    複製(レプリカ)の作成を意味する。2セット(稼働系と待機系)用意された環境において リアルタイムにデータ複製する技術のこと。
    障害とか何かあれば瞬時に切り替わる仕組み。

まとめ

AWSについて全くの素人がここまで学べました。
残りの教材も頑張っていきたいです。

この記事はAWS初学者を導く体系的な動画学習サービス
「AWS CloudTech」の課題カリキュラムで作成しました。

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

【 Ruby on Rails 6.0 】AWS + Nginx + Unicornでデプロイ⑥

始めに

前回の内容でブラウザ上でRailsアプリを起動するところまで実装出来ました。
今回はNginxというWebサーバーをインストールしてリクエストとレスポンスをインタラクティブに可能にしていきたいと思います。

目次

目次 内容
セクション1 EC2インスタンス作成
セクション2 Linuxサーバー構築
セクション3 データベース設定
セクション4 EC2上でGemをインストールし環境変数を設定
セクション5 Railsアプリを起動
セクション6 Nginxの導入(今回の内容)

Nginxの導入

Nginx(エンジン・エックス)とは、Webサーバの一種です。
ユーザーのリクエストに対して静的コンテンツの取り出し処理を行い、そして動的コ ンテンツの生成をアプリケーションサーバに依頼するためのものになります。 早速インストールしていきましょう。

Nginxをインストール

ターミナル(EC2)
# Nginxをインストール
[ec2-user@ip-172-31-25-189 ~]$ sudo amazon-linux-extras install nginx1

Nginxの設定ファイルを編集

次に、Nginxが正しく動くように設定しましょう。
Nginxの設定は設定項目X 設定値x;という形式で入力していきます。
これも先ほどと同様に、vimコマンドを使ってターミナル上で編集していきます。 /etc以下のファイルなので、強い権限でないと書き込み、保存ができません。そのため、コマンドの頭にsudoをつけています。

ターミナル(EC2)
[ec2-user@ip-172-31-25-189 ~]$ sudo vim /etc/nginx/conf.d/rails.conf

開けたら次のように編集します。

rails.conf
upstream app_server {
  # Unicornと連携させるための設定。
  # アプリケーション名を自身のアプリ名に書き換えることに注意。今回であればおそらく
  server unix:/var/www/〇〇〇〇〇〇<アプリケーション名>/tmp/sockets/unicorn.sock;
}

# {}で囲った部分をブロックと呼ぶ。サーバの設定ができる
server {
  # このプログラムが接続を受け付けるポート番号
  listen 80;
  # 接続を受け付けるリクエストURL ここに書いていないURLではアクセスできない
  server_name XX.XXX.XXX.XXElastic IP;

  # クライアントからアップロードされてくるファイルの容量の上限を2ギガに設定。デフォルトは1メガなので大きめにしておく
  client_max_body_size 2g;

# 接続が来た際のrootディレクトリ
  root /var/www/〇〇〇〇〇<アプリケーション名>/public;

# assetsファイル(CSSやJavaScriptのファイルなど)にアクセスが来た際に適用される設定
  location ^~ /assets/ {
    gzip_static on;
    expires max;
    add_header Cache-Control public;
  }

  try_files $uri/index.html $uri @unicorn;

  location @unicorn {
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    proxy_set_header Host $http_host;
    proxy_redirect off;
    proxy_pass http://app_server;
  }

  error_page 500 502 503 504 /500.html;
}
  • 3行目の<アプリケーション名> となっている箇所は、ご自身のものに変更してください。
  • 11行目のとなっている箇所も同様に、ご自身のものに変更してください。
  • 14行目の<アプリケーション名>となっている箇所は、ご自身のものに変更してくだ さい。

nginxの権限を変更

POSTメソッドでもエラーが出ないようにするために、下記のコマンドも実行

ターミナル(EC2)
[ec2-user@ip-172-31-25-189 ~]$ cd /var/lib
[ec2-user@ip-172-31-25-189 lib]$ sudo chmod -R 775 nginx

これで、Nginxの設定が完了しました。

Nginxを起動して、設定ファイルを再読み込み

[ec2-user@ip-172-31-25-189 lib]$ cd ~
[ec2-user@ip-172-31-25-189 ~]$ sudo systemctl start nginx
[ec2-user@ip-172-31-25-189 ~]$ sudo systemctl  reload nginx

# ステータス確認
[ec2-user@ip-172-31-25-189 ~]$ sudo systemctl  status nginx
● nginx.service - The nginx HTTP and reverse proxy server
   Loaded: loaded (/usr/lib/systemd/system/nginx.service; disabled; vendor preset: disabled)
   Active: active (running) since 日 2021-02-21 04:20:53 UTC; 32s ago

unicorn.rbを修正

次にNginxを介した処理を行うためにunicornの設定を修正します。

unicorn.rb(ローカル)
listen 3000

以下のように修正

listen "#{app_path}/tmp/sockets/unicorn.sock"

修正をしたら忘れずに、commitとpushをし、サーバ側で以下のコマンドを実行して修正点を反映させておきます。

ローカルの変更点を本番環境へ反映

ターミナル(EC2)
[ec2-user@ip-172-31-25-189 ~]$ cd /var/www/アプリ名

# 本番環境に反映
[ec2-user@ip-172-31-23-189 <アプリ名>]$ git pull origin master

Unicornを再起動

Unicornのプロセスをkillして、再起動する作業を行います。

ターミナル(EC2)
# プロセスを確認
[ec2-user@ip-172-31-23-189 <リポジトリ名>]$ ps aux | grep unicorn

ec2-user 17877  0.4 18.1 588472 182840 ?       Sl   01:55   0:02 unicorn_rails master -c config/unicorn.rb -E production -D
ec2-user 17881  0.0 17.3 589088 175164 ?       Sl   01:55   0:00 unicorn_rails worker[0] -c config/unicorn.rb -E production -D
ec2-user 17911  0.0  0.2 110532  2180 pts/0    S+   02:05   0:00 grep --color=auto unicorn

# 続いて、unicorn_rails master(一番上)のプロセスをkillします。
[ec2-user@ip-172-31-23-189 <リポジトリ名>]$ kill <確認したunicorn rails masterのPID上のコードでは17877>

# unicornを起動します
[ec2-user@ip-172-31-23-189 <アプリ名>]$ RAILS_SERVE_STATIC_FILES=1 unicorn_rails -c config/unicorn.rb -E production -D

ブラウザで確認してみましょう

ブラウザからElastic IPでアクセスすると、アプリケーションにアクセスできます(:3000 をつける必要はありません)。なお、この時もunicornが起動している必要があります。

ローカルの変更を本番環境に反映させる手順まとめ

  • 開発環境でgit push
  • EC2インスタンスにSSHログイン
ターミナル(ローカル)
# ssh.ディレクトリで行う
ssh. $ ssh -i ダウンロードしたキーペア名.pem ec2-user@Elastic IPアドレス
  • ローカルの変更を本番環境に反映
ターミナル(EC2)
# アプリのディレクトリでに移動
[ec2-user@ip-172-31-23-189 <アプリ名>]$ cd /var/www/リポジトリ名

# 本番環境に反映
[ec2-user@ip-172-31-23-189 <アプリ名>]$ git pull origin master
  • アセットのコンパイル
ターミナル(EC2)
[ec2-user@ip-172-31-23-189 <アプリ名>]$ rails assets:precompile RAILS_ENV=production
  • Unicorn起動
ターミナル(EC2)
# プロセスを確認
[ec2-user@ip-172-31-23-189 <リポジトリ名>]$ ps aux | grep unicorn

ec2-user 17877  0.4 18.1 588472 182840 ?       Sl   01:55   0:02 unicorn_rails master -c config/unicorn.rb -E production -D
ec2-user 17881  0.0 17.3 589088 175164 ?       Sl   01:55   0:00 unicorn_rails worker[0] -c config/unicorn.rb -E production -D
ec2-user 17911  0.0  0.2 110532  2180 pts/0    S+   02:05   0:00 grep --color=auto unicorn

# 続いて、unicorn_rails master(一番上)のプロセスをkillします。
[ec2-user@ip-172-31-23-189 <リポジトリ名>]$ kill <確認したunicorn rails masterのPID上のコードでは17877>

# unicornを起動します
[ec2-user@ip-172-31-23-189 <アプリ名>]$ RAILS_SERVE_STATIC_FILES=1 unicorn_rails -c config/unicorn.rb -E production -D

IPアドレスをうってブラウザで確認

IPアドレスにアクセスしてもエラーが出る時

エラーが出る時は以下の項目確認してみてください。

  • 502 but gateway とエラーが出る場合は、nginxのlogの確認が必要になります。
  • /var/log/nginx/error.logをlessまたはcatコマンドで確認する。
  • サーバ側で、 /var/www/<レポジトリ名>/log/unicorn.stderr.log を less またはcatコマンドで確認し、エラーが出ていないか確認する(下に行くほど最新のログです。時刻表記がUTCであることに注意してください)
  • Railsを起動しているか
  • EC2インスタンスの再起動を行ってみる(※本番環境にてmysqlとnginxの起動が必要です。)

終わりに

以上で本番環境でRailsアプリを起動・操作できると思います!
しかし、現状だとローカル環境で変更点が発生した時に本番環境に反映させるのが工数が多く大変です。
なので次回の記事でこのデプロイ作業を自動化するためCapistranoというツールを導入したいと思います。
お疲れさまでした。。。

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

コマンドラインから(awscliで)CloudFrontのキャッシュ無効化する

手順

3つのコマンドを実行して達成可能。

  1. CloudFront の disutribution id を入手
  2. パスを無効化する
  3. 無効化の進捗状況を確認する

例の内訳

{profile}
認証情報のプロファイル
{hostname}
ドメイン割り当て済みならFQDN
{path}
無効化するパス。例えば/aaa/bbb.json

$ aws cloudfront list-distributions --profile {profile} | jq '.DistributionList.Items[] | .Id + " " + .Aliases.Items[0]' -r
E************ {hostname}
...

$ aws cloudfront create-invalidation --distribution-id E************ --paths "{path}" --profile {profile}
{
    "Location": "https://cloudfront.amazonaws.com/2020-05-31/distribution/E************/invalidation/I17***********",
    "Invalidation": {
        "Id": "I17***********",
        "Status": "InProgress",
        "CreateTime": "2021-02-22T12:47:09.866Z",
        "InvalidationBatch": {
            "Paths": {
                "Quantity": 1,
                "Items": [
                    "{path}"
                ]
            },
            "CallerReference": "cli-0000000000-000000"
        }
    }
}

$ aws cloudfront get-invalidation --id I17*********** --distribution-id E************ --profile {profile} | jq -r '.Invalidation | .CreateTime + " " + .Status'
2021-02-22T12:47:09.866Z Completed

$ aws cloudfront get-invalidation --id I17*********** --distribution-id E************ --profile {profile}
{
    "Invalidation": {
        "Id": "I17***********",
        "Status": "Completed",
        "CreateTime": "2021-02-22T12:47:09.866Z",
        "InvalidationBatch": {
            "Paths": {
                "Quantity": 1,
                "Items": [
                    "{path}"
                ]
            },
            "CallerReference": "cli-0000000000-000000"
        }
    }
}
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

AWSサービスを擬人化で覚える!主要サービスのまとめ

AWSにはとてもいろんなサービスがあり、AWSの資格試験の勉強をする際には、知らないサービスが出てきて戸惑うことがあるのではないでしょうか。
それぞれのサービスの特徴も文字情報だけでは理解しづらく、概要を掴むことも難しいなんてことも。
AWSを擬人化してサービス説明をすることで、わかりやすくイメージをつかめるようにしようという試みを行ってみました。

TwitterでもAWS擬人化の発信しています。

DNS

Route 53

Route53.jpeg
【AWS擬人化サービス紹介】Route53
(擬人化キャラがサービスの概要や特徴について語るページです)

コンピュート、配信系

EC2とEBS

EC2.jpeg
EC2
クラウド上で動くコンピューター。起動している時間だけお金がかかるので実体のあるPCを購入するより安く済む場合が多く、スペックも変更したいときにすぐ変更できる。AWSの一番基本的なサービス。

EBS
EC2に接続されるストレージ。

【AWS擬人化サービス紹介】EC2とEBS
(擬人化キャラがサービスの概要や特徴について語るページです)

ELB

ELB.jpeg
複数のEC2にリクエストを振り分けるロードバランサー。
ELBの中にレイヤー7で使えるALB、レイヤー4で使えるNLB、古くから存在するCLBの三種類が存在している。
【AWS擬人化サービス紹介】ELB
(擬人化キャラがサービスの概要や特徴について語るページです)

Lambda

Lambda.jpeg
Node.js/Python/Javaなどで書かれたコードをサーバーの準備なしで実行できる。
他のAWSサービスでトリガーを設定し、Lambdaで処理を実行したり、APIGatewayと一緒にサーバーレスアーキテクチャのサービスを作成するのに使える。
【AWS擬人化サービス紹介】Lambda
(擬人化キャラがサービスの概要や特徴について語るページです)

API Gateway

APIGateway.jpeg
HTTPリクエストの受け口としてLambdaと一緒に使われることが多い。RestAPIを作成するのに使う。

CloudFront

CloudFront.jpeg
コンテンツをキャッシュして、オリジンサーバー(EC2など)の代わりに答えてくれるサービス。CloudFrontをつかうことでサーバーの負荷が減るし、ユーザーに近いCloudFrontが答るのでレスポンスも早くなる。DDOS対策やSSL対応もちゃんとできていて高セキュリティー。

ストレージ系

S3

S3.jpeg
データを安く保存できるオブジェクトストレージ。
・容量無制限
・高い耐久性
・安価
・スケーラブルで安定した性能
が特徴
他のサービスの裏側で使われていることもある。
【AWS擬人化サービス紹介】Lambda
(擬人化キャラがサービスの概要や特徴について語るページです)

Glacire

Clacer.jpeg
中長期間保管するデータをS3よりさらに安く保存できるサービス。
S3の1/3ほどの値段で保管できるが、データの取り出しには時間がかかる。
ファイルのアップロードにAWSのSDKを使う必要があったり、アーカイブIDを記録して削除時に指定しなければいけないなど取り扱いがすこし面倒。

EFS

EFS.jpeg
スケーラブルでシンプルなファイルストレージ
・課金は使った分だけ
・勝手に拡張してくれる
・データを複数のAZに分散して保存してくれるので安全な上、同時書き込みにも対応してくれる
という優秀な共有ストレージ(ただしLinuxオンリー)

Docker系

ECS

ECS.jpeg
AWSでDockerを扱うのに便利なサービス。

EKS

EKS.jpeg
Kubenetesのマネージドサービス。

ECR

ECR.jpeg
DockerImageを保管するサービス。

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

【APIGateway+Lambda】APIキーを必要とするAPIでアクセス制限

APIはすでに作成されておりデプロイ状態にある前提とします。

まずは使用量プランをクリック
スクリーンショット (160)_LI.jpg

作成

スクリーンショット (161).png

作成に必要な設定を行います。

このリクエスト数を越えてしまうと
429 Too Many Requests というエラーが出てアクセスができなくなります。

スクリーンショット (162).png

スクリーンショット (163).png

APIキーを作成して使用料プランの作成を終えるとリソースのメソッドリクエストページ、APIχの必要性の欄に注意書きが出ています。

スクリーンショット (164).png

こちらをtrueに切り替えると使用量プランに紐づいたAPIキーがないとこのエンドポイントにはリクエストが届かなくなります。

スクリーンショット (165).png

スクリーンショット (166).png

設定したAPIキーは
APIキー→APIキー名→表示で確認できますのでコピーしておきましょう。

実行

APIキーをヘッダーに含める場合はx-api-key:の後に設定されたキーを追加します。

キーが正しい場合

$ curl  -X POST -H "x-api-key: correct_api_key" https://aj.execute-api.us-east-2.amazonaws.com/default
>> {"message": "Request is Suceeded"}

キーが違う場合

$ curl  -X POST -H "x-api-key: incorrect_api_key" https://xxxxxxx.execute-api.us-east-2.amazonaws.com/default
>> {"message":"Forbidden"}

キーがない場合

$ curl  -X POST https://xxxxxxx.execute-api.us-east-2.amazonaws.com/default
>> {"message":"Forbidden"}
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

APIGatewayにパラメーターを送ってLambdaを実行する

先ずはLambda関数を作成

今回は与えらえた値を返すだけのtest_return_valuablesという
シンプルな関数をPythonで作成します。

スクリーンショット (154).png

APIGatewayでAPIを作成

スクリーンショット (150)_LI.jpg

REST APIを選択し構築。

さらにメソッド作成でPOSTを追加します。
スクリーンショット (158).png

これでPOSTメソッドをAPIとして使用できます。

Lambdaと統合

次にAPIGatewayから実行するLambdaを統合します。

リソースの画面からPOSTをクリック

統合タイプにデフォルトでLambdaが選択されているためそのまま統合したい関数を入力します。

スクリーンショット (157).png

Lambdaの統合はたったこれだけで完了します。

APIGatewayとの統合はシンプルで良いですね

それではこのAPIをデプロイして外部からアクセスできる様にしましょう。

デプロイを忘れるとエンドポイントが作成されていないため、外部からアクセスできません。

リソースを作成してるのにAPIが使えないのは直観ではわかりにくかったです…

スクリーンショット (153)_LI.jpg

ステージ選択→新しいステージを作成→わかりやすい名前で作成(今回はdefault)

それではコンソールからPOSTメソッド指定してリクエストを送ってみます。

ステージ作成時に表示されたAPIエンドポイントへリクエストを送ります

$ curl  -X POST https://xxxxxxx.execute-api.us-east-2.amazonaws.com/default

>> {}

パラメーターが何もないため空欄が返されました。
APIGatewayとLambdaが正常に機能していることが分かります。

しかしこのままクエリパラメータを送ってもLambdaには引数として渡すことはできません。

$ curl  -X POST https://xxxxxxx.execute-api.us-east-2.amazonaws.com/default?name=hoge
>> {}

パラメーターをマッピングしてAWS側で受け取れようにしましょう。

マッピング

リソースの画面で統合リクエストを選択

マッピングテンプレート

スクリーンショット (151)_LI.jpg

新たにマッピングテンプレートを追加します。
application/jsonと入力

スクリーンショット (152).png

上記のように

{
"受け取るパラメーター名": "$input.params('送る際のパラメーター名')"
}
のように記載すると、Lambda関数でevent変数としてパラメーターを使用できるようになります。

$input.paramsはAPIGatewayを使用してパラメーターを送った際に自動的に格納される場所です。

最後にリソースを忘れずにデプロイしましょう!

デプロイされたリソースの反映には少し時間がかかるようなので、時間が経ってから再度更新されたエンドポイントへリクエストを送信

$ curl  -X POST https://aj7i8pust1.execute-api.us-east-2.amazonaws.com/default?name=hoge
>> {"name": "hoge"}

無事パラメーターを送信できました。

アクセスを制限したい場合はapi-keyなども必須にすることもできます。

$ curl  -X POST -H "x-api-key: correct_api_key" https://aj.execute-api.us-east-2.amazonaws.com/default?name=hoge
>> {"name": "hoge"}

key間違い

$ curl  -X POST -H "x-api-key: incorrect_api_key" https://xxxxxxx.execute-api.us-east-2.amazonaws.com/default?name=hoge
>> {"message":"Forbidden"}

keyなし

$ curl  -X POST -https://xxxxxxxx.execute-api.us-east-2.amazonaws.com/default?name=hoge
>> {"message":"Forbidden"}

>> APIキーの設定方法はこちら解説してますのでよろしければご覧くださいー

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

【APIGateway+Lambda】AWS外からのパラメーターを使用する

先ずはLambda関数を作成

今回は与えらえた値を返すだけのtest_return_valuablesという
シンプルな関数をPythonで作成します。

スクリーンショット (154).png

APIGatewayでAPIを作成

スクリーンショット (150)_LI.jpg

REST APIを選択し構築。

さらにメソッド作成でPOSTを追加します。
スクリーンショット (158).png

これでPOSTメソッドをAPIとして使用できます。

Lambdaと統合

次にAPIGatewayから実行するLambdaを統合します。

リソースの画面からPOSTをクリック

統合タイプにデフォルトでLambdaが選択されているためそのまま統合したい関数を入力します。

スクリーンショット (157).png

Lambdaの統合はたったこれだけで完了します。

APIGatewayとの統合はシンプルで良いですね

それではこのAPIをデプロイして外部からアクセスできる様にしましょう。

デプロイを忘れるとエンドポイントが作成されていないため、外部からアクセスできません。

リソースを作成してるのにAPIが使えないのは直観ではわかりにくかったです…

スクリーンショット (153)_LI.jpg

ステージ選択→新しいステージを作成→わかりやすい名前で作成(今回はdefault)

それではコンソールからPOSTメソッド指定してリクエストを送ってみます。

ステージ作成時に表示されたAPIエンドポイントへリクエストを送ります

$ curl  -X POST https://xxxxxxx.execute-api.us-east-2.amazonaws.com/default

>> {}

パラメーターが何もないため空欄が返されました。
APIGatewayとLambdaが正常に機能していることが分かります。

しかしこのままクエリパラメータを送ってもLambdaには引数として渡すことはできません。

$ curl  -X POST https://xxxxxxx.execute-api.us-east-2.amazonaws.com/default?name=hoge
>> {}

パラメーターをマッピングしてAWS側で受け取れようにしましょう。

マッピング

リソースの画面で統合リクエストを選択

マッピングテンプレート

スクリーンショット (151)_LI.jpg

新たにマッピングテンプレートを追加します。
application/jsonと入力

スクリーンショット (152).png

上記のように

{
"受け取るパラメーター名": "$input.params('送る際のパラメーター名')"
}
のように記載すると、Lambda関数でevent変数としてパラメーターを使用できるようになります。

$input.paramsはAPIGatewayを使用してパラメーターを送った際に自動的に格納される場所です。

最後にリソースを忘れずにデプロイしましょう!

デプロイされたリソースの反映には少し時間がかかるようなので、時間が経ってから再度更新されたエンドポイントへリクエストを送信

$ curl  -X POST https://aj7i8pust1.execute-api.us-east-2.amazonaws.com/default?name=hoge
>> {"name": "hoge"}

無事パラメーターを送信できました。

アクセスを制限したい場合はapi-keyなども必須にすることもできます。

$ curl  -X POST -H "x-api-key: correct_api_key" https://aj.execute-api.us-east-2.amazonaws.com/default?name=hoge
>> {"name": "hoge"}

key間違い

$ curl  -X POST -H "x-api-key: incorrect_api_key" https://xxxxxxx.execute-api.us-east-2.amazonaws.com/default?name=hoge
>> {"message":"Forbidden"}

keyなし

$ curl  -X POST -https://xxxxxxxx.execute-api.us-east-2.amazonaws.com/default?name=hoge
>> {"message":"Forbidden"}

>> APIキーの設定方法はこちら解説してますのでよろしければご覧くださいー

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

【AWS】ECSで作ったDocker(Laravel)プロジェクトをRoute53、ALB、ACM、お名前ドットコムを使ってHTTPS化してみた

皆さんこんにちは!

今回はDockerで作ったLaravelプロジェクトをRoute53とALB(ApplicationLoadBalancer)とACM(AmazonCertificateManager)を使ってHTTPS化してみたいと思います!

前提条件

・既にDockerで作ったコンテナをECSで作成していること
・お名前ドットコムでドメインを登録していること

補足

DockerをまだECSで作成していない方は以下の記事をご覧ください。

【AWS】AWS超初心者が、頑張ってDockerで作ったLaravelプロジェクトをECR、ECS、EC2を使ってAWS上で動かしてみた

また、お名前ドットコムでドメインを登録していない方は登録してから本記事をご覧ください。(お名前ドットコムでない場合も可ですが、その場合説明が異なる部分があると思うのでご了承ください)

リッスンポート

nginx/default.conf
server {
    listen 80;
    root /work/laravel/public;
    index index.php;
    charset utf-8;
    error_log /var/log/nginx/error_test.log;

    location / {
        root /work/laravel/public;
        try_files $uri $uri/ /index.php$is_args$args;
    }

    location ~ \.php$ {
        fastcgi_split_path_info ^(.+\.php)(/.+)$;
        fastcgi_pass app:9000;
        fastcgi_index index.php;
        include fastcgi_params;
        fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
        fastcgi_param PATH_INFO $fastcgi_path_info;
    }
}

nginxのコンテナではlisten 80;としているように、80番のポートをリッスンしています。

ここが443になっている場合は適時変えて頂くか、上記のようにlisten 80;としてください。

参考記事

本記事を書くにあたって下記の記事を参考させて頂きました。

AWSでWebサイトをHTTPS化 その1:ELB(+ACM発行証明書)→EC2編

僕が説明不十分なところもあるので、分からない点がある場合はこちらの記事を見て頂くとよいかと。

それでは早速説明していきます!!

ACMでSSL証明書の発行

まず初めにHTTPS化するには、SSL証明書の発行を行います。

AWSはこのSSL証明書の発行が無料となっております。(AWS神)

サービス検索欄で「CertificateManager」を入力しましょう。

  1. 「証明書のリクエスト」をクリック
  2. 「パブリック証明書のリクエスト」を選択
  3. ドメイン名を入力(この後Route53で登録するドメインを入力。現段階ではRoute53にECS用のドメインを登録していないので、お好きなドメインをご入力ください。以下、説明用としてここで入力したドメイン名をwww.example.comとします。)
  4. 「DNSの検証」を選択
  5. タグは登録してもしなくてもどちらでもいいです
  6. 「確定とリクエスト」をクリック

image.png

すると画像のように名前や値が表示されます。

これをお名前ドットコムで登録します。

image.png

「ドメインのDNS設定」から「DNSレコード設定を利用する」をクリック

無題.png

そして画像のように先ほどCertificateManagerで発行した名前(ホスト名)と値(VALUE)を登録します。(画像のホスト名や値は適当です)

そしてAWSに戻ってRoute53で先ほどCertificateManagerで登録したドメイン名のホストゾーンを作成します。例で言うとwww.example.comと言う名前で登録します。

※注意 既にホストゾーンを作成している場合は、新たにホストゾーンを作成しないでください。後ほど、既に作成してあるホストゾーンで先ほど作成したドメイン名をレコード名として作成してください。

そしたら、作成したホストゾーンの「レコードを作成」をクリック。

タイプを「CNAME」にしてお名前ドットコムで登録したときと同じように名前と値を入れて下さい。

CertificateManagerに戻り、「状況」が「発行済み」になればOK!(時間がかかる場合があります)

ALBでHTTPS登録

サービス検索欄で「ECS」と検索し、左のメニュー欄の「ロードバランシング」にある「ロードバランサー」をクリック。

「ロードバランサーの作成」をクリック。

  1. 「Application Load Balancer(HTTP、HTTPS)」を選択
  2. 手順1:名前を入力し、「ロードバランサーのプロトコル」をHTTPSにする(ポート番号が443になる)。「アベイラビリティーゾーン」の「VPC」はECSインスタンスで使用しているVPCを選択。「アベイラビリティーゾーン」にいくつかの候補が出るのですべてにチェック
  3. 手順2:「証明書タイプ」で「ACMから証明書を選択する」にチェック。「証明書の名前」で先ほど作成した証明書を選択
  4. 手順3:「新しいセキュリティグループを作成する」にチェック。適当にグループ名を入力し、「タイプ」を「HTTPS」にする
  5. 手順4:名前を適当に入力し、プロトコルは「HTTP」を選択
  6. 手順5:利用するインスタンスを選択し「登録済みに追加」をクリック
  7. 手順6:「作成」をクリック

無事作成されればOK!

EC2インスタンスのセキュリティ登録

これで最後になるので、あともう一息頑張りましょう!

サービス検索欄で「EC2」と検索。

左のメニューの「インスタンス」の「インスタンス」をクリック。

利用するインスタンスの「インスタンスID」をクリック。

無題.png

下にある「セキュリティ」タブから「セキュリティグループ」をクリック。

下の「インバウンドルール」から「インバウンドルールを編集」をクリック。

「タイプ」は「HTTP」、「ソース」は先ほど作成したALBのグループ名を選択。

「ルールを保存」をクリック。

これで、独自ドメインかつHTTPS化されたサイトにアクセスすることができます。

例で言うとhttps://www.example.comにアクセスするとDockerで作ったLaravelのサイトが開くようになります。

いかがだったでしょうか??

少し説明不足のところもあると思うので、何かご不明な点があれば遠慮せずにコメント欄にてお申し付けください。

以上、「【AWS】ECSで作ったDocker(Laravel)プロジェクトをRoute53、ALB、ACM、お名前ドットコムを使ってHTTPS化してみた」でした!

良ければ、LGTM、コメントお願いします。

また、何か間違っていることがあればご指摘頂けると幸いです。

他にも初心者さん向けに記事を投稿しているので、時間があれば他の記事も見て下さい!!

あと、最近「ココナラ」で環境構築のお手伝いをするサービスを始めました。

気になる方はぜひ一度ご相談ください!

Thank you for reading

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

PHPでAWS S3からディレクトリ単位でダウンロード

前提条件

AWS SDK for PHP 3.x を利用

やってみた感想

CommandPool利用のために配列を作成する必要がなく
コードもシンプルになるのでよい

AWS S3 バケットを再帰的にダウンロード

同期転送

sample.php
<?php

use Aws\S3\S3Client;
use Aws\S3\Transfer;

$client = new S3Client([
    'region'  => '****',
    'version' => 'latest',
]);

// from
$source = 's3://bucket/foo';
// to ローカルディレクトリのパス
$dest   = '/path/to/destination/dir';

$manager = new Transfer(
    $client,
    $source,
    $dest,
);
$manager->transfer();

非同期転送

sample.php
<?php

use Aws\S3\S3Client;
use Aws\S3\Transfer;

$client = new S3Client([
    'region'  => '****',
    'version' => 'latest',
]);

// from
$source = 's3://bucket/foo';
// to ローカルディレクトリのパス
$dest   = '/path/to/destination/dir';

$manager = new Transfer(
    $client,
    $source,
    $dest,
);

$promise = $manager->promise();
$promise
    ->then(function () {
        echo 'Done!';
    })
    ->otherwise(function ($reason) {
        echo 'Transfer failed';
    });

参考

Amazon S3バージョン 3 での AWS SDK for PHP Transfer Manager

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

Github Actions を使って AWS の S3 へデプロイする

Github Actions を使って AWS の S3 へデプロイするための環境設定手順を記載します

S3 バケットの作成

アップロードする先の S3 バケットを作成しておきましょう

AWS IAM の作成

S3 へアクセス可能な IAM ユーザーを作成します

  1. AWS IAM へ遷移する
  2. アクセス管理のユーザーへ遷移する
  3. ユーザーを追加ボタンを押下する
  4. ユーザー名に適当な名前「github」などを入力し、「プログラムによるアクセス」にチェックを付けて次のステップボタンを押下する
  5. アクセス許可の設定へ遷移するので、「既存のポリシーを直接アタッチ」を選択して「AmazonS3FullAccess」にチェックを付けて次のステップボタンを押下する
  6. タグの追加画面に遷移するので、次のステップボタンを押下する
  7. ユーザーの作成確認画面に遷移するので、ユーザーの作成ボタンを押下する
  8. ユーザーが作成されたら、「アクセスキー ID」「シークレットアクセスキー」をメモするか、.csvのダウンロードをしておく

Github リポジトリの Secrets へ AWS 接続情報を登録

Github リポジトリの Secrets へ AWS 接続情報を登録します

  1. S3 へアップロードする Github リポジトリの Settings を選択する
  2. Secrets メニューへ遷移する
  3. Actions secrets で、New repository secret ボタンを押下する
  4. 以下の内容で各追加する
Name Value
AWS_ACCESS_KEY_ID (作成したIAMユーザーのアクセスキーID)
AWS_SECRET_ACCESS_KEY (作成したIAMユーザーのシークレットアクセスキー)
S3_BUCKET (アップロードする先の S3 バケット名)

Github Actions 用のワークフローを定義

  1. Github で Actions へ遷移し、「set up a workflow yourself」のリンクをクリックする
  2. Edit new file に以下の内容を記載して、Start commit ボタンを押下し、コミットテキスト「Github Actions の設定を追加」などを入力して Commit new file ボタンを押下する
name: Amazon S3 Upload

on:
  push:
    branches:
      - master

jobs:
  build:
    runs-on: ubuntu-latest

    steps:
      - name: Checkout
        uses: actions/checkout@v2

      - name: Configure AWS credentials
        uses: aws-actions/configure-aws-credentials@v1
        with:
          aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }}
          aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
          aws-region: ap-northeast-1

      - name: Upload to S3
        env: 
          S3_UPLOAD_BUCKET: ${{ secrets.S3_BUCKET }}
        run: |
          aws s3 sync . s3://$S3_UPLOAD_BUCKET/ --delete --exclude "README.md" --exclude ".git/*" --exclude ".github/*" --exclude ".gitignore"

これで master ブランチへファイルをPUSHするごとに、S3 へファイルがアプロードされます

ワークフローの状態は、Github リポジトリの Actions へ遷移してみてください

プルリクエストマージ時にしたい場合や、S3 アップ後に CloudFront のキャッシュを削除したいなど、場合によってワークフローの定義を編集してください

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

AWS CodeCommit の使いづらい点

背景

AWSのサービスということもあり、コードレビューの自動化CI/CD等AWSの他のサービスと組み合わせたアーキテクトが便利というCodeCommit。
これまでリポジトリ管理にGitBucketやGitHubを使ってきましたが、CodeCommitを始めて使いずらいと感じた点を少ないですがまとめました。

使いづらい点

遅い

どの操作をするにも体感遅いです。これは時と場合によるかも。

プルリクのコメントが改行されない

全て1行で表示されてしまい見にくいです。
image.png

差分を表示できない

エラー『違いを表示できません。個別のファイルが大きすぎて表示できないか、ファイル間の全体的な違いが複雑すぎます。』と表示される場合がある。これは致命的です。ソース管理を奇麗にしろとも取れますが、基準が曖昧ですし不親切に感じます。
追記:ファイルの行数を3250行以下にしないと当該エラーが発生する。開発チームに連携した上で対応有無・時期未定とAWS公式回答。
cf. AWS CodeCommit のクォータ
cf. 公式フォーラムで未解決らしい
image.png

プルリクエストに対して、マージ先の最新のソースを取り込む機能がない

GitBucketにあったこんな機能です。これがないとレビューの度に最新のソースを取り込んでからPUSHし直してもらう必要があったりします。

image.png

因みにGitBucketの場合に、同じ個所に表示される競合(コンフリ)が発生した際のUIも分かりやすくて好きです。
image.png

別のリポジトリ管理を使う

完全プライベートリポジトリに絞ると、GitLab?(CodeGuruには対応していない)とかでしょうか。これいいよというのがあればご教授頂きたいです。

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

RailsアプリをAWSで自動デプロイ【ステップ2 DBの構築】

はじめに

最近Rilsのアプリケーションをデプロイする機会がありましたので、その方法を忘れない内に書き込みます。
何記事に分けて説明してます。
この記事では、RDSの構築まで解説します。

現在のAWSの構成

スクリーンショット 2021-02-18 10.59.24.png

RDSの構築

RDSとは、AWSのフルマネージドなリレーショナルデータベースのサービスです。

スクリーンショット 2021-02-25 11.45.05.png

プライベートサブネットの作成

VPC:ステップ1で作成したVPCを指定します。
サブネット名:sample-privatesubnet-c
アベイラビリティーゾーン:アジアパシフィック (東京) / ap-northeast-1c
IPv4 CIDR ブロック:10.0.21.0/24

セキュリティーグループ作成

セキュリティグループ名:sample-infra-db
説明:sample-infra-db
VPC:ステップ1で作成したVPCを指定します。

インバウンドルール

タイプ プロトコル ポート範囲 ソース 説明
MYSQL/Aurora TCP 3306 ステップ1で作成したセキュリティーグループを指定

DBサブネットグループの作成

以下のリンクに移動します。
https://console.aws.amazon.com/rds/

スクリーンショット 2021-02-25 11.20.22.png

スクリーンショット 2021-02-25 11.21.30.png

名前:sample-infra-subnet-group
説明:sample-infra-subnet-group
VPC:ステップ1で作成したVPCを指定します。

ステップ1、2で作成したプライベートサブネットの追加を行います。

スクリーンショット 2021-02-18 11.38.40.png

DBパラメーターグループの作成

DBパラメーターグループとは、DBのパラメーターの設定をテンプレートとして登録できるサービス

スクリーンショット 2021-02-25 11.50.20.png

スクリーンショット 2021-02-25 11.21.44.png

パラメータグループファミリー:mysql8.0
グループ名:aws-infra-mysql80
説明:aws-infra-mysql80

DBオプショングループの作成

オプショングループとは、DBの機能的部分を設定できるサービス

スクリーンショット 2021-02-25 11.50.20のコピー.png

スクリーンショット 2021-02-25 11.21.54.png

名前:aws-infra-mysql80
説明:aws-infra-mysql80
エンジン:mysql
メジャーエンジンバージョン:8.0

RDSの作成

スクリーンショット 2021-02-25 11.50.20のコピー2.png

スクリーンショット 2021-02-25 11.22.15.png

エンジンのオプション

エンジンのタイプ:MySQL 
バージョン:MySQL8.0.21

テンプレート

開発テスト #今回はテスト用で作成するので、開発テスト用を選択しました。

設定

DB インスタンス識別子:sample-infra-web
認証情報の設定:
マスターユーザー名:root
パスワードの自動生成:✅

DB インスタンスサイズ

DB インスタンスクラス:バースト可能クラス
db.t3.micro

ストレージ

ストレージタイプ:汎用SSD
ストレージ割り当て:20
ストレージの自動スケーリング:無効

可用性と耐久性

マルチ AZ 配置:スタンバイインスタンスを作成しない

接続

Virtual Private Cloud (VPC):VPCを指定
サブネットグループ:ステップ2で作成したものを指定
パブリックアクセス可能:なし
VPC セキュリティグループ:既存の選択
既存の VPC セキュリティグループ:ステップ2で作成したセキュリテーグループを指定
アベイラビリティーゾーン:ap-northeast-1a
追加の接続設定:
データベースポート:3306

追加設定

最初のデータベース名:
DB パラメータグループ:aws-infra-mysql80
オプショングループ情報:aws-infra-mysql80
自動バックアップの有効化:✅
バックアップ保持期間:30日

バックアップウィンドウ:選択ウィンドウ
開始時間:21:00 #日本時間の午前6時に開始
期間:0.5

スナップショットにタグをコピー:✅
暗号を有効化:✅
マイナーバージョン自動アップグレード:✅

メンテナンスウィンドウ:選択ウィンドウ
開始日:日曜日
開始時間:20:00 
期間:0.5

削除保護:✅

ここまで設定が完了しましたら、作成を行います!

最後に

本記事では、RDSの構築までを解説しました。
次回は、アプリをデプロイするところまで解説しようと思います。

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

【 Ruby on Rails 6.0 】AWS + Nginx + Unicornでデプロイ⑤

始めに

前回まででEC2上に必要なGemをインストールし本番環境用に環境変数を設定しました。今回はHTTP通信を設定しRailsアプリを起動する工程までをまとめたいと思います。

目次

目次 内容
セクション1 EC2インスタンス作成
セクション2 Linuxサーバー構築
セクション3 データベース設定
セクション4 EC2上でGemをインストールし環境変数を設定
セクション5 Railsアプリを起動(今回の内容)
セクション6 Nginxの導入

ポート開放

立ち上げたばかりのEC2インスタンスはSSHでアクセスすることはできますが、HTTPなどの他の通信方法では一切つながらないようになっています。そのため、WEBサーバとして利用するEC2インスタンスは事前にHTTPがつながるように「ポート」を開放する必要があります。

セキュリティグループのポートを設定

AWSのEC2インスタンス一覧画面から、対象のインスタンスを選択し、「セキュリティグ
ループ」のリンクをクリックします。
スクリーンショット 2021-02-25 10.11.11.png
すると、インスタンスの属するセキュリティグループの設定画面に移動するので、「イン バウンド」タブの中の「編集」をクリックします。
スクリーンショット 2021-02-25 10.14.07.png
モーダルが開くので、「ルールの追加」をクリックします。

タイプ カスタムTCPルール」
プロトコル TCP
ポート範囲 3000
送信元 カスタム、0.0.0.0/0

「0.0.0.0」は「全てのアクセスを許可する」という意味です。

以上で、ポートの開放が完了です。

database.ymlの本番環境の設定を編集

本番環境のmysqlの設定に合わせるため、ローカルのdatabase.ymlを以下のように編集して下さい。

config/database.yml
production:
  <<: *default
  database: ここは編集しないこと
  username: root
  password: <%= ENV['DATABASE_PASSWORD']
  socket: /var/lib/mysql/mysql.sock

ローカルでの編集をコミットして、GitHubにプッシュ

リモートリポジトリが更新されたため、サーバ上のアプリケーションにも反映させましょう。今回はすでにEC2とGithubは接続できているため、git pullコマンドを利用します。
※別にブランチを切っている場合は、masterブランチにmergeしてから以下のコマンドを 実行しましょう。

ターミナル(EC2)
[ec2-user@ip-172-31-23-189 <app名>]$ git pull origin master

データベースを作成しマイグレーションを実行

ターミナル(EC2)
[ec2-user@ip-172-31-23-189 <app名>]$ rails db:create RAILS_ENV=production
[ec2-user@ip-172-31-23-189 <app名>]$ rails db:migrate RAILS_ENV=production

もしここでMysql2::Error: Can't connect to local MySQL server through socket '/var/lib/mysql/mysql.sock' というエラーが起こった場合、データベース が起動していない可能性があります。sudo systemctl start mariadbというコマン ドをターミナルから打ち込み、mysqlの起動を試してみましょう。

アセットファイルをコンパイル

続いて、アセットファイルをコンパイルします。
アセットファイルとは、画像・CSS・ JavaScript等を管理しているファイルです。
コンパイルとはアセットファイルを圧縮し、 そのデータを転送するということです。
この作業を行わないと、本番環境でCSSが反映されずにビューが崩れてしまったり、エラーでブラウザが表示されない、などの問題が生じてしまいます。

ターミナル(EC2)
[ec2-user@ip-172-31-23-189 <アプリ名>]$ rails assets:precompile RAILS_ENV=production

# 成功すると
Yarn executable was not detected in the system.
Download Yarn at https://yarnpkg.com/en/docs/install
I, [2020-01-18T12:51:01.4345644 #1265]  INFO -- : Writing /var/app/web-share/public/assets/member_photo_noimage_thumb-224a733c50d48aba6d9fdaded809788bbeb5ea5f6d6b8368adaebb95e58bcf53.png
I, [2020-01-18T12:51:02.2615123#1265]  INFO -- : Writing /var/app/appname/public/assets/application-bc071e28a78e2b63c9313afed5ad3476e00e3f0e5b12445c37214d1f1317be48.js
I, [2020-01-18T12:51:02.2626434 #1265]  INFO -- : Writing /var/app/appname/public/assets/application-bc071e28a78e2b63c9313afed5ad3476e00e3f0e5b12445c37214d1f1317be48.js.gz
I, [2020-01-18T12:51:08.484546 #1265]  INFO -- : Writing /var/app/appname/public/assets/application-8549fb9a804686e593d5c0f90a2412a39de85908e5fb58fdf6681d4b0073d891.css
I, [2020-01-18T12:51:08.485454 #1265]  INFO -- : Writing /var/app/appname/public/assets/application-8549fb9a804686e593d5c0f90a2412a39de85908e5fb58fdf6681d4b0073d891.css.gz

ここでyarnのエラーが発生したらnode.jsをupdateします。

Node.jsのアップデート

Node.jsのバージョン管理ツールnvmを使用してインストールします。

ターミナル(EC2)
# 現在のバージョン確認
[ec2-user@ip-172-31-23-189 <アプリ名>]$ node -v
v4.9.1

# Node.jsのバージョン管理ツールnvmをclone
[ec2-user@ip-172-31-23-189 <アプリ名>]$ git clone git://github.com/creationix/nvm.git ~/.nvm
[ec2-user@ip-172-31-23-189 <アプリ名>]$ echo . ~/.nvm/nvm.sh >> ~/.bashrc
[ec2-user@ip-172-31-23-189 <アプリ名>]$ . ~/.bashrc

# nvmバージョン確認
[ec2-user@ip-172-31-23-189 <アプリ名>]$ nvm --version
0.35.0

# インストールできるNode.jsの確認
[ec2-user@ip-172-31-23-189 <アプリ名>]$ nvm ls-remote

# 最新の安定版をインストール
[ec2-user@ip-172-31-23-189 <アプリ名>]$ nvm install stable

# バージョン確認
[ec2-user@ip-172-31-23-189 <アプリ名>]$ node -v
v12.12.0 # バージョンが最新になっていたら成功

もう一度コンパイルを実行してみましょう。

Unicornのプロセスを確認

コンパイルが成功したら反映を確認するため、Railsを再起動します。しかし、まずは今動 いているUnicornをストップします。そのために、Unicornのプロセスを確認し、プロセスを止めます。ターミナルからプロセスを確認するにはpsコマンドを利用します。

ターミナル
# unicorn起動
[ec2-user@ip-172-31-38-126 <リポジトリ名>]$ bundle exec unicorn_rails -c config/unicorn.rb -E production -D

[ec2-user@ip-172-31-23-189 <リポジトリ名>]$ ps aux | grep unicorn

ec2-user 17877  0.4 18.1 588472 182840 ?       Sl   01:55   0:02 unicorn_rails master -c config/unicorn.rb -E production -D
ec2-user 17881  0.0 17.3 589088 175164 ?       Sl   01:55   0:00 unicorn_rails worker[0] -c config/unicorn.rb -E production -D
ec2-user 17911  0.0  0.2 110532  2180 pts/0    S+   02:05   0:00 grep --color=auto unicorn

大事なのは左から2番目の列です。ここに表示されるのがプロセスのid、つまりPIDになります。
「unicorn_rails master」と表示されているプロセスがUnicornのプロセス本体です。この時のPIDは、17877となっています。

killコマンドを入力してUnicornのプロセスを停止

ターミナル
[ec2-user@ip-172-31-23-189 <リポジトリ名>]$ kill <確認したunicorn rails masterのPID>

# 再度確認する
[ec2-user@ip-172-31-23-189 <リポジトリ名>]$ ps aux | grep unicorn
...
ec2-user 17911  0.0  0.2 110532  2180 pts/0    S+   02:05   0:00 grep --color=auto unicorn

# できない場合は強制終了する
[ec2-user@ip-172-31-23-189 <リポジトリ名>]$ kill -9 [プロセスID]

先頭にRAILS_SERVE_STATIC_FILES=1をつけて、unicornを起動

続いて再びunicornを起動しましょう。このときRAILS_SERVE_STATIC_FILES=1という指定を先頭に追加してください。これは、コンパイルされたアセットをRailsが見つけられるような指定になります。以下のようにコマンドを実行してください。

ターミナル
[ec2-user@ip-172-31-23-189 <リポジトリ名>]$ RAILS_SERVE_STATIC_FILES=1 unicorn_rails -c config/unicorn.rb -E production -D

ブラウザで確認

ブラウザで http://:3000/ にアクセスして、サイトが正常に表示されているか確認してみましょう。

Railsの起動がうまくできなかった時

上記のコマンドを実行してもRailsが起動しないときや、起動できてもIPアドレス:3000に
アクセスするとエラーが表示されていることがあります。

以下の項目をチェックしてみてください。

  • pushのし忘れ、またはEC2サーバ側でのpullのし忘れは無いか
  • ローカルでの編集のpushやEC2でのgit pullを忘れていないか
  • データベースの起動は正しく行えているか
  • EC2サーバ側のSECRET_KEY_BASE等は正しく設定できているか
  • EC2インスタンスの再起動を行ってみる

unicornのログを確認する

上記のポイントでも解決出来ない場合はunicornのログを確認してみましょう。
lessコマンドまたはcatコマンドを使えばログを見ることが出来ます。

ターミナル(EC2)
[ec2-user@ip-172-31-23-189 <app名>]$ less log/unicorn.stderr.log

# 実行結果
I, [2021-02-21T02:28:26.245480 #7257]  INFO -- : Refreshing Gem list
I, [2021-02-21T02:28:28.232692 #7257]  INFO -- : listening on addr=0.0.0.0:3000 fd=9
E, [2021-02-21T02:28:28.245079 #7257] ERROR -- : Unknown database 'app_production' (ActiveRecord::NoDatabaseError)

ログはEnterキーを押せば下にスクロールすることが出来ます。(下にいくほど最新のログです。)
上の例ではUnknown databaseとなっているためrails db:createをし忘れている可能生があります。
もしくはdatabase.ymlの設定に誤りがあるかもしれません。
このようにログを頼りに原因を特定していきます。

終わりに

今回の内容までで、Elastic IPアドレスを入力してブラウザ上でアプリが起動していることを確認出来ました。
次回はユーザーのリクエストに対してレスポンスを送れるようにWebサーバーを導入していきます。

次回
Nginxの導入

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

EC2 サーバー構築(基本設定)

EC2 サーバー構築

概要

EC2インスタンスを初期に立ち上げた際にすることをまとめてみました。
過不足あれば今後編集していきたいと思います。

環境

  • Amazon Linux2

システム設定

yumのパッケージ更新

sudo yum -y update

タイムゾーン・ロケール設定

タイムゾーン確認

timedatectl status

タイムゾーンを日本時間に設定

sudo timedatectl set-timezone Asia/Tokyo

ロケール確認

localectl status

ロケール変更

sudo localectl set-locale LANG=ja_JP.UTF-8

ニックネーム設定

ホスト名に影響を与えずにシェルプロンプトを変更する
参考

1. 環境変数定義

$ sudo sh -c 'echo "export NICKNAME={ニックネーム}" > /etc/profile.d/prompt.sh'
$ sudo sh -c 'echo "export NICKNAME=app01" > /etc/profile.d/prompt.sh'

2. シェルプロンプトの設定編集

$ sudo vi /etc/bashrc

\h (hostname を表す記号) を NICKNAME 変数の値に変更

/etc/bashrc
 [ "$PS1" = "\\s-\\v\\\$ " ] && PS1="[\u@\h \W]\\$ "[ "$PS1" = "\\s-\\v\\\$ " ] && PS1="[\u@\$NICKNAME \W]\\$ "

3. シェルウィンドウのタイトルを新しいニックネームに設定

# ファイル作成
sudo touch /etc/sysconfig/bash-prompt-xterm

#  実行権限付与
$ sudo chmod +x /etc/sysconfig/bash-prompt-xterm

# ファイル編集
$ sudo vi /etc/sysconfig/bash-prompt-xterm
/etc/sysconfig/bash-prompt-xterm
echo -ne "\033]0;${USER}@${NICKNAME}:${PWD/#$HOME/~}\007"
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

AWSにデプロイ後、よく使うコマンド

EC2にSSHで接続し、git pullしてからよく使うコマンドまとめました。

  • 使用頻度が多いものを自分用に簡単にまとめました。

環境

rails 5.2.4
ruby 2.6.3
Cloud9
MySQL

AWSの構成

スクリーンショット 2021-02-25 8.15.49.png

EC2にSSHで接続する方法
$ ssh -i ~/.ssh/キー名.pem ec2-user@xx.xx.xx.xx

Nginxの再起動する方法
$ sudo systemctl restart nginx

アプリ(puma)起動する方法
$ rails s -e production

アプリ(puma)停止する方法
$ kill プロセスID
どちらも同じです
$ kill $(cat tmp/pids/puma.pid)
本番環境でbundle installする時のコマンド
$ bundle install --path vendor/bundle --without test development

CSS・JS変更時に使うコマンド
$ bundle exec rails assets:precompile RAILS_ENV=production

本番環境でrails db:migrateする時のコマンド
$ bundle exec rails db:migrate RAILS_ENV=production

seeds.rb編集した場合は、本番環境のデータベースを削除してからやり直す方がいいです。
本番環境のデータはなくなるので使う際はご自身で判断してください。

$ RAILS_ENV=production DISABLE_DATABASE_ENVIRONMENT_CHECK=1 bundle exec rails db:drop
$ mysql -u root -p -h エンドポイント
mysql> CREATE DATABASE 作成したいデータベース名;
$ bundle exec rails db:migrate RAILS_ENV=production
$ bundle exec rails db:seed RAILS_ENV=production
nginxエラーログ確認するコマンド
$ sudo tail -f /var/log/nginx/error.log

railsのエラーログ確認するコマンド
$ sudo tail -f log/production.log

全体の把握に時間がかかりたくさんのエラーを経験し心が折れそうになりました。
何度もEC2作り直ししましたのでAWSの知識もより深まりました。
今回は、S3を使っていないため今度はS3を使って構成することを考えてます?

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

Fargate とは?

勉強前イメージ

ECSと関連してる感じはするけど、
ECSの中の機能の一つ・・とかかな?

調査

Fargate とは?

Amazon ECSとAmazon EKSでコンテナを実行する際の起動タイプの1つになります。
Amazon ECSについての詳細は こちら
ECSの概要はDockerコンテナを簡単に実行・停止出来る管理サービスになります。
そのDockerコンテナの起動タイプには以下2つがあり、そのうちの1つになります。

  • EC2インスタンス
  • Fargate

以下はECSでクラスタを作成する際の画面です。

1Amazon ECS - Google Chrome 2021-02-24 22.11.20.png

Fargate のメリット

  • デプロイ時にインスタンス選定の必要がない

コンテナ実行時にCPU・メモリの組み合わせを選択するだけで構築・運用に集中することが出来ます。
サーバの管理が不要になり、本来の作業に集中出来ます。

  • キャパシティコントロールについて

コンテナの起動・スケーリングについては
Auto Scallingで調整されます。

勉強後イメージ

EC2かFargateか・・・ってことか。
Fargateの方が楽なのは楽そうだね。

参考

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

OpenCVをAWS Lambda + Python + Serverless Frameworkで動かす

OpenCVをAWS Lambda + Python + Serverless Frameworkで動かしてみました。

先日、PillowをLambdaで動かす記事を書きましたが、このときと違って、OpenCVはyumでインストールの必要なshared objectに依存しているのでだいぶ面倒でした。

手順概要

  1. serverless-python-requirements インストール
  2. Pythonサンプルコードを記述
  3. requirements.txt と serverless.yml と Dockerfile にOpenCV動作に必要な事項を記述
  4. あとはデプロイ

OpenCV特有は3のみです。

手順詳細

serverless-python-requirements インストール

AWS Lambda + Python + Serverless FrameworkにPythonのパッケージをインストールする方法は以前の記事に書きました。

これに従って、まずは serverless create して、serverless-python-requirementsプラグインをインストールします。

$ serverless create --template aws-python3

$ serverless plugin install -n serverless-python-requirements

ServerlessFrameworkのバージョンはv2.18.0でした。

Pythonソースコード

handler.py の内容です。OpenCVを参照できることを確認できる最小限です。

import cv2

def hello(event, context):
    print("Hellow, OpenCV!")
    print(cv2.__version__)

requirements.txt

OpenCVのパッケージ名を記述します。この1行のみです。

opencv-python

serverless.yml

serverless.yml の記載がもっとも面倒でした。成功例を書きます。

service: sample

frameworkVersion: '2'

provider:
  name: aws
  runtime: python3.8
  lambdaHashingVersion: 20201221
  region: ap-northeast-1

functions:
  hello:
    handler: handler.hello
    events:
      - httpApi: "*"

plugins:
  - serverless-python-requirements

custom:
  pythonRequirements:
    dockerizePip: true
    dockerFile: Dockerfile
    dockerExtraFiles:
      - /usr/lib64/libGL.so.1
      - /usr/lib64/libgthread-2.0.so.0
      - /usr/lib64/libglib-2.0.so.0
      - /usr/lib64/libGLX.so.0
      - /usr/lib64/libX11.so.6
      - /usr/lib64/libXext.so.6
      - /usr/lib64/libGLdispatch.so.0
      - /usr/lib64/libxcb.so.1
      - /usr/lib64/libXau.so.6

Dockerfile

Dockerfile を作成します。serverless.ymlからファイル名で参照しています。

FROM lambci/lambda:build-python3.8

RUN yum install -y mesa-libGL

デプロイと実行

デプロイ。

$ serverless deploy -v

デプロイされたLambdaを実行するとCloudWatch Logsに以下が出力されました。

Hellow, OpenCV!
4.5.1

serverless.yml を書くまでの道のり

最初は以下だけで動かそうとしました。

service: sample

frameworkVersion: '2'

provider:
  name: aws
  runtime: python3.8
  lambdaHashingVersion: 20201221
  region: ap-northeast-1

functions:
  hello:
    handler: handler.hello

plugins:
  - serverless-python-requirements

これでデプロイしてLambdaを実行すると、CloudWatch Logsに以下のエラーが吐かれました。

[ERROR] Runtime.ImportModuleError: Unable to import module 'handler': libGL.so.1: cannot open shared object file: No such file or directory

libGL.so.1 というファイルが不足しているので、これを追加すればよいのですが、これは環境に依存していそうなので、手元にある同じファイル名をコピーしただけではたぶん動きません。Lambdaの動くAmazon Linux環境でこのファイルを用意する必要があります。

これをするためにserverless.yml にdockerの記述をします。以下の記述です。

custom:
  pythonRequirements:
    dockerizePip: true
    dockerFile: Dockerfile
    dockerExtraFiles:
      - ...

Dockerfileも用意します。

FROM lambci/lambda:build-python3.8

RUN yum install -y mesa-libGL # OpenCVに必要なパッケージをインストール

これを書くだけでserverlessがデプロイ時にDockerを起動して、Lambdaの動くAmazon Linux環境を再現し、その中でyumインストールしてくれます。serverless.ymldockerExtraFilesに記載したファイルを、yumインストール後に抜き出して、Lambdaデプロイイメージに同梱してくれます。

dockerExtraFilesに書いたリストは、デプロイして実行時のエラーメッセージから1つずつ書き足して、成功するまで繰り返しました。

エラーメッセージにはsoファイル名しか表示されませんので、以下のコマンドでLambdaの動くAmazon Linux環境の中に入ってみて、yum install -y mesa-libGLしてから、soファイルのありかを探しました。

$ docker run -it --rm lambci/lambda:build-python3.8 bash

Amazon Linux上では /usr/lib64/libGL.so.1/usr/lib64/libGL.so.1.7.0 へというように、すべてシンボリックリンクになっていますが、serverless.ymlには実態ではなくシンボリックリンクだけ記述すれば動きました。

注意事項

ここに書いているsoファイルのリストはサンプルPythonコードを動かすために最小限のものです。エラーメッセージを見て、足りないsoファイルを追加するというのを繰り返しましたのみです。従ってOpenCVのすべての動作がこれだけで足りてるかどうかはわかりません。

ハマりどころ1

.serverless/requirements/の中にLambdaのイメージが展開されるのですが、Dockerで構築されるためか、soファイルがroot権限になり、試行錯誤の過程で serverless.yml の変更が権限不足で反映できないというトラブルがありました。原因がわかればroot権限でそのディレクトリを削除することで解決しましたが、それに気が付くまで時間をだいぶ消耗しました。

ハマりどころ2

serverlessが内部でDockerを利用するため、serverless自体をDockerの中で動かしたらデプロイ時にDockerでエラーになりました。Dockerのvolumeも使っていたので、Dockerのsocket共有でもうまくいかず、あきらめました。

ハマりどころ3

最初はLambdaのLayerにOpenCVを入れたかったのですが、LD_LIBRARY_PATH がLayerには通っていないため、OpenCVを動作させることはできませんでした。

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

【 Ruby on Rails 6.0 】AWS + Nginx + Unicornでデプロイ④

始めに

前回の記事ではEC2インスタンスにmariaDBというデータベースの設定を行いました。今回はインスタンス上でRailsアプリの起動に必要なGemをインストールし環境変数を設定する工程までをまとめたいと思います。

目次

目次 内容
セクション1 EC2インスタンス作成
セクション2 Linuxサーバー構築
セクション3 データベース設定
セクション4 EC2上でGemをインストールし環境変数を設定(今回の内容)
セクション5 Railsアプリを起動
セクション6 Nginxの導入

EC2のサーバにアプリのコードをクローン

全世界に公開できるIPアドレスを持ったEC2サーバ上でRailsアプリを動かすためにアプリケーションのコードをGithubからEC2サーバへクローンします。

GithubにSSH鍵を登録

現状、EC2サーバにアプリケーションのコードをクローンしようとしても permission deniedとエラーが出てしまいます。これは、Githubから見てこのEC2インスタンスが何者かわからないためです。

EC2インスタンスからGithubにアクセスするためには、作成したEC2インスタンスのSSH 公開鍵をGithubに登録する必要があります。 SSH鍵をGithubに登録すると、Githubはそれを認証に利用し、コードのクローンを許可してくれるようになります。

ターミナル
[ec2-user@ip-172-31-23-189 ~]$ ssh-keygen -t rsa -b 4096

# 三段階ほど認証を求められるが全てyesでenterを押す

Enter file in which to save the key (/home/ec2-user/.ssh/id_rsa):
Enter passphrase (empty for no passphrase): 
Enter same passphrase again:

# 以下の表示が出れば成功

Your identification has been saved in /home/ec2-user/.ssh/id_rsa.
Your public key has been saved in /home/ec2-user/.ssh/id_rsa.pub.
The key fingerprint is:
3a:8c:1d:d1:a9:22:c7:6e:6b:43:22:31:0f:ca:63:fa ec2-user@ip-172-31-23-189
The key's randomart image is:
+--[ RSA 4096]----+
|    +            |
| . . =           |
|  = . o .        |
| * o . o         |
|= *     S        |
|.* +     .       |
|  * +            |
| .E+ .           |
| .o              |
+-----------------+

# .SSH公開鍵を表示し、値をコピーするため、下記コマンドを実装
[ec2-user@ip-172-31-23-189 ~]$ cat ~/.ssh/id_rsa.pub

# ssh~から最後の文字列までをコピーする
ssh-rsa AAAAB3Nza・・・・・

以下のURLからGithubにアクセスします。
https://github.com/settings/keys
アクセスしたら以下の画像のように操作します。
スクリーンショット 2021-02-25 4.06.19.png

スクリーンショット 2021-02-25 4.12.11.png
Githubに鍵を登録できたら、SSH接続できるか以下のコマンドで確認してみましょう。

ターミナル
[ec2-user@ip-172-31-23-189 ~]$ ssh -T git@github.com

# 下記の表示が出たらyesを選択

The authenticity of host 'github.com (IP ADDRESS)' can't be established.
RSA key fingerprint is 16:27:ac:a5:76:28:2d:36:63:1b:56:4d:eb:df:a6:48.
Are you sure you want to continue connecting (yes/no)?

# 成功したら下記の表示が出る

[ec2-user@ip-172-31-23-189 ~]$ ssh -T git@github.com
Hi <Githubユーザー名>! You've successfully authenticated, but GitHub does not provide shell access.

# エラーが出たらログインし直してもう一度ssh接続する

Warning: Permanently added the RSA host key for IP address 'XXXXXXXXX' to the list of known hosts.

アプリケーションサーバの設定

アプリケーションサーバとは、ブラウザからの「リクエスト」を受け付けRailsアプリケ ーションを実際に動作させるソフトウェアのことです。
アプリケーションサーバが動いていれば、ブラウザからのリクエストを受け付けてRails アプリケーションが動作します。
という訳で、全世界に公開するEC2サーバ上でもアプリケーションサーバを動かす必要が あるのです。今回はUnicornというアプリケーションサーバーを使用します。

Unicorn

全世界に公開されるサーバ上で良く利用されるアプリケーションサーバです。rails sコマンドの代わりに unicorn_rails コマンドで起動することができます。
この後、EC2サーバにSSH接続しUnicornを起動することで全世界からアクセスできるようにしていきます。

Unicornをインストール

UnicornはRubyで作成されており、gem化されています。なのでローカルのGemfileを編集しましょう。

Gemfile
# 追記(本番環境)
group :production do
  gem 'unicorn', '5.4.1' # バージョン指定
end
ターミナル(ローカル)
$ bundle install

config/unicorn.rbを作成し、内容を以下のように編集

Unicornの設定ファイルとして、次の内容でファイルを作成しましょう。最初からは存在していないので、自分でconfig ディレクトリ以下に作成します。
この後すぐ、ファイルの中身がそれぞれ何を行なっているか説明しますので、まずはコピ ー&ペーストで作成したファイルに貼り付けましょう。

config/unicorn.rb
app_path = File.expand_path('../../', __FILE__)

#アプリケーションサーバの性能を決定する
worker_processes 1

#アプリケーションの設置されているディレクトリを指定
working_directory app_path

#Unicornの起動に必要なファイルの設置場所を指定
pid "#{app_path}/tmp/pids/unicorn.pid"

#ポート番号を指定
listen 3000

#エラーのログを記録するファイルを指定
stderr_path "#{app_path}/log/unicorn.stderr.log"

#通常のログを記録するファイルを指定
stdout_path "#{app_path}/log/unicorn.stdout.log"

#Railsアプリケーションの応答を待つ上限時間を設定
timeout 60

#以下は応用的な設定なので説明は割愛

preload_app true
GC.respond_to?(:copy_on_write_friendly=) && GC.copy_on_write_friendly = true

check_client_connection false

run_once = true

before_fork do |server, worker|
  defined?(ActiveRecord::Base) &&
    ActiveRecord::Base.connection.disconnect!

  if run_once
    run_once = false # prevent from firing again
  end

  old_pid = "#{server.config[:pid]}.oldbin"
  if File.exist?(old_pid) && server.pid != old_pid
    begin
      sig = (worker.nr + 1) >= server.worker_processes ? :QUIT : :TTOU
      Process.kill(sig, File.read(old_pid).to_i)
    rescue Errno::ENOENT, Errno::ESRCH => e
      logger.error e
    end
  end
end

after_fork do |_server, _worker|
  defined?(ActiveRecord::Base) && ActiveRecord::Base.establish_connection
end

変更修正をリモートリポジトリに反映

ここまで、ローカルのフォルダ内で変更修正を行ったので、こちらをリモートリポジトリへ反映します。変更修正をコミットしてプッシュしましょう。
この時必ず、masterブランチで行うようにしてください。もし、別ブランチでコミット&プッシュした場合は、リモートリポジトリでプルリクエストを作成し、ブランチをmasterへマージしてください。

Githubからコードをクローン

続いて、Unicornの設定を済ませたコードをEC2インスタンスにクローンします。

/var/wwwディレクトリを作成し、権限をec2-userに変更

ターミナル(EC2)
#/var/wwwディレクトリを作成(後述するCapistranoの初期値がwwwなので、ディレクトリをwwwに設定しています)
[ec2-user@ip-172-31-23-189 ~]$ sudo mkdir /var/www/

#作成したwwwディレクトリの権限をec2-userに変更
[ec2-user@ip-172-31-23-189 ~]$ sudo chown ec2-user /var/www/

Githubから「リポジトリURL」を取得

スクリーンショット 2021-02-25 4.29.50.png
取得した「リポジトリURL」を使って、コードをクローンします。

ターミナル(EC2)
[ec2-user@ip-172-31-23-189 ~]$ cd /var/www/
[ec2-user@ip-172-31-23-189 www]$ git clone https://github.com/リポジトリURL

# 成功したら以下の表示が出る

remote: Enumerating objects: 298, done.
remote: Counting objects: 100% (298/298), done.
remote: Compressing objects: 100% (190/190), done.
remote: Total 298 (delta 109), reused 274 (delta 86), pack-reused 0
Receiving objects: 100% (298/298), 58.53 KiB | 365.00 KiB/s, done.
Resolving deltas: 100% (109/109), done.

EC2の能力を拡張

現状動かしているEC2のインスタンスではコンピューターの能力が足りず、Gemのインストール時などにエラーが発生する可能性があります。具体的には、コンピューターの処理能力に関係するメモリというものが足りません。これは、無料で動かせるインスタンスの限界であるため仕方ありません。
そこで、今後の設定を行う前にメモリを増強する処理を行います。

ターミナル
# ホームディレクトリに移行
[ec2-user@ip-172-31-25-189 ~]$ cd ~
[ec2-user@ip-172-31-25-189 ~]$ sudo dd if=/dev/zero of=/swapfile1 bs=1M count=512

# 成功すると以下の表示が出る

512+0 レコード入力
512+0 レコード出力
536870912 バイト (537 MB) コピーされました 5.19011  103 MB/

# 次は権限に制限をかけましょう(chmodコマンド)
[ec2-user@ip-172-31-25-189 ~]$ sudo chmod 600 /swapfile1

# スワップ(swap)領域を作成する - mkswap
[ec2-user@ip-172-31-25-189 ~]$ sudo mkswap /swapfile1

#成功すると下記の表示が出ます
スワップ空間バージョン1を設定しますサイズ = 524284 KiB
ラベルはありません, UUID=74a961ba-7a33-4c18-b1cd-9779bcda8ab1

# スワップ(swap)領域を有効化する - swapon
[ec2-user@ip-172-31-25-189 ~]$ sudo swapon /swapfile1
[ec2-user@ip-172-31-25-189 ~]$ sudo sh -c 'echo "/swapfile1  none        swap    sw              0   0" >> /etc/fstab'

gemをインストール

ターミナル(EC2)
# まずは、EC2にダウンロードしたWEB Appを開く
[ec2-user@ip-172-31-23-189 www]$ cd  /var/www/アプリ名

# Rubyのバージョンを確認する
[ec2-user@ip-172-31-23-189 <アプリ名>]$ ruby -v

# 指定したrubyのバージョンが表示されれば成功です。
ruby 2.5.1p57 (2018-03-29 revision 63029) [x86_64-linux]

本番環境でgemを管理するための bundlerをインストール

まず開発環境(ローカル)で開発してきたアプリにおいて、どのバージョンの bundlerが使われていたのか確認します。

ターミナル(ローカル)
$ bundler -v

# するとバージョンが表示されます
Bundler version 2.1.4 # 人によってバージョンが違う可能性があります

開発環境で仕様しているbundlerのバージョンがわかったので、同じバージョンのものを EC2サーバ側にも導入します。上記の場合では、bundler 2.1.4のバージョンを導入してbundle installを実行します。

ターミナル(EC2)
# ローカルで確認したbundlerのバージョンを導入する
[ec2-user@ip-172-31-23-189 <アプリ名>]$ gem install bundler -v 2.1.4
Fetching bundler-2.1.4.gem
Successfully installed bundler-2.1.4
Parsing documentation for bundler-2.1.4
Installing ri documentation for bundler-2.1.4
Done installing documentation for bundler after 3 seconds
1 gem installed

# 上記コマンドは、数分以上かかる場合もあります。
[ec2-user@ip-172-31-23-189 <アプリ名>]$ bundle install

環境変数の設定

データベースのパスワードなどセキュリティのためにGithubにアップロードすることがで きない情報は、環境変数というものを利用して設定します。
環境変数は、Railsからは ENV['<環境変数名>'] という記述でその値を利用することができます。今回は、SECRET_KEY_BASE という環境変数を指定していきます。

secret_key_baseを作成

ターミナル(EC2)
[ec2-user@ip-172-31-23-189 <アプリ名>]$ rake secret

# うまくいくと、
cdfasdfadgfsadfdgc314751a8dadfadf7c8b9a1dc888e...
という感じで表示されます
これをコピーしておきましょう

環境変数は /etc/environment というファイルに保存することで、サーバ全体に適用さ れます。環境変数の書き込みはvimコマンドを使用して行います。

ターミナル
[ec2-user@ip-172-31-23-189 <アプリ名>]$ sudo vim /etc/environment

スクリーンショット 2021-02-25 4.43.33.png
上の様な画面になれば、iと打ち込んで入力モードに切り替えた後、下記の記述を打ち込みます。 = の前後にスペースは入れません。

/etc/environment
DATABASE_PASSWORD='データベースのrootユーザーのパスワード'
SECRET_KEY_BASE='先程コピーしたsecret_key_base'

書き込みができたら esc(エスケープキー)を押下後、:wq と入力して内容を保存します。 保存できたら環境変数を適用するために一旦ログアウトします。

ターミナル(EC2)
[ec2-user@ip-172-31-23-189 <アプリ名>]$ exit
logout
Connection to XX.XXX.XXX.XX closed.

# もう一度ログイン
$ ssh -i ダウンロードした鍵の名前.pem ec2-user@Elastic IPアドレス

# 設定した環境変数が適用されているか確認
$ env | grep SECRET_KEY_BASE
SECRET_KEY_BASE='XXXXXXXXXXXXXXXXXXXXXXXXX'

$ env | grep DATABASE_PASSWORD
DATABASE_PASSWORD='XXXXXXXXXXXXX'

これで環境変数が設定出来ました!

終わりに

ここまでで、EC2インスタンスにSSHログインしてアクセスすることが出来ました。
次回でHTTP通信を可能にしてRailsアプリを起動させる工程まで進めます。
お疲れさまでした。。。

次回
Railsアプリを起動

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

MacでM5stack Core2 for AWS その2

0. はじめに

前回はQiitaを書くのに疲れてしまい、
投稿はESP-IDFまでと中途半端に終わってしまったので
今回はLチカまで進めます。
ドキュメントはここのAWS CLIのインストールからです。

例によってエラーとの格闘です:ghost:

1. AWS CLIインストール

AWSアカウントも何もないところからだと、ちと面倒ですが、
ココを乗り越えないと先に進めませんので、
ドキュメント通りにAWSのアカウント作成、AWS CLIのインストール、
aws configureを行います

2. Minicondaインストール

ドキュメント通り進めます。
私はココのPython3.8のpkgをインストールしました。

ドキュメントにある、edukit環境作成とedukit環境への切り替えは
下の通りうまくいきました

(base) オレ@MacBook ~ % conda create -n edukit python=3.7
Collecting package metadata (current_repodata.json): done
Solving environment: done

## Package Plan ##

  environment location: /Users/オレ/opt/miniconda3/envs/edukit

  added / updated specs:
    - python=3.7


The following packages will be downloaded:

    package                    |            build
    ---------------------------|-----------------
    ca-certificates-2021.1.19  |       hecd8cb5_0         121 KB
    certifi-2020.12.5          |   py37hecd8cb5_0         140 KB
    openssl-1.1.1j             |       h9ed2024_0         2.2 MB
    pip-21.0.1                 |   py37hecd8cb5_0         1.8 MB
    python-3.7.9               |       h26836e1_0        19.7 MB
    readline-8.1               |       h9ed2024_0         333 KB
    setuptools-52.0.0          |   py37hecd8cb5_0         721 KB
    wheel-0.36.2               |     pyhd3eb1b0_0          33 KB
    ------------------------------------------------------------
                                           Total:        25.0 MB

The following NEW packages will be INSTALLED:

  ca-certificates    pkgs/main/osx-64::ca-certificates-2021.1.19-hecd8cb5_0
  certifi            pkgs/main/osx-64::certifi-2020.12.5-py37hecd8cb5_0
  libcxx             pkgs/main/osx-64::libcxx-10.0.0-1
  libedit            pkgs/main/osx-64::libedit-3.1.20191231-h1de35cc_1
  libffi             pkgs/main/osx-64::libffi-3.3-hb1e8313_2
  ncurses            pkgs/main/osx-64::ncurses-6.2-h0a44026_1
  openssl            pkgs/main/osx-64::openssl-1.1.1j-h9ed2024_0
  pip                pkgs/main/osx-64::pip-21.0.1-py37hecd8cb5_0
  python             pkgs/main/osx-64::python-3.7.9-h26836e1_0
  readline           pkgs/main/osx-64::readline-8.1-h9ed2024_0
  setuptools         pkgs/main/osx-64::setuptools-52.0.0-py37hecd8cb5_0
  sqlite             pkgs/main/osx-64::sqlite-3.33.0-hffcf06c_0
  tk                 pkgs/main/osx-64::tk-8.6.10-hb0a8c7a_0
  wheel              pkgs/main/noarch::wheel-0.36.2-pyhd3eb1b0_0
  xz                 pkgs/main/osx-64::xz-5.2.5-h1de35cc_0
  zlib               pkgs/main/osx-64::zlib-1.2.11-h1de35cc_3


Proceed ([y]/n)? y


Downloading and Extracting Packages
setuptools-52.0.0    | 721 KB    | ##################################### | 100% 
certifi-2020.12.5    | 140 KB    | ##################################### | 100% 
wheel-0.36.2         | 33 KB     | ##################################### | 100% 
ca-certificates-2021 | 121 KB    | ##################################### | 100% 
readline-8.1         | 333 KB    | ##################################### | 100% 
python-3.7.9         | 19.7 MB   | ##################################### | 100% 
openssl-1.1.1j       | 2.2 MB    | ##################################### | 100% 
pip-21.0.1           | 1.8 MB    | ##################################### | 100% 
Preparing transaction: done
Verifying transaction: done
Executing transaction: done
#
# To activate this environment, use
#
#     $ conda activate edukit
#
# To deactivate an active environment, use
#
#     $ conda deactivate

次に環境の移動

(base) オレ@MacBookAir ~ % conda activate edukit
(edukit) オレ@MacBookAir ~ %

(base)から(edukit)に変わりました。
が、次のexport.shでまたコケました

(edukit) オレ@MacBookAir ~ % . $HOME/esp/esp-idf/export.sh 
Setting IDF_PATH to '/Users/オレ/esp/esp-idf'
Adding ESP-IDF tools to PATH...
Using Python interpreter in /Users/オレ/opt/miniconda3/envs/edukit/bin/python
Checking if Python packages are up to date...
The following Python requirements are not satisfied:
click>=5.0
pyserial>=3.0
future>=0.15.2
cryptography>=2.1.4
pyparsing>=2.0.3,<2.4.0
pyelftools>=0.22
gdbgui==0.13.2.0
pygdbmi<=0.9.0.2
reedsolo>=1.5.3,<=1.5.4
bitstring>=3.1.6
ecdsa>=0.16.0
Please follow the instructions found in the "Set up the tools" section of ESP-IDF Getting Started Guide
Diagnostic information:
    IDF_PYTHON_ENV_PATH: (not set)
    Python interpreter used: /Users/オレ/opt/miniconda3/envs/edukit/bin/python
    Warning: python interpreter not running from IDF_PYTHON_ENV_PATH
    PATH: /Users/オレ/.espressif/tools/xtensa-esp32-elf/
〜〜〜以下略〜〜〜

Getting Started Guideを読みやがれと。。。
う〜ん、まあなんか
IDF_PYTHON_ENV_PATH: (not set)
が怪しそうだな。。。と思いつつも先に進める。。。

3. デバイス証明書の取得と登録

(edukit) オレ@MacBookAir % cd Core2-for-AWS-IoT-EduKit/Blinky-Hello-World/utilities/AWS_IoT_registration_helper
(edukit) オレ@MacBookAir AWS_IoT_registration_helper % pip3 install -r requirements.txtRequirement already satisfied: awscli>=1.18.202 in /Users/オレ/opt/miniconda3/envs/edukit/lib/python3.7/site-packages (from -r requirements.txt (line 1)) (1.19.11)
Requirement already satisfied: cryptography>=2.7 in /Users/オレ/opt/miniconda3/envs/edukit/lib/python3.7/site-packages (from -r requirements.txt (line 2)) (3.4.6)
Requirement already satisfied: pyasn1_modules==0.1.5 in /Users/オレ/opt/miniconda3/envs/edukit/lib/python3.7/site-packages (from -r requirements.txt (line 3)) (0.1.5)
〜〜〜中略〜〜〜
Requirement already satisfied: chardet<5,>=3.0.2 in /Users/オレ/opt/miniconda3/envs/edukit/lib/python3.7/site-packages (from requests->requests-aws4auth==1.0.1->-r requirements.txt (line 10)) (4.0.0)
Requirement already satisfied: certifi>=2017.4.17 in /Users/オレ/opt/miniconda3/envs/edukit/lib/python3.7/site-packages (from requests->requests-aws4auth==1.0.1->-r requirements.txt (line 10)) (2020.12.5)
(edukit) オレ@MacBookAir AWS_IoT_registration_helper %

なんかうまくいった模様
早速、デバイス証明書の取得と登録
シリアルデバイスは前のページと同じく
/dev/cu.usbserial-0225F023
を指定

(edukit) オレ@MacBookAir AWS_IoT_registration_helper % python registration_helper.py -p /dev/cu.usbserial-0225F023 
Pyserial is not installed for /Users/オレ/opt/miniconda3/envs/edukit/bin/python. Check the README for installation instructions.
Traceback (most recent call last):
  File "registration_helper.py", line 42, in <module>
    import esptool
ModuleNotFoundError: No module named 'esptool'

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "registration_helper.py", line 49, in <module>
    import esptool
  File "/Users/オレ/esp/esp-idf/components/esptool_py/esptool/esptool.py", line 38, in <module>
    import serial
ModuleNotFoundError: No module named 'serial'

またエラー。。。
モジュールがないだけなので、何も考えずserialとesptoolをインストール!

〜〜〜まずはserial〜〜〜

(edukit) オレ@MacBookAir AWS_IoT_registration_helper % pip install serial
Collecting serial
  Downloading serial-0.0.97-py2.py3-none-any.whl (40 kB)
     |████████████████████████████████| 40 kB 4.5 MB/s 
Collecting future>=0.17.1
  Using cached future-0.18.2.tar.gz (829 kB)
Requirement already satisfied: pyyaml>=3.13 in /Users/オレ/opt/miniconda3/envs/edukit/lib/python3.7/site-packages (from serial) (5.3.1)
Collecting iso8601>=0.1.12
  Downloading iso8601-0.1.14-py2.py3-none-any.whl (9.5 kB)
Building wheels for collected packages: future
  Building wheel for future (setup.py) ... done
  Created wheel for future: filename=future-0.18.2-py3-none-any.whl size=491059 sha256=52d0697b9ade772839886084076f64bc586b6c0869c69f501ce868c4d720f95a
  Stored in directory: /Users/オレ/Library/Caches/pip/wheels/56/b0/fe/4410d17b32f1f0c3cf54cdfb2bc04d7b4b8f4ae377e2229ba0
Successfully built future
Installing collected packages: iso8601, future, serial
Successfully installed future-0.18.2 iso8601-0.1.14 serial-0.0.97

〜〜〜つづいて esptool 〜〜〜

(edukit) オレ@MacBookAir AWS_IoT_registration_helper % pip install esptool
Collecting esptool
  Downloading esptool-3.0.tar.gz (149 kB)
     |████████████████████████████████| 149 kB 9.1 MB/s 
Collecting bitstring>=3.1.6
  Using cached bitstring-3.1.7.tar.gz (195 kB)

〜〜〜中略〜〜〜

Successfully built esptool bitstring reedsolo
Installing collected packages: reedsolo, pyserial, bitstring, esptool
Successfully installed bitstring-3.1.7 esptool-3.0 pyserial-3.5 reedsolo-1.5.4

インストール完了!
ということで、再度チャレンジ

(edukit) オレ@MacBookAir AWS_IoT_registration_helper % python registration_helper.py -p /dev/cu.usbserial-0225F023

〜〜〜なんかちょっとwarning...笑〜〜〜

Conda 'edukit' environment active...
Python 3.7.x detected...
AWS CLI configured for IoT endpoint: xxxxxxxxxxxxxx-ats.iot.us-west-2.amazonaws.com
Checking module (1 of 13): awscli>=1.18.202

〜〜〜中略〜〜〜

Checking module (2 of 13): cryptography>=2.7
Requirement already satisfied: cryptography>=2.7 in /Users/オレ/opt/miniconda3/envs/edukit/lib/python3.7/site-packages (3.4.6)

〜〜〜13 of 13まで略〜〜〜

-----------------------------------------
Completed checking/installing package dependencies

Generating ECDSA 256-bit prime field key...
Generating self-signed x.509 certificate...
Successfully created x.509 certificate with expiration in 365 days...
Connecting....
Changing baud rate to 921600
Changed.
RAM boot...
Downloading 31364 bytes at 3ffb0000... done!
Downloading 456 bytes at 3ffb8f28... done!
Downloading 1028 bytes at 40080000... done!
Downloading 107384 bytes at 40080404... done!
Downloading 4 bytes at 4009a77c... done!
All segments done, executing at 40081bf0
Wait for init
- CLI Initialised
>>

>>

Serial Number:
012345678901234567
Generating Manifest
>>

Crypto Authentication Root CA 002
-----BEGIN CERTIFICATE-----
MIIB8TCCAZegAwIBAgIQd9NtlW7IrmI

〜〜〜中略〜〜〜MG1TrVv7HhhfdFyhYmA==
-----END PUBLIC KEY-----

Validate Device Certificate:
OK

012345678901234567
reading slot 0 public key
>>

reading slot 1 public key
>>

reading slot 2 public key
>>

reading slot 3 public key
>>

reading slot 4 public key
>>



Generated the manifest file 012345678901234567_manifest.json in output_files
Created policy Default
Number of certificates: 1

Loading the manifest_item...
    Unique ID: 012345678901234567

Try importing certificate...
Response: {'ResponseMetadata': {'RequestId': 'なんか', 'HTTPStatusCode': 200, 'HTTPHeaders': {'date': 'Fri, 19 Feb 2021 15:54:26 GMT', 'content-type': 'application/json', 'content-length': '209', 'connection': 'keep-alive', 'x-amzn-requestid': 'なんか', 'access-control-allow-origin': '*', 'x-amz-apigw-id': 'a__P5HbyPHcF6FA=', 'x-amzn-trace-id': 'Root=なんか'}, 'RetryAttempts': 0}, 'certificateArn': 'arn:aws:iot:us-west-2:なんか:cert/なんか', 'certificateId': 'なんか'}
Certificate import complete - returning
MANIFEST_IMPORT     SUCCESS arn:aws:iot:us-west-2:なんか:cert/なんか  arn:aws:iot:us-west-2:なんか:thing/012345678901234567

Number of ThingIDs to check: 1
Checking the manifest item(1)
    Unique ID: 012345678901234567
Manifest was loaded successfully

おお、うまくいったようです〜!

4. ESP32ファームウェアの更新

(edukit) オレ@MacBookAir AWS_IoT_registration_helper % cd ../..
(edukit) オレ@MacBookAir Blinky-Hello-World % aws iot describe-endpoint --endpoint-type iot:Data-ATS
{
    "endpointAddress": "xxxxxxxxxxxxxx-ats.iot.us-west-2.amazonaws.com"
}

上で表示されたエンドポイントを控えておきます
xxxxxxxxxxxxxx-ats.iot.us-west-2.amazonaws.com ←これ

で、Kconfigによる設定

(edukit) オレ@MacBookAir Blinky-Hello-World % idf.py menuconfig            
The following Python requirements are not satisfied:
pyparsing>=2.0.3,<2.4.0
pyelftools>=0.22
gdbgui==0.13.2.0
pygdbmi<=0.9.0.2
Please follow the instructions found in the "Set up the tools" section of ESP-IDF Getting Started Guide
Diagnostic information:
    IDF_PYTHON_ENV_PATH: (not set)
    Python interpreter used: /Users/オレ/opt/miniconda3/envs/edukit/bin/python
    Warning: python interpreter not running from IDF_PYTHON_ENV_PATH
    PATH: /Users/オレ/.espressif/tools/

〜〜〜中略〜〜〜

ESP-IDF v4.2-238-g8cd16b60f

むー、またGuideを見やがれが出てConfig画面でない。。。
どうやら先にあったIDF_PYTHON_ENV_PATHがないのが気に入らないらしい。
が、そもそも何を設定するんだ???
ディレクトリを歩き回り、
/Users/オレ/opt/miniconda3/envs/edukit
こんなのがあったので、とりあえず

(edukit) オレ@MacBookAir Blinky-Hello-World % export IDF_PYTHON_ENV_PATH="/Users/オレ/opt/miniconda3/envs/edukit"

気を取り直して

(edukit) オレ@MacBookAir Blinky-Hello-World % idf.py menuconfig
The following Python requirements are not satisfied:
pyparsing>=2.0.3,<2.4.0
pyelftools>=0.22
gdbgui==0.13.2.0
pygdbmi<=0.9.0.2
To install the missing packages, please run "/Users/オレ/esp/esp-idf/install.sh"
Diagnostic information:
    IDF_PYTHON_ENV_PATH: /Users/オレ/opt/miniconda3/envs/edukit
    Python interpreter used: /Users/オレ/opt/miniconda3/envs/edukit/bin/python

ESP-IDF v4.2-238-g8cd16b60f

お、さっきと違うエラー。
install.shを実行せよと。

(edukit) オレ@MacBookAir Blinky-Hello-World % /Users/オレ/esp/esp-idf/install.sh
Installing ESP-IDF tools
Installing tools: xtensa-esp32-elf, xtensa-esp32s2-elf, esp32ulp-elf, esp32s2ulp-elf, openocd-esp32
Skipping xtensa-esp32-elf@esp-2020r3-8.4.0 (already installed)

〜〜〜中略〜〜〜

Installing Python environment and packages
Creating a new Python environment in /Users/オレ/.espressif/python_env/idf4.2_py3.7_env

〜〜〜お、IDF_PYTHON_ENV_PATHに使えそうなのが表示された〜〜〜

Installing virtualenv
Collecting virtualenv

〜〜〜中略〜〜〜

Successfully built Flask-Compress
Installing collected packages: MarkupSafe, Werkzeug, python-engineio, Jinja2, itsdangerous, click, bidict, python-socketio, pycparser, greenlet, Flask, brotli, six, Pygments, pygdbmi, gevent, Flask-SocketIO, Flask-Compress, cffi, reedsolo, pyserial, pyparsing, pyelftools, gdbgui, future, ecdsa, cryptography, bitstring
Successfully installed Flask-0.12.5 Flask-Compress-1.9.0 Flask-SocketIO-2.9.6 Jinja2-2.11.3 MarkupSafe-1.1.1 Pygments-2.8.0 Werkzeug-0.16.1 bidict-0.21.2 bitstring-3.1.7 brotli-1.0.9 cffi-1.14.5 click-7.1.2 cryptography-3.4.6 ecdsa-0.16.1 future-0.18.2 gdbgui-0.13.2.0 gevent-1.5.0 greenlet-1.0.0 itsdangerous-1.1.0 pycparser-2.20 pyelftools-0.27 pygdbmi-0.9.0.2 pyparsing-2.3.1 pyserial-3.5 python-engineio-4.0.0 python-socketio-5.0.4 reedsolo-1.5.4 six-1.15.0
All done! You can now run:

  . /Users/オレ/esp/esp-idf/export.sh

(edukit) オレ@MacBookAir Blinky-Hello-World %

なんかうまくいったっぽい
export.shを実行せよとのことなので

. /Users/オレ/esp/esp-idf/export.sh
Adding ESP-IDF tools to PATH...
Using Python interpreter in /Users/オレ/.espressif/python_env/idf4.2_py3.7_env/bin/python
Checking if Python packages are up to date...
Python requirements from /Users/オレ/esp/esp-idf/requirements.txt are satisfied.
Updated PATH variable:

〜〜〜中略〜〜〜

Done! You can now compile ESP-IDF projects.
Go to the project directory and run:

  idf.py build

(edukit) オレ@MacBookAir Blinky-Hello-World %

今度はさらっとexport.shが完了!
この時点でIDF_PYTHON_ENV_PATHを確認すると

(edukit) オレ@MacBookAir Blinky-Hello-World % echo $IDF_PYTHON_ENV_PATH
/Users/オレ/.espressif/python_env/idf4.2_py3.7_env

おぉ、ちゃんと設定されている!
ということは、Minicondaをインストールしたときに
export.shを実行する前に、適当なIDF_PYTHON_ENV_PATHを設定して
install.shを実行すればよかっただけな予感。。。:sweat:

というわけで再度チャレンジ!

(edukit) オレ@MacBookAir Blinky-Hello-World % idf.py menuconfig
Executing action: menuconfig

やっとでましたよ〜Config画面!
スクリーンショット 2021-02-20 1.41.50.png

ここからはドキュメント通り、
先ほど控えておいたエンドポイントと自宅のWifi設定を入れて保存後に終了
すると同時に

Running cmake in directory /Users/オレ/m5stack/Core2-for-AWS-IoT-EduKit/Blinky-Hello-World/build
Executing "cmake -G Ninja -DPYTHON_DEPS_CHECKED=1 -DESP_PLATFORM=1 -DCCACHE_ENABLE=0 /Users/オレ/m5stack/Core2-for-AWS-IoT-EduKit/Blinky-Hello-World"...
-- Found Git: /usr/bin/git (found version "2.24.2 (Apple Git-127)") 
-- IDF_TARGET not set, using default target: esp32
-- The C compiler identification is GNU 8.4.0
-- The CXX compiler identification is GNU 8.4.0
-- The ASM compiler identification is GNU

〜〜〜中略〜〜〜

-- Configuring done
-- Generating done
-- Build files have been written to: 

〜〜〜以下略〜〜〜

無事Configできたっぽい

ではBuildを!

(edukit) オレ@MacBookAir Blinky-Hello-World % idf.py build
Executing action: all (aliases: build)
Running ninja in directory /Users/オレ/m5stack/Core2-for-AWS-IoT-EduKit/Blinky-Hello-World/build
Executing "ninja all"...
[0/1] Re-running CMake...
-- Building ESP-IDF components for target esp32

〜〜〜なんとか走り始めました! ここから結構時間がかかります〜〜〜

[1244/1244] Generating binary image from built executable
esptool.py v3.0
Generated /Users/オレ/m5stack/Core2-for-AWS-IoT-EduKit/Blinky-Hello-World/build/AWS_IoT_EduKit-Blinky-Hello-World.bin

Project build complete. To flash, run this command:
/Users/オレ/.espressif/python_env/idf4.2_py3.7_env/bin/python ../../../esp/esp-idf/components/esptool_py/esptool/esptool.py -p (PORT) -b 460800 --before default_reset --after hard_reset --chip esp32  write_flash --flash_mode dio --flash_size detect --flash_freq 80m 0x1000 build/bootloader/bootloader.bin 0x8000 build/partition_table/partition-table.bin 0x10000 build/AWS_IoT_EduKit-Blinky-Hello-World.bin
or run 'idf.py -p (PORT) flash'

おぉ、ついにbinができあがりました!
転送する前にドキュメント通りに古いファームを消します

(edukit) オレ@MacBookAir Blinky-Hello-World % idf.py erase_flash -p /dev/cu.usbserial-0225F023 
Executing action: erase_flash

〜〜〜中略〜〜〜

esptool.py v3.0
Serial port /dev/cu.usbserial-0225F023
Connecting........___
Chip is ESP32-D0WDQ6-V3 (revision 3)
Features: WiFi, BT, Dual Core, 240MHz, VRef calibration in efuse, Coding Scheme None
Crystal is 40MHz
MAC: 24:0a:c4:f9:9f:ac
Uploading stub...
Running stub...
Stub running...
Changing baud rate to 460800
Changed.
Erasing flash (this may take a while)...
Chip erase completed successfully in 26.2s
Hard resetting via RTS pin...
Done

きえました!
では、転送します!

(edukit) オレ@MacBookAir Blinky-Hello-World % idf.py flash monitor -p /dev/cu.usbserial-0225F023 
Executing action: flash

〜〜〜中略(しばし待ちます)〜〜〜

I (7508) esp_netif_handlers: sta ip: xxx.xxx.xxx.xxx, mask: 255.255.255.0, gw: xxx.xxx.xxx.xxx
I (7528) Blinky: Connecting to AWS IoT Core...
I (7708) aws_iot: Attempting to use device certificate from ATECC608
I (20048) Blinky: Successfully connected to AWS IoT Core!
I (20048) Blinky: Subscribing...
I (20398) Blinky: Subscribed to topic: 012345678901234567/#
I (20398) Blinky: 
I (20398) Blinky: **************************************
I (20398) Blinky: Client Id - 012345678901234567
I (20408) Blinky: **************************************

やっとAWSに接続できました!!!

5. Lチカ

もうあとは簡単です。
ドキュメント通りにAWS IoT Coreコンソールで状態確認!
IoT_Dashboard.png

Publishの入力画面で
<Client ID>/blink
をtopicにpublishすると
M5Stackの横にあるLEDが点滅し、
もう一回同じようにpublishすると点灯状態になります!

L_CHIKA480.gif

Macのターミナルではこんな感じでモニターすることができます
(4回publishしています)

I (635748) Blinky: Subscribe callback
I (635748) Blinky: 012345678901234567/blink {
  "message": "Hello from AWS IoT console"
}
I (650488) Blinky: Subscribe callback
I (650488) Blinky: 012345678901234567/blink {
  "message": "Hello from AWS IoT console"
}
I (731598) Blinky: Subscribe callback
I (731598) Blinky: 012345678901234567/blink {
  "message": "Hello from AWS IoT console"
}
I (738968) Blinky: Subscribe callback
I (738968) Blinky: 012345678901234567/blink {
  "message": "Hello from AWS IoT console"
}

6. とりあえず

IoTの勉強というよりも、環境設定のラボのようですが
とりあえずLチカのラボ終了!

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

Cognitoのロックアウトの条件洗い出してみた

ロックアウトとは

サインインに連続して失敗した場合、一時的または永久的にアカウントを使用できないようにする仕組みです。
ほぼ同じ意味の「アカウントロック」と言ったほうがピンとくる人は多いのですかね。
馴染みがあるものだと、iPhone のロック画面がこの仕組みになっています。
サインインを必要としているシステムには、ブルートフォースアタックの対策として入れておきたい仕組みです。

Amazon Cognito にはあるのか

AWS の認証のサービスでお馴染みの Amazon Cognito さん。
このサービスは、全く知らない人でも画面をポチポチやっていれば簡単に構築できちゃいますし、Amplify をつかえば、さらに簡単に使えちゃうサービスになっております!(ただ詳しく知ろうとすると難しいんですよねー...)
さて、この AWS を使っていれば認証として多く利用されているであろう Cognito にはロックアウトはあるのかですが、

答えは「あります」
Amazon Cognito 開発者ガイドの最初あたりの注記に記載されていました。
Cognitoは永久的なロックアウトはなく、一時的なロックアウトみたいです。

あれ、、、思ったよりも情報が結構書かれていたんだけど、、、
前調べたときは全然情報がなく、ロックされる条件や期間については内部仕様だから公開していないよ!!的な感じだったようなきがするんですが、、、
あ、この記事はこれでおわりですね(笑)

でもまぁ、一応 AWS CLI 叩いて試してみましょう。

AWS CLI でアカウントロック検証

サインイン(初回認証)はこんな感じで叩けます。

aws cognito-idp initiate-auth \
--auth-flow USER_PASSWORD_AUTH \
--client-id xxxxxxxxxxxxxxxx \
--auth-parameters USERNAME=xxxx,PASSWORD=xxxxxx

で、パスワードを間違えてみると、、

An error occurred (NotAuthorizedException) when calling the InitiateAuth operation: Incorrect username or password.

ユーザー名かパスワード間違えてるぞってエラーが返ってきます。
そんなの知ってるよってことで気にせず、連続で叩いてみます。

2回目...3回目...4回目...5回目...6回目...

6回目でエラーが変わりました!!

An error occurred (NotAuthorizedException) when calling the InitiateAuth operation: Password attempts exceeded

パスワードの試行回数を超えましたってエラーですね。
ロックアウトの仕組みを確認することができました。

あとは、思いつく限り色々とパターンを出して、まとめてみようと思います。

ロックアウトの仕様

色々と試した結果以下がわかりました。

  • サインインの試行の失敗は 5 回まで許容
  • ロック後の再試行の失敗許容回数は1回許容
  • 規定の失敗回数に達すると、一時的なロックアウトが開始する
  • ロック時間は最初は1秒。再試行後に失敗すると、時間は倍増し15分まで到達する
  • 15分間サインインを再試行せずに待つと、ロックアウトがリセットされる
  • パスワードリセットをしても、ロックアウトはリセットされず、ロック時間を待機する必要がある

補足として、最初のロック時間が1秒なので、早く叩かないとエラーを出力できないです。最初「6回失敗できちゃった!?」ってなりました。

※ この情報は2021/2/25時点のもので、AWS側都合により変更される場合あります。

最後に

セキュリティにかかわるものですので記事にするかは迷いましたが、公式に書いてあるので、良しとしました。
Cognitoのロックアウトを調べている人の参考になれば幸いです。

参考資料

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

EFSで共有ストレージを作成し普段使い用Minecraftサーバの処理をロードバランサで負荷分散する

はじめに

ある時Minecraftサーバの処理自体を負荷分散するにはどうすればいいのだろうと考えていました。
PvPサーバのようにワールドデータが変更されないようにしてるやつなら、ワールドデータを複数のサーバに配置してロードバランシングすれば良いですが、普段友だちといっしょにMinecraftをする際はもちろんワールドデータは同じですし、ワールドデータの変更もされます(ブロックを配置したり消したりするので)。

となると問題になってくるのはリアルタイムでのワールドデータの同期です。

どんなにMinecraftサーバ自体の処理を分散させることができても、スムーズなワールドデータのリアルタイム同期ができなければ意味がありません。

そこで見つけたのがこちらのサービス
AWS EFS
要はAWSが提供しているNFSです。

今日はこちらを使って、ワールド用ストレージを複数のサーバに共有し、Minecraftの根本的な処理部分自体はロードバランサで負荷分散させる、といったことをやっていこうと思います。

要はこういうこと↓です。絵が下手で申し訳ないです。

EFSで共有ストレージを作成する

AWSコンソール画面でEFSを開け、ファイルシステムの作成を押すと↓みたいなモーダルがでます。
適当な名前をつけて作成しましょう。
image.png

EFSファイルシステム(Elastic File System ファイルシステムって頭痛が痛いみたいな名前ですね)を作成すると、こんなの↓が出ると思うので、名前のところをクリックしてネットワークタブを開けます。
image.png

セキュリティグループ名はあとで使うので、こいつをメモしておきましょう、
image.png

EC2インスタンスを作る

今回はお試しということで、インスタンスタイプt2.microのやつを2つ建てることにしました。
インスタンスの詳細の設定で、ファイルシステムの追加をしておきます。
こうすることでなんとマウントなどを自動でやってくれます。超便利ですね。
マウント先はデフォルトの/mnt/efs/fs1 にしておきます。

インスタンスを作成したら、インスタンスのインバウンドルールで、先ほどコピーしたEFSのセキュリティグループをソースに2049を許可しておきます。また、カスタムTCPで25565番も許可しておきます。

Java等のインストール

どっちかのインスタンスに入って、

$ sudo apt update
$ sudo apt install openjdk-8-jdk

でJava8をインストールします。
入ったかの確認はjava -version でできますが、インスタンスタイプによってはヒープサイズを指定しないとjava -version すら実行できない可能性があります。
ヒープサイズを指定して実行する場合は
java -Xms64m -version
でいけると思います。

これを別のインスタンスでも同じことをします。

Minecraft Serverのダウンロード/インストール

こちらにアクセスし、Minecraft Serverの最新版のダウンロードリンクをコピーする。本記事執筆時点では最新版は1.16.5でした、

どれか1つのインスタンスに入り、

$ cd /mnt/efs/fs1
$ sudo mkdir minecraft_server
$ cd minecraft_server
$ sudo curl -LO https://launcher.mojang.com/v1/objects/1b557e7b033b583cd9f66746b7a9ab1ec1673ced/server.jar

でMinecraft Serverをダウンロードします。
そして、初回起動。今回使用しているインスタンスのメモリが1GBと小さいため、ヒープサイズは512MBとしていますが、必要に応じて変えてもらっていいです。

$ sudo java -Xmx512M -Xms512M -jar /mnt/efs/fs1/minecraft_server/server.jar nogui

初回は必ずエラーを吐きます。

$ sudo nano /mnt/efs/fs1/minecraft_server/eula.txt

で、eula=falseeula=true にしておきます。

そして、2回目の実行

$ sudo java -Xmx512M -Xms512M -jar /mnt/efs/fs1/minecraft_server/server.jar nogui

これで多分実行できたと思います。

別サーバでも実行

別サーバでも

$ sudo java -Xmx512M -Xms512M -jar /mnt/efs/fs1/minecraft_server/server.jar nogui

を実行します。しかし、実行すると以下のようなエラーが出てると思います。

[15:25:22] [main/INFO]: Environment: authHost='https://authserver.mojang.com', accountsHost='https://api.mojang.com', sessionHost='https://sessionserver.mojang.com', servicesHost='https://api.minecraftservices.com', name='PROD'
[15:25:22] [main/FATAL]: Failed to start the minecraft server
aex$a: /mnt/efs/fs1/minecraft_server/./world/session.lock: already locked (possibly by other Minecraft instance?)
        at aex$a.a(SourceFile:98) ~[server.jar:?]
        at aex.a(SourceFile:44) ~[server.jar:?]
        at cyg$a.<init>(SourceFile:287) ~[server.jar:?]
        at cyg.c(SourceFile:275) ~[server.jar:?]
        at net.minecraft.server.Main.main(SourceFile:118) [server.jar:?]

今回は時間が無かったので卍暴力卍で解決しようと思います。

$ sudo rm /mnt/efs/fs1/minecraft_server/./world/session.lock

これでもう1度

$ sudo java -Xmx512M -Xms512M -jar /mnt/efs/fs1/minecraft_server/server.jar nogui

を実行してみてください。今度は多分いけたと思います。

ロードバランサを作る。

おなじみのあの画面でロードバランサを作りましょう。
今回選択するのはNetwork Load Balancerです。

image.png

以下の点に注意します。

  • リスナーのポートはTCPの25565番
  • アベイラビリティゾーンはEC2インスタンスがある場所を選択
  • ターゲットへのポートもTCPの25565番
  • ヘルスチェックの設定は上書きを選択し、Portを25565にしておく

ロードバランサのグローバルIPを取る

AWSコンソール画面のEC2のサイドメニューに「ネットワークインターフェイス」を選択します。

ネットワークインターフェイスのフィルターでロードバランサの名前で検索し、先ほど作成したNLBのグローバルIPをメモしておきます。

Minecraftをプレイ

サーバを追加し、Server Addressは先ほどメモしたロードバランサのIPをペーストします。
image.png

後は良いMinecraftプレイを!

私たちについて

私が所属しているKISGについて最後に宣伝します。
Kosen Infrastructure Study Group略してKISGは、高専生によるインフラを勉強したりする会です。
月1で勉強会を開いたり、外部講師を招いて様々なインフラ関連技術の勉強をしています。
興味のある高専関係者はTwitter ID @FPC_COMMUNITY まで!

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