ツナワタリマイライフ

日常ネタから技術ネタ、音楽ネタまで何でも書きます。

「Docker / Kubernetes 実践コンテナ開発入門」を読んだ

Docker/Kubernetes 実践コンテナ開発入門

Docker/Kubernetes 実践コンテナ開発入門

読んだ。雑に記録。

1-3章はDockerについて。ふむふむと軽く目を通した感じ。

ところでdocker containerコマンドって今まで使ったことなかったです。

で、4章と5章がSwarm。これまで使ったことなかった。

docker in dockerで、swarmのmanagerとnodeとregistryをそれぞれdockerの上に作って、そこでいろいろ遊ぶのはすごいうまくやってるデモだなぁと思った。

でも正直作者もいうとおりswarmはkubernetesにつなぐための布石でしかなくて、一応podだとかの概念の理解の助けにはなるとはいえ、面倒な部分、本番運用に耐えない部分を、そうそれを解決するんです〜って感じで、swarmを今後の人生で使うことはないなと思った。

あと動かすのにサンプルコードがgihyoさんのサイトからDLできたり、適宜githubからcloneしたりできるんだけどこれがとってもやりづらくて。gihyoさんからダウンロードするコードはディレクトリが章節ごとに細かくわかれすぎて面倒だったし、swarmのmanagerにいちいちコード送ってやらないといけないのも面倒だった(最初からしこんでおいてくれ)

で、swarmさんと最初で最後の出会いをしたところでkubernetes編。短いボリュームでリソースの概念をささっとさらえるし、これまで動かしてきたサンプルアプリも動くしで、とても良い例だと思った。

もちろんGKEも使ったけど、Docker for Mackubernetesがちゃんと動くじゃん!っていうのを体感したので、もうminikubeじゃなくていいね、と思った。

最後8章以降はロギングとかDockerホストの運用、チューニングとか障害対応とか。軽量なDockerイメージを作るモチベーションが個人的には今あんまりない。軽いにこしたことはないけど。

10章のDockerの様々な活用方法で、CLIツールをコンテナで入れるっていうの、それ、するかなぁって思った。bashで書くならgistにおいて使いたい人が使えばいいし、そうでなければGoで書いてgo getでええやんって思ったり。開発環境の構築をDocker(docker-compose)でやるのは賛成だけどね。

で、いろんなひとが書評に書いていたようにコラムが結構いい。何がよかったかは忘れたけど、コラムが読み物として楽しいのでまずコラムだけ読むぐらいでもいいかもしれない。

で、誰におすすめかというとDockerやKubernetes名前聞いたことあるけどあんまり何が嬉しいかわかってないしどう動くかもわかってない、って人にちょうどいいと思った。僕はKubernetesまわりの操作の復習のつもりで読みました。コラムが面白かった。

でもgihyoさんこれミスが多くて3件ほどフィードバック送りました。僕が読んでる時点で正誤表も盛りだくさんだったので校閲頑張ってほしいというお気持ちです。(本を書く大変さは想像でも死ねるし、進化の早いこの分野の作者の功績は大変大きく、リスペクトはあります、その上での意見です)

で、そうこうしてる間に青山さんのコレが届くのでまたすっと読もうかなと思います。

Kubernetes完全ガイド (impress top gear)

Kubernetes完全ガイド (impress top gear)

gitで複数のコミットをまとめるコマンド「qs」のv0.2.0をReleaseした

前回

blog.chaspy.me

した。

github.com

qsのまじめな解説はOwnerの@kamontiaが書いてくれている!

qiita.com

で、gihub-changelog-generatorで生成したCHANGELOGを眺めるに、まぁ前回のリリースの時に気になっていたことは結構消化できていて、まずはMVPというか、最低限でリリースして、あとで治すというのはとっても大事だなぁと思ったのでありました。

github.com

とはいえ、Goのコードが全然イケてない上にGoのテストをかけていないので、そのへんは次のリリースに向けて細々と変えていきたいところ。

で、このコマンド何か、というと、複数のコミットをまとめる、すなわちsquash/fixupするのを楽にするツールです。

branch切って、pushして、よっしゃreview依頼をアッーーーってなって1文字ミスってるやんけってなったとき、再度コミットして、git rebase -iしてfixupにするっていうのを一瞬でできるようになります。まぁ普通に自分でもわりと使っていて、自分が欲しいツールが作れて満足しています。go getで取れるのでみなさんぜひ使ってみてください。

