gitkadoの気まぐれ日記

島根在住エンジニアが何かに興味を持ったらブログを更新します

色んな画像生成AIにスイカゲームの画像を書かせてみた

最近流行り?の「スイカゲーム」について生成AIで遊んでみました。
実は「スイカゲーム」がリリースされたのは 2年前の 2021/12/9 らしいです。
※ 本ブログ投稿日(2023/12/3)時点の情報を元に作成しています。

生成AIを使って画像生成のpromptを作成する

以下のWikiと公式サイトに記載されいてるスイカゲームに関する説明を元にPromptを作成する。

スイカゲーム - Wikipedia store-jp.nintendo.com

Input(ChatGPT4)

The following are pages describing a game called "Watermelon Game".
Based on this description, please generate a prompt to draw a picture of the game screen.
The generated prompts will be run on a separate service.

###pages
- https://store-jp.nintendo.com/list/software/70010000043363.html
- https://ja.m.wikipedia.org/wiki/スイカゲーム

Output

Based on the description of the "Watermelon Game" from the provided sources, here is a detailed prompt to create an image of the game screen:

"Imagine a vibrant and colorful game screen from a puzzle game called 'Watermelon Game', which combines elements of falling-block and merging gameplay. In the center of the screen, there's a box filled with a variety of fruits in different stages of merging, arranged in a visually appealing manner. The fruits include cherries, strawberries, grapes, dekopons, persimmons, apples, pears, peaches, pineapples, and melons, with the ultimate goal being to create the largest watermelon. The fruits are depicted using physics-based animations, suggesting they can roll and interact with each other. The game interface should be intuitive, showing scores and perhaps an indicator of the next fruit to drop. The background and overall aesthetic of the game are playful and engaging, appealing to a broad audience. Include subtle hints that the game has no time limit but requires thoughtful placement of the fruits."

各画像生成AIに同じpromptを投げてみる

DALLE3

openai.com

Input(ChatGPT4)

Please generate images based on the following description: "Imagine a vibrant and colorful game screen from a puzzle game called 'Watermelon Game', which combines elements of falling-block and merging gameplay. In the center of the screen, there's a box filled with a variety of fruits in different stages of merging, arranged in a visually appealing manner. The fruits include cherries, strawberries, grapes, dekopons, persimmons, apples, pears, peaches, pineapples, and melons, with the ultimate goal being to create the largest watermelon. The fruits are depicted using physics-based animations, suggesting they can roll and interact with each other. The game interface should be intuitive, showing scores and perhaps an indicator of the next fruit to drop. The background and overall aesthetic of the game are playful and engaging, appealing to a broad audience. Include subtle hints that the game has no time limit but requires thoughtful placement of the fruits."

Output

DALLE3

Youtubeとかの広告で出てきそうなタッチの絵。
フルーツたくさんでゲーム感はあるけど、どういうゲームなのか...

DALLE2

openai.com

Input(OpenAI API)

from langchain.utilities.dalle_image_generator import DallEAPIWrapper

dalle = DallEAPIWrapper() # model="dall-e-2"
image_url = dalle.run("Please generate images based on the following description: `Imagine a vibrant and colorful game screen from a puzzle game called 'Watermelon Game', which combines elements of falling-block and merging gameplay. In the center of the screen, there's a box filled with a variety of fruits in different stages of merging, arranged in a visually appealing manner. The fruits include cherries, strawberries, grapes, dekopons, persimmons, apples, pears, peaches, pineapples, and melons, with the ultimate goal being to create the largest watermelon. The fruits are depicted using physics-based animations, suggesting they can roll and interact with each other. The game interface should be intuitive, showing scores and perhaps an indicator of the next fruit to drop. The background and overall aesthetic of the game are playful and engaging, appealing to a broad audience. Include subtle hints that the game has no time limit but requires thoughtful placement of the fruits.`")

from google.colab.patches import cv2_imshow  # for image display
from skimage import io

image = io.imread(image_url)
cv2_imshow(image)

Output

DALLE2

ホラーな画像になった。DALLE2は全般こんな画像になるので、正直使い物にならない...

