とんちゃんといっしょ

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

v2 Managed Pipeline Template

Spinnaker v1.12.0 からManaged Pipeline Template v2 というのがでてきたらしい。

www.spinnaker.io

This release adds alpha API and spin CLI support for MPT v2. See the blog post for more information.

詳しくは以下のBlogを見ろということらしい。

blog.spinnaker.io

ブログを読んでみると多分こういうことらしい(英語力不足)

MPT v2でできること

  • テンプレートの作成と編集の改善としてSpinnakerから取得したPipelineのJSONをそのままテンプレートの定義として使える。
  • spinからの MPT v2利用
  • テンプレートの標準化としてSpring Expression Language(SpEL)を、パイプラインとテンプレート用の単一の共有式言語として利用。
  • テンプレートの多重継承のサポートを辞めることで、サーバーサイドのMPTバックエンドを簡素化

今後何ができるか

  • v2 Pipeline Templateに対してFiatによる権限管理によりSpinnakerの管理者はどのユーザがPipeline Templateの作成、編集、読み込みコントロールできるように。
  • Sponnetライブラリが複数ソース、サポートされているモジュール、継承などから構成されるpipeline templateの構成をサポートすることで、MPT v1の頃よりMPTのバックエンドが大幅に簡素化される。
  • UIサポートの改善し、指定されたパイプラインのインスタンスがどのテンプレートを元にしたのか、どの変数値を指定されたのかなどを可視化が簡単に。

その他

sponnet library の変更の方を見てみたが、以前より大きい違いはmetadataとvariablesで、特に前者のmetadataのなかでscopeが設定できるようなので、ここがFiatと連携をして権限管理をしてくれるのかなと思う。

github.com

Amazon Prime会員の値上げにも気にならないお得なAmazon Mastercardゴールドの作り方

最近 Amazon Primeが年会費を1000円あげるというのが話題になったが、私もAmazon Prime会員なので以下のお便りが来た。

Amazon プライム会員の皆様

平素よりAmazonプライムをご利用いただきありがとうございます。Amazonプライムの会費変更に関するお知らせです。

Amazonプライムは2007年に配送特典のみで開始し、以降11年間、同価格でより多くの特典を追加してまいりました。配送特典対象商品は現在では数百万点に増え、プライム会員はその対象商品の配送を追加料金なしで無制限にお使いいただけます。さらに、Prime Videoの会員特典対象コンテンツへのアクセスや、Prime Music、Prime Reading、プライム・ワードローブ、世界各国で同時開催されているプライムデーなど増え続ける多様な特典の多くをご利用いただけます。プライム会員の皆様の生活を便利で豊かにするため、努めてまいります。

この度2019年4月12日付でAmazonプライムの年会費を3,900円(税込)から4,900円(税込)に変更する事となりました。

お客様がご登録されている年会費のお支払いプランにて会員登録の更新をされる場合は、2019年5月17日以降の会員登録更新時に新しい会費への変更が適用されます。

プライム会費の変更に伴う追加の手続きは必要ありません。会員登録は「アカウントサービス」でいつでも変更いただけます。

引き続きAmazonプライムをお楽しみください。

Amazon プライム

値上げがあるけどまだやめるような値段でもないので継続はしようと思っていたのだが、ちょうどクレジットカードを今の手持ちから変えようと思っていたところのAmazonプライム会員の値上げである。いろいろ調べているとどうも Amazon Mastercardゴールドがお得そうだということがわかった。

Amazon Mastercardゴールドは年会費10,800円が毎年必要なものの、プライム会員の会費が不要らしくこれだけで4,900円が浮く。 また2年目以降は年会費が最大6,480円割引のため実質無料でAmazonゴールドカードが持てることになる。

ご利用状況により、2年目以降から年会費が最大6,480円割引(税込み)割引 ・「マイ・ペイすリボ」でおトク ゴールドカードの方で「マイ・ペイすリボ」にご登録の方は、年に1回以上カードをご利用になれば、2年目以降から年会費が半額の「5,400円(税込み)」割引となります。

・「WEB明細書サービス」でおトク さらに「カードご利用代金WEB明細書サービス」のご利用で2年目以降年会費が「1,080円(税込み)」割引となります。 よって、最大税込み6,480円の割引となりますので是非ご利用ください。

