kakakakakku blog

Weekly Tech Blog: Keep on Learning!

Kubernetes の YAML をカスタマイズする kustomize の基本を学べる Examples「helloWorld」

「Kubernetes 完全ガイド 第2版」「第14章 マニフェストの汎用化を行うオープンソースソフトウェア」を読んでいたら「第1版」では紹介されていなかった(正確には名前は載っていた)kustomize の解説が新しく追加されていた.本書を読みながら概要を理解したため,GitHub に公開されている kustomizeExamples を試しながら理解を深めていく.今回は「helloWorld」を試す.

github.com

前提

今回は Docker Desktop for Mac "Edge" を使って,以下の Kubernetes 環境で試した.kustomize コマンドは brew install kustomize で使えるようにした.なお,現在は kubectl と統合されて kubectl kustomize というコマンドも使えるけど,本書にコラムが載っている通り,バージョンが異なる.

$ kubectl version --short
Client Version: v1.18.6
Server Version: v1.18.6

$ kustomize version --short
{3.8.1  2020-07-16T05:11:04+01:00  }

Examples「helloWorld」とは?

kustomizeExamples「helloWorld」 は,kustomize の第一歩として,メタデータ関連のフィールドを更新したり,Overlay(オーバーレイ)を使って環境ごとにマニフェストを作ったり,リソースにパッチを適用する流れを学ぶ.さっそく試していく!

1. 事前準備

まず,作業ディレクトリを作って,変数 DEMO_HOME に設定しておく.手順書では mktemp コマンドを使っているけど,自由に変えられる.今回は自分用のマニフェストリポジトリにした.そして,もう1つ作っている base ディレクトリは,変換元になる「ベースマニフェスト」を置く場所として使う.

$ DEMO_HOME=~/helloWorld
$ BASE=${DEMO_HOME}/base
$ mkdir -p ${BASE}

次に GitHub に公開されているマニフェストを base ディレクトリにダウンロードする.tree コマンドの結果を見ればわかる通り,ConfigMap / Deployment / Service リソースのマニフェストをダウンロードする.もう1個は kustomize の設定ファイルとして kustomization.yaml もダウンロードする.kustomization.yaml に関しては後述する.

$ curl -s -o "${BASE}/#1.yaml" "https://raw.githubusercontent.com\
/kubernetes-sigs/kustomize\
/master/examples/helloWorld\
/{configMap,deployment,kustomization,service}.yaml"

$ tree ${DEMO_HOME}
~/helloWorld
└── base
    ├── configMap.yaml
    ├── deployment.yaml
    ├── kustomization.yaml
    └── service.yaml

2. kustomize build を実行する

ダウンロードした base/service.yaml の一部を以下に載せておく.base ディレクトリに置いてあるマニフェストを直接適用するのではなく,kustomize でビルドをするため,あくまで「ベースマニフェスト」になる.

kind: Service
apiVersion: v1
metadata:
  name: the-service
spec:
  selector:
    deployment: hello
  type: LoadBalancer
  ports:
  - protocol: TCP
    port: 8666
    targetPort: 8080

次に base/kustomization.yaml を確認する.構文として commonLabelsresources の概要を以下に載せておく.簡単に言えば「3種類のマニフェストに labelsselector を追加する」と言える.

  • commonLabels : ベースマニフェストに labelsselector を追加する
  • resources : kustomize build を実行するときに含めるリソースファイルのリストを指定する
commonLabels:
  app: hello

resources:
- deployment.yaml
- service.yaml
- configMap.yaml

さっそく kustomize build を実行すると,ビルドしたマニフェストが標準出力に表示される.今回は Service リソースを抜粋した.base/service.yaml と比較すると,新しく metadata.labels.appspec.selector.app が追加されている.

$ kustomize build ${BASE}

(中略)

apiVersion: v1
kind: Service
metadata:
  labels:
    app: hello
  name: the-service
spec:
  ports:
  - port: 8666
    protocol: TCP
    targetPort: 8080
  selector:
    app: hello
    deployment: hello
  type: LoadBalancer

(中略)

3. Overlay(オーバーレイ)を追加する

さらに kustomize の良さを学んでいくため,次はリソースにパッチを適用する「Overlay(オーバーレイ)」を試す.まず,overlays ディレクトリを作り,さらに overlays/staging ディレクトリと overlays/production ディレクトリを作っておく.

$ OVERLAYS=${DEMO_HOME}/overlays
$ mkdir -p ${OVERLAYS}/staging
$ mkdir -p ${OVERLAYS}/production

