新卒2年目のエンジニアが、急速に拡大していく組織の中で取り組んでいる、強い思いを持った強いチームづくり

Regional Scrum Gathering Tokyo 2020のプロポーザルをもういっこ出しました。僕が聞きたい話を出したいなと思って。僕の好きな2人と一緒にプロポーザルを出しました。もし、聞いてみたいな、と思ってくれた方は是非投票をお願いします!ページ開いたところのハートマークをポチッと。ログイン必要です。

confengine.com

## まっすぐな気持ち

2人には、それぞれのまっすぐな気持ちをぶつけてもらいたいなと思ってます。今日は、その2人のうちの1人を紹介。しゅんごさん。

テーマは「急速に拡大していく組織の中で取り組んでいる、強い思いを持った強いチームづくり」

## 組織は形を変える

僕がこの数年、色んなチームのサポートをしてきて感じたのは「組織って今の会社のフェーズに合わせて形を変えていくんだなぁ」ってこと。昨日までの自分の経験は、そのままでは今日の現場には活かせない。だから戸惑う。そういう感じなのかなって。

そんな風に、常に斜め上から飛んでくる何かを受け止めて、消化して、次の人たちに渡していかなきゃならないような現場にいながら、いい笑顔でみんなを癒やしてくれてるのが、新卒2年目のしゅんごさん。

## いい流れの中心にいる

彼は特に急速に成長して急速に拡大している組織にいて。だから、気を抜くと大きな混乱に飲み込まれてしまいそうで、僕はそれをちょっと離れたところから「大丈夫かなぁ?」と思って見てた。のだけど、気づいたら、なんか彼を中心にしていい流れができてる。

へー面白いなー!って思いながら見てたら、しゅんごさんから声をかけてくれて「今悩んでることがある。どんな風にチームづくりをしたらいいか相談に乗ってほしい」「というかスクラムについて聞きたい」って相談してくれた。

## スクラムチームづくり

「僕はこんな風に考えてチームづくりしてるよ」とか「あのチームはこんな風にやってるよ」とか、あーだこーだ話をしたら、「じゃあ、今の自分のチームではこの辺からやってみようと思う」って言って、まっすぐ前を向いて、1つずつ取り組んで、その結果を自分たちで分析して、「ここが良かった」って笑顔で教えてくれて、その次の課題を相談しにきてくれた。

色んなことが激しく変化し続けている組織の中で、全く誰もスクラムをやったことがなかったチームを引っ張って、今ではモブプログラミングも取り入れて開発に取り組んでるとのこと。

## 成長の傾き

去年初めて会ったときは「結構おとなしいのかな?」と思って見てたけど、しばらくして見てみたら、結構はっきり自分の考えを教えてくれるようになってて、んで最近は、純粋な目でまっすぐ前を向いてチームを引っ張ってて、なんか成長がすごい。

だから、僕は、彼の中の色んな変化とか、試行錯誤とか、何を考えて、何を難しいと思ったかとか、次に何をしようと思ってるかとか、そういうことを聞きたいなと思って、プロポーザルを一緒に出しました。

## プロポーザルを出しました

もし、聞いてみたいな、と思ってくれた方は是非投票をお願いします!ページ開いたところのハートマークをポチッとお願いします!

confengine.com

マルチゾーンのPrivate GKEクラスターを作成してNodePortにLBからつないで公開

慣れたら全部で30分かからないぐらいかな。といってもほぼ待ち時間で、GKEの生成を待ってるのに5分ぐらいで、最後の証明書の生成の待ち時間が15分ぐらい。

## 前置き

Private GKEクラスターを立ててみる。まだ、ちゃんとProductionレベルで動かすような設定は勉強してないので、とりあえずおもちゃみたいな気分で。

GCP周りの操作はgcloudとかTerraformとかを使えば良さそうだなーとは思うけど、今回はGUIでやってみることにする。Terraformとかはまた別で勉強しとく。

LoadBalancerはk8sからはコントロールせずに自分で作ろうと思う。なのでk8sはNodePortまでにしておく。LBのライフサイクルはk8sから切り離して考えたいなと思って。