よし、ではAmazon Mastercardゴールドを申し込もうと思ったところ、 どうも以下のようにAmazon Mastercardクラシックから申し込んだほうが良いとわかったのでまとめておく。

クラシック ⇒ ゴールド 最適オペレーション

クラシック ⇒ ゴールド 最適オペレーション

上記のユーザコメントでは以下のような手順が最適だと言っている

  1. Amazonにログインする
  2. AmazonMasterCardのリンクからAmazon Mastercardクラシックを選択する
  3. 5000ポイント獲得の文言があるのを確認したうえで申し込みをする(※Myペイすリボを申し込む(重要))
  4. クラシックカードが届くまで首を長くしてまつ
  5. 届いたらまずvPassを登録する
  6. そのままWeb明細を申込する
  7. Myペイすリボの月の支払額をカードの限度額に設定する
  8. Amazon Mastercardゴールドへの切り替えを申し込む
  9. ゴールドカードが届くまで首を長くしてまつ
  10. ゴールドカードが届いたらまずvPassに追加する
  11. Myペイすリボの月の支払額をゴールドカードの限度額に設定する
  12. Amazonアカウントの支払用クレジットカードにゴールドカードを登録
  13. Amazonの支払用カードからテンポラリーカードとクラシックカードを削除する

いきなりゴールドカードに申し込むとAmazonポイント5000ポイントが貰えないらしく、 クラシックカードを申し込み5000ポイントを得てからゴールドカードにしたほうがお得という流れらしい。

しかし、知人の情報によると7月のプライムデーは毎年ゴールドガード申込でキャッシュバックのキャンペーンがあるらしく、

「8. Amazon Mastercardゴールドへの切り替えを申し込む」の部分を

8. 7月のプライムデー Amazon Mastercardゴールドへの切り替えを申し込む」

とすることでよりお得にAmazonゴールドカードを手に入れられるらしい。

そんなわけで早速Amazon Mastercardクラシックを申し込んだので受け取り待ちのため、 次は7月のプライムデーを逃さず切り替えをしていく予定。

pumbaを調べてみた

前回 に続きChaos Engineering系の調べ物

今回は pumba について調べてみた。

github.com

Chaos testing and network emulation tool for Docker

pumba はDocker向けのChaos testingとネットワークエミュレーションを行うツールらしい。

できること

コンテナ単位で

  • コンテナを壊す(kill/rm)
    • killの場合signalの指定が可能
  • コンテナを止める(pause/stop)
    • pauseの場合止める時間を指定可能
  • NWのエミュレーション
    • 遅延
    • パケットロス
      • パケットロスの方式に異なる3つがある模様(loss, loss-state, loss-gemodel)
    • トラフィックへのレートリミット
    • パケットの重複
    • パケットの破損
  • 対象とするコンテナの指定(名前, 正規表現マッチ)

できないこと

  • namespace単位での設定やブラックリスト登録
    • 気をつけないと kube-system 配下のコンテナが殺されたり遅延する
  • 動作のスケジューリング
    • chaosmonkeyやkube-monkeyと違って1回だけの動作もしくは一定間隔で動作を続ける
    • intervalなどで動作間隔の調整は可能

動作

コマンドラインから定期的/単発にランダム/特定のコンテナの

  • 破壊/停止を行う
  • NW障害をエミュレーションする

動かし方

注:manifestは全部Spinnakerから放り込んだのでSpinnakerがなければ kubectl で作成してください。

namespaceの作成

一応作っておく

$ kubectl create namespace pumba
namespace/pumba created

nginxのデプロイ

apiVersion: apps/v1
kind: Deployment
metadata:
  name: pumba-nginx
  namespace: pumba
  labels:
    app: pumba-nginx
spec:
  replicas: 3
  selector:
    matchLabels:
      app: pumba-nginx
  template:
    metadata:
      labels:
        app: pumba-nginx
    spec:
      containers:
        - image: nginx
          name: nginx
          ports:
            - containerPort: 80

nginx(service)のデプロイ

apiVersion: v1
kind: Service
metadata:
  labels:
    app: pumba-nginx
  name: pumba-nginx
  namespace: pumba
