継続は力なり

タイトル通り定期的な更新を心掛けるブログです。

『Amazon Builder's Library』オンライン輪読会 第11回開催レポート

タダです.

Amazon Builder's Library」オンライン輪読会の第11回目を開催しましたのでレポートします.

開催経緯

開催の経緯は, kdnakt さんがまとめてくれています. kdnakt.hatenablog.com

第11回の記事

今回の輪読は,「シャッフルシャーディングを使ったワークロードの分離」を選びました.記事を読んで思考整理してから資料を作ったのですが,スムーズに資料を作れていいループだなと感じたので今後の輪読会でも生かしたいです.

輪読の記事 aws.amazon.com

輪読の内容整理記事 sadayoshi-tada.hatenablog.com

資料

所感

Route 53 の開発の話と DNS ホスティングサービスの課題である DDoS 対策としてシャッフルシャーディングに関する記事でした.

肝となるシャッフルシャーディングの仕組みを図解化してみましたが,シャッフルシャーディングの理解が誤っていたところを kdnakt さんに正してもらいました.ありがとうございました.仮想シャード(矢印)作って2ワーカー(サーバー)をユーザーごとに割り当てる図です.

f:id:sadayoshi_tada:20200420011112p:plain

また,記事にも紹介があった「route53-infima」も確認してみたところシャッフルシャーディングの解説と,シャッフルシャーディングには2種類あることがわかりました.確率的ハッシュ値を使ってシャードを割り当てる「SimpleSignatureShuffleSharder」とデータストアで割り当てたシャードを記録して重複しないようにする「StatefulSearchingShuffleSharder」です.シャッフルシャーディングも奥が深い... github.com

記事を通して改めて Route53 の裏側を知ると AWS がこれを実装できてしまうことがただただすごいと感じました.普段から使っているサービスの裏側を知れて個人的に面白い内容でした!

まとめ

シャッフルシャーディングを使ったワークロードの分離」輪読会のレポートでした.次回は「乗り越えられないキューバックログの回避」を読みます.担当は脱脂綿さんです.よろしくお願いします!

aws.amazon.com

過去の開催レポート

『The Amazon Builder's Library』オンライン輪読会 第1回開催レポート kdnakt.hatenablog.com

Amazon Builder's Library』オンライン輪読会 第3回開催レポート sadayoshi-tada.hatenablog.com

『The Amazon Builder's Library』オンライン輪読会 第5回開催レポート kdnakt.hatenablog.com

『The Amazon Builder's Library』オンライン輪読会 第7回開催レポート sadayoshi-tada.hatenablog.com

『Amazon Builder's Library』の『シャッフルシャーディングを使ったワークロードの分離』

タダです.

Amazon Builder's Library」のオンライン輪読会で今週のテーマが「シャッフルシャーディングを使ったワークロードの分離」という記事なので内容を理解するために記事の整理をします.

輪読の記事 aws.amazon.com

記事の整理

今回の記事で話題になっているのは Route53 という AWS のマネージド DNS サービスとサービスで使われている「シャッフルシャーディング」技術および採用の経緯が書かれていました.

記事の構成

  • はじめに
  • DNS ホスティングの対応開始
  • DDoS 攻撃への対処
  • シャッフルシャーディングとは?
  • Amazon Route53 とシャッフルシャーディング
  • まとめ

DDoS対策としてのシャッフルシャーディング

Amazon では DNS ホスティングがビジネス全体へ大きな影響と需要があることを認識しつつサービス開発にあたっていました.その中での最大の課題が DDoS 対策でした.DDoS 攻撃では DNS サーバーが標的になるため,攻撃(DNS フラッド攻撃)に対策が必要になります.

www.shadan-kun.com

開発チームは DDoS 対策で Route53 で行ったのは攻撃を受けているドメインの防御だけにサーバーリソースを制御するための方法を検討し,シャッフルシャーディングを採用しました.

シャッフルシャーディングについて

シャッフルシャーディングとは,サーバーでのトラフィック処理効率性を抑えるもののサーバーへの攻撃影響範囲を狭めるための技術です.例えば,8台のサーバーがあった際に,通常であれば8台のサーバーが全てのリクエストを処理することになります.これは効率や冗長性は取れた手法ですが,1つのサーバーが攻撃を受けた場合,数珠つなぎのように他のサーバーも攻撃を受けてダウンする恐れがあります.その影響を抑えるためにリクエストをさばくサーバーを分割(シャード)して,攻撃を抑制します.

