4
3

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

Kubernetes 1.32: SIG-API Machineryの変更内容

Last updated at Posted at 2025-01-12

はじめに

Kubernetes v1.32 がリリースされました 🎉

Flowcontrolのv1alpha3が削除され、久しぶりに非推奨APIが無くなりました。InPlacePodVerticalScalingは一時Beta昇格のPull-Requestがマージされていましたが、他の機能のテストに影響がでていたため見送られています。一方、前回入らなかったWatchListはベータに昇格しました。また、待望の(?)MutatingAdmissionPolicyの実装や、PodLevelResourcesという大きな変更もそれぞれアルファで入っています。

それでは、API周りの変更を担当するSIG-API Machineryの変更点をCHANGELOGからピックアックします。(📝がついた文章は、CHANGELOGの公式の内容ではなく筆者の補足です)

SIG, KEPについてはこちらを参照ください。
過去の変更内容はこちら

:wastebasket: Deprecation (非推奨になったAPI)

  • なし

🌏 API Changes (API周りの変更)

  • 新しい /resize サブリソースが追加され、Podリソースのサイズ変更をリクエストできるようになりました。Podのリサイズ操作に /resize サブリソースを利用するように、k8sクライアントコードを更新してください。 (#128266)

📝 in-place pod vertical scalingの変更の一部です。まだアルファでデフォルト向こうなため、試す場合は、InPlacePodVerticalScalingを有効にしてください。

  • 破損したリソースの安全でない削除を許可する新機能が追加されました。デフォルトでは無効になっており、オプション --feature-gates=AllowUnsafeMalformedObjectDeletion=true を設定することで有効にできます。これにはAPIの変更が伴い、新しい削除オプション ignoreStoreReadErrorWithClusterBreakingPotential が導入されました。これはデフォルトでは設定されておらず、後方互換性を維持しています。破損したリソースの安全でない削除を実行するには、ユーザーが削除リクエストのオプションの有効化が必要です。リソースは、a) 変換エラー(例:復号化失敗)や b) オブジェクトのデコード失敗により、ストレージから正常に取得できない場合に破損したと見なされます。通常の削除フローが最初に試行され、破損リソースエラーで失敗した場合に安全でない削除がトリガーされます。さらに、この機能が有効になっている場合、LISTレスポンスの 'Status' の 'details' フィールドには、破損したオブジェクトを特定する情報が含まれます。注意:安全でない削除はFainalizer制約を無視し、前提条件チェックをスキップします。警告:これにより、安全でない削除に関連付けられたリソースに基づくワークロードが崩れる可能性があるため、クラスターを壊す結果が生じる可能性があります。 (#1275b13)

📝 この機能は、KMSなどで復号化できなくなったリソースを強制的に削除することを目的に追加されました。注意にあるように、中身を確認して削除できないので、Finalizerによるブロックはできません。

  • kubelet設定に singleProcessOOMKill フラグが追加されました。これをtrueに設定すると、cgroups v2で単一プロセスのOOMkillが有効になります。このモードでは、コンテナ内で単一のプロセスがOOMkillされた場合、残りのプロセスはOOMkillされません。 (#126096)
  • kube-apiserverエンドポイントに /flagz エンドポイントが追加されました。 (#127581)
  • PodLogOptionsStream フィールドが追加され、クライアントがコンテナの特定のログストリーム(stdoutまたはstderr)をリクエストできるようになりました。また、特定の StreamTailLines の組み合わせはサポートされていないことにも注意してください。 (#127360)
  • 割り当てられたデバイスごとのデバイスステータスデータを報告するために、 ResourceClaim.Status にドライバー用のフィールドが追加されました。 (#128240)
  • CELのDRA評価に対する上限コストバウンドの強制が追加されました。APIサーバーとスケジューラは、CEL式を評価するために必要なコストと実行ステップの上限を強制します。(#128101)
  • CrashLoopBackOff 内のコンテナのノード間でのコンテナ再起動の最大バックオフ遅延を変更する機能が追加されました。これをノードに対して設定するには、FeatureGate KubeletCrashLoopBackoffMax を有効にし、kubelet設定ファイル 内の CrashLoopBackOff.MaxContainerRestartPeriod フィールドを "1s""300s" の間に設定します。 (#128374)

📝 nodeごとにPodがbackoffしたときの遅延秒数を調整できるようになりました。このFeatureGateは現在アルファで、デフォルト無効です。詳細はKEP-4603: tune-crashloopbackoff参照してください。

  • ⭐ Pod APIがPodレベルのリソースに対して spec レベルでの resources をサポートするように変更されました。 (#128407)

📝 大きな変更が入りました!FeatureGate名は PodLevelResources で、現在アルファ、デフォルト無効です。その名のとおり、container単位ではなくPod単位でリソース制限するための機能です。これは、リソース配分の柔軟性向上やサイドカーコンテナなどPod全体でリソース管理したいケースに対応するため開発されています。詳しくはKEP-2837: Pod Level Resource Specificationsを参照してください。

  • ContainerStatus.AllocatedResources は、新しいFeatureGate InPlacePodVerticalScalingAllocatedStatus でガードされるようになりました。 (#128377)
  • ⭐ Coordination.v1alpha1 API は廃止され、coordination.v1alpha2 に置き換えられました。古い coordination.v1alpha1 型はアップグレード前に削除が必要です。 (#127857)

📝 前バージョンの1.31で追加されたリーダ選出の戦略を変更するためのFeatureGate, CoordinatedLeaderElection で利用するAPIです。まだアルファでデフォルト無効なので基本的に削除による影響はありません。

  • DRA: opaque deviceの設定パラメータの長さが制限されました。受け入れ時に、Kubernetes は 10KiB のサイズ制限を強制します。 (#128601)
  • DRA: シナリオによっては、ポッドのスケジューリングが最大 16 倍速くなりました。スケジューリングのスループットはクラスターの利用状況に大きく依存します。リソースが空いている軽負荷のクラスターでのスループットは高く、クラスターの利用状況が増えるにつれて低下します。 (#127277)
  • DRA: DeviceRequestAllocationResult 構造体に "AdminAccess"フィールドが追加され、割り当ての際に DeviceRequest フィールド内の対応するフィールドの代わりの使用が必要です。デバイスが管理者アクセスのみのために割り当てられている場合でも、通常の使用のために再度割り当てることがサポートされるようになりました。管理者アクセスを許可するには、1.32 から DRAAdminAccess FeatureGateの有効化が必要です。 (#127266)
  • 非構造化フィールドアクセッサー NestedNumberAsFloat64 のバグが修正され、非常に大きな int64 値にアクセスする際にエラーを返す代わりに、丸められた float64 値が返される可能性がありました。 (#128099)
  • Pod の spec.terminationGracePeriodSeconds が、soft evictionの MaxPodGracePeriodSeconds で常に上書きされるバグが修正されました。 AllowOverwriteTerminationGracePeriodSeconds FeatureGateを有効にすることで、以前の動作を復元できます。これを設定する必要がある場合は、Kubernetes プロジェクトに問題を報告し、contributorがその理由を理解できるようにしてください。 (#122890)
  • Jobの ManagedBy フィールドがBeta版に昇格しました。 (#127402)
  • SELinuxChangePolicy FeatureGateの下で、Podレベルの securityContext 内に新しい alpha seLinuxChangePolicy フィールドを実装しました。このフィールドは、SELinuxMount 機能が有効になっている場合に SELinux ラベル付き Pod ボリュームをマウントすることをオプトアウトするために使用できます(これは alpha であり、現在デフォルトで無効になっています)。SELinux の動作が変更される前にユーザーに警告する方法や、オプトアウトする方法については、KEP を参照してください。このフィールドとFeatureGateは、SELinux が有効なクラスターでのみ役立ちます。SELinux が無効なクラスターでは特にアクションは不要です。 (#127981)
  • ⭐ mutating admission policyに v1alpha1 API が導入され、CEL 表現による拡張可能な admission controlが可能になりました(KEP 3962: mutating admission policy)。使用するには、 MutatingAdmissionPolicy FeatureGateを有効にし、 --runtime-config を介して admissionregistration.k8s.io/v1alpha1 API を有効にします。 (#127134)

📝 MutatingAdmissionPolicyのAPIが追加されました。FeatureGateはv1.30で追加されましたが、その時はFeatureGateの追加のみで、今回のv1.32の変更で実際の処理が入っています。まだAlphaのままなので、利用には上記の有効化が必要です。

  • kube-apiserver: StructuredAuthorizationConfiguration FeatureGateが GA に昇格しました。 --authorization-config フラグは、バージョン apiserver.config.k8s.io/v1AuthorizationConfiguration を受け入れるようになりました(apiserver.config.k8s.io/v1beta1 から変更はありません)。 (#128172)
  • Customresourcefieldselectors がGAに昇格し、デフォルトで有効になりました。kube-apiserverバイナリから --feature-gates=CustomResourceFieldSelectors=true フラグは不要になり、今後のリリースで削除される予定です。 (#127673)

📝 v1.30でアルファで導入された Customresourcefieldselectors がGAしました。この機能を利用すると、標準リソースの定義済みfield selector(e.g., Podの .spec.nodeName)のように、カスタムリソースのList/Watchリクエストのフィルターとして利用するフィールドが定義できます。

  • FeatureGate StatefulSetAutoDeletePVC がBeta版からGAに昇格しました。 (#128247)
  • Classic Dynamic Resource Allocation (DRA) のサポートがすべて削除されました。以前はAlphaだった DRAControlPlaneController FeatureGateは利用できなくなりました。Kubernetes は現在、ポッドにダイナミックリソースを割り当てる際に structured parameters モデル(これもAlpha)を使用します。クラシック DRA がクラスターで有効になっている場合のみ、クラシック DRA に依存するすべてのワークロード(ポッド、アプリのデプロイメントなど)を削除し、アップグレード前にすべての PodSchedulingContext リソースが削除されていることを確認してください。PodSchedulingContext リソースはアップグレード後に apiserver を通じて削除できず、ワークロードは適切に機能しなくなります。 (#128003)
  • GAしているFeatureGate HPAContainerMetrics が削除されました。 (#126862)
  • Dynamic Resource Allocation (DRA) のコア機能がBeta版に昇格しました。 アップグレード 時には特にアクションは必要ありません。以前の v1alpha3 API は引き続きサポートされているため、v1alpha3 に基づく既存のデプロイメントや DRA ドライバーはそのまま機能します。 ダウングレード は、1.32 から 1.31 への DRA リソース(resourceclaims、resourceclaimtemplates、deviceclasses、resourceslices)が含まれているクラスターでは サポートされていません 。新しい v1beta1 がストレージバージョンとして使用され、1.31 では読み取れません。 (#127511)
  • resource/v1alpha3.ResourceSliceList フィールドは "metadata" と呼ばれるべきでしたが、"listMeta" と名付けられていました。正しく "metadata" なりました。 (#126749)

📝 ResourceSliceListはDRAで使われているリソースです

  • Watchストリームリクエストのための合成 "Bookmark" イベントは、新しいアノテーション kubernetes.io/initial-events-list-blueprint を含むようになりました。このアノテーションには、リクエストされた形式(protobuf、JSON、CBOR など)でエンコードされた空のバージョン付きリストが含まれ、その後 base64 エンコードされて文字列として保存されます。 (#127587)
  • ユーザビリティと開発者体験を向上させるために、CRD バリデーションルールは、オブジェクト検証式内でフィールド名として (CEL) 予約語を直接使用することをサポートするようになりました。名前形式の CEL ライブラリは新しい式でサポートされています。 (#126977)
  • persistentVolumeClaimRetentionPolicy の不正確な説明が更新されました。 (#126545)
  • X.509 クライアント証明書認証が kube-apiserver に対して実施されると、監査ログ用に証明書の署名から派生した資格情報IDが生成されるようになりました。 (#125634)

✨ Features (機能追加)

  • --concurrent-daemonset-syncs コマンドラインフラグが kube-controller-manager に追加されました。この値は、DaemonSetコントローラーのワーカー数を設定します。 (#128444)
  • kube-apiserver エンドポイントに /statusz エンドポイントが追加されました。 (#125577)
  • kube-controller-manager に新しいコントローラー、volumeattributesclass-protection-controller が追加されました。この新しいコントローラーは、VolumeAttributesClass オブジェクトの保護ファイナライザーを管理します。 (#123549)
  • WatchList FeatureGateを kube-apiserver のBeta版に昇格させ、KCM に対して WatchListClient を有効にしました。 (#128053)

📝 この機能は、リソースList時のAPIサーバのメモリ負荷を軽減するために、chunkでデータをListするのではなく、streamで取得する変更です。v1.27で追加され、前回のv1.31では一旦リバートされていましたが、ついに WatchList がベータに昇格しました。また、デフォルトでKCM=k8s controller-managerで有効になっています。公式ブログ Enhancing Kubernetes API Server Efficiency with API Streaming で解説も投稿されています。設計の詳細は KEP-3157: allow informers for getting a stream of data instead of chunkingを参照してください。

  • ⭐ Go クライアントコード(client-go)ライブラリに新しい機能が追加されました。メタデータクライアントの List() メソッドは、コレクションの取得時に API ストリーミングを有効にできます。これにより、多くのオブジェクトをListする際のパフォーマンスが向上します。この動作をリクエストするには、クライアントソフトウェアが WatchListClient client-go FeatureGateの有効化が必要です。さらに、ストリーミングはクラスターがサポートしている場合のみ利用できます。接続している API サーバーもストリーミングのサポートが必要です。API サーバーがストリーミングをサポートしていない場合、 client-golist API verbにフォールバックします。 (#127388)

📝 この機能は、 WatchList に対応する、クライアント側の機能です。v1.30でClient-goにFeatureGateだけ追加されていましたが、v1.31で初期実装が入り、今回はmetadataのList機能が追加されています。v1.30から引き続きベータでデフォルト無効です。

  • kube-apiserver に、ServiceAccountトークンの外部署名と公開検証キーの取得を行うための alpha 機能が追加されました。これを有効にするには、Alpha ExternalServiceAccountTokenSigner FeatureGateを有効にした上で、 --service-account-signing-endpoint を指定します。フラグの値は、ファイルシステム上の Unix 埋め込みソケットの場所であるか、@ 記号で始まり、抽象ソケット名前空間にある Unix 埋め込みソケットの名前を指定できます。 (#128190)
  • API リクエストとレスポンスボディのエンコーディングとして CBOR を許可するためのFeatureGate CBORServingAndStorage が追加され、カスタムリソースのストレージエンコーディングとしても使用されます。クライアントはオプトインが必要です。client-go でビルドされたプログラムは、client-go FeatureGate ClientsAllowCBOR と ClientsPreferCBOR を使用してこれを実行できます。 (#128539)
  • list verbのために btree データ構造を使用したWatchキャッシュの新しい実装が採用されました。この新しい実装はデフォルトでアクティブです。 BtreeWatchCache FeatureGateを無効にすることでオプトアウトできます。 (#128415)

📝 BtreeWatchCache は今回v1.32で初めて入ったFeatureGateですが、アルファではなくベータでデフォルト有効になっています。パフォーマンスの計測結果は一つ前のPR(#126754)にのっています。ここ最近は、APIリストまわりが ConsistentListFromCache, WatchList, WatchListClient, BtreeWatchCache と、Google Polandの人達による改善が進んでますね。

  • Client-go/rest: リクエスト/レスポンスのcontextual loggingに呼び出し元のソースコード位置が追加されました。 (#126999)
  • Discovery GroupManager に Group lister インターフェースを拡張しました。 (#127524)
  • リソースに特有の検証、例えば API サーバーによる暗号化設定の処理に使用できる、on_operations_total メトリックに追加のリソース labeltransformation を含めました。 (#126512)
  • JWT 認証者は、監査ログに使用される資格情報 ID として jti クレーム(存在する場合、かつ文字列値である場合)を設定するようになりました。 (#127010)
  • kube-apiserver: AuthorizeWithSelectors をBeta版に昇格させ、webhook認証呼び出しにリクエストからのフィールドおよびラベルセレクタ情報を含めます。 また、 AuthorizeNodeWithSelectors をBeta版に昇格させ、ノード API クライアントからのリクエストを制限するようにノード承認者の動作を変更します。これにより、各ノードは自分のノード API オブジェクトのみをGet/List/Watchでき、さらにそのノードにバインドされた Pod API オブジェクトのみをGet/List/Watchできます。他のノードや無関係なポッドを読むために kubelet 資格情報を使用するクライアントは、認証資格情報を変更(推奨)、使用方法を調整、またはノード承認者とは独立してより広範な読み取りアクセスの取得が必要です。 (#128168)
  • kube-apiserver: 新しい --requestheader-uid-headers フラグにより、指定されたヘッダーから認証ユーザーの UID を取得するリクエストヘッダー認証を構成できるようになりました。この新しいオプションの推奨値は X-Remote-Uid です。指定された場合、 kube-system/extension-apiserver-authentication configmap の .data[requestheader-uid-headers] フィールドに値が含まれます。 (#115834)
  • RetryGenerateName をGAに昇格させました。このはデフォルトで有効です。kube-apiserver バイナリでは --feature-gates=RetryGenerateName=true は不要で、今後のリリースで削除されます。 (#127093)
  • FeatureGate StrictCostEnforcementForVAP および StrictCostEnforcementForWebhooks が昇格されました。 (#127302)
  • ServiceAccountTokenNodeBindingValidation を GA に昇格させました。これはノードに直接バインドされたServiceAccountトークンを検証します。 (#128169)

🐛 Bug or Regression (バグ修正)

  • applyconfiguration-gen は、埋め込み構造体を通じて同じ名前のメンバーが複数存在する場合に、重複したメソッドやあいまいなメンバーアクセスを生成しなくなりました。 (#127001)
  • ブックマークイベントは、watchCache ストア内のすべてのアイテムが処理された後に即座に送信され、クライアントの動作の一貫性が向上しました。 (#127012)
  • kube-controller-manager の service-lb-controller ループをクラッシュさせる可能性がある 1.31 の回帰バグが修正されました。 (#128182)
  • キャッシュ同期の失敗により無期限にブロックされる可能性があるガーベジコレクターコントローラーのバグが修正されました。この修正により、特定のリソースをListまたはWatchできない場合でも、ガーベジコレクターは最終的に他のリソースのガーベジコレクションを続行できるようになります。 blockOwnerDeletion: true を持つオーナー参照を持つ無同期リソースタイプのオブジェクトは、ガーベジコレクターには知られません。 blockOwnerDeletion の使用は常に最善の努力に基づき、起動時およびオブジェクト作成時に競合的でした。この修正により、ガーベジコレクターコントローラーによって同期できないリソースについても最善の努力が続けられます。 (#125796)
  • KMSv2 サービスによって送信されたリクエストが無効な authority ヘッダーのために拒否される問題が修正されました。 (#126930)
  • メタデータ名なしのリクエストを受け入れるためにfake-clientが修正され、実際のクライアントの動作をより良くエミュレートできるようになりました。 (#126727)
  • IP、CIDR、数量、フォーマット、および URL に対して等価チェックを行う式の CEL における推定コストが修正されました。 (#126359)
  • 子スパンと親スパン(すなわち SerializeObjectList)の両方に対する階層構造の誤りが修正されました。以前は、いくつかの子スパンがその親と並行して表示されていました。 (#127551)
  • 修正: dynamic client-go は、UnstructuredList レスポンスを持つサブリソースを扱えるようになりました。 (#126809)
  • kubelet と kube-apiserver のメモリ漏れが、トレーシングに関連してデフォルトの 1.29 構成で修正されました。 (#126957)
  • クライアントが API ストリーミングリクエストを行い、 application/json;as=Table コンテンツタイプを指定した場合、API サーバーは 406 (Not Acceptable) エラーで応答します。この変更により、 Table 表現のようなサポートされていないフォーマットが正しく拒否されることが保証されます。 (#126996)
  • 古いポッド仕様がイメージボリュームソースを使用している場合、リソースを更新する際に、Feature Gate の ImageVolume が無効であってもそれの許可が必要です。 (#126733)
  • kube-apiserver: –version フラグでのビルド ID オーバーライドを無視する 1.31 の回帰バグが修正されました。 (#126665)
  • ポートフォワード中にエラーが発生した際にストリームをリセットし、kubectl がポートフォワード接続を維持できるようにします。 (#128318)

📝 bugfixのところにサラっと書かれてますが嬉しい変更ですね

  • クライアントがリソースのWatchに制限されているか認証されていない場合、ResultChan にエラーを送信し、RetryWatcher を閉じます。 (#126038)
  • build-tag フラグが conversion-gen および defaulter-gen に再導入され、ユーザーがコード生成プロセス中にカスタムビルドタグをインジェクトできるようになりました。 (#128259)

🔬 Others (その他修正)

  • CBOR エンコードされたWatchレスポンスは、非準拠の "application/cbor" の代わりに "application/cbor-seq" という Content-Type ヘッダーを設定するようになりました。 (#128501)
  • toleration に関する API バリデーションエラーが明確化され、operatorExistsvalue が空でない場合に注意が必要です。(#128119)
  • CBORServingAndStorage FeatureGateが有効になり、要求したクライアント向けに組み込み API を CBOR 形式で提供できるようになりました。 (#128503)
  • fake-client setは、共通の汎用実装を使用するようになりました。対応する構造体はプライベートになり、呼び出し元は対応するコンストラクタの使用が必要です。 ([#126503] (https://github.com/kubernetes/kubernetes/pull/126503))

📝 fake-clientがGoのgenericsを使って書き直されています。

  • k8s.io/cloud-provider/service コントローラーにバグが修正されました。サービスが更新されるとパニックになる可能性があり、イベントレコーダーが初期化される前に使用されていました。 v1.31.0 クラウドプロバイダーサービスコントローラーを使用しているすべてのクラウドプロバイダーは、インフォーマーがイベントを処理し始める前にコントローラーが初期化されていることを確認するか、バージョン 1.32.0 にアップデートが必要です。 (#128179)
  • PostStartHookContext.StopCh が完全に削除されました。 (#127341)
  • kube-apiserver の --admission-control-config-file ファイルは厳密に検証されるようになりました(EnableStrict)。設定内の重複または不明なフィールドは、今後エラーを引き起こします。 (#128013)
  • kube-apiserver の --egress-selector-config-file ファイルも厳密に検証されるようになりました(EnableStrict)。設定内の重複または不明なフィールドは、今後エラーを引き起こします。 (#128011)
  • kube-apiserver の ResourceQuotaConfiguration Admissionプラグインのサブセクションが --admission-control-config-file ファイル内で厳密に検証されるようになりました(EnableStrict)。設定内の重複または不明なフィールドは、今後エラーを引き起こします。 (#128038)
  • kube-controller-manager の --leader-migration-config ファイルも厳密に検証されるようになりました(EnableStrict)。設定内の重複または不明なフィールドは、今後エラーを引き起こします。 (#128009)
  • GAしているFeatureGate ValidatingAdmissionPolicy が削除されました。 (#126645)
  • GAしているFeatureGate CloudDualStackNodeIPs が削除されました。 (#126840)
  • GAしているFeatureGate StableLoadBalancerNodeSet が削除されました。 (#126841)
  • GAしているFeatureGate ZeroLimitedNominalConcurrencyShares が削除されました。 (#126894)
  • ServerSideApply および ServerSideFieldValidation に関する GAしている FeatureGateが削除されました。 (#127058)
  • KMSv2 および KMSv2KDF FeatureGateが削除されました。関連する機能は Kubernetes v1.29 リリースでGAに昇格しました。 (#126698)
  • ポートフォワードに関するエラーハンドリングが改訂され、ポートフォワードがブロックされるのを防ぐためにストリームリセットが追加されました。 (#128681)

📝 #128318のclient-go側の修正です

  • FlowSchema および PriorityLevelConfigurationflowcontrol.apiserver.k8s.io/v1beta3 API バージョンは v1.32 での提供が終了しました。マニフェストおよび API クライアントを v1.29 から利用可能な flowcontrol.apiserver.k8s.io/v1 API バージョンに移行してください。詳細については、https://kubernetes.io/docs/reference/using-api/deprecation-guide/#flowcontrol-resources-v132 を参照してください。 (#127017)
  • Reflector 構造体のフィールド名と typeDescription のgetterが名前変更されました。 (#128035)
  • kube-apiserver の --tracing-config-file が厳密に検証されます(EnableStrict)。設定内の重複または不明なフィールドは、エラーの原因となります。 (#128073)
  • Reflector 構造体のメンバー名と typeDescription がエクスポートされ、ユーザーの拡張性が向上しました。 (#127663)
  • etcd クライアントが v3.5.16 にアップグレードされました。 (#127279)
  • kubelet: 1.32.0 リリース候補における Windows ノードでの CSI ボリュームのマウントに関する問題が修正されました。 (#129083)
4
3
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
4
3

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?