base ディレクトリと overlays ディレクトリの関係はザッと以下のようになる.このように構成することにより,共通的なマニフェストを base ディレクトリに置きつつ,環境ごとに異なる設定を overlays ディレクトリに置くことができる.kustomize 便利!

f:id:kakku22:20200817144209p:plain

次に overlays ディレクトリに置く「計4ファイル」を紹介する.

overlays/staging/kustomization.yaml

まず,staging 環境のための overlays/staging/kustomization.yaml を作る.新しく出てくる構文を紹介する.

  • namePrefix : リソース名の命名規則としてプレフィックスを追加する
  • commonAnnotations : ベースマニフェストに annotations を追加する
  • bases : resources と同じ(現在 bases は deprecated になっている)
  • patchesStrategicMerge : ベースマニフェストに適用する「パッチマニフェスト」のリストを指定する

よって,staging 環境ではリソース名に staging- プレフィックスを付けたり,labelsselectorannotations を追加する.

namePrefix: staging-
commonLabels:
  variant: staging
  org: acmeCorporation
commonAnnotations:
  note: Hello, I am staging!
bases:
- ../../base
patchesStrategicMerge:
- map.yaml

overlays/staging/map.yaml

次に patchesStrategicMerge に指定していた overlays/staging/map.yaml を作る.これは「パッチマニフェスト」として使う ConfigMap リソースのマニフェストとなり,altGreetingenableRisky の設定値を登録している.なお,kustomizeConfigMap を組み合わせた configMapGenerator 構文に関しては次回の記事に載せる予定!

apiVersion: v1
kind: ConfigMap
metadata:
  name: the-map
data:
  altGreeting: "Have a pineapple!"
  enableRisky: "true"

overlays/production/kustomization.yaml

staging 環境と同様に production 環境のための overlays/production/kustomization.yaml も作る.production 環境ではリソース名に production- プレフィックスを付ける.なお,今回の例では ConfigMap のパッチは適用せず,Deployment のパッチを適用する.

namePrefix: production-
commonLabels:
  variant: production
  org: acmeCorporation
commonAnnotations:
  note: Hello, I am production!
bases:
- ../../base
patchesStrategicMerge:
- deployment.yaml

overlays/production/deployment.yaml

最後に overlays/production/deployment.yaml を作る.一般的に production 環境は staging 環境よりも Pod を多く起動するため,以下のマニフェストでは Deployment リソースの replicas10 に更新している.

apiVersion: apps/v1
kind: Deployment
metadata:
  name: the-deployment
spec:
  replicas: 10

最終的な構成を tree コマンドで確認すると,以下のようになる.

$ tree ${DEMO_HOME}
~/helloWorld
├── base
│   ├── configMap.yaml
│   ├── deployment.yaml
│   ├── kustomization.yaml
│   └── service.yaml
└── overlays
    ├── production
    │   ├── deployment.yaml
    │   └── kustomization.yaml
    └── staging
        ├── kustomization.yaml
        └── map.yaml

4. 環境ごとにマニフェストを適用する

Overlay の設定もしたため,最後にまた kustomize build コマンドを使って staging 環境と production 環境のマニフェストを確認する.今回はマニフェストを kubectl apply -f - にパイプすることにより,直接適用もする.

# staging
$ kustomize build ${OVERLAYS}/staging

$ kustomize build $OVERLAYS/staging | kubectl apply -f -
configmap/staging-the-map created
service/staging-the-service created
deployment.apps/staging-the-deployment created

# production
$ kustomize build ${OVERLAYS}/production

$ kustomize build $OVERLAYS/production | kubectl apply -f -
configmap/production-the-map created
service/production-the-service created
deployment.apps/production-the-deployment created

✅ プレフィックスを確認する

例えば ConfigMap を確認すると,リソース名に staging-production- が追加されている!

$ kubectl get configmaps
NAME                 DATA   AGE
production-the-map   2      5s
staging-the-map      2      20s

✅ アノテーションを確認する

例えば Pod を確認すると,アノテーションが追加されている!

$ kubectl describe pods staging-the-deployment-6cd65cfc7f-2lcts | grep Annotations
Annotations:  note: Hello, I am staging!

$ kubectl describe pods production-the-deployment-bb7fd8b65-29b52 | grep Annotations
Annotations:  note: Hello, I am production!

✅ ConfigMap のパッチを確認する

kubectl describe configmapsConfigMap の値を確認する.

$ kubectl describe configmaps staging-the-map
Name:         staging-the-map
Namespace:    default
Labels:       app=hello
              org=acmeCorporation
              variant=staging