8台のサーバーで例えば,1つのリクエストを2つのサーバーで捌くようにリソースを分割します.仮にそのうちの特定の2つのサーバーのみ攻撃を受けても他のサーバーは影響を受けません.また,特定のサーバーにしか攻撃を対象を隔離することで他のサーバーを利用しているユーザーにも影響を与えないようになります.これがシャッフルシャーディングの効果です.

Route53 のシャッフルシャーディング

それでは,Route53 のシャッフルシャーディングがどのように実装されているのでしょうか?Route 53 では、全 2048 の仮想ネームサーバーにサーバーリソースを振っています.各ユーザーのドメインは4つのネームサーバーが作られてこれらに対してシャッフルシャードされていくのですが,Route53 でドメインを作るたびに自動で生成されるネームサーバが4つある理由がわかりました.

Amazon Route 53 によって、ホストゾーンと同じ名前のネームサーバー (NS) レコードが自動的に作成されます。これには、ホストゾーンの 4 つの正式なネームサーバーがリストされます。このレコードに対して、ネームサーバーを追加、変更、または削除しないでください。

次の例は、Route 53 ネームサーバーの名前の形式を示してます (これらはサンプルとして提供されています。これらをレジストラのネームサーバーレコードを更新するときに使用しないでください)。

ns-2048.awsdns-64.com

ns-2049.awsdns-65.net

ns-2050.awsdns-66.org

ns-2051.awsdns-67.co.uk

ドキュメント

そして,シャッフルシャーディングによって DDoS 攻撃があっても特定のドメインにおけるネームサーバへのトラフィックが増えるものの,他のドメインは影響受けません.また,攻撃を受けているドメインへのサーバーリソースを足しつつ攻撃されている箇所を隔離することが可能です.更に,AWS Shield Standard を無料で利用者は自動で使っているためレイヤー3および4の攻撃を防御してくれています.AWS における DDoS 対策についてはホワイトペーパーにも記載があるため気になる方は参照しておこうと思います.

aws.amazon.com

aws.amazon.com

いずれにせよ,Route53 のシャッフルシャーディングによって利用者はたとえ DDoS 攻撃を受けていてもサービス利用が止まることなく操作できるようになっています.シャッフルシャーディングの実装部分は GitHub のソースコードが公開されています.

まとめ

シャッフルシャーディングを使ったワークロードの分離」の記事の内容整理をしました.シャッフルシャーディングの実装について確認しつつ資料を作っていきます!

『Amazon Builder's Library』の『ジッターを伴うタイムアウト、再試行、およびバックオフ』

タダです.

Amazon Builder's Library」のオンライン輪読会で今週のテーマが「ジッターを伴うタイムアウト、再試行、およびバックオフ」という記事なので内容を理解するために思考整理をします.

輪読の記事 aws.amazon.com

記事の整理

当然ですが,故障しないシステムはないから Amazon では障害可能性を許容してその可能性を削減する次の取組みが紹介されました.

タイムアウト

タイムアウトの課題は設定するタイムアウト値の選択することと言い,タイムアウトの設定が高過ぎればクライアントの待ち時間が増えるしリソース消費も増える,低すぎるとリクエスト回数が増えレイテンシーの増加して最終的にサーバーダウンにつながります.Amazon のあるシステムではデプロイ直後にサービスが起動するときに少数のリクエストアイムアウトが発生したが,リトライすればリクエストの成功が見受けられていました.当初はタイムアウト値が20ミリ秒以下だったが,タイムアウトの長さを伸ばしてタイムアウトの問題を回避しました.

リトライ

リトライはサーバー側の負荷を増やしてリクエストの成功可能性を上げるため,それによって障害発生したとしてもトレードオフの関係になると触れられています.しかし,リトライとそのサーバーへの過負荷は劇薬と例えられ,適切な量であれば問題ないがやりすぎると重大な損傷(障害)の可能性がある上,分散システムではクライアント側で適切なリトライ回数を調整する方法がほとんどないです.そこで,Amazon の推奨はバックオフを使うことです.

ただし,Amazon の見解はリトライは適切なトレードオフの関係を作れば良い方法とされており,リトライのリクエストのタイミングが誤らなければこの方法は高可用性を提供するソリューションとなります.

バックオフ

バックオフはリトライを積極的に行う代わりにクライアント側である程度の待ち時間を作ります.バックオフの一般的な例がエクスポネンシャル・バックオフでリトライごとに待機時間が急激に増加する特徴があります.AWS SDK でもエクスポネンシャル・バックオフの実装が紹介されています.

