僕はダンスが嫌いだ。

僕はダンスが嫌いである。

その理由は僕が小学生の時にあった出来事が原因である。


当時僕の小学校ではクッソダサいダンス、略してクソダサダンスがなぜか流行っていた。

流行っていたと言っても皆が踊っているわけでもなく、そのクソダサダンスをなんとかして踊らせて、バカにしようという感じの流行り方である。

(どんなダンスかは具体的には忘れてしまったが、当時流行っていた芸人のダンスを、さらに下品にしたものだったと記憶している)


そんな当時、何をしたかまでは忘れたが、僕と町山くんという子がいたずらをしたことが原因で、教室の前に吊し上げられていた。

教室のみんなの前で謝罪をしなければならないと言う、令和では既に廃れた、平成の置き土産となる文化である。


ここでは穏便に謝罪をし、その場を終了しなければならない。

僕は可及的速やかに謝罪の弁を重ねた。隣の町山くんは無言だった。


するとクラスのボス的な女の子が「クソダサダンスを踊ったら許してあげる!」と言い出した。

ダンスを踊ることと謝罪をすることはイコールではないが、全体の嘲笑の下にさらされることで謝罪とみなす提案である。もはや平成ですら太刀打ちのできない、昭和の文化である。


周りもボス女の意見に賛同し、クソダサダンスを踊れと囃し立てる。町山くんは無言を貫いている。

僕はこの場を納めるためにはクソダサダンスを踊り、終わらせることが最善だと判断し、踊った。クソダサダンスを、踊った。


クラスは僕に向けた嘲笑で、大爆笑である。

いつも給食で大量にお代わりをする際に「育ち盛りだから」と言うため『盛り』と言うあだ名のついた彼も、とても優しいのに耳が真っ赤であるだけで『オコリザル』と言うあだ名のついた彼女も、指をさして僕を笑っている。

仕方ない。仕方ないんだ。これはいたずらをしたことへの贖罪である。世の中は嘲笑のもとで成り立っているのだから。


しかしこれで僕の禊は終わった。次は町山くんの番だ。はりきって、どうぞ。

そう思って僕が町山くんの方を見たところ、町山くんはフルフルと震えている。そして、泣き出した。

「僕はこんなダンス踊りたくない。絶対に踊りたくない」

そう言って泣き出す町山くん。


おいおい、それはないよ町山くん。

僕は踊った。笑われた。次は君の番なんだ。

そんな泣き落としで逃げてはいけないんだよ。これからの世の中、逃げてはいけない場面はたくさんあるんだ。町山くん。

僕はそう思っていると、先ほどまで嘲笑の渦に包まれていたクラスの雰囲気もなぜか変わっていき、


「町山くんかわいそう」

「確かにあのダンス踊って謝らせるのは違うよ」

「私だって絶対踊りたくない」


とクラスの子達が次々に言い出した。

しまいにはボス女も「みんな!あんなダンス踊らせて謝らせるなんておかしいよ!」と言い出した。はじめに言い出したのはこの女なのに。


町山くんは泣きながら「いたずらしてごめんね」と呟き、クラスのみんなも「ごめんね、変なダンス踊れとか言って」と、やさしい空気へと変わっていった。





へぇ〜〜〜〜〜、僕、クソダサダンス踊ったんだが? へぇ〜〜〜〜 なにこの空気。

ねぇ。町山くん? 僕はクソダサダンスを踊った。ねぇクラスのみんな? ねぇ町山くん?

へぇ〜〜〜〜





僕はそれ以降、ダンスが嫌いである。

k3sをラズパイで構築してみた

k8sのラズパイクラスタを遊ばせていたので、k3sのクラスタを組んでみました。

構築手順

使ったもの

Raspberry Pi環境の構築

raspbian streachのダウンロード

busterも出ていたのですが、自分のローカルにstreachがあったのでこちらを利用することに。

