tech.guitarrapc.cóm

Technical updates

PowerShellでマルチプラットフォームに動くモジュールの作成と継続的なテスト

この記事は、PowerShell Advent Calendar 2018 の 22日目です。

qiita.com

今年は、PowerShell Coreについて本を書いたのですが、その中で書ききれなかった.NET Core と .NET Framework の両方で動くPowerShellモジュールの実用的なサンプルです。

目次

目的

このサンプルを作った目的は、単純に自分が書いていて自分のために用意した環境が汎用的に使えるものだったのでオープンにしただけです。(正直)

ただ、その背景にはいくつか動機があります。

  • 最近.NET は .NET Coreでしか作らないこと
  • PowerShell モジュールを作ろうという機会があった
  • CIで継続的に実行可否をテストしたい
  • ビルド環境につかれたのでDockerでビルドしたい

これらの例は本で提供するには紙面の見せ方も難しく、あの本でやるにはスコープを外していました。 今回の記事はそういう意味では本の補足記事になります。

Utf8BomHeader

非常にこじんまりとしたモジュールを作りました。実装は Utf8BomHeader.psm1 ファイル1つ、PowerShell Gallery で公開するためにUtf8BomHeader.psd1 を一つ追加しただけです。

github.com

このモジュールはファイルのUtf8Bomを扱うだけのもので、Windows 10、MacOS (mojave), ubuntu上で動作を確認しています。PowerShell 5.1以上、PowerShell Core 6.0 以上で動作します。

動機

Windows と Linux の相互対応、あるいはWindowsでクロスプラットフォームで動くものを動かす時、そのどちらでも課題になるのがファイルのエンコーディングです。 特に、Utf8 の BOMはWindowsでBOMが意図せずつくことがあったりして厄介度が上がっているように思います。

皆さんも Docker for Windows でDockerにファイルをmountで渡したときにファイルエンコーディングで怒られた経験をお持ちなのではないでしょうか? あるいは、GoやPythonでクロスプラットフォームに動く前提で作られたものが求めるファイルエンコーディングも通常は Utf8noBomです。

モジュールができること

このモジュールが提供するのは4機能だけです。

  • Test : utf8bom の有無をテストします。BOMがあれば trueです
  • Get : ファイルを先頭から読んでバイナリを表示します。デフォルトは3バイトです(BOM分)
  • Remove : ファイルのBOMを削除します
  • Add : ファイルにBOMを追加します
  • Coimpare : 2ファイル間でそれぞれのBOM結果を出します

実装について

少し実装について触れましょう。 当初PowerShell のみで書いていたのですが、ファイルをストリームで読むためのDisposeのために関数用意するのも冗長になるのも嫌です。 サンプルとして、Test-Utf8BomHeade のPowerShell 版は次のようにFileStream を開いてヘッダを読むことになります。

gist.github.com

本でも書きましたが、リソースの自動破棄は簡単な Using-Dispose 当りの糖衣関数を書いてもいいのですが、あまりスクリプトブロック内部で例外を起こしたくもありません。

そのため、今回のモジュールはインラインで定義した C# で実装を書いて、PowerShell はAdd-Typeでオンザフライにコンパイルしています。

https://github.com/guitarrapc/Utf8BomHeader/blob/94af0c001495a9a49a6bce53f207f5df09cf54a5/src/Utf8BomHeader.psm1#L1-L104

C# はNET Coreで動作することだけ気を付ければたいがい問題ありません。読み込んだC# クラスをPowreShell から呼び出すようにすると先ほどの実装が次のようになります。

gist.github.com

やりたいことだけ、という感じでシンプルになります。 さて、インラインでC#コードを文字列で書くのはよみにくいですね? 私も同意です、PowerShell の外に C# コードを定義したファイルはGitHub上でコードハイライトが利いたり、VS Codeで単品で動かせるメリットがあります。しかしビルド、展開、利用を考えるとファイルは少ない方が取り扱いが圧倒的に楽なため、インラインに定義できるならそうするのをオススメします。

今回はC# で実装を書きましたが、もちろんPowerShell で書くのほうが楽なことも多いです。気を付けるといいのはPowerShell Core と Windows PowerShellで両方動くようにするための抽象化は余り頑張らないようにした方が「書くのが苦しくない」ということです。いちいち互換性を気を付けることも、互換性の抽象化レイヤーを書くのもどちらもやりたいことではありません。私は苦しいのが嫌なので楽をするためにもC# で書きました。C# なら言語レベルで .NET Framework / .NET Core で気を付けることはかなり少ないので選択したということです。

CI

今回はCIとして Appveyor を用いました。 2つのパターンでビルドを用意しました。

  • appveyor 提供の ubuntu18.04 での .NET Coreを使ったビルド
  • Microsoft/PowerShell 提供のDockerを使ったビルド

自前のDockerイメージを使うとどこのCIという縛りはありません。