単純な再試行に加えて、各 AWS SDK は効果的なフロー制御を行うために、エクスポネンシャルバックオフアルゴリズムを実装します。エクスポネンシャルバックオフは、再試行間の待機時間を累進的に長くして、連続的なエラー応答を受信するという考えに基づいています。最大遅延間隔で最大回数の再試行を実行する必要があります。再試行の最大遅延間隔と最大回数は必ずしも固定値ではなく、実行する操作や局所的な要因 (ネットワークのレイテンシーなど) に基づいて設定する必要があります

AWS でのエラーの再試行とエクスポネンシャルバックオフ https://docs.aws.amazon.com/ja_jp/general/latest/gr/api-retries.html

ただ,バックオフも万能ではなく過負荷やリクエストの競合による障害が原因の場合は役立ちません.リクエストの失敗が同じ時間であった場合次のリトライのタイミングで再度競合や過負荷が発生するため,ジッターつまり待ち時間をランダムにしてリトライのタイミングを分散させます.

ジッター

追加するジッターの量と追加方法は下記のブログが参考になります.記事を見ると,バックオフ(エクスポネンシャル・バックオフ)によりリトライの頻度は減っているが競合しているためジッターを入れることで競合が減ってクライアント側の仕事量も減っていってます.

原文 aws.amazon.com

翻訳記事 aws.typepad.com

原文を要約して補足説明した記事 codezine.jp

ジッターは全てのタイマー,バッチ処理,その他のバックオフ処理に追加することを検討することで,サーバーの負荷が分散されるてダウンストリームサービスのワークロードに合わせた拡張をしやすくする効果があります.著者はサーバーへのスパイクアクセスに対する制御ないが,顧客体験に影響を与えない場所へのジッターを追加することを推奨しています.Amazon ではリトライに注意を向けることが大切であると学び,システムの依存関係について確認して適切なタイミングでリトライすれば負荷の増加を回避することができます.そしてリトライが可用性の改善に役立たない場合はリトライを停止することも辞さないと記載がありました.

まとめ

ジッターを伴うタイムアウト、再試行、およびバックオフ」の記事の内容整理をしました.今夜の輪読会も楽しみです!

pip install した時の SSL エラーが発生した場合の対応を整理した

タダです.

Mac のローカルで pip installしようとした時に SSL 関連のエラーの事象にあたりました.突然,pip installの実行ができなくなったため,この記事で対応方法を整理します.

事象の概要

boto3 を導入しようとしてみたところ,pip is configured with locations that require TLS/SSL, however the ssl module in Python is not available.と表示され,SSL のモジュールで利用できるものがないと表示されてコケました.

» pip install boto3                       
pip is configured with locations that require TLS/SSL, however the ssl module in Python is not available.
~中略~
Could not fetch URL https://pypi.org/simple/pip/: There was a problem confirming the ssl certificate: HTTPSConnectionPool(host='pypi.org', port=443): Max retries exceeded with url: /simple/pip/ (Caused by SSLError("Can't connect to HTTPS URL because the SSL module is not available.",)) - skipping

実行環境は次の通りです.

  • macOS Majave
  • Python 3.6.8
    • pyenv で導入したもの

結論

結論としては, Python と pip のバージョンを上げて対応しました.

エラー対応の時系列

OpenSSL 周りを再インストール

まず,SSL 関連のエラーがでたのでbrew reinstall opensslを実行して OpenSSL を入れ直しました.

» brew unlink openssl        
Unlinking /usr/local/Cellar/openssl@1.1/1.1.1f... 0 symlinks removed
» brew reinstall openssl
==> Reinstalling openssl@1.1 
==> Downloading https://homebrew.bintray.com/bottles/openssl@1.1-1.1.1f.mojave.bottle.tar.gz
Already downloaded: /XXX/XXX/Library/Caches/Homebrew/downloads/f46ab457fe1e0a3e8679dd2725494506e01504b448ace015cf5d5eee0c7307f0--openssl@1.1-1.1.1f.mojave.bottle.tar.gz
==> Pouring openssl@1.1-1.1.1f.mojave.bottle.tar.gz
==> Caveats
A CA file has been bootstrapped using certificates from the system
keychain. To add additional certificates, place .pem files in
  /usr/local/etc/openssl@1.1/certs

and run
  /usr/local/opt/openssl@1.1/bin/c_rehash

openssl@1.1 is keg-only, which means it was not symlinked into /usr/local,
because openssl/libressl is provided by macOS so don't link an incompatible version.