spec:
  ports:
    - port: 80
      protocol: TCP
  selector:
    app: pumba-nginx

pumbaのデプロイ

apiVersion: apps/v1
kind: DaemonSet
metadata:
  name: pumba
  namespace: pumba
spec:
  selector:
    matchLabels:
      app: pumba
  template:
    metadata:
      labels:
        app: pumba
        com.gaiaadm.pumba: "true" # prevent pumba from killing itself
      name: pumba
    spec:
      containers:
      - image: gaiaadm/pumba:master
        imagePullPolicy: Always
        name: pumba
        # Pumba command: modify it to suite your needs
        # Currently: randomly try to kill some container every 3 minutes
        args:
          - --random
          - --interval
          - "3m"
          - kill
          - --signal
          - "SIGKILL"
          - re2:pumba-nginx
        resources:
          requests:
            cpu: 10m
            memory: 5M
          limits:
            cpu: 100m
            memory: 20M
        volumeMounts:
          - name: dockersocket
            mountPath: /var/run/docker.sock
      volumes:
        - hostPath:
            path: /var/run/docker.sock
          name: dockersocket

動作確認(kill)

$ kubectl get pods -n pumb
NAME                           READY   STATUS             RESTARTS   AGE
pumba-d92ms                    1/1     Running            0          3h
pumba-m56gr                    1/1     Running            0          3h
pumba-m7szx                    1/1     Running            0          3h
pumba-nginx-78cbbc666d-lczjr   0/1     CrashLoopBackOff   37         1d
pumba-nginx-78cbbc666d-lfglj   1/1     Running            34         1d
pumba-nginx-78cbbc666d-nb2t5   0/1     CrashLoopBackOff   47         1d

RESTARTSが増えていくのが確認できた

alpine(ping)のデプロイ

apiVersion: apps/v1
kind: Deployment
metadata:
  name: pumba-ping
  namespace: pumba
  labels:
    app: pumba-ping
spec:
  replicas: 1
  selector:
    matchLabels:
      app: pumba-ping
  template:
    metadata:
      labels:
        app: pumba-ping
    spec:
      containers:
        - image: alpine
          name: pumba-ping
          command: ["/bin/ping"]
          args: 
            - "10.0.3.182" # 適当なPodのIPを指定

pumba(delay)のデプロイ

apiVersion: apps/v1
kind: DaemonSet
metadata:
  name: pumba-delay
  namespace: pumba
spec:
  selector:
    matchLabels:
      app: pumba-delay
  template:
    metadata:
      labels:
        app: pumba-delay
        com.gaiaadm.pumba: "true" # prevent pumba from killing itself
      name: pumba-delay
    spec:
      containers:
      - image: gaiaadm/pumba:master
        imagePullPolicy: Always
        name: pumba-delay
        # Pumba command: modify it to suite your needs
        # Currently: randomly try to kill some container every 3 minutes
        args:
          - --random
          - --interval
          - "1m"
          - netem
          - --tc-image
          - "gaiadocker/iproute2"
          - --duration
          - "20s"
          - delay
          - re2:pumba-ping
        volumeMounts:
          - name: dockersocket
            mountPath: /var/run/docker.sock
      volumes:
        - hostPath:
            path: /var/run/docker.sock
          name: dockersocket

実行結果(delay)