PowrShell でコンテナを使ったビルド? 大げさでしょうか?ビルド、テストにコンテナを使うことで、普通のプログラミング言語のビルドと同様にビルド環境を選ばなくなります。自分のコードの実行を各種環境で検証することも容易になり、ビルドしたらもうその環境はクリーンなDisposableが担保されます。いろんな環境への可搬性を考慮するとコンテナを用いないという選択はないでしょう。

Appveyor 提供のビルドイメージを使ったビルド

さて、AppVeyor はビルド環境イメージが定義されています。

www.appveyor.com

このイメージにはあらかじめ開発ツールがインストールされていおり、PowerShell Core も ubuntuイメージに含まれています。

www.appveyor.com

仮にappveyor提供のubuntuイメージでやる場合、これぐらいのカジュアルな内容でいけます。 今回は、cd を使っているあたりなんというかそういう感じって感じです。

gist.github.com

では独自のdockerイメージではどうなるでしょうか?

独自Dockerイメージを用いた場合のビルド

Dockerイメージは、Microsoft/PowerShell 提供のmcr.microsoft.com/powershell:6.1.0-ubuntu-18.04を使います。Pesterだけ入れて、プロジェクトを突っ込みましょう。

gist.github.com

appveyor.yml は次のようになります。

gist.github.com

先ほどのAppveyor提供のubuntuイメージくらべると、各種コマンド部分がそのままDockerコンテナでの実行に代わっただけです。こういった簡便な違いで済む割に、コンテナ内部の依存性はDockerfileで統一されるので敷居は低いでしょう。

ただし、mcr.microsoft.com/powershell:6.1.0-ubuntu-18.04 で1つ気になるのが、dotnet が叩けず、Publish-Moduleが実行できないことです。 Artifactなので外に出せばいいので別にいいというわけにもいかない場合があるのでちょっとどうしようかという感じです。

Appveyor のdockerを用いる場合の注意

AppveyorでDocker Imageをビルドする時は、services定義とbefore_build を使うのがプラクティスになっています。dockerは、linux image でdockerサービスの起動をかけることで利用できるので、servicesセクションを appveyor.yml 冒頭に定義しておきます。

services:
- docker

install: よりも後でしかservice startさればいため、docker buildbeffore_build:あたりでします。この実行タイミングはドキュメントになくてここで説明されています。

Build failed: Cannot connect to the Docker daemon at unix:///var/run/docker.sock. Is the docker daemon running? / Problems / Discussion Area - AppVeyor Support

テスト

テストは、PowerShell の標準的なテストツールである Pester を用いたユニットテストとしました。 ここまで小さい機能だと、ユニットテストが使うシーンそのままなのでシナリオテストにもなります。

Utf8BomHeader/Utf8BomHeader.Tests.ps1 at master · guitarrapc/Utf8BomHeader · GitHub

重要なのはテストを書くことではなく、継続的にテストが回ることです。 テストはCIと一緒にやることで初めてスタート地点に立つのはPowerShell モジュールでも変わりません。

なお、テストカバレッジは Peseterで出せるので、適当にこんなコードでREADME.md を書き換えたりもできます。

gist.github.com

あとは適当に remote push しましょう。

environment:
  access_token:
    secure: zYCOwcOlgTzvbD0CjJRDNQ==

on_success:
  - git config --global credential.helper store
  - ps: Add-Content "$HOME\.git-credentials" "https://$($env:access_token):x-oauth-basic@github.com`n"
  - git config --global user.email "Your email"
  - git config --global user.name "Your Name"
  - git commit ...
  - git push ...

成果物の取得

ビルドして生成された成果物は Artifacts でアップロードしてあげればいいでしょう。

https://ci.appveyor.com/project/guitarrapc/utf8bomheader/branch/master/artifacts

ビルド結果

ログがすぐに吹き飛ぶのでキャプチャで。

Build started
git clone -q --branch=master https://github.com/guitarrapc/Utf8BomHeader.git /home/appveyor/projects/utf8bomheader
git checkout -qf ecf403c5fa0975688503c2c74a15a4837ed62e93
Running "install" scripts
pwsh --version
PowerShell 6.1.1
Starting 'services'
Starting Docker
Running "before_build" scripts
docker build -t utf8bomheader_build:latest .
Sending build context to Docker daemon  175.6kB
Step 1/5 : FROM mcr.microsoft.com/powershell:6.1.0-ubuntu-18.04
6.1.0-ubuntu-18.04: Pulling from powershell
124c757242f8: Pulling fs layer 
Status: Downloaded newer image for mcr.microsoft.com/powershell:6.1.0-ubuntu-18.04
 ---> bcea40fb0698
Step 2/5 : WORKDIR /app
 ---> Running in e03532abc50f
Removing intermediate container e03532abc50f
 ---> 40e5cd66d690
Step 3/5 : COPY . .
 ---> a391219f8b2e
Step 4/5 : RUN pwsh -c Install-Module Pester -Scope CurrentUser -Force
 ---> Running in 20dab6bbeaf2
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                 Installing package 'Pester'                                                        Downloaded 0.00 MB out of 0.69 MB.                                              [                                                                    ]                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                      Removing intermediate container 20dab6bbeaf2
 ---> 8bee724ae30b
