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
もう一つはEFSにアタッチするためのlambda-efs-sg
こちらはインバウンドでNFSの2049を許可する
あとはEC2にアタッチするSSHが許可されたSG
まあこれはおそらく既存のものがあるはず
次にEFSを準備
さっき作ったVPCを指定し
セキュリティグループはlambda-efs-sgを指定
もう一つ設定が必要なのはアクセスポイントのところ
lambdaにEFSの操作権限を与える。
このまま作成を完了
lambdaの設定
次にlambdaの関数画面へ
アクセス権限を設定する
ロール名をクリックしてIAMの画面を開き、以下の二つのポリシーをアタッチ
次にlambda関数のVPCの設定へ
ここのサブネットで作った2つともを登録
セキュリティグループはlambda-sg
で作成。
ちょっと時間がかかって、できましたのメッセージ。
lambdaが裏で動かすEC2にネットワークインタフェースを作ったりなんやりしてたみたい
次にいよいよファイルシステムとの接続
さて・・・
EFSを選んだら、マウントするターゲットポイントが出てきた。
さっきEFSで設定したアクセスポイントだ。
ローカルマウントパスには適当に
/mnt/slp
と設定。
EFSへのパッケージインストール
さて、ここからが問題
新しいVPCのパブリックサブネットでAmazon Linux EC2インスタンスを起動します。インスタンスの詳細で、EFSマウントポイントがあるアベイラビリティーゾーンの1つを選択してから、[Add file system ]を選択して、関数に使用しているのと同じEFSを自動的にマウントします。 EC2インスタンスのセキュリティグループには、
default
のセキュリティグループ(EFSをマウントできるようにする)とSSHへのインバウンドアクセスを与える(インスタンスに接続できるようにする)セキュリティグループを選択します。
ほほー、EC2を立ち上げて、EFSをマウントしろと。面白いな
AMIに関してなにも書いてないが、python3.8で試しているようなので
EC2作成手順の途中で、ファイルシステムにEFSを追加・・・したのだが
これは後々なぜかうまくいかなかったのでやめた。
普通にEC2を起動して、EFSをマウントしたほうがよい。
なんでうまくいかなかったのか原因を探る元気がないので、うまくいく手順を記すことに力を使う
立ち上がったEC2にて
sudo mkdir efslambda
sudo mount -t efs -o tls,accesspoint=[アクセスポイント名] [ファイルシステムID] efslambda
してマウントする。詳細は過去記事をみてください。
ちなみに今後のインストール作業に割と時間がかかるので
EC2はメモリ4GBぐらいのを選んだ方がいい。無料枠じゃないけど。
今回必要なパッケージ情報は以下。
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
sudo yum install python3.8 -y
echo 'alias python=python3.8' >> ~/.bashrcsource ~/.bashrc
python -V
(2022/12/20更新ここまで)
無事、pythonのインストールが終わったら
pip3.8 install -t /efslambda/lib38 -r requirements.txt
で各種パッケージをインストール。
結構時間がかかる
無事終わったら
最後に、EFSアクセスポイントに使用したユーザーとグループに
/ml
パス全体の所有権を与えます。
以下を実行。
sudo chwon -R 1001:1001 /efslambda
lambdaの動作環境設定
次はlambda関数に戻ってきて、環境変数の書き換え
使用するランタイムに応じて、依存関係が展開パッケージに含まれていないか、レイヤーに含まれていない場合に、依存関係を探す場所を指示する方法を見つける必要があります。 Pythonの場合、
PYTHONPATH
環境変数を/mnt/inference/lib
に設定しています。
だそうなので、PYTHONPATHをさっきパッケージを詰め込んだ/mnt/slp/lib38に割当
ガイドではモデルもEFSに入れているみたいだけど、まずは動くところを確認したいのでこれで。
次に基本設定もいじる
ランタイム=Python3.8
メモリ=1024MB
タイムアウト=3分
実行してみる
いよいよ必要なパッケージを全部importして実行してみる
実行!
やった〜!
ブログだと1本道で成功を歩んでいるが、
実際はいろいろあって半日以上費やし、もう目がしぱしぱ。
後日談
EFS配下にモデルとインプットファイルを置いて、機械学習の推論を実行してみた。
ソース全部は載せられないが、一部抜粋でこんな感じ
結果・・・成功!気持ちいい〜
おわりに
まあでもserverlessだのレイヤーだのzipで固めるだの言う話よりは断然わかりやすいし
コードもコンソール上でいじれて扱いやすいし
設定さえうまくできれば良いことしかない。最高だ。
ということでようやく下地が整ったので、
モデルファイル食わせたり、トリガーの設定したりができる。
それはまた今度で。
おまけ1
ubuntu使っているので完全には参考にならなかったが
動画でセットアップする手順公開してる人がいたので貼っておく
おまけ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のインストール
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
成功!
serverlessからAWSにアクセスするためのIAMアカウントを作成
プログラムによるアクセスを選択してユーザを作成。
AdministratorAccessを付与。
・・・なんか与えすぎな気もするが一旦作成。
lambdaにデプロイするときにcroud formation使ったりS3バケット作ったりと
いろんなことしまくるようなので、まとめてエイヤ権限ってことなんだろう。
ローカル端末から以下のコマンドを実行してserverlessからawsにアクセスできるようにする
serverless config credentials --provider aws --key [アクセスキーID] --secret [シークレットアクセスキー]
以下の文が返ってきたら成功
Serverless: Setting up AWS...
プロジェクトを作る。pythonを使うのでtemplateはaws-pythonを選択
コマンドを実行したディレクトリに
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-requirementscustom:
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:
passimport 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-requirementsprovider:
name: aws
region: ap-northeast-1
runtime: python3.7
stage: devcustom:
pythonRequirements:
dockerizePip: true
layer:
compatibleRuntimes:
- python3.7
slim: true
strip: falseresources:
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するコマンドを放り込む。
こ、コンソール上でプログラムの変更ができない・・・。
つまり毎回デプロイせなあかんのか!?
デプロイ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を選ばないといけない点
今回使おうとしている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をメモっておく
lambdaの画面に移動
Additional Resourcesからレイヤーを選択、レイヤーの作成
レイヤーの作成。
S3からアップロードを選択し
リンクURLに先ほどメモしたURLを貼る
互換性のあるランタイムオプションはPython3.7を選択
次に関数の作成
まずはHello Worldから。
ロールは特に用意していないので作ってもらう
関数の作成を実行。
ほどなくして作成が完了
何かいろいろできそう(小並感)
ともあれ関数を実行してみる。
右上のテストボタンを押す
こんな画面が出てくるので、イベント名に適当にhelloと入力、作成
再度テストを実行
結果がずらずらとでてきた。とりあえずは動いたようだ。
さて、問題のimport pandasができるのかを試す
レイヤーを選択
お客様のレイヤーにさっき登録したレイヤーが出てきた。
numpyとscipyならデフォルトで用意してくれとるのね。
ちなみに、余談だが試行錯誤してるときはこんな怒られ方をした
どうも、追加パッケージは合計262MBまでしかだめらしい。
AWS LambdaでTensorFlow 2.0を使った画像分類 - ユニファ開発者ブログ
この辺にいかにやりくりするか、みたいなテクニックが書いてあった。
ええ、そこって気を使わないかんとこなの・・・。
いろんなものimportして大きめのプログラム動かそうと思ったらlambdaは諦めて
EC2で普通に動かすしかないのかも。
とりあえず追加は完了。
プログラムにimport pandasとかを追加してテストしてみる。
ソースを変更したら、Saveしたのちにテストを実行
どうやらうまくいったらしい。
import kerasも試してみる
ぐえ、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
ずらずら、とインストールされた中からダメ元で重そうなのを消してみる。
tensorboardとかは確かにいらんよなぁ
容量を確認するコマンドを打ってみる
du -sh ./*/
本体が1.5GB〜!!
犯人探ししていこう
これか。
これ消しちゃまずそうなやつ・・・え、みんなどうやってんの?
Running TensorFlow on AWS Lambda using Serverless - Mike Moritz - Medium
slim
— Removes unneeded files and directories such as *.so
, *.pyc
, dist-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
レイヤーに登録しようとすると
これでもでかすぎてだめか。
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は最初から入っているので不要。
リポジトリ を準備。
作業ディレクトリは適当に以下とした。
/home/bitnami/git/repos
リポジトリ を作成
なお、pushするたびにupdate-server-infoしないといけないらしいので
それを回避する設定もいれておく
実行権限も付与
bitnamiで建てたRedmineの、Apacheやwww-なんとかみたいなユーザ相当はdaemon。
それはこのサイトをみて知った。
Amazon Lightsailの諸々ファイル置場 | It works for me
他にもログの場所など有益な情報がまとまっていてありがたい
gitでやり取りする時に、必ずユーザとパスワードを要求したいので、その準備。
-bをつけて1ラインで登録してしまわないとバグるみたいな記載をみたので念の為書いておく
Apache用コンフィグの作成
bitnami式redmineの裏で動いているのはApache。
主にこのディレクトリ 配下にいろんなconfigが入っている
/opt/bitnami/apache2/conf/
この配下で作業を行っていく
git.confを新たに作成。
まずは最小構成の内容をgit.confに記載する。
このgit.confを読み込んでもらうために、同一ディレクトリにあるhttpd.confの最終行に
を追加
これで最小構成が完成。システムのリスタートを行う。
bitnami式redmineのリスタートコマンドは以下。
いったんここまででテスト。
ローカル環境にて、cloneを試す。
ユーザ名入力
パスワード入力
Cloning into 'test'...
warning: You appear to have cloned an empty repository.
この返答がくればOK
ちなみに、まだcloneはできてもpushはできない。
[master 452f009] first commit
1 file changed, 0 insertions(+), 0 deletions(-)
create mode 100644 testfile
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を有効化する手順は巷にたくさん書いてあるが、
それをそのまま入れると失敗するのが最大のハマりポイント。
具体的にはこういうやつだ
上3行を追加し、取り消し線のところを削除
他にもなんだか装飾されたコンフィグが公開されているが、最低限これだけでいい。
リスタートしてconfファイルを読み込む
すると、ローカルで実行した結果がこうなる
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インストール
ユーザグループ設定
git.confを大改造。Subversionとかは使わないので自分用に多少アレンジ
モジュールの配置
そして
すると、無事clone/pushどちらも動いた。
先人の知恵さまさま・・・!
これで、http通信+password要求でgitが使える環境が完成。
redmineとgitの連携は
あたりをみながら設定してなんなく動いた。
で
ここからはうまくいっていなのでただの参考記事
どうもredmineで作ったID/PASSをgitの認証に使うことができるとのこと
これは便利と思って試そうとして死んだ。
先人様のサイトにあるこのconfigをgit.confに追加でぶちこむ。
なお、DbPassは
/opt/bitnami/apps/redmine/htdocs/config/database.yml
に書いてある。
これでclone実行するとこんな感じのエラー
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
なんでこのエラーがでるかの仕組みがしっかりと書いてあるが、
悲しいかなこのサイトの結論は
「サポートに繰り返し言ってくしかないね!」
こっちは気合で解決しましたと書いてある
過去サーバから設定ファイルをコピーしてきて、config書き換えたらうまくいったんだと。
試しにファイルをいくつかそれっぽいコピーしてみたけど、
そこまで知識がないので泥沼化して諦めた。つら。
どうも昔のredmineにはちゃんと入ってたモジュールっぽいんだよなぁ。
現時点の最新(4.1.0-8)には含まれてないのは謎
AWSをいじり倒す(12.Amazon Lightsail)
今回は勉強ではなく、仕事でLightsailを使ってredmineサーバを建てることになったのでついでに記事化
そもそもLightsailとは何か
Amazon Lightsailとは?EC2との違いとメリット・デメリットを調べてみた | NHN テコラス Tech Blog | AWS、機械学習、IoTなどの技術ブログ
簡単に言うとAWSのパッケージ商品。
何も考えなくてもちゃんとした構成で用意してくれる。
何だかえらいポップな画面からスタート。
ロケーションの選択。国旗まで出しちゃってまあ。
明らかに他のサービスとは異質w
プラットフォームの選択
Windowsだとできることは現時点でほとんどなく、
どのアプリ入れますか
複数選択はできない。今回はRedmine
キーペアの設定
デフォルトだと、キーの名前を自動生成してくれるみたい。
デフォルトキーを手元にダウンロードしておく。
スナップショットは・・・うーんいるようないらんような
月額$0.05/GBで、2回目以降は増分のみとのことなのでとりあえず有効化。
お値段。月額$3.5は安い。
派手な使い方しないしこれでよさそう。後から増築もできるし。
リソース名の設定とか、インスタンス数の指定とか。
このキータグはLightsailのリソースの中だけで使うものみたいだ。
用途は普通に管理のため。
Amazon Lightsail のタグ | Lightsail ドキュメント
でもわざわざキーオンリータグを準備した意味がわからん。キー値タグでいいやん
せっかくなのでつけてみた。
作成ボタンポチー
こんばんは!
過剰にユーザフレンドリー感だしてるなぁ。
AWSとっつきにくい人向けなのかね。
ほどなくしてできた。
独自のSSHクライアントも提供してくれているみたいだが、
IPとユーザ名と、先ほどダウンロードしたキーがあるので
EC2にアクセスするのと同じ要領でSSHで接続。
つながった
そしてこの黒塗りのところにブラウザからのログインパスワードが書いてある
パブリックIPをブラウザに放り込むと
無事表示された。
仕上げの設定。
IPアドレスの固定化。無料だから必ずやろう。
ネットワーキングから静的IPの作成
ロケーションは東京、インスタンスは先ほど作ったものを指定
静的IPの指定で一意な名前をつける
アタッチしている間は無料ですよ、と。
ちなみにアタッチしないと$0.005/h取られる模様。無駄に確保すんなってことね
作成を押すと静的IPが取得できた。アタッチもそのまましてくれたっぽい
早速このIPアドレスでRedmineにログインできることが確認できた。
DNSの設定も行えるらしい。
静的IPを設定した後、新たなメニューが増えている
が、今回はLBも使わないので
名前解決してやれば事足りてしまった。
ということで今回はAWSの設定見送り。
月額$3.5、遊びでポイポイたてるにはちと高いが、
ちゃんと使う目的で建てるなら安いし、何よりラクチンだ。
後日、HTTPS化を行った。
やり方は複数あるみたいで、
lightsailで立てたredmineをHTTPS化する手順を書いたサイトを探したが、
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分でできた。。。
進捗
AWSをいじり倒す(11.リソースグループ)
組織アカウントを使っている関係で、人目に付かないところでテストを行おうと思ってオハイオリージョンで作業をしていたのだが、リソースグループ機能使えば同一リージョンでも見えなくできるのでは?という話がでたので試してみる。(Azureのリソースグループ機能ならそういうことができるらしい。)
ちなみに先に結論を書いておくと、残念ながら見えなくすることはできないみたいだ。
AWSマネジメントコンソールにおいて、IAMユーザごとに参照(表示)できるEC2インスタンスを制御したい - Qiita
ここに書いてあるように、人目から隠すなら(今の自分の環境では)リージョンを変えるのが最良。
ただ、色々触っているせいでサービスが乱立しているのは間違い無いので、
管理のためにリソースグループを使ってみる。
AWS リソースグループ とは? - AWS リソースグループ
手順はこちらを参考に
[AWS]リソースグループを使って、テスト・ステージング・本番環境ごとにAWSリソースを管理する | Developers.IO
ここから設定開始
グループの作成
リソースタイプは全て、でいいとして
タグ・・・
ああ〜〜こうなるのかー。今まで適当につけてきたツケがw
統一しとけばよかった
タグもNameじゃなくて、リソースグループ用のタグを1個作った方がよさそう
そんなあなたにタグエディター。タグをまとめて変更できる便利な機能。
条件を指定して検索し、出てきたリソースを選んで、タグを管理するボタンを押す
Nameは個を識別するために残しておきたいので、
envというタグを作り(何でもいいが参考にしていた記事がenvとつけたので真似した)
今回の作業に関するもの全てにproject-testとつけることにした
こんな感じでまとめて設定される
この調子で今まで作ってきたリソースにポチポチとenvタグをつけていく
改めてリソースグループ作成画面に戻って、
env project-testを指定
一つのタグでずらずらでるようになった。
グループ名と、このグループそのものにつけるタグの設定。
できた。
使い方。
色々探したが、下図のような参考記事にある超便利そうな画面が出したいのに見当たらない・・・。なんで?
リソースグループの画面から、まとめあげた各リソースにアクセスできるのは確認。
便利かもしれないがレイアウトが不満だなぁ。
また、タグを使って絞り込むことは可能だけど
あくまでただのタグによる絞り込みなので、リソースグループの便利さってわけではない。
では、どんな時にリソースグループを使えばいいのか。
複数人で管理する時に、作った本人はどんなサービス使ってるかだいたい把握しているけど別の人がみる場合はどこで何使っているのかわからないので、リソースグループとしてまとまってみれたほうがありがたい、とか。
また、リソースグループを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環境を作成。
ELBからは(無駄に)AutoScailingで作成した2台のEC2がぶら下がっており、
そのどちらでもWebサーバが立っている状態。
次にS3にsorryページを作ってみる。
ちなみに、バケット名はドメイン名と同一にしなければならないという注意書きがあるのだが、この時点ではその意味がよく理解できていないので名前は後で変更する。
(変更というか、削除して作り直す)
Static website hositingから
ウェブサイトをホストしますを選択し
インデックスドキュメントの名前(index.html)を書いて、保存。
せっかくなのでAWS CLIを使って、index.htmlを送り込むことにする
適当なEC2上で20年前ぐらいに覚えた化石htmlでindex.htmlを作成し、保存
アップロード実行
この状態で直接アクセスしてみたらどうなるのか試してみたら
AccessDenied。S3のパブリックアクセスの設定してないせいだとおもう。
こいつのチェックを外して再トライしてみる
・・・だめですね。
index.htmlの権限を確認してみる。アクセス権限のところをクリック。
出てきた画面
ここのパブリックアクセスの許可っぽいな〜〜
読み取り許可を出して保存。
リトライ結果やいかに
でた!
静的なHPであればもうこれでいいんじゃ無いのってぐらい簡単だ。
まあでもS3ってダウンロード量に応じてお金がかかるから、アクセスされればされるほどお金取られることになる。そう思うと動画コンテンツとかうかうか載せてらんないし、sorryページ利用ぐらいがちょうどいいのかもしれん。
S3なら絶対にダウンしないのも魅力。耐久性99.999999999%は伊達じゃない。
さて、次にRoute53を設定していく
ヘルスチェックの設定。このOKNG結果でフェイルオーバーを機能させることになる。
ヘルスチェックの環境設定
まずはELBのヘルスチェック設定ということで名前にELBを入れた。
他のヘルスチェックのステータス・・・でELBのヘルスチェックが指定できるのかな?と一瞬思ったが、どうも違うらしい
Amazon Route 53 がヘルスチェックの正常性を判断する方法 - Amazon Route 53
Route53内でヘルスチェックに親子関係を作って、子のヘルスチェック結果を親が利用する・・・と読めた。
今回はエンドポイントを選択。
監視対象の設定
高度な設定
文字列マッチングというのが気になった。
ポーリングのレスポンスに含まれる文字列をみて、指定文字列が入ってて初めてOKと見なすものらしい。いつ使うんだろうと思って調べたら、事例を見つけた。
Route53 ヘルスチェックのエンドポイント設定のわな - Qiita
へぇ〜
最後に通知設定
作成。
S3版ヘルスチェックも作成する
結果を見てみると
ELBがうまくいってない。各地のヘルスチェッカーさんがFailureを出している。
そういやセキュリティーグループの設定はどうなってたっけ。
黒塗りしているが、マイIPしか許可していなかったw
う〜ん、でもこのブログに堂々とドメインとか書いているので
誰からもアクセスOKにはしたくない・・・せや!
これを・・・
こうして・・・・
こうじゃ
正常で結果もSuccessとなったのでヨシ!
いよいよDNSフェイルオーバーの作成・・・がここで引っかかる。
DNSフェイルオーバーを設定してみたというブログ記事はいくつか見かけたが
どれもこれも既に独自のドメイン名を取得している状態から始まっており
今回のように0から設定する時のことが考えられた記載になっていないようだ。訴訟!
このように最初、ホストゾーン設定は空である。
詳しくはここに書いてあるが、年間契約でどんなに安くても9$からっぽい。
さすがに使い捨てに1000円はかけられない・・・。
ということで無料ドメインを取ってくることにするが
最終的にIPアドレスに解決するのはAWSなので、AWSのネームサーバに名前解決を委託
つまりNSレコードがかける無料DNSサーバでないといけない
・・・これがなかなか見当たらない。
AWS Route 53を使って独自ドメインのWebページを表示させてみよう | Avintonジャパン株式会社
うまくいっている例っぽいこれを参考にfreenomもアクセスしてみたが、ドメインが取得不可と出て前に進まない、困った。
苦肉の策として、ゴリ押しで架空ドメインを登録することにした。
まずは、適当に
test12345domain.ddns.net
を使うことに決める。
で、これを先ほどのドメイン名のところに放り込んで、
パブリックホストゾーンで登録
するとこの
test12345domain.ddns.netを
解決してくれるネームサーバ一覧が見えるようになる。
フェイルオーバーの設定兼、このドメインを何のIPで解決したらいいかを設定する。
レコードセットの作成から
これでweb.test12345domain.ddns.netをAWSのネームサーバに聞きにきたら、
ELBのドメイン名(で解決できるIPアドレス)を返却してくれるようになる。
ルーティングポリシーはフェイルオーバーにして、こちらはプライマリ
ヘルスチェックとの関連付けも有効にして、先ほど作ったヘルスチェックを指定
作成。
さて、改めて今どういう状況かというと、
普段インターネットを使う環境で名前解決しようとすると失敗する。
なぜならweb.test12345domain.ddns.netは世界に向けて公開されていないからだ。
(この世界に向けて公開、というのが無料DNSサービスにお願いしようとしていた部分であり、AWSにお願いすると1000円取られる部分である。)
でも、AWSのネームサーバさんに直接、お前知ってるよな?と聞くと答えてくれる!
さきほど教え込んだからだ。
あとはパソコンのDNSサーバ設定を
awsのネームサーバに指定してしまえばゴリ押しの完成である。
Macだとここ。WindowsならIPアドレス設定するところの下のほうに入力できる
パソコンの設定を変えたあとはコマンド上でDNSサーバ指定しなくても名前解決できる。
この状態でブラウザにweb.test12345domain.ddns.netを放り込むと
ELB越しにEC2で動いているWebサーバのページが表示された。
フェイルオーバーの設定を続ける。フェイルオーバー先のS3について、
前述の通りS3のバケット名は「S3のバケット名をプライマリサイトのドメイン名と同じにする」ことが必要なので、改めて作成する。
つまり今回はweb.test12345domain.ddns.netという名前のバケットが必要ということになる。
こんなかんじ。index.htmlの設置などは先に説明した通りなので割愛。
Route53に戻ってきて、再度レコードセットを作成する。
エイリアス先に今作ったS3を指定する。
フェイルオーバーをセカンダリにして、
ヘルスチェックとの関連付けも、はいに。
(バケット名変えたのでヘルスチェックの対象設定も変更しなおした。)
これで、設定は完了。
ようやくテストを行っていく。
まずは普通に繋がることを確認。
次に、ELB配下のEC2を停止する
するとこいつらへのヘルスチェックが失敗して・・・
切り替わる!
しばらくのち、Auto-Scalingが働いて新しいEC2が建つ
ホームページ復活。
きれいに動いた〜!
欲を言うと、フェイルオーバーの切り替わりにはそこそこ時間がかかったので
ヘルスチェックの間隔はもっと短くていいと思った。
今は30秒間隔で3回失敗したら異常と判定するので切り替わりに90秒かかる。
10秒間隔にも設定できるので、早く切り替えたい場合はこちらかな。
途中謎の工夫をしたせいでめちゃめちゃ時間がかかってしまった。
ホストゾーン設定も存在しているだけで毎月そこそこのお金を取られるらしいので、最後に全消しして、終わり。Webページ用のS3も削除。
本記事に書いてあるIPやドメインにアクセスしても繋がらないのであしからず。
進捗。いい加減図を整理しないと辛くなってきたぞ