【Jenkins】JenkinsからJMeterで負荷試験をやってみる
はじめに
JenkinsからJMeterを使用した負荷試験をやってみました。
JMeter全然使いこなせてないウーマンですが、
そのあたりは目をつむって。。
Jenkinsでこう設定すると、こんな感じで実行できて、こんな風に結果が見えます、
をざっくりまとめてみました。
pythonもろもろのバージョンなど、環境特有のものかもですが、
いろいろトラブったのでおまけでトラブルシュートの軌跡をメモしておきました。
トラブルシュートは相変わらずパワープレーですが、悪しからず。。
目次
環境情報
項目 | 値 |
---|---|
OS | RHEL7 |
Python | 2.7.5 |
Jenkins | 2.138.2 |
Jenkins Performance Plugin | 3.1.17 |
Apache JMeter | 5.1.1 |
要件
JenkinsにPerformance Plugin追加
JenkinsからJMeterによる負荷試験実行するために、
Performance Pluginをインストールします。
Performance PluginはTaurusという自動テストフレームワークから
Jmeterなどのテストツールを実行する仕組みのようです。
プラグインのインストールは、下記の方法で行いました。
- Performance Pluginにアクセスし、
Archives
をクリック 3.17
をクリックしてダウンロード- ダウンロードしたperformance.hpiをJenkinsにアップロード
Jenkinsの管理
->プラグインの管理
->高度な設定
タブ->プラグインのアップロード
ジョブの作成
新規ジョブの作成
を押下し、フリースタイル・プロジェクトのビルド
を選択し、
新規ジョブを作成します。
ソースコードの管理
ディレクトリに固定で置いても良いと思いますが、
今回Gitで試験シナリオを定義したJmxファイルを管理する構成にしてみたので、
下記のように設定しました。
ビルド
ビルド手順の追加
からRun Performance Test
を選択します。
Taurus tool parameters:
に実行するJmxファイル名を指定します。
そのほかの項目はデフォルトから変えていないですが、
Automatically generate performance report
は結果出力に必要なパラメータのようです。
ビルド後の処理
ビルド後の処理の追加
からPublish Performance test results report
を選択します。
Source data files (autodetects format):
は**/*.jtl
を指定します。
それ以外はデフォルトのままです。
ジョブの実行結果
#(ジョブの実行No)
をクリックして、Performance Report
をクリックすると表示されます。
Jmxファイルの内容によるので、参考程度ですが、
こんな感じに出力されました。
今回の実行結果+過去結果からの推移が可視化されるようです。
おわりに
JMeterを使い込んでないので、
JMeter単体で使う場合とのギャップを語ることはできませんが、
下記3点がポイントだと思います。
- GitLabでテストシナリオをバージョン管理
- スケジュール実行可
- Jenkinsで試験結果推移の可視化
おまけ:トラブルシュート
私の検証環境特有の問題だと思うので、別出しでまとめました。
あとコンソールログが消えちゃったりしたので、ふわっと書いてます。
bzt
かvirtualenv
をpip install
しろやと言われ、ジョブエラー
すみません、ジョブのコンソールログ消えちゃいました。
手動でbzt
インストールを試行しました。
virtualenv
はすんなりはいりましたが、
ジョブ動かしたら結局venvした先でbztがインストールできず詰んだ
(プロキシの関係かな、、あきらめたので未調査)ので、
bzt
インストールしました。
pip install bzt DEPRECATION: Python 2.7 reached the end of its life on January 1st, 2020. Please upgrade your Python as Python 2.7 is no longer maintained. A future version of pip will drop support for Python 2.7. More details about Python 2 support in pip, can be found at https://pip.pypa.io/en/latest/development/release-process/#python-2-support Collecting bzt Downloading bzt-1.13.9-py2.py3-none-any.whl (311 kB) |????????????????????????????????| 311 kB 2.3 MB/s ~(略)~ Collecting Appium-Python-Client Downloading Appium-Python-Client-1.0.0.tar.gz (51 kB) |????????????????????????????????| 51 kB 285 kB/s ERROR: Command errored out with exit status 1: command: /usr/bin/python -c 'import sys, setuptools, tokenize; sys.argv[0] = '"'"'/tmp/pip-install-b0nYvk/Appium-Python-Client/setup.py'"'"'; __file__='"'"'/tmp/pip-install-b0nYvk/Appium-Python-Client/setup.py'"'"';f=getattr(tokenize, '"'"'open'"'"', open)(__file__);code=f.read().replace('"'"'\r\n'"'"', '"'"'\n'"'"');f.close();exec(compile(code, __file__, '"'"'exec'"'"'))' egg_info --egg-base /tmp/pip-install-b0nYvk/Appium-Python-Client/pip-egg-info cwd: /tmp/pip-install-b0nYvk/Appium-Python-Client/ Complete output (8 lines): Traceback (most recent call last): File "<string>", line 1, in <module> File "/tmp/pip-install-b0nYvk/Appium-Python-Client/setup.py", line 19, in <module> from appium.common.helper import library_version File "appium/common/helper.py", line 20 def extract_const_attributes(cls: type) -> Dict[str, Any]: ^ SyntaxError: invalid syntax ---------------------------------------- ERROR: Command errored out with exit status 1: python setup.py egg_info Check the logs for full command output. WARNING: You are using pip version 20.0.2; however, version 20.1 is available. You should consider upgrading via the '/usr/bin/python -m pip install --upgrade pip' command.
Appium-Python-Clientのインストールでこけているようです。
https://pypi.org/project/Appium-Python-Client/
Notice
Since v1.0.0, only Python 3 is supported
とのことなので、Python2も対応してるバージョンをインストールしました。
# pip install Appium-Python-Client==0.51
さっきとは違うエラーが出てきました。
Collecting Appium-Python-Client==0.51 Downloading Appium-Python-Client-0.51.tar.gz (56 kB) |????????????????????????????????| 56 kB 445 kB/s ERROR: Command errored out with exit status 1: command: /usr/bin/python -c 'import sys, setuptools, tokenize; sys.argv[0] = '"'"'/tmp/pip-install-Docu3L/Appium-Python-Client/setup.py'"'"'; __file__='"'"'/tmp/pip-install-Docu3L/Appium-Python-Client/setup.py'"'"';f=getattr(tokenize, '"'"'open'"'"', open)(__file__);code=f.read().replace('"'"'\r\n'"'"', '"'"'\n'"'"');f.close();exec(compile(code, __file__, '"'"'exec'"'"'))' egg_info --egg-base /tmp/pip-pip-egg-info-C2pD_b cwd: /tmp/pip-install-Docu3L/Appium-Python-Client/ Complete output (5 lines): Traceback (most recent call last): File "<string>", line 1, in <module> File "/tmp/pip-install-Docu3L/Appium-Python-Client/setup.py", line 37, in <module> packages=find_packages(include=['appium*']), TypeError: find_packages() got an unexpected keyword argument 'include' ---------------------------------------- ERROR: Command errored out with exit status 1: python setup.py egg_info Check the logs for full command output.
https://github.com/appium/python-client/issues/397
同じことて困ってる人いました。
私もsetuptoolsのバージョンが低いのかな。。。と思い。
# pip show setuptools Name: setuptools Version: 0.9.8 Summary: Easily download, build, install, upgrade, and uninstall Python packages Home-page: https://pypi.python.org/pypi/setuptools Author: Python Packaging Authority Author-email: distutils-sig@python.org License: PSF or ZPL Location: /usr/lib/python2.7/site-packages Requires: Required-by:
上げてみました。怖いくらい上がってしまった。
# pip install -U setuptools pip install -U setuptools DEPRECATION: Python 2.7 reached the end of its life on January 1st, 2020. Please upgrade your Python as Python 2.7 is no longer maintained. pip 21.0 will drop support for Python 2.7 in January 2021. More details about Python 2 support in pip, can be found at https://pip.pypa.io/en/latest/development/release-process/#python-2-support Collecting setuptools Downloading setuptools-44.1.0-py2.py3-none-any.whl (583 kB) |????????????????????????????????| 583 kB 409 kB/s Installing collected packages: setuptools Attempting uninstall: setuptools Found existing installation: setuptools 0.9.8 Uninstalling setuptools-0.9.8: Successfully uninstalled setuptools-0.9.8 Successfully installed setuptools-44.1.0
もう一度bzt
インストール試行!
先に進めてエラーが変わりました。
ERROR: Cannot uninstall 'chardet'. It is a distutils installed project and thus we cannot accurately determine which files belong to it which would lead to only a partial uninstall.
https://stackoverflow.com/questions/49915951/cannot-uninstall-chardet
こちらを参考にchardetを一回消しました。
もう一度bzt
インストール試行!
ようやくbztインストールできました。
# pip show bzt Name: bzt Version: 1.13.9 Summary: Taurus Tool for Continuous Testing Home-page: http://gettaurus.org/ Author: Andrey Pokhilko Author-email: andrey@blazemeter.com License: Apache 2.0 Location: /usr/lib/python2.7/site-packages Requires: nose, requests, pytest, terminaltables, psutil, fuzzyset, progressbar33, astunparse, pyvirtualdisplay, gevent, colorlog, cssselect, selenium, pyyaml, apiritif, lxml, hdrpy, ipaddress, colorama, urwid, Appium-Python-Client Required-by:
JMeterのインストール失敗
もう一度ジョブ流してみました。
11:36:23 INFO: Taurus CLI Tool v1.13.9 11:36:23 INFO: Starting with configs: ['/var/lib/jenkins/workspace/Execute_Performance_Test/jenkins-report.yml', '/tmp/jmx_HIaZOv.json'] 11:36:23 INFO: No personal config found, creating one at /var/lib/jenkins/.bzt-rc 11:36:23 INFO: Configuring... 11:36:23 INFO: Artifacts dir: /var/lib/jenkins/workspace/Execute_Performance_Test/2020-05-19_11-36-23.694021 11:36:23 INFO: Preparing... 11:36:24 INFO: Will install JMeter into /var/lib/jenkins/.bzt/jmeter-taurus/5.1.1 11:36:33 WARNING: Failed to check for updates 11:36:34 ERROR: Can't fetch https://jmeter.apache.org/download_jmeter.cgi 11:36:34 INFO: Downloading: https://archive.apache.org/dist/jmeter/binaries/apache-jmeter-5.1.1.zip 11:36:39 ERROR: Error while downloading https://archive.apache.org/dist/jmeter/binaries/apache-jmeter-5.1.1.zip: Unsuccessful download from https://archive.apache.org/dist/jmeter/binaries/apache-jmeter-5.1.1.zip 11:36:39 ERROR: Internal Error: JMeter download failed: No more links to try 11:36:39 INFO: Post-processing... 11:36:39 INFO: Artifacts dir: /var/lib/jenkins/workspace/Execute_Performance_Test/2020-05-19_11-36-23.694021 11:36:39 WARNING: Done performing with code: 1 Build step 'Run Performance Test' changed build result to FAILURE Creating parser with percentiles:'0,50,90,100,' filterRegex: Performance: Recording JMeter reports '**/*.jtl' Performance: No threshold configured for making the test unstable Performance: No threshold configured for making the test failure Started calculate disk usage of build Finished Calculation of disk usage of build in 0 seconds Started calculate disk usage of workspace Finished Calculation of disk usage of workspace in 0 seconds Finished: FAILURE
JMeterのインストールで止まりました。
プロキシ配下の環境のため、Jenkinsを通してインストールできていないのかもしれません。
(このへん、切り分けてないです)
パワープレーですが、
/var/lib/jenkins/.bzt/jmeter-taurus/5.1.1
(ディレクトリは自分で掘りました)に、
# wget https://archive.apache.org/dist/jmeter/binaries/apache-jmeter-5.1.1.zip
で取得したzipファイルを解凍してソースを配置すれば、動きます。
所有者や権限は気を付けてください。
【Redmine】プラグイン紹介 その2
はじめに
Redmine4.1.0に入れてお試ししてみたプラグインを紹介します。
その2です。
目次
環境
Redmine Work Time Plugin
バージョン | 公式URL |
---|---|
0.4.0 | https://www.redmine.org/plugins/redmine_work_time |
工数管理をサポートするプラグインです。
ユーザ別に何のタスクにどのくらい工数をかけているかを見える化できます。
Redmineを絶対神としてタスク管理しているPJは、
稼働管理表がRedmineで自動的に生成できるので、効果を発揮すると思います。
Pluginの話をする前に、
Redmineにデフォルトで入っている作業時間管理機能を見ておきましょう。
Redmineの工数管理機能 | Redmine.JP Blog
- 一覧
各個人がどのタスクにいつどれだけ工数をかけたのか、
わからないこともないですが、
カレンダー風にサマってくれてる方がユーザ的には嬉しいのかなと思います。
- 入力画面
時間を記録
ボタンを押下すると入力画面に遷移します。
チケットの編集画面からでも入力できます。
ユーザ的には、一日の終わりにまとめてつけたかったりするので、
いちいちチケット番号検索したり、
チケットにアクセスしたりが若干面倒な気がします。
そこで、Work Time Pluginを入れると、、、(ここからが本題)
工数タブからこの画面が見えます。
一覧と入力画面は1画面に収まってます。
日毎工数-YYYY-MM-DDのところにアサインされてるタスクが並んでるので、
その日働いた工数を記録して、更新
ボタンを押せば一覧に反映されます。
ロールに紐づく権限(管理
⇒ロールと権限
)を操作して、
ほかの人の工数の読み書きができるようになります。
このプルダウンでユーザを切り替えできます。
個人単位のサマリが見やすくなったのがポイントだと思います。
さらに、月間集計表も出せます。
付け替え設定もできるようで、、
PJ管理の経験がないので利用シーンが思いつきませんが、
外見せをよくするために工作するときに使うのかな?
ごにょごにょできるみたいです。
付け替えた月間集計と付け替えないバージョンの月間集計、
どちらも表示可能です。
おわりに
Redmine Work Time Pluginのポイントは、以下の通りです。
- 入力UIがいい感じ
- 個人単位のサマリが見やすい
- 月間集計の出力ができる
【Redmine】プラグイン紹介 その1
はじめに
Redmine4.1.0に入れてお試ししてみたプラグインを紹介します。
そんな使いこんでるわけでもないので、
どんな風に使うのかは半分想像ですが。。
たくさん書こうと思ってましたが、
試したやつ全部書くとけっこうボリューミーになるので、
シリーズ化します。
目次
環境
Redmine Banner
バージョン | 公式URL |
---|---|
0.3.1 | https://www.redmine.org/plugins/redmine_banner |
Redmineのユーザへ一斉通知するプラグインです。
プラグインを入れると上部に「バナー」のメニューが追加されます。
プロジェクトのタブにも追加されます。
設定画面は以下の通りです。
項目名 | 説明 |
---|---|
表示対象 | 誰に表示するか(ログインしてる人?してない人?全員?) |
メッセージタイプ | メッセージの重要度(アイコンが変わる) |
表示位置 | ヘッダORフッタOR両方/ログインページのみ |
バナーメッセージ | 表示するメッセージ。マークダウンで書ける! |
リンク | [詳細] のリンク先に設定される |
表示期間 | バナーを出す期間を設定できる |
有効にする□
にチェックして、適用
を押下すると、
こんな風に表示されます。
一番下のバナー管理者グループっていうのは、
バナーで通知できる人を所属させるグループです。
GlobalBanner_Adminグループに一般ピーポを所属させてみると、
その人もバナーのメニューから通知出せるようになってました。
Redmine Issue Templates
バージョン | 公式URL |
---|---|
1.0.1 | https://www.redmine.org/plugins/redmine_issue_templates |
チケットの書き方って、センスが問われるもので、
人によって書きっぷりが違ってきてしまうことって多々ありますよね。
このプラグインを使えば、
説明欄の定型文などをテンプレートとして登録できます。
多少チケットの書きっぷり問題は解決するのではないかと思われます。
テンプレートはRedmine全体(グローバル)でも管理できるし、
プロジェクトごとにも管理できます。
グローバルのテンプレートは管理
->グローバルチケットテンプレート
から
プロジェクトごとのテンプレートはチケットテンプレート
タブから
設定画面は以下の通りです。
項目名 | 説明 |
---|---|
テンプレート名 | テンプレート名(そのままですね) |
トラッカー | テンプレートを適用するトラッカー |
チケットタイトル | タイトルも任意でテンプレート化できる。接頭に【XXXX】つけるとか、よくありそう |
チケット本文 | ここにテンプレート(定型文、見出しなど)を定義 |
メモ | このテンプレートに対するメモ |
関連リンク | テンプレートの利用例とか、テンプレートに対する参考情報のリンク |
関連リンクのタイトル | リンクにタイトルつけられる |
デフォルト値 | 有効にすると、新規チケット作成でトラッカーを選択した瞬間テンプレートが反映される |
有効 | 新規チケット作成の時に選べるようにするためには有効にする |
新規チケット作成で、
テンプレートを選ぶと、
登録したテンプレートが呼び出せます。
おわりに
知られざる便利プラグインはまだまだたくさんある気がするので、
ほかにもいろいろ試そうかと思います。
すでに入れてるプラグインは、
若干キャプチャでチラ見せしてますがね!
おまけ
2月に室内楽の本番がありました。
テレワークのBGMにどうぞ。
【AWS】Systems Manager 自作オートメーションドキュメント その2
はじめに
AWSのSystems Managerで、(以下SSM)
オートメーションドキュメントを自作したので、
やりたいこと別に紹介します!
前前回導入編を書いて、前回「その1」を書いて、
その続編的な何かです。
目次
■値を取得して別のステップで使いたい
ステップ1のレスポンスで帰ってきた値を変数に格納しておけば、
そのあとのステップで、
ステップ名.変数名
みたいな感じで使用できます。
例えば、
対象EC2インスタンスのNameタグの値を取得してみます。
- name: getNameTag action: 'aws:executeAwsApi' inputs: Service: ec2 Api: DescribeTags Filters: - Name: resource-id Values: - '{{ InstanceId }}' - Name: key Values: - Name outputs: - Name: InstanceName Selector: 'Tags[0].Value' Type: String
上記のように取得すれば、後のステップで、
{{ getNameTag.InstanceName }}
のように使えます。
ポイント
action: 'aws:executeAwsApi'
で`APIを実行DescribeXXX
を使うことが多いかな- 期待するレスポンスを得るために、
Filters:
を使う
outputs:
で格納する変数をName:
に定義&格納する値へのパスをSelector:
に記述- 使う時は、前述のとおり、
{{ ステップ名.変数名 }}
■RDSのDBインスタンスを操作したい
メンテナンスウィンドウのターゲットに、
RDSのDBインスタンスを設定して、
オートメーションドキュメントで操作を自動化してみます。
まず、メンテナンスウィンドウでの
ターゲットの設定は、
Choose a resource group
で
リソースタイプがAWS::RDS::DBInstance
のリソースグループを指定するイメージです。
※EC2インスタンス以外のターゲットを指定する方法がこれしかない気がします。
※あれば知りたい
上記のようなメンテナンスウィンドウから
呼び出されるオートメーションドキュメントを書こうとしたときの注意点です。
parameters: DBInstanceId: type: String description: (Required) The DBInstance's ID.
たとえば、上記のように入力パラメータを定義し、
メンテナンスウィンドウでのタスク登録で、
こんな風に、{{ TARGET_ID }}
を指定すると、
オートメーション実行時に、
DBInstanceId
に実際に入力される値は、
arn:aws:rds:ap-northeast-1:000000000000:db:piyomaru-db
のように、
ARNの値が入ってきます。
RDSを操作するようなAPIを使う場合って、
DB識別子が必須パラメータが多いので、
1ステップ目で、
ARNからDB識別子を取得するようにしてます。
mainSteps: - name: GetDBInstanceIdentifier action: 'aws:executeAwsApi' inputs: Service: rds Api: DescribeDBInstances Filters: - Name: db-instance-id Values: - '{{ DBInstanceId }}' outputs: - Name: DBInstanceIdentifier Selector: 'DBInstances[0].DBInstanceIdentifier'
■値を取得して別のステップで使いたいの
おさらいですが、
取得したDB識別子は、この後のステップで、
GetDBInstanceIdentifier.DBInstanceIdentifier
として使えます。
動かし始めたとき、
DB識別子が入ってくれると勝手に勘違いしていたので、
紛らわしい命名になっていますが、
DBInstanceId
をDBarn
とかにすると分かりやすいかもですね。
続きの処理の例です。
スナップショット作成してみました。
- name: CreateRDSSnapshot action: 'aws:executeAwsApi' inputs: Service: rds Api: CreateDBSnapshot DBInstanceIdentifier: '{{ GetDBInstanceIdentifier.DBInstanceIdentifier }}' DBSnapshotIdentifier: '{{ global:DATE }}-{{ GetDBInstanceIdentifier.DBInstanceIdentifier }}'
■分岐したい
スクリプトみたいに、
あまり器用なことはできませんが、
分岐の記法はあります。
https://docs.aws.amazon.com/ja_jp/systems-manager/latest/userguide/automation-branchdocs.html
ちょっと書いてみました。
対象のEC2インスタンスが特定のEC2インスタンスだった場合、
echo "Hello World"
してね!そうじゃない場合は、眠りましょう!
というオートメーションドキュメントです。
description: Exec runCommand to specified Instance. schemaVersion: '0.3' parameters: InstanceId: type: String description: (Required) The ID of the Amazon EC2 instance. mainSteps: - name: Jadgment Instance action: 'aws:branch' inputs: Choices: - NextStep: runCommand Variable: '{{ InstanceId }}' StringEquals: i-026828bd5e33fba70 Default: Sleep - name: runCommand action: 'aws:runCommand' inputs: DocumentName: AWS-RunShellScript InstanceIds: - i-0000aaaa0000bbbb Parameters: commands: - 'echo "Hello World"' isEnd: true - name: Sleep action: 'aws:sleep' inputs: Duration: PT5S
ポイント
action:
にaws:branch
を指定するNextStep:
に分岐先のステップ名を定義- 複数分岐条件があれば、複数定義できる
- どの条件にも合致しない場合の分岐先は
Default:
に定義 - 分岐先で処理を終了する場合には
isEnd
を定義- 定義しておかないと、止まらずに上から下にそのまま流れてしまう
おわりに
「その2」はちょっと応用バージョンみたいなネタをまとめてみました。
ただ、あんまりアクロバットなことをするなら
Lambdaの方が適していると思います。
自作オートメーションドキュメントの実例はあまりネットに落ちてない気がするので、
誰かの役に立てば幸いです。
【読書】リーダブルコード読みました
はじめに
ずっと読もうと思っていた
リーダブルコードを読んだので、
響いたことを、自分なりに咀嚼してつらつらと書きます!
この記事の【ポイント】部分は、
ほぼ自分への戒めです。
今までの自身の愚かなコードを振り返りつつ…
振り返るほどコーディングの経験ないけども。
命名
脇役的な変数にも愛を持って命名する
念のために定義しておこう~いらなかったら消そう~
と思って、適当な変数定義して、
結局消さずに居座られるあるある
置換もめんどくて、そのままにしちゃうあるある
tmp_hogehoge
とか気を抜くと使ってしまう気がします。
というか、中間結果を保持するだけの変数は、
乱立させないように気をつけます。
【ポイント】
tmp
という文字列も「一時的」とか意味を持つので、適当に使わない- 変数を無駄に増やさない
その関数にはどんな動作が期待される?
コードを読む側の先入観を想定して書くと、
より読みやすくなるとのことです。
書き手としては意識したことなかったですが、
読み手的にはGet…()
みたいな関数は、
メンバの値を返すだけの軽めの関数かなぁと期待します。
確かにGet…()
が何十行にわたる重厚なコードだったら萎えますね。
【ポイント】
- 関数は、読み手が期待する動作(のレベル感)を想像して命名する
コメント
無駄なコメント削減
心配性なもので、
明日には記憶喪失になってたらどうしようと思い、
やたら細かくコメントしてしまいます。
ただ、コメントが無駄に多いのもスマートさに欠けるし、
見た目から読む気を削ぎますよね。
【ポイント】
- コード見ればわかることはコメントしない
- コメントしなくて済むような命名を意識する
#〇〇を定義
とかやめよう。。
意図を記録する
記憶喪失まではいかなくても、
やたら凝ったコード書いて、
翌週、え、私何がしたくて、こんなコード書いたの…
ってなることはあります。
そんなときのためにも、
「意図」をコメントとして残すのは大事です。
【ポイント】
- 何を思ってそのコードを書いたのか、コメントに残す
- 夢中になって書いた傑作コードほど、未来の自分のために書き残す
コードの手段ではなく目的を書く
例えば、
古いメッセージを削除するために、
メッセージ一覧を取得して、最古メッセージIDを特定して、delete実行する。
とか、そんな処理があったとしたら、
コメントするべきなのは、
メッセージ一覧を取得して、最古メッセージIDを特定して、delete実行する。
ではなく、
古いメッセージを削除
がベター、ということですかね。
目的を書いておけば、
第三者が見たとき、「え、この目的達成できてなくね?」
ってなった時に、バグが発覚できるので、
救われる命があるかもしれませんね。
【ポイント】
- 目的が書いてあれば、第三者がレビューしやすいかも
関数の切り出し方
書籍で述べていることを簡潔にまとめると、
読み手をコード全体を通した目標に集中させるために、
目標に直接的に関係ない部分を
積極的に関数化しましょと言っています。
コードも読みやすくなるし、
メンテもしやすくなるります。
【ポイント】
- 関数の切り出し観点
- コード全体を通した目標に直接関係ない
- 汎用的で、使いまわせそう
- やりすぎない笑(調子に乗って、関数作りすぎても逆に見づらい)
おわりに
コーディング歴は半年くらいの雛鳥なので、
行き当たりばったりで書いていることが多く、
なかなか刺さりました。
もう少し経験積んだら、
読む観点も変わってくるのかなと感じました。
定期的に自戒のために、読み続けたい名著です。
【AWS】Systems Manager 自作オートメーションドキュメント その1
はじめに
AWSのSystems Managerで、(以下SSM)
オートメーションドキュメントを自作したので、
やりたいこと別に紹介します!
前回導入編を書いたので、その続編的な何かです。
目次
■API使って操作したい
下記の例は、DBインスタンスのスナップショットを作成するAPI、
CreateDBSnapshot
を使って、
命名規則に則ったスナップショットを作成します。
description: Create DB snapshot schemaVersion: '0.3' parameters: DBInstanceId: type: String description: (Required) The identifier of the Amazon RDS DB instance. mainSteps: - name: CreateRDSSnapshot action: 'aws:executeAwsApi' inputs: Service: rds Api: CreateDBSnapshot DBInstanceIdentifier: '{{ DBInstanceId }}' DBSnapshotIdentifier: 'Ops-{{ global:DATE }}-{{ DBInstanceId }}'
parameters
のDBInstanceId
ではDB識別子を指定するイメージです。
ポイント
action:
に'aws:executeAwsApi'
を指定すれば、APIが使えるinputs:
のApi
に、使用するAPIを指定する- APIの引数を
inputs
に追加する- 今回の場合は、CreateDBSnapshotの
Request Parameters
を参考に指定 DBInstanceIdentifier
はパラメータのDBInstanceId
の値を、DBSnapshotIdentifier
は命名規則に沿って指定- APIの情報は、大体操作方法をググると出てくる
- 今回の場合は、CreateDBSnapshotの
- ちなみに
{{ global:DATE }}
は日付をとってくるシステム変数
■ステータスの変化を待ちたい
APIでCreateなんとか
を使ってなんか作ったとして、
その何かが指定した状態に変わるのを待つことができます。
下記の例は、■API使って操作したいで作成したスナップショットの状態が
available
になるのを待ちます。
# ヘッダは省略 - name: VarifyRDSSnapshot action: 'aws:waitForAwsResourceProperty' inputs: Service: rds Api: DescribeDBSnapshots PropertySelector: 'DBSnapshots[0].Status' DesiredValues: - available DBSnapshotIdentifier: 'Ops-{{ global:DATE }}-{{ DBInstanceId }}'
ポイント
action:
に'aws:waitForAwsResourceProperty'
を使用Api:
には状態をトレースしたい対象の表示(Describe)系APIを指定- 今回の場合は、DBスナップショットの状態が知りたいので、
DescribeDBSnapshots
を指定
- 今回の場合は、DBスナップショットの状態が知りたいので、
PropertySelector:
には、Apiで取得できるレスポンスから状態へのJSONパスを指定- 今回の場合は、DescribeDBSnapshotsのSample Responceを参考に指定
DesiredValues:
には、期待する状態を指定DBSnapshotIdentifier:
はDescribeDBSnapshots
に対する引数
■別のオートメーションドキュメントを呼び出したい
下記の例は、RDSのリードレプリカを作成するオートメーションドキュメントを
呼び出しています。
※呼び出し先ドキュメントは■API使って操作したいと■ステータスの変化を待ちたいの連結版だと思っていただければ。。
# ヘッダは省略 - name: CallCreateDBSnapshotAutomation action: 'aws:executeAutomation' inputs: DocumentName: CreateDBSnapshot RuntimeParameters: DBInstanceIdentifier: - '{{ DBInstanceId }}'
ポイント
action:
は、'aws:executeAutomation'
を指定inputs:
のDocumentName
は呼び出すオートメーションドキュメントを指定RuntimeParameters:
には指定するオートメーションドキュメントのパラメータを指定- 呼び出し先のオートメーションドキュメントの
parameters:
で定義しているパラメータ
- 呼び出し先のオートメーションドキュメントの
■コマンドを投入したい
方法はいくつかありますが、
オートメーションドキュメントで実行する方法を紹介します。
下記の例は、
対象のEC2インスタンス(Linux)に対して、cat /etc/hosts
を実行します。
出力結果は、オートメーションの実行履歴から確認できます。
description: exec command schemaVersion: '0.3' parameters: InstanceId: type: String mainSteps: - name: CatHostsFile action: 'aws:runCommand' inputs: DocumentName: AWS-RunShellScript InstanceIds: - '{{ InstanceId }}' Parameters: commands: - cat /etc/hosts
実体は、AWS-RunShellScript
というコマンドドキュメントを
外部から呼び出しているだけです。
ただコマンド実行したいだけなら、
AWS-RunShellScript
を実行すればよいと思います。
(書いてて気づいた)
ただ、オートメーションドキュメントに組み込みたいんじゃ!っていう場合は、
この書き方で実現できます。
私は、aws:branch
で分岐させた先で使いました。
※分岐させる書き方は次回書きます。
ポイント
action:
はコマンドドキュメントを呼び出す'aws:runCommand'
を指定- コマンドドキュメントは
AWS-RunShellScript
を指定 - InstanceIdsには対象のEC2インスタンスを指定
Parameters:
のcommands:
に投入したいコマンドを記述
■眠りたい
オートメーションドキュメントでは下記のように眠ります。
時間はISO 8601の書式で記述します。
タイムスタンプでの指定も可能です。
# ヘッダは省略 - name: Sleep action: 'aws:sleep' inputs: Duration: PT5S
ポイント
- 時間はISO 8601の書式で記述
- タイムスタンプでの指定も可能(Duration→Timestampにする)
おわりに
AWSコンソールからポチポチやっていることや、
EC2インスタンスにログインしてコマンドたたくなど、
それらを並べてフローにできるので、
なかなか便利です。
参考
https://docs.aws.amazon.com/ja_jp/systems-manager/latest/userguide/automation-actions.html
【AWS】Systems Manager使ってみる 導入編
はじめに
AWS環境の運用自動化するのに、
AWS Systems Manager(以下、SSM)を試行中です。
今回は導入編ということで、
メンテナンスウィンドウを動かす最低限のチュートリアルを書きました。
オートメーションドキュメントの自作とかもやってみたので、
別記事で公開します。
AWS Systems Managerとは
公式サイトの紹介ページはこちら
AWS Systems Manager(運用時の洞察を改善し、実行)| AWSaws.amazon.com
https://docs.aws.amazon.com/ja_jp/systems-manager/latest/userguide/what-is-systems-manager.html
機能はいくつかあるようですが、
私が使ってみたのはAutomationの機能です。
メンテナンスウィンドウから、
- ターゲット
- タスク(オートメーションドキュメント)
- スケジュール
を登録して、実行します。
※ざっくり説明してます。詳細は後述。
動作確認環境
事前準備
SSM Automationタスク用IAMロールの作成
SSMからAWS上のリソースに対して
実行しようとする操作を許可するための
IAMロールを作成します。
以下、SSMServiceRoleとします。(説明の便宜上)
https://docs.aws.amazon.com/systems-manager/latest/userguide/sysman-maintenance-permissions.html
実行するタスクに応じて、
ポリシーをアタッチする必要があります。
例えばオートメーションドキュメントの中で、
DescribeInstancesというAPIを使う場合は、
SSMServiceRoleに
DescribeInstancesを許可するポリシーをアタッチしていないと、
実行時、権限がないよってエラーになります。
Step fails when it is Execute/Cancelling action. An error occurred (AccessDenied) when calling the DescribeInstances operation: User: arn:aws:sts::XXXXXXXXXXXX:assumed-role/SSMServiceRole/OrchestrationService is not authorized to perform: ec2:DescribeInstances. Please refer to Automation Service Troubleshooting Guide for more diagnosis details.
SSMに操作されるEC2用のIAMロールの作成
SSMに操作されるEC2インスタンス割り当てるIAMロールを作成します。
以下、EC2InstanceRoleForSSMとします。(説明の便宜上)
https://docs.aws.amazon.com/ja_jp/systems-manager/latest/userguide/setup-instance-profile.html
AmazonSSMManagedInstanceCoreはアタッチ必須です。
S3やAD、CloudwatchとEC2を連携するような操作をするには、
カスタムポリシーが必要みたいです。
メンテナンスウィンドウの登録
メンテナンスウィンドウの設定手順は、こちら。
https://docs.aws.amazon.com/systems-manager/latest/userguide/sysman-maintenance-working.html
今回は、AWSにデフォルトで登録されている、
オートメーションドキュメントを使用して、
EC2インスタンスを18時に停止するメンテナンスウィンドウを作ってみます。
① Systems Manager のコンソールを開く
②[メンテナンスウィンドウの作成]を押下
③以下の項目を入力し、 [メンテナンスウィンドウの作成]を押下
No | 項目名 | 値 |
---|---|---|
1 | 名前 | StopEC2Instance |
2 | 説明 | Stop EC2 Instance at 18:00. |
3 | 指定 | Cronスケジュールビルダー |
4 | ウィンドウの開始 | 毎日の18:00 |
5 | 期間 | 1 |
6 | タスクの開始を停止 | 0 |
7 | ウィンドウの開始日 | 指定なし |
8 | ウィンドウの終了日 | 指定なし |
9 | タイムゾーンのスケジュール | (GMT+09:00)Japan |
④ 作成したメンテナンスウィンドウを選択し、[編集]を押下
⑤ターゲットタブを開き、[ターゲットの編集]を押下
⑥以下の項目を入力し、 [ターゲットの登録]を押下
No | 項目 | 値 |
---|---|---|
1 | 名前 | TargetHosts |
2 | 説明 | Hosts stopped at 18:00 |
3 | 所有者情報 | 指定なし |
4 | Target Selection | Choose instances manually |
5 | インスタンス | ★対象のインスタンスたち |
※インスタンスが出てこない場合は、以下をチェック
⑦タスクタブに移動して、[タスクを登録する]を押下
⑧[オートメーションタスクの登録]を押下
⑨以下の項目を入力し、 [タスクの登録]を押下
No | 項目 | 値 |
---|---|---|
1 | 名前 | StopInstance |
2 | 説明 | |
3 | オートメーションドキュメント | AWS-StopEC2Instance |
4 | ドキュメントのバージョン | ランタイムのデフォルトバージョン |
5 | 優先度 | 1 |
6 | ターゲット | 登録済みのターゲットグループの選択:TargetHosts |
7 | レート制御-並行性 | 1ターゲット |
8 | レート制御-誤差閾値 | 0エラー |
9 | IAMサービスロール | カスタムサービスロールを使用する:SSMServiceRole |
10 | 入力パラメータ-InstanceId | {{ TARGET_ID }} |
※優先度って何…?
- タスクの実行順番を制御できます。
- 優先度は今回は1タスクのみなので、
1
にしてます。 - 複数タスクを順次実行する場合は、優先度の値の昇順で実施されます。
オートメーションドキュメントの実体は、
AWS Systems Managerコンソールの左ペインの[ドキュメント]にあります。
これで、18時にEC2インスタンスを停止してくれるメンテナンスウィンドウができました。
タスクの実行履歴は履歴タブから確認できます。
おわりに
オートメーションドキュメント、
もとから入っているものでもけっこういろんなことできそうです。
SSMで運用チームが幸せになる使い方を模索中です。