Step 5/5 : ENTRYPOINT [ "pwsh", "-c" ]
 ---> Running in a365d19ff2e5
Removing intermediate container a365d19ff2e5
 ---> 138aa32dca7b
Successfully built 138aa32dca7b
Successfully tagged utf8bomheader_build:latest
docker image ls
REPOSITORY                     TAG                  IMAGE ID            CREATED                  SIZE
utf8bomheader_build            latest               138aa32dca7b        Less than a second ago   369MB
mcr.microsoft.com/powershell   6.1.0-ubuntu-18.04   bcea40fb0698        2 months ago             367MB
Running "build_script" scripts
docker run --rm -v "${APPVEYOR_BUILD_FOLDER}/publish:/app/publish" utf8bomheader_build:latest "./build_psd1.ps1 -Version ${APPVEYOR_BUILD_VERSION}"
    Directory: /app/publish
Mode                LastWriteTime         Length Name
----                -------------         ------ ----
d-----         12/22/18   7:16 PM                Utf8BomHeader
7z a "${APPVEYOR_BUILD_FOLDER}/publish/Utf8BomHeader_${APPVEYOR_BUILD_VERSION}.zip" "${APPVEYOR_BUILD_FOLDER}/publish/Utf8BomHeader/"
7-Zip [64] 16.02 : Copyright (c) 1999-2016 Igor Pavlov : 2016-05-21
p7zip Version 16.02 (locale=C.UTF-8,Utf16=on,HugeFiles=on,64 bits,2 CPUs Intel(R) Xeon(R) CPU @ 2.30GHz (306F0),ASM,AES-NI)
Scanning the drive:
  0M Scan  /home/appveyor/projects/utf8bomheader/publish/                                                         1 folder, 4 files, 17125 bytes (17 KiB)
Creating archive: /home/appveyor/projects/utf8bomheader/publish/Utf8BomHeader_1.0.69.zip
Items to compress: 5
  0%    
Files read from disk: 4
Archive size: 5053 bytes (5 KiB)
Everything is Ok
Running "test_script" scripts
docker run --rm utf8bomheader_build:latest "Invoke-Pester -CodeCoverage src/Utf8BomHeader.psm1"
Executing all tests in '.'
Executing script /app/tests/Utf8BomHeader.Tests.ps1
  Describing Utf8BomHeader
    [+] Test should be pass for bom 1.2s
    [+] Test should be fail for bomless 75ms
    [+] Add should append BOM 45ms
    [+] Add should not operate when BOM already exists 44ms
    [+] Add -Force should append BOM even already exists 26ms
    [+] Remove should not contains BOM 33ms
    [+] Remove should not operate when BOM not exists 20ms
    [+] Remove -Force should remove BOM even already not exists 38ms
    [+] Compare should return == when both contains BOM 25ms
    [+] Compare should return <= when reference not contains BOM 28ms
    [+] Compare should return => when difference not contains BOM 16ms
    [+] Compare should return <> when reference & difference not contains BOM 17ms