Annotations:  note: Hello, I am staging!

Data
====
altGreeting:
----
Have a pineapple!
enableRisky:
----
true
Events:  <none>

altGreetingenableRisky の値を base/configMap.yaml と比較すると,staging 環境では値を書き換えられている!

Key base staging production
altGreeting Good Morning! Have a pineapple! Good Morning!
enableRisky false true false

✅ Deployment のレプリカ数を確認する

kubectl describe deploymentsDeployment のレプリカ数を確認する.production 環境ではレプリカ数を更新できている!

$ kubectl describe deployments | egrep 'Name:|Replicas:'
Name:                   production-the-deployment
Replicas:               10 desired | 10 updated | 10 total | 10 available | 0 unavailable
Name:                   staging-the-deployment
Replicas:               3 desired | 3 updated | 3 total | 3 available | 0 unavailable

5. リソースを削除する

手順には入っていなかったけど,試したらリソースを削除しておく.

$ kustomize build ${OVERLAYS}/staging | kubectl delete -f -
configmap "staging-the-map" deleted
service "staging-the-service" deleted
deployment.apps "staging-the-deployment" deleted

$ kustomize build ${OVERLAYS}/production | kubectl delete -f -
configmap "production-the-map" deleted
service "production-the-service" deleted
deployment.apps "production-the-deployment" deleted

まとめ

「Kubernetes 完全ガイド 第2版」で解説が新しく追加されていた kustomize を試した.GitHub に公開されている Examples「helloWorld」kustomize の基本を学べてオススメ!なお,今回は kustomization.yaml の構文として以下を使った.詳しくはドキュメントを見てみてもらえればと!

  • bases
  • commonAnnotations
  • commonLabels
  • namePrefix
  • patchesStrategicMerge
  • resources

kubernetes-sigs.github.io

Kubernetes でバイナリを ConfigMap (binaryData) に登録する

今年の4月頃に「Kubernetes 完全ガイド」を読み終えたけど,まだ書評を書いていなかった.そしたら8月に「Kubernetes 完全ガイド 第2版」が出版されたため,さっそく購入して,読み直している.読みながら気になった機能を試していく.今回は ConfigMap にする.

Kubernetes完全ガイド 第2版 (Top Gear)

Kubernetes完全ガイド 第2版 (Top Gear)

  • 作者:⻘⼭ 真也
  • 発売日: 2020/08/07
  • メディア: 単行本(ソフトカバー)

ConfigMap (binaryData)

「第7章 : Config & Storage APIs カテゴリ」ConfigMap を読み直していたら,テキスト (UTF-8) だけではなく「バイナリ」を登録する内容が新しく追加されていた.拡張子 .jpg など画像ファイルを Base64 でエンコードして,nginx コンテナから HTML と画像ファイルを配信するというサンプルだった.今まで ConfigMap「バイナリ」を登録したことがなく,動作確認のために「Kubernetes 完全ガイド 第2版」を参考にしながら試した.なお,今回試した Kubernetes 環境は以下の通り.

$ kubectl version --short
Client Version: v1.18.6
Server Version: v1.18.6

通常の Docker Desktop for Mac だと Kubernetes v1.16 になるけど,Docker Desktop for Mac "Edge" を使えば,Kubernetes v1.18 を使えるようになる.個人的には Edge を使っている.

docs.docker.com

ConfigMap を作成する

まず,マニフェストを書かずに kubectl create で直接 ConfigMap を作成する.今回は --from-literal オプションで HTML をテキストとして設定し,--from-file オプションで画像を設定している.画像のフィールド名は cat.png だけど,実際には白い猫アイコン (cat-white.png) を設定している.

$ kubectl create configmap sandbox-configmap-binary \
  --save-config \
  --from-literal=index.html='Hello, <img src="./cat.png">' \
  --from-file=cat.png=cat-white.png
configmap/sandbox-configmap-binary created

コマンド例はドキュメントにも載っている.

kubernetes.io

マニフェスト管理をする場合は,Base64 でエンコードをする必要はなく,kubectl create--dry-run オプションと --output オプションを追加すれば,マニフェストにリダイレクトできる.

$ kubectl create configmap sandbox-configmap-binary \
  --save-config \
  --from-literal=index.html='Hello, <img src="./cat.png">' \
  --from-file=cat.png=cat-white.png \
  --dry-run=client \
  --output=yaml > sandbox-configmap-binary.yaml

data フィールドと binaryData フィールド

