僕はダンスが嫌いだ。
僕はダンスが嫌いである。
その理由は僕が小学生の時にあった出来事が原因である。
当時僕の小学校ではクッソダサいダンス、略してクソダサダンスがなぜか流行っていた。
流行っていたと言っても皆が踊っているわけでもなく、そのクソダサダンスをなんとかして踊らせて、バカにしようという感じの流行り方である。
(どんなダンスかは具体的には忘れてしまったが、当時流行っていた芸人のダンスを、さらに下品にしたものだったと記憶している)
そんな当時、何をしたかまでは忘れたが、僕と町山くんという子がいたずらをしたことが原因で、教室の前に吊し上げられていた。
教室のみんなの前で謝罪をしなければならないと言う、令和では既に廃れた、平成の置き土産となる文化である。
ここでは穏便に謝罪をし、その場を終了しなければならない。
僕は可及的速やかに謝罪の弁を重ねた。隣の町山くんは無言だった。
するとクラスのボス的な女の子が「クソダサダンスを踊ったら許してあげる!」と言い出した。
ダンスを踊ることと謝罪をすることはイコールではないが、全体の嘲笑の下にさらされることで謝罪とみなす提案である。もはや平成ですら太刀打ちのできない、昭和の文化である。
周りもボス女の意見に賛同し、クソダサダンスを踊れと囃し立てる。町山くんは無言を貫いている。
僕はこの場を納めるためにはクソダサダンスを踊り、終わらせることが最善だと判断し、踊った。クソダサダンスを、踊った。
クラスは僕に向けた嘲笑で、大爆笑である。
いつも給食で大量にお代わりをする際に「育ち盛りだから」と言うため『盛り』と言うあだ名のついた彼も、とても優しいのに耳が真っ赤であるだけで『オコリザル』と言うあだ名のついた彼女も、指をさして僕を笑っている。
仕方ない。仕方ないんだ。これはいたずらをしたことへの贖罪である。世の中は嘲笑のもとで成り立っているのだから。
しかしこれで僕の禊は終わった。次は町山くんの番だ。はりきって、どうぞ。
そう思って僕が町山くんの方を見たところ、町山くんはフルフルと震えている。そして、泣き出した。
「僕はこんなダンス踊りたくない。絶対に踊りたくない」
そう言って泣き出す町山くん。
おいおい、それはないよ町山くん。
僕は踊った。笑われた。次は君の番なんだ。
そんな泣き落としで逃げてはいけないんだよ。これからの世の中、逃げてはいけない場面はたくさんあるんだ。町山くん。
僕はそう思っていると、先ほどまで嘲笑の渦に包まれていたクラスの雰囲気もなぜか変わっていき、
「町山くんかわいそう」
「確かにあのダンス踊って謝らせるのは違うよ」
「私だって絶対踊りたくない」
とクラスの子達が次々に言い出した。
しまいにはボス女も「みんな!あんなダンス踊らせて謝らせるなんておかしいよ!」と言い出した。はじめに言い出したのはこの女なのに。
町山くんは泣きながら「いたずらしてごめんね」と呟き、クラスのみんなも「ごめんね、変なダンス踊れとか言って」と、やさしい空気へと変わっていった。
へぇ〜〜〜〜〜、僕、クソダサダンス踊ったんだが? へぇ〜〜〜〜 なにこの空気。
ねぇ。町山くん? 僕はクソダサダンスを踊った。ねぇクラスのみんな? ねぇ町山くん?
へぇ〜〜〜〜
僕はそれ以降、ダンスが嫌いである。
k3sをラズパイで構築してみた
k8sのラズパイクラスタを遊ばせていたので、k3sのクラスタを組んでみました。
構築手順
使ったもの
- raspberry pi model B+ ×3
- macbook pro 13inch 2015 ealry
- 5ポートモバイルバッテリー
- Wi-Fiルータ
- LANケーブル
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 PI ⇄ Wi-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 piにsshした後、以下のコマンドを実行します。およそ数分かかります。
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との違いなんかも少しずつ見ていこうと思います。
参考
みんなの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/sternはzshかbashのprofileに設定しておく
- KustomizeはHelmを使うほどではないが、GitOpsなどでYamlを管理するには便利すぎる
活用事例の所感
- Kubernetesでは難しいStatefulな部分は外部SaaSを積極的に活用する
- マルチクラウド・ハイブリッドクラウドの前に、まず一つのベンダにロックインしても使いこなす事が大切
- オンプレは大変。アプライアンスを使わずに自前でツールを作っている例(サイボウズ)もあったが、Kubernetesの中身まで知り使いこなすためにはそれ相応の覚悟と労力が必要
学ぶべき事
- Istio
- knative
- Helm/Kustomize
特にIstio(Envoy) + gRPCの仕組みはこれからどんどん主流になっていくと思うので、ここは抑えとかないといけないなぁ
CloudNativeDaysでも言ってたが、コンテナもk8sもクラウドも、自動化を進めていくためのツールの一つで、ツールを入れる事が目的であってはいけないですね
ES2018の糖衣構文に迷う
Nuxt.jsビギナーズガイドを読んでいるところですが、しっくりこなかったJSの糖衣構文に関してメモ。 糖衣構文は波括弧だったり、丸括弧だったり、角括弧だったりで混乱しますね。
- 波括弧・・・{...}
- 丸括弧・・・(...)
- 角括弧・・・[...]
アロー関数の糖衣構文
functionではなく=>で関数を記載することが可能。
export const state = () => ({ counter: 0 });
- 式のため、厳密にはセミコロンが必要
- 引数がひとつのときは丸括弧を省略できる
- 処理が1つの場合、returnと波括弧が省略できる
- returnを省略してリテラルを複数行書く場合は、丸括弧が必要
- exportをつけると、別ファイルからimportすることができる
引数分割束縛
関数の実引数に波括弧が利用される
increment ({ commit }) { commit('increment') }
本来であれば、contextを変数にもち、 以下のように記載する必要がある。
increment (context) { context.commit('increment') }
それを、分割代入した形となる。
({ commit })→({ commit } = context) →( commit = context.commit )
本来のコードを省略して書くことができるため、 Vuexでは多用されている。
importで波括弧がつくかつかないか
import { mapGetters, mapActions } from 'vuex' import Cookies from 'universal-cookie'
- export defaultとしたときは、波括弧は不要
- exportとしたときは、波括弧が必要
オブジェクトスプレッド
...obj、のように...をつけることで、配列でもオブジェクトでも要素を展開してくれる。
obj = { id: 1, user: 'name', data: 'test' } obj = { ...obj, data: 123 }
つらたん。