エンジニャーリング

技術ときどきネコ

EC2のAutoScalingと起動テンプレートと

AWSのAutoScalingの起動設定がAMIの入れ替えがめんどくさくて使いにくいな〜って思っていたところ、 起動テンプレートという機能があって、これが使い勝手が良い!
またこの起動テンプレートと組み合わせることで、AutoScalingの設定にもバリエーションが出てくる。

ということで早速やってみよう。

起動テンプレートの作成

EC2の左のメニューから起動テンプレートを選択 f:id:taiyakikuroann:20210621221903p:plain

右上の「起動テンプレートを作成」から始める。

f:id:taiyakikuroann:20210621221528p:plain

f:id:taiyakikuroann:20210621222130p:plain

f:id:taiyakikuroann:20210621222143p:plain

後の設定はデフォルトでオッケー。
無事にテンプレートが作成できました。

f:id:taiyakikuroann:20210621222159p:plain

次は、AutoScalingの設定。

EC2の左のメニューからAuto Scaling グループを選択 f:id:taiyakikuroann:20210621224129p:plain

なぜかこのメニューを選ぶとメニューが英語化する。
この現象に気がついてからしばらく経つけど一向に直る気配なし。
特に困ってないし、まぁ、いいか。

f:id:taiyakikuroann:20210621224327p:plain

起動テンプレートには先ほどのテンプレートを。

f:id:taiyakikuroann:20210621224345p:plain

これで次へ

ここから重要。
デフォルトの設定でも良いのですが、「購入オプションとインスタンスタイプを組み合わせる」を選ぶことでAutoScalingで起動するインスタンスにスポットインスタンスを取り入れることが可能になります。
これは使い方次第でかなり節約が見込めそう

f:id:taiyakikuroann:20210621224405p:plain

f:id:taiyakikuroann:20210621224425p:plain

常に立ち上げておく、オンデマンドインスタンスの数と、オンデマンドとスポットの比率の調整をここで設定

f:id:taiyakikuroann:20210621224447p:plain

ここも重要。
スポットインスタンスを多めに使う場合は、空き容量がなくなったらそもそも立ち上がらなくなるため(立ち上がってもすぐ死んだり)、使用するインスタンスタイプを分けて優先順位をつけておくことで、必要な数立ち上がらなくなるという事態を避けることができる。この時に必要なサイズに近いもので設定しておくのが良し。m5.largeとm4.largeとか。

f:id:taiyakikuroann:20210621224500p:plain

置き場所を選んで、次へ
(Multi AZしたい場合はSubnet2つ以上選ぶこと)

f:id:taiyakikuroann:20210621224515p:plain

ロードバランシングは一旦なしで、次へ

f:id:taiyakikuroann:20210621224541p:plain

最大最小数を設定する。とりあえず3台動くように設定してみる。

f:id:taiyakikuroann:20210621224557p:plain

EC2インスタンスの一覧で3台起動したことを確認できた。 オンデマンドインスタンスとスポットインスタンスの比率の調整がイマイチだったので、全部オンデマンドで立ち上がってしまいましたが、10台立ち上げたら、2〜3台がスポットインスタンスになっていたはず。
最初に設定するオンデマンドインスタンスの1台以上にしておけば、残りは全てスポットに当てるなどの設定をしてもいいかもしれない。この辺は運用見ながら調整していけばいいところなので、稼働が始まったら動きを観察して決めていけばいいかな。

また、起動テンプレートでは、AMIに変更があった場合にテンプレート側でバージョン管理ができて、起動設定のようにAMIが変わるたびにAutoScalingへのアタッチをやり直す必要もないので、管理コストも少し減りそうな予感。

EC2のAutoScalingよりも最近はサーバレスのLambdaとかコンテナベースのECSとかが主流になってきてそうだから、使う機会も減ってくるかもしれないけど、コスト削減には起動テンプレートは知っておいた方が良いかなと思います。

セッションマネージャ+ポートフォワーディングを利用したDB接続

前回のセッションマネージャー接続の続編。
セッションマネージャーで繋いだEC2を踏み台としてDB接続やるよ。

  • 前提:
    • セッションマネージャーの利用を完了させておくこと
    • EC2にキーペア鍵ファイルを設定しておくこと

さあ、やってみよう。

sshポートフォワーディングしてクライアントツールで接続するまで

ssh設定を記述

~/.ssh/configに下記を書く

host i-* mi-*
    ProxyCommand sh -c "aws ssm start-session --target %h --document-name AWS-StartSSHSession --parameters 'portNumber=%p'"

共通鍵を使うために、鍵置き場に鍵をおいておく。
鍵名:[EC2にアタッチした鍵ファイル]

sshポートフォワーディングする

ssh -i [鍵ファイル置き場所] ec2-user@[インスタンスのID] -L 5432:[rdsのエンドポイント]:3306
  • コンソール上で上記コマンドを流して、トンネルを掘る。接続できたらOK。

DBに接続

接続情報: host:localhost
port:5432
username:XXXX
password:YYYY

※portは適宜変えてください。

DB接続のクライアントツールに直接SSH接続の設定ができないのが若干ビミョー(というか面倒臭い)なところではありますが、大事なデータを守るためにはこのくらいはやった方がいいのかもしれない。