リダイレクトした sandbox-configmap-binary.yaml を確認すると,以下のようにテキスト (UTF-8) の値は data フィールドに設定されて,バイナリは binaryData フィールドに設定される.なお,エンコードされた内容は長いので xxxxx と省略した.

apiVersion: v1
binaryData:
  cat.png: xxxxx
data:
  index.html: Hello, <img src="./cat.png">
kind: ConfigMap
metadata:
  creationTimestamp: null
  name: sandbox-configmap-binary

ConfigMap に変化はないけど,マニフェストを kubectl apply で適用しておく.

$ kubectl apply -f sandbox-configmap-binary.yaml
configmap/sandbox-configmap-binary configured

Pod を作成する

今度は ConfigMap を Volume マウントした nginx の Pod マニフェスト sandbox-configmap-binary-nginx.yaml を書く.目的としては nginx から ConfigMap に登録した index.htmlcat.png を配信できるようにする.

apiVersion: v1
kind: Pod
metadata:
  name: sandbox-configmap-binary-nginx
spec:
  containers:
  - name: nginx
    image: nginx:1.18
    volumeMounts:
    - name: config-volume
      mountPath: /usr/share/nginx/html
  volumes:
  - name: config-volume
    configMap:
      name: sandbox-configmap-binary

マニフェストを kubectl apply で適用し,ポートフォワードもしておく.

$ kubectl apply -f sandbox-configmap-binary-nginx.yaml
pod/sandbox-configmap-binary-nginx created

$ kubectl port-forward sandbox-configmap-binary-nginx 8888:80

さっそく http://localhost:8888/ にアクセスをすると,期待通りに index.htmlcat.png を表示できた.なお,白い猫アイコンと次に使う黒い猫アイコンは Icons8 から取得した.

f:id:kakku22:20200814214221p:plain

ConfigMap を更新する

今度は ConfigMap に登録した cat.png を 白い猫アイコン (cat-white.png) から黒い猫アイコン (cat-black.png) に変えて,マニフェストを適用する.

$ kubectl create configmap sandbox-configmap-binary \
  --save-config \
  --from-literal=index.html='Hello, <img src="./cat.png">' \
  --from-file=cat.png=cat-black.png \
  --dry-run=client \
  --output=yaml > sandbox-configmap-binary.yaml

$ kubectl apply -f sandbox-configmap-binary.yaml
configmap/sandbox-configmap-binary configured

ConfigMap を Volume マウントしている場合は,自動的に反映されるため,ブラウザを更新すると黒い猫アイコンに変わった.

f:id:kakku22:20200814214233p:plain

まとめ

8月に出版された「Kubernetes 完全ガイド 第2版」を読みながら ConfigMapbinaryData フィールドを試した.実際のワークロードでは画像を Base64 でエンコードする場面は少ないかもしれないけど,試せて良かった.引き続き,読み直していくぞ!

Kubernetes完全ガイド 第2版 (Top Gear)

Kubernetes完全ガイド 第2版 (Top Gear)

  • 作者:⻘⼭ 真也
  • 発売日: 2020/08/07
  • メディア: 単行本(ソフトカバー)

Redash v9 で採用されたジョブキューライブラリ RQ (Redis Queue) の基本機能を試した

Redash v9「ジョブキューライブラリ」として採用された RQ (Redis Queue) を試した.今までの Redash では Celery を使っていた.RQRedis を使って「ジョブ登録 (enqueue)」「ジョブ実行 (work)」の機能をサポートする.ドキュメントを読むと,多くの機能が実装されているけど,今回は基本機能にフォーカスした.

github.com

検証環境

今回は Docker Compose で検証環境を構築した.役割としては,大きく4種類あり,以下に載せておく.簡単に構成図も描いておいた.

  • enqueue コンテナ : ジョブ登録 (Python)
  • queue コンテナ : キュー (Redis)
  • worker1 コンテナ : ジョブ実行 (Python)
  • worker2 コンテナ : ジョブ実行 (Python)

f:id:kakku22:20200810083901p:plain

なお,検証環境を再現する場合は GitHub の sandbox-rq リポジトリを見てもらえればと!docker-compose.ymlenqueue.pyworker.py など,サンプルコードも全てコミットしてある.

github.com

1.「queue」コンテナを起動する

最初に queue コンテナを起動する.今回は RQ の Redis コマンドを確認するため,並行して queue に接続して redis-cli monitor を実行しておく.実行された Redis コマンドがストリーミングされるため,便利!

