Kubernetes ネイティブなカオスエンジニアリングツール Chaos Mesh を使ってみる

Netflix が提唱した耐障害テスト技法 Chaos Engineering。実行環境に実際に障害を発生させてアプリケーションの復旧をテストする方法です。

Chaos Mesh は Kubernetes クラスターで稼働するアプリケーションをターゲットに Chaos Engineering テストを実行できるツールです。CNCF でホストされており、最近 v1.0 に到達しました。

chaos-mesh.org

以下のような障害発生の Experiment を実施できます。

  • PodChaos : Pod に定期的にエラーを発生させたり、Kill したりする
  • NetworkChaos : Pod のネットワークを遮断したり、遅延やロスを発生させる
  • StressChaos : Pod に負荷をかける
  • TimeChaos : 時刻取得のシステムコールを置き換えて時刻同期を狂わせる
  • IOChaos : IO エラーを発生させる
  • KernelChaos : Linux Kernel レベルのエラーを発生させる (デフォルトでは無効化されておりプロダクション環境での使用は禁止)

v1.0.1 現在、素の Pod への Chaos 注入はサポートされておらず、deployment, statefulset, daemonset が対象とのことです。

Docker Desktop for Mac の Kubernetes 環境で動かしてみました。

ドキュメント にしたがって、インストール*1

% curl -sSL https://mirrors.chaos-mesh.org/v1.0.1/web-show/deploy.sh | sh

Install Chaos Mesh chaos-mesh
   :
Waiting for pod running
Chaos Mesh chaos-mesh is installed successfully

無事デプロイされ、namespace chaos-testing に次のような Pod や Service が起動しました。

% kubectl -n chaos-testing get po,svc,deploy
NAME                                            READY   STATUS    RESTARTS   AGE
pod/chaos-controller-manager-86c96f985f-pvjcv   1/1     Running   0          11m
pod/chaos-daemon-9n9mb                          1/1     Running   0          11m
pod/chaos-dashboard-5d8dff7df9-5hp6h            1/1     Running   0          11m

NAME                                    TYPE        CLUSTER-IP       EXTERNAL-IP   PORT(S)                       AGE
service/chaos-dashboard                 NodePort    10.97.228.5      <none>        2333:31287/TCP                11m
service/chaos-mesh-controller-manager   ClusterIP   10.106.150.179   <none>        10081/TCP,10080/TCP,443/TCP   11m

NAME                                       READY   UP-TO-DATE   AVAILABLE   AGE
deployment.apps/chaos-controller-manager   1/1     1            1           11m
deployment.apps/chaos-dashboard            1/1     1            1           11m

次のような CRD (Custom Resource Definition) が適用されています。IO, Kernel, Network, Pod, Pod Network, Stress, Time などの Chaos type があるのがわかります。

% kubectl get crd
NAME                             CREATED AT
iochaos.chaos-mesh.org           2020-10-22T15:03:17Z
kernelchaos.chaos-mesh.org       2020-10-22T15:03:18Z
networkchaos.chaos-mesh.org      2020-10-22T15:03:18Z
podchaos.chaos-mesh.org          2020-10-22T15:03:18Z
podiochaos.chaos-mesh.org        2020-10-22T15:03:18Z
podnetworkchaos.chaos-mesh.org   2020-10-22T15:03:18Z
stresschaos.chaos-mesh.org       2020-10-22T15:03:18Z
timechaos.chaos-mesh.org         2020-10-22T15:03:18Z

Network chaos を引き起こすサンプルマニフェスト。NetworkChaos という CRD として適用され、10ms のレイテンシを web-show というラベルの Pod に 60秒毎に30秒の間発生させます。

apiVersion: chaos-mesh.org/v1alpha1
kind: NetworkChaos
metadata:
  name: web-show-network-delay
