k8s source code reading #0 に行ってきた。

# TL;DR

+ Kubernetesのソースを読むきっかけとして、[k8s source code reading #0](https://k8s-code-reading.connpass.com/event/114427/)という勉強会にいってみた。
+ StatefulSetのプルリクをテーマにソースを読んでみた。
+ Goはあまり読めないけどテーマに集中して読んだら、収穫は確実にあった。


# k8s source code reading とは
[conpassのイベントページ](https://k8s-code-reading.connpass.com/event/114427/)に概要がありますが、今回は#0ということで、色々と進め方も議論しながらソースコード・リーディングをしてみた、という感じでした。

色々な勉強会を主催されていたり登壇されている方々が出席されており、メンバーの豪華さに一般人の私は少し気圧され気味でした。

そして、このグループの目標は日本からのコントリビュータを増やすこと、だそうです。
<blockquote class="twitter-tweet" lang="ja"><a href="https://twitter.com/cloudnativedays/status/1083687871977013248">k8s source code readingの目標！？ </a></blockquote>

## グループ分けの結果
初回ということで、自己紹介に加えて自分が読みたい箇所を一つあげて、それらをグループ分けしていきます。結果は以下のようになったのですが、kube-apiserverの人気が高かったです（テーブル2つ、10名弱）。

<blockquote class="twitter-tweet" lang="ja"><a href="https://twitter.com/y_taka_23/status/1083676769503178752">当日のグループ分け </a></blockquote>

私はStatefulSet周りを読みたかったということで「その他」のグループになりました。ちなみにその他は3人メンバーがいましたが、以下のようにテーマを持っていました。

+ eksctlを読みたい
+ kubeflow周りを読みたい
+ StatefulSetを中心にコントローラを読みたい（私）

# 私が読んでみたところ
[昨年末のアドベントカレンダーでも書いたのですが](https://qiita.com/tzkoba/items/946555fa62726edeb21a)、StatefulSetでノード障害時にポッドが移動されないという問題に対するプルリクがありました。このプルリク自体は却下されているのですが、何をしようとしていたものなのかは当時から理解したかったため、それを中心に読んでみることにしました。

対象のプルリクエストは[force deleting sts pods when nodes get lost](https://github.com/kubernetes/kubernetes/pull/54472/commits/f70cd8f11a8abe96a8d1e0c5cb35fe5d23a85ab2)というもので、StatefulSetのソースにいくつかの修正がされています。

## StatefulSetのソースはどこにあるか
ソースは以下になります。

+ [kubernetes/pkg/controller/statefulset](https://github.com/kubernetes/kubernetes/tree/master/pkg/controller/statefulset)

kubernetes/pkg/controllerには他にもdeploymentやdaemonなどのフォルダがあり、それぞれのコントローラのソースが置かれています。

## force deleting sts pods when nodes get lost #54472 の意図
このプルリクはノード障害を検知し、その上で稼動しているポッドを"force delete"することが目的です。そのため、下記モジュールの修正が根幹となります。

+ [pkg/controller/statefulset/stateful_set_control.go](https://github.com/kubernetes/kubernetes/blob/master/pkg/controller/statefulset/stateful_set_control.go)

このモジュールではStatefulSetの状態を変更する処理を担当しており、具体的には[```func \(ssc *defaultStatefulSetControl\) updateStatefulSet```](https://github.com/kubernetes/kubernetes/blob/master/pkg/controller/statefulset/stateful_set_control.go#L254)の中に処理が実装されています。

[#54472のプルリクではそのうちの条件分岐に手が入れられており](https://github.com/kubernetes/kubernetes/pull/54472/commits/f70cd8f11a8abe96a8d1e0c5cb35fe5d23a85ab2#diff-daa5b073ddfa8e3390bee583280edb5bR370)、PodがisFailedな時だけでなく、NodeLostの際にも[pkg/controller/statefulset/stateful_pod_control.goのDeleteStaefulPod](https://github.com/kubernetes/kubernetes/blob/master/pkg/controller/statefulset/stateful_pod_control.go#L136)が呼び出される（＝ポッドを削除する）ように修正されています。

さらにこの```DeleteStaefulPod```と呼び出し元にも修正がされており、PodのDelete時にオプションが渡せるようになっています。

```golang:pkg/controller/statefulset/stateful_pod_control.goの修正部分
# 修正前
func (spc *realStatefulPodControl) DeleteStatefulPod(set *apps.StatefulSet, pod *v1.Pod) error {
	err := spc.client.Core().Pods(set.Namespace).Delete(pod.Name, nil)

# 修正後
func (spc *realStatefulPodControl) DeleteStatefulPod(set *apps.StatefulSet, pod *v1.Pod, options *metav1.DeleteOptions) error {
	err := spc.client.Core().Pods(set.Namespace).Delete(pod.Name, options)
```

ここから先は[client-goの範囲](https://github.com/kubernetes/client-go/blob/master/kubernetes/typed/core/v1/pod.go)になるようで読めていないのですが、意図からして**pod.Spec.TerminationGracePeriodSeconds**を0で上書きするオプションを渡しているようです。これによって強制削除が可能となるのが、[#54472](https://github.com/kubernetes/kubernetes/pull/54472/commits/f70cd8f11a8abe96a8d1e0c5cb35fe5d23a85ab2#diff-daa5b073ddfa8e3390bee583280edb5bR370)のプルリクの詳細であると今回は理解しました（違っていたらすみません）。

# まとめ
StatefulSetのプルリクを中心にコードを追ってみましたが、仕様がコードベースで確認できるとやはり良いですね。私自身の課題として、そもそもKubernetesのkube-apiserverやController、client-goなどの関係を理解できていないことに気付きましたので、改めてその辺りを調べたいというモチベーションが湧いてきました。

Kubernetesについて何か知りたい・調べたいことがあれば、**k8s source code reading**、おすすめです。私は雰囲気でしかGoを読めませんし、そもそも書けませんが、そんなライトユーザでも学びがありました。

参加者の皆様、様々な情報の共有、ありがとうございました。
次回お会いできることを楽しみにしています。