github.com

2018年9月

なんか元気が出てきたからか急に忙しくなってきた予感がするので何するんだっけ何したいんだっけ本当にできるんだっけって感じでいったん書いて落ち着くということをしようと思う。

先月

8月、なんか元気が出てきたので目標達成ってことにしよう。

blog.chaspy.me

8月は特に目標を立てずにいこうと思う。まずは、通常営業、いつものペースを取り戻す。

イベントごと

  • 9/7-8 Builderscon 2018参加、フル参加はせず6,7割聴こうかなって感じ。

builderscon.io

  • 9/4〜18 とある翻訳書の翻訳レビューボランティア。刊行が決まったあとぐらいにあらためて何か書きます。SRE的にとっても関係のある内容なので、純粋に読める+翻訳に貢献できる/翻訳の難しさを体験できるので、win-winな感じ。

  • 9/16 isucon2018参加。社内で募集していて、こんな学びのチャンスはないと思いエイヤで挙手。楽しみだ。

isucon.net

ちなみにペアは9月に入社された @ujihisaと、同じく現職の@sat0yu。とても優秀なwevdev2人と一緒にできて幸せでしかない。SREとして強みを発揮しないといけないコンテストなので、何かしら貢献できるといいな。。。

  • 9/20 主催のクローズド勉強会でISUCONネタでLT
  • 同じく一緒に作ってるkamontia/qsについて@kamontiaが発表するので、その資料レビューと、あとv1.0.0のrelease。その前に9/7(今日だ!)にv0.2.0のrelease。

  • 9/27 弊社開催のMeguro.rbでLT。GitHubのアクティビティを振り返るために、簡単にレポートを生成するツールをRubyで作る予定。

絶対間に合わないけど読みたい本。

kubernetes復習。ささっと終えたい。

Docker/Kubernetes 実践コンテナ開発入門

Docker/Kubernetes 実践コンテナ開発入門

読み終えたけどまとめてないやつ。

CAREER SKILLS ソフトウェア開発者の完全キャリアガイド

CAREER SKILLS ソフトウェア開発者の完全キャリアガイド

なんかアーキテクチャ的なやつ。絶対読めないな。。。

進化的アーキテクチャ ―絶え間ない変化を支える

進化的アーキテクチャ ―絶え間ない変化を支える

Clean Architecture 達人に学ぶソフトウェアの構造と設計

Clean Architecture 達人に学ぶソフトウェアの構造と設計

手を動かしていこ。

複数のコミットをsquashするコマンド「qs(quick squash)」を作った

前回書いたこれ、がv0.1.0 releaseされた。

blog.chaspy.me

コマンド自体のまじめな解説は作者の@kamontiaが書いてくれてる。

qiita.com

このエントリではどちらかというとこのOSS作りで感じたことを中心に綴りたいと思う。

OSSを作ってリリースすること

実は、はじめてだ。今回も、collaboratorとして参加していて、自分1人で作ったわけでもない。

ただ散々OSSを利用しておいて、供給側にまわっていないということは、この業界にいながら罪悪感に近い引っかかりを得ていた。別のこのOSSがまだ誰かに使われたわけでもないが、大きな一歩だと思った。

モチベーションと作ったもの

github.com

はなから2人で作ろう、としてはじめたものなので、organizationのnamespaceでやってもよかったが、なんだか中途半端な格好になることを前回別の(挫折した)アプリで感じたので、今回はkamontia以下のnamespaceで作った。別にそこにこだわりは僕としてはない。

基本的にラフにpushして、CI通るまで細かくなおして、通ったらcommitをまとめてforce pushする、という開発スタイルでやることが多いので、わりとsquashする機会は多い。

自分が本当に欲しいものを作ることこそがOSS活動だと思うので、今回欲しいもの、作りたいテーマがうまく見つかったのが一番の幸運であり、リリースまでこぎつけた成功要因だと思う。

ちなみにまあ、普通に使える。

使用例

適当に1ファイル追加するコミットが4つあったとして、それをまとめたい。

