AWSをいじり倒す(13-3.lambda+EFS)

あらすじ

lambdaを使おうとするもtensorflowがデカすぎて容量問題に苦しむ

そこに現れた一筋の光、新機能EFSとの接続

新機能 – Lambda関数の共有ファイルシステム – Amazon Elastic File System for AWS Lambda | Amazon Web Services ブログ

さっそく試してみることにする。

 

 VPCを作成

まずはVPCを作成。インターネットゲートウェイの設定も作成。

後々s3も使おうと思っているのでエンドポイントも作成。

この辺は過去記事で一回やっているのでサクサク作れた

サブネットは2個作っておくと良いらしいので2個作った。

 

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

1つはインバウンドやアウトバウンドになにも書いていないlambda-sg

f:id:Messerarche:20200703230100p:plain

 

もう一つはEFSにアタッチするためのlambda-efs-sg

こちらはインバウンドでNFSの2049を許可する

f:id:Messerarche:20200703230153p:plain

 

あとはEC2にアタッチするSSHが許可されたSG

まあこれはおそらく既存のものがあるはず

 

 

次にEFSを準備

さっき作ったVPCを指定し

セキュリティグループはlambda-efs-sgを指定

f:id:Messerarche:20200703230629p:plain

 

もう一つ設定が必要なのはアクセスポイントのところ

f:id:Messerarche:20200703173443p:plain

lambdaにEFSの操作権限を与える。

このまま作成を完了

 

lambdaの設定

次にlambdaの関数画面へ

f:id:Messerarche:20200703173901p:plain

アクセス権限を設定する

 

ロール名をクリックしてIAMの画面を開き、以下の二つのポリシーをアタッチ

f:id:Messerarche:20200703174111p:plain

 

 

 

次にlambda関数のVPCの設定へ

f:id:Messerarche:20200703171629p:plain

 

f:id:Messerarche:20200703171706p:plain

ここのサブネットで作った2つともを登録

セキュリティグループはlambda-sg

で作成。

ちょっと時間がかかって、できましたのメッセージ。

lambdaが裏で動かすEC2にネットワークインタフェースを作ったりなんやりしてたみたい

f:id:Messerarche:20200703174512p:plain

 

 

次にいよいよファイルシステムとの接続

f:id:Messerarche:20200703174626p:plain

 

さて・・・

f:id:Messerarche:20200703174739p:plain

EFSファイルシステムってダブルミーニング

 

f:id:Messerarche:20200703174909p:plain

EFSを選んだら、マウントするターゲットポイントが出てきた。

さっきEFSで設定したアクセスポイントだ。

 

ローカルマウントパスには適当に

/mnt/slp

と設定。

 

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

さて、ここからが問題

新しいVPCのパブリックサブネットでAmazon Linux EC2インスタンスを起動します。インスタンスの詳細で、EFSマウントポイントがあるアベイラビリティーゾーンの1つを選択してから、[Add file system ]を選択して、関数に使用しているのと同じEFSを自動的にマウントします。 EC2インスタンスのセキュリティグループには、defaultのセキュリティグループ(EFSをマウントできるようにする)とSSHへのインバウンドアクセスを与える(インスタンスに接続できるようにする)セキュリティグループを選択します。

ほほー、EC2を立ち上げて、EFSをマウントしろと。面白いな

AMIに関してなにも書いてないが、python3.8で試しているようなので

一応Amazon Linux AMI2を使うことにする

 

EC2作成手順の途中で、ファイルシステムにEFSを追加・・・したのだが

これは後々なぜかうまくいかなかったのでやめた。

f:id:Messerarche:20200703180009p:plain

 普通にEC2を起動して、EFSをマウントしたほうがよい。

なんでうまくいかなかったのか原因を探る元気がないので、うまくいく手順を記すことに力を使う

立ち上がったEC2にて

sudo mkdir efslambda

sudo mount -t efs -o tls,accesspoint=[アクセスポイント名] [ファイルシステムID] efslambda 

してマウントする。詳細は過去記事をみてください。 

 

ちなみに今後のインストール作業に割と時間がかかるので

EC2はメモリ4GBぐらいのを選んだ方がいい。無料枠じゃないけど。

 

SSHを使用してインスタンスに接続し、以下の必要な依存関係を含むrequirements.txtファイルを作成します。 

 

 今回必要なパッケージ情報は以下。

vi requirements.txtしてリストアップする。

tensorflow

keras

numpy

pandas 

 

ちなみに、最新を入れずに過去のバージョン

つまりpython3.7だとか、tensorflow1.14.0だとかを入れようとすると

lambdaの実行がまったくうまくいかなくて心折れそうになった。

少しでも容量の節約を・・・と過去バージョンに拘っていたけど

EFSがきた以上、容量気にせず最新で入れてしまった方が良いみたいだ

 

EFSは、EC2によって/mnt/efs/fs1の下に自動的にマウントされます。そこで、/mlディレクトリを作成し、パスの所有者を、現在接続(ec2-user)しているユーザーとグループに変更します。

sudo mkdir /mnt/efs/fs1/ml

sudo chown ec2-user:ec2-user /efslambda

手動でマウントしたのでmkdirは無視して(斜線済)

sudo chown のほうだけ実行

 

まずはpythonのインストール

 

(2022/12/20更新)

以下の通り設定すればスマートにできた。

 

今入っているバージョンを確認

python3 -V
python 3.7.15
 
3.8が使えることを確認
amazon-linux-extras | grep -i python
→ 44 python3.8 available [ =stable ]
 
python3.8のインストールをできるよう許可し、インストール
sudo amazon-linux-extras enable python3.8
sudo yum install python3.8 -y
 
python 3.8がデフォルト設定になるよう設定
echo 'alias python=python3.8' >> ~/.bashrc
source ~/.bashrc
 
3.8に変わったか確認

(2022/12/20更新ここまで)

 

無事、pythonのインストールが終わったら

pip3.8 install -t /efslambda/lib38 -r requirements.txt

で各種パッケージをインストール。

結構時間がかかる

 

無事終わったら

最後に、EFSアクセスポイントに使用したユーザーとグループに/mlパス全体の所有権を与えます。

以下を実行。

sudo chwon -R 1001:1001 /efslambda

 

lambdaの動作環境設定 

次はlambda関数に戻ってきて、環境変数の書き換え

f:id:Messerarche:20200703203625p:plain

 

使用するランタイムに応じて、依存関係が展開パッケージに含まれていないか、レイヤーに含まれていない場合に、依存関係を探す場所を指示する方法を見つける必要があります。 Pythonの場合、PYTHONPATH環境変数/mnt/inference/libに設定しています。

だそうなので、PYTHONPATHをさっきパッケージを詰め込んだ/mnt/slp/lib38に割当

f:id:Messerarche:20200704031132p:plain



ガイドではモデルもEFSに入れているみたいだけど、まずは動くところを確認したいのでこれで。

 

次に基本設定もいじる

f:id:Messerarche:20200704031459p:plain

 

ランタイム=Python3.8

メモリ=1024MB

タイムアウト=3分

 

 実行してみる

いよいよ必要なパッケージを全部importして実行してみる

f:id:Messerarche:20200704031311p:plain

