訳しながら理解していくKubernetes_Managing Compute Resources for Containers編

# はじめに
Kubernetesのドキュメントって英語だし、英検3級レベルで英語力のない私にはつらい・・・
そして、一回(google翻訳を使って)訳しながら読んでまた忘れてまた(google翻訳を使って)訳すを繰り返すのをやめたい。
調べるときは全文を見ずに、必要な部分だけを見てたりするので、公式ドキュメントを訳しながら全体を理解していこうと思う。

英語読むのめんどくせーーーとなっている人の助けになればと思い公開した

今回は [Managing Compute Resources for Containers](https://kubernetes.io/docs/concepts/configuration/manage-compute-resources-container/)


## 注意事項
* 基本的にGoogle翻訳のまんまです。
* 一応、意味が分かるようには訳してるつもりですが、ちょいちょい意味分からない部分もあります。  
誤訳がある可能性があるので、最後はちゃんと公式ドキュメントを読みましょう
* 私の知りたい部分からやるので、訳す部分はバラバラになります。
* 公式ドキュメントに記載されていない部分(自分で調べた部分とか)は_italic_で記載しています。
* V1.11でのドキュメントを記載

## Managing Compute Resources for Containers
[Pod](https://kubernetes.io/docs/concepts/workloads/pods/pod/)を指定する場合は、オプションで、各コンテナに必要なCPUとメモリ（RAM）の量を指定できます。コンテナにリソース要求が指定されている場合、スケジューラはPodを配置するノードをより適切に決定できます。また、コンテナの制限が指定されている場合、ノード上のリソースの競合を指定された方法で処理できます。要求と制限の違いの詳細については、[リソースQoS](https://github.com/kubernetes/community/blob/master/contributors/design-proposals/node/resource-qos.md)を参照してください。

## Resource requests and limits of Pod and Container
ポッドの各コンテナは、以下の1つまたは複数を指定できます。

* `spec.containers[].resources.limits.cpu`
* `spec.containers[].resources.limits.memory`
* `spec.containers[].resources.requests.cpu`
* `spec.containers[].resources.requests.memory`

---

要求と制限は個々のコンテナでのみ指定できますが、Podリソースの要求と制限について話をすると便利です。特定のリソースタイプに対するPodリソース要求/制限は、Pod内の各コンテナに対するそのタイプのリソース要求/制限の合計です。

## Meaning of CPU
CPUリソースの制限と要求は、CPU単位で測定されます。 Kubernetesにある1つのCPUは、次のものと同等です。

* 1 AWS vCPU
* 1 GCP Core
* 1 Azure vCore
* 1 Hyperthread on a bare-metal Intel processor with Hyperthreading

---

分数リクエストが許可されます。`spec.containers[].resources.requests.cpu`が`0.5`のコンテナは、CPUの1つを要求するものの半分のCPUが保証されています。式0.1は、式100mと等価であり、これは「100millicpu」と読み取ることができる。一部の人々は "100ミリコア"と言っています。これは同じことを意味すると理解されています。小数点を含む要求（`0.1`など）はAPIによって`100m`に変換され、`1m`より細かい精度は許可されません。

CPUは常に絶対量として要求され、相対量としては決して要求されません。 0.1は、シングルコア、デュアルコア、または48コアマシン上のCPUの量と同じです。

## Meaning of memory
制限とメモリ要求はバイト単位で測定されます。E、P、T、G、M、Kの接尾辞のいずれかを使用して、メモリを平方整数または固定小数点整数として表すことができます。Ei、Pi、Ti、Gi、Mi、Kiの2乗法を使うこともできます。たとえば、次の値はおおよそ同じ値を表します。

`128974848, 129e6, 129M, 123Mi`

ここに例があります。次のポッドには2つのコンテナがあります。各コンテナには、0.25 cpuと64MiB（2の26乗バイト）のメモリの要求があります。各コンテナには0.5 cpuと128MiBのメモリがあります。あなたは、ポッドに0.5 cpuと128 MiBのメモリ、1 cpuと256 MBbのメモリの要求があると言うことができます。

```yaml

apiVersion: v1
kind: Pod
metadata:
  name: frontend
spec:
  containers:
  - name: db
    image: mysql
    env:
    - name: MYSQL_ROOT_PASSWORD
      value: "password"
    resources:
      requests:
        memory: "64Mi"
        cpu: "250m"
      limits:
        memory: "128Mi"
        cpu: "500m"
  - name: wp
    image: wordpress
    resources:
      requests:
        memory: "64Mi"
        cpu: "250m"
      limits:
        memory: "128Mi"
        cpu: "500m"
```

## How Pods with resource requests are scheduled
Podを作成すると、KubernetesスケジューラーはPodのノードを選択して実行します。各ノードには、リソースタイプごとに最大容量（ポッドに提供できるCPUとメモリの量）があります。スケジューラは、各リソースタイプに対して、スケジュールされたコンテナのリソース要求の合計がノードの容量よりも少ないことを保証する。ノード上の実際のメモリまたはCPUリソース使用率は非常に低くても、スケジューラは容量チェックに失敗した場合でもノードにPodを配置することを拒否します。これは、リソースの使用率が後で増加する場合（たとえば、リクエストの1日のピーク時など）、ノード上のリソース不足から保護します。

## How Pods with resource limits are run
kubeletがPodのコンテナを開始すると、CPUとメモリの制限がコンテナのランタイムに渡されます。

Dockerを使用する場合：

* `spec.containers[].resources.requests.cpu`は、コアの値に変換されます。これは、小数点以下の桁数で、1024を掛けたものです。この数または2のうち大きい方が、`docker run`コマンドの[--cpu-shares](https://docs.docker.com/engine/reference/run/#/cpu-share-constraint)フラグの値として使用されます。
* `spec.containers[].resources.limits.cpu`はミリコア値に変換され、100が乗算されます。結果の値は、コンテナが100msごとに使用できるCPU時間の合計量です。コンテナは、この間隔の間にCPU時間の共有以上を使用することはできません。

注：デフォルトのクォータ期間は100msです。 CPUクォータの最小解像度は1msです。

* `spec.containers[].resources.limits.memory`は整数に変換され、`docker run`コマンドの[--memory](https://docs.docker.com/engine/reference/run/#/user-memory-constraints)フラグの値として使用されます。

コンテナがメモリ制限を超えると、コンテナが終了する可能性があります。再起動可能であれば、kubeletは他のタイプのランタイムエラーと同様に再起動します。

コンテナがそのメモリ要求を超えると、ノードがメモリ不足になるたびに、そのPodが追い出される可能性があります。

コンテナは、長時間にわたってCPU制限を超えても超えなくてもよい。ただし、CPU使用率が過剰になってもkillされません。

リソース制限のためにコンテナをスケジュールできない、または強制終了できないかどうかを判断するには、[トラブルシューティング](https://kubernetes.io/docs/concepts/configuration/manage-compute-resources-container/#troubleshooting)を参照してください。

## Monitoring compute resource usage
ポッドのリソース使用状況は、ポッドステータスの一部として報告されます。

クラスタに[オプションの監視](https://github.com/kubernetes/kubernetes/blob/master/cluster/addons/cluster-monitoring/README.md)が設定されている場合、監視システムからPodリソースの使用状況を取得できます。

## Troubleshooting
### My Pods are pending with event message failedScheduling
スケジューラがPodが収まるノードを見つけることができない場合、Podは場所が見つかるまでスケジュールされません。スケジューラが次のようにPodの場所を見つけられないたびにイベントが生成されます。

```
$ kubectl describe pod frontend | grep -A 3 Events
Events:
  FirstSeen LastSeen   Count  From          Subobject   PathReason      Message
  36s   5s     6      {scheduler }              FailedScheduling  Failed for reason PodExceedsFreeCPU and possibly others
```

前述の例では、ノード上のCPUリソースが不十分なため、「frontend」という名前のポッドがスケジュールされませんでした。同様のエラーメッセージは、不十分なメモリ（PodExceedsFreeMemory）による不具合を示唆することもあります。一般に、Podがこのタイプのメッセージで保留中の場合、試してみるべきいくつかのことがあります：

* クラスタにノードを追加してください。
* 保留中のポッドのためのスペースを確保するため、不要なポッドを終了します。
* ポッドがすべてのノードよりも大きくないことを確認します。たとえば、すべてのノードがcpu：1の容量を持つ場合、`cpu：1.1`の要求を持つポッドは決してスケジューリングされません。

---

`kubectl describe nodes`コマンドで割り当てられたノードの容量と量を確認できます。例えば：

```
$ kubectl describe nodes e2e-test-minion-group-4lw4
Name:            e2e-test-minion-group-4lw4
[ ... lines removed for clarity ...]
Capacity:
 cpu:                               2
 memory:                            7679792Ki
 pods:                              110
Allocatable:
 cpu:                               1800m
 memory:                            7474992Ki
 pods:                              110
[ ... lines removed for clarity ...]
Non-terminated Pods:        (5 in total)
  Namespace    Name                                  CPU Requests  CPU Limits  Memory Requests  Memory Limits
  ---------    ----                                  ------------  ----------  ---------------  -------------
  kube-system  fluentd-gcp-v1.38-28bv1               100m (5%)     0 (0%)      200Mi (2%)       200Mi (2%)
  kube-system  kube-dns-3297075139-61lj3             260m (13%)    0 (0%)      100Mi (1%)       170Mi (2%)
  kube-system  kube-proxy-e2e-test-...               100m (5%)     0 (0%)      0 (0%)           0 (0%)
  kube-system  monitoring-influxdb-grafana-v4-z1m12  200m (10%)    200m (10%)  600Mi (8%)       600Mi (8%)
  kube-system  node-problem-detector-v0.1-fj7m3      20m (1%)      200m (10%)  20Mi (0%)        100Mi (1%)
Allocated resources:
  (Total limits may be over 100 percent, i.e., overcommitted.)
  CPU Requests    CPU Limits    Memory Requests    Memory Limits
  ------------    ----------    ---------------    -------------
  680m (34%)      400m (20%)    920Mi (12%)        1070Mi (14%)
```

上記の出力では、Podが1120mを超えるCPUまたは6.23Giのメモリを要求した場合、ノードに収まらないことがわかります。

`Pods`セクションを見ると、どのポッドがノード上のスペースを占めているのかが分かります。

Podsに利用可能なリソースの量は、システムデーモンが利用可能なリソースの一部を使用するため、ノードの容量よりも少なくなります。`allocatable(割り当て可能)`フィールド[NodeStatus](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.11/#nodestatus-v1-core)は、Podで使用可能なリソースの量を示します。詳細については、[ノード割り当て可能なリソース](https://github.com/kubernetes/community/blob/master/contributors/design-proposals/node/node-allocatable.md)を参照してください。

[リソースクォータ](https://kubernetes.io/docs/concepts/policy/resource-quotas/)機能は、消費可能なリソースの総量を制限するように構成できます。名前空間と組み合わせて使用​​すると、1つのチームがすべてのリソースを奪うのを防ぐことができます。

### My Container is terminated
あなたのContainerはリソースが枯渇しているため、終了する可能性があります。リソース制限に達しているためにコンテナが強制終了されているかどうかを確認するには、該当するPodの`kubectl describe pod`を呼び出します。

```
[12:54:41] $ kubectl describe pod simmemleak-hra99
Name:                           simmemleak-hra99
Namespace:                      default
Image(s):                       saadali/simmemleak
Node:                           kubernetes-node-tf0f/10.240.216.66
Labels:                         name=simmemleak
Status:                         Running
Reason:
Message:
IP:                             10.244.2.75
Replication Controllers:        simmemleak (1/1 replicas created)
Containers:
  simmemleak:
    Image:  saadali/simmemleak
    Limits:
      cpu:                      100m
      memory:                   50Mi
    State:                      Running
      Started:                  Tue, 07 Jul 2015 12:54:41 -0700
    Last Termination State:     Terminated
      Exit Code:                1
      Started:                  Fri, 07 Jul 2015 12:54:30 -0700
      Finished:                 Fri, 07 Jul 2015 12:54:33 -0700
    Ready:                      False
    Restart Count:              5
Conditions:
  Type      Status
  Ready     False
Events:
  FirstSeen                         LastSeen                         Count  From                              SubobjectPath                       Reason      Message
  Tue, 07 Jul 2015 12:53:51 -0700   Tue, 07 Jul 2015 12:53:51 -0700  1      {scheduler }                                                          scheduled   Successfully assigned simmemleak-hra99 to kubernetes-node-tf0f
  Tue, 07 Jul 2015 12:53:51 -0700   Tue, 07 Jul 2015 12:53:51 -0700  1      {kubelet kubernetes-node-tf0f}    implicitly required container POD   pulled      Pod container image "k8s.gcr.io/pause:0.8.0" already present on machine
  Tue, 07 Jul 2015 12:53:51 -0700   Tue, 07 Jul 2015 12:53:51 -0700  1      {kubelet kubernetes-node-tf0f}    implicitly required container POD   created     Created with docker id 6a41280f516d
  Tue, 07 Jul 2015 12:53:51 -0700   Tue, 07 Jul 2015 12:53:51 -0700  1      {kubelet kubernetes-node-tf0f}    implicitly required container POD   started     Started with docker id 6a41280f516d
  Tue, 07 Jul 2015 12:53:51 -0700   Tue, 07 Jul 2015 12:53:51 -0700  1      {kubelet kubernetes-node-tf0f}    spec.containers{simmemleak}         created     Created with docker id 87348f12526a
```

上記の例では、`Restart Count：5`は、Pod内の`simmemleak`コンテナが5回終了して再起動されたことを示しています。

以前に終了したコンテナのステータスを取得するには、`-o go-template = ...`オプションを指定して`kubectl get pod`を呼び出すことができます。


# ドキュメントが崩れてているため後から記載

たとえば、次のポッドには2つのコンテナがあります。各コンテナには、2GiBのローカルephemeral storageの要求があります。各コンテナには、4GiBのローカルephemeral storageの制限があります。したがって、ポッドには一時的なローカルストレージの4GiBが要求され、ストレージには8GiBの制限があります。

```yaml
apiVersion: v1
kind: Pod
metadata:
  name: frontend
spec:
  containers:
  - name: db
    image: mysql
    env:
    - name: MYSQL_ROOT_PASSWORD
      value: "password"
    resources:
      requests:
        ephemeral-storage: "2Gi"
      limits:
        ephemeral-storage: "4Gi"
  - name: wp
    image: wordpress
    resources:
      requests:
        ephemeral-storage: "2Gi"
      limits:
        ephemeral-storage: "4Gi"
```

### How Pods with ephemeral-storage requests are scheduled
Podを作成すると、KubernetesスケジューラーはPodのノードを選択して実行します。各ノードには、Podに提供できるローカルの一時的なストレージの最大量があります。詳細は、[ノードの割り当て可能性(Node Allocatable)](https://kubernetes.io/docs/tasks/administer-cluster/reserve-compute-resources/#node-allocatable)を参照してください。スケジューラは、スケジュールされたコンテナのリソース要求の合計がノードの容量より少ないことを確認します。

### How Pods with ephemeral-storage limits run
コンテナレベルの分離では、コンテナの書き込み可能なレイヤーとログの使用量がストレージの制限を超えた場合、ポッドは追い出されます。ポッドレベルの分離の場合、すべてのコンテナからの一時的なストレージの使用量の合計とポッドのEmptyDirボリュームが上限を超えると、ポッドは追い出されます。

## Extended Resources
拡張リソースは、`kubernetes.io`ドメインの外部にある完全修飾リソース名です。これにより、クラスターオペレーターは宣言(advertise)し、ユーザーはKubernetesビルトインリソース以外を消費することができます。

拡張リソースを使用するには、2つのステップが必要です。まず、クラスタオペレータは拡張リソースを宣言しなければなりません。次に、ユーザーは、ポッドで拡張リソースを要求する必要があります。

### Managing extended resources
#### Node-level extended resources
ノードレベルの拡張リソースはノードに結びついています。

##### Device plugin managed resources
デバイスプラグイン管理リソースを各ノードにアドバタイズする方法については、[デバイスプラグイン](https://kubernetes.io/docs/concepts/extend-kubernetes/compute-storage-net/device-plugins/)を参照してください。

##### Other resources
新しいノードレベルの拡張リソースをアドバタイズするには、クラスタオペレータは`PATCH` HTTPリクエストをAPIサーバーに送信して、クラスタ内のノードの`status.capacity`に使用可能な数量を指定します。この操作の後、ノードの`status.capacity`に新しいリソースが含まれます。`status.allocatable`フィールドは、kubeletによって非同期的に新しいリソースで更新されます。ポッドの適性を評価するときには、スケジューラはノードのstatus.allocatable値を使用するため、ノードの容量を新しいリソースにパッチすることと、そのノードでリソースをスケジュールするように要求する最初のポッドとの間に短い遅延が生じることに注意してください。

##### Example:
次は、`curl`を使用して、マスターが`k8s-master`であるノード`k8s-node-1`に5つの "example.com/foo"リソースをアドバタイズするHTTPリクエストを作成する方法を示す例です。

```
curl --header "Content-Type: application/json-patch+json" \
--request PATCH \
--data '[{"op": "add", "path": "/status/capacity/example.com~1foo", "value": "5"}]' \
http://k8s-master:8080/api/v1/nodes/k8s-node-1/status
```

注：前の要求(request)では、`〜1`はパッチパス内の文字`/`のエンコーディングです。JSON-Patchの操作パス値はJSON-Pointerとして解釈されます。詳細については、[IETF RFC 6901のセクション3](https://tools.ietf.org/html/rfc6901#section-3)を参照してください。

#### Cluster-level extended resources
クラスタレベルの拡張リソースはノードに結びついていません。それらは通常、スケジューラー エクステンダーによって管理され、リソースの消費、割り当てなどを処理します。[スケジューラー・ポリシー構成](https://github.com/kubernetes/kubernetes/blob/release-1.10/pkg/scheduler/api/v1/types.go#L31)でスケジューラー・エクステンダーによって処理される拡張リソースを指定できます。

##### Example:
スケジューラーポリシーの次の構成は、クラスター拡張リソース "example.com/foo"がスケジューラーエクステンダーによって処理されることを示します。スケジューラーは、ポッドが「example.com/foo」を要求する場合にのみスケジューラーエクステンダーにポッドを送信します。`ignoredByScheduler`フィールドは、スケジューラーが`PodFitsResources`述部の "example.com/foo"リソースをチェックしないことを指定します。

```json
{
  "kind": "Policy",
  "apiVersion": "v1",
  "extenders": [
    {
      "urlPrefix":"<extender-endpoint>",
      "bindVerb": "bind",
      "managedResources": [
        {
          "name": "example.com/foo",
          "ignoredByScheduler": true
        }
      ]
    }
  ]
}
```

### Consuming extended resources
ユーザーは、CPUとメモリのようなPodの仕様で拡張リソースを使用することができます。スケジューラーは、使用可能な量をPodに同時に割り当てることができないように、リソースアカウンティングを行います。APIサーバーは、拡張リソースの数を整数に制限します。有効な量の例は3,3000mと3Kiです。無効な量の例は、0.5と1500mです。

注：拡張リソースは不透明整数リソースを置き換えます。ユーザーは予約済みの"`kubernetes.io`"以外の任意のドメイン名の接頭辞を使用できます。

Podで拡張リソースを使用するには、コンテナ仕様の`spec.containers[].resources.limits`マップにキーとしてリソース名を含めます。

注：拡張リソースはオーバーコミットできません。したがって、両方がコンテナ・スペックに存在する場合、要求と制限は等しくなければなりません。

ポッドは、CPU、メモリ、拡張リソースなど、すべてのリソース要求が満たされている場合にのみスケジュールされます。リソース要求が満たされない限り、Podは`PENDING`状態のままです。

#### Example:
以下のポッドは2つのCPUと1つの "example.com/foo"（拡張リソース）を要求します。

```yaml
apiVersion: v1
kind: Pod
metadata:
  name: my-pod
spec:
  containers:
  - name: my-container
    image: myimage
    resources:
      requests:
        cpu: 2
        example.com/foo: 1
      limits:
        example.com/foo: 1
```

### Planned Improvements
Kubernetesバージョン1.5では、コンテナにリソース数量を指定することしかできません。[emptyDirボリューム](https://kubernetes.io/docs/concepts/storage/volumes/#emptydir)など、ポッド内のすべてのコンテナで共有されるリソースのアカウンティングを改善する予定です。

Kubernetesバージョン1.5は、コンテナ要求とCPUとメモリの制限のみをサポートしています。ノードディスクスペースリソースやカスタムリソースタイプを追加するためのフレームワークなど、新しい[リソースタイプ](https://github.com/kubernetes/community/blob/master/contributors/design-proposals/scheduling/resources.md)を追加する予定です。

Kubernetesは、複数のレベルの[サービス品質](https://github.com/kubernetes/kubernetes/issues/168)をサポートすることにより、リソースの過剰提供(overcommitment)をサポートしています。

Kubernetesバージョン1.5では、CPUの1つのユニットは、異なるクラウドプロバイダ上で、同じクラウドプロバイダ内の異なるマシンタイプ上で異なることを意味します。たとえば、AWSでは、ノードの容量はECUsでレポートされ、GCEでは論理コアでレポートされます。我々は、プロバイダーとプラットフォーム間のより一貫性を可能にするために、CPUリソースの定義を修正する予定です。