Stability AI SDXL 1.0

ja.stability.ai

Input(Amazon Bedrock)

Input_SDXL1.0

Output

SDXL1.0

ボンバーマン感あるのができた。
ゲームのタイトルが「スイカゲーム」であることは伝えておりスイカが出てくることもPromptに書いてるのに、スイカが無いのは攻めてるなと思った。
Promptに箱があるという表現を入れていたので、それを強く受け止めてくれたのかな?

Stability AI SDXL 0.8

Input(Amazon Bedrock)

Input_SDXL0.8

Output

SDXL0.8

絵のタッチは個人的に一番オシャレで好き。
パズルゲーム要素は何処へ

Amazon Titan Image Generator G1 Preview

aws.amazon.com

Input(Amazon Bedrock)

Input_Titan

Output

Titan

イカ・いちご・さくらんぼは分かるけど、他が色付きの丸というのは残念だった。
Promptの前半はしっかり読んでくれてるけど、後半(特にゲーム要素のあるスコアや次に落ちてくるフルーツ)のPromptが読まれてない?と思った。

料金

Amazonの料金ページ(日本語)がアップデートされてなくてクソ焦った。
SDXL1.0がプロビジョンドスループットしか記載なくて、月契約での請求と書いてあったので、その通りなら 5,446,596 JPY 請求されて終わるところだった。
実際はオンデマンド料金が存在していてImage単位で課金されるものなので 0.04 USD で済むはず。

まとめ

画像生成AIの選択肢も広がっており、どれも手を伸ばしたらスグに使えるところにある。
料金面ではTitanが安いし、遅れて出てきたモデルということもあってか精度もre:Inventの発表を見た感じだと良さそうだった。あと、DALLE2からDALLE3の進化が優秀すぎると感じました。

どの画像が「スイカゲーム」っぽいのかを知人に聞いてみた結果は以下のようになりました。

Titan > SDXL 1.0 >> DALLE3 > SDXL 0.8 >>>> DALLE2

ChatGPT Plus なので、DALLE3でもう少しPrompt工夫しながら、スイカゲーム作ってみます。

※ 今回は細かい特徴や機能比較まで行っていません。ご了承ください。

DockerComposeの起動順を制御する

開発環境でcompose.ymlを使用してると実行順を制御したくなることがある。
具体的にはDBコンテナよりAPIコンテナが先に起動するとmigrationなどがコケてつらい。

昔のワタシ

以下の公式ドキュメント(ja)にあるようにwait-for-xx.shを実行して制御していた。
※ サンプルの都合で昔はpostgresになっています

#!/bin/sh
# wait-for-postgres.sh

set -e

host="$1"
shift

until PGPASSWORD=$POSTGRES_PASSWORD psql -h "$host" -U "postgres" -c '\q'; do
  >&2 echo "Postgres is unavailable - sleeping"
  sleep 1
done

>&2 echo "Postgres is up - executing command"
exec "$@"
# compose.yml
version: "2"
services:
  web:
    build: .
    ports:
      - "80:8000"
    depends_on:
      - "db"
    command: ["./wait-for-postgres.sh", "db", "python", "app.py"]
  db:
    image: postgres

docs.docker.jp

最近のワタシ

healthcheckでDBコンテナのヘルスチェックを行ってからAPIコンテナが起動するようにdepends_onを設定しています。

# compose.yml
version: "3.9"
services:
  web:
    build: .
    ports:
      - "80:8000"
    depends_on:
      db:
        condition: service_healthy
    command: ["python", "app.py"]
  db:
    image: mysql
    environment:
      MYSQL_USER: myuser
      MYSQL_PASSWORD: mypassword
    healthcheck:
      test: mysqladmin ping -h 127.0.0.1 -u $$MYSQL_USER --password=$$MYSQL_PASSWORD
      start_period: 5s
      interval: 5s
      timeout: 5s
      retries: 55

docs.docker.com

メリット

  • ローカル固有の問題をcompose.yml内で完結できるのが良い(shell追加とか不要)
  • コンテナ間の依存関係がcompose.yml内で表現されているので分かりやすい
  • 起動順だけの話ならservice_healthy+healthcheckでなくservice_startedだけでいける

