試験は1問〇点みたいなのじゃなくて、難易度毎に調整が入る方式だと思う(項目応答理論的な)。
なので単純計算はできないが、仮に単純計算したら、65問中5問も間違えてる計算。
何が駄目だったんだろう。昔はなかった持続可能性周りの範囲でやらかしたのかな。
とりま、SAA目指して頑張りますん(5年くらい前に1回取ったけどとっくの昔に有効期限切れてる)。
試験は1問〇点みたいなのじゃなくて、難易度毎に調整が入る方式だと思う(項目応答理論的な)。
なので単純計算はできないが、仮に単純計算したら、65問中5問も間違えてる計算。
何が駄目だったんだろう。昔はなかった持続可能性周りの範囲でやらかしたのかな。
とりま、SAA目指して頑張りますん(5年くらい前に1回取ったけどとっくの昔に有効期限切れてる)。
書きたいネタはあるが整理する時間がないので今直面した小ネタを。
VSCode から WSL 2 につないでる状態で、python ライブラリをうまく検知できてなくてワーニングが出た。
これで解決。
$ python -c "import site; print (site.getsitepackages())" ['/home/talkeyboid/anaconda3/lib/python3.9/site-packages']
今セールしているので Ozone 9 から 10 にアップグレードしました。使う予定はまだないです。軽く沼ってる気がします。
新機能が使えるぞ!※まだ1秒も使ってない。
ついでにプラグインを棚卸しました。なんか他に買ってる気もするが一旦これだけ。
種別 | メーカー | ソフト |
---|---|---|
DAW | Ableton | Ableton Live 11 Suite |
Plugin | Native Instruments | KOMPLETE 13 Ultimate |
Plugin | WAVES | Diamond 12 |
Plugin | WAVES | Sibilance 14 |
Plugin | WAVES | Vocal Rider 12 |
Plugin | FabFilter | Pro Q3 |
Plugin | iZotope | Ozone 10 Advanced |
Plugin | Antares | Autotune Access |
それぞれどこにアプリケーション、オーディオファイル、VSTが配置されていて自分で外付けSSDに逃がしたのはどれかとか整理したいんですが大変なのでまたやる気のあるときに(絶対やらないやつ)。
業務環境では WSL2 が使えないので Git Bash で AWS CLI 操作をしていましたが、スラッシュが扱えなかったためメモ。
MSYS側で良しなに Windows パスを扱えるようにしてくれますが、CLI の引数では /
はそのまま通してほしいです。
そんなときに MSYS_NO_PATHCONV=1
を指定します。
MSYS_NO_PATHCONV=1 aws logs describe-metric-filters --log-group-name /aws/lambda/hoge-function
以上!
導入までは以下の記事ほぼそのままです。※pip 使わず conda 使ってるところだけ違う。元記事の方はうんこ漏らしてません。
インストーラは一ディレクトリ作成
$ mkdir tmp $ cd tmp
以下のページより Linux 向けインストーラのパスをコピー
これ
ダウンロード
# URLに上記インストーラのパスを指定 $ wget https://repo.anaconda.com/archive/Anaconda3-2022.10-Linux-x86_64.sh
インストーラ実行
$ bash Anaconda3-2022.10-Linux-x86_64.sh Welcome to Anaconda3 2022.10 In order to continue the installation process, please review the license agreement. Please, press ENTER to continue >>> ##### ここにライセンス文が表示される #####
ライセンスに同意
Do you accept the license terms? [yes|no] [no] >>> yes
ロケーション選択
Anaconda3 will now be installed into this location: /home/talkeyboid/anaconda3 - Press ENTER to confirm the location - Press CTRL-C to abort the installation - Or specify a different location below [/home/talkeyboid/anaconda3] >>>
conda init するか
Do you wish the installer to initialize Anaconda3 by running conda init? [yes|no] [no] >>> yes
/tmp
を削除
$ cd .. $ rm -rf tmp/
パス設定し反映
$ echo "export PATH=~/anaconda3/bin:\$PATH" >> ~/.bash_profile $ source ~/.bash_profile
バージョン確認
$ conda -V conda 22.9.0
元記事では conda init bash
を実行していますが、インストーラの指示に従い、conda init? >>> yes
としたため対応不要です。
念のため確認
$ cat ~/.bashrc ... # >>> conda initialize >>> # !! Contents within this block are managed by 'conda init' !! __conda_setup="$('/home/talkeyboid/anaconda3/bin/conda' 'shell.bash' 'hook' 2> /dev/null)" if [ $? -eq 0 ]; then eval "$__conda_setup" else if [ -f "/home/talkeyboid/anaconda3/etc/profile.d/conda.sh" ]; then . "/home/talkeyboid/anaconda3/etc/profile.d/conda.sh" else export PATH="/home/talkeyboid/anaconda3/bin:$PATH" fi fi unset __conda_setup # <<< conda initialize <<<
設定を反映
$ source ~/.bashrc
するとこんな感じでプロンプトに conda 環境名がつく
talkeyboid@talkeyboidsrfc:~$ source ~/.bashrc (base) talkeyboid@talkeyboidsrfc:~$
一旦適当に作る。
$ conda create -n test python=3.9 $ conda info -e # conda environments: # base * /home/talkeyboid/anaconda3 test /home/talkeyboid/anaconda3/envs/test $ conda activate test
# 元サイトは pip で入れているが私の環境では conda でインストールする $ conda install jupyterlab $ jupyter kernelspec list Available kernels: python3 /home/talkeyboid/anaconda3/envs/test/share/jupyter/kernels/python3
$ jupyter lab --NotebookApp.token='' [W 2023-03-06 21:54:36.226 LabApp] 'token' has moved from NotebookApp to ServerApp. This config will be passed to ServerApp. Be sure to update your config before our next release. [I 2023-03-06 21:54:36.232 ServerApp] jupyterlab | extension was successfully linked. [I 2023-03-06 21:54:36.238 ServerApp] nbclassic | extension was successfully linked. [I 2023-03-06 21:54:36.241 ServerApp] Writing Jupyter server cookie secret to /home/talkeyboid/.local/share/jupyter/runtime/jupyter_cookie_secret [I 2023-03-06 21:54:36.458 ServerApp] notebook_shim | extension was successfully linked. [W 2023-03-06 21:54:36.475 ServerApp] All authentication is disabled. Anyone who can connect to this server will be able to run code. [I 2023-03-06 21:54:36.478 ServerApp] notebook_shim | extension was successfully loaded. [I 2023-03-06 21:54:36.480 LabApp] JupyterLab extension loaded from /home/talkeyboid/anaconda3/envs/test/lib/python3.9/site-packages/jupyterlab [I 2023-03-06 21:54:36.480 LabApp] JupyterLab application directory is /home/talkeyboid/anaconda3/envs/test/share/jupyter/lab [I 2023-03-06 21:54:36.484 ServerApp] jupyterlab | extension was successfully loaded. _ _ _ _ | | | |_ __ __| |__ _| |_ ___ | |_| | '_ \/ _` / _` | _/ -_) \___/| .__/\__,_\__,_|\__\___| |_| Read the migration plan to Notebook 7 to learn about the new features and the actions to take if you are using extensions. https://jupyter-notebook.readthedocs.io/en/latest/migrate_to_notebook7.html Please note that updating to Notebook 7 might break some of your extensions. [I 2023-03-06 21:54:36.491 ServerApp] nbclassic | extension was successfully loaded. [I 2023-03-06 21:54:36.492 ServerApp] Serving notebooks from local directory: /home/talkeyboid [I 2023-03-06 21:54:36.492 ServerApp] Jupyter Server 1.23.4 is running at: [I 2023-03-06 21:54:36.492 ServerApp] http://localhost:8888/lab [I 2023-03-06 21:54:36.492 ServerApp] or http://127.0.0.1:8888/lab [I 2023-03-06 21:54:36.492 ServerApp] Use Control-C to stop this server and shut down all kernels (twice to skip confirmation).
が、http://localhost:8888/lab
もしくは http://localhost:8888
でつながらない。
こんなかんじで pending
。
設定ファイル周りで何かよくないのかといろいろとググっていたところ、いつのまにか起動してました。あまりに時間がかかってしまっていたので、ググってる途中でちょっとうんこ漏れた。
何回もアクセスしていたからか、起動ログ的には GET がめちゃくちゃ走ってる。22:04~22:13って時間かかりすぎでないか???使い物にならん。
[I 2023-03-06 22:04:20.021 ServerApp] Use Control-C to stop this server and shut down all kernels (twice to skip confirmation). [I 2023-03-06 22:13:09.644 ServerApp] 302 GET / (127.0.0.1) 31.37ms [I 2023-03-06 22:13:09.645 ServerApp] 302 GET / (127.0.0.1) 31.54ms [I 2023-03-06 22:13:09.645 ServerApp] 302 GET / (127.0.0.1) 31.49ms [I 2023-03-06 22:13:09.645 ServerApp] 302 GET / (127.0.0.1) 31.28ms [I 2023-03-06 22:13:09.646 ServerApp] 302 GET / (127.0.0.1) 31.20ms [I 2023-03-06 22:13:09.646 ServerApp] 302 GET / (127.0.0.1) 31.16ms [I 2023-03-06 22:13:09.651 ServerApp] 302 GET / (127.0.0.1) 35.09ms [I 2023-03-06 22:13:09.652 ServerApp] 302 GET / (127.0.0.1) 35.22ms [I 2023-03-06 22:13:09.652 ServerApp] 302 GET / (127.0.0.1) 35.40ms [I 2023-03-06 22:13:09.664 ServerApp] 302 GET / (127.0.0.1) 45.87ms [I 2023-03-06 22:13:09.677 ServerApp] 302 GET / (127.0.0.1) 55.90ms
ノートブック動きました。
立ち上がるまでにめちゃ時間かかるのとても前時代的PC感あるのでなんとかしたいですね。
基本的には以下のやり方でOK。
curl https://hub.docker.com/v2/repositories/<repository name>/tags?page_size=100 | jq .results[].name
公式イメージを取得する場合は、リポジトリ名に library
を指定する必要があるので注意。
以下では "magic string" と呼んでいる人がいる。公式ドキュメントに記載はない模様(見つけた人いたら教えて)。
例えば python:3.6
の亜種を見つけたい場合は以下のようにする。
curl https://hub.docker.com/v2/repositories/library/python/tags?page_size=100 | jq .results[].name | grep 3.6
CKA, CKAD の試験では DockerHub を見ることができないので覚えておきたい。
が、、、そんな問題出るのか? Nginx Ingress だって試験中に公式ページ見れないけど全部覚える???
無理、そんなむずい問題でたら諦めます。
今回は Serverless Framework で StepFunctions を作成し、エラー時の Cloudwatch Alarm も併せて定義します。
今回構築する環境を超適当に書くとこんな感じです。
Step Functions の Map を使って後続の関数をスケールします。SQS 使わずに実装できてとても便利です。
また、Step Functions の実行がコケたときに通知するため、Alarm と SNS を実装しています。
今回は2つのプラグインを利用します。
$ npm install -g serverless-step-functions $ npm install -g serverless-prune-plugin
こんな感じでディレクトリを作成します。
$ tree stepfunctions-tutorial/ stepfunctions-tutorial/ ├── email.yml ├── handler1.py ├── handler2.py └── serverless.yml 0 directories, 4 files
email.yml
は SNS トピックに設定するメールをブログでうっかり公開しないように serverless.yml
から外出しするために作りました。
address: hogehoge@fugafuga.com
適当に Lambda を実装します。
import json def func1(event, context): body = { "message": "Go Serverless v3.0! Your function executed successfully!", "input": event, "targets": [0,1,2] } response = {"statusCode": 200, "body": body} # json.dumps しない。 return response
import json def func2(event, context): print(event) body = { "message": "Go Serverless v3.0! Your function executed successfully!", "input": event, } response = {"statusCode": 200, "body": json.dumps(body)} return response
handler1.py
から body.targets
配列を返しています。Lambda の初期レスポンス値は json.dumps()
されているのですが、dump するとエスケープされてしまうので json.dumps()
しないように注意。
ちなみに、json.dumps()
した値が後続処理に渡ると以下のようにマッピング失敗となります。
serverless.yml
を書いていきます。
まずは全体像。
org: talkeyboid service: stepfunctions-tutorial frameworkVersion: '3' plugins: - serverless-step-functions - serverless-prune-plugin provider: name: aws runtime: python3.9 region: ap-northeast-1 memorySize: 128 timeout: 3 logRetentionInDays: 14 apiKeys: - ${self:service}-key usagePlan: quota: limit: 100 offset: 0 period: MONTH throttle: burstLimit: 3 rateLimit: 1 custom: prune: automatic: true number: 3 env: email: ${file(./email.yml)} functions: func1: handler: handler1.func1 func2: handler: handler2.func2 stepFunctions: stateMachines: myStateMachine1: name: myStateMachine1 # role: "設定する場合はここにARN" loggingConfig: level: ALL includeExecutionData: true destinations: - Fn::GetAtt: [StepFunctionLogGroup, Arn] alarms: topics: alarm: Ref: EmailTopic metrics: - executionTimedOut - executionFailed - executionsAborted - executionThrottled treatMissingData: missing events: - http: path: hoge method: POST private: true # iamRole: "設定する場合はここにARN" definition: StartAt: Task1 States: Task1: Type: Task Resource: Fn::GetAtt: [Func1LambdaFunction, Arn] Next: MapTask MapTask: Type: Map ItemsPath: "$.body.targets" Iterator: StartAt: Task2 States: Task2: Type: Task Resource: Fn::GetAtt: [Func2LambdaFunction, Arn] End: true End: true resources: Resources: EmailTopic: Type: AWS::SNS::Topic Properties: TopicName: EmailTopic EmailSubscription: Type: AWS::SNS::Subscription Properties: Protocol: email TopicArn: !Ref EmailTopic Endpoint: ${self:custom.env.email.address} StepFunctionLogGroup: Type: AWS::Logs::LogGroup DeletionPolicy: Delete Properties: LogGroupName: /aws/states/${self:service}-${self:stepFunctions.stateMachines.myStateMachine1.name}-Logs RetentionInDays: 14
ポイントをいくつか。
provider: name: aws runtime: python3.9 region: ap-northeast-1 memorySize: 128 timeout: 3 logRetentionInDays: 14 apiKeys: - ${self:service}-key usagePlan: quota: limit: 100 offset: 0 period: MONTH throttle: burstLimit: 3 rateLimit: 1
provider
で メモリサイズとタイムアウト等を明示的に指定しています。serverless のデフォルト値だとオーバースペックすぎるためです。
apiKeys
, usagePlan
で API Gateway のキーと使用量プランを設定しています。これは明示的に設定しない限り作成されないので自分で書く必要があります。API キーが不要な場合は記載しなくていいです。
custom: prune: automatic: true number: 3 env: email: ${file(./email.yml)}
custom.prune
で Lambda のバージョン世代保持数を指定しています。デフォルトでは無限に増殖するため、抑えないといけません。今回は検証なので特に指定する必要はなかったですが、後学のために設定しました。
また、env.email
に email.yml
ファイルを設定しています。そのため、メールアドレスを取得したければ ファイル内のプロパティと結合し、${self:custom.env.email.address}
で取得できます。
今回の本題、StepFunctions の部分です。
stepFunctions: stateMachines: myStateMachine1: name: myStateMachine1 # role: "設定する場合はここにARN" loggingConfig: level: ALL includeExecutionData: true destinations: - Fn::GetAtt: [StepFunctionLogGroup, Arn]
StepFunctions のロググループは明示的に設定しないと作成されないようなので、後述する resources
でロググループを作成し、それを loggingConfig.destinations
に Fn::GetAtt
で Arn を取得し設定しています。
alarms: topics: alarm: Ref: EmailTopic metrics: - executionTimedOut - executionFailed - executionsAborted - executionThrottled treatMissingData: missing
Cloudwatch Alarm の設定もここでできます。alarms
プロパティの中で、後述する resources
で定義した SNS トピックを設定しています。メトリクスは以下を参照。
欠損データの取り扱いについては以下を参照。
ここでは書いていませんが、スレッショルドも設定できると思うので次やるときには設定したいと思います。
API Gateway の設定は Lambda の定義と同じく、events
に設定します。API キーを利用する場合、private=true
に設定します。
events: - http: path: hoge method: POST private: true # iamRole: "設定する場合はここにARN"
definition: StartAt: Task1 States: Task1: Type: Task Resource: Fn::GetAtt: [Func1LambdaFunction, Arn] Next: MapTask MapTask: Type: Map ItemsPath: "$.body.targets" Iterator: StartAt: Task2 States: Task2: Type: Task Resource: Fn::GetAtt: [Func2LambdaFunction, Arn] End: true End: true
StepFunctions の中身を definition
に設定します。ここはマネジメントコンソールのビジュアルエディタで作成した json の内容をほぼそのまま転記する形で記載できそうです。
ただし、どの Lambda 関数を実行するかは若干のハックが必要です。Arn を指定する必要があるため、Fn::GetAtt
をしていますが、ここへは functions
へ定義した関数名をパスカルケースにし、後ろに LambdaFunction を付けます。
functions: func1: # これをパスカルケースにする -> Func1、+ LambdaFunction = Func1LambdaFunction handler: handler1.func1 func2: # これをパスカルケースにする -> Func2、+ LambdaFunction = Func2LambdaFunction handler: handler2.func2
これは serverless の仕様で、serverless deploy(package)
するときに作成される CloudFormation テンプレートにそのように定義されるためです。
{ "AWSTemplateFormatVersion": "2010-09-09", "Description": "The AWS CloudFormation template for this Serverless application", "Resources": { ... "Func1LambdaFunction": { "Type": "AWS::Lambda::Function", "Properties": { ... "Handler": "handler1.func1", "Runtime": "python3.9", "FunctionName": "stepfunctions-tutorial-dev-func1", ... } }
resources: Resources: EmailTopic: Type: AWS::SNS::Topic Properties: TopicName: EmailTopic EmailSubscription: Type: AWS::SNS::Subscription Properties: Protocol: email TopicArn: !Ref EmailTopic Endpoint: ${self:custom.env.email.address} StepFunctionLogGroup: Type: AWS::Logs::LogGroup DeletionPolicy: Delete Properties: LogGroupName: /aws/states/${self:service}-${self:stepFunctions.stateMachines.myStateMachine1.name}-Logs RetentionInDays: 14
Email 通知用の SNS トピック・サブスクリプションと、StepFunctions 用のロググループを作成しています。StepFunctions のデフォルトのロググループ名は /aws/vendedlogs/states/<statemachine name>-Logs
のようになっているため、それに合わせています。※AWSで作成しているわけではないので、vendedlogs
は抜いています。
RetentionInDays
は完全に適当です。実務で使うときには考えましょう。
マネジメントコンソールからエンドポイントとAPI キーを取得し、Postman に設定し、実行します。
項目 | 値 |
---|---|
メソッド | POST |
URL | ステージのエンドポイント + パス(https://~/dev/hoge) |
HTTPヘッダ | x-api-key=APIキー |
私はよくルートURLの後にパスをつけ忘れて 403 になってしまうことがあります。404 なら気づきようがあるのですが、403 だと「キー設定してるのにおかしいな...」となるので備忘として残しておきます。
実行結果は以下のように返ってきます。executionArn
は ステートマシン名 + 実行ID(ランダム値)です。
{ "executionArn": "arn:aws:states:ap-northeast-1:XXXXXXXXXXXX:execution:myStateMachine1:0fbeb2e9-581c-49ed-88b8-1c70e200a609", "startDate": 1.676463213988E9 }
少々ハックはありますが、簡単に実装することができました。
Alarm の確認もしようと思ったのですが、結構時間がかかったのでまた次回。