$ docker-compose up -d queue
Starting sandbox-rq_queue_1 ... done

2.「enqueue」コンテナを起動する

次に RQ のドキュメントの通りに,サンプルジョブ job.py を実装する.実装は簡単で count_words_at_url() 関数は requests を使って与えられた URL の文字数を返す.

import requests

def count_words_at_url(url):
    resp = requests.get(url)
    return len(resp.text.split())

python-rq.org

今度はジョブを登録をするために enqueue.py を実装する.同じくドキュメントのサンプルコードを参考にする.Redis に対するコネクションを作成したら enqueue() 関数を使ってジョブを登録する.引数には job.py に実装した count_words_at_url() 関数と引数となる URL を渡す.今回は kakakakakku blog の URL にした.RQ は非同期処理を前提にするため,もし結果を取得する場合は,数秒待機してから job.result で取得できる.

from rq import Queue
from redis import Redis
from job import count_words_at_url
import time

r = Redis(host='queue', port=6379, db=0)
q = Queue(connection=r)

job = q.enqueue(count_words_at_url, 'https://kakakakakku.hatenablog.com/')

time.sleep(5)
print(job.result)

動作確認をするために enqueue コンテナを起動する.

$ docker-compose up -d enqueue
Starting sandbox-rq_enqueue_1 ... done

redis-cli monitor の結果から,RQrq:queue:default キーにジョブをリスト型として RPUSH していることを確認できた.そして rq:job:${UUID} キーにはジョブ情報を HSET していることを確認できた.実際に HGET でキーの中身を見ると,以下のように enqueued_atstatusdescription を取得できた.

127.0.0.1:6379> LRANGE rq:queue:default 0 -1
1) "18d1bb26-4948-45f9-8195-0de1c06c395e"
2) "d391221d-7c31-4822-98ae-1e25be4306f4"
3) "dacbcd76-af61-4b91-8d95-6c702bd4d3ba"

127.0.0.1:6379> HGET rq:job:18d1bb26-4948-45f9-8195-0de1c06c395e enqueued_at
"2020-08-09T22:32:59.752159Z"

127.0.0.1:6379> HGET rq:job:18d1bb26-4948-45f9-8195-0de1c06c395e status
"queued"

127.0.0.1:6379> HGET rq:job:18d1bb26-4948-45f9-8195-0de1c06c395e description
"job.count_words_at_url('https://kakakakakku.hatenablog.com/')"

3.「worker」コンテナを起動する

最後にジョブ実行をするために,ドキュメントのサンプルコードを参考に worker.py を実装する.ポイントは Redis に対するコネクションを作成したら work() 関数でジョブを実行する.なお,実行結果は直接 Redis に HSET で更新される.

from redis import Redis
import rq
from rq import Connection, Worker

r = Redis(host='queue', port=6379, db=0)

with Connection(r):
    w = Worker(['default'])
    w.work()

なお,載せた worker.py を見るとわかる通り,ジョブに依存せず,汎用的な実装になっている.具体的には job.py をインポートせずに動く.仕組みとしては,RQ のドキュメントにも載っているけど,内部的には Python の pickle モジュールを使って,関数自体をシリアライズしている.pickle は今まで使ったことがなかった.

docs.python.org

worker1 コンテナと worker2 コンテナを起動して,常駐させておく.

$ docker-compose up -d worker1 worker2
sandbox-rq_queue_1 is up-to-date
Recreating sandbox-rq_worker2_1 ... done
Recreating sandbox-rq_worker1_1 ... done

4. 動作確認をする

最後に全体を連携させながら動作確認をする.enqueue コンテナに -d オプションを付けずにフォアグラウンドで実行すると,5秒後に「5649文字」を取得できている.

$ docker-compose up enqueue
sandbox-rq_queue_1 is up-to-date
Starting sandbox-rq_enqueue_1 ... done
Attaching to sandbox-rq_enqueue_1
enqueue_1  | 5649
sandbox-rq_enqueue_1 exited with code 0

まとめ

Redash v9「ジョブキューライブラリ」として採用された RQ (Redis Queue) の基本機能を試した.pickle モジュールを使って,関数自体をシリアライズして「ジョブ登録 (enqueue)」をしている仕組みなのは興味深かった.ドキュメントを読むと,RQ にはまだまだ他に機能があり,引き続き試していく.

  • プライオリティ
  • タイムアウト
  • リトライ
  • スケジューリング
  • 監視
  • etc

関連記事

RQ (Redis Queue) を使った「Redash v9.0.0-beta」の紹介記事は以下にある!