注意点

  • compose-specのversionが3.9である必要があります(2023/05/24時点の最新)
    • 試してないけど3.0 ~ 3.8ではdepends_onで使用するconditionが動作しなかったとか?

最後に

実は結構前から使えてたみたいだけど公式ドキュメント(ja)は更新されてない*1っぽくて気づけなかった。
Do not turn away from English documents!

*1:compose-specのversionが"2"ってのが何よりの証拠

【フロントエンド開発のためのテスト入門】読んだ備忘録

自分用に フロントエンド開発のためのテスト入門 を読んだ備忘録を残しておきます。
以下、自分が付箋をはってた箇所をピックアップします。

備忘録

2-4 テスト戦略モデル

テストピラミッドは有名で何度も聞いたことがあった。

アイスクリームコーン型・テストピラミッド型

今回紹介されていたのはテスティングトロフィー型というものだった。

  • Testing Libraryの開発者であるKent氏が提唱するテスト戦略モデルです。
    • 効率よくテストを書くよりも、正しくソフトウェアが動作することを保証することが大切
    • ユニットテストよりもインテグレーションテストを充実させよう!!
    • 単体でなく結合させてソフトウェアを提供するので、そこの品質を補償しなければならない。
      • 問題なくソフトウェアを提供できていれば単体にバグが潜んでても問題ない(暴論)

参考: コンポーネント思考のテスト方針(ブログ)

今の現場でもユニットテストより結合テストを大切にしていたが、何故そうしているのか説明できるようになった気がします。

第5章 UIコンポーネントテスト

ここで登場したのが Webアクセシビリティ(web-a11y) です。
ブラウザの支援技術を活用してシステムを使えるのか?というものですが、人生で1度も気にしたことがありませんでした。

  • testing-library でUIテストを実装できます。
    • 基本原則で「暗黙的なロール」も含めたクエリーを優先的に使用することを推奨しています。

参考: Testing Library Queries Priority

以下ではロール"button"を指定しているが、コンポーネント側では明示的に指定していない。

// https://github.com/frontend-testing-book/unittest/tree/main/src/05/03
test("ボタンの表示", () => {
  render(<Form name="taro" />);
  expect(screen.getByRole("button")).toBeInTheDocument();
});

ユーザ操作に近いシュミレートができる testing-library/user-event が特に良さそうだった。

//  https://github.com/frontend-testing-book/unittest/blob/main/src/05/05/InputAccount.test.tsx
import { render, screen } from "@testing-library/react";
import userEvent from "@testing-library/user-event";
import { InputAccount } from "./InputAccount";

const user = userEvent.setup();

test("メールアドレス入力欄", async () => {
  render(<InputAccount />);
  // 入力欄を取得
  const textbox = screen.getByRole("textbox", { name: "メールアドレス" });
  const value = "taro.tanaka@example.com";
  // 値を入力
  await user.type(textbox, value);
  // 検証
  expect(screen.getByDisplayValue(value)).toBeInTheDocument();
});

5-7 非同期処理を含むUIコンポーネントテスト

Arrange-Act-Assert(AAA)パターン

  • 準備・実行・検証の3パターンでテストコードを構成する書き方
  • 普段自分が意識している Given-When-Then と同じだと思う

参考

test("成功時「登録しました」が表示される", async () => {
  // Arrange(準備)
  const mockFn = mockPostMyAddress();
  render(<RegisterAddress />);
  // Act(実行)
  const submitValues = await fillValuesAndSubmit();
  // Assert(検証)
  expect(mockFn).toHaveBeenCalledWith(expect.objectContaining(submitValues));
  expect(screen.getByText("登録しました")).toBeInTheDocument();
});

6-2 カバレッジレポートの読み方

カバレッジが高いからといって品質の高いテストであるとは限らない

品質をカバレッジに頼りすぎるのはNGだが、以下をパトロールするには便利な指標になる。

  • テストは足りてるけどカバレッジが低い場合
    -> 不要な実装があるのでリファクタの余地あり
  • テスト足りてなくてカバレッジが低い場合
    -> テスト観点漏れ