If you need to have openssl@1.1 first in your PATH run:
  echo 'export PATH="/usr/local/opt/openssl@1.1/bin:$PATH"' >> ~/.zshrc

For compilers to find openssl@1.1 you may need to set:
  export LDFLAGS="-L/usr/local/opt/openssl@1.1/lib"
  export CPPFLAGS="-I/usr/local/opt/openssl@1.1/include"

For pkg-config to find openssl@1.1 you may need to set:
  export PKG_CONFIG_PATH="/usr/local/opt/openssl@1.1/lib/pkgconfig"

==> Summary
🍺  /usr/local/Cellar/openssl@1.1/1.1.1f: 8,057 files, 18MB

再度,pip installしてみるも事象改善しないため次のアプローチを検討しました.

pip install boto3                                   
pip is configured with locations that require TLS/SSL, however the ssl module in Python is not available.
~中略~
pip is configured with locations that require TLS/SSL, however the ssl module in Python is not available.
Could not fetch URL https://pypi.org/simple/pip/: There was a problem confirming the ssl certificate: HTTPSConnectionPool(host='pypi.org', port=443): Max retries exceeded with url: /simple/pip/ (Caused by SSLError("Can't connect to HTTPS URL because the SSL module is not available.",)) - skipping

Python と pip のバージョンアップ

下記の issue を参考に Python が 3.6.8 だったところを 3.8 系に上げて,pip もバージョンアップしてみました.

github.com

» pyenv install --list
Available versions:
~中略~
3.8.0
~中略~
» pyenv install 3.8.0
python-build: use openssl@1.1 from homebrew
python-build: use readline from homebrew
Downloading Python-3.8.0.tar.xz...
-> https://www.python.org/ftp/python/3.8.0/Python-3.8.0.tar.xz
Installing Python-3.8.0...
python-build: use readline from homebrew
python-build: use zlib from xcode sdk
Installed Python-3.8.0 to /XXX/XXX/.pyenv/versions/3.8.0
» pyenv global 3.8.0
» curl -kL https://bootstrap.pypa.io/get-pip.py | python
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
100 1764k  100 1764k    0     0  1956k      0 --:--:-- --:--:-- --:--:-- 1954k
Collecting pip
  Downloading pip-20.0.2-py2.py3-none-any.whl (1.4 MB)
     |████████████████████████████████| 1.4 MB 3.0 MB/s
Collecting wheel
  Downloading wheel-0.34.2-py2.py3-none-any.whl (26 kB)
Installing collected packages: pip, wheel
  Attempting uninstall: pip
    Found existing installation: pip 19.2.3
    Uninstalling pip-19.2.3:
      Successfully uninstalled pip-19.2.3
Successfully installed pip-20.0.2 wheel-0.34.2

再度,pip install してみたらコケずに boto3 を導入できました.

» pip install boto3
Collecting boto3
  Downloading boto3-1.12.36-py2.py3-none-any.whl (128 kB)
     |████████████████████████████████| 128 kB 1.3 MB/s
Collecting s3transfer<0.4.0,>=0.3.0
  Using cached s3transfer-0.3.3-py2.py3-none-any.whl (69 kB)
Collecting jmespath<1.0.0,>=0.7.1
  Using cached jmespath-0.9.5-py2.py3-none-any.whl (24 kB)
Collecting botocore<1.16.0,>=1.15.36
  Downloading botocore-1.15.36-py2.py3-none-any.whl (6.1 MB)
     |████████████████████████████████| 6.1 MB 3.3 MB/s
Collecting urllib3<1.26,>=1.20; python_version != "3.4"
  Using cached urllib3-1.25.8-py2.py3-none-any.whl (125 kB)
Collecting docutils<0.16,>=0.10
  Using cached docutils-0.15.2-py3-none-any.whl (547 kB)
Collecting python-dateutil<3.0.0,>=2.1
  Using cached python_dateutil-2.8.1-py2.py3-none-any.whl (227 kB)
Collecting six>=1.5
  Using cached six-1.14.0-py2.py3-none-any.whl (10 kB)
Installing collected packages: urllib3, docutils, jmespath, six, python-dateutil, botocore, s3transfer, boto3
Successfully installed boto3-1.12.36 botocore-1.15.36 docutils-0.15.2 jmespath-0.9.5 python-dateutil-2.8.1 s3transfer-0.3.3 six-1.14.0 urllib3-1.25.8

まとめ

これまで動作していた pip installSSL エラーが発生したのでその対処をまとめました.突然のpip installが動作しなくなる事象は戸惑ったので同じ事象に遭遇したら,Python や pip のバージョンを見直してみるのは1つの手段してみると良いかもしれません.