$ qs -n 2 -d -m "squashed"
WARN[0000] [ 3] pickup -> pickup  9e94b2d fileA
WARN[0000] [ 2] pickup -> pickup  262207a fileB
WARN[0000] [ 1] pickup -> squash  a4bede9 fixup! fileB
WARN[0000] [ 0] pickup -> squash  fcdda5f fixup! fileB
Do you squash the above commits?(y/n)

-n 2はHEAD..HEAD~2をまとめるという意味だ。-dはdebug option。-mはsquashed commitのメッセージだ。-mがない場合まとめ先の262207aのメッセージが使われるようになる。

squashといいつつ、内部実装的にはfixupでまとめてからメッセージ変更をする擬似的なsqaushになっている。

結果はこうなる。

$ git log --oneline
0cbbd9d (HEAD -> master) squashed
262207a fileB
9e94b2d fileA

gitはまぁ使いはじめて長いが、いまだにrebase時の順番とlogの順番が逆なのは結構気にくわないし毎回混乱している。慣れない。

複数人開発

とはいっても2人だけど。

開発はissueとPRベースで進めた。別にissueはなくてもいいが、あとあとlabelとかで整理する意味であったほうがいい気がしたのであえて採用した。わりとこれいるんじゃない?と思いつくと、slackに発言してpin、気づいたひとがissueを立てる。(備忘をかねている)そしてPRでrefarenceして実装、review、mergeという流れだ。まぁ、きっと一般的な開発フローだと思う。

現職で上司との1on1で「レビューって案外重要なんですよね、他の人のブロッカーになるから」ということを聞いて、確かにそうだなぁと思った。今回、2人だからこそ意識的にPRのレビューは素早くすることを心がけた。だいたい1日に2回はチェックする時間を作って、うまくいけば半日以内にmergeできるサイクル感を目指した。

プロダクトとしても、個人としても、停滞はモチベーション下がるじゃない?initial commitは14days agoになっている。そこから100 commit、29のPRをまわせたのはなかなかよかったのではないかと思う、実際結構稼働はかけたけどね。それでも1日1h〜2hぐらいだし、夏休みで触ってない日もあるし。

反省点としては、初期で結構デカいfeatureを実装しているときに、テストの変更をしてしまって、そのケアに時間がかかってしまったことが悔やまれる。テストやるならやるで最初に同期して作ってしまってやる、ということをすべきだったなと思う。立ち上げからinitial commitまでリモートペアプロでやったのはよかったけど、そこからしばらくはパラレルにやらず、assignはするけど順番にやったほうがよかったのかなぁと思った

テスト

今回はgitという外部コマンドと連携するプロダクトなので、UnitTest(は、まだない)というよりはE2Eテスト的なものが必要だ。今回はそれをbashで実装した。

github.com

最初はひどいもんだったけど、release前にリファクタをして、マシにしたって感じ。

テスト1回ごとにディレクトリを作成し、git initからサンプルコミットを作って、qsコマンドを実行して、期待値と比較する、ことを繰り返す。テストフレームワークを自前で実装した感じ。このへんはrspecを普段はよく使うのでそのへんの印象で作っている。

テストの数は少ないが、これがあるとないとではかなり違う。最初の頃はそれこそ手作業でテスト用のgit履歴を作っていたから、はやめに取り掛かってよかったと思う。もちろん大好きで大嫌いなCircleCIを使っている。

Go言語

正直、雰囲気で選択したし、まぁ書いたが、Tour of GOを半端にやったぐらいで、何も身についたとは言えない。実際、今のコードはbashでできることを3倍ぐらいの行数をかけてGoで実装したようなもんで、Go言語である必要性はまったく活かせていない(し別に理解もしていない)状況だ。

ただ、便利なCLI toolのためのframework、codegangsta/cliには助かったし、go getで配れるのは本当に楽だよなぁと思うので、今のところ享受しているメリットはそのあたり。

今回v0.1.0はとりあえず動くものをリリース、次でリファクタの予定なので、しっかりGoを学んで「なんだこのクソコード」と思えるようになってからリファクタしたい。

おわりに

2週間で動く、(自分にとって)有用なコマンドを作れたのは、なかなかない成功体験だと思う。今回の成功要因はこんなところか。

  • プロジェクトのinitializeをリモペアで合意し、同期的にやれたこと
  • PR -> mergeサイクルを可能な限り高速化したこと
  • 作りたいものが決して技術の学習用、とかではなく、本当に自分たちが欲しいものであったこと