64 bytes from 8.8.8.8: seq=1864 ttl=121 time=94.832 ms
64 bytes from 8.8.8.8: seq=1865 ttl=121 time=93.230 ms
64 bytes from 8.8.8.8: seq=1866 ttl=121 time=94.726 ms
64 bytes from 8.8.8.8: seq=1867 ttl=121 time=96.826 ms
64 bytes from 8.8.8.8: seq=1868 ttl=121 time=109.091 ms
64 bytes from 8.8.8.8: seq=1869 ttl=121 time=100.854 ms
64 bytes from 8.8.8.8: seq=1870 ttl=121 time=97.063 ms
64 bytes from 8.8.8.8: seq=1871 ttl=121 time=109.645 ms
64 bytes from 8.8.8.8: seq=1872 ttl=121 time=107.117 ms
64 bytes from 8.8.8.8: seq=1873 ttl=121 time=101.009 ms
64 bytes from 8.8.8.8: seq=1874 ttl=121 time=103.168 ms
64 bytes from 8.8.8.8: seq=1875 ttl=121 time=98.855 ms
64 bytes from 8.8.8.8: seq=1876 ttl=121 time=97.942 ms
64 bytes from 8.8.8.8: seq=1877 ttl=121 time=97.129 ms
64 bytes from 8.8.8.8: seq=1878 ttl=121 time=108.756 ms
64 bytes from 8.8.8.8: seq=1879 ttl=121 time=95.386 ms
64 bytes from 8.8.8.8: seq=1880 ttl=121 time=104.386 ms
64 bytes from 8.8.8.8: seq=1881 ttl=121 time=95.275 ms
64 bytes from 8.8.8.8: seq=1882 ttl=121 time=110.080 ms
64 bytes from 8.8.8.8: seq=1883 ttl=121 time=94.726 ms
64 bytes from 8.8.8.8: seq=1884 ttl=121 time=96.021 ms
64 bytes from 8.8.8.8: seq=1885 ttl=121 time=97.216 ms
64 bytes from 8.8.8.8: seq=1886 ttl=121 time=100.285 ms
64 bytes from 8.8.8.8: seq=1887 ttl=121 time=0.598 ms
64 bytes from 8.8.8.8: seq=1888 ttl=121 time=0.545 ms
64 bytes from 8.8.8.8: seq=1889 ttl=121 time=0.555 ms
64 bytes from 8.8.8.8: seq=1890 ttl=121 time=0.598 ms
64 bytes from 8.8.8.8: seq=1891 ttl=121 time=1.746 ms
64 bytes from 8.8.8.8: seq=1892 ttl=121 time=1.066 ms
64 bytes from 8.8.8.8: seq=1893 ttl=121 time=1.235 ms
64 bytes from 8.8.8.8: seq=1894 ttl=121 time=0.581 ms

20秒遅延が発生しているのが確認できた

pumba(loss)のデプロイ

apiVersion: apps/v1
kind: DaemonSet
metadata:
  name: pumba-loss
  namespace: pumba
spec:
  selector:
    matchLabels:
      app: pumba-loss
  template:
    metadata:
      labels:
        app: pumba-loss
        com.gaiaadm.pumba: "true" # prevent pumba from killing itself
      name: pumba-loss
    spec:
      containers:
      - image: gaiaadm/pumba:master
        imagePullPolicy: Always
        name: pumba-loss
        # Pumba command: modify it to suite your needs
        # Currently: randomly try to kill some container every 3 minutes
        args:
          - --random
          - --interval
          - "1m"
          - netem
          - --tc-image
          - "gaiadocker/iproute2"
          - --duration
          - "20s"
          - loss
          - --percent
          - "100"
          - re2:pumba-ping
        volumeMounts:
          - name: dockersocket
            mountPath: /var/run/docker.sock
      volumes:
        - hostPath:
            path: /var/run/docker.sock
          name: dockersocket

結果(loss)

64 bytes from 8.8.8.8: seq=809 ttl=121 time=0.490 ms
64 bytes from 8.8.8.8: seq=810 ttl=121 time=0.587 ms
64 bytes from 8.8.8.8: seq=811 ttl=121 time=0.509 ms
64 bytes from 8.8.8.8: seq=832 ttl=121 time=1.199 ms
64 bytes from 8.8.8.8: seq=833 ttl=121 time=0.535 ms
64 bytes from 8.8.8.8: seq=834 ttl=121 time=0.717 ms
64 bytes from 8.8.8.8: seq=835 ttl=121 time=0.552 ms
64 bytes from 8.8.8.8: seq=836 ttl=121 time=0.530 ms
64 bytes from 8.8.8.8: seq=837 ttl=121 time=0.470 ms
64 bytes from 8.8.8.8: seq=838 ttl=121 time=0.481 ms
64 bytes from 8.8.8.8: seq=839 ttl=121 time=0.466 ms
64 bytes from 8.8.8.8: seq=840 ttl=121 time=0.504 ms

seq=811から832まで20s消えているのが確認できた

pumba(rate)のデプロイ