spec:
  action: delay # the specific chaos action to inject
  mode: one # the mode to run chaos action; supported modes are one/all/fixed/fixed-percent/random-max-percent
  selector: # pods where to inject chaos actions
    namespaces:
      - default
    labelSelectors:
      "app": "web-show"  # the label of the pod for chaos injection
  delay:
    latency: "10ms"
  duration: "30s" # duration for the injected chaos experiment
  scheduler: # scheduler rules for the running time of the chaos experiments about pods.
    cron: "@every 60s"

ターゲットとなる web-show アプリをデプロイ。これは、kube-system Pod に ping してレイテンシーを表示する React アプリです。

% curl -sSL https://mirrors.chaos-mesh.org/v1.0.1/web-show/deploy.sh | sh
service/web-show created
deployment.apps/web-show created
 :
Waiting for pod running

localhost:8081 に接続するとこんな感じで、レイテンシーの推移が表示されます。

f:id:kondoumh:20201023080812p:plain

この状態で先ほどの Network Chaos のサンプルを apply してみます。

% kubectl apply -f network-delay.yaml

Network Chaos の引き起こしたレイテンシが一定間隔で発生しているのが見て取れます。

f:id:kondoumh:20201023083219p:plain

Chaos Mesh のダッシュボードは Node Port で公開されているため port-forward して画面を表示します。

% kubectl port-forward -n chaos-testing svc/chaos-dashboard 2333:2333
Forwarding from 127.0.0.1:2333 -> 2333
Forwarding from [::1]:2333 -> 2333

localhost:2333 に接続するとダッシュボードが表示され、適用中の Experiment (この場合は Network Chaos) が確認できます。

f:id:kondoumh:20201023083729p:plain

タイムラインや詳細情報を閲覧できます。

f:id:kondoumh:20201023084221p:plain

f:id:kondoumh:20201023084243p:plain

このように Chaos Mesh はターゲットの Kubernetes アプリケーションに対して様々な障害を注入することで耐障害性をテストすることができます。ダッシュボードも見やすくて完成度が高い印象です。リリース前のシステムテストなどに組み込めば、アプリケーションのウィークポイントを発見したり、運用時の障害復旧のリハーサルにも活用できそうです。

*1:Helm でも導入可能です。

リモートワーク時代のスマホ活用 - Pixel + ThinkPad TrackPoint Keyboard

リモートワークになって、Pixel 3 XL の稼働率が如実に下がりました。外出しない日はほぼ電話を受けるだけなので、バッテリーもあまり減りません。

ところで、数ヶ月前に買った ThinkPad TrackPoint Keyboard 2

blog.kondoumh.com

最初は ThinkPad ファンとしてのノスタルジーもあって喜んで使ってたのですが、Ctrl キーが押しづらく長時間使ってると小指がつるようになり*1、結局 REALFORCE に回帰してしまいました。

サブマシンに iPad Pro + Trackpad + Magic Keyboard 使ってたのですが、奥さんが iPad Pro を再び使い始めたので TrackPoint Keyboard と Pixel 3 XL をペアリングしてみました。TrackPoint Keyboard 2 には Android 用のスイッチが用意されていて問題なく設定できました。

Nexus 6P を使ってた時に PC 用のキーボードを Bluetooth でペアリングできるデバイスを使って使ったりしてたので、なんとなく使用感はわかっていました。

blog.kondoumh.com

Pixel 3 XL 買った直後は Termux + 物理キーボードでコード書いたりしてたし。

blog.kondoumh.com

信頼できるデバイスに登録することで、指紋センサーに触らなくてもロック解除できます。TrackPoint がポインティングデバイスになるので画面にタッチせずに操作も可能。

Zoom 会議も ペアリングしてる完全ワイヤレスのヘッドセットでこなせてシンプルになりました*2。画面小さいけど YouTube もランドスケープ&スレテオで普通に見れますし YouTube Music も流しっぱなしでいけます。ということでしばらく Pixel 3 XL を仕事中のサブマシンとして使っていこうと思います。

f:id:kondoumh:20201012225541j:plain