kakakakakku.hatenablog.com

最近 Cyber-Dojo に導入された「実行結果予測 : predict?」機能

環境構築に悩むことなく「テスト駆動開発」「モブプログラミング」を試すときに「Cyber-Dojo」をよく使う.一部は Cyber-Dojo Blog にも載っているけど,今年4月頃(時期は少し曖昧)から「Cyber-Dojo」に新機能と機能改善がリリースされている.代表的な新機能を紹介する.

なお,本記事は「2020年7月30日 (木)」に書き終えたけど,なんと「2020年8月1日 (土)」「2020年8月2日 (日)」にリリースがあり,紹介する新機能のデザインがさらに変わった!本記事の最後に最新リリースのキャプチャも載せておく😇

cyber-dojo.org

1. 実行履歴で最初と最後に飛べるようになった

今までは「信号🚥」をクリックする以外だと をクリックして順番に遡る機能しか提供されていなかった.以下のキャプチャの通り,もう1個 が追加されたことで,すぐに「最初」「最後」の実行履歴を確認できるようになった.

f:id:kakku22:20200801093246p:plain

2. 実行履歴で「チェックアウト」と「フォーク」ができるようになった

今までは「実行履歴」を確認する機能しか提供されていなかった.新機能「チェックアウト (checkout)」を使うと,選んだ「信号🚥」の状態から実装できる.試行錯誤した過程を一度捨てて,やり直すときなどに使える.便利!

f:id:kakku22:20200801093258p:plain

さらに新機能「フォーク (fork)」を使うと,選んだ「信号🚥」の状態から新しくエクササイズを作れる.例えば,モブを分割して複数のアイデアを同時並行的に試したり,使いたくなる場面もありそう!

f:id:kakku22:20200801093310p:plain

3. エディタの背景色を変えられるようになった

画面左上の theme? ボタンをクリックすると,エディタの背景色を「白 (light)」から「黒 (dark)」に変えられるようになった.隣の colour? ボタンをクリックすると,シンタックスハイライトを ON/OFF できる.colour? ボタンも今まではなかったけど,機能としてはあり,前は Highlight という名称だった.

f:id:kakku22:20200801093430p:plain

f:id:kakku22:20200801103907p:plain

4. 実行結果の信号を予測できるようになった

Cyber-Dojo を使って「テスト駆動開発」を教える場合,必ず「実行したらどういう結果になる?」という問いに答えてもらってから実行してもらっている.これは闇雲にトライアンドエラーをするのではなく,意思を持って実行してもらうためで,新機能 predict? ボタンを使うと,まさに「信号🚥」を予測してから実行できる.最高!

f:id:kakku22:20200801093446p:plain

さらに「予測結果(⭕の回数と❌の回数)」も集計される.「テスト駆動開発」predict? の組み合わせは本当に便利!

f:id:kakku22:20200801093501p:plain

新デザイン : 2020年8月1日 (土)

冒頭に書いた通り,本記事を書き終えた直後にリリースがあった.以下のように「設定アイコン」をクリックすると,今回紹介した theme?colour?predict? をまとめて設定できる settings ダイアログが表示されるようになった.

f:id:kakku22:20200801105016p:plain

新デザイン : 2020年8月2日 (日)

翌日にまたリリースがあり「設定アイコン」の位置が変わった.また feedbackhelp などは「情報アイコン」にまとまった.

f:id:kakku22:20200803071711p:plain

Cyber-Dojo Blog

blog.cyber-dojo.org

blog.cyber-dojo.org

関連記事

kakakakakku.hatenablog.com

モブプログラミングパターンを紹介した記事「Harvesting Mob Programming Patterns」を読んだ

Agile AllianceExperience Reports として公開されている記事「Harvesting Mob Programming Patterns: Observing how we work」を読んだ.本記事は「モブプログラミング」で遭遇する「振る舞い」「モブプログラミングパターン」として紹介している.モブプログラミングは何よりも「楽しさを増幅」する.しかし,実際にモブプログラミングを効果的に行うのは簡単ではなく,だからこそ「パターン」を知っておくことに意味がある.本記事を読んでいくと「あるあるー!」という「パターン」も多かったけど,名前を付けることに価値があると思う.今回は本記事の翻訳ではなく,読んだ個人的な感想をまとめる!

www.agilealliance.org

Pattern Map(パターンマップ)