公式だと最新版しかなく、またダウンロードに時間がかかるため、以下の日本のミラーサイトを利用した方が良いです。 http://ftp.jaist.ac.jp/pub/raspberrypi/raspbian/images/raspbian-2019-04-09/

raspbianの書き込み

SDカードへの書き込みはEtcherを使いました。

imageは先ほど用意したraspbianのzipファイルを指定し、書き込み先に差し込んだSDカードを指定すればOKです。 5分ほどで書き込み完了します。

書き込んだ後はSSHをするために以下のファイルをtouchしておきます。

$ touch /Volumes/boot/ssh

raspberry piへのssh接続

自宅にモニターもマウスもキーボードもないので、wifi経由で繋げるようにします。 よくあるラズパイクラスタを作成する際はハブで接続すればOKだと思います。

①LANケーブルをRaspberry PIWi-Fiルータに接続する

Wi-Fiルータのサイトにアクセスして、IPを取得する
自分の場合は192.168.1.1など。ルータによって変わると思います。

自分の場合、raspberry piは192.168.1.170でした。

sshで接続

$ ssh pi@192.168.1.170
## 初期パスワードはraspberry

④cmdline.txtの書き換え
cgroupsの設定を反映しないと、k3sを起動させるときに失敗します。

$ sudo vi /boot/cmdline.txt

変更前

dwc_otg.lpm_enable=0 console=serial0,115200 console=tty1 root=PARTUUID=10437ae6-02 rootfstype=ext4 elevator=deadline fsck.repair=yes rootwait quiet splash plymouth.ignore-serial-consoles

変更後

dwc_otg.lpm_enable=0 console=serial0,115200 console=tty1 root=PARTUUID=10437ae6-02 rootfstype=ext4 elevator=deadline fsck.repair=yes rootwait quiet splash plymouth.ignore-serial-consoles cgroup_enable=cpuset cgroup_memory=1 cgroup_enable=memory

Wi-Fi設定

$ sudo raspi-config 

raspberry piの設定画面が表示されるため、以下を設定します。

  • 「2 Network Options」 → 「N2 Wi-Fi」→ 「国設定:Japan」 → 「SSID:ルータのSSIDを入力」 → 「パスワード:ルータのパスワードを設定」
  • 「2 Network Options」 → 「N1 HostName」 → 「ホスト名を適当に変更する(master/workerわかりやすいように)」

両方終わったら「Finish」を押す。rebootするかと言われるので、rebootを行います。

で、この間に有線LANを抜いておきます。 先にLANを抜くともちろん操作ができなくなるので、その際はraspberry piの電源を抜き差ししましょう。

Wi-Fi経由での接続
Wi-Fiルータのサイトにアクセスして、IPを取得します。 IPが170→114に変わってました。

sshで接続

$ ssh pi@192.168.1.114
## 初期パスワードはraspberry

⑧3台のraspberry piで上記設定をやっておく。
ホスト名は以下にしました。

  • raspberry-master
  • raspberry-worker-1
  • raspberry-worker-2

k3sのインストール(3台のraspberry piで実施)

raspberry pisshした後、以下のコマンドを実行します。およそ数分かかります。

curl -sfL https://get.k3s.io | sh -

完了後、以下のコマンドでk3sのインストールを確認します。

$ k3s kubectl get nodes
NAME               STATUS   ROLES    AGE   VERSION
raspberry-master   Ready    master   90s   v1.14.6-k3s.1

workerの接続

worker-1/worker-2はworkerノードとして参加させたいので、以下を実施します。

masterで実施

$ cat /var/lib/rancher/k3s/server/node-token
[tokenが表示されるので、コピーしておく]

workerで実施

$ sudo service k3s stop
$  sudo k3s agent --server https://[masterのIP]:6443 --token [masterで表示されたtoken]

クラスタの確認

$ sudo k3s kubectl get nodes
NAME                   STATUS   ROLES    AGE   VERSION
raspberry-master       Ready    master   55m   v1.14.6-k3s.1
raspberrypi-worker-1   Ready    worker   33m   v1.14.6-k3s.1
raspberrypi-worker-2   Ready    worker   21m   v1.14.6-k3s.1