*1:CapsLock ももちろん Ctrl キーに割り当ててました・・が、Ctrl キーは小指の肉球で押す派なので・・。

*2:会議中に電話がなるとプチパニックになってしまいますが

野良 Scrapbox アプリ - プロジェクトを選択してページ一覧を開く UI

野良 Scrapbox アプリのページ一覧は Scrapbox のプロジェクトページよりも素早く開いて見通しがいいのですが、開くには対象のプロジェクトのページを開いておく必要がありました。なので、まずプロジェクトのホームかプロジェクト内の任意のページを開いてからページ一覧を開くという2ステップが必要でした。また、複数プロジェクトのページを開いている場合はアクティブなタブのプロジェクトの一覧が開かれるという仕様にしているため、どのプロジェクトのページ一覧が開くのか直観的に分かりづらい問題がありました*1

そこで、プロジェクトのページを開くたびにプロジェクト名の履歴を残しておき、セレクトボックスから直接ページ一覧画面を開くことができる UI を追加しました。

favs や History と同じ感じのセレクトボックス。

f:id:kondoumh:20200924125227p:plain

一度開いたプロジェクトが列挙されてます。

f:id:kondoumh:20200924125246p:plain

選択したプロジェクトのページ一覧が表示されます。

f:id:kondoumh:20200924125301p:plain

ということで v2.0.0 リリース。

Release v2.0.0 · kondoumh/sbe · GitHub

*1:プロジェクトを1個だけ扱ってる場合はさほど気になりませんが。

GitHub CLI 1.0 がリリースされたので使ってみる

GitHub の CLI 1.0 がリリースされました。

github.blog

macOS だと brew でインストールできます。

% brew install gh
Updating Homebrew...
==> Auto-updated Homebrew!

==> Downloading https://homebrew.bintray.com/bottles/gh-1.0.0.catalina.bottle.ta
==> Downloading from https://d29vzk4ow07wi7.cloudfront.net/77b42bd6b610134ee3b40
  :
==> Summary
🍺  /usr/local/Cellar/gh/1.0.0: 60 files, 16.2MB

gh auth login で対話的に認証設定ができます。Personal Access Token を使って認証するようにしました。reporead:org へのアクセスを許可した Token を指定する必要があります。

% gh auth login
? What account do you want to log into? GitHub.com
- Logging into github.com
? How would you like to authenticate? Paste an authentication token

Tip: you can generate a Personal Access Token here https://github.com/settings/tokens
The minimum required scopes are 'repo' and 'read:org'.
? Paste your authentication token: ****************************************
? Choose default git protocol SSH
- gh config set -h github.com git_protocol ssh
✓ Configured git protocol
✓ Logged in as kondoumh

ドキュメントは以下。

cli.github.com

Core commands として gist, issue, pr, release, repo のサブコマンドが、Additional commands として上記の auth や config, help などの補助的なサブコマンドが提供されています。

CORE COMMANDS
  gist:       Create gists
  issue:      Manage issues
  pr:         Manage pull requests
  release:    Manage GitHub releases
  repo:       Create, clone, fork, and view repositories

ADDITIONAL COMMANDS
  alias:      Create command shortcuts
  api:        Make an authenticated GitHub API request
  auth:       Login, logout, and refresh your authentication
  completion: Generate shell completion scripts
  config:     Manage configuration for gh
  help:       Help about any command

ローカルに Clone したリポジトリのディレクトリに移動して、gh release を使うとリリース一覧 や個別のリリースの ChangeLog や Assets を見ることができます。

f:id:kondoumh:20200920190935p:plain

release listrelease view などの サブコマンドに --web (-w) フラグをつけると Web ブラウザで該当ページを開きます。

% gh release view v1.9.0 -w
Opening github.com/kondoumh/sbe/releases/tag/v1.9.0 in your browser.

repo サブコマンドでは、clone や create ができますし、repo view でテキストブラウザ的に Terminal で リポジトリの README を閲覧できます。