まず,本記事に載っている「Pattern Map(パターンマップ)」を見ると,大きく「1. Mob Role(モブロール)」「2. Collaboration Pattern(コラボレーションパターン)」「3. Driving Pattern(ドライブパターン)」の3種類に分類されていて,それぞれにパターンが紐付いている.「計18パターン」のサマリーは筆者の GitHub リポジトリにも載っている.日本語は参考程度にしてもらえればと!なお,本記事で紹介されているパターンに ✅ を付けておいた.

  • 1. Mob Role(モブロール)
    • Facilitator(ファシリテーター)✅
    • Recorder(レコーダー)✅
    • Researcher(研究者)
    • Navigator(ナビゲーター)
    • Driver(ドライバー)
    • Devil’s Advocate(悪魔の代弁者)
  • 2. Collaboration Pattern(コラボレーションパターン)
    • Punch List(パンチリスト)✅
    • Splinter Group(破片グループ)
    • Ridin’ Shotgun(助手席に乗る)✅
    • Mute your mic(マイクをミュートにする)✅
    • Fight Club(ファイトクラブ)
    • Natural Swap(自然なスワップ)
    • Forced Swap(強制的なスワップ)
    • Distracted non-Participant(注意散漫な非参加者)
  • 3. Driving Pattern(ドライブパターン)
    • Thinking Out Loud(大声で考える)
    • Tell me what to write(何を書くのか教えて)✅
    • Driving on Autopilot(自動操縦で運転する)
    • Plowing Through(切り開いて進む)✅

github.com

1. Mob Role(モブロール)

まず「Mob Role(モブロール)」とは,名前の通り「モブプログラミング中の役割」を意味する.一般的には「ドライバー」「ナビゲーター」をイメージすると思う.本記事を読むと「気付かずに他の役割も兼任していること」に気付かされる.計6種類ある役割の中で,本記事では「ファシリテーター」「レコーダー」の2種類が紹介されていた.

🔵 Facilitator(ファシリテーター)

モブプログラミングに集中したり,正しく前進したり,作業時間が伸びているときに中断したり,モブプログラミング中にアドバイスが必要な場面がある.具体的には「休憩を取ろう!」「モブを分割して進めよう!」など.このように,モブプログラミングに参加しながら「客観的な視点で提案をする役割」「ファシリテーター」と言う.モブプログラミングを導入した序盤は僕自身がファシリテーターを担当することが多かったけど,慣れてくると全員がファシリテーターを担当できるようになっていたように思う.1番重要なのは「特定のナビゲーターにファシリテーターを担当してもらう」のではなく,モブプログラミングの「流れ」で,自然に「誰かが」ファシリテーターを担当していたという状態を目指すことと言える.

🔵 Recorder(レコーダー)

モブプログラミング中に設計をしたり,意思決定が必要な議論をするときに,モブプログラミングだからこそ意思決定を素早く行えるけど,必要最低限のドキュメントはある.本記事では ADRs (Architecture Decision Records) が紹介されていたけど,簡単に言えば「チームに必要な決定事項をまとめたドキュメント」となる.モブプログラミング中にドキュメントを書く役割を「Recorder(レコーダー)」と言う.モブプログラミングに参加しながら「レコーダー」を担当するのは難易度が高いように感じるけど,とても重要な役割だと思う.当然ながら「議事録担当」のように「レコーダー」を担当すれば「自分の居場所が確立されている」という意味ではないため,勘違いしないように!本記事には書いてなかったけど,例えば「ドキュメントをレビューするモブセッション」をするなど,レコーダーに負荷を偏らせずに進めることもできる.

adr.github.io

2. Collaboration Pattern(コラボレーションパターン)

次に「Collaboration Pattern(コラボレーションパターン)」とは,名前の通り「モブプログラミング中にコラボレーションを高めるパターン」を意味する.単純にドライバーとナビゲーターが実装をするだけではなく,ちょっとした「パターン」を適用すると効果的だと思う.

🔵 Punch List(パンチリスト)

モブプログラミング中に実装するとしても「アプローチ(実装の順番)」はメンバーによって異なる.例えば,最初からモジュール化をする人もいれば,全体を実装してから細かく分割する人もいる.ようするに実装を始める前に「アプローチ(実装の順番)」をタスクリストとして明確に整理しておくことを「Punch List(パンチリスト)」と言う.本記事を読むと,プライオリティ付きのタスクリストだけではなく,ホワイトボードを使ったグラフィカルなタスクリストも紹介されていた.やはり,ホワイトボードに図解することにより,コラボレーションも高められると思う.

🔵 Ridin’ Shotgun(助手席に乗る)