実行!

 

f:id:Messerarche:20200704031604p:plain

やった〜!

ブログだと1本道で成功を歩んでいるが、

実際はいろいろあって半日以上費やし、もう目がしぱしぱ。

 

後日談

EFS配下にモデルとインプットファイルを置いて、機械学習の推論を実行してみた。

ソース全部は載せられないが、一部抜粋でこんな感じ

f:id:Messerarche:20200706175832p:plain

 

結果・・・成功!気持ちいい〜

f:id:Messerarche:20200706175932p:plain

 

 

おわりに

まあでもserverlessだのレイヤーだのzipで固めるだの言う話よりは断然わかりやすいし

コードもコンソール上でいじれて扱いやすいし

設定さえうまくできれば良いことしかない。最高だ。

 

ということでようやく下地が整ったので、

モデルファイル食わせたり、トリガーの設定したりができる。

それはまた今度で。

 

おまけ1

ubuntu使っているので完全には参考にならなかったが

動画でセットアップする手順公開してる人がいたので貼っておく

www.youtube.com

 

 

おまけ2

ちなみに

python3.7以下の環境でtensorflowを動かそうとすると

インストールまではうまくいくが、lambda実行時に以下のようなメッセージが出て壁にぶち当たる。

ImportError: /lib64/libm.so.6: version `GLIBC_2.23' not found (required by /mnt/slp/lib/tensorflow/python/_pywrap_tensorflow_internal.so)


Failed to load the native TensorFlow runtime.

 

amazon web services - [AWS Lambda]: How to fix "version GLIBC 2.27 Not found" - Stack Overflow

無理やりglibを移植すれば動くらしいけど、自分には無理だった

 

せっかく調べた関連コマンドものせとく

$ ls -l | grep libm.so
-rw-r--r-- 1 root root 141 1月 17 06:34 libm.so
lrwxrwxrwx 1 root root 12 5月 27 00:46 libm.so.6 -> libm-2.26.so

 

 strings libm-2.26.so | grep GLIBC
GLIBC_2.2.5
GLIBC_2.4
GLIBC_2.15
GLIBC_2.18
GLIBC_2.23
GLIBC_2.24
GLIBC_2.25
GLIBC_2.26
GLIBC_PRIVATE
GLIBC_2.15 

python3.8で快調に動いたので、こっちはもう追わない。

 

 

 

 

AWSをいじり倒す(13-2.lambda+serverless)

再びこちらの記事に戻ってきて

TensorFlowをAWS Lambdaで使って競艇予想APIを爆誕させました!! - Qiita

 Serverlessを使ったlambda関数の定義。

果たしてこれで容量問題を掻い潜って関数が実行できるのか。

まずはやってみよう

 

 

さっそく、Serverlessを動かすためのnode.jsのインストール

MacにNode.jsをインストール - Qiita

 

2箇所エラーがでて詰まった

・1個目

Homebrewで「Warning: The following directories are not writable by your user:」とエラーが出た際の解消法 - Qiita

エラーメッセージに解決方法も書いてあるので、whoamiのところだけ書き換えて

コピペで解消

・2個目

Homebrewで「Warning: The following directories are not writable by your user:」とエラーが出た際の解消法 - Qiita

ディレクトリを作って解消。

 

どちらも記事の記載を淡々とこなせば解消したので特筆することはなし。

 

serverlessをインストール

npm install -g serverless

f:id:Messerarche:20200701174738p:plain

 成功!

 

serverlessからAWSにアクセスするためのIAMアカウントを作成

f:id:Messerarche:20200701175229p:plain

プログラムによるアクセスを選択してユーザを作成。 

 

f:id:Messerarche:20200701175422p:plain

AdministratorAccessを付与。

・・・なんか与えすぎな気もするが一旦作成。

lambdaにデプロイするときにcroud formation使ったりS3バケット作ったりと

いろんなことしまくるようなので、まとめてエイヤ権限ってことなんだろう。

 

ローカル端末から以下のコマンドを実行してserverlessからawsにアクセスできるようにする

serverless config credentials --provider aws --key [アクセスキーID] --secret [シークレットアクセスキー]

 

以下の文が返ってきたら成功 

Serverless: Setting up AWS...

 

プロジェクトを作る。pythonを使うのでtemplateはaws-pythonを選択

serverless create --template aws-python

f:id:Messerarche:20200701180857p:plain

 

コマンドを実行したディレクトリに

handler.py

serverless.yml

の2ファイルができた。

pyにはメインとなるlambda関数を、ymlにはデプロイするサービスの設定を書き込む。

 

lambda-layerとlambda-functionフォルダを作って、handler.pyとserverless.ymlをそれぞれのフォルダにコピーする

mkdir lambda-layer

mkdir lambda-function

cp handler.py lambda-layer/

cp serverless.yml lambda-layer/

cp handler.py lambda-function/

cp serverless.yml lambda-function/

 

lambda-functionの設定

vi lamda-function/serverless.yml

serverless-python-requirementsという機能を使って

追加のパッケージをインストールしてくれるらしいので、その設定を書く。

なお、serverless-python-requirementsを利用する場合、Dockerも必要となる

今回はインストール済みだったので手順は割愛

 

とはいえserverless.ymlのお作法はよくわからないので参考サイト通りに作成。

ただ、結局こっちでもslimPatternsにいらなさそうなファイルをずらずらと列挙して容量削減を図ることになる

service: [サービス名]

plugins:
  - serverless-python-requirements

custom:
  pythonRequirements:
    dockerizePip: true
    zip: true
    slim: true
    slimPatterns:
      - "**/debug"
      - "**/grpc"
      - "**/h5py"
      - "**/markdown"
      - "**/pkg_resources"
      - "**/setuptools"
      - "**/tensorboard/plugins"
      - "**/tensorboard/webfiles.zip"
      - "**/tensorflow_core/contrib"
      - "**/tensorflow_core/examples"
      - "**/tensorflow_core/include"
      - "**/tensorflow_estimator"
      - "**/werkzeug"
      - "**/wheel"
  requirementsService: [サービス名]-layer
  requirementsExport: [サービス名]Layer
  requirementsLayer: ${cf:${self:custom.requirementsService}-${self:provider.stage}.${self:custom.requirementsExport}}

provider:
  name: aws
  runtime: python3.7
  stage: dev
  region: ap-northeast-1
  iamRoleStatements:
      - Effect: "Allow"
        Action:
          - s3:ListBucket
          - s3:GetObject
        Resource:
          - "arn:aws:s3::*"

functions:
  classify:
    handler: handler.classify
    memorySize: 2048
    timeout: 60
    layers:
      - ${self:custom.requirementsLayer}

斜体太字部分は自分の環境に応じて書き換え。

 

handler.pyには実行したいプログラムを記載。

とりあえず動作確認をしたいので先頭に

try:
    import unzip_requirements
except ImportError:
   pass

import json
import pandas
from keras.models import load_model
import numpy

をつけるだけつけた。

最初の4行はserverlessで必須、後半の4行で動作確認

 

requirements.txtを新たに作る

vi requirements.txt

そこに追加で入れたいパッケージを指定。

tensorflow == 1.14.0

 

 

lambda-layerの設定

service: [サービス名]-layer

plugins:
  - serverless-python-requirements

provider:
  name: aws
  region: ap-northeast-1
  runtime: python3.7
  stage: dev

custom:
  pythonRequirements:
    dockerizePip: true
    layer:
      compatibleRuntimes:
        - python3.7
      slim: true
      strip: false

resources:
  Outputs:
    [サービス名]Layer:
      Value:
        Ref: PythonRequirementsLambdaLayer

インデントとか空白とかその通りにしないとエラーが出るので注意

(これで数時間無駄にした)

 

こちらにも

requirements.txtを新たに作る

vi requirements.txt

そこに追加で入れたいパッケージを指定。

keras == 2.3.1

numpy == 1.18.1

pandas == 1.0.1

 

設定が終わったら以下のコマンドを実行してデプロイ。

cd lambda-layer

serverless deploy

cd ../lambda-function

serverless deploy

 

・・・

  An error occurred: HandlerLambdaFunction - Unzipped size must be smaller than 64198656 bytes (Service: AWSLambdaInternal; Status Code: 400; Error Code: InvalidParameterValueException; Request ID: db8cece7-fd05-4e73-9066-d0921795792c).

というエラーが出て停止。

結局サイズが足りずにだめなんかーい

 

また容量との格闘か・・・

とりあえず組み合わせを変えてみる

具体的にはLayerのrequiementsを

numpy == 1.18.1

 

functionのrequirementsを

tensorflow == 1.14.0
keras == 2.3.1
pandas == 1.0.1

というふうに組み合わせを変えてみる

重複するパッケージがうまいこと作用することを祈って

 

Serverless: Checking Stack update progress...
...............
Serverless: Stack update finished...

 

う、うまくいった・・・。本当にギリギリの戦いだ

AWS lambdaにデプロイした関数ができているので、早速テスト

 

"errorMessage": "[Errno 28] No space left on device",
"errorType": "OSError",

 

はい、エラー

Lambda実行時に 'No space left on device'とエラーが出るときの対処法 - Qiita

 

 tmpを使い切った模様。

果たして、この関数1つで使い切ったのか、トライアンドエラーしているうちに使い切ったのか・・・

とりあえずtmpをrmするコマンドを放り込む。

f:id:Messerarche:20200703162759p:plain

こ、コンソール上でプログラムの変更ができない・・・。

つまり毎回デプロイせなあかんのか!?

デプロイ1回に5分ぐらいかかるのでこれは地味にめんどくさい。

 

しょうがないので再デプロイ

→No space left on device

 

エラーメッセージを読むに、zip解凍した時点でtmp使い切っている疑惑。

これもうだめかもわからんね

 

頭抱えてたらまた新たな突破口を発見

新機能 – Lambda関数の共有ファイルシステム – Amazon Elastic File System for AWS Lambda | Amazon Web Services ブログ

 

いくつかのユースケースではLambda関数によって実装がより容易になります。例えば:

  • /tmpで使用可能な容量(512MB)より大きいデータを処理またはロードする。

ど、ドンピシャ〜

しかも2020/6/17の記事て。最近すぎワロタ 

 

械学習の推論を実装するLambda関数を作成するには、コード内で、必要なライブラリをインポートして機械学習モデルをロードできる必要があります。たいてい、そのようなことをすると、それらの依存関係の全体的なサイズは、デプロイメントパッケージサイズの現在のAWS Lambdaの制限を超えます。これを解決する1つの方法は、ライブラリを適切に最小化して関数コードとともにデプロイし、モデルをS3バケットからメモリ(モデルの処理に必要なメモリを含めて最大3 GB)または/tmp(最大512 MB)に配置します。このようなモデルのダウンロードとカスタムが必要な最小化は、実装するのが簡単ではありませんでした。しかし、これからはEFSを使用できます。

数日間悩んできたことが全部書いてあるしマジかよ。

もうlambdaやめようと思ってたけど、もうちょっと頑張る。

長くなってきたので次回へ

 

 

 

AWSをいじり倒す(13.lambda)

食わず嫌いしてたlambdaを使ってみる。

 

今回は目的があって、

s3にファイルが入ったタイミングで

tensorflowで作成したモデルを使って推論をするプログラムを動かしたい、というもの。

 

まずは下調べしてみたけど、やっぱりちょっとめんどくさい。

今回は手元にあるpythonのコードを動かすのが目的なんだけど、

import numpyとかpandasとかしてたら、

事前にそれらパッケージをzipでアップロードしてあげないといけないようだ

pandasをLambdaのLayerとして追加する - Qiita

そのパッケージも、ローカルで作ってもだめで、指定したEC2で作る必要がある

 

 

まず最初にややこしいのが、使うpythonのバージョンによって

アップロードするパッケージの生成元となるEC2のAMIを選ばないといけない点

AWS Lambda ランタイム - AWS Lambda

今回使おうとしているpython3.7のOSはAmazon Linux(2ではない)

のでこのAMIを選んでインスタンスを起動。

 

次に、EC2のデフォルトpythonのバージョンが2.7だかなんだかで古いので

目的のバージョンのpythonをインストール。

現時点でyumに対応したpythonは3.6系までしかないので、

3.7以降はソースからインストールするしかない

 

今回はPython3.7.6を使う。

具体的な手順はここが参考になった

AWS Lambdaでpandasを利用する(Lambda Layers編) - marmarossa’s blog

 

まず目的のpythonをダウンロード

curl https://www.python.org/ftp/python/3.7.6/Python-3.7.6.tgz -o Python-3.7.6.tgz

 

解凍

tar xzf Python-3.7.6.tgz

 

ディレクトリに移動

cd Python-3.7.6

 

必須ライブラリをインストール

yum install gcc openssl-devel bzip2-devel libffi-devel

 

コンパイルしてインストール

./configure --enable-optimizations

sudo make altinstall

 

パッケージをインストールするディレクトリを作成

mkdir python/lib/python3.7/site-packages/

 

pandasのインストール

pip3.7 install pandas -t ./python/lib/python3.7/site-packages/

kerasのインストール

pip3.7 install keras -t ./python/lib/python3.7/site-packages/

 

zipに固める

zip pandaskeras.zip python/ -r

 

S3にアップロード(EC2へのS3アクセス権限付与など忘れずに)

aws s3 mv pandaskeras.zip s3://[s3bucket名]/module/pandaskeras.zip

 

S3のコンソール画面からアップロードされたことを確認して、

オブジェクトURLをメモっておく

f:id:Messerarche:20200701192746p:plain

 

 

 

 

 

lambdaの画面に移動

Additional Resourcesからレイヤーを選択、レイヤーの作成

f:id:Messerarche:20200701035239p:plain


レイヤーの作成。

f:id:Messerarche:20200701192926p:plain

S3からアップロードを選択し

リンクURLに先ほどメモしたURLを貼る
互換性のあるランタイムオプションはPython3.7を選択

 

 

次に関数の作成

f:id:Messerarche:20200701161804p:plain

 

まずはHello Worldから。

f:id:Messerarche:20200701162014p:plain


ロールは特に用意していないので作ってもらう

f:id:Messerarche:20200701162114p:plain

関数の作成を実行。

 

ほどなくして作成が完了

f:id:Messerarche:20200701162402p:plain

 

f:id:Messerarche:20200701162421p:plain

何かいろいろできそう(小並感)

 

ともあれ関数を実行してみる。

右上のテストボタンを押す

f:id:Messerarche:20200701163234p:plain

こんな画面が出てくるので、イベント名に適当にhelloと入力、作成

 

f:id:Messerarche:20200701163328p:plain

再度テストを実行

 

f:id:Messerarche:20200701163355p:plain

結果がずらずらとでてきた。とりあえずは動いたようだ。

 

 

さて、問題のimport pandasができるのかを試す

レイヤーを選択

f:id:Messerarche:20200701163526p:plain



お客様のレイヤーにさっき登録したレイヤーが出てきた。

f:id:Messerarche:20200701193452p:plain
numpyとscipyならデフォルトで用意してくれとるのね。

 

ちなみに、余談だが試行錯誤してるときはこんな怒られ方をした

f:id:Messerarche:20200701163800p:plain

どうも、追加パッケージは合計262MBまでしかだめらしい。

AWS LambdaでTensorFlow 2.0を使った画像分類 - ユニファ開発者ブログ

この辺にいかにやりくりするか、みたいなテクニックが書いてあった。

ええ、そこって気を使わないかんとこなの・・・。

いろんなものimportして大きめのプログラム動かそうと思ったらlambdaは諦めて

EC2で普通に動かすしかないのかも。

 

 

とりあえず追加は完了。

f:id:Messerarche:20200701193743p:plain



 

プログラムにimport pandasとかを追加してテストしてみる。

f:id:Messerarche:20200701193836p:plain

ソースを変更したら、Saveしたのちにテストを実行


f:id:Messerarche:20200701193924p:plain


どうやらうまくいったらしい。

import kerasも試してみる

 

f:id:Messerarche:20200701194540p:plain

 

ぐえ、tensorflowもいりますよ、と(凡ミス)。

しかしtensorflowは馬鹿デカ容量なので

上に書いたように262MBなんて余裕で超えて、そのままlambdaには持ってこれない。
 

 

一応EC2にインストールしてみる

pip3.7 install tensorflow -t ./python/lib/python3.7/site-packages/ --no-cache-dir

(--no-cache-dirについては以下)

AWS EC2でMemoryErrorとNo space left on deviceで詰まった話 - Qiita

 

ずらずら、とインストールされた中からダメ元で重そうなのを消してみる。

f:id:Messerarche:20200701195221p:plain

tensorboardとかは確かにいらんよなぁ

 

容量を確認するコマンドを打ってみる

du -sh ./*/

f:id:Messerarche:20200701195749p:plain

本体が1.5GB〜!!

 

犯人探ししていこう

f:id:Messerarche:20200701195917p:plain

 

これか。

f:id:Messerarche:20200701200308p:plain

 

これ消しちゃまずそうなやつ・・・え、みんなどうやってんの?

Running TensorFlow on AWS Lambda using Serverless - Mike Moritz - Medium

slim — Removes unneeded files and directories such as *.so*.pycdist-info, etc.

 

まじ?これ消していいの?(わかってない

どうみてもプログラムの本体だから無理だよなぁ

 

物は試しってことで除外してzipしてみる

[ec2-user@ip-172-31-14-167 ~]$ zip pkt.zip python/ -r -x python/lib/python3.7/site-packages/tensorflow/python/_pywrap_tensorflow_internal.so

 

できたのは164MBのzip

f:id:Messerarche:20200701202612p:plain

 

レイヤーに登録しようとすると

f:id:Messerarche:20200701202728p:plain

これでもでかすぎてだめか。

 

 tensorflowさえ使わなければ万事うまくいきそうなんだけど、

使うんだよな〜〜

 

次回、どうも成功してる事例っぽいserverlessからデプロイするやり方をダメ元で試してみる・・・。 

 

 

あと、s3に格納されたファイルを引数としたり、

結果をs3に格納したりする方法を探してみると

【AWS Lambdaの基本コードその2】 S3へのファイル保存 | ナレコムAWSレシピ

これをみると普通にpythonのコードでs3にアクセスする感じなのね。

てっきり、lambdaの機能として提供されているのかと思った。

 

 そうなってくると、あとはimportがうまくいけば

この関数のトリガーイベントの設定と、

成功時・失敗時ログをどこに流すかって設定するぐらいか。

 

なんだかlambdaの全体像は見えてきたが、超えるべき山がまだ高い

AWSをいじり倒す(番外編.LightSailのredmineにgit設定)

LightSailで建てたRedmineの中にGitを入れ込むという設定。

別にLightSailがEC2(redmineの入ったAMI利用)であってもよい。設定は一緒。

これらの特徴はbitnamiのRedmineを利用するという点にある。

bitnami式Redmine色々制約があるので、大半のネット記事を鵜呑みにするとうまくいかず、死ぬほど紆余曲折したのでメモしておく。

最後は妥協しているので参考程度に。

bitmani式ではなくて自前で構築する場合は、この記事は逆に参考にならんので注意

 

環境は

Ubuntu 16.04.6

Bitnami Redmine 4.1.0-8 

 

 

gitのインストール

bitnami式redmineにgitは最初から入っているので不要。

f:id:Messerarche:20200524170851p:plain

 

リポジトリ を準備。

作業ディレクトリは適当に以下とした。

/home/bitnami/git/repos

 

リポジトリ を作成

mkdir test.git
cd test.git
git init --bare
git update-server-info

なお、pushするたびにupdate-server-infoしないといけないらしいので

それを回避する設定もいれておく

mv hooks/post-update.sample hooks/post-update

実行権限も付与

cd ../
chmod -R o+w test.git

 

 

 

 

bitnamiで建てたRedmineの、Apacheやwww-なんとかみたいなユーザ相当はdaemon。

chown -R bitnami:daemon .

それはこのサイトをみて知った。

Amazon Lightsailの諸々ファイル置場 | It works for me

 他にもログの場所など有益な情報がまとまっていてありがたい

 

gitでやり取りする時に、必ずユーザとパスワードを要求したいので、その準備。

htpasswd -c -b /home/bitnami/git/.htpasswd ユーザ名 パスワード

 -bをつけて1ラインで登録してしまわないとバグるみたいな記載をみたので念の為書いておく

 

Apache用コンフィグの作成

bitnami式redmineの裏で動いているのはApache

主にこのディレクトリ 配下にいろんなconfigが入っている

/opt/bitnami/apache2/conf/

この配下で作業を行っていく

 

git.confを新たに作成。

まずは最小構成の内容をgit.confに記載する。

Alias /git /home/bitnami/git/repos

<Location /git>
    AuthType basic
    AuthName "Git"
    AuthUserFile /home/bitnami/git/.htpasswd
    Require valid-user
</Location>

 

 

このgit.confを読み込んでもらうために、同一ディレクトリにあるhttpd.confの最終行に

Include "/opt/bitnami/apache2/conf/git.conf"

を追加

 

これで最小構成が完成。システムのリスタートを行う。

bitnami式redmineのリスタートコマンドは以下。

sudo sh /opt/bitnami/ctlscript.sh restart

 

いったんここまででテスト。

ローカル環境にて、cloneを試す。

git clone https://example.com/git/test.git

ユーザ名入力

パスワード入力

Cloning into 'test'...

warning: You appear to have cloned an empty repository.

この返答がくればOK

 

ちなみに、まだcloneはできてもpushはできない。

touch testfile
git add testfile
git commit -m "first commit" 

 [master 452f009] first commit

1 file changed, 0 insertions(+), 0 deletions(-)

create mode 100644 testfile

git remote set-url origin https://example.com/git/test.git 
git push -u origin master

 error: Cannot access URL https://example.com/git/test.git/, return code 22

fatal: git-http-push failed

error: failed to push some refs to 'https://example.com/git/test.git'

 

pushするための設定

pushを行うためには、git.confに追加の設定が必要でそのやり方は2通りある

1.git-http-backendを使う

2.WebDavを使う

のどちらかを行う必要がある。

なお、SSHは使わずにhttpでなんとかしたい、というのが前提。

(鍵管理したくないので) 

 

さて、git-http-backendを有効化する手順は巷にたくさん書いてあるが、

それをそのまま入れると失敗するのが最大のハマりポイント。

 

具体的にはこういうやつだ

SetENV GIT_PROJECT_ROOT /home/bitnami/git/repos
SetENV GIT_HTTP_EXPORT_ALL
ScriptAlias /git "/usr/lib/git-core/git-http-backend"

Alias /git /home/bitnami/git/repos

<Location /git>
    AuthType basic
    AuthName "Git"
    AuthUserFile /home/bitnami/git/.htpasswd
    Require valid-user
</Location>

上3行を追加し、取り消し線のところを削除

他にもなんだか装飾されたコンフィグが公開されているが、最低限これだけでいい。

 

リスタートしてconfファイルを読み込む

sudo sh /opt/bitnami/ctlscript.sh restart

 

すると、ローカルで実行した結果がこうなる

git push -u origin master

 fatal: repository 'https://example.com/git/test.git/' not found

ちなみに、cloneも失敗するようになる。

これが何故なのかわからず死ぬほど時間を使った。

 

 

結論はbitnami式redmine環境特有のものだった。

自分なりに調べた結果を言葉にすると

bitnami式は動作するための最小限のモジュールしかインストールしていない

かつ、通常インストールされる場所とは別のディレクトリにモジュールを置いているのでapt-get等で追加インストールしてもそれだけでは反映されない。

 

なので、普通に動かないし、追加でpkgインストールしても動かないという二重苦。

ちなみに2番目のDAVの設定にも手を出してみたがこれまた沼が深そうで諦めた。

また、手探りでa2enmod cgiコマンド打ったあと再起動したらredmineが立ち上がらなくなり、ubuntuのデフォルトページが表示されるようになってしまった。クソ焦って慌てて復旧させたが、configのいかんところが書き変わってしまったんだろうか・・・。若干トラウマ

 

 

さて、試行錯誤を経てたどり着いたのがこのブログ

bitnami redmine と同じホストで git 連携する - criticablog

完全ではないが、動くところまではもっていくことができた。

以下にコピペな部分もあるが手順を書いておく。

 

fcgiwrapインストール

sudo apt-get install fcgiwrap

  ユーザグループ設定

vi /etc/default/fcgiwrap
FCGI_USER=daemon
FCGI_GROUP=bitnami
FCGI_SOCKET_OWNER=daemon
FCGI_SOCKET_GROUP=daemon

  

 

git.confを大改造。Subversionとかは使わないので自分用に多少アレンジ

<IfModule !perl_module>
LoadModule perl_module modules/mod_perl.so
</IfModule>
<IfModule !env_module>
LoadModule env_module modules/mod_env.so
</IfModule>
PerlLoadModule Apache::Authn::Redmine

# Gitの設定
<IfModule !proxy_module>
LoadModule proxy_module modules/mod_proxy.so
</IfModule>
<IfModule !proxy_fcgi_module>
LoadModule proxy_fcgi_module modules/mod_proxy_fcgi.so
</IfModule>

LogLevel trace2

AliasMatch "/git/(.+)" "/opt/bitnami/git/libexec/git-core/git-http-backend/$1"
<Location /git>
    SetHandler "proxy:balancer://fcgi59618workaround"

    SetEnv GIT_HTTP_EXPORT_ALL ""
    SetEnv GIT_PROJECT_ROOT "/home/bitnami/git/repos"

    AuthType Basic
    AuthName "Git"
AuthUserFile /home/bitnami/git/.htpasswd Require valid-user </Location> <Proxy "balancer://fcgi59618workaround"> BalancerMember "unix:/run/fcgiwrap.socket|fcgi://." </Proxy>

 

モジュールの配置

mkdir -p /opt/bitnami/perl/lib/site_perl/5.16.3/Apache/Authn
ln -sv /opt/bitnami/apps/redmine/htdocs/extra/svn/Redmine.pm /opt/bitnami/perl/lib/site_perl/5.16.3/Apache/Authn/Redmine.pm

そして

sudo sh /opt/bitnami/ctlscript.sh restart

すると、無事clone/pushどちらも動いた。

先人の知恵さまさま・・・!

 

これで、http通信+password要求でgitが使える環境が完成。

https設定ができていればhttpsでも問題なく動いた。

 

redmineとgitの連携は

RedmineでGitを連携させる - Qiita

あたりをみながら設定してなんなく動いた。

 

 

 

ここからはうまくいっていなのでただの参考記事

どうもredmineで作ったID/PASSをgitの認証に使うことができるとのこと

これは便利と思って試そうとして死んだ。

 

先人様のサイトにあるこのconfigをgit.confに追加でぶちこむ。

    # Redmine プロジェクトのメンバー管理と連動したアクセス制御。
    PerlAccessHandler Apache::Authn::Redmine::access_handler
    PerlAuthenHandler Apache::Authn::Redmine::authen_handler
    # /opt/bitnami/apps/redmine/htdocs/config/database.yml と同じ値にする。
    RedmineDSN "DBI:mysql:database=bitnami_redmine;host=localhost;mysql_socket=/opt/bitnami/mysql/tmp/mysql.sock"
    RedmineDbUser "bitnami"
    RedmineDbPass "****"

なお、DbPassは

/opt/bitnami/apps/redmine/htdocs/config/database.yml

に書いてある。

 

これでclone実行するとこんな感じのエラー

git clone https://example.com/git/test.git

Cloning into 'test'...

fatal: unable to access 'https://example.com/git/test.git/': The requested URL returned error: 500

 

 

/opt/bitnami/apache2/logs/error_logをみるとこんなことが書いてある

[Mon May 25 14:36:04.034645 2020] [perl:error] [pid 21399:tid 139890079483648] [client 118.2.90.3:54909] install_driver(mysql) failed: Can't locate DBD/mysql.pm in @INC (@INC contains: /opt/bitnami/git/lib/site_perl/5.16.3 /opt/bitnami/perl/lib/5.16.3/x86_64-linux-thread-multi /opt/bitnami/perl/lib/5.16.3 /opt/bitnami/perl/lib/site_perl/5.16.3/x86_64-linux-thread-multi /opt/bitnami/perl/lib/site_perl/5.16.3 /opt/bitnami/perl/lib/5.16.3/x86_64-linux-thread-multi /opt/bitnami/perl/lib/site_perl/5.16.3/x86_64-linux-thread-multi /bitnami/ruby25stack-linux-x64/output/perl/lib/site_perl/5.16.3/x86_64-linux-thread-multi /bitnami/ruby25stack-linux-x64/output/perl/lib/site_perl/5.16.3 /bitnami/ruby25stack-linux-x64/output/perl/lib/5.16.3/x86_64-linux-thread-multi /bitnami/ruby25stack-linux-x64/output/perl/lib/5.16.3 . /opt/bitnami/apache2) at (eval 6) line 3.\nPerhaps the DBD::mysql perl module hasn't been fully installed,\nor perhaps the capitalisation of 'mysql' isn't right.\nAvailable drivers: DBM, ExampleP, File, Gofer, Proxy, Sponge.\n at /opt/bitnami/perl/lib/site_perl/5.16.3/Apache/Authn/Redmine.pm line 557.\n

太字のところに着目

DBD/mysql.pmが見つからねーよ、と。

これが先に説明したbitnami特有のモジュール足りてないアレ。

 

これについて戦っている記事を2つ見つけた。

git - install_driver(mysql) failed: Can't locate DBD/mysql.pm - Stack Overflow

なんでこのエラーがでるかの仕組みがしっかりと書いてあるが、

悲しいかなこのサイトの結論は

「サポートに繰り返し言ってくしかないね!」

 

こっちは気合で解決しましたと書いてある

Subversion login - install_driver(mysql) failed: Can't locate DBD/mysql.pm in @INC - Redmine - Bitnami Community

過去サーバから設定ファイルをコピーしてきて、config書き換えたらうまくいったんだと。

試しにファイルをいくつかそれっぽいコピーしてみたけど、

そこまで知識がないので泥沼化して諦めた。つら。

 

どうも昔のredmineにはちゃんと入ってたモジュールっぽいんだよなぁ。

現時点の最新(4.1.0-8)には含まれてないのは謎

 

AWSをいじり倒す(12.Amazon Lightsail)

今回は勉強ではなく、仕事でLightsailを使ってredmineサーバを建てることになったのでついでに記事化

 

そもそもLightsailとは何か

Amazon Lightsailとは?EC2との違いとメリット・デメリットを調べてみた | NHN テコラス Tech Blog | AWS、機械学習、IoTなどの技術ブログ

 

簡単に言うとAWSのパッケージ商品。

何も考えなくてもちゃんとした構成で用意してくれる。

 

何だかえらいポップな画面からスタート。

f:id:Messerarche:20200520192512p:plain

 

ロケーションの選択。国旗まで出しちゃってまあ。

f:id:Messerarche:20200520192647p:plain

明らかに他のサービスとは異質w

 

プラットフォームの選択

f:id:Messerarche:20200520192727p:plain

Windowsだとできることは現時点でほとんどなく、

Linux/Unixが主流のようだ

 

どのアプリ入れますか

f:id:Messerarche:20200520192831p:plain

複数選択はできない。今回はRedmine

 

キーペアの設定

f:id:Messerarche:20200520193157p:plain

デフォルトだと、キーの名前を自動生成してくれるみたい。

デフォルトキーを手元にダウンロードしておく。

 

スナップショットは・・・うーんいるようないらんような

f:id:Messerarche:20200520193403p:plain

月額$0.05/GBで、2回目以降は増分のみとのことなのでとりあえず有効化。

 

お値段。月額$3.5は安い。

f:id:Messerarche:20200520193439p:plain

派手な使い方しないしこれでよさそう。後から増築もできるし。

 

リソース名の設定とか、インスタンス数の指定とか。

f:id:Messerarche:20200520193736p:plain

このキータグはLightsailのリソースの中だけで使うものみたいだ。

用途は普通に管理のため。

Amazon Lightsail のタグ | Lightsail ドキュメント

でもわざわざキーオンリータグを準備した意味がわからん。キー値タグでいいやん

 

せっかくなのでつけてみた。

f:id:Messerarche:20200520195130p:plain

作成ボタンポチー

 

こんばんは!

f:id:Messerarche:20200520195324p:plain

過剰にユーザフレンドリー感だしてるなぁ。

AWSとっつきにくい人向けなのかね。

 

ほどなくしてできた。

f:id:Messerarche:20200520195835p:plain

f:id:Messerarche:20200520200205p:plain

独自のSSHクライアントも提供してくれているみたいだが、

IPとユーザ名と、先ほどダウンロードしたキーがあるので

EC2にアクセスするのと同じ要領でSSHで接続。

つながった

f:id:Messerarche:20200520200332p:plain

 

そしてこの黒塗りのところにブラウザからのログインパスワードが書いてある

f:id:Messerarche:20200520200954p:plain



パブリックIPをブラウザに放り込むと

f:id:Messerarche:20200520201501p:plain

 

無事表示された。

 

 

仕上げの設定。

IPアドレスの固定化。無料だから必ずやろう。

f:id:Messerarche:20200520202946p:plain

ネットワーキングから静的IPの作成

 

ロケーションは東京、インスタンスは先ほど作ったものを指定

f:id:Messerarche:20200520203041p:plain

 

静的IPの指定で一意な名前をつける

f:id:Messerarche:20200520203130p:plain

アタッチしている間は無料ですよ、と。

ちなみにアタッチしないと$0.005/h取られる模様。無駄に確保すんなってことね

 

作成を押すと静的IPが取得できた。アタッチもそのまましてくれたっぽい

f:id:Messerarche:20200520203400p:plain

 

早速このIPアドレスRedmineにログインできることが確認できた。

 

 

DNSの設定も行えるらしい。

静的IPを設定した後、新たなメニューが増えている

f:id:Messerarche:20200520204005p:plain

 

が、今回はLBも使わないので

ドメイン取得した場所で今取った静的IPアドレスを登録して

名前解決してやれば事足りてしまった。

ということで今回はAWSの設定見送り。

 

月額$3.5、遊びでポイポイたてるにはちと高いが、

ちゃんと使う目的で建てるなら安いし、何よりラクチンだ。

 

 

 

後日、HTTPS化を行った。

やり方は複数あるみたいで、

lightsailで立てたredmineHTTPS化する手順を書いたサイトを探したが、

certbot-autoを入れるやり方はredmine 404 errorとでてうまくいかん。

結局、lego clientを使うこれでうまくいった。

Generate and Install a Let's Encrypt SSL Certificate for a Bitnami Application

lightsail環境だとApacheが動いているみたいなのでApacheの場合を選んでいけばOK。

bitnami公式ドキュメントだから手順も安心

このサイトにたどり着くまでに3時間、たどり着いてからは10分でできた。。。

 

 

進捗

f:id:Messerarche:20200520211343p:plain

 

 

AWSをいじり倒す(11.リソースグループ)

組織アカウントを使っている関係で、人目に付かないところでテストを行おうと思ってオハイオリージョンで作業をしていたのだが、リソースグループ機能使えば同一リージョンでも見えなくできるのでは?という話がでたので試してみる。(Azureのリソースグループ機能ならそういうことができるらしい。)

 

ちなみに先に結論を書いておくと、残念ながら見えなくすることはできないみたいだ。

AWSマネジメントコンソールにおいて、IAMユーザごとに参照(表示)できるEC2インスタンスを制御したい - Qiita

ここに書いてあるように、人目から隠すなら(今の自分の環境では)リージョンを変えるのが最良。

 

 

ただ、色々触っているせいでサービスが乱立しているのは間違い無いので、

管理のためにリソースグループを使ってみる。

AWS リソースグループ とは? - AWS リソースグループ

 

手順はこちらを参考に

[AWS]リソースグループを使って、テスト・ステージング・本番環境ごとにAWSリソースを管理する | Developers.IO

 

ここから設定開始

f:id:Messerarche:20200519123021p:plain

 

グループの作成

f:id:Messerarche:20200519123140p:plain

 

リソースタイプは全て、でいいとして

タグ・・・

f:id:Messerarche:20200519123524p:plain

ああ〜〜こうなるのかー。今まで適当につけてきたツケがw

統一しとけばよかった

タグもNameじゃなくて、リソースグループ用のタグを1個作った方がよさそう

 

 

そんなあなたにタグエディター。タグをまとめて変更できる便利な機能。

f:id:Messerarche:20200519125044p:plain

f:id:Messerarche:20200519125023p:plain

 

 

条件を指定して検索し、出てきたリソースを選んで、タグを管理するボタンを押す

f:id:Messerarche:20200519125132p:plain

 

 

Nameは個を識別するために残しておきたいので、

envというタグを作り(何でもいいが参考にしていた記事がenvとつけたので真似した)

今回の作業に関するもの全てにproject-testとつけることにした

f:id:Messerarche:20200519125239p:plain

 

 

こんな感じでまとめて設定される

f:id:Messerarche:20200519125629p:plain

この調子で今まで作ってきたリソースにポチポチとenvタグをつけていく

 

 

改めてリソースグループ作成画面に戻って、

env project-testを指定

f:id:Messerarche:20200519130107p:plain

 

一つのタグでずらずらでるようになった。

f:id:Messerarche:20200519130249p:plain

 

 

グループ名と、このグループそのものにつけるタグの設定。

f:id:Messerarche:20200519130343p:plain

 

 

できた。

f:id:Messerarche:20200519124724p:plain

 

 

使い方。

 

 

色々探したが、下図のような参考記事にある超便利そうな画面が出したいのに見当たらない・・・。なんで?

f:id:Messerarche:20200519133911p:plain

 

リソースグループの画面から、まとめあげた各リソースにアクセスできるのは確認。

f:id:Messerarche:20200519133742p:plain

便利かもしれないがレイアウトが不満だなぁ。

 

 

また、タグを使って絞り込むことは可能だけど

f:id:Messerarche:20200519135051p:plain

あくまでただのタグによる絞り込みなので、リソースグループの便利さってわけではない。

 

では、どんな時にリソースグループを使えばいいのか。

複数人で管理する時に、作った本人はどんなサービス使ってるかだいたい把握しているけど別の人がみる場合はどこで何使っているのかわからないので、リソースグループとしてまとまってみれたほうがありがたい、とか。

 

また、リソースグループをRun Commandの対象にできるらしいので、これを使う場合は便利かも。

Run Commandのターゲットとしてリソースグループが選択可能になりました | Developers.IO

 

ということでリソースグループそれ自体はふーんという感じだが

タグは個を識別するNameと、グループを識別するenvの2つつけていきましょうってのが今回の学び。

AWSをいじり倒す(10.Route53)

もっと早くにやれば良かったと思いつつ、DNSサービスたるRoute53を触ってみる。

具体的には、

Route53 でDNSフェイルオーバーを設定する。 - Qiita

を参考にして、DNSフェイルオーバーを使ったsorryページ表示を試してみることにする

ELBは対象をEC2にしかできない(その分ヘルスチェックをきめ細やかに設定できる)がDNSフェイルオーバーはEC2、S3、ELBを対象にできる。

また、S3で簡易なHP(sorryページ用)を作れるというのも面白い点だ

 

まずは思い出しながらELB環境を作成。

f:id:Messerarche:20200519210251p:plain

ELBからは(無駄に)AutoScailingで作成した2台のEC2がぶら下がっており、

そのどちらでもWebサーバが立っている状態。

 

 

 

次にS3にsorryページを作ってみる。

ちなみに、バケット名はドメイン名と同一にしなければならないという注意書きがあるのだが、この時点ではその意味がよく理解できていないので名前は後で変更する。

(変更というか、削除して作り直す)

f:id:Messerarche:20200519211528p:plain

 

 

Static website hositingから

f:id:Messerarche:20200519211632p:plain

ウェブサイトをホストしますを選択し

インデックスドキュメントの名前(index.html)を書いて、保存。

 

せっかくなのでAWS CLIを使って、index.htmlを送り込むことにする

適当なEC2上で20年前ぐらいに覚えた化石htmlでindex.htmlを作成し、保存

f:id:Messerarche:20200519214712p:plain

 

アップロード実行

f:id:Messerarche:20200519214916p:plain

 

この状態で直接アクセスしてみたらどうなるのか試してみたら

f:id:Messerarche:20200519215140p:plain

AccessDenied。S3のパブリックアクセスの設定してないせいだとおもう。

 

こいつのチェックを外して再トライしてみる

f:id:Messerarche:20200519215220p:plain

 

f:id:Messerarche:20200519215433p:plain

・・・だめですね。

 

index.htmlの権限を確認してみる。アクセス権限のところをクリック。

f:id:Messerarche:20200519215759p:plain

 

出てきた画面

f:id:Messerarche:20200519215555p:plain

ここのパブリックアクセスの許可っぽいな〜〜

 

読み取り許可を出して保存。

f:id:Messerarche:20200519215649p:plain

 

リトライ結果やいかに

f:id:Messerarche:20200519215907p:plain

でた!

静的なHPであればもうこれでいいんじゃ無いのってぐらい簡単だ。

まあでもS3ってダウンロード量に応じてお金がかかるから、アクセスされればされるほどお金取られることになる。そう思うと動画コンテンツとかうかうか載せてらんないし、sorryページ利用ぐらいがちょうどいいのかもしれん。

S3なら絶対にダウンしないのも魅力。耐久性99.999999999%は伊達じゃない。

 

 

さて、次にRoute53を設定していく

 

ヘルスチェックの設定。このOKNG結果でフェイルオーバーを機能させることになる。

f:id:Messerarche:20200519220633p:plain

 

ヘルスチェックの環境設定

f:id:Messerarche:20200519223803p:plain



まずはELBのヘルスチェック設定ということで名前にELBを入れた。

他のヘルスチェックのステータス・・・でELBのヘルスチェックが指定できるのかな?と一瞬思ったが、どうも違うらしい

Amazon Route 53 がヘルスチェックの正常性を判断する方法 - Amazon Route 53

Route53内でヘルスチェックに親子関係を作って、子のヘルスチェック結果を親が利用する・・・と読めた。

今回はエンドポイントを選択。

 

監視対象の設定

f:id:Messerarche:20200519223832p:plain

ドメイン名指定で、ELBのドメインを指定

 

高度な設定

f:id:Messerarche:20200519224314p:plain

文字列マッチングというのが気になった。

ポーリングのレスポンスに含まれる文字列をみて、指定文字列が入ってて初めてOKと見なすものらしい。いつ使うんだろうと思って調べたら、事例を見つけた。

Route53 ヘルスチェックのエンドポイント設定のわな - Qiita

へぇ〜

 

最後に通知設定

f:id:Messerarche:20200519224730p:plain

作成。

 

 

 

S3版ヘルスチェックも作成する

f:id:Messerarche:20200519225112p:plain

 

結果を見てみると

f:id:Messerarche:20200519225315p:plain

 

ELBがうまくいってない。各地のヘルスチェッカーさんがFailureを出している。

 

そういやセキュリティーグループの設定はどうなってたっけ。

f:id:Messerarche:20200519225541p:plain

黒塗りしているが、マイIPしか許可していなかったw

 

う〜ん、でもこのブログに堂々とドメインとか書いているので

誰からもアクセスOKにはしたくない・・・せや!

 

これを・・・

f:id:Messerarche:20200519230006p:plain


こうして・・・・

f:id:Messerarche:20200519230040p:plain

 

こうじゃ

f:id:Messerarche:20200519230122p:plain

 

 

正常で結果もSuccessとなったのでヨシ!

f:id:Messerarche:20200519230632p:plain

 

 

いよいよDNSフェイルオーバーの作成・・・がここで引っかかる。

DNSフェイルオーバーを設定してみたというブログ記事はいくつか見かけたが

どれもこれも既に独自のドメイン名を取得している状態から始まっており

今回のように0から設定する時のことが考えられた記載になっていないようだ。訴訟!

 

このように最初、ホストゾーン設定は空である。

f:id:Messerarche:20200519231444p:plain

 

さらにこのドメイン名、AWSで取得すると結構な金がかかる。

詳しくはここに書いてあるが、年間契約でどんなに安くても9$からっぽい。

さすがに使い捨てに1000円はかけられない・・・。

 

ということで無料ドメインを取ってくることにするが

最終的にIPアドレスに解決するのはAWSなので、AWSのネームサーバに名前解決を委託

つまりNSレコードがかける無料DNSサーバでないといけない

・・・これがなかなか見当たらない。

AWS Route 53を使って独自ドメインのWebページを表示させてみよう | Avintonジャパン株式会社

うまくいっている例っぽいこれを参考にfreenomもアクセスしてみたが、ドメインが取得不可と出て前に進まない、困った。

 

 

苦肉の策として、ゴリ押しで架空ドメインを登録することにした。

まずは、適当に

test12345domain.ddns.net

を使うことに決める。

 

 

で、これを先ほどのドメイン名のところに放り込んで、

パブリックホストゾーンで登録

f:id:Messerarche:20200519234619p:plain

 

するとこの

test12345domain.ddns.netを

解決してくれるネームサーバ一覧が見えるようになる。

f:id:Messerarche:20200520010704p:plain

 

 

 

フェイルオーバーの設定兼、このドメインを何のIPで解決したらいいかを設定する。

f:id:Messerarche:20200519234839p:plain

レコードセットの作成から

Aレコードの設定。エイリアス先にELBのDNSを指定。

f:id:Messerarche:20200519235536p:plain

これでweb.test12345domain.ddns.netをAWSのネームサーバに聞きにきたら、

ELBのドメイン名(で解決できるIPアドレス)を返却してくれるようになる。

ルーティングポリシーはフェイルオーバーにして、こちらはプライマリ

 

ヘルスチェックとの関連付けも有効にして、先ほど作ったヘルスチェックを指定

f:id:Messerarche:20200519235713p:plain

 

作成。

 

さて、改めて今どういう状況かというと、

普段インターネットを使う環境で名前解決しようとすると失敗する。

なぜならweb.test12345domain.ddns.netは世界に向けて公開されていないからだ。

f:id:Messerarche:20200520010445p:plain

(この世界に向けて公開、というのが無料DNSサービスにお願いしようとしていた部分であり、AWSにお願いすると1000円取られる部分である。)

 

でも、AWSのネームサーバさんに直接、お前知ってるよな?と聞くと答えてくれる!

さきほど教え込んだからだ。

f:id:Messerarche:20200520010525p:plain

 

あとはパソコンのDNSサーバ設定を

awsのネームサーバに指定してしまえばゴリ押しの完成である。

Macだとここ。WindowsならIPアドレス設定するところの下のほうに入力できる

f:id:Messerarche:20200520024028p:plain

 

パソコンの設定を変えたあとはコマンド上でDNSサーバ指定しなくても名前解決できる。

f:id:Messerarche:20200520011923p:plain

この状態でブラウザにweb.test12345domain.ddns.netを放り込むと

ELB越しにEC2で動いているWebサーバのページが表示された。

 

フェイルオーバーの設定を続ける。フェイルオーバー先のS3について、

前述の通りS3のバケット名は「S3のバケット名をプライマリサイトのドメイン名と同じにする」ことが必要なので、改めて作成する。

つまり今回はweb.test12345domain.ddns.netという名前のバケットが必要ということになる。

f:id:Messerarche:20200520012548p:plain

こんなかんじ。index.htmlの設置などは先に説明した通りなので割愛。

 

Route53に戻ってきて、再度レコードセットを作成する。

f:id:Messerarche:20200520012704p:plain

エイリアス先に今作ったS3を指定する。

フェイルオーバーをセカンダリにして、

ヘルスチェックとの関連付けも、はいに。

バケット名変えたのでヘルスチェックの対象設定も変更しなおした。)

これで、設定は完了。

 

ようやくテストを行っていく。

まずは普通に繋がることを確認。

f:id:Messerarche:20200520014316p:plain

 

次に、ELB配下のEC2を停止する

f:id:Messerarche:20200520014343p:plain

するとこいつらへのヘルスチェックが失敗して・・・

f:id:Messerarche:20200520014430p:plain

切り替わる!

f:id:Messerarche:20200520014444p:plain

しばらくのち、Auto-Scalingが働いて新しいEC2が建つ

f:id:Messerarche:20200520014559p:plain

 

ホームページ復活。

f:id:Messerarche:20200520014316p:plain

 

きれいに動いた〜!

欲を言うと、フェイルオーバーの切り替わりにはそこそこ時間がかかったので

ヘルスチェックの間隔はもっと短くていいと思った。

今は30秒間隔で3回失敗したら異常と判定するので切り替わりに90秒かかる。

10秒間隔にも設定できるので、早く切り替えたい場合はこちらかな。

 

途中謎の工夫をしたせいでめちゃめちゃ時間がかかってしまった

ホストゾーン設定も存在しているだけで毎月そこそこのお金を取られるらしいので、最後に全消しして、終わり。Webページ用のS3も削除。

本記事に書いてあるIPやドメインにアクセスしても繋がらないのであしからず。

 

 

進捗。いい加減図を整理しないと辛くなってきたぞ

f:id:Messerarche:20200520022336p:plain