ジョギング
- 山王公園をサクッと
- 懸垂 x 6
夕飯
- ネギとかとろろ芋とかしめじの豚肉巻き
- 奥さんは, 街の料理スクールに通おうかしらと言っているけど, そんな必要が無いくらいにとても美味しかった
学びが多い毎日
- 業務上, 学びが多い日が続いている
- 業務中, お昼ご飯を食べたあとの眠気はなんとかならないものか...
Auth0 でユーザー登録した際に一緒にポストしたメタデータとか ID Token に含める方法を調べたので, 取り急ぎメモ. 以下の記事 (というかドキュメント) が参考になりました.
Auth0 において, ユーザーに紐付けることが出来るメタデータには二種類あって, user_metadata と app_metadata が利用可能です. どちらをどのように使うかについては未調査です.
ID Token の標準的な情報 (Standard Claims) 以外が Custom Claim となり, これを ID Token に含める為には, Rule で以下のコードを書きます.
function (user, context, callback) { const namespace = 'https://myapp.example.com/'; context.idToken[namespace + 'nickname'] = user.user_metadata.nickname; callback(null, user, context); }
上記は user_matadata に登録されている nickname を ID Token に含める場合のコード例です. 尚, user_metadata には以下のように登録されています.
{ "nickname": "testtest" }
Auth0 の Rule 自体の詳細については割愛しますが, ユーザーがアプリケーションを認証する際に実行する JavaScript の関数で認証のプロセスが完了すると実行され, Auth0 の機能をカスタマイズして拡張することが出来るものとなります.
上記のサイトの冒頭にて一行で書かれているので引用させていただきます.
ID Tokenとはユーザー認証情報を含む改ざん検知用の署名付きTokenであり、JWT(JSON Web Token)フォーマットでエンコードされています。
個人的には, この一行でスッと入ってきました.
走り書きでした. 引き続き, 時間を見つけてメモります.
周りの方たちの評判が良いので、奥さんに頼み込んで買ってもらいました。入力デバイスにはお金を惜しむなという婆ちゃんの教えの通り、ちょっとお高めのスペースグレイデルモです。
いい感じです.
お仕事にて, 指定したプロセスが停止したら (それだけではないですが), 自動的にそのプロセスを起動してくれる monit というツールを使いました.
monit の詳細については, インターネット上の記事がたくさんありますので, そちらをご一読ください.
monit は 2000 年前半にリリースされたいにしへのツールで, 現在でもメンテナンスが続けれています. monit が出来ることは以下の通りで, その気になれば, monit だけでサーバーの運用が出来てしまうと思います.
サーバーリソースは使い捨てが望ましいと言われている時代, サーバーはコンテナ化され, そのコンテナのオーケストレーションも自動化されていく中で, 1 台のサーバーの中で個々のサービスプロセス自体の死活を監視し, 再起動を促すようなツールの存在意義が薄れてしまいそうな状況にありながら, monit は現在もバージョンアップを重ねていることは素晴らしいことだと思います.
ということで, 今回, 格闘した環境は以下の通りです.
$ cat /etc/system-release Amazon Linux AMI release 2018.03 $ monit -V This is Monit version 5.2.5 Copyright (C) 2000-2011 Tildeslash Ltd. All Rights Reserved.
先述の通り, monit については, インターネット上に多くの記事がありますので, そちらの記事の方が monit の出来ることや良さ, 欠点等も網羅されているかと思います. あくまでも, 本記事は自分が monit でやりたかったことをどのように実現したか, 簡単なデモを交えて書いていきます.
シンプルな例です.
Apache のプロセスが停止したら, Apache のプロセスを再起動して欲しい場合, monit の設定は以下のように書きます. 尚, 設定は /etc/monit.conf に書いても良いですし, /etc/monit.d/ 以下に任意のファイル名で作成しても構いません.
check process httpd with pidfile "/var/run/httpd/httpd.pid" start program = "/sbin/service httpd start" stop program = "/sbin/service httpd stop"
/var/log/monit には以下のようなログが記録され, httpd プロセスは自動的に起動されています.
[UTC Mar 20 23:43:20] error : 'httpd' process is not running [UTC Mar 20 23:43:20] info : 'httpd' trying to restart [UTC Mar 20 23:43:20] info : 'httpd' start: /sbin/service [UTC Mar 20 23:44:21] info : 'httpd' process is running with pid 2686
尚, monit はデフォルトは 60 秒間隔で監視対象をチェックしています.
人間というのは, 色々と欲が出てくるもので, 再起動してくれるんなら, 一報入れてから再起動してよって思ってしまいます. そんな時には以下のように設定を書きました.
check process httpd with pidfile "/var/run/httpd/httpd.pid" start program = "/sbin/service httpd start" stop program = "/sbin/service httpd stop" if does not exist then exec "/bin/bash -c '/path/to/bin/slak -env /path/to/bin/.env && /sbin/service httpd restart'" else if succeeded then exec "/path/to/bin/slak -env /path/to/bin/.env"
上記の例は, exec コマンドを使って, Slack に通知する為の別のスクリプトを叩いている例となります. キモというか, 苦肉の策となるのが, 以下の部分です.
if does not exist then exec "/bin/bash -c '/path/to/bin/slak -env /path/to/bin/.env && /sbin/service httpd restart'"
if does not exist
は, 監視対象のプロセスが存在しない場合という条件で, その条件が真となる場合に then exec
以降が実行されることになりますが, 複数のコマンドを実行する場合には /bin/bash -c...
で書きはじめて &&
でコマンドを連結するみたいな書き方をする必要がありました.
httpd プロセスが停止すると, Slack の指定したチャンネルに以下のように通知されます.
/var/log/monit には以下のようなログが記録されます.
[UTC Mar 21 00:02:27] error : 'httpd' process is not running [UTC Mar 21 00:02:27] info : 'httpd' exec: /bin/bash [UTC Mar 21 00:03:27] info : 'httpd' process is running with pid 3153 [UTC Mar 21 00:03:27] info : 'httpd' exec: /path/to/bin/slak
せっかくなので, monit によって再起動が完了したら, 通知してもらいましょう. 既に, 設定は掲出していますが, 改めて, 以下に記載します.
check process httpd with pidfile "/var/run/httpd/httpd.pid" start program = "/sbin/service httpd start" stop program = "/sbin/service httpd stop" if does not exist then exec "/bin/bash -c '/path/to/bin/slak -env /path/to/bin/.env && /sbin/service httpd restart'" else if succeeded then exec "/path/to/bin/slak -env /path/to/bin/.env"
ポイントは, else if succeeded then exec "/path/to/bin/slak -env /path/to/bin/.env"
となります. これは, monit によるチェックが成功したら exec
以降の処理を実行することを意味しています.
全体的な処理の流れとしては, httpd プロセスが停止したら, Slack に通知してから httpd プロセスの再起動を行い, 60 秒後 (厳密には 60 秒よりも短い) の次のチェックでプロセスチェックに成功 (プロセスが存在) していたら Slack に通知という感じです.
with pidfile
ではなく, matching
を利用します.
check process httpd matching "httpd" start program = "/sbin/service httpd start" stop program = "/sbin/service httpd stop"
matching
の後のプロセス名がちゃんとチェックされるかどうかは, 以下のコマンドを利用してチェックすることが出来ます.
$ sudo monit procmatch httpd
以下のように出力されます.
List of processes matching pattern "httpd": ------------------------------------------ /usr/sbin/httpd /usr/sbin/httpd /usr/sbin/httpd /usr/sbin/httpd /usr/sbin/httpd /usr/sbin/httpd /usr/sbin/httpd /usr/sbin/httpd /usr/sbin/httpd ------------------------------------------ Total matches: 9 WARNING: multiple processes matched the pattern. The check is FIRST-MATCH based, please refine the pattern
monit -vI
を実行します.
$ sudo monit -vI
以下のように出力されます.
Process Name = httpd Pid file = /var/run/httpd/httpd.pid Monitoring mode = active Start program = '/sbin/service httpd start' timeout 30 second(s) Stop program = '/sbin/service httpd stop' timeout 30 second(s) Existence = if does not exist 1 times within 1 cycle(s) then exec '/bin/bash -c /path/to/bin/slak -env /path/to/bin/.env && /sbin/service httpd restart' timeout 0 cycle(s) else if succeeded 1 times within 1 cycle(s) then exec '/path/to/bin/slak -env /path/to/bin/.env' timeout 0 cycle(s) Pid = if changed 1 times within 1 cycle(s) then alert Ppid = if changed 1 times within 1 cycle(s) then alert System Name = system_ip-xx-x-x-xxx.ap-northeast-1.compute.internal Monitoring mode = active
今回, monit のほんの一部の機能を使ってみました. 通知の部分については, ちょっと格闘しちゃいましたが, プロセスが停止したら再起動させるというシンプルな使い方であれば, とても簡単に使うことが出来ました.
ということで, 素敵な monit ライフをお過ごしください.
monit から Slack に通知するコマンドは初心者レベルの Go 言語で作ってみました. クソコードでお恥ずかしい限りですが, おまけとして掲載させて頂きます.
package main import ( "bytes" "flag" "fmt" "github.com/joho/godotenv" "net/http" "os" "strings" ) const ( AppVersion = "0.0.1" ) var ( argEnv = flag.String("env", "", ".env ファイルのパスを指定.") argVersion = flag.Bool("version", false, "バージョンを出力.") ) func loadEnv(envPath string) { var err error if envPath != "" { err = godotenv.Load(envPath) } else { err = godotenv.Load() } if err != nil { fmt.Println("Error loading .env file") os.Exit(1) } } func main() { flag.Parse() if *argVersion { fmt.Println(AppVersion) os.Exit(0) } loadEnv(*argEnv) username := os.Getenv("SLACK_USER_NAME") channel := os.Getenv("SLACK_CHANNEL") icon_emoji := os.Getenv("SLACK_ICON") descStr := `{"title":"description","value":"` + os.Getenv("MONIT_DESCRIPTION") + `"}` var text string var attachmentStr string if strings.Contains(os.Getenv("MONIT_DESCRIPTION"), "not running") { text = os.Getenv("MONIT_HOST") + " にて " + os.Getenv("MONIT_SERVICE") + " プロセスが停止しました." attachmentStr = `{"color":"#ff0000","fields":[` + descStr + `]}` } else { text = os.Getenv("MONIT_HOST") + " にて " + os.Getenv("MONIT_SERVICE") + " プロセスが再起動しました." attachmentStr = `{"color":"#008000","fields":[` + descStr + `]}` } jsonStr := `{"channel":"` + channel + `","username":"` + username + `","text":"` + text + `","icon_emoji":"` + icon_emoji + `","attachments":[` + attachmentStr + `]}` req, err := http.NewRequest( "POST", os.Getenv("SLACK_URL"), bytes.NewBuffer([]byte(jsonStr)), ) if err != nil { fmt.Print(err) } req.Header.Set("Content-Type", "application/json") client := &http.Client{} resp, err := client.Do(req) if err != nil { fmt.Print(err) } // fmt.Print(resp) defer resp.Body.Close() }
monit は監視対象に異常を検知した場合, 以下のような環境変数に値をセットします.
これらを利用して, プロセスが停止した場合, 再起動した場合の処理分岐を行っています. また, Slack の Incomming Webhook の URL 等の情報は .env
ファイルに書いて, 別で管理することを想定しています. コマンドは以下のように実行します.
/path/to/bin/command -env /path/to/env
Availability Zone のどっちか!とか, Subnet ID のどっちか!をランダムに欲しい時にどうしようかなと思っていたら, Terraform には Random Provider というプロバイダが用意されていたので, 色々と触ってみました.
ここのリソースの細かいオプションはドキュメントを読みましょう.
尚, 検証に利用した環境は以下の通りです. 最新でなくてごめんなさい.
$ terraform version Terraform v0.11.11 + provider.random v2.1.0 Your version of Terraform is out of date! The latest version is 0.11.13. You can update by downloading from www.terraform.io/downloads.html
resource "random_id" "sample" { byte_length = 8 } output "ramdom_id-b64_url" { value = "${random_id.sample.b64_url}" } output "ramdom_id-b64_std" { value = "${random_id.sample.b64_std}" } output "ramdom_id-hex" { value = "${random_id.sample.hex}" } output "ramdom_id-dec" { value = "${random_id.sample.dec}" }
Outputs: ramdom_id-b64_std = +5xe3FnkIKw= ramdom_id-b64_url = -5xe3FnkIKw ramdom_id-dec = 18130470500380713132 ramdom_id-hex = fb9c5edc59e420ac
resource "random_integer" "sample" { min = 1 max = 99999 } output "ramdom_integer" { value = "${random_integer.sample.result}" }
Outputs: ramdom_integer = 16343
resource "random_pet" "sample" {} output "ramdom_pet" { value = "${random_pet.sample.id}" }
Outputs: ramdom_pet = lenient-viper
resource "random_shuffle" "sample" { input = ["foo", "bar", "buz", "qux", "quux"] result_count = 2 } output "ramdom_shuffle" { value = "${random_shuffle.sample.result}" }
Outputs: ramdom_shuffle = [ bar, buz ]
resource "random_string" "sample" { length = 16 special = true } output "ramdom_string" { value = "${random_string.sample.result}" }
Outputs: ramdom_string = 0ucqy18F+VR9lhC5
resource "random_uuid" "sample" {} output "ramdom_uuid" { value = "${random_uuid.sample.result}" }
Outputs: ramdom_uuid = d8a65bb0-46c4-17a0-ab47-ba1d7b15d562
ざっくりと Ramdom プロバイダを触ってみました. まじで Terraform ってなんでも出来ますよね.