第7章 Webアプリケーション結合テスト

インタラクション*1も関数で抽象化することで、UIコンポーネントのそうだが直感的に理解できる可読性の高いテストコードが書ける。

// https://github.com/frontend-testing-book/nextjs/blob/main/src/components/templates/MyPosts/Posts/Header/index.test.tsx
import { render, screen } from "@testing-library/react";
import userEvent from "@testing-library/user-event";
import mockRouter from "next-router-mock";
import { Header } from "./";

const user = userEvent.setup();

function setup(url = "/my/posts?page=1") {
  mockRouter.setCurrentUrl(url);
  render(<Header />);
  const combobox = screen.getByRole("combobox", { name: "公開ステータス" });
  // インタラクション関数
  async function selectOption(label: string) {
    await user.selectOptions(combobox, label);
  }
  return { combobox, selectOption };
}

test("公開ステータスを変更すると、status が変わる", async () => {
  const { selectOption } = setup();
  expect(mockRouter).toMatchObject({ query: { page: "1" } });
  await selectOption("公開");
  expect(mockRouter).toMatchObject({
    query: { page: "1", status: "public" },
  });
  await selectOption("下書き");
  expect(mockRouter).toMatchObject({
    query: { page: "1", status: "private" },
  });
});

第8章 UIコンポーネントエクスプローラ

Storybook

誤解

実際

  • 1コンポーネントでも条件や振る舞いを加味したら複数のStoryが存在する
  • 細かいコンポーネントの単位で実装/テストが可能になる
    • Pageに組み込まなくてもコンポーネント単体で確認ができるのは知らなかった
  • AtomicDesignの粒度が人によってマチマチになってる現場とかでは粒度を揃えるきっかけになりそう
  • 運用コストが気になるところだがテストで利用できるのでプラマイゼロくらいな印象
    • 以下が実装例だが、Givenに当たる部分をStoryで賄える
// https://github.com/frontend-testing-book/nextjs/blob/main/src/components/organisms/AlertDialog/index.test.tsx
import { composeStories } from "@storybook/testing-react";
import { render, screen } from "@testing-library/react";
import * as stories from "./index.stories";

const { Default, CustomButtonLabel, ExcludeCancel } = composeStories(stories);

describe("AlertDialog", () => {
  test("Default", () => {
    render(<Default />);
    expect(screen.getByRole("alertdialog")).toBeInTheDocument();
  });

  test("CustomButtonLabel", () => {
    render(<CustomButtonLabel />);
    expect(screen.getByRole("button", { name: "OK" })).toBeInTheDocument();
    expect(
      screen.getByRole("button", { name: "キャンセル" })
    ).toBeInTheDocument();
  });

  test("ExcludeCancel", () => {
    render(<ExcludeCancel />);
    expect(screen.getByRole("button", { name: "OK" })).toBeInTheDocument();
    expect(
      screen.queryByRole("button", { name: "CANCEL" })
    ).not.toBeInTheDocument();
  });
});

気になること

  • デザイナと共有できるというのはあまり納得いってない
    • 開発環境で見れるものという認識だからレビューで見せるくらいしか使えなさそう
  • コンポーネントフレームワーク(Vuetifyなど)使ってたら活躍の場が少ない?

第9章 ビジュアルリグレッションテスト

ビジュアルテスト

  • Jestでは検証できないブラウザを使った見え方のテスト
  • E2Eもブラウザを使ってるが目的が違う

実現方法

  • Storybookがあるとビジュアルテストを追加作業ほぼ無しで実現できる
    • storycapでStoryごとのキャプチャを取得
    • reg-cliで修正前後のキャプチャを比較してデグレを検知

著者のオンラインイベント

codezine.connpass.com

そこで聞いた耳寄り情報

作業メモ

とりまNuxt3のアプリケーションにStorybookをインストールしておきました。

$ npx sb init --type vue3 --builder vite
$ yarn storybook

*1:何らかのユーザ操作をトリガーにシステムがそれに応じた反応を起こすこと

快適な開発環境のために