特に一番最後がもっとも大切なことだと思った。技術は、解決したい課題に対する、手段である、どこまでも。

ペアを組んだのは本当に気のおけない友人であることももちろん大きい。ありがとう。

feedback

わりと破壊的な変更をするコマンドなので、慎重に、といいつつ、まぁまぁ使えるんじゃないかなあと思うので、実際に使ってみて、feedbackをissueにくれるとうれしい。GitHubのissueでもtwitterのリプ/DMでも構いません。よろしくお願いします。

github.com

twitter.com

友人とOSSを作っている

まだ1st releaseまでこぎついてないので、キリのいいところでまたエントリーを書こうと思うけど、とりあえず今の段階で文章を書きたくなったので何か書く。

Go言語で、gitのsquashを自動化するCLIツールを作っている。

自分はよく、ブランチを切って、WIPでPR出して、CIが通るまでオラオラと修正を続けて、最後にコミットをまとめてPRのWIPをはずす、という方法で(業務でも)開発することが多い。そのときのsquashするためにrebaseしてエディタを開いてpickをsなりfなりに変更するのがめんどくさい、というのがモチベーションだ。

その友人とは、先月あたりから一緒に開発をしていて、その前は彼が練習用に作ったJavaのアプリを彼が借りたVPS上にCI/CDの整備と監視のお手伝いをした。Docker化したり。

で、第二弾としてサービスじゃなくて何かツール作りませんか、ということで今回。

現職では「できない」「失敗した」の連続で、「わからない」「だけどやらなきゃ」そして「また失敗した」「迷惑かけた」のループの中ですっかりメンタルが憔悴していて、業務外の自主学習も一切止まってしまった。そんな中、友人との開発ではちゃんと貢献できるので、それでなんとか自尊心を保っている感じだ。感謝。

ちゃんと(?)したOSS開発をしたことも、contributionしたこともないので、コードを書いて、それなりに動きそうなモノができそうなのは楽しみだ。現職にならってissueでネタを貯めたり議論して、PRで修正出す。英語で。というOSS開発ではもちろん当たり前だが、そういうことも実践できているのは、現職での経験のおかげだ。

この友人は大学の友人で、何年か前も一緒に作ろうとしたが、途中で頓挫してしまった。(細かい理由は忘れてしまった)だけど、今それなりにうまく続いているのは、タイミングというのもあるだろうが、お互いの技術力が当時よりは向上したとか、OSS開発のやりかたみたいなのをなんとなく身についたとか、そういうところがあると思っていて、強くなって再開した感があってなんだかうれしい。

学びや気づきはあって。開発に割ける時間がバラバラなので、テストや本体実装の大きな変更が、相手の開発に影響を与えたりしてよくないので、リズムとPRの単位に関しては適切じゃないシーンがぼちぼちあって反省だったり。 この規模で、わりとはやく出したい!というモチベーションが高い中で、PRが溜まってしまうと相手がbranchを切った時点での状態と乖離してしまってマージにrebase & conflict解消が必要でダルいとか。

悪いところだけじゃなくて、最初はVScodeのLiveShare機能を使って、リモートペアプロで最初のinitialなcommitまでを一緒にやれたのはすごいよかった。これ、週1ぐらいで何か1つの機能を作るとかやればよかったね。

と、まだ作り終えてないのに振り返りみたいなことをしてしまったが、はじめての経験なので完成が楽しみだ。

2018年7月振り返り

blog.chaspy.me

といっても、7月は全然目標達成できていない。あんまりまじめに振り返るつもりはないが、一筆書いておく。

前半はちょいちょいブログを書いてるように、また開発合宿とか言ってるぐらいなのでまだよかったが、後半はメンタルがしんでいた。

今はもっとも底にある状態からは少しはあがってきて、なんとか浮上できそうな感じなのでこうやって文を書いている。

認知の歪みが起きていた。

大好きな読書もしていなければ、ブログを書いたり、空いてる時間で技術学習もまったくしなかった。ひたすら止まらない歪んだ認知のループに、言い聞かせてなんとか暴走しないようにするので精一杯だった、という感じ。

8月は特に目標を立てずにいこうと思う。まずは、通常営業、いつものペースを取り戻す。