次は「アンチパターン」の紹介で「Ridin’ Shotgun(助手席に乗る)」と言う.別名としては「Dominate the Mob(モブを支配する)」とも言う.昔話として,馬車で移動するときに手綱を引く人は両手がふさがってしまうため,敵から身を守るために助手席に用心棒を雇っていたという話のメタファーになっている.ようするに「特定のナビゲーターばかり喋っている」というアンチパターンのことを意味している.短期的な効果はあるかもしれないけど,参加できないナビゲーターも増えてしまうため,長期的にはマイナスとなり,避けるようにする.

🔵 Mute your mic(マイクをミュートにする)

1個前で紹介した「Ridin’ Shotgun(助手席に乗る)」のパターンに当てはまっている場面など,多くのナビゲーターがうまくモブプログラミングに参加できてなく沈黙が続いている場合は,効果的なディスカッションにならないため,よく喋るナビゲーターに「意図的に数分間マイクをミュートにしてもらえないか?(もしくは喋らずに見ててもらえないか?)」「ファシリテーター」から提案する.本記事では「気まずい沈黙 (awkward silence) はコラボレーションを促進する」と書いてあり,とても良い表現だと思った.

なお「マイクをミュートにする」のは,モブプログラミングから離脱するという意味ではなく,例えば「レコーダー」「Researcher(研究者)」など,他の役割に専念することもできる.チームが前進するために必要な情報を調査する役割を「Researcher(研究者)」と言う.前に読んだ「モブプログラミング・ベストプラクティス」では「タイムボックス付きの探求」という表現になっていて,どちらも似ている.

kakakakakku.hatenablog.com

3. Driving Pattern(ドライブパターン)

最後に「3. Driving Pattern(ドライブパターン)」とは,タイピストとも呼ばれる「ドライバーの振る舞い」を意味する.

🔵 Plowing Through(切り開いて進む)

ドライバーはナビゲーターのアドバイスで作業を進めていくことに価値があるはずなのに,ドライバーが「勝手に1人で」作業をどんどん進めてしまう場面は少なからずあると思う.そういうドライバーの振る舞いを「Plowing Through(切り開いて進む)」と言う.「耕す」という翻訳も選択肢にあったけど,個人的には「切り開いて進む」が良いと思った.

ドライバーが勝手に進めてしまうと,ナビゲーターのアドバイスが採用されなかったり,チームでコードを理解する機会が得られないため,基本的はアンチパターンと言える.よって,ファシリテーターに注意してもらう.しかし,必ずしもアンチパターンであるというわけではなく,納期が厳しかったり,とにかく完了することに価値があったり,専門家の作業を見て学んでもらいたい場合には有効だと本記事には書いてある.そのときには「Thinking Out Loud(大声で考える)」と言うパターンを使って,ドライバーの思考を喋りながら進めてもらう.過去にチームで新しいプログラミング言語を採用したときは,詳しいメンバーに喋りながらドライバーをしてもらったこともあり,実体験としても重要だと感じる.

🔵 Tell me what to write(何を書くのか教えて)

実装をするときに必要になるコンテキスト(業務知識やモジュール構成など)を詳細に知っているメンバーがチームに数名しかいなかったりすると,モブプログラミングを進めたくても,正しい方向に進められないという不安もある.そのときはドライバーが「コードはどこにあるー?」「どのクラスの責務なのー?」「どのようにテストをすれば良いのー?」など,とにかく積極的にナビゲーターに質問をすることが重要で,この振る舞いを「Tell me what to write(何を書くのか教えて)」と言う.どこに向かっていくのかが明確になれば,うまく進めていくことができる.ドライバーに限らず,ナビゲーターも理解ができなかったら,遠慮なく「待って!」と言うべきだと思う.

まとめ

「Harvesting Mob Programming Patterns: Observing how we work」を読んだ.「1. Mob Role(モブロール)」「2. Collaboration Pattern(コラボレーションパターン)」「3. Driving Pattern(ドライブパターン)」にうまく分類されているし,実体験としても「あるあるー!」と感じられる点も多く,とても良かった.本記事には詳しく載っていなかった「Researcher(研究者)」「Splinter Group(破片グループ)」「Thinking Out Loud(大声で考える)」も個人的に重要だと思っているので,全パターンが詳細に解説されている記事があったら嬉しい!「モブプログラミングパターン」に興味があったら読んでみると良いのでは!

www.agilealliance.org

関連記事

最近は「リモートモブプログラミング」の話題も増えてきた.以下の記事を合わせて読んでもらえると参考になるはず!

kakakakakku.hatenablog.com