Python でクラウドの構成図を作ろう!『Diagrams』でね

タダです.

皆さん,普段システムの構成図ってどうやって管理していますか?ExcelPowerPoint,専用のツールを使われていたり色々な方法で管理されているのですが,以前 PlantUML の形式で作図できる「AWS-PlantUML」を紹介させてもらいました.

sadayoshi-tada.hatenablog.com

今回も同じコードでの作図ですが Python で記述できるツールの「Diagrams」を紹介します.

github.com

Diagrams の概要

Diagrams」は Pythonクラウドサービスのアーキテクチャを作図するツールです.「Diagrams」では AWS のほか,Azure,GCP,Alibaba,Oracle Cloud のアイコンに対応しています.

diagrams.mingrammer.com

diagrams.mingrammer.com

diagrams.mingrammer.com

diagrams.mingrammer.com

diagrams.mingrammer.com

このツールのメリットは,コードで構成図を管理するため変更の履歴追跡が可能になることです.そして,何より手で矢印やリソースのグルーピングを細かに弄らなくてもいいところです!僕は手で作図をしていて図の重なりで細かな調整をするのが面倒だと思ってしまいますが,その手間が何行かのコードで解決できます.

Diagrams の導入

Diagrams」の導入は簡単です.pipであれば次のコマンドで導入できます.また,Graphviz も必要なので適宜インストールしてください.

pip install diagrams

diagrams.mingrammer.com

Diagrams での描画

Diagrams」でどれくらいのコード量で作図ができるかを実際に2つの例でみていきます.

Web3層構造

1つ目のパターンとして Web の3層構造を AWS で構成するコード例です.

コード例

from diagrams import Diagram, Cluster
from diagrams.aws.compute import AutoScaling,EC2
from diagrams.aws.network import ELB
from diagrams.aws.database import RDS

with Diagram("Scale-Out Computing", show=False):
    lb = ELB("LB")
    db = RDS("DB")
    with Cluster("Scaling Servers"):
        srv_group = [EC2("web01"),
                    EC2("web02"),
                    EC2("web03")]

    lb >> srv_group >> db

図を出力するためには次のようにコードを実行します.コードの実行が成功すると,コードと同じ階層に構成図がデフォルトですとpng形式で生成されます.なお,形式は,svg,jpg,pdfに対応しています.

python xxx.py

ELB で受けたトラフィックを3台までスケールする EC2 とデータを格納する RDS を表現してみました.10数行でこの絵を書けるのだから楽ですね.

f:id:sadayoshi_tada:20200331001349p:plain

サーバレスアーキテクチャ

2つ目の例としてサーバーレスアーキテクチャを作図してみます.題材として「実践 AWS CDK - TypeScript でインフラもアプリも!」で扱った感情分析システムのワークフローのコード例です.

sadayoshi-tada.hatenablog.com

コード例

from diagrams import Diagram, Cluster
from diagrams.onprem.client import User
from diagrams.aws.storage import S3
from diagrams.aws.integration import SF,SNS
from diagrams.aws.compute import Lambda
from diagrams.aws.ml import Comprehend
from diagrams.aws.compute import Compute

with Diagram("Osenchi Architecture", show=False):

    with Cluster("Osenchi WorkFlow"):
        with Cluster("State Machine"):
            wf =  SF("Step Functions")

        with Cluster("Send E-mail"):
            wf >> SNS("Email Topic") >> User("Client")

        with Cluster("Delete Object"):
            wf >> Lambda("Delete Objects Functions")>>S3("Input")

        with Cluster("Call DetectStatement API"):
            wf >> Lambda("Call Comprehend Functions") >> Comprehend("DetectStatement API") >> S3("Ouput")

    User("Client") >> S3("Input") >> wf

出力された図が次のものです. f:id:sadayoshi_tada:20200331001836p:plain

Clustesを使うことで関連処理のグループ化が可能です.ワークフローで呼び出す各処理を1つずつグループ化していくとワークフローの作図もできます.

diagrams.mingrammer.com

まとめ

Diagrams」いかがでしたでしょうか? Pythonに慣れていて手での作図にモヤモヤしている人に有用なツールと思います.主要なクラウドサービスだけでなく,オンプレミスのリソース表現もあります.AWS 観点で行くとアイコンも最新になっているし,構成図もコードで管理できれば履歴の管理もし易いと感じました.興味を持った人はぜひ「Diagrams」使ってみて欲しいです!