From db6a06db832797eeedff6fdbe4380b9bb0008933 Mon Sep 17 00:00:00 2001 From: kyamau Date: Sun, 13 Mar 2022 22:13:37 +0900 Subject: [PATCH] Fix typos and mistranslations --- ja-jp/README.md | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/ja-jp/README.md b/ja-jp/README.md index a276d37..a34c509 100644 --- a/ja-jp/README.md +++ b/ja-jp/README.md @@ -8,7 +8,7 @@ kubectl run --image=nginx --replicas=3 そしてエンターキーを押します。数秒後、3つの nginx ポッドがすべてのワーカーノードに展開されているのがわかるでしょう。魔法のように動作し、素晴らしいです!しかし、実際のところ何が起こっているのでしょうか。 -Kubernetes の素晴らしいところの1つは、ユーザーフレンドリーな API を介してインフラストラクチャ全体でワークロードの展開を処理することです。複雑さはシンプルな抽象化によって隠されています。しかし、それが提供する価値を十分に理解するためには、その内部を理解することも有用です。このガイドではクライアントから kubelet へのリクエストのライフサイクル全体を通してあなたを理解へと導きます。そして何が起こっているのかを説明するのに必要なところでソースコードを参照します。 +Kubernetes の素晴らしいところの1つは、インフラストラクチャ全体へのワークロードの展開を、ユーザーフレンドリーな API を介して処理することです。複雑さはシンプルな抽象化によって隠されています。しかし、それが提供する価値を十分に理解するためには、その内部を理解することも有用です。このガイドではクライアントから kubelet へのリクエストのライフサイクル全体を通してあなたを理解へと導きます。そして何が起こっているのかを説明するのに必要なところでソースコードを参照します。 これ文書は鋭意作成中です。改善や書き換えが可能な部分を見つけたら、ぜひコントリビューションしてください! @@ -55,7 +55,7 @@ Deployment リソースを作成したいことが認識された後、提供さ ### APIグループとバージョンネゴシエーション -先に進む前に指摘する価値があるのは、Kubernetes は「APIグループ」に分類される _versioned_API を使用しているということです。APIグループは、似たリソースを分類して、簡単に推測できるようにすることを目的としています。それはまた、単一のモノリシックAPIに対するより良い代替手段を提供します。Deployment リソースのAPIグループは `apps` という名前で、その最新バージョンは `v1` です。Deployment リソースのマニフェストの上部に `apiVersion: apps/v1` と書く必要があるのはこのためです。 +先に進む前に指摘する価値があるのは、Kubernetes は「APIグループ」に分類される _versioned_ API を使用しているということです。APIグループは、似たリソースを分類して、簡単に推測できるようにすることを目的としています。それはまた、単一のモノリシックAPIに対するより良い代替手段を提供します。Deployment リソースのAPIグループは `apps` という名前で、その最新バージョンは `v1` です。Deployment リソースのマニフェストの上部に `apiVersion: apps/v1` と書く必要があるのはこのためです。 とにかく... kubectl はランタイムオブジェクトを生成した後、[適切なAPIグループとそれに対するバージョンを見つけ始め](https://github.com/kubernetes/kubernetes/blob/v1.14.0/pkg/kubectl/cmd/run/run.go#L674-L686)、リソースに対する様々なRESTセマンティクスを知っている[バージョン管理されたクライアント](https://github.com/kubernetes/kubernetes/blob/v1.14.0/pkg/kubectl/cmd/run/run.go#L705-L708)を組み立てます。この探索ステージはバージョンネゴシエーションと呼ばれ、すべての利用可能なAPIグループを取得するためにリモートAPI上の `/apis` パスを kubectl がスキャンすることを含みます。kube-apiserver はこのパスでスキーマ文書( OpenAPI フォーマット)を公開しているので、クライアントがディスカバリーを実行するのは簡単です。 @@ -70,7 +70,7 @@ Deployment リソースを作成したいことが認識された後、提供さ リクエストを正常に送信するために、kubectl は認証できる必要があります。ユーザ認証情報はほとんどの場合ディスク上の `kubeconfig`ファイルに保存されていますが、そのファイルは別の場所に保存することもできます。それを見つけるために、kubectl は以下を行います。 - `--kubeconfig` フラグが指定されている場合はそれを使います。 -- `$ KUBECONFIG` 環境変数が定義されている場合はそれを使います。 +- `$KUBECONFIG` 環境変数が定義されている場合はそれを使います。 - その他は `~/.kube` のような[推奨されるホームディレクトリ](https://github.com/kubernetes/client-go/blob/release-1.21/tools/clientcmd/loader.go#L43)を探し、見つかった最初のファイルを使います。 ファイルを解析した後、使用する現在のコンテキスト、指す現在のクラスタ、現在のユーザーに紐付けられている認証情報を決定します。ユーザーがフラグ固有の値( `--username` など)を指定した場合、それらが優先され、kubeconfig で指定された値を上書きします。この情報が得られるとkubectl はクライアントの設定を追加し、HTTP リクエストを適切に装飾できるようになります。 @@ -138,7 +138,7 @@ kube-apiserver はリクエストを受けたとき、どのようにして何 1. すべてのAPIグループに対して各グループバージョンについても繰り返し、HTTP ルートごとに[REST マッピングをインストール](https://github.com/kubernetes/apiserver/blob/7001bc4df8883d4a0ec84cd4b2117655a0009b6c/pkg/endpoints/groupversion.go#L92)します。これにより kube-apiserver はリクエストをマッピングし、一致するものが見つかったら正しいロジックに委任することができるようになります。 1. 特定のユースケースでは、[POST ハンドラー](https://github.com/kubernetes/apiserver/blob/7001bc4df8883d4a0ec84cd4b2117655a0009b6c/pkg/endpoints/installer.go#L710)が登録され、それが順番に [create resource ハンドラー](https://github.com/kubernetes/apiserver/blob/7001bc4df8883d4a0ec84cd4b2117655a0009b6c/pkg/endpoints/handlers/create.go#L37)に委譲されます。 -この時点で、kube-apiserver はどのルートが存在するかを完全に認識しており、リクエストが一致した場合にどのハンドラーとストレージプロバイダーを呼び出すかの内部マッピングを持っています。なんと賢いクッキーなのでしょうか。それでは、HTTP リクエストが流れ込んだとしましょう。 +この時点で、kube-apiserver はどのルートが存在するかを完全に認識しており、リクエストが一致した場合にどのハンドラーとストレージプロバイダーを呼び出すかの内部マッピングを持っています。なんと賢いのでしょうか。それでは、HTTP リクエストが流れ込んだとしましょう。 1. ハンドラーチェーンがリクエストを設定パターン(つまり、登録したルート)に一致させることができる場合、そのルートに登録されていた[専用ハンドラにディスパッチ](https://github.com/kubernetes/apiserver/blob/7001bc4df8883d4a0ec84cd4b2117655a0009b6c/pkg/server/handler.go#L143)されます。それ以外は[パスベースのハンドラー](https://github.com/kubernetes/apiserver/blob/7001bc4df8883d4a0ec84cd4b2117655a0009b6c/pkg/server/mux/pathrecorder.go#L248)にフォールバックします(これは `/apis` を呼び出したときに起こることです)。そのパスにハンドラが登録されていない場合は、[not found ハンドラー](https://github.com/kubernetes/apiserver/blob/7001bc4df8883d4a0ec84cd4b2117655a0009b6c/pkg/server/mux/pathrecorder.go#L254)が呼び出され、404が返されます。 1. 幸いなことに、私たちには [`createHandler`](https://github.com/kubernetes/apiserver/blob/7001bc4df8883d4a0ec84cd4b2117655a0009b6c/pkg/endpoints/handlers/create.go#L37) という登録されたルートがあります。それは何をするためのものなのでしょうか?それは最初にHTTPリクエストをデコードし、提供された JSON がバージョン管理された API リソースの期待に沿うことを保証するような基本的なバリデーションを実行するでしょう。 @@ -201,7 +201,7 @@ Deployment レコードが etcd に保存され初期化された後、それは ### ReplicaSetコントローラー -前のステップでは、Deployment コントローラーは、Deployment の最初の ReplicaSet を作成しましたが、まだ Pod はありません。ここで ReplicaSet コントローラーの出番です!仕事は # ReplicaSet とその依存リソース( Pod )のライフサイクルを監視することです。他のほとんどのコントローラーと同様に、特定のイベントでハンドラを起動することによって実現されます。 +前のステップでは、Deployment コントローラーは、Deployment の最初の ReplicaSet を作成しましたが、まだ Pod はありません。ここで ReplicaSet コントローラーの出番です!このコントローラーの仕事は、ReplicaSet とその依存リソース( Pod )のライフサイクルを監視することです。他のほとんどのコントローラーと同様に、特定のイベントでハンドラを起動することによって実現されます。 関心のあるイベントは作成です。ReplicaSet が作成されると( Deployment コントローラーの動作の結果)、RS コントローラーは新しい ReplicaSet の[状態を調べ](https://github.com/kubernetes/kubernetes/blob/master/pkg/controller/replicaset/replica_set.go#L583)、既存のものと必要なものとの間に差分があることを認識します。その後、ReplicaSet に属する [Pod の数を増やし](https://github.com/kubernetes/kubernetes/blob/master/pkg/controller/replicaset/replica_set.go#L460)てこの状態を調整しようとします。ReplicaSet のバーストカウント(親の Deployment から継承したもの)が常に一致するように、慎重に作成されます。 @@ -218,7 +218,7 @@ Owner Reference 設計のもう1つの小さな利点はステートフルであ ### インフォーマー -お気づきかもしれませんが、RBAC オーソライザーやDeployment コントローラーはクラスターの状態を関数に退避する必要があります。RBAC オーソライザーの例に戻ると、リクエストがきたときに、オーセンティケーターは後で使用するためにユーザー状態の初期表現を保存します。RBAC オーソライザーは、これを使用して etcd 内のユーザーに関連付けられているすべてのロールとロールバインディングを取得します。コントローラーはどのようにしてそのようなリソースにアクセスして変更するのでしょうか?これは一般的な使用例であり、Kubernetes ではインフォーマーを使って解決されています。 +お気づきかもしれませんが、RBAC オーソライザーやDeployment コントローラーのようなコントローラーが機能するには、クラスターの状態を取得する必要があります。RBAC オーソライザーの例に戻ると、リクエストがきたときに、オーセンティケーターは後で使用するためにユーザー状態の初期表現を保存します。RBAC オーソライザーは、これを使用して etcd 内のユーザーに関連付けられているすべてのロールとロールバインディングを取得します。コントローラーはどのようにしてそのようなリソースにアクセスして変更するのでしょうか?これは一般的な使用例であり、Kubernetes ではインフォーマーを使って解決されています。 インフォーマーとは、コントローラーがストレージイベントをサブスクライブして、関心のあるリソースを簡単にリストできるようにするパターンです。扱いやすい抽象化を提供することとは別に、それはキャッシングのような多くの仕組みの面倒を見ます(キャッシングは、不要な kube-apiserver 接続を減らし、サーバーとコントローラーの重複するシリアル化コストを減らすので重要です)。この設計を使用することで、周囲に迷惑をかけずに、コントローラーがスレッドセーフな方法でやりとりできるようになります。 @@ -248,11 +248,11 @@ kube-apiserverが この Binding オブジェクトを受け取ると、レジ ### Pod同期 -さて、メインコントローラのループは終了しました。まとめて見ましょう。HTTP リクエストが認証、認可、アドミッションコントロールの各ステップを通過しました。Deployment、ReplicaSet、3つのPodリソースは etcd に永続化されました。一連のイニシャライザーが実行されましたそして最後に、各 Pod は適切なノードにスケジュールされました。しかしこれまでのところ、私たちが推理してきた状態は純粋に etcd に存在します。次のステップには、ワーカーノード間での状態を分配することが含まれます。これは、Kubernetesの ような分散システムの本質なのです!これは kubelet と呼ばれるコンポーネントを通して行われます。さぁ、始めましょう! +さて、メインコントローラのループは終了しました。まとめて見ましょう。HTTP リクエストが認証、認可、アドミッションコントロールの各ステップを通過しました。Deployment、ReplicaSet、3つのPodリソースは etcd に永続化されました。一連のイニシャライザーが実行されました。そして最後に、各 Pod は適切なノードにスケジュールされました。しかしこれまでのところ、私たちが推理してきた状態は純粋に etcd に存在します。以降のステップには、ワーカーノード間に状態を分配することが含まれます。これは、Kubernetesの ような分散システムの本質なのです!これは kubelet と呼ばれるコンポーネントを通して行われます。さぁ、始めましょう! kubelet は、Kubernetes クラスタ内のノード毎に実行されるエージェントで、特に Pod のライフサイクルの管理を担当します。これは、「Pod」(これは実際には単なるKubernetes の概念です)の抽象化とその構成要素であるコンテナとの間のすべての翻訳ロジックを処理することを意味します。また、ボリュームのマウント、コンテナのログ記録、ガベージコレクション、その他多くの重要なことに関連するすべての関連ロジックも処理します。 -kubelet について考えるのに便利な方法は、やはりコントローラーのようなものです。20秒ごと(これは設定可能です)に kube-apiserver から Pod をクエリし、 `NodeName` が kubelet が実行されているノードの名前と一致するものをフィルタリングします。リストを持っていると、自身の内部キャッシュと比較することによって新たな追加を検出し、何らかの矛盾が存在すれば状態を同期させ始めます。その同期プロセスがどのようなものかを見てみましょう。 +kubelet について考えるのに便利な方法は、やはりコントローラーのようなものとして考えることです。20秒ごと(これは設定可能です)に kube-apiserver から Pod をクエリし、 `NodeName` が kubelet が実行されているノードの名前と一致するものをフィルタリングします。リストを持っていると、自身の内部キャッシュと比較することによって新たな追加を検出し、何らかの矛盾が存在すれば状態を同期させ始めます。その同期プロセスがどのようなものかを見てみましょう。 1. pod が作成されている場合(私たちのものです!)、pod のレイテンシーを追跡するために Prometheus で使用されるいくつかの[スタートアップメトリックスを登録](https://github.com/kubernetes/kubernetes/blob/fc8bfe2d8929e11a898c4557f9323c482b5e8842/pkg/kubelet/kubelet.go#L1519)します。 1. 次に、Pod の現在の Phase の状態を表す [PodStatus オブジェクトを生成](https://github.com/kubernetes/kubernetes/blob/dd9981d038012c120525c9e6df98b3beb3ef19e1/pkg/kubelet/kubelet_pods.go#L1287)します。Pod の Phase は、pod がそのライフサイクルのどこにあるのかの概要です。例としては、`Pending`、`Running`、`Succeeded`、`Failed`、`Unknown` などがあります。この状態を生成するのは非常に複雑なので、正確に何が起こるのかを見てみましょう。 @@ -273,7 +273,7 @@ kubelet について考えるのに便利な方法は、やはりコントロー より拡張性を高めるために、v1.5.0以降の kubelet では、具体的なコンテナランタイムとやりとりするために CRI( Container Runtime Interface )と呼ばれる概念を使用してきました。一言で言えば、CRI は kubelet と特定のランタイム実装の間の抽象化を提供します。通信は[プロトコルバッファ](https://github.com/google/protobuf)(より速いJSONのようなもの)と[gRPC API](https://grpc.io/)( Kubernetes オペレーションを実行するのに最適なタイプの API )を介して行われます。kubelet とランタイムの間で定義済みの契約を使用することによって、コンテナの編成方法に関する実際の実装の詳細はほとんど無関係になるため、これは非常に素晴らしいアイデアです。重要なのは契約だけです。これにより、コア Kubernetes コードを変更する必要がないため、最小限のオーバーヘッドで新しいランタイムを追加できます! -だいぶ横道にそれてしまったのでコンテナのデプロイに戻りましょう…。Pod が最初に起動されると、kubelet は `RunPodSandbox`リモートプロシージャコマンド( RPC )を呼び出します。「サンドボックス」とは、CRI用語では一連のコンテナを表し、ご想像の通りKubernetesで言う Pod です。この用語は意図的に曖昧になっているため、実際にコンテナを使用しない他のランタイムの意味を失うことはありません(サンドボックスが VM の場合があるハイパーバイザベースのランタイムを想像してください)。 +だいぶ横道にそれてしまったのでコンテナのデプロイに戻りましょう…。Pod が最初に起動されると、kubelet は `RunPodSandbox`リモートプロシージャコマンド( RPC )を呼び出します。「サンドボックス」とは、CRI用語では一連のコンテナを表し、ご想像の通りKubernetesで言う Pod です。この用語は意図的に曖昧になっているため、実際にコンテナを使用しない他のランタイムに対しても、その意味を失うことはありません(サンドボックスが VM の場合があるハイパーバイザベースのランタイムを想像してください)。 今回は Docker を使用しています。このランタイムでは、サンドボックスの作成には「一時停止」コンテナの作成が含まれます。一時停止コンテナは、ワークロードコンテナが使用することになる多くの pod レベルのリソースをホストするため、pod 内の他のすべてのコンテナの親のように機能します。これらの「リソース」とは Linux ネームスペース(IPC、network、PID)です。Linux でコンテナがどのように機能するのかに慣れていない場合は、簡単に説明しましょう。Linux カーネルにはネームスペースの概念があり、ホスト OS は専用のリソースセット( CPU やメモリなど)を切り出し、それを使用している世界で唯一のものであるかのようにプロセスに提供できます。Cgroup は、Linux がリソース割り当てを管理する方法であるため、ここでも重要です(リソース使用量を監視する警官のようなものです)。Docker は、これらのカーネル機能の両方を使用して、リソースが保証され分離が強化されたプロセスをホストします。詳細については、b0rkの素晴らしい投稿「[コンテナとは何か?](https://jvns.ca/blog/2016/10/10/what-even-is-a-container/)」をチェックしてください。 @@ -317,7 +317,7 @@ kubelet が pod 用のネットワークを設定すると、タスクを「CNI ### ホスト間ネットワーキング -これまで、コンテナがホストに接続する方法について説明しましたが、ホストはどのように通信するのでしょうか?異なるマシン上の2つのPodが通信したい場合必ず起こります。 +これまで、コンテナがホストに接続する方法について説明しましたが、ホスト間の通信はどのように行われるのでしょうか?これは異なるマシン上の2つのPodが通信したい場合に、必ず起こります。 これは通常、オーバーレイネットワーキングと呼ばれる概念を使用して実現されます。これは、複数のホスト間で動的にルートを同期させる方法です。人気のオーバーレイネットワークプロバイダの1つが Flannel です。インストール時の中心的な役割は、クラスタ内の複数のノード間にレイヤ3 IPv4ネットワークを提供することです。Flannel はコンテナがどのようにホストにネットワーク接続されるか(これはCNIが覚えている仕事です)を制御するのではなく、トラフィックがホスト「間」でどのように転送されるかを制御します。これを行うには、ホストのサブネットを選択して etcd に登録します。次に、クラスタルートのローカル表現を維持し、発信パケットを UDP データグラムにカプセル化して、正しいホストに到達できるようにします。詳細については、[CoreOS のドキュメント](https://github.com/coreos/flannel)をチェックしてください。 @@ -331,10 +331,10 @@ kubelet が pod 用のネットワークを設定すると、タスクを「CNI 1. CRI を介して[コンテナを作成し](https://github.com/kubernetes/kubernetes/blob/5f9f4a1c5939436fa320e9bc5973a55d6446e59f/pkg/kubelet/kuberuntime/kuberuntime_container.go#L115)ます。これは、親の PodSpec から `ContainerConfig` 構造体(コマンド、画像、ラベル、マウント、デバイス、環境変数などが定義されている)を生成し、それをプロトコルバッファ経由で CRI プラグインに送信することによって行われます。Docker の場合は、ペイロードをデシリアライズして、Daemon API に送信するための独自の設定構造体を生成します。その過程で、コンテナにいくつかのメタデータラベル(コンテナタイプ、ログパス、サンドボックス ID など)が適用されます。 1. コンテナを CPU マネージャに登録します。これは1.8の新しいアルファ機能であり、 `UpdateContainerResources` CRI メソッドを使ってローカルノード上の CPU のセットにコンテナを割り当てます。 1. コンテナか[開始され](https://github.com/kubernetes/kubernetes/blob/5f9f4a1c5939436fa320e9bc5973a55d6446e59f/pkg/kubelet/kuberuntime/kuberuntime_container.go#L135)ます。 -1. 起動後のコンテナライフサイクルフックが登録されている場合は[実行](https://github.com/kubernetes/kubernetes/blob/5f9f4a1c5939436fa320e9bc5973a55d6446e59f/pkg/kubelet/kuberuntime/kuberuntime_container.go#L156-L170)されます。フックは `Exec`(コンテナ内の特定のコマンドを実行する)か` HTTP`(コンテナエンドポイントに対してHTTPリクエストを実行する)のどちらかです。PostStartフックの実行に時間がかかりすぎたり、ハングアップしたり、失敗したりした場合、コンテナは決して `running` 状態にはなりません。 +1. 起動後のコンテナライフサイクルフックが登録されている場合は[実行](https://github.com/kubernetes/kubernetes/blob/5f9f4a1c5939436fa320e9bc5973a55d6446e59f/pkg/kubelet/kuberuntime/kuberuntime_container.go#L156-L170)されます。フックは `Exec`(コンテナ内の特定のコマンドを実行する)か`HTTP`(コンテナエンドポイントに対してHTTPリクエストを実行する)のどちらかです。PostStartフックの実行に時間がかかりすぎたり、ハングアップしたり、失敗したりした場合、コンテナは決して `running` 状態にはなりません。 ## まとめ 完了です。 -結局のところ、1つ以上のワーカーノードでは3つのコンテナを実行する必要があります。すべてのネットワーキング、ボリューム、シークレットは、kubelet によって集められ、CRI プラグインを介してコンテナになりました。 +以上の後に、3つのコンテナが、1つまたは複数のワーカーノードで実行されているはずです。すべてのネットワーキング、ボリューム、シークレットは、kubelet によって追加され、CRI プラグインを介してコンテナになりました。