とんちゃんといっしょ

Cloudに関する技術とか日常とかについて書いたり書かなかったり

kube-monkey を調べてみた

Chaos Engineeringに興味があっていろいろ調べているのでメモ。

Chaos EngineeringといえばNetflixのChaosmonkeyが有名である。

github.com

先にこちらを試していたのだが、Spinnakerとの連携が必要となる。 まあそれは別にいいのだが公式にはKubernetes への対応も謳っているものの実際は動かないケースが見られた(後日記載予定)ので別のものを試すことにした。

というわけで今回は kube-monkey を見てみた。

github.com

なおこの記事を書いているときの kube-monkey のバージョンは v0.3.0 である

kube-monkeyはk8sのCluster内のPodをランダムに削除することでシステムの対障害性や回復性を確認するためのツールである。

できること

READMEに書いてあるのを眺めると

  • kube-monkeyのオンオフ
  • 起動時間の設定(デフォルトは平日8時)
  • 動作時間の設定(デフォルトは平日10時〜16時)
  • 動作する回数(例として 3 と設定すると週の平日日勤帯に3回動作する)
  • 特定の(ラベルがついた)アプリだけを削除対象にする
  • kill-mode: Podの落とし方を設定
    • 全Podを落とす
    • 指定数のPodを落とす
    • n%以内のPodを落とす
    • 指定数の n%以内のPodを落とす
  • kill-value: kill-modeで利用する値を設定する
  • namespace単位でのblacklist(削除しないリスト)登録
  • (READMEには書いてないけど)namespace単位でのwhitelist登録

できないこと

  • 動作する日や曜日の設定(平日固定っぽい?)
  • TBD

動作

ドキュメントによると

  • 1日1回スケジューリングを行い削除するPodをランダム決める(もしくは削除しないことを決める)
  • 削除対象のPodの削除時間をランダムに決める
  • 削除方法を決める
  • 削除の時間に指定された索条方法でPodを削除する

らしい

動かしてみた

namespaceの作成

READMEは kube-system においているが本当だとよくなさそうなので namespace を別に作る

$ kubectl create namespace kube-monkey
namespace/kube-monkey created

設定

READMEを読むと設定は以下の3つからできるらしい

今回はconfig.tomlを書いてconfigmapに登録してみる

[kubemonkey]
dry_run = false                          # Terminations are only logged
run_hour = 8                             # Run scheduling at 8am on weekdays
start_hour = 9                           # Don't schedule any pod deaths before 10am
end_hour = 17                            # Don't schedule any pod deaths after 4pm
blacklisted_namespaces = ["kube-system"] # Critical apps live here
whitelisted_namespaces = ["default"]
time_zone = "Asia/Tokyo"           # Set tzdata timezone example. Note the field is time_zone not timezone

# Add debug parameters
[debug]
enabled= true
schedule_immediate_kill= true

scheduleがなかなか割当らないのでデバッグをオンにした。 (オンにすると30秒ごとにスケジューリングが行われる模様)

$ kubectl create configmap kube-monkey-config-map --from-file=config.toml -n kube-monkey

READMEはnamespaceを指定していなかったので default に作られてしまいハマった・・・

Service Accountの作成と権限設定

これもREADMEには書いてないけどないとダメそうなので作って設定しておく。

apiVersion: v1
kind: ServiceAccount
metadata:
 name: kube-monkey
 namespace: kube-monkey
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
  name: kube-monkey-role-binding
roleRef:
  apiGroup: rbac.authorization.k8s.io
  kind: ClusterRole
  name: cluster-admin
subjects:
- namespace: kube-monkey
  kind: ServiceAccount
  name: kube-monkey
$ kubectl create -f rbac.yml
serviceaccount/kube-monkey created

kube-monkeyのデプロイ