こんにちは。松江市在住でエンジニアやってます。
普段はリモートでWEBアプリケーションを開発しています。

こちらは「山陰 Advent Calendar 2022 - Adventar」の4日目の記事です。

何を話すか

IT業界は便利なツールが毎日のように開発されています。
その中から快適な開発環境のために、購入して利用中のものを幾つか紹介します。
Mac専用のものが含まれます

1. JetBrains製IDE各種 [オススメ度 : ★★☆]

www.jetbrains.com

What is it ?

こんな人にオススメ

  • とりまJAVE/Kotlinの開発するなら買ってください。世界変わります
  • IntelliJVSCodeを併用してる人は使い勝手を統一できてUX最高です

マイナスポイント

  • 高いです。
  • All Products Packは10種類くらいIDEが付いてきますが実際は数種類しか使わないです
    • 私の場合はIntelliJを使わなくなったら単品でライセンス買ったほうが安くなります

¥38,148 JPY
※ 年間ライセンス...

2. 1Password [オススメ度 : ★★★]

1password.com

What is it ?

  • 様々なパスワードをコレ1つで管理できます(イメージ通り)
  • クレジット情報やライセンス、セキュアなメモなどパスワード以外も管理可能です
  • Mac,Windowsは勿論、ブラウザの拡張機能やモバイルアプリなど様々な箇所で使えます

こんな人にオススメ

  • パスワードを暗記したり適当なメモに残してる人、もっと楽しましょう
  • WEB開発のSTGやPROD環境でログイン情報が溢れている人は呪縛から開放されます

マイナスポイント

  • 買い切りもありましたがデバイス間で同期されないので、実質年間ライセンスを買う1択...

¥4,673 JPY ($39.47 USD)
※ 年間ライセンス...

3. Alfred [オススメ度 : ★★★]

www.alfredapp.com

What is it ?

  • Mac標準Spotlightの上位版みたいなものです
    • 例えば検索候補が過去に検索したものを優先してくれたりします
  • コピー履歴を残せるので直前のコピー以外もペーストできます(これが欲しくて買った)
  • 詳細は↑のリンク先見てください。色々機能あります

こんな人にオススメ

  • コピペのストレスを軽減したい人は試して見る価値あり

マイナスポイント

  • うーん、無い。買い切りは正義