そのためには好きなことをしなきゃね、やっぱりね、と思っている。いや、それができなかったんだろーがって感じだけど。今は大丈夫。

ゆっくり、少しずつ、進もう。

helm installで"Error: no available release name found"

何が起きたのか

deisをサクっと試すのにチュートリアルをやっている。

Install Workflow - Deis Workflow Documentation

で、GKEのクラスタを準備して、helmをいれて、さぁdeisをdeployすっぞーというタイミングでエラー。

$ helm install deis/workflow --namespace deis
Error: no available release name found

解決策としてはこのへん

github.com

でやってみる

$ kubectl create serviceaccount --namespace kube-system tiller
serviceaccount "tiller" created
$ kubectl create clusterrolebinding tiller-cluster-rule --clusterrole=cluster-admin --serviceaccount=kube-system:tiller
clusterrolebinding "tiller-cluster-rule" created
$ kubectl patch deploy --namespace kube-system tiller-deploy -p '{"spec":{"template":{"spec":{"serviceAccount":"tiller"}}}}'
deployment "tiller-deploy" patched

$ helm init --service-account tiller
$HELM_HOME has been configured at /Users/take/.helm.
Warning: Tiller is already installed in the cluster.
(Use --client-only to suppress this message, or --upgrade to upgrade Tiller to the current version.)
Happy Helming!

成功。

$ helm install deis/workflow --namespace deis --set global.use_rbac=true
NAME:   austere-mongoose
LAST DEPLOYED: Mon Jul 23 01:59:04 2018
NAMESPACE: deis
STATUS: DEPLOYED

RESOURCES:
==> v1/Secret
NAME                   TYPE    DATA  AGE
minio-user             Opaque  2     3s
deis-router-dhparam    Opaque  1     3s
objectstorage-keyfile  Opaque  2     3s

==> v1/ConfigMap
NAME                  DATA  AGE
dockerbuilder-config  2     3s
slugbuilder-config    2     3s
slugrunner-config     1     3s

==> v1beta1/RoleBinding
NAME                   AGE
deis-builder           3s
deis-monitor-telegraf  3s
deis-router            3s

==> v1/Service
NAME                    TYPE          CLUSTER-IP    EXTERNAL-IP  PORT(S)                                                   AGE
deis-builder            ClusterIP     10.7.250.176  <none>       2222/TCP                                                  3s
deis-controller         ClusterIP     10.7.253.248  <none>       80/TCP                                                    3s
deis-database           ClusterIP     10.7.254.205  <none>       5432/TCP                                                  3s
deis-logger             ClusterIP     10.7.249.24   <none>       80/TCP                                                    3s
deis-minio              ClusterIP     10.7.251.113  <none>       9000/TCP                                                  3s
deis-monitor-grafana    ClusterIP     10.7.250.120  <none>       80/TCP                                                    3s
deis-monitor-influxapi  ClusterIP     10.7.245.126  <none>       80/TCP                                                    3s
deis-monitor-influxui   ClusterIP     10.7.248.97   <none>       80/TCP                                                    3s
deis-nsqd               ClusterIP     10.7.251.253  <none>       4151/TCP,4150/TCP                                         3s
deis-logger-redis       ClusterIP     10.7.255.161  <none>       6379/TCP                                                  3s
deis-registry           ClusterIP     10.7.245.229  <none>       80/TCP                                                    3s
deis-router             LoadBalancer  10.7.247.6    <pending>    80:30737/TCP,443:30975/TCP,2222:32153/TCP,9090:30151/TCP  3s
deis-workflow-manager   ClusterIP     10.7.246.247  <none>       80/TCP                                                    3s

==> v1/ServiceAccount
NAME                   SECRETS  AGE
deis-builder           1        3s
deis-controller        1        3s
deis-database          1        3s
deis-logger-fluentd    1        3s
deis-logger            1        3s
deis-minio             1        3s
deis-monitor-telegraf  1        3s
deis-nsqd              1        3s
deis-registry          1        3s
deis-router            1        3s
deis-workflow-manager  1        3s

==> v1beta1/ClusterRole
NAME                      AGE
deis:deis-builder         3s
deis:deis-controller      3s
deis:deis-logger-fluentd  3s
deis:deis-router          3s

==> v1beta1/ClusterRoleBinding
NAME                      AGE
deis:deis-builder         3s
deis:deis-controller      3s
deis:deis-logger-fluentd  3s
deis:deis-router          3s