SSLの証明書はGoogleに管理してもらう。

## 準備

  • プロジェクトを適当な名前で新しく作成した buffering-20190901。最後にプロジェクトごと削除したいから。
  • Google Cloud SDKがインストールされてる(gcloudとkubectl使う)
  • 課金を有効にしてる

## 手順

こうかな。

  1. VPCを作る
  2. GKEを作る
  3. Cloud NATを設定する
  4. サンプルアプリをGKEにデプロイする
  5. LoadBalancer用にFirewallを設定する
  6. LoadBalancer用にStatic IPを作成する
  7. Cloud LoadBalancerを作る

## 1. VPCを作る

デフォルトで作成されてるVPCは使わないので削除した。新しく my-vpc って名前のVPCを作成して、Custom Subnetを東京リージョンに作った。Private Google AccessはOnにしておいた。

f:id:bufferings:20190901085858p:plain

## 2. GKEを作る

Highly available のテンプレートから作った。

f:id:bufferings:20190901094106p:plain

  1. 左側から「Highly available」のテンプレートを選択
  2. 名前を my-gke にした
  3. Regionが us-central1 になってるので asia-northeast1 にした
  4. Number of nodes (per zone)が 3 になってるので 1 にした。合計で3台動くことになる
  5. 下の方にある「Availability, networking, security, and additional features」の部分をクリックして広げて
    1. さっき作成したVPCが選ばれてることを確認
    2. 「Private cluster」にチェックを入れた
    3. 「Master IP range」には 172.16.0.0/28 を入れておいた
    4. 「Enable master authorized networks」に、Masterへのアクセスを許可するIPを設定した方が良いとは思うんだけど、今回は別にいっかと思ってチェックを外しておいた。
    5. 「Stackdriver」の「Enable Stackdriver Kubernetes Engine Monitoring」をチェックしておいた(分かってない)
  6. 「Create」をクリック

これで、5分くらい待てばRegionalでAutoscalingなPrivateクラスターができる。

  • Regionalだと、MasterもNodeも複数Zoneに分散した構成になる。
  • Autoscalingを有効にすると、NodeのCPU使用率とかによって自動でScale Out/InしてくれるNodePoolになる。
  • Privateクラスターは、NodeにGlobalIPを持たせないので外部からのアクセスができない。MasterはGoogleのネットワーク側で管理されていて、外部からのアクセスが可能。

Privateクラスターだと、NodeがGlobalIPを持っていないので、このままだとNodeから外部へのアクセスもできない。ので、Cloud NATを設定する。

## 3. Cloud NATを設定する

東京リージョンを選んで作成する。Cloud Routerがコントロールプレーンとして必要らしいので作成する。

f:id:bufferings:20190901094746p:plain

## 4. サンプルアプリをGKEにデプロイする

これで、GKE上にアプリをデプロイできるので、サンプルアプリをデプロイする。サービスは最初に書いたとおり、NodePortにする。

gcloudでログイン

$ gcloud auth login

GKEのクレデンシャルを取得。リージョンやプロジェクト名は gcloud config で設定してもいい。

$ gcloud container clusters get-credentials my-gke \
    --region asia-northeast1 --project bufferings-20190901

これでkubectlがGKEにつながるようになる。

$ kubectl get node
NAME                                       STATUS   ROLES    AGE   VERSION
gke-my-gke-standard-pool-1-6f5f83d6-vzxn   Ready    <none>   55m   v1.12.8-gke.10
gke-my-gke-standard-pool-1-7cec640a-790g   Ready    <none>   55m   v1.12.8-gke.10
gke-my-gke-standard-pool-1-978f3a3c-6dbc   Ready    <none>   55m   v1.12.8-gke.10

サンプルのアプリをデプロイする。ファイル名は my-nginx.yaml でいいかな。NodePortには 31380 を指定しといた。自動でアサインしても問題ない。

apiVersion: v1
kind: Service
metadata:
  name: my-nginx-service