Tests completed in 1.58s
Tests Passed: 12, Failed: 0, Skipped: 0, Pending: 0, Inconclusive: 0 
Code coverage report:
Covered 44.62% of 65 analyzed Commands in 1 File.
Missed commands:
File               Function             Line Command
----               --------             ---- -------
Utf8BomHeader.psm1 Add-Utf8BomHeader     130 if (!$Force) {...
Utf8BomHeader.psm1 Add-Utf8BomHeader     131 $header = [FileHeader]::Read($F...
Utf8BomHeader.psm1 Add-Utf8BomHeader     132 if ($header -eq $bomHex) {...
Utf8BomHeader.psm1 Add-Utf8BomHeader     133 Write-Verbose "Bom already exis...
Utf8BomHeader.psm1 Add-Utf8BomHeader     137 Write-Verbose "-Force paramter ...
Utf8BomHeader.psm1 Add-Utf8BomHeader     139 [FileHeader]::Write($File, $Out...
Utf8BomHeader.psm1 Remove-Utf8BomHeader  175 if (!$Force) {...
Utf8BomHeader.psm1 Remove-Utf8BomHeader  176 $header = [FileHeader]::Read($F...
Utf8BomHeader.psm1 Remove-Utf8BomHeader  177 if ($header -ne $bomHex) {...
Utf8BomHeader.psm1 Remove-Utf8BomHeader  178 Write-Verbose "Bom already miss...
Utf8BomHeader.psm1 Remove-Utf8BomHeader  182 Write-Verbose "-Force paramter ...
Utf8BomHeader.psm1 Remove-Utf8BomHeader  184 [FileHeader]::Remove($File, $Ou...
Utf8BomHeader.psm1 Get-Utf8BomHeader     218 $header = [FileHeader]::Read($F...
Utf8BomHeader.psm1 Get-Utf8BomHeader     219 Write-Output $header
Utf8BomHeader.psm1 Test-Utf8BomHeader    258 $header = [FileHeader]::Read($F...
Utf8BomHeader.psm1 Test-Utf8BomHeader    259 Write-Output ($header -eq $bomHex)
Utf8BomHeader.psm1 Test-Utf8BomHeader    259 $header -eq $bomHex
Utf8BomHeader.psm1 Test-Utf8BomHeaderPS  281 if ($PSBoundParameters.Contains...
Utf8BomHeader.psm1 Test-Utf8BomHeaderPS  282 [System.IO.FileStream]$stream
Utf8BomHeader.psm1 Test-Utf8BomHeaderPS  284 $stream = $File.OpenRead()
Utf8BomHeader.psm1 Test-Utf8BomHeaderPS  285 $header = (1..3 | ForEach-Objec...
Utf8BomHeader.psm1 Test-Utf8BomHeaderPS  285 1..3
Utf8BomHeader.psm1 Test-Utf8BomHeaderPS  285 ForEach-Object {$stream.ReadByt...
Utf8BomHeader.psm1 Test-Utf8BomHeaderPS  285 $stream.ReadByte().ToString("X2")
Utf8BomHeader.psm1 Test-Utf8BomHeaderPS  286 Write-Output ($header -eq $bomHex)
Utf8BomHeader.psm1 Test-Utf8BomHeaderPS  286 $header -eq $bomHex
Utf8BomHeader.psm1 Test-Utf8BomHeaderPS  289 $stream.Dispose()
Utf8BomHeader.psm1 Test-Utf8BomHeaderPS  293 [System.IO.FileStream]$stream
Utf8BomHeader.psm1 Test-Utf8BomHeaderPS  295 $stream = [System.IO.FileStream...
Utf8BomHeader.psm1 Test-Utf8BomHeaderPS  296 $header = (1..3 | ForEach-Objec...
Utf8BomHeader.psm1 Test-Utf8BomHeaderPS  296 1..3
Utf8BomHeader.psm1 Test-Utf8BomHeaderPS  296 ForEach-Object {$stream.ReadByt...
Utf8BomHeader.psm1 Test-Utf8BomHeaderPS  296 $stream.ReadByte().ToString("X2")
Utf8BomHeader.psm1 Test-Utf8BomHeaderPS  297 Write-Output ($header -eq $bomHex)
Utf8BomHeader.psm1 Test-Utf8BomHeaderPS  297 $header -eq $bomHex
Utf8BomHeader.psm1 Test-Utf8BomHeaderPS  300 $stream.Dispose()
Collecting artifacts...
Found artifact 'publish/Utf8BomHeader_1.0.69.zip' matching 'publish/Utf8BomHeader_1.0.69.zip' path
Uploading artifacts...
[1/1] publish/Utf8BomHeader_1.0.69.zip (5053 bytes)...100%
Running "deploy_script" scripts
pwsh -file ./deploy_pagallery.ps1 -NuGetApiKey ${PS_GELLERY_RELEASE_API} -BuildBranch master -ModuleName Utf8BomHeader
"Appveyor" deployment has been skipped as "APPVEYOR_REPO_TAG_NAME" environment variable is blank
Build completed

まとめ

PowerShell Core 使っていくといいです。本にも書きましたが、PowerShell Coreは十分実用に到達して、すでにWindows PowerShell が及ばないレベルまでまともに動けるようになっています。

特に私の場合は、クロスプラットフォームで動作することを仕事でも私生活でも扱っているので、Windows PowerShell はたまに触るたびに本当につらいです。モジュールを作った動機もBOMごるぁ、だったのです。特にWindows で、PowerShell で書いていた、書きたい時にマルチプラットフォーム向けのファイルを吐き出したい時は抜群に使いやすいでしょう。

そして、CIは回しましょう。 PowerShell にはビルドがないのでCIはいらない? そんなことを言うのは3年前まではスルーでしたが、今は最低限でも担保したいテストを書いて、CIで継続的に回す方が自分にとって楽になることが多くなっています。

今後PowerShell のネタが PowerShell Core が大半を占めるようになることを祈ります。(個人の勝手なお願い

PS. 本当はAWS Lambda Runtime で PowerShell 動かして見せる。というのを書くかと思ったのですが、「毎年アドベントカレンダーを書いた後にもっとアドベントカレンダーは軽いネタをやるものだ。」と言われたので、今年はそのことを思い出して軽くしました。

オフトピック : もしも.NET Core + PowerShell Core を独自イメージにいれるなら

もし自分でインストールする場合に備えて、.NET Core / PowerShell Core のインストールステップも公開しておきます。.NET Core がubuntu で公開されているやり方にひと手間必要だったのでどぞ。

gist.github.com

.NET Core のMicrosoft Docページにもありますが、libicu60が必要なのですが .NET Coreのインストールページの説明にはなくてほげ、って感じです。apt-get install libicu60 でも入らないですし罠感はあります。

Serverless Conf Tokyo 2018 に来ている記事7 : Serverworks Session #ServerlessConf #serverlesstokyo

毎年参加しているServerless Conf Tokyoです。3回目になります。 集中力の限界なので、ここで終わりです。(途中で力尽きた

http://tokyo.serverlessconf.io/tokyo.serverlessconf.io

他のセッション

tech.guitarrapc.com

tech.guitarrapc.com

tech.guitarrapc.com

tech.guitarrapc.com

tech.guitarrapc.com

tech.guitarrapc.com

引用は私のコメントです。

目次

Title

Serverless Architecting and NoSQL Data Modeling for Successfully Microservices

Speaker

Masashi Terui

@marcy_terui

Slide

前提

AWS です。

Serverless で Microservice アプローチで問題なりやすいのは?

Function の粒度、切り方 サービスとしてのトレース

これらがいわゆるMicroservice と同様に懸念としてデてくる。

FaaS と DB

FaaS とRDBの相性は悪いのか

コネクションが都度破棄されるのでプーリングどうする? セキュリティ どうする? (VPCつなげないと認証強度あれ.....) VPCに入れるとENI作成のオーバーヘッド..... スケーリングが、厳しい.... まず垂直から検討になる。

FaaS とNoSQL の相性はいいのか

コネクションモデル がステートレス + HTPS IAM だでセキュリティ担保だよね。 スケーリングです。

で、どうしていく

という話ができないと、使い分けなんですよ、ではだめぽ。

目的のために最適化は違うことを踏まえる

やりかたはいろいろ

  • モノリシックに1つで処理
  • バックエンドAPIに分割
  • Microservice に分割して、データドリブンにつなげる

ここで話題とするのは、FaaS ごとにMicro Service にしてイベントドリブンにつなげましょう。

すべてのサービスはEventとActionの組み合わせ

Event をどのように処理すべきか。

原則として、Serverless のスケールアウトメリットを活かすなら非同期ベースに考える

  • 同期
    • API Gateway
  • 非同期
    • 直列
      • Kinesis Streams
    • 並列
      • SNS
      • SQS
      • StepFunctions

不安なのは、エラーハンドリングとなる。

  • 大事なのは、リトライできる仕組みにする。(リトラできないエラーは、1つのイベントとして通知させる)
  • モニタリング、トレーシングで必要な情報を集める

リトライアビリティはクラウドの基本だけど、冪等性、あるいは入力に対して常に同じ結果となるようにするのが重要。

どのように管理スべきか

  • Cloud Formation がいいと考えている
    • SAM / Serfverless Framework で管理すると楽

なぜかというと、Service の管理ができるから。

  • Event Srouce -> Action (Lambda) で紐付けられる
  • 宣言的
  • ImportValue /Ref

この意味で、CloudFormation はよくできている(書きにくいけど

ポイント

Event Source と Action 単位でStack を分けるのがいい。 EventSource を接続点として依存関係を集約できる。 非同期な関係性を重視することで依存関係の向きが揃う(循環依存がなくなりよい)

なぜここでClean Architecture をもってきたのか..... 文脈ちがうでしょ

Integration Test

SAM で、ステージ名をパラメータ化して、ステージごとのEventSour¥ce入れ替え。Mockを使ってDBを偽装。 入力をMock化するのでテストしやすい。 時間はかかるので基本CI化

Jenkisn や CircleCI のIDで一意なIDを取得、設定することで追跡も可能ですよ、と。

アプリケーション設計時のこつ

アプリケーション + DynamoDB 設計時のコツ

  • アプリケーションとデータモデルは同時に設計する
  • 書き込みと読み込みで都合いいデータを扱う
    • アイテムにまとめることで整合しを守る
    • 呼び込みは結果整合を受け入れて効率のよいジョインを

アプリケーション +RDS 設計時のコツ

Kibesis を噛ませてコネク暑中をおさえるのがいい。

Lambda に困っているるわけではない。

しっておくこと

  • 各データストアの特性
  • データ整合性を守る仕組み
    • ACID
  • データアクセス
    • B+ Tree Index

[ここで限界を迎えたのでおわり]

Serverless Conf Tokyo 2018 に来ている記事6 : Epsagon Session #ServerlessConf #serverlesstokyo

毎年参加しているServerless Conf Tokyoです。3回目になります。

http://tokyo.serverlessconf.io/tokyo.serverlessconf.io

他のセッション

tech.guitarrapc.com

tech.guitarrapc.com

tech.guitarrapc.com

tech.guitarrapc.com

tech.guitarrapc.com

引用は私のコメントです。

目次

Title

What We Should All Worry About When Monitoring Serverless Applications

Speaker

Nitzan Shapira @nitzanshapira

Slide

[]

Complexity and Monitoring

Serverless は複雑.... Resource は管理したい、Application はどんどん複雑になっていく..... 管理不可能になる前に関しを...。

Function は大事 (貴重)

  • Out of Memory
  • Cold start
  • Timeout

でもみたいのは、Service ですよー。

System > Function

これは重要で、System は、Functions + APIs + Transactions なので、Function の集合がサービスではない。 Function だけでは不十分、かつ、非同期イベントの関しまでトラブルシュートと修正には必要になる。

Distributed Tracing

Micro Service は、ロジックが個別に構成されている。 ロジックは関連を知らないので、同様にどのように接続されているのかを把握する必要がある。

Jaeger で可視化できるが、必要なのはどうやってそのデータを得るのか。

Manual Traces/Instrurentaion

このあたりをつかってやったり...。

  • OpenTracing
  • OpenCensus

やらないといけないことは多い。

  • Before and after call

Serverelss apps are very distributed

Complex Systems have thousands of functions What about the developer velopcity?

Exisiing Solutions?

  • AWS Cloud WatchLogs : ログは見れるけどそこまで
  • AWS X-Rays : Distributed ではあるけど、Lambda まで、AWS Service のプロファイリングに過ぎない
    • いわゆる Distributed Tracing ではない
    • 非同期イベントもおえない

縦串に処理を負えない、中途半端なTracing、APMになっている。起因がなにかを判別するのが難しいのがとてもじゃないけど、コレでは足りない。

Quick Look が重要

Serverless でスピードアップするので、Developer体験もスピードアップが必要。 そのため、Quick Loock として、トランザクション全体のリソース間の処理時間がぱっと見えるなどのレベルで簡単さが重要になる。

では、マニュアルでCloudWatch Logs を Lamnda で5分毎にスキャンしてRDSへ?

* CloudWatch がHighly Throttleに
* Request が時間かかるように
* 5K 同時Lambda for 5min はむりぽよ。

当然コストもべらぼうに高くなる。

まったくで、この常時起動 + Fanout手法でのServerless は地獄一直線なぁ

Obervability

ということで、X-Ray もだめ、マニュアルも厳しいので Epasgon ですよ。

https://epsagon.com/

Dynamic Service Map ビジネスフローを乗っけている。

Transaction の流れ、があるのはかなりいいのでは。 グラフDB使わないと関連クムのだるそうだな

ログインはこっちから

https://dashboard.epsagon.com/login

まとめ

トランザクションの流れは注目したいと思いつつ、どうやるかアイディアがわかなかったのでいい感じに思う。けど、正直StackDriverでID関連で組めないかなぁっていうのもあり.... 処理ごとにってなると手間だけど地道にいくしかないかなぁ

Serverless Conf Tokyo 2018 に来ている記事5 : Game Server Service Session #ServerlessConf #serverlesstokyo

毎年参加しているServerless Conf Tokyoです。3回目になります。

http://tokyo.serverlessconf.io/tokyo.serverlessconf.io

他のセッション

tech.guitarrapc.com

tech.guitarrapc.com

tech.guitarrapc.com

tech.guitarrapc.com

引用は私のコメントです。

目次

Title

Game Server Service サーバーレスアプリケーションの監視・運用

Speaker

丹羽一智

@kazutomo

Slide

従来のインフラ監視

  • Load Average
  • CPU Average
  • Memory Usage
  • Disk IO

を見てきた

Serverless 監視

これらは不要だけど、サービスは正しく動いているのか、コンポーネントが動いているのかを確認していくのが重要になる。 つまり

  • サービス監視
    • サービスが正しく提供されているか判断する指標
  • コンポーネント監視
    • コンポーネントが動いているのか

レイヤがインフラ生からサービスの要素に変わっているので、そうなりますね。

コンポーネント監視

キャパシティ管理、上限革の必要な項目

  • Lambda の同時実行数
  • API GAteway へのRequest/Sec
  • DynamoDB のキャパシティ使用率

障害発生時に障害店を特定するための項目

  • API Gateway の応答時間
  • Lambda の実行時間
  • DynamoDBの処理時間

などが重要

マルチクラウドでG2S は提供

AWS/GCPで提供される視覚表示は、折れ線グラフになっており指標とあってないこともおおい。

そのため、Datadog に大型モニタに表示して席から見てる。

監視内容

かなりDatadog の利用方法にそった監視方法になってる

基本メトリック

  • 秒間アクセス数
  • サービス利用者起因のエラー数 : User Error
  • GS2 のエラー数 : Backend Error
  • 想定外の例外発生数 : Fatal
  • Google App Engine のクォーターリミット

サービスパフォーマンス

所要時間が重要。

  • API GAtewya Response
  • Lambda Reponse
  • Lambda Code Response
  • Auth Duration
  • DunamoDB IO

Datadogのしきい値、色変化で見てる。

キャパシティ監視

  • DynamoDB で最もキャパシティを消費しているテーブルの使用率
    • 個別のテーブルはどうでもよくて、一番使っているやつを知る必要がある
  • Lambda の同時実行数のアカウント上限値に対する使用率
    • 同時実行の多いやつはどれだ!
  • Lambda/DynamoDB のスロットル発生回数

アラーム状態

  • アラームがすべてOKな状態か

直近4時間のAPIコール数

  • 点線は1週間前の同時間帯のグラフ
  • 直線は直近4時間におけるトレンド
  • 今どの程度のアクセスがあるかを可視化

Datadog のフィルタ機能で、移動平均やトレンドを出してる

一週間前の、とかトレンド、とか自分がやってるのと同じことやってる....

直近4時間のAPIランキング

  • 利用されているマイクロサービスランキング
  • レスポンスタイムのワーストランキング

ここも全く同じ....

直近一週間のAPI ランキング

期間を変えると見る要素かわりますからねぇ

直近1ヶ月のAPIコール数

  • 点線は1ヶ月前の同時間帯のグラフ
  • 直線は直近一ヶ月におけるトレンド
  • 跳ね上がっているのは、クライアントの実装ミスによってビジーになったこと

インフラのコスト

サービスの提供にかかっているインフラコストの可視化

異常な増え方をしていないかを視覚化

売上

サービスの売上可視化

  • 24h
  • 一ヶ月

ここまで、 黒騎士と白の魔王を支えるDatadogを使ったモニタリングで書いた内容とほぼ同じ

Datadog でどう監視するのか

プラグインの設定

  • AWS アカウントと、AssumeRoleに使用するロールの設定
  • どのサービスのメトリックを収集するか設定
  • どのサービスにどのタグを設定

コンポーネントの追加

どのようそを関しするよ、とかをScreen Bpard に投げてる

メトリックの設定

どのメトリックのをせてい

  • レンダリングするデータソースを設定
  • SelectyaGroupBy もできる
  • フィルタで移動平均とかもだせる

値の範囲でダッシュボードに表示する色を設定可能

  • 異常値になったときには色が変わるようにすることええ、すぐに異常でアルことを認識できるように

想定外の例外が検出時の対応

どのアカウントで何が発生しているの....?

  • Lambda の CloudWatch Logs は厳しい
    • Lmabda が実行されたコンテナごとに別れている
  • そこでDatadog Logs
    • すべてのアカウント、プロジェクトのエログを集約
    • フィルタリングも爆速

たとえば、マイクロサービスを絞り込んだり、ファンクションで絞り込んだり、ステータスコードで絞り込んだり、レコードを選ぶと詳細が見られる。ここで、リクエストの内容やレスポンスの内容を埋め込んでいる。

ダッシュボードのメトリックからログに飛ぶことが可能。

  • API Error -> View related logs > タグで絞り込んだ状態のログを見られる

ログの取り込み方

TCPでつないで投げ続けるだけ

サービスマップ

X-Ray の100倍まし。

ノードを選択するとより細かい利用が見られる。

何がいいかというと、プラットフォーマーが提供しうるサービスとは異なり、クラウドをまたげる。 (が、サービスマップはサーバーレスからは利用できない、エージェントインストールが必要)

Q&A

インシデントがあったときに連動方法は?

異常はダッシュボードで確認。 ここからDynamoDB用など詳細のダッシュボードでわかるようになっている。 あとは、じょじょに上がっているのであればキャパシティ問題。 スパイクなら、異常が発生しているのかの確認。 スパイクを起こしているテーブルから、そのテーブルを使っている関数をたどる。

ダッシュボードドリブン + Slack での通知でハンドルしている。 異常 -> 正常化は、マニュアルでやっている(運用自動化はしていない)

キャパシティなどは、日常的に上がっているとき -> 日常的に改善が必要と認識。

Slack 通知 = 異常 = 人間が対処するしかないという認識。

インシデント管理

スクリーンボード 以外に、タイムボードでメモを残している。 あとは、 Confluence にメモ残している。(フルマネージドなので、クラウド障害じゃないと障害にナリにくいのでノウハウが溜まりにくい)

ちょっとインシデント管理厳しいですよねぇ。Datadogのメモはこういうの弱いので、Timeline に流して、自動的にesaにpostあたりがいいかなぁ。 GitHub Issueもインシデント管理にそこまで強くいないしなぁ。(悪い選択じゃないので、こっちでもいい)

Serverless Conf Tokyo 2018 に来ている記事4 : Acroquet Technology Session #ServerlessConf #serverlesstokyo

毎年参加しているServerless Conf Tokyoです。3回目になります。

昼を食べると眠くなるので、最近はランチを取らない様になってきました。サクッと集中してやって、さくっと、ね。

http://tokyo.serverlessconf.io/tokyo.serverlessconf.io

他のセッション

tech.guitarrapc.com

tech.guitarrapc.com

tech.guitarrapc.com

引用は私のコメントです。

目次

Title

サーバーレスなシステムの頑張らない運用監視 - Monitoring からObservabilityへ

Speaker

鈴木 貴典 @takanorig

資料

サーバーレスシステム開発バックグラウンド

AWS を利用している。 主にServerless Framework をつかっている。

サーバーレスシステムの運用監視の課題

サーバーレスはサーバーは見なくてもいいけど、アプリケーション監視としては変わってない、むしろモノリシックよりも大変。

  • サーバーはなくても、ファンクションやサービスの時状況は関しが必要
  • イベントドリブンなシステムは、どのようによびだされているか、どこで障害が発生しているのかトレースが大変
  • どれだけリソースを消費しているか、わかりにくいので最適化しにくい
違い メリット ・デメリット
従来 アプリ構築簡単、デバッグ、運用もわかりやすい 冗長化考慮必要、サーバー管理必要
サーバーレス 開発スピードUP、拡張性、冗長化は任せられる デバッグ難しい、システム細分化、分散化する

つまり、開発容易性、スピードは向上するけど、運用監視は複雑化する。

第一次監視 : CloudWatch + 人力デバッグ

デバッグ効率が悪い、原因特定、解決まで時間がかかる。 問題が発生しないと気づかない。 監視できていない内容も多い。

  • 監視自体のメンテナンスに手間がかかる
  • だんだんとダッシュボードなどをみなくなる

第二次監視 : CloudWatch Logs の内容から自動エラーチェック、X-Ray導入

CloudWatch Logs を使って、自前で監視アプリを作ってエラーチェックを開始した。 X-Ray でデバッグ構築や監視が向上。

from aws_xray_sdk.core import xray_recorder
from aws_xray_sdk.core import patch_all

patch_all()

X-Ray でサービスマップ、実行状況、トレース詳細がわかる。

実行状況では、処理時間のパーセンタイルやエラーの発生状況を確認できる。 トレース詳細では、処理ごとの時間が見える。

第三次監視 : Observability

重要なのは Observability = 可観測性

Monitoringの上位互換的に。 簡単にシステムの状態を把握したり、アプリケーションの動作を確認したりできること。 トレーシング(X-Ray)、メトリクス(CloudWatch)、ロギング(CloudWatch) を包括している。

  • CloudWatch Logs -> ロギング は、Log Streams が別れていて間作しにくいしきつい
  • Cloud Watch Metrics -> メトリクスは、Lambda 関数や DynamoDBのテーブル追加時に自分で追加する必要あって吊上
  • X-Ray : トレーシングは、とりあえず有効化しておけ

Distributed Systems Observability より

Logging / Metrics / Tracingがあっても、Observability ではない。

アラート化 + 見せるか

  • CloudWatch Logs に出力されるログを一定時間ごとにチェック
    • メトリクスフィルタは正規表現使えない、サブすくしプションでも都合が合わない
    • Lamnbda で横断的にチェック可能にした
  • 特定のキーワードを正規表現でチェックし、その内容を検出した際に、該当部分のログをSlackに通知
  • Slack には、Cloud Watch Logs へのリンクを設定をし、それをクリックしたらダイレクトにログの内容を確認できるようにしている
    • 問題発生箇所、前後の動きがわかるように

当然ですが、リンクはだいじ。

リソースの監視として、 Lamnbda の関数実行時間(制限の80%超えたら)、DynamoDBのキャパシティの消費量(キャパシティの80%超えたら)を見て通知かけている。

サービスの正常性確認として、異常障害以外に、サービス正常可能確認もしている。 テキストでわかりにくいものは、ヘッドレスブラウザを利用して画面キャプチャを通知。(Lambda でキャプチャとって数値)

Datadog の利用を検討してやろうとしている。 Lambndaは、関数増えても自動追加される。時間は絶対時間になる。 DynamoDBも、テーブル増えると自動追加されるし、キャパシティみれる。

どのようなツールを導入するにしても、対象となるサーバーレスシステムに対して、重要なのは、継続的に活用、拡張していくことが重要。

当然DataDog 使うんだけどなぁ.... 考え方は基本のキですね。やり方が時前になるとやっぱりびみょいなぁ。なんというか、自前でやる時点で、(開発し続けないと)継続性が落ちるので厳しい

改善事例

想定外に時間がかかる処理の早期検出

バッチ処理にLambda を利用。 安全のため、5分(Lambda の上限) していた。

処理のどこが時間かかっているか、Step Functions の実行詳細から時間を確認、X-Ray のトレース詳細でどの処理か確認↓。 結果、DynamoDBのTTLの設定質を取得しており、1テーブルあたり3病時間がかかっていた。 全テーブルの処理をしていたので、処理時間がかかっていた。

DataDog で気づけるじゃん.... APM 使えば... はないな、ここはX-Ray のほうがいい。

キャパシティの最適化

Lambda 実行時に DynamoDBからスキャンで複数件のデータを取得。 Redis を使うほどの高速性は不要、コストをかけたくなかった。

Scan はもちろんなるべく使わないほうがいい(特にサーバーレスはスケールするので危険が危ない)

どの程度キャパシティを設定するのか予想しにくい。そのくせ、キャパシティ釣果でデータが取得できなくなったてサービスへの影響が大きい。

正常時 : 10ms 異常時 : 159msかかる。アクセスが増えると処理時間はより長くなり、サービス障害につながる。

この状況からキャパシティの最適化をおこなった。

普通の監視では、処理時間に気づけ無いけど気づけた!

気づけ無い....だと.....

ついでに、同時実行数が多いとLambda の初期化(AWSの準備)に待ちが発生する。 関数の実行実行数を制限して、必要以上にリソースを消費されないように調整。

いいプラクティス。AWSが同時実行数多いと時間かかるのが悪いw

第四次監視 : IoT、機械学習

やりたい

まとめ

普通のアプリ監視と同じで、監視するだけじゃだめなので可視化、気づける化は重要ですねぇ。X-Ray 以外だと、StackDriver ですねぇ。AzureがInsightだけど微妙すぎる。