¥7,896 JPY(£49.00 EUR
※ 買い切り!!

4. PixelSnap 2 [オススメ度 : ★☆☆]

getpixelsnap.com

What is it ?

こんな人にオススメ

  • Figmaに慣れてて実際のフロント開発でもついついサイズを測りたくなる人はググってみて
  • WireFrameに沿ったフロント実装が必要なら開発が楽になります

マイナスポイント

  • 私の場合は便利だけど利用頻度があまりなかった。
  • 割と高い。買い切りだから許せるけど...

¥6,227 JPY($42.90 USD)
※ 買い切り!!

最後に

気になるものはありましたか?
きっと普段の開発をより良くしてくれるので是非ご検討ください。
ただし一度買ってしまったら戻れない体になるので、自己責任でお願いします。

総額 ¥56,944 JPY

Auth0でIP制限を実現しようとしたが断念した話

特定グローバルIP(以下、GIP)からのリクエストのみ許可する機能(以下、IP制限)を実装する必要があった。
認証プラットフォームとしてAuth0を使用しているので、以下のように実装してみた。

f:id:gitkado:20211114133251p:plain

どうやってAuth0のログイン後に処理を追加するのか

少し調べてみるとAuth0 Rules機能を使ってる記事が結構ヒットしたので、とりあえず公式ドキュメントを確認してみた。

auth0.com

公式ドキュメントの冒頭に、If you want to extend Auth0, we highly recommend you use Actions, which are a cornerstone of our overall extensibility product. とあったので、Auth0 Actionsを使うことにした。

auth0.com

Auth0 Actions

簡単に説明すると、Auth0の特定タイミングで実行される関数をNode.jsで実装できる。
AWS Lambdaのようなイメージだと思ってもらえれば良いかなと。
2021/11/14時点だと、以下のタイミングで実行させることができる。

f:id:gitkado:20211114134434p:plain

触ってみる

Step1: Auth0に関数を追加する

右上の「Build Custom」から作成していきます。 f:id:gitkado:20211114135357p:plain

関数名とか入力するモーダルが表示されるので適当に入力してCreateする。 f:id:gitkado:20211114135646p:plain

雛形が作成されるので、ここに関数を実装して右上の「Deploy」を叩けば作成できる。
使用できるオブジェクトはeventapiで2種類ある。 f:id:gitkado:20211114135807p:plain

auth0.com

exports.onExecutePostLogin = async (event, api) => {
  // 解説1
  if (event.client.client_id === "hogefugabuzz") {
    // 解説2
    if (event.request.ip !== "xxx.xxx.xxx.xxx") {
      api.access.deny(`Access to ${event.client.name} from ${event.request.ip} is not allowed.`)
    }
    // 解説3
    api.idToken.setCustomClaim('allowed-ip', event.request.ip)
  }
};
  • 解説1 event.client.client_id === "hogefugabuzz"
    • Auth0は複数Applicationから共通で使用される認証プラットフォーム
    • 特定Applicationのみ関数を実行する場合は、関数側で制御するする必要がある
  • 解説2 event.request.ip === "xxx.xxx.xxx.xxx"
    • リクエスト元のGIPを取得して許可されたIPであることを確認する
  • 解説3
    • 発行されるJWTに許可されたGIPを追加する

Step2: 作成した関数をログイン処理に追加する

今回はLoginに対して処理を追加したいので、Choose FlowでLoginをクリックする。
すると、ログインしてからJWTを発行するまでのフローが表示された。

f:id:gitkado:20211114134925p:plain

Add Actionから先程作成した関数をDrag&DropしてApplyするだけでOK!! f:id:gitkado:20211114143242g:plain

断念した理由

ここまで見ると順調に見えると思います。私もそう思ってました。
実際に動かしてみると、どうもうまくいきません。

デバッグしていくと... event.request.ipで取得するIPアドレスIPv6になってる!?!?!?!?!?!?
IPv4で制限をかけたいという要望だったのですが、どうやらv4とv6が混在するみたいです。

(以下、参考記事)
Context.Request.IP returns IPv6 address lately - #2 by john.gateley - Auth0 Community
In Rules, ipv6 IP address comes [sorry, resend] - #10 by tanver.hasan - Auth0 Community

最終的にどうしたか

Auth0で実現するのは断念して、アプリケーション側かEKS使ってるのでIstioでなんとか実現できないか再検討しています。
IPv6がこんな身近に迫ってきてるんだなというのを感じるいい機会でした。
皆さんもIP制限を実現しなければいけない時には、しっかり検証しておくことをオススメします。


クラメソさんの記事があったので、IP制限を検証するところまではスムーズに進みましたmm
Auth0のActionsでログイン時のIPアドレスを制限してみた | DevelopersIO

AWS Fault Injection Simulator (FIS) 触ってきた

はじめに

これで安全なアプリケーションになった!と思っていたが悲劇は起きた。

AWSのDynamoDBに障害が発生した

障害内容

この障害によりDynamoDBを始めとする20以上のAWSサービスが6時間以上の間使用できなくなりました。 社内システムなら5時間止まってもなんとかなるかもしれないが、SaaSとして事業を展開している企業にとっての5時間は想像以上にダメージが大きいと思います。

AWS DynamoDB障害 に関する詳細

その時のNetflix

Netflixもこの大規模障害の影響を受けたものの、このようなリージョン単位の大規模障害に備えていたことから、重大な事態には至りませんでした。 Netflixでは常に障害発生ツールを使って障害対応の経験を積みアプリケーションを改善しています。これらをNetflixでは「ChaosEngineering」と呼んでいます。

AWS大規模障害を乗り越えたNetflixが語る「障害発生ツールは変化に対応できる勇気を与えてくれる」

What's ChaosEngineering

  • ツールを使ってシステムに障害を注入する
    • 障害: フェイルオーバーや特定インスタンスの謎の死など
    • 障害注入は目的ではなく『手段』
  • 『目的』はシステムの弱点を見つけて改善すること
    • システムの安定性と回復力を強化する

起源は2011年にNetflixが開発したChaosMonkeyだと言われています。 Netflixを中心としたコミュニティがカオスエンジニアリングの原則を提唱しています。

なぜ最近よく聞くようになってきたのか

昨今、集中システム(モノリス)から分散システム(マイクロサービス)にトレンドが変わってきています。 マイクロサービスは「システムは落ちる」という前提でシステムを設計しているので、実際にシステムが落ちた時に影響を最小限に抑える必要があります。

モノリス マイクロサービス
特徴 全ての機能が1サーバに集中している 機能ごとにサービスを分ける
障害点 少ない(特定可能) 多い(特定困難)
求められる品質 落ちない 落ちても自動回復

カオスエンジニアリングを行い、障害を早期に発見して被害を最小限に抑えることで、本番環境での障害発生に備えることができます。

Qiita: カオスエンジニアリングと聞いてカオスになった人必見

カオスエンジニアリングの基本原則

  1. 通常の動作を示すシステムの測定可能な出力として「定常状態」を定義することから始めます
    • 定常状態はCPU使用率が〜。ではなくエラー率が〜%。のようにビジネスに直結する内容が良い
  2. この定常状態は、対照群および実験群の両方で継続すると仮定します
  3. サーバーのクラッシュ、ハードドライブの誤作動、ネットワーク接続の切断など、現実世界のイベントを反映する変数を導入します
  4. 対照群と実験群との間の定常状態の違いを調べることによって仮説を反証しようとします

【引用: カオスエンジニアリングの原則(検証におけるカオス)

忘れられがちですが、可観測性がとても重要です。(要は定常状態の確認方法がしっかりしてること) 障害注入しても何が起きているか見えないのなら、改善につなげることはできず、ただカオスなだけになります。

要約するとこんな感じでしょうか。

「正常状態を可視化(モニタリングなど)して特定の障害注入を行った時に正常状態のままであるかを確認する。

詳細原則

  • 定常状態における振る舞いの仮説を立てる
    • システムが落ちると分かっててやるのはカオスなだけ
  • 実世界の事象は多様である
  • 本番環境で検証を実行する
  • 継続的に実行する検証の自動化
  • 影響範囲を局所化する
    • 仮にシステムが落ちた場合に復旧させる必要があるため

【引用: カオスエンジニアリングの原則(詳細な原則)

What's FIS

AWSリソースに対して障害注入を行いシステムの振る舞いを検証します。 エージェントレスで使えるので既に稼働中のシステムにも導入しやすいです。

AWS Fault Injection Simulator

実験テンプレート

実験の設計図です。これには、実験のアクション、ターゲット、および停止条件が含まれます。実験テンプレートを作成したら、それを使用して実験を実行できます。【引用: AWS FIS の概念

アクション

  • 注入する障害を定義する
  • 注入する期間を定義する
  • 複数ある場合は順次または並行を定義できる

ターゲット

  • アクションを実行する対象のAWSリソースを指定する
  • 特定の条件に基づいてAWSリソースを選択することも可能

停止条件

  • Amazon CloudWatch アラームとして閾値を定義する
    • アラームが発火した場合に実験を停止する

サポートしてるAWSリソース

2021/05/13時点では4種類+α(割愛)ですが今後増やしていく方針です

AWS FIS アクションのリファレンス

実際にハンズオンで触ってきた

「EC2に対してFISを試してみる」という内容でした。
後半ではAutoScalingがちゃんと動くかを確認するための実験を行いました。


まず、ターゲット(今回はEC2インスタンス)を選択します。
特定の条件に合致するインスタンスを一定割合選択することもできます。

f:id:gitkado:20210515133956p:plain

f:id:gitkado:20210515135228p:plain

どんな障害(アクションタイプ)を発生させるかはこんな感じで設定します。

f:id:gitkado:20210515134255p:plain

停止条件が登録されてないと確認画面が挟まります。
ハンズオンでは登録しませんでしたが、実際に本番環境で試すなら絶対設定しましょう!

f:id:gitkado:20210515134510p:plain

実験テンプレート登録完了!

f:id:gitkado:20210515134542p:plain


さぁ、実験を開始してみましょう。
本番を攻撃することになるのでココでも確認画面が挟まっています。

f:id:gitkado:20210515135255p:plain

f:id:gitkado:20210515135450p:plain

↑実験前(インスタンス起動してる)
↓実験開始(インスタンス停止)※ 1分後に復旧しました

f:id:gitkado:20210515135519p:plain


f:id:gitkado:20210515141157p:plain

↑片方はAutoScalingを設定している状態で両方のインスタンスをTerminatedします。
↓AutoScalingが設定されているインスタンスは自動で復旧しました。

f:id:gitkado:20210515141331p:plain

github.com

感想

事前に調べてから臨んだハンズオンだったので手を動かしながら知識の確認ができてて良かった。これからもやる
実際の現場に取り入れることができるのはいつになるか分からないが、その日のために未知の技術を体験して仕入れることができたのは非常に大切だと思いました。 現在はFISがサポートしているサービスは多くありませんが、今後増えていくと公言されているので楽しみです!
こんな怖いことを本番環境で実行している会社があると思うと.....色々な意味を込めて「スゴイ」の一言です。


参考にさせていただきました

CloudFront Functionsがリリースされました!

CDN

CDNとは、「コンテンツデリバリーネットワーク」(Content Delivery Network) の略で、世界中に張り巡らされた配信ネットワークを利用して、Webサイトにアクセスしようとするユーザーに効率的かつ高速にWebコンテンツを配信するしくみです。【転載】

【CDNとは?】初心者にもわかりやすく解説 | WafCharm(ワフチャーム) - AIによるAWS / Azure WAFのルール自動運用サービス

CloudFront

AWSが提供しているCDNサービス

ユーザーへの静的および動的なウェブコンテンツ (.html、.css、.js、イメージファイルなど) の配信を高速化するウェブサービスです。CloudFront では、エッジロケーションというデータセンターの世界的ネットワークを経由してコンテンツを配信します。【転載】

f:id:gitkado:20210505133236p:plain

Amazon CloudFront とは何ですか? - Amazon CloudFront 特徴 - Amazon CloudFront | AWS

ユースケース

  • OriginへのアクセスをEdgeでキャッシュする
  • Origin負荷が減り、Userに近いEdgeから応答できる

f:id:gitkado:20210505133304p:plain

Lambda@Edge

  • CloudFrontの機能の1つ
  • CloudFrontの前後にLambda処理を入れ込める

f:id:gitkado:20210505133551p:plain Lambda@Edge | AWS aws.amazon.com

ユースケース

  • 画像(S3) へのアクセス可否をLambdaで検証する
  • 認可処理なのでViewerRequestを使用する

f:id:gitkado:20210505133642p:plain

CloudFront Functions

  • 2021年5月3日にサービスイン
  • Lambda@Edgeより手前で関数を爆速で実行できる

f:id:gitkado:20210505133840p:plain

  • Lambda@EdgeはRegionalEdgeCaches 上で実行される
    • EdgeLocationsは使われていなかった

f:id:gitkado:20210505133853p:plain f:id:gitkado:20210505134007p:plain

aws.amazon.com

特徴

  • ユーザに近いEdgeLocationsで実行され早い
  • 10KB以下のJSファイル内で完結させることができる処理しかできない
  • ネットワークアクセスできないので認可処理のようなことは難しいのかも
  • 当たり前だがLambdaではない

f:id:gitkado:20210505134110p:plain f:id:gitkado:20210505134156p:plain CDN Pricing | Free Tier Eligible, Pay-as-you-go | Amazon CloudFront

まとめ

  • AWS上で完結させるにはLambda@Edgeしか選択肢がなかった部分に新しい選択肢が増えたのは面白いなと思いました。
  • CloudFront Functionsの方がコスパ良い&爆速処理なので採用できる場面では積極的に試してみても良いのかなと思いました。
  • クラメソさんのブログ更新が早すぎました。(いつもお世話になってます)

dev.classmethod.jp