apiVersion: apps/v1
kind: DaemonSet
metadata:
  name: pumba-rate
  namespace: pumba
spec:
  selector:
    matchLabels:
      app: pumba-rate
  template:
    metadata:
      labels:
        app: pumba-rate
        com.gaiaadm.pumba: "true" # prevent pumba from killing itself
      name: pumba-rate
    spec:
      containers:
      - image: gaiaadm/pumba:master
        imagePullPolicy: Always
        name: pumba-rate
        # Pumba command: modify it to suite your needs
        # Currently: randomly try to kill some container every 3 minutes
        args:
          - --random
          - --interval
          - "1m"
          - netem
          - --tc-image
          - "gaiadocker/iproute2"
          - --duration
          - "20s"
          - rate
          - --rate
          - "100kbit"
          - re2:pumba-ping
        volumeMounts:
          - name: dockersocket
            mountPath: /var/run/docker.sock
      volumes:
        - hostPath:
            path: /var/run/docker.sock
          name: dockersocket

実行結果(rate)

64 bytes from 8.8.8.8: seq=1163 ttl=121 time=1.178 ms
64 bytes from 8.8.8.8: seq=1164 ttl=121 time=9.096 ms
64 bytes from 8.8.8.8: seq=1165 ttl=121 time=8.444 ms
64 bytes from 8.8.8.8: seq=1166 ttl=121 time=8.358 ms
64 bytes from 8.8.8.8: seq=1167 ttl=121 time=8.377 ms
64 bytes from 8.8.8.8: seq=1168 ttl=121 time=8.477 ms
64 bytes from 8.8.8.8: seq=1169 ttl=121 time=8.507 ms
64 bytes from 8.8.8.8: seq=1170 ttl=121 time=8.390 ms
64 bytes from 8.8.8.8: seq=1171 ttl=121 time=8.377 ms
64 bytes from 8.8.8.8: seq=1172 ttl=121 time=8.396 ms
64 bytes from 8.8.8.8: seq=1173 ttl=121 time=8.590 ms
64 bytes from 8.8.8.8: seq=1174 ttl=121 time=8.429 ms
64 bytes from 8.8.8.8: seq=1175 ttl=121 time=8.570 ms
64 bytes from 8.8.8.8: seq=1176 ttl=121 time=8.303 ms
64 bytes from 8.8.8.8: seq=1177 ttl=121 time=9.068 ms
64 bytes from 8.8.8.8: seq=1178 ttl=121 time=8.332 ms
64 bytes from 8.8.8.8: seq=1179 ttl=121 time=8.336 ms
64 bytes from 8.8.8.8: seq=1180 ttl=121 time=8.512 ms
64 bytes from 8.8.8.8: seq=1181 ttl=121 time=8.393 ms
64 bytes from 8.8.8.8: seq=1182 ttl=121 time=9.980 ms
64 bytes from 8.8.8.8: seq=1183 ttl=121 time=9.001 ms
64 bytes from 8.8.8.8: seq=1184 ttl=121 time=0.991 ms
64 bytes from 8.8.8.8: seq=1185 ttl=121 time=0.758 ms
64 bytes from 8.8.8.8: seq=1186 ttl=121 time=3.291 ms
64 bytes from 8.8.8.8: seq=1187 ttl=121 time=1.169 ms
64 bytes from 8.8.8.8: seq=1188 ttl=121 time=0.613 ms
64 bytes from 8.8.8.8: seq=1189 ttl=121 time=0.597 ms
64 bytes from 8.8.8.8: seq=1190 ttl=121 time=0.772 ms

seq=1165から20sほど遅延しているのが確認できた

pumba(corrupt)のデプロイ

apiVersion: apps/v1
kind: DaemonSet
metadata:
  name: pumba-corrupt
  namespace: pumba