---
  apiVersion: apps/v1
  kind: Deployment
  metadata:
    name: kube-monkey
    namespace: kube-monkey
  spec:
    replicas: 1
    selector:
      matchLabels:
        app: kube-monkey
    template:
      metadata:
        labels:
          app: kube-monkey
      spec:
        containers:
          -  name: kube-monkey
             command:
               - "/kube-monkey"
             args: ["-v=4", "-log_dir=/var/log/kube-monkey"]
             image: ayushsobti/kube-monkey:v0.3.0
             volumeMounts:
               - name: config-volume
                 mountPath: "/etc/kube-monkey"
        serviceAccountName: kube-monkey
        volumes:
          - name: config-volume
            configMap:
              name: kube-monkey-config-map
  • apiVersionはREADMEのやつは古いので apps/v1 に変更
  • spec.selector のあたりはSpinnakerを使ったデプロイで必要だったので追加
  • argsに -v4デバッグレベルのログを出力するように変更

f:id:mazinlabs:20190328102014p:plain
kube-monkey のデプロイ

アプリケーションのデプロイ

nginxをデプロイしてみる

apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx
  namespace: default
  labels:
    app: nginx
    kube-monkey/enabled: enabled
    kube-monkey/identifier: nginx
    kube-monkey/mtbf: '10'
    kube-monkey/kill-mode: "fixed"
    kube-monkey/kill-value: '1'
spec:
  replicas: 2
  selector:
    matchLabels:
      app: nginx
  template:
    metadata:
      labels:
        app: nginx
        kube-monkey/enabled: enabled
        kube-monkey/identifier: nginx
        kube-monkey/mtbf: '10'
        kube-monkey/kill-mode: "fixed"
        kube-monkey/kill-value: '1'
    spec:
      containers:
        - image: nginx
          name: nginx
          ports:
            - containerPort: 80
  • kube-monkey/mtbf はWeekdayのうちn 回故障するというものなので多めに設定

動作確認

$ kubectl logs -n kube-monkey kube-monkey-7fff7ff466-68xlb
I0401 06:33:51.282396       1 kubemonkey.go:62] Status Update: Waiting to run scheduled terminations.
I0401 06:33:51.282515       1 kubemonkey.go:76] Status Update: All terminations done.
I0401 06:33:51.282824       1 kubemonkey.go:19] Debug mode detected!
I0401 06:33:51.282966       1 kubemonkey.go:20] Status Update: Generating next schedule in 30 sec
I0401 06:34:21.283392       1 schedule.go:64] Status Update: Generating schedule for terminations
I0401 06:34:21.305535       1 schedule.go:57] Status Update: 1 terminations scheduled today
I0401 06:34:21.305890       1 schedule.go:59] v1.Deployment nginx scheduled for termination at 04/01/2019 15:34:26 +0900 JST
    ********** Today's schedule **********
    k8 Api Kind    Kind Name        Termination Time
    -----------    ---------        ----------------
    v1.Deployment    nginx        04/01/2019 15:34:26 +0900 JST
    ********** End of schedule **********
I0401 06:34:21.306260       1 kubemonkey.go:62] Status Update: Waiting to run scheduled terminations.
I0401 06:34:26.339117       1 kubemonkey.go:70] Termination successfully executed for v1.Deployment nginx
I0401 06:34:26.339166       1 kubemonkey.go:73] Status Update: 0 scheduled terminations left.
I0401 06:34:26.339189       1 kubemonkey.go:76] Status Update: All terminations done.
I0401 06:34:26.339287       1 kubemonkey.go:19] Debug mode detected!
I0401 06:34:26.339293       1 kubemonkey.go:20] Status Update: Generating next schedule in 30 sec
I0401 06:34:56.339917       1 schedule.go:64] Status Update: Generating schedule for terminations
I0401 06:34:56.663981       1 schedule.go:57] Status Update: 0 terminations scheduled today

無事にScheduleとTerminateされたことが確認できた。

結果

kube-monkeyは動く。(これ大事)

小ネタ

  • run_hour > start_hour にするとErrorになってコンテナが立ち上がらない
  • kube-monkey/mtbf を小さめに設定しているとまったくスケジューリングされず動作がわからないのでデバッグのときは大きめに設定するとよいかも

AmazonでLycamobileのSIMを買ってトラブった話

家族旅行でアメリカに行くのでモバイルWi-Fiを借りようかという話にもなっていたのだが、 1日だけ夫婦別々に行動する可能性があったのでSIMを試してみようとAmazonで以下のSIMを発注。