pythonのエラーハンドリング

pythonでエラーが起こった時にどう対処するか?
pythonのエラーハンドリングについての世の中の知見を見て回った。

大きくは2系統。
エラー判定してreturnするタイプと例外を投げてキャッチするケースとあるらしい。
他の言語と一緒ってことで考えて良さげかな。

実際のところどちらが良いかなんて、システムの方向性とか設計思想によるのでどちらが良い!とは言えないですが、 何も考えなければ、例外を投げてキャッチする方が使い勝手が良さそうだったので、例外の方を採用。
あとは、呼び出し元まで投げてあげれば大体は丸く収まるので、戻り値を戻るたびに判定しないといけないreturnの場合よりも楽な気がする。

ときに、pythonでは例外を投げるときに 「raise」を使って投げるのだが、復活って意味かと思ってたら(FFのせい)、上げるって割と普通の意味だった。例外=死からの復活(raise)だと思ってコード書いたのになんか意味違ってガッカリ。

セッションマネージャーが意外と使えた

EC2への接続はSSHで接続してましたが、セッションマネージャーを使えばIAMベース簡単に接続できた。

セッションマネージャーの利点

  • IAMで管理可能
  • 22番ポートを開けなくて良い
  • privateなEC2インスタンスにも接続可能
  • 踏み台がいらないんじゃない?
    • これはDBインスタンスへの接続する場合は踏み台が必要でした
    • その時もセッションマネージャーを通しての踏み台が可能

IAM1本で管理できるようになるので、SGで22番ポートにIPアドレス制限かけたりとかも気にしなくて良く、セキュリティ的にも安心。
これはやらない手はない。それではやってみよう。

AWS CLIのインストール・設定からEC2へ接続をするまで

AWS CLI v2のインストール

接続にはAWS CLIが必要となるので、ドキュメントの通りインストールを行います。なお、今回は最新のAWS CLI v2をインストールします。

curl "https://awscli.amazonaws.com/AWSCLIV2.pkg" -o "AWSCLIV2.pkg"
sudo installer -pkg AWSCLIV2.pkg -target /
which aws
  • /usr/local/bin/aws であればOK
aws --version
  • aws-cli/2.X.XX であればOK

Session Manager plugin のインストール

cd /tmp
curl "https://s3.amazonaws.com/session-manager-downloads/plugin/latest/mac/sessionmanager-bundle.zip" -o "sessionmanager-bundle.zip"
unzip sessionmanager-bundle.zip
sudo ./sessionmanager-bundle/install -i /usr/local/sessionmanagerplugin -b /usr/local/bin/session-manager-plugin
session-manager-plugin
  • The Session Manager plugin was installed successfully. Use the AWS CLI to start a session. のように表示されればOK

aws configure でIAMユーザの設定情報をセット

$ aws configure
AWS Access Key ID [None]: AKIXXXXXXXXXXXXXXXXX
AWS Secret Access Key [None]: KO8XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
Default region name [None]: ap-northeast-1
Default output format [None]: json

ここまでで設定は完了

EC2接続確認

EC2インスタンスインスタンスID(i-XXXXXXXXXXXXXXXXX)を指定して接続する

aws ssm start-session --target i-XXXXXXXXXXXXXXXXX

ssmユーザーでログインします。(ススムくんと命名
このままだと、bashrcが読まれないので気になるようだったら自分で読み込む必要がある。

Starting session with SessionId: XXXXXXXXXX

sh-4.2$ source ~/.bashrc
[ssm-user@ip-xx-xx-xx-xx bin]$ cd
[ssm-user@ip-xx-xx-xx-xx  ~]$ 

これでec2-userで繋いだ時と同様な使い方ができるようになった。

2021/08/11 追記
これを使用するためには、EC2側にあらかじめSSM Agentのインストールが必要ですが、AmazonLinux2にはデフォルトでインストールされてるとのこと。
また、[AmazonSSMManagedInstanceCore]がアタッチされたiam roleを対象のEC2heアタッチする必要があります。

pythonの正解って?

最近Python書いてみてます。
良い感じで自由。でもルールづけしないと統一性が保てなさそう。
型をきちんと定義しないのはCとかJavaやってた頃と違うなぁと思う。
多少の気持ち悪さはあってもなんとなくで書けちゃう。

け ど ね !

正しく書けてない気がする。
dict型の使い方とかエラーハンドリングとか...

こういうことって、誰かの洗練されたコードを見て学ぶべき!
ってことで、GitHubに落ちてるコードを読んでみると、なんか自由で本来見たいところに目が行かなかった。

例えば、変数の命名規則が、スネークケースだったり、キャメルケースだったり。
変数名はスネークで、クラス名はパスカルで、メソッド名はキャメルが正解だと思ってたんですが、違うんでしょうか。
しばらく調査は続きそう。

技術者がすなるといふ技術ブログといふものをしてみんとてするなり

はじめてみました。

つい1ヶ月前にやったことをさっぱり忘れてしまうという今日この頃。 人間忘れないと新しいことが入ってこないのです。その点ではなんだかPCと似てますね。

数ヶ月の自分のため、同じことで悩む仲間のためになんとかなればいいな。