f:id:kondoumh:20200920194424p:plain

サブコマンドの使い方を調べるには gh help issue list のように help を挟めば usage がプリントされます。

% gh help issue list
List and filter issues in this repository

USAGE
  gh issue list [flags]

FLAGS
  -a, --assignee string    Filter by assignee
  -A, --author string      Filter by author
  -l, --label strings      Filter by labels
  -L, --limit int          Maximum number of issues to fetch (default 30)
      --mention string     Filter by mention
  -m, --milestone number   Filter by milestone number or `title`
  -s, --state string       Filter by state: {open|closed|all} (default "open")
  -w, --web                Open the browser to list the issue(s)

INHERITED FLAGS
      --help              Show help for command
  -R, --repo OWNER/REPO   Select another repository using the OWNER/REPO format

EXAMPLES
  $ gh issue list -l "help wanted"
  $ gh issue list -A monalisa
  $ gh issue list --web
  $ gh issue list --milestone 'MVP'

ここでは、list や view などの参照系コマンドだけしか示してませんが、issue や Release や PR などを create したり delete したりする更新系のコマンドも利用できます。GitHub のページで Chrome のタブがいっぱいになりがちなので、CLI と Web をうまく使い分けられると効率が上がりそうですし、自動化にも役立ちそうです。Actions のサブコマンドも提供されるとよいと思いました。

Additonal commands として api があります。GitHub API を最初から認証された状態で呼び出せます。

% gh api repos/kondoumh/sbe/releases

curl で呼び出すのに比べると https://api.github.com という固定の base url を省略できたり、認証トークンを ヘッダーに渡す手間が省けるのでこれも便利だと思います。

helmfile がステキになってた

helmfile は 複数の Helm Chart をまとめて Kubernetes cluster にデプロイするツールです。

github.com

Helm のラッパーとなっており、複数の Chart から構成されるアプリを効率よくデプロイ、更新できます。Helm Chart のインストール順というか依存関係の管理もできますし、デプロイ前後のフックでなにかの処理を実行したりすることも可能です。Helm と同様 Go Template が使えるので sed で置換したりが不要になります。

個人プロジェクトのようですが、開発は活発で contributer は 130人越えです。

Even though Helmfile is used in production environments across multiple organizations, it is still in its early stage of development, hence versioned 0.x.

とのことで 現在 v0.125.8。いいかげん v1.0 リリースしてもいい気ががします。

helmfile 便利なので自分も GitHub Actions で helmfile をセットアップする Action を作って公開してるほどです。

github.com

けっこう古いバージョンを使っていて最新を追ってなかったのですが、いつの間にか Helm Chart だけでなく Kustomize や Plain manifest のデプロイも対応してました(v0.118.0)。