日本国内でLycamobile公式サイトでの5つの項目を入力するだけでアクティベーション(番号発行)可能です。※日本時間の昼間アクティベーションはメンテナンス時間の可能性がございます。

Amazonのページには上記のように書いてあったので行く前にActivateすればいいやと思い旅行前日の夜に届いたSIMをアクティベーションしようとしたところ Invalid ICCID と表示されてしまいできない。

f:id:mazinlabs:20190325171056p:plain
Invalid ICCIDの画面

サポートに連絡をしてみたところ

  • SIMが認識されるか → される
  • Invalid ICCIDの画面をくれ → 上記のやつを渡す
  • 該当のICCIDのSIMはないと言われSIMカードの背面のシリアルコードの写真を要求される → 渡す
  • Amazonの注文番号をきかれる → 渡す
  • 画面キャプチャで送ったSIMの記録はないけどその番号はあるしPUKコードも正しい画面のようにアクティベーションできるはずと言う謎のメールが送られてくる → 画面に思いっきり Invalid ICCIDってでて事を指摘 → 間違いを認める
  • simカード番号は既にアクティベートされた可能性があるといわれる → 確認してもらう

翌日も家を出る前まで試してみたがアクティベーションできないので仕方がなく空港でモバイルWi-Fiをレンタルして渡米。 到着後モバイルWi-Fiをつなぐとアメリカ到着2時間前にメールが返ってきていて

We already active it sussessfully for you.

Sim 8919…xxxx.  

Sim 8919… yyyy.

Have a nice trip

"Have a nice trip" じゃねえよ!

ここから返金できないかの交渉を英語で始めるもののアクティベーションしたから無理とのこと。 まぁ、こちらも渡米する前に返金の依頼をしていないこともあったのでぐぬぬと思いながら諦める。しかしながら、なんでこんな事になったのかはすごく興味があったので「返金は諦めたんだけど原因教えてくれない?」と聞いてまだやり取りを続けてみたところ

  • 初回の入力でZIP Code間違えてね? → 入れたのは間違えてないはずだし2枚ともミスるとか無くね?
  • もしかするとLycamobile側でなんかミスが有ったのかも。何にせよ改善は必要だよね → そうだよね、原因わかったら教えて
  • Zip codeも間違ってなさそうだし返金するわ → え、まじで

突然返金に応じてきたのでちょっとびっくり。 その後しばらくしてAmazonから返金のお知らせメールが来たのでまじで返金されたらしい。

なんだかんだトラブったんだけど現地でSIM使う機会もあったのでまあいい勉強になったかなと思う。

といりあえずLycamobile使ってWebからアクティベーションする際に Invalid ICCID ってでたらすぐにサポートに連絡しましょう。

Slackで発言していない人をチャンネルからkickするスクリプト

Slackで発言していない人をチャンネルからkickするスクリプトを雑に書いたので置いておく。

動作としては

  1. 対象のチャンネルのメンバを取得
  2. 発言者のリストを取得(今回はBigQueryからUser IDを抽出してきたファイルを利用[下記参照])
  3. 1と2の差分から未発言のユーザリストを作成
  4. 3で作成したユーザリストのメンバを対象チャンネルからkick
require 'json'
require 'slack-ruby-client'

Slack::Web::Client.configure do |config|
  config.token = ENV['SLACK_API_TOKEN']
  raise 'Missing ENV[SLACK_API_TOKEN]!' unless config.token

  STDOUT.sync = true

  config.logger = Logger.new(STDOUT)
  config.logger.level = Logger::INFO
end

CHANNEL_ID = '' # TARGET_CHANNEL_ID
FILE_NAME  = '' # DATA_FILE_PATH

client = Slack::Web::Client.new
res = client.channels_info(channel: CHANNEL_ID)
channel_members = res['channel']['members']

post_members = open(FILE_NAME) do |data|
  members = JSON.load(data)
  members.map{|member| member['user']}
end

kick_members = channel_members - post_members
kick_members.each do |member|
  user = client.users_info(user: member)
  client.channels_kick(channel: CHANNEL_ID, user: member)
end
[
  {
    "user": "U0331B9R5",
  },
  {
    "user": "UEFRP7DU5",
  },
  ...
  {
    "user": "U0DDUMYM7",
  },
  {
    "user": "U3YJ3FWC9",
  }
]