spec:
  type: NodePort
  ports:
  - name: http
    protocol: TCP
    nodePort: 31380
    port: 8080
    targetPort: 80
  selector:
    app: my-nginx
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: my-nginx-deployment
spec:
  selector:
    matchLabels:
      app: my-nginx
  replicas: 2
  template:
    metadata:
      labels:
        app: my-nginx
    spec:
      containers:
      - name: my-nginx
        image: nginx:1.7.9
        ports:
        - containerPort: 80

これを適用して

$ kubectl apply -f my-nginx.yaml
service/my-nginx-service created
deployment.apps/my-nginx-deployment created

作成されてることを確認したら

$ kubectl get svc,po
NAME                       TYPE        CLUSTER-IP     EXTERNAL-IP   PORT(S)          AGE
service/kubernetes         ClusterIP   10.201.0.1     <none>        443/TCP          43m
service/my-nginx-service   NodePort    10.201.1.148   <none>        8080:31380/TCP   9s

NAME                                       READY   STATUS    RESTARTS   AGE
pod/my-nginx-deployment-5796dcf6c4-bxjw8   1/1     Running   0          9s
pod/my-nginx-deployment-5796dcf6c4-rz87d   1/1     Running   0          8s

Port Forwardingで確認しておく

$ kubectl port-forward svc/my-nginx-service 8888:8080
Forwarding from 127.0.0.1:8888 -> 80
Forwarding from [::1]:8888 -> 80

これで、localhost:8888をブラウザで開くとnginxにつながる。

f:id:bufferings:20190901103304p:plain

## 5. LoadBalancer用にFirewallを設定する

k8s側でNodePortじゃなくてLBサービスを使えばFirewallも自動で設定してくれるんだけど、自分でLBを作るのでFirewallも自分で設定する必要がある。

### LB → NodePort

さっきNodePortを 31380 にしたからそこへのアクセスを許可する。

次のページに書いてあるように、LBからのアクセスは 130.211.0.0/2235.191.0.0/16 のレンジからのアクセスを許可する。

https://cloud.google.com/load-balancing/docs/https/#firewall_rules

TargetのTagは、既にGKE生成時に自動的に作成されている設定と同じものを入れておいた。

f:id:bufferings:20190901105035p:plain

### LB → Health Check

それともうひとつ、LBからNodeへのHealthCheckを許可しないといけない。これは各Nodeのポート 10256 でパスが /healthz で動いてるので、そこを通す。NodePortのやつに混ぜても良かったんだけど、別で作っておいた。

f:id:bufferings:20190901105618p:plain

## 6. LoadBalancer用にStatic IPを予約する

LB用なのでRegionalじゃなくてGlobalで予約する。

f:id:bufferings:20190901112812p:plain

「Reserve」ボタンを押すとIPが予約される。

今回僕が予約できたのは 35.244.157.110 だったので、これをLBから使う。LBを作成するときにHTTPSアクセスのための証明書を自動設定したいので、自分で持ってるドメインに登録しておく。

my-gke.shiiba.dev でこのIPアドレスを登録しておいた。

$ nslookup my-gke.shiiba.dev
Server:         127.0.0.53
Address:        127.0.0.53#53

Non-authoritative answer:
Name:   my-gke.shiiba.dev
Address: 35.244.157.110

## 7. Cloud LoadBalancerを作る

ということで、最後にLBを作る。種類は「HTTP(S) Load Balancing」

f:id:bufferings:20190901113700p:plain

LBはBackend、Rule、Frontendの3つの設定があって、Frontendがリクエストをインターネットから受ける部分、それをRuleで処理して、Backendに流す、という感じ。

BackendにGKEのNodePortを設定して、FrontendでSSLの設定をする。Ruleは特に設定せずに受けたリクエストを全部GKEに流すことにする。

### Backend

対象はInstance Groupで、PortはNodePortに指定した 31380

f:id:bufferings:20190901115243p:plain

Regional Clusterにしたので、各ZoneにInstance Groupが作られてる。なので、各ZoneのInstance Groupに対して同じ設定をする。

Backendに対するHealthCheckは新規作成する。これがPort 10256 で、パスが /healthz

f:id:bufferings:20190901115500p:plain

### Frontend

HTTPSのフロントエンドを作成する。IPアドレスには、さっき予約したIPアドレスを指定する。