完成!

実験

raspberry piの良いところは物理的な故障を手軽に試せるところかなと思っています。

今回はstorage故障(SDカードを引っこ抜く)を試してみます。

masterでdeployment/svc作成

$ kubectl run nginx --image=nginx
$ kubectl expose deploy nginx --port=80 --type=NodePort

疎通確認

$ kubectl get svc
NAME         TYPE        CLUSTER-IP     EXTERNAL-IP   PORT(S)        AGE
kubernetes   ClusterIP   10.43.0.1      <none>        443/TCP        59m
nginx        NodePort    10.43.182.60   <none>        80:32157/TCP   25s

ブラウザでhttp://[masterのIP]:32157でnginxへのアクセスができることを確認。

storage故障を起こす

$ get pods -o wide
NAME                     READY   STATUS    RESTARTS   AGE   IP          NODE                   NOMINATED NODE   READINESS GATES
nginx-7db9fccd9b-68vbc   1/1     Running   0          26m   10.42.2.3   raspberrypi-worker-1   <none>           <none>

worker-1に紐づいているので、worker-1のSDカードを抜いてみます。

$ k3s kubectl get nodes
NAME                   STATUS     ROLES    AGE   VERSION
raspberry-master       Ready      master   63m   v1.14.6-k3s.1
raspberrypi-worker-1   NotReady   worker   40m   v1.14.6-k3s.1
raspberrypi-worker-2   Ready      worker   28m   v1.14.6-k3s.1

worker-1がNotReadyになりました。

その間はwatch kubectl get podsで様子をみます。

NAME                     READY   STATUS              RESTARTS   AGE   IP          NODE                   NOMINATED
NODE   READINESS GATES
nginx-7db9fccd9b-28lxc   0/1     ContainerCreating   0          27s   <none>      raspberrypi-worker-2   <none>
       <none>
nginx-7db9fccd9b-68vbc   1/1     Terminating         0          32m   10.42.2.3   raspberrypi-worker-1   <none>
       <none>
NAME                     READY   STATUS        RESTARTS   AGE   IP          NODE                   NOMINATED NODE   READINESS GATES
nginx-7db9fccd9b-28lxc   1/1     Running       0          74s   10.42.3.2   raspberrypi-worker-2   <none>           <none>

worker-1のPodが削除されて、worker-2にPodが再作成されました。

しかしworker-1のPodがTerminateされるまで5分かかりました。そのため、

  • Kubeletが死んでいることを確認するまで少し時間がかかる
  • Kubeletが死んでいることを確認してから、Podが移動する
  • replica: 1の場合疎通ができなくなるため、replica: 2以上とし、Podは別々のノードに反映されるように設定をすべき

という挙動が確認できました。

最後に

k8sの時とは違って、IoTを前提に作られているのでインストールは簡単でした。

k3sはetcdの代わりにsqliteが使われており、現在multi masterができなそう?な感じだったりします。 k8sとの違いなんかも少しずつ見ていこうと思います。

参考

qiita.com

kenfdev.hateblo.jp

みんなのdocker/kubernetesを読みました

みんなのDocker/Kubernetes

みんなのDocker/Kubernetes

  • 作者: 石澤基,五十嵐綾,大塚元央,須田一輝,稲津和磨,九岡佑介,坂部広大,青山真也,池添明宏,上岡真也
  • 出版社/メーカー: 技術評論社
  • 発売日: 2019/04/18
  • メディア: 単行本(ソフトカバー)
  • この商品を含むブログを見る

良い本です。

docker、kubernetesをある程度利用していて、自分の知らないことも多かったので、備忘録として。

細かいところは本を実際に見た方が良いと思います。ページ数も少なくてさらっと読め、かつ効果的です。 ある程度利用しているユーザ向けなので、Kubernetes完全ガイドを読んでからの方がすんなり入ってくると思います。