spec:
  selector:
    matchLabels:
      app: pumba-corrupt
  template:
    metadata:
      labels:
        app: pumba-corrupt
        com.gaiaadm.pumba: "true" # prevent pumba from killing itself
      name: pumba-corrupt
    spec:
      containers:
      - image: gaiaadm/pumba:master
        imagePullPolicy: Always
        name: pumba-corrupt
        # Pumba command: modify it to suite your needs
        # Currently: randomly try to kill some container every 3 minutes
        args:
          - --random
          - --interval
          - "1m"
          - netem
          - --tc-image
          - "gaiadocker/iproute2"
          - --duration
          - "20s"
          - corrupt
          - --percent
          - "100"
          - re2:pumba-ping
        volumeMounts:
          - name: dockersocket
            mountPath: /var/run/docker.sock
      volumes:
        - hostPath:
            path: /var/run/docker.sock
          name: dockersocket

実行結果(corrupt)

64 bytes from 10.0.3.182: seq=333 ttl=62 time=0.540 ms
64 bytes from 10.0.3.182: seq=334 ttl=62 time=0.372 ms
64 bytes from 10.0.3.182: seq=335 ttl=62 time=0.272 ms
64 bytes from 10.0.3.182: seq=336 ttl=62 time=0.300 ms
64 bytes from 10.0.3.182: seq=337 ttl=62 time=6.558 ms
64 bytes from 10.0.3.182: seq=357 ttl=62 time=1.927 ms
64 bytes from 10.0.3.182: seq=358 ttl=62 time=0.221 ms
64 bytes from 10.0.3.182: seq=359 ttl=62 time=0.360 ms
64 bytes from 10.0.3.182: seq=360 ttl=62 time=0.376 ms
64 bytes from 10.0.3.182: seq=361 ttl=62 time=0.238 ms
64 bytes from 10.0.3.182: seq=362 ttl=62 time=1.223 ms
64 bytes from 10.0.3.182: seq=363 ttl=62 time=0.519 ms

seq=337から357まで20seq応答がなくなっているのがわかる

除外

  • duplicate: pingだと意味なさそうなので今回はパス
  • loss-state: lossと同じっぽいので今回はパス
  • loss-gemodel: 同上

小ネタ

  • kube-monkeyと違ってコンテナを落とすのでPodからはErrorとして扱われるのでRestartsのカウントが増えていく
  • /var/run/docker.sock はCRIソケットという訳でもなくdockerクライアント向けのソケットなのでdocker依存かも?
  • pumbaのchaos test対象コンテナにtcがないとエラーになる(その場合対象コンテナに iproute2 を入れるか --tc-image gaiadocker/iproute2 が必要)
  • gaiaadm/pumba:master タグ以外で動くかどうか怪しい・・・

最近の寝かせつけ

ちょっと前まで寝かせつけではベッドの上で同じ本を何度も読まされ大変だった。

でも最近の寝かせつけはもっぱらこれに頼っている。

ディズニー ピクサーキャラクターズ Dream Switch(ドリーム スイッチ)

商品紹介には

親子の眠る前が楽しくなる、寝室の天井にディズニーのお話を投影する絵本プロジェクター。
50種のコンテンツからお話を選択し、10分程度のお話が始まり、お話が終るとオートオフで消えます。
天井に映し出させるディズニーのお話が夢の世界へ誘います!

<コンテンツ 50種>
毎日使える! 長く使える! ボリュームの50種! !
・【えほん 30種】講談社のディズニーゴールド絵本から厳選された30作品 (日本語字幕の有無が選択できるため、声で読み聞かせすることもできます。)
・【ことば 11種】ABCやあいうえお、生活習慣が学べる、ことばに関するコンテンツ
・【おたのしみ 9種】ディズニーの星空やひつじかぞえなどのエンターテイメントコンテンツ

とあるように5分〜10分程度のディズニーコンテンツが入っているので天井に映しながら寝かせつけを行っている。

いいところ

  • 天井に映すと子供がベッドに寝っ転がってくれる
  • 日本語/英語モードがある
  • いろいろな話がある
  • オートオフの機能がある
  • 本と違って自分が読まなくてもいい(これ大事)

わるいところ

  • 1歳児には今ひとつ効果が薄い
  • 自分が眠たくなって先に寝てしまう

結論

ドリームスイッチを使うと子供をベッドに誘いやすくなるし、本を読みすぎて自分の喉が乾くのは防げる。 あと英語になれさせたりするのに便利(と思ってる)。

でもこれを使っても子供は寝るときは寝るし、寝ないときは寝ないので、結局子供との仁義なき戦いは終わらない・・・

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

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