Release v0.118.0: feat: GA of Kustomize and K8s manifests support (#1172) · roboll/helmfile · GitHub

Kustomize のアプリも plain manifest も local chart として扱えるので kubectl や kustomize コマンドを別途叩かなくてもよくなりました。

その少し前、namespace がなかったら作るという機能も追加されてました。

Release v0.113.0: Support for createNamespace (#1226) · roboll/helmfile · GitHub

デプロイ先の namespace は手順やシェルスクリプト内で別途作るので、作り忘れ、消し忘れが発生しやすい部分ですが、これで helmfile にお任せできるようになりました。

GitHub Actions が手動実行に対応してた

GitHub Actions にはずっと手動実行が提供されていなかったので repository_dispatch トリガーを使って GitHub API 経由で起動することでしのいでいました。この方法は Master ブランチにしか適用できないという制約がありました。

先月 workflow_dispatch という手動実行用のトリガー機能がリリースされてました。

github.blog

日本語ドキュメントへの反映はまだのようです。

https://docs.github.com/en/actions/reference/events-that-trigger-workflows#manual-events

トリガーとして workflow_dispatch を指定してワークフローを選択すると Run workflow というボタンが表示され手動実行が可能になります。repository_dispatch と違ってブランチを指定することができます。

on: 
  workflow_dispatch:

f:id:kondoumh:20200805170411p:plain

さらに Action を書く時に使用するメタデータ構文で、ワークフロー実行時の入力値を設定できます。

docs.github.com

docs.github.com

workflow_dispatch に inputs でログレベルやタグ名を指定するサンプルが紹介されています。

on: 
  workflow_dispatch:
    inputs:
      logLevel:
        description: 'Log level'     
        required: true
        default: 'warning'
      tags:
        description: 'Test scenario tags'

実行時に入力フォームが生成され、入力値を設定できます。この例では logLevel は必須で、デフォルト値として warning が設定されます。

f:id:kondoumh:20200805172713p:plain

ワークフローの job では入力値を github.event から取得でき、${{ github.event.inputs.logLevel }} のように取り出すことができます。

Jenkins のパラメータ付きビルドのように使えそうです。

  • テストケース番号を指定してテスト結果の成果物ファイル名に埋め込む
  • 他リポジトリのブランチ・タグを指定して checkout してテストする

などなど、いろいろと使い道が考えられます。

workflow_dispatch はGitHub API 経由で呼ぶことも可能です。Web UI と同様ブランチ指定する refinputs を POST パラメータで指定できます。

https://docs.github.com/en/rest/reference/actions#create-a-workflow-dispatch-event

Windows で VS Code Remote SSH を使う時のエラー対応

Windows 10 で VS Code の Remote SSH でリモートマシンへの接続が失敗すると Could not establish connection to "xx". というエラーダイアログが出ます。

f:id:kondoumh:20200805092020p:plain

エラーの要因はいろいろありますが、VS Code の出力に

[09:22:02.936] > Bad owner or permissions on C:\\Users\\kondoh/.ssh/config
> 
[09:22:02.946] > プロセスが、存在しないパイプに書き込もうとしました。

のように Bad owner or permissions on .../.ssh/config というメッセージが出る場合は config ファイルのパーミッションが問題があります。Remote SSH の Config File はデフォルトで %USERPROFILE%\.ssh\config になっていて、同ファイルのパーミッションが 400 になっていない場合にこのエラーになるようです。.ssh はプライベートキーが格納されるディレクトリなので config ファイルのパスを変更する方法で回避してみました*1

VS Code が提示してくる設定ファイル Remote-SSH:Open Configuration File.. の選択肢には、C:\ProgramData\ssh\ssh_config があります。

f:id:kondoumh:20200805090825p:plain

C:\ProgramData\ssh\ssh_config を選択するとパーミッションエラーでファイルが作成できません。C:\ProgramData 配下にファイルを作るのは管理者権限が必要です。

そこで C:\Users\<user>\.ssh\config で設定した内容を C:\ProgramData\ssh\ssh_config にコピーします*2。その後 C:\Users\<user>\.ssh\config は削除します*3

これで、無事に VS Code Remote SSH でリモートのプロジェクトを開いて作業できるようになりました。

別の方法として、Remote-SSH:Open Configuration File..Settings specify a custom configuration file で Config File のパスを設定する方法もあります。ユーザプロファイル配下に Config File を作れば、UAC の許可は不要です。

f:id:kondoumh:20200805090003p:plain

この他、

  • 踏み台サーバ経由で接続する場合 ProxyCommand にフルパスを指定する必要がある
  • SSL 証明書 (pem ファイル) を使用する場合、これもユーザプロファイル配下に配置しないと Permissions for 'xxx' are too open. のようなエラーになる

など、色々とハマりポイントがあります。

*1:Git for Windows を使ってるとパーミッションを変更するのがちょっと面倒そうなので。

*2:コピー時に Windows の UAC のダイアログが出るので OK する必要があります

*3:C:\Users\.ssh\config の優先度が高いらしく削除しないと冒頭のエラーが出ます。