Kubernetes 1.17: SIG-Network の変更内容

## はじめに

ここでは、Kubernetes 1.17 の CHANGELOG から SIG-Network の取り組みについてまとめています。

- https://github.com/kubernetes/kubernetes/blob/master/CHANGELOG-1.17.md

## What's New (新情報)

SIG-Network に関する大きな変更はありません。

## Known Issues（既知の問題）

SIG-Network に関する既知の問題はありません。

## Urgent Upgrade Notes（必ず一読してからアップグレードしなければならない事項）

EndpointSlices がすでに有効なクラスタをアップグレードする場合、EndpointSlice コントローラにより管理されるべき EndpointSlices オブジェクトは、`endpointslice.kubernetes.io/managed-by` ラベルの値に `endpointslice-controller.k8s.io` と設定しておく必要があります。

- :memo: いったい何を言っているんだという感じですが、詳しくは [EndpointSlice API の KEP](https://github.com/kubernetes/enhancements/blob/master/keps/sig-network/20190603-EndpointSlice-API.md#additional-endpointslice-controllers) に記載があります
    - KEP が何を知りたい方は「[KEPから知るKubernetes](https://qiita.com/Ladicle/items/24cff72f5e8f4bd293a6)」を参照
- :memo: **まず、EndpointSlice は 1.16 時点でアルファであり、明示的に有効に設定していない限り上記の対応の対象ではありませんので安心してください**
- :memo: どうやら、EndpointSlices は高い拡張性を目指して EndpointSlice コントローラ以外によっても管理できる状態を目指しているようで、そのため「EndpointSlice コントローラにより管理されるべき EndpointSlices オブジェクト」という言い方がされているようです
- :memo: どのコントローラにより管理されている EndpointSlice オブジェクトなのかを示すために使われるのラベルが、`endpointslice.kubernetes.io/managed-by` であり、EndpointSlice コントローラを示す値が `endpointslice-controller.k8s.io` ということです
- :memo: 1.16 のアルファ時点では、すべての EndpointSlice オブジェクトが EndpointSlice コントローラにより管理されていたため、上記のラベルは付与されていませんでした。v1.17 ではこのラベルが有効になっているため、v1.17 にアップグレードする前に既存のすべての EndpointSlice オブジェクトに上記のラベルを設定しておく必要があります

:memo: 全てのネームスペースの全ての EndpointSlice オブジェクトに必要なラベルを設定するには次のコマンドを実行します。

```bash
for ns in $(kubectl get ns -o 'jsonpath={.items[*].metadata.name}'); do kubectl label endpointslice --all -n "$ns" endpointslice.kubernetes.io/managed-by=endpointslice-controller.k8s.io; done
```

## Deprecations and Removals (廃止および削除）

- デフォルトの service IP CIDR は廃止されました。以前のデフォルトであった `10.0.0.0/24` は2マイナーリリース（6ヶ月）で削除されます。クラスタ管理者は kube-apiserver の `--service-cluster-ip-range` フラグを使用して自身の望ましい値を指定しなければなりません ([#81668](https://github.com/kubernetes/kubernetes/pull/81668), [darshanime](https://github.com/darshanime))
- certificate signer は、`CFSSL_CA_PK_PASSWORD` 環境変数を介して ca.key のパスワードを受け付けなくなりました。 ([#84677](https://github.com/kubernetes/kubernetes/pull/84677), [mikedanese](https://github.com/mikedanese))

## Notable Features（主な機能）

### Beta（ベータ）

- EndpointSlices はベータになりましたが、まだデフォルトで有効にはなっていません。この機能を有効にするためには `EndpointSlice` feature gate を使用する必要があります ([#85365](https://github.com/kubernetes/kubernetes/pull/85365), [robscott](https://github.com/robscott))

## API Changes（API の変更）

- EndpointSlice の Port 名の検証が Endpoint の Port 名の検証と一致するように修正されました（15文字より長い Port 名を許可する） ([#84481](https://github.com/kubernetes/kubernetes/pull/84481), [robscott](https://github.com/robscott))

## Other notable changes（その他の主な変更）

- 公式の kube-proxy イメージ（とくに kubeadm で使用される）は、"nft" モードで iptables 1.8 を実行しているシステムと互換性を持つようになり、使用するモードを自動検出するようになりました ([#82966](https://github.com/kubernetes/kubernetes/pull/82966), [danwinship](https://github.com/danwinship))
- Kubenet は、IPv6 サポートが追加されました。HostPortManager は、1つの IP ファミリでのみ動作し、異なる IP ファミリのポートマッピングエントリを受け取ると失敗します。HostPortSyncer は、1つの IP ファミリでのみ動作し、異なる IP ファミリのポートマッピングエントリをスキップします。 ([#80854](https://github.com/kubernetes/kubernetes/pull/80854), [aojea](https://github.com/aojea))
- kube-proxy は、EndpointSlices と IPVS によるデュアルスタック機能をサポートしました。 ([#85246](https://github.com/kubernetes/kubernetes/pull/85246), [robscott](https://github.com/robscott))
- `externalTrafficPolicy=Local` で Service Topology を使用した際の冗長な API バリデーションが削除されました ([#85346](https://github.com/kubernetes/kubernetes/pull/85346), [andrewsykim](https://github.com/andrewsykim))
- github.com/vishvananda/netlink が v1.0.0 でアップデートされました ([#83576](https://github.com/kubernetes/kubernetes/pull/83576), [andrewsykim](https://github.com/andrewsykim))
- kube-controller-manager
    - `--node-cidr-mask-size-ipv4 int32` デフォルト: 24. デュアルスタッククラスタにおける IPv4 node-cidr のマスクサイズ
    - `--node-cidr-mask-size-ipv6 int32`  デフォルト: 64. デュアルスタッククラスタにおける IPv6 node-cidr のマスクサイズ
    - これらの2つのフラグは、デュアルスタッククラスタでのみ使用できます。デュアルスタックではないクラスタでは、マスクサイズの設定に `--node-cidr-mask-size` フラグを引き続き使用します。
    - IPv6 のデフォルトの node cidr マスクサイズは 24 から64 に変更されました ([#79993](https://github.com/kubernetes/kubernetes/pull/79993), [aramase](https://github.com/aramase))
- `cleanup-ipvs` フラグが廃止予定になりました ([#83832](https://github.com/kubernetes/kubernetes/pull/83832), [gongguan](https://github.com/gongguan))
    - :memo: kube-proxy のフラグです。
    - :memo: `--cleanup` を使用すれば IPVS のルールをフラッシュするという同様の効果があるようです
- kube-proxy は、v1alpha1 で不正な形式のコンポーネント設定ファイルが使用されると警告を発するようになりました ([#84143](https://github.com/kubernetes/kubernetes/pull/84143), [phenixblue](https://github.com/phenixblue))
- `config.BindAddress` が指定されていない場合、IPv4 アドレス `127.0,0.1` が指定されるようになりました ([#83822](https://github.com/kubernetes/kubernetes/pull/83822), [zouyee](https://github.com/zouyee))
    - :memo: kube-proxy の設定です。
- kube-proxy ipvs の README で、読み込まれている ipvs モジュールをリストするための grep 引数が誤っていたのが修正されました ([#83677](https://github.com/kubernetes/kubernetes/pull/83677), [pete911](https://github.com/pete911))
- kube-proxy の userspace モードは、実際には追加しているエンドポイントの削除に関するメッセージをログに落とさなくなりました ([#83644](https://github.com/kubernetes/kubernetes/pull/83644), [danwinship](https://github.com/danwinship))
- kube-proxy iptables の probability（ランダムにパケットがマッチする確率）はより粒度が細かくなり、結果として 319 endpoints を超えてよりよい分布になります ([#83599](https://github.com/kubernetes/kubernetes/pull/83599), [robscott](https://github.com/robscott))
    - :memo: これまで iptables `--probability` の値を小数点以下5桁で算出していたところを10桁で算出するように変更したことで、319 endpoints より多くの場合でランダムの精度がよくなるということのようです
- kube-proxy で UDP ではないポートに対して大幅なパフォーマンス改善が行われました ([#83208](https://github.com/kubernetes/kubernetes/pull/83208), [robscott](https://github.com/robscott))
    - :memo: kube-proxy 内の `detectStaleConnections` 関数は CPU 使用率の点で非常に高価だそうです。しかし、実際にはこの関数は UDP ポートでのみ使用されるそうで、そこでプロトコルを判定するようにして UDP 接続のみで処理が実行されるように変更したことで主に TCP 接続のみを使用するクラスタで kube-proxy のパフォーマンスが2倍に改善されるそうです（本当か？
- より効率的なソートにより EndpointSlice が有効な kube-proxy でパフォーマンスが改善されました ([#83035](https://github.com/kubernetes/kubernetes/pull/83035), [robscott](https://github.com/robscott))
- スケーリングにおいてよりよい Network エンドポイントパフォーマンスを提供する EndpointSlices がベータになりました ([#84390](https://github.com/kubernetes/kubernetes/pull/84390), [robscott](https://github.com/robscott))
- Service の PublishNotReadyAddresses を使用するように EndpointSlices が更新されました ([#84573](https://github.com/kubernetes/kubernetes/pull/84573), [robscott](https://github.com/robscott))
    - :memo: Service `.spec.publishNotReadyAddresses` フィールドは、NotReady なアドレスを公表する設定でデフォルトは `false` です。おもに Headless Service でエンドポイントの状態に関わらず SRV レコードにエンドポイントを含ませるために使用されます。
- EndpointSlices が有効なクラスタを 1.17 にアップグレードした際に、各 EndpointSlice は `endpointslice.kubernetes.io/managed-by` ラベルが設定される必要があります ([#85359](https://github.com/kubernetes/kubernetes/pull/85359), [robscott](https://github.com/robscott))
    - :memo: 詳しくは本エントリ上部「Urgent Upgrade Notes」を参照してください
- EndpointSlice は FQDN addressType サポートが追加されました ([#84091](https://github.com/kubernetes/kubernetes/pull/84091), [robscott](https://github.com/robscott))
- NetworkPolicy に特定の PolicyType が設定されていない場合にも、そのポリシで Pods が分離されることを示唆する誤った説明が修正されました ([#84194](https://github.com/kubernetes/kubernetes/pull/84194), [jackkleeman](https://github.com/jackkleeman))
    - :memo: `kubectl describe networkpolicy` の出力部分の修正です
- EndpointSlice コントローラが共有オブジェクトを変更しようとするバグを修正しました ([#85368](https://github.com/kubernetes/kubernetes/pull/85368), [robscott](https://github.com/robscott))
- EndpointSlices の IP address タイプを IPv4 と IPv6 に分割しました ([#84971](https://github.com/kubernetes/kubernetes/pull/84971), [robscott](https://github.com/robscott))
- EndpointSlice `Ports` フィールドに `appProtocol`フィールドが追加されました ([#83815](https://github.com/kubernetes/kubernetes/pull/83815), [howardjohn](https://github.com/howardjohn))
    - :memo: http や gRPC など、ポートで使用されるアプリケーションプロトコルを指定できるようにするフィールドで、任意の文字列が使用できます
    - :memo: 何に使うんでしょうね。KEP にも盛り込まれているので何やらユースケースがあるようですが :thinking: 
    - :memo: 2020/1/7 追記: KEP が作られました
        - [KEP: Adding AppProtocol to Services and Endpoints by robscott · Pull Request \#1422 · kubernetes/enhancements](https://github.com/kubernetes/enhancements/pull/1422)
- Docker コンテナランタイムは、コンテナのネットワーク操作で220秒のタイムアウトを強制するようになりました ([#71653](https://github.com/kubernetes/kubernetes/pull/71653), [liucimin](https://github.com/liucimin))
    - :memo: kubelet が CNI プラグインを呼び出すときにこれまでタイムアウトが設定されていなかったようです
- CNI プラグインで IPv4/IPv6 デュアルスタックモードで実行しているときに、kubelet が panic になる問題が修正されました ([#82508](https://github.com/kubernetes/kubernetes/pull/82508), [aanm](https://github.com/aanm))
- EndpointSlices hostname は、Endpoints hostname と同じ条件で設定されるようになりました ([#84207](https://github.com/kubernetes/kubernetes/pull/84207), [robscott](https://github.com/robscott))
    - :memo: この hostname は、`endpointslice.spec.subsets.addresses.hostname` フィールドのことです。
- Service のセレクタをキャッシュすることで、Endpoint と EndpointSlice コントローラのパフォーマンスを改善しました ([#84280](https://github.com/kubernetes/kubernetes/pull/84280), [gongguan](https://github.com/gongguan))
- スケーリングにおいて EndpointSlices を使用している際の kube-proxy のパフォーマンスが大幅に改善されました ([#83206](https://github.com/kubernetes/kubernetes/pull/83206), [robscott](https://github.com/robscott))

## 所感

諸事情で今回は SIG-Network も担当しました。普段そこまでしっかり把握していない SIG をみてみると知らなかったことがたくさんあって楽しいです。

多くは EndpointSlice、IPv4/IPv6 デュアルスタックの変更でした。EndpointSlice を現時点で検証環境以外で使用している人はいないと思いますが、互換性のない変更が入っていますので使用している方は  1.17 にアップグレードする前に対応するようにしましょう。そのほか、kube-proxy iptables モードの改善も目立ちます。一方で IPVS モードに関する改善はあまりないようです :thinking_face:

EndpointSlice が高い拡張性を意識しているということは知りませんでした。どういう用途を想定しているんでしょうね。`managed-by` ラベルは現状 EndpointSlice にしかありませんが、今後広がっていくのかもなあなんて想像しました。また 1.17 からベータに昇格したのにも関わらずデフォルトで有効にならないというのはなんなんでしょうね。ベータはデフォルト有効というルールを破ってまで昇格させた理由があるんでしょうか。デフォルト有効にしないならアルファのままでいいのではないかと思うのですが。