本当は発言している人のリストをBigQueryから直接とってこればよかったのだが、 今回は雑にファイルに落とし込んだものを利用してみた。

※発言者のリストを作るための処理はこっちを参照。 mahito.hatenablog.com

無事にチャンネルのお掃除ができたのでよし!

Display Nameが設定されてなくてもユーザ名が出るように修正

Display Nameが設定されていないとBOTの名前になってしまうバグが有った。

github.com

毎回Display Nameを設定してねっていうのが面倒になったし、 そもそも設定しなくても出るようにしてたはずだったのだがそうなっていなかったので修正した。

github.com

これでDisplay Nameが設定されてなくてもユーザ名が出るようになった。

あー、Docker imageのダイエットしたいな・・・

子育てエンジニアのインプット・アウトプット方法

2019/2/16 22:42 ながらに追記

きっかけ

続々とコメントが寄せられているのでとりあえず昼休みにまとめてみた。

寄せられたコメント

家事時間の短縮・削減

  • やること/やらないことの明確化
  • 家事の自動化
    • ルンバ
    • 食洗機
    • 乾燥機能つき洗濯機
    • 浴室乾燥
  • 料理キットの活用
  • 外食の活用

空き時間の活用

  • 通勤時間
  • ビルドの待ち時間
  • 子供の習い事の付き添い時間

時間の捻出

  • 仕事の量を減らす
  • テレビを見る時間を削る
  • 子供と早い時間に寝て朝早くに
  • 夜更かし可能な日に(ex.土曜)
  • 有給
  • 子供も自分もそれぞれ一人で本を読む時間を設ける
  • リモートワーク
  • 職場に近づく引っ越し
  • 子供をYoutubeで釘付けにする
  • シッターさんを雇う

ながら

  • 寝かせつけ前に競技プログラミング等の問題を見て寝かせつけをしながら脳内で解く
  • 家事をしながらTVにChromecast経由でYoutubeに上がっているカンファレンスの動画を流す
    • 海外のカンファレンスの場合英語字幕をつけると英語の勉強にもなる

効率化

  • アウトプット(ゴール)を先に決めて集める情報を効率化
  • 仕事をチャレンジングなものにする
    • 場合によっては転職も視野に

番外編

こういう勉強会もあるらしい

ちなみに我が家

  • 夫婦共働き
  • 子供2人
    • 上5歳、下1歳
    • 共に保育園
  • 通勤 1.5h

来てるコメントの中ではまだこれぐらいしかまだやってないのでもう少しいろいろやってみようと思う。

  • ルンバ
  • 食洗機
  • 乾燥機能つき洗濯機
  • 通勤時間
  • 夜更かし
  • 子供をYoutubeで釘付けにする
  • リモートワーク(週1〜2程度)

Macで `ip` コマンド

Linuxip コマンドになったのにMacはifconfigだったりするのでなかなか ip に慣れないところ、知り合いに以下のツールを教えてもらった。

github.com

% /usr/bin/ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)"
% brew install iproute2mac
% ip a
lo0: flags=8049<UP,LOOPBACK,RUNNING,MULTICAST> mtu 16384
    inet 127.0.0.1/8 lo0
    inet6 ::1/128
    inet6 fe80::1/64 scopeid 0x1
...

これでMacでも ip コマンドが使える様になるのでようやく自分の中で ip コマンドが根付きそうである。

Error 1298: Unknown or incorrect time zone: 'UTC' の解決

なんかタイトルのエラーが出た。

Error 1298: Unknown or incorrect time zone: 'UTC'

ググったところ簡単に解決策が見つかった。

dba.stackexchange.com

以下のコマンドで解決できるらしい。

$ mysql_tzinfo_to_sql /usr/share/zoneinfo/|sudo mysql -u root mysql

mysql_tzinfo_to_sql プログラムは、mysql データベースに、タイムゾーンテーブルをロードします。

MySQL :: MySQL 5.6 リファレンスマニュアル :: 4.4.6 mysql_tzinfo_to_sql — タイムゾーンテーブルのロード

ということらしい。 つまりMySQLタイムゾーンが入っていないことが原因だったらしいのでこれで解決。