最高のコンテナイメージをビルドする

コンテナの良いところはVMよりもオーバーヘッドを小さくし、「早く」「小さく」環境へ移動する事ができる点

そのためには、コンテナイメージを出来るだけ小さくする・キャッシュを活用するべき

  • イメージを圧縮してビルドしたい場合はdocker-slimコマンド
  • コンテナイメージの解析をしたい場合はdiveコマンド
  • entrypoint.shなどで起動する場合、ゾンビプロセスになるのを防ぐためには--initオプション

また、コンテナのUFSの特徴なども把握しておく必要がある

kubernetesによる宣言的なシステム管理

kubectl apply -fの挙動と、Strategic Marge Patchの挙動に関して 何も考えずapplyしてしまうとリストの記載が消失してしまう事があるため、kubectl diffでの事前確認が大切

Kustomize良さそう

本番運用に向けたPod機能の利用

いざ本番環境で利用した際に起こる問題に対処する方法が記載されている

  • resourcesのQoSクラスを意識しないと、意図しないPodのTerminateが走ってしまう
  • Terminateの挙動を意識する。gracefulを意識して設定しないと、HTTPリクエストが消失してしまう
  • NodeのUpdateのEvictでPodの数が不足してしまわないように、PodDisruptionBudgetを設定すべき

Kubernetesでの開発を高速化するツール

  • kube-ps1/kubectx/kubens/compilation/sternzshbashのprofileに設定しておく
  • KustomizeはHelmを使うほどではないが、GitOpsなどでYamlを管理するには便利すぎる

活用事例の所感

  • Kubernetesでは難しいStatefulな部分は外部SaaSを積極的に活用する
  • マルチクラウド・ハイブリッドクラウドの前に、まず一つのベンダにロックインしても使いこなす事が大切
  • オンプレは大変。アプライアンスを使わずに自前でツールを作っている例(サイボウズ)もあったが、Kubernetesの中身まで知り使いこなすためにはそれ相応の覚悟と労力が必要

学ぶべき事

  • Istio
  • knative
  • Helm/Kustomize

特にIstio(Envoy) + gRPCの仕組みはこれからどんどん主流になっていくと思うので、ここは抑えとかないといけないなぁ

CloudNativeDaysでも言ってたが、コンテナもk8sクラウドも、自動化を進めていくためのツールの一つで、ツールを入れる事が目的であってはいけないですね

ES2018の糖衣構文に迷う

www.amazon.co.jp

Nuxt.jsビギナーズガイドを読んでいるところですが、しっくりこなかったJSの糖衣構文に関してメモ。 糖衣構文は波括弧だったり、丸括弧だったり、角括弧だったりで混乱しますね。

  • 波括弧・・・{...}
  • 丸括弧・・・(...)
  • 角括弧・・・[...]

アロー関数の糖衣構文

functionではなく=>で関数を記載することが可能。

export const state = () => ({
  counter: 0
});

引数分割束縛

qiita.com

関数の実引数に波括弧が利用される

increment ({ commit }) {
  commit('increment')
}

本来であれば、contextを変数にもち、 以下のように記載する必要がある。

increment (context) {
  context.commit('increment')
}

それを、分割代入した形となる。

({ commit })→({ commit } = context) →( commit = context.commit )

本来のコードを省略して書くことができるため、 Vuexでは多用されている。

importで波括弧がつくかつかないか

blog.bgbgbg.net

import { mapGetters, mapActions } from 'vuex'
import Cookies from 'universal-cookie'
  • export defaultとしたときは、波括弧は不要
  • exportとしたときは、波括弧が必要

オブジェクトスプレッド

qiita.com

...obj、のように...をつけることで、配列でもオブジェクトでも要素を展開してくれる。

obj = {
  id: 1,
  user: 'name',
  data: 'test' 
}
obj = { ...obj, data: 123 }

つらたん。