f:id:bufferings:20190901120119p:plain

Certificateの部分で「Create a new certificate」を選んで、証明書の作成と管理をGoogleにやってもらうようにする。

f:id:bufferings:20190901120315p:plain

ドメインの部分にさっき設定しておいた my-gke.shiiba.dev を指定しておいた。これで「Let's Encrypt」の証明書発行などをGoogleがやってくれる。

### Create

全部終わったら、Createボタンを押して15分ぐらい待つ。LBが作成されて、証明書のStatusがACTIVEになってから、5分ぐらい待つと、つながるようになる。

f:id:bufferings:20190901122231p:plain

(∩´∀`)∩ワーイ

## プロジェクトを削除

楽しんだら忘れずにプロジェクトとDNSの設定を削除しておしまい!

状況をなんとかしたいときは一歩外に出てみる

自分が今いる状況をなんとかしたいなと思ったときは、その場で色々考えるんじゃなくて、自分が今いる場所から一歩外に出ると良さそう。

んで、外側で何がおこっているのかを眺めながら、あぁこういう流れだからこんな状況になってるのか、だったらこう動くと良さそうかなぁ、みたいなことを考えて、中に戻ってそういう行動をとると、わりとスムーズかな。

自分が今いる場所の中だけで考えてしまうと、その周りの力の流れに気づきにくいし、それに気づかないと周りの人のせいにしてしまいたくなる。それだと状況は変わりにくい。

開発メンバーのときはリーダーの場所まで行って見てみたり、リーダーのときはビジネスオーナーのところに立って見てみたり、娘が片付けをしないときは一緒になって散らかしてみたりとか(怒られる)、そんな感じ。

変化はできるだけ自然にポジティブに

この数年間は、エンジニアとして他のチームに入っていって、そのチームの改善をサポートする、という活動をしてる。

そういうときに自分が意識しているのは「自然とそうなるようにする」ということ。だって、それが例え良い変化だとしても、外からやってきた人から求められてする変化ってすごいストレスだから。

ここに行けたら良さそう、というのが自分には見えたとして、

f:id:bufferings:20190823234221p:plain

これが足りない、ああした方がいい、どうしてこんな実装なの?とか、そういうネガティブな指摘をしても、構えられるだけだし、相手のストレスになってしまうし、良いことない。

このチームってこういうところが良いね、あの部分は難しいのによくやってるね、みんなお互いに助け合ってるの良いね、とか、そういうポジティブな部分を伝えながら、できている部分を認めながら、ちょっとずつ前に進むのがいい。

色んなタイプの人やチームやマネージャーがいるから、それぞれに合ったやり方で、それぞれのペースで前に進むのがいい。ときには転んだり遠回りをしたりしながら、でも、お互いに支え合って、自然とゴールに向かって行ってるのがいい。

って、そんな風に思ってるんだなぁと自分のことを発見したのであった。それをもっと楽に実現するためには、色んなスキルをもっとアップしなきゃ。

今日もふわっとした話になってしまった。

## よかったらポチッと

「成長していく組織の中でテックリードとして僕はどう動くか」ってタイトルでRegional Scrum Gathering Tokyo 2020にプロポーザルを出してますー。もし、聞いてみたいなと思ってくれたらぜひ投票をお願いします!

confengine.com

組織のフェーズによって求められるものって変わっていくよなぁ

もう今の会社で10年目に突入してしまってた。こんなに長く働くと思ってなかったなぁ。しみじみ。この10年間でほんとに色んなことが毎年変わっていってて、幸せなことに僕はエンジニアとして色んなチームやサービスに関わらせてもらってきた。

そんな中で最近思うのは、組織のフェーズによって求められるものって変わっていくよなぁってこと。そこに、楽しさと、難しさがある。

特に、サービス立ち上げ期と、組織の拡大期では、求められるものが全然違うので、立ち上げ期のメンバーが組織の拡大期にマネージャーをやると悩みそう。だし、いい感じにやってる人たちはすごい。

以下、ふんいき。こんな感じする。全然まとまってなくてざざっと書くけど。

## サービス立ち上げ期

少数精鋭のメンバーが、持ってるスキルを存分に発揮してサービスの生き残りをかけて取り組むフェーズ。

寝ても覚めてもサービスのことを考えてるような人たちが、自分たちのやりたいことをできるだけはやく実現するためには何をしないといけないか、を自分で考えて自分で決断して前進する。そのために必要な技術があれば、自分で触りながら身につける。そんなフェーズ。

  • 全員が自分で考えて進めるので、すごいスピードで開発が進む。
  • サービスの開発や運用に対する当事者意識が高い。

そんな風にして全ての力をサービスの生き残りに注ぐため、削ぎ落とされているものも色々ある。

  • 人依存になってる。この部分はあの人が知ってる、この部分は別の人が知ってる。
  • ドキュメントは少ないか、なさそう。誰かの頭の中にしかないことが普通だろうな。
  • 機能の実現を最優先にするので、コードはあんまり綺麗じゃないことが多いと思う。

生き残らなければ意味がないので理解できる。

## サービスの成長期

立ち上げたサービスを成長させていくフェーズ。

人も増えてくる。立ち上げメンバーたちがリーダーになって、まだ手を動かしながら、新しく入ってきたメンバーを引っ張っていく。組織としての管理も始まる。

  • サービスは大きくなってるけど、まだまだスピード感はある。
  • リーダーが手を動かしながら指示を出して引っ張る。ので、そこにくらいついていくことで成長できる。
  • とがった人も入ってくる。立ち上げ期のメンバーよりスキルが高かったりして、システムがレベルアップしていく。
  • 技術的負債やクリーンコード、ドキュメンテーションをしっかり考えていこうよって話が出てくる。

その一方で、立ち上げ期と成長期のあいだのゆがみも出てくる。

  • 立ち上げ期のメンバーの考え方についていけないメンバーも出てくる。
  • 立ち上げ期よりは開発スピードが遅くなる。サービス規模や技術的負債や部署構成のために遅くなるのは当然のことだけど、立ち上げ期のメンバーがそれを理解できずに受け入れることができないでいたりすると良くない。「自分が開発してたころはもっとはやかった」みたいなの。
  • 自分で考えて行動することを求められるけど、指示はふわっとしてたりする。やった後に「そうじゃない」って言われるけど、それなら最初からそう言ってよ。って思ったりする。
  • とがった人たちがやっていることを周りが理解できなかったりする。中には、周りの人のことや、立ち上げ期のことを攻撃する人がいたりする。
  • 部署間の衝突も増えてくる。

このフェーズは、弱肉強食的に混沌としてるかもしれない。

## 組織の拡大期

サービスのさらなる拡大のために、組織を拡大していくフェーズ。

より多くの人が力を発揮していけるように変わっていく必要がある。立ち上げ期の文化からは完全に変わる。

  • 仕組みが整っていく。ドキュメント、プロジェクト管理、スキルアップ研修、ワークライフバランスなどなど。
  • 弱肉強食的なのは薄れて、スキルの高い人から、これから成長する人まで、色んな人が尊重されながら働けるようになる。
  • 技術的負債を計画的に返していく仕組みができてくる。

一方で

  • 開発スピードは遅くなる。でも、これが普通にあるべきスピードだったりする。
  • サービスに対する当事者意識は低くなる。
  • 触らないようにしてた立ち上げ期のシステムがそろそろ古くなってリプレースが必要になる。

組織としては安定してきて働きやすくなる。でも、その中でも挑戦をし続けるという文化を維持しないとすぐ組織もサービスも腐りそうで、それはそれでなかなか大変かもしれない。

## マネージャーの悩み

サービスの礎を築き上げた立ち上げ期のメンバーは、サービスの成長期でリーダーとして自分のやり方をメンバーに伝えながら結果も求められて、そこを乗り越えたと思ったら、組織の拡大期には自分と全く考え方の違うメンバーたちのことを尊重しながら同じ方向を向けるようなマネージメントを求められつつ、メンバーからは完璧を求められたりしてて、そりゃ悩むよね。という気持ちがある。

それと、成長期に入ってきたとがった人たちは、拡大期の「これから成長する人たち」を中心にした優しい文化は合わなくてやめていっちゃうかもしれない。

僕は、どのフェーズも良いところもあれば難しいところもあって、どれも面白いよなぁと思いながら見てる。

## そんなところも含めて

「成長していく組織の中でテックリードとして僕はどう動くか」についてお話したいなと思いました。ので、Regional Scrum Gathering Tokyo 2020にプロポーザルを出しました。もし、聞いてみたいなと思ってくれたらぜひ投票をお願いします!

confengine.com

ただ単に話を聞くだけっていうサポート

開発チームのサポートを依頼されて、ぼーっと眺めてたら「あぁ、これって、あの人の話を聞くだけで大丈夫だな」ってときがある。

それは、答えがその人の中にあるから。だけど、ふだんはそこにたどり着く前に攻撃されてるから守ってしまってたり。単に、本人も気づいていなかったり。

だから、話を聞きながら、そこにたどりつけば良いだけ。

やることは単純で

  • 相手の言うことを最後まで聞く
  • 気持ちや言葉を探してくれているときには待つ。「すみません」って言われたら「いえ、ゆっくりでいいですよ」って言って待つ。
  • 言ってくれたことに対して「でも」って接続詞でで返さない。自分だったらそうは考えないなと思ったとしても、それは今は関係ない。相手の気持ちや考えを否定しない。
  • 「そっか、そう思ったんですね。だから大変だったんですね」と「相手はそう感じた」という事実を受け入れる。
  • それを受け入れたあとに、それを一枚めくって聞く。「それはなぜですか?」

そんなことを繰り返して、5,6枚めくったところで答えがでてくる「じゃあ、それをやってみますか?」って聞くと「そうですね」ってなって、終わり。

ふわっとしてるけど。そういう感じ。

 

GKE with Istio Addon の情報を Stackdriver で確認

昨日はGKE with Istio Addonにmicroservices-demoをデプロイしてみた。

bufferings.hatenablog.com

今日は、そのデプロイしたアプリのモニタリングがどんな感じでできるんかなぁと思ってStackdriverを確認してみた。特に何も設定は触ってない。デフォルトでこういう風になってる。便利だなぁ。(わかってない

何を見たらいいかすら分かってないので、ここを参考にして見てみた。

Istio and Stackdriver - Google Cloud Platform - Community - Medium

## Metrics Explorer

StackdriverのMetrics Explorerを確認。"istio"とタイプするとIstioが送信してるMetricsが出てくる。へー。

f:id:bufferings:20190804112836p:plain

## Trace

分散トレーシングもあるのか。

f:id:bufferings:20190804113717p:plain

これ、microservices-demoがちゃんとトレースできるようなTrace IDとかSpan IDを送信してるってことかな。OpenCensus使ってるんかな。これも勉強しなきゃかな。

ふむふむ。あとでゆっくり読んでみよっと。

Stackdriver Trace (OpenCensus)を導入してみた

## Logging

ログも見ることができる。こんな風にして、Istioのproxyのログを選ぶと

f:id:bufferings:20190804114911p:plain

こんな感じで見える。へー。

f:id:bufferings:20190804114842p:plain

## 感想

便利(語彙

## この後

今の自分のBacklogはこうかな

  1. microservices-demoでVirtualServiceやDestinationRuleの設定を変えてみたりして遊ぶ(このあと忘れずにクラスターを削除する)
  2. Istioのドキュメントを読む。Traffic Management周りを中心に。たぶん、ここにめっちゃ時間がかかる。デフォルトでproxyにリトライが入ってそうなので見ておきたい。IngressGatewayとかMixerらへんがボトルネックにならないのかとか、落ちたりしないのかとかも気になる。
  3. Addonを使わずにGKEクラスターにIstioをインストールする。できればNodePortの設定で。Stackdriver周りもたぶん設定が必要なんだろうな。
  4. Istio + Spinnaker

今はやらない

  • IstioのmTLSとかFault InjectionとかCircuit Breakerを調べる
  • Stackdriverを色々触ってみる
  • Skaffoldの勉強
  • OpenCensusの勉強
  • microservices-demoの中を見てみる