==> v1beta1/Role
NAME                   AGE
deis-builder           3s
deis-monitor-telegraf  3s
deis-router            3s

==> v1beta1/DaemonSet
NAME                   DESIRED  CURRENT  READY  UP-TO-DATE  AVAILABLE  NODE SELECTOR  AGE
deis-logger-fluentd    2        2        0      2           0          <none>         3s
deis-monitor-telegraf  2        2        0      2           0          <none>         3s
deis-registry-proxy    2        2        1      2           1          <none>         3s

==> v1beta1/Deployment
NAME                   DESIRED  CURRENT  UP-TO-DATE  AVAILABLE  AGE
deis-builder           1        1        1           0          3s
deis-controller        1        1        1           0          3s
deis-database          1        1        1           0          3s
deis-logger            1        1        1           0          3s
deis-minio             1        1        1           0          3s
deis-monitor-grafana   1        1        1           0          2s
deis-monitor-influxdb  1        1        1           0          2s
deis-nsqd              1        1        1           0          2s
deis-logger-redis      1        1        1           0          1s
deis-registry          1        0        0           0          1s
deis-router            1        0        0           0          1s
deis-workflow-manager  1        0        0           0          0s

==> v1/Pod(related)
NAME                                    READY  STATUS             RESTARTS  AGE
deis-logger-fluentd-2nzb5               0/1    ContainerCreating  0         3s
deis-logger-fluentd-tdr9q               1/1    Running            0         3s
deis-monitor-telegraf-4flv9             0/1    ContainerCreating  0         3s
deis-monitor-telegraf-sscpr             0/1    ContainerCreating  0         3s
deis-registry-proxy-97cgs               0/1    ContainerCreating  0         3s
deis-registry-proxy-j2k2s               1/1    Running            0         3s
deis-builder-55bbd946bd-9srb5           0/1    ContainerCreating  0         3s
deis-controller-59c948dbd4-k7hxq        0/1    Pending            0         3s
deis-database-5875dcff85-6cl6t          0/1    Pending            0         3s
deis-logger-7445666f95-8w9wq            0/1    ContainerCreating  0         2s
deis-minio-64454c6bf6-cvpch             0/1    Pending            0         2s
deis-monitor-grafana-77d54db485-rdq48   0/1    Pending            0         2s
deis-monitor-influxdb-5fb56d489c-zn4c5  0/1    Pending            0         1s
deis-nsqd-649fbc4947-tjcwr              0/1    ContainerCreating  0         1s
deis-logger-redis-7fcc95cc5d-977tm      0/1    Pending            0         1s
deis-registry-554c5569db-zxcgb          0/1    Pending            0         0s
deis-router-98ccf5c64-466r5             0/1    Pending            0         0s

何をしたのか

そういえばhelm initを最初にしたときにこう言われている。

$ helm init
Creating /Users/take/.helm
Creating /Users/take/.helm/repository
Creating /Users/take/.helm/repository/cache
Creating /Users/take/.helm/repository/local
Creating /Users/take/.helm/plugins
Creating /Users/take/.helm/starters
Creating /Users/take/.helm/cache/archive
Creating /Users/take/.helm/repository/repositories.yaml
Adding stable repo with URL: https://kubernetes-charts.storage.googleapis.com
Adding local repo with URL: http://127.0.0.1:8879/charts
$HELM_HOME has been configured at /Users/take/.helm.

Tiller (the Helm server-side component) has been installed into your Kubernetes Cluster.

Please note: by default, Tiller is deployed with an insecure 'allow unauthenticated users' policy.
For more information on securing your installation see: https://docs.helm.sh/using_helm/#securing-your-helm-installation
Happy Helming!

TillerというHelmのServer側にあるコンポーネントは既にGKE上にインストールされてるよ。デフォルトだとallow unauthenticated usersを認めてないんよ。と言ってる。

やり方公式に載ってました。

github.com

Service Accountはkubernetesの認証方式の1つ。作成したservice accountにはsecretも一緒に作成されて、そのtokenを使ってclientはpodへアクセスすることができる。今回helm initで使うservice accountを明示することで、podのdeployが許可されたのだろう。

参考

qiita.com

⎈ Happy Helming!⎈