1 - 複数のゾーンで動かす

This page describes how to run a cluster in multiple zones.

始めに

Kubernetes 1.2より、複数のゾーンにおいて単一のクラスターを運用するサポートが追加されました(GCEでは単純に"ゾーン",AWSは"アベイラビリティゾーン"と呼びますが、ここでは"ゾーン"とします)。 これは、より範囲の広いCluster Federationの軽量バージョンです(以前は"Ubernetes"の愛称で言及されていました)。 完全なCluster Federationでは、異なるリージョンやクラウドプロバイダー(あるいはオンプレミスデータセンター)内の独立したKubernetesクラスターをまとめることが可能になります。しかしながら、多くのユーザーは単に1つのクラウドプロバイダーの複数のゾーンでより可用性の高いKubernetesクラスターを運用したいと考えており、バージョン1.2におけるマルチゾーンサポート(以前は"Ubernetes Lite"の愛称で使用されていました)ではこれが可能になります。

マルチゾーンサポートは故意に限定されています: 1つのKubernetesクラスターは複数のゾーンで運用することができますが、同じリージョン(あるいはクラウドプロバイダー)のみです。現在はGCEとAWSのみが自動的にサポートされています(他のクラウドプロバイダーやベアメタル環境においても、単にノードやボリュームに追加する適切なラベルを用意して同様のサポートを追加することは容易ではありますが)。

機能性

ノードが開始された時、kubeletは自動的にそれらにゾーン情報を付したラベルを追加します。

Kubernetesはレプリケーションコントローラーやサービス内のPodをシングルゾーンクラスターにおけるノードにデプロイします(障害の影響を減らすため)。マルチゾーンクラスターでは、このデプロイの挙動はゾーンを跨いで拡張されます(障害の影響を減らすため)(これはSelectorSpreadPriorityによって可能になります)。これはベストエフォートな配置であり、つまりもしクラスターのゾーンが異種である(例:異なる数のノード,異なるタイプのノードや異なるPodのリソース要件)場合、これはゾーンを跨いだPodのデプロイを完璧に防ぐことができます。必要であれば、同種のゾーン(同一の数及びタイプのノード)を利用して不平等なデプロイの可能性を減らすことができます。

永続ボリュームが作成されると、PersistentVolumeLabelアドミッションコントローラーがそれらにゾーンラベルを付与します。スケジューラーはVolumeZonePredicateを通じて与えられたボリュームを請求するPodがそのボリュームと同じゾーンにのみ配置されることを保証します、これはボリュームはゾーンを跨いでアタッチすることができないためです。

制限

マルチゾーンサポートにはいくつか重要な制限があります:

  • 異なるゾーンはネットワーク内においてお互いに近接して位置していることが想定されているため、いかなるzone-aware routingも行われません。特に、トラフィックはゾーンを跨いだサービスを通じて行き来するため(サービスをサポートするいくつかのPodがクライアントと同じゾーンに存在していても)、これは追加のレイテンシやコストを生むかもしれません。

  • Volume zone-affinityはPersistentVolumeと共に動作し、例えばPodのスペックにおいてEBSボリュームを直接指定しても動作しません。

  • クラスターはクラウドやリージョンを跨げません(この機能はフルフェデレーションサポートが必要です)。

*ノードは複数のゾーンに存在しますが、kube-upは現在デフォルトではシングルマスターノードでビルドします。サービスは高可用性でありゾーンの障害に耐えることができますが、コントロールプレーンは単一のゾーンに配置されます。高可用性コントロールプレーンを必要とするユーザーは高可用性の説明を参照してください。

ボリュームの制限

以下の制限はtopology-aware volume bindingに記載されています。

  • 動的なプロビジョニングを使用する際のStatefulSetボリュームゾーンのデプロイは、現在Podのアフィニティあるいはアンチアフィニティと互換性がありません。

  • StatefulSetの名前がダッシュ("-")を含む場合、ボリュームゾーンのデプロイはゾーンを跨いだストレージの均一な分配を提供しない可能性があります。

  • DeploymentやPodのスペックにおいて複数のPVCを指定すると、StorageClassは特定の1つのゾーンに割り当てる必要があります、あるいはPVは特定のゾーンに静的にプロビジョンされる必要があります。もう一つの解決方法として、StatefulSetを使用すると、レプリカに対する全てのボリュームが同じゾーンにプロビジョンされます。

全体の流れ

GCEとAWSの両方にマルチゾーンのクラスターをセットアップし使用する手順について説明します。そのために、フルクラスターを用意し(MULTIZONE=trueと指定する)、kube-upを再び実行して追加のゾーンにノードを追加します(KUBE_USE_EXISTING_MASTER=trueと指定する)。

クラスターの立ち上げ

通常と同様にクラスターを作成します、しかし複数のゾーンを管理するためにMULTIZONEをクラスターに設定します。ノードをus-central1-aに作成します。

GCE:

curl -sS https://get.k8s.io | MULTIZONE=true KUBERNETES_PROVIDER=gce KUBE_GCE_ZONE=us-central1-a NUM_NODES=3 bash

AWS:

curl -sS https://get.k8s.io | MULTIZONE=true KUBERNETES_PROVIDER=aws KUBE_AWS_ZONE=us-west-2a NUM_NODES=3 bash

このステップは通常と同様にクラスターを立ち上げ、1つのゾーンで動作しています(しかし、MULTIZONE=trueによりマルチゾーン能力は有効になっています)。

ノードはラベルが付与される

ノードを見てください。それらがゾーン情報と共にラベルされているのが分かります。 それら全ては今のところus-central1-a (GCE)あるいはus-west-2a (AWS)にあります。ラベルはtopology.kubernetes.io/regionがリージョンに、topology.kubernetes.io/zoneはゾーンに付けられています:

kubectl get nodes --show-labels

結果は以下のようになります:

NAME                     STATUS                     ROLES    AGE   VERSION          LABELS
kubernetes-master        Ready,SchedulingDisabled   <none>   6m    v1.13.0          beta.kubernetes.io/instance-type=n1-standard-1,topology.kubernetes.io/region=us-central1,topology.kubernetes.io/zone=us-central1-a,kubernetes.io/hostname=kubernetes-master
kubernetes-minion-87j9   Ready                      <none>   6m    v1.13.0          beta.kubernetes.io/instance-type=n1-standard-2,topology.kubernetes.io/region=us-central1,topology.kubernetes.io/zone=us-central1-a,kubernetes.io/hostname=kubernetes-minion-87j9
kubernetes-minion-9vlv   Ready                      <none>   6m    v1.13.0          beta.kubernetes.io/instance-type=n1-standard-2,topology.kubernetes.io/region=us-central1,topology.kubernetes.io/zone=us-central1-a,kubernetes.io/hostname=kubernetes-minion-9vlv
kubernetes-minion-a12q   Ready                      <none>   6m    v1.13.0          beta.kubernetes.io/instance-type=n1-standard-2,topology.kubernetes.io/region=us-central1,topology.kubernetes.io/zone=us-central1-a,kubernetes.io/hostname=kubernetes-minion-a12q

2つ目のゾーンにさらにノードを追加

それでは、現存のマスターを再利用し、現存のクラスターの異なるゾーン(us-central1-bかus-west-2b)にもう1つのノードのセットを追加しましょう。 kube-upを再び実行します.しかしKUBE_USE_EXISTING_MASTER=trueを指定することでkube-upは新しいマスターを作成せず、代わりに以前作成したものを再利用します。

GCE:

KUBE_USE_EXISTING_MASTER=true MULTIZONE=true KUBERNETES_PROVIDER=gce KUBE_GCE_ZONE=us-central1-b NUM_NODES=3 kubernetes/cluster/kube-up.sh

AWSではマスターの内部IPアドレスに加えて追加のサブネット用のネットワークCIDRを指定する必要があります:

KUBE_USE_EXISTING_MASTER=true MULTIZONE=true KUBERNETES_PROVIDER=aws KUBE_AWS_ZONE=us-west-2b NUM_NODES=3 KUBE_SUBNET_CIDR=172.20.1.0/24 MASTER_INTERNAL_IP=172.20.0.9 kubernetes/cluster/kube-up.sh

ノードをもう1度見てください。更なる3つのノードがus-central1-bに起動し、タグ付けられているはずです:

kubectl get nodes --show-labels

結果は以下のようになります:

NAME                     STATUS                     ROLES    AGE   VERSION           LABELS
kubernetes-master        Ready,SchedulingDisabled   <none>   16m   v1.13.0           beta.kubernetes.io/instance-type=n1-standard-1,topology.kubernetes.io/region=us-central1,topology.kubernetes.io/zone=us-central1-a,kubernetes.io/hostname=kubernetes-master
kubernetes-minion-281d   Ready                      <none>   2m    v1.13.0           beta.kubernetes.io/instance-type=n1-standard-2,topology.kubernetes.io/region=us-central1,topology.kubernetes.io/zone=us-central1-b,kubernetes.io/hostname=kubernetes-minion-281d
kubernetes-minion-87j9   Ready                      <none>   16m   v1.13.0           beta.kubernetes.io/instance-type=n1-standard-2,topology.kubernetes.io/region=us-central1,topology.kubernetes.io/zone=us-central1-a,kubernetes.io/hostname=kubernetes-minion-87j9
kubernetes-minion-9vlv   Ready                      <none>   16m   v1.13.0           beta.kubernetes.io/instance-type=n1-standard-2,topology.kubernetes.io/region=us-central1,topology.kubernetes.io/zone=us-central1-a,kubernetes.io/hostname=kubernetes-minion-9vlv
kubernetes-minion-a12q   Ready                      <none>   17m   v1.13.0           beta.kubernetes.io/instance-type=n1-standard-2,topology.kubernetes.io/region=us-central1,topology.kubernetes.io/zone=us-central1-a,kubernetes.io/hostname=kubernetes-minion-a12q
kubernetes-minion-pp2f   Ready                      <none>   2m    v1.13.0           beta.kubernetes.io/instance-type=n1-standard-2,topology.kubernetes.io/region=us-central1,topology.kubernetes.io/zone=us-central1-b,kubernetes.io/hostname=kubernetes-minion-pp2f
kubernetes-minion-wf8i   Ready                      <none>   2m    v1.13.0           beta.kubernetes.io/instance-type=n1-standard-2,topology.kubernetes.io/region=us-central1,topology.kubernetes.io/zone=us-central1-b,kubernetes.io/hostname=kubernetes-minion-wf8i

ボリュームのアフィニティ

動的ボリュームを使用してボリュームを作成します(PersistentVolumeのみがゾーンアフィニティに対してサポートされています):

kubectl apply -f - <<EOF
{
  "apiVersion": "v1",
  "kind": "PersistentVolumeClaim",
  "metadata": {
    "name": "claim1",
    "annotations": {
        "volume.alpha.kubernetes.io/storage-class": "foo"
    }
  },
  "spec": {
    "accessModes": [
      "ReadWriteOnce"
    ],
    "resources": {
      "requests": {
        "storage": "5Gi"
      }
    }
  }
}
EOF
備考: バージョン1.3以降のKubernetesは設定したゾーンを跨いでPVクレームを分配します。 バージョン1.2では動的永続ボリュームは常にクラスターのマスターがあるゾーンに作成されます。 (ここではus-central1-a / us-west-2a); このイシューは (#23330) にバージョン1.3以降で記載されています。

それでは、KubernetesがPVが作成されたゾーン及びリージョンを自動的にラベルしているか確認しましょう。

kubectl get pv --show-labels

結果は以下のようになります:

NAME           CAPACITY   ACCESSMODES   RECLAIM POLICY   STATUS    CLAIM            STORAGECLASS    REASON    AGE       LABELS
pv-gce-mj4gm   5Gi        RWO           Retain           Bound     default/claim1   manual                    46s       topology.kubernetes.io/region=us-central1,topology.kubernetes.io/zone=us-central1-a

では永続ボリュームクレームを使用するPodを作成します。 GCE PD / AWS EBSボリュームはゾーンを跨いでアタッチできないため、これはこのPodがボリュームと同じゾーンにのみ作成されることを意味します:

kubectl apply -f - <<EOF
apiVersion: v1
kind: Pod
metadata:
  name: mypod
spec:
  containers:
    - name: myfrontend
      image: nginx
      volumeMounts:
      - mountPath: "/var/www/html"
        name: mypd
  volumes:
    - name: mypd
      persistentVolumeClaim:
        claimName: claim1
EOF

一般的にゾーンを跨いだアタッチはクラウドプロバイダーによって許可されていないため、Podは自動的にボリュームと同じゾーンに作成されることに注意してください:

kubectl describe pod mypod | grep Node
Node:        kubernetes-minion-9vlv/10.240.0.5

ノードのラベルをチェックします:

kubectl get node kubernetes-minion-9vlv --show-labels
NAME                     STATUS    AGE    VERSION          LABELS
kubernetes-minion-9vlv   Ready     22m    v1.6.0+fff5156   beta.kubernetes.io/instance-type=n1-standard-2,topology.kubernetes.io/region=us-central1,topology.kubernetes.io/zone=us-central1-a,kubernetes.io/hostname=kubernetes-minion-9vlv

Podがゾーンをまたがって配置される

レプリケーションコントローラーやサービス内のPodは自動的にゾーンに跨いでデプロイされます。まず、3つ目のゾーンに更なるノードを立ち上げましょう:

GCE:

KUBE_USE_EXISTING_MASTER=true MULTIZONE=true KUBERNETES_PROVIDER=gce KUBE_GCE_ZONE=us-central1-f NUM_NODES=3 kubernetes/cluster/kube-up.sh

AWS:

KUBE_USE_EXISTING_MASTER=true MULTIZONE=true KUBERNETES_PROVIDER=aws KUBE_AWS_ZONE=us-west-2c NUM_NODES=3 KUBE_SUBNET_CIDR=172.20.2.0/24 MASTER_INTERNAL_IP=172.20.0.9 kubernetes/cluster/kube-up.sh

3つのゾーンにノードがあることを確認します:

kubectl get nodes --show-labels

シンプルなWebアプリケーションを動作する、3つのRCを持つguestbook-goの例を作成します:

find kubernetes/examples/guestbook-go/ -name '*.json' | xargs -I {} kubectl apply -f {}

Podは3つの全てのゾーンにデプロイされているはずです:

kubectl describe pod -l app=guestbook | grep Node
Node:        kubernetes-minion-9vlv/10.240.0.5
Node:        kubernetes-minion-281d/10.240.0.8
Node:        kubernetes-minion-olsh/10.240.0.11
kubectl get node kubernetes-minion-9vlv kubernetes-minion-281d kubernetes-minion-olsh --show-labels
NAME                     STATUS    ROLES    AGE    VERSION          LABELS
kubernetes-minion-9vlv   Ready     <none>   34m    v1.13.0          beta.kubernetes.io/instance-type=n1-standard-2,topology.kubernetes.io/region=us-central1,topology.kubernetes.io/zone=us-central1-a,kubernetes.io/hostname=kubernetes-minion-9vlv
kubernetes-minion-281d   Ready     <none>   20m    v1.13.0          beta.kubernetes.io/instance-type=n1-standard-2,topology.kubernetes.io/region=us-central1,topology.kubernetes.io/zone=us-central1-b,kubernetes.io/hostname=kubernetes-minion-281d
kubernetes-minion-olsh   Ready     <none>   3m     v1.13.0          beta.kubernetes.io/instance-type=n1-standard-2,topology.kubernetes.io/region=us-central1,topology.kubernetes.io/zone=us-central1-f,kubernetes.io/hostname=kubernetes-minion-olsh

ロードバランサーはクラスター内の全てのゾーンにデプロイされています; guestbook-goの例は負荷分散サービスのサンプルを含みます:

kubectl describe service guestbook | grep LoadBalancer.Ingress

結果は以下のようになります:

LoadBalancer Ingress:   130.211.126.21

IPの上に設定します:

export IP=130.211.126.21

IPをcurlを通じて探索します:

curl -s http://${IP}:3000/env | grep HOSTNAME

結果は以下のようになります:

  "HOSTNAME": "guestbook-44sep",

再び、複数回探索します:

(for i in `seq 20`; do curl -s http://${IP}:3000/env | grep HOSTNAME; done)  | sort | uniq

結果は以下のようになります:

  "HOSTNAME": "guestbook-44sep",
  "HOSTNAME": "guestbook-hum5n",
  "HOSTNAME": "guestbook-ppm40",

ロードバランサーは、たとえPodが複数のゾーンに存在していても、全てのPodをターゲットします。

クラスターの停止

終了したら、クリーンアップします:

GCE:

KUBERNETES_PROVIDER=gce KUBE_USE_EXISTING_MASTER=true KUBE_GCE_ZONE=us-central1-f kubernetes/cluster/kube-down.sh
KUBERNETES_PROVIDER=gce KUBE_USE_EXISTING_MASTER=true KUBE_GCE_ZONE=us-central1-b kubernetes/cluster/kube-down.sh
KUBERNETES_PROVIDER=gce KUBE_GCE_ZONE=us-central1-a kubernetes/cluster/kube-down.sh

AWS:

KUBERNETES_PROVIDER=aws KUBE_USE_EXISTING_MASTER=true KUBE_AWS_ZONE=us-west-2c kubernetes/cluster/kube-down.sh
KUBERNETES_PROVIDER=aws KUBE_USE_EXISTING_MASTER=true KUBE_AWS_ZONE=us-west-2b kubernetes/cluster/kube-down.sh
KUBERNETES_PROVIDER=aws KUBE_AWS_ZONE=us-west-2a kubernetes/cluster/kube-down.sh

2 - 大規模クラスタの構築

サポート

At v1.22, Kubernetes supports clusters with up to 5000 nodes. More specifically, we support configurations that meet all of the following criteria:

  • No more than 110 pods per node
  • No more than 5000 nodes
  • No more than 150000 total pods
  • No more than 300000 total containers

構築

A cluster is a set of nodes (physical or virtual machines) running Kubernetes agents, managed by a "master" (the cluster-level control plane).

Normally the number of nodes in a cluster is controlled by the value NUM_NODES in the platform-specific config-default.sh file (for example, see GCE's config-default.sh).

Simply changing that value to something very large, however, may cause the setup script to fail for many cloud providers. A GCE deployment, for example, will run in to quota issues and fail to bring the cluster up.

When setting up a large Kubernetes cluster, the following issues must be considered.

クォータの問題

To avoid running into cloud provider quota issues, when creating a cluster with many nodes, consider:

  • Increase the quota for things like CPU, IPs, etc.
    • In GCE, for example, you'll want to increase the quota for:
      • CPUs
      • VM instances
      • Total persistent disk reserved
      • In-use IP addresses
      • Firewall Rules
      • Forwarding rules
      • Routes
      • Target pools
  • Gating the setup script so that it brings up new node VMs in smaller batches with waits in between, because some cloud providers rate limit the creation of VMs.

Etcdのストレージ

To improve performance of large clusters, we store events in a separate dedicated etcd instance.

When creating a cluster, existing salt scripts:

  • start and configure additional etcd instance
  • configure api-server to use it for storing events

マスターのサイズと構成要素

On GCE/Google Kubernetes Engine, and AWS, kube-up automatically configures the proper VM size for your master depending on the number of nodes in your cluster. On other providers, you will need to configure it manually. For reference, the sizes we use on GCE are

  • 1-5 nodes: n1-standard-1
  • 6-10 nodes: n1-standard-2
  • 11-100 nodes: n1-standard-4
  • 101-250 nodes: n1-standard-8
  • 251-500 nodes: n1-standard-16
  • more than 500 nodes: n1-standard-32

And the sizes we use on AWS are

  • 1-5 nodes: m3.medium
  • 6-10 nodes: m3.large
  • 11-100 nodes: m3.xlarge
  • 101-250 nodes: m3.2xlarge
  • 251-500 nodes: c4.4xlarge
  • more than 500 nodes: c4.8xlarge
備考:

On Google Kubernetes Engine, the size of the master node adjusts automatically based on the size of your cluster. For more information, see this blog post.

On AWS, master node sizes are currently set at cluster startup time and do not change, even if you later scale your cluster up or down by manually removing or adding nodes or using a cluster autoscaler.

アドオンのリソース

To prevent memory leaks or other resource issues in cluster addons from consuming all the resources available on a node, Kubernetes sets resource limits on addon containers to limit the CPU and Memory resources they can consume (See PR #10653 and #10778).

For example:

  containers:
  - name: fluentd-cloud-logging
    image: k8s.gcr.io/fluentd-gcp:1.16
    resources:
      limits:
        cpu: 100m
        memory: 200Mi

Except for Heapster, these limits are static and are based on data we collected from addons running on 4-node clusters (see #10335). The addons consume a lot more resources when running on large deployment clusters (see #5880). So, if a large cluster is deployed without adjusting these values, the addons may continuously get killed because they keep hitting the limits.

To avoid running into cluster addon resource issues, when creating a cluster with many nodes, consider the following:

  • Scale memory and CPU limits for each of the following addons, if used, as you scale up the size of cluster (there is one replica of each handling the entire cluster so memory and CPU usage tends to grow proportionally with size/load on cluster):
  • Scale number of replicas for the following addons, if used, along with the size of cluster (there are multiple replicas of each so increasing replicas should help handle increased load, but, since load per replica also increases slightly, also consider increasing CPU/memory limits):
  • Increase memory and CPU limits slightly for each of the following addons, if used, along with the size of cluster (there is one replica per node but CPU/memory usage increases slightly along with cluster load/size as well):

Heapster's resource limits are set dynamically based on the initial size of your cluster (see #16185 and #22940). If you find that Heapster is running out of resources, you should adjust the formulas that compute heapster memory request (see those PRs for details).

For directions on how to detect if addon containers are hitting resource limits, see the Troubleshooting section of Compute Resources.

少数のノードの起動の失敗を許容する

For various reasons (see #18969 for more details) running kube-up.sh with a very large NUM_NODES may fail due to a very small number of nodes not coming up properly. Currently you have two choices: restart the cluster (kube-down.sh and then kube-up.sh again), or before running kube-up.sh set the environment variable ALLOWED_NOTREADY_NODES to whatever value you feel comfortable with. This will allow kube-up.sh to succeed with fewer than NUM_NODES coming up. Depending on the reason for the failure, those additional nodes may join later or the cluster may remain at a size of NUM_NODES - ALLOWED_NOTREADY_NODES.

3 - ノードのセットアップの検証

ノード適合テスト

ノード適合テスト は、システムの検証とノードに対する機能テストを提供するコンテナ型のテストフレームワークです。このテストは、ノードがKubernetesの最小要件を満たしているかどうかを検証するもので、テストに合格したノードはKubernetesクラスタに参加する資格があることになります。

制約

Kubernetesのバージョン1.5ではノード適合テストには以下の制約があります:

  • ノード適合テストはコンテナのランタイムとしてDockerのみをサポートします。

ノードの前提条件

適合テストを実行するにはノードは通常のKubernetesノードと同じ前提条件を満たしている必要があります。 最低でもノードに以下のデーモンがインストールされている必要があります:

  • コンテナランタイム (Docker)
  • Kubelet

ノード適合テストの実行

ノード適合テストを実行するには、以下の手順に従います:

  1. Kubeletをlocalhostに指定します(--api-servers="http://localhost:8080")、 このテストフレームワークはKubeletのテストにローカルマスターを起動するため、Kubeletをローカルホストに設定します(--api-servers="http://localhost:8080")。他にも配慮するべきKubeletフラグがいくつかあります:
  • --pod-cidr: kubenetを利用している場合は、Kubeletに任意のCIDR(例: --pod-cidr=10.180.0.0/24)を指定する必要があります。
  • --cloud-provider: --cloud-provider=gceを指定している場合は、テストを実行する前にこのフラグを取り除いてください。
  1. 以下のコマンドでノード適合テストを実行します:
# $CONFIG_DIRはKubeletのPodのマニフェストパスです。
# $LOG_DIRはテスト出力のパスです。
sudo docker run -it --rm --privileged --net=host \
  -v /:/rootfs -v $CONFIG_DIR:$CONFIG_DIR -v $LOG_DIR:/var/result \
  k8s.gcr.io/node-test:0.2

他アーキテクチャ向けのノード適合テストの実行

Kubernetesは他のアーキテクチャ用のノード適合テストのdockerイメージを提供しています:

Arch Image
amd64 node-test-amd64
arm node-test-arm
arm64 node-test-arm64

選択したテストの実行

特定のテストを実行するには、環境変数FOCUSを実行したいテストの正規表現で上書きします。

sudo docker run -it --rm --privileged --net=host \
  -v /:/rootfs:ro -v $CONFIG_DIR:$CONFIG_DIR -v $LOG_DIR:/var/result \
  -e FOCUS=MirrorPod \ # MirrorPodテストのみを実行します
  k8s.gcr.io/node-test:0.2

特定のテストをスキップするには、環境変数SKIPをスキップしたいテストの正規表現で上書きします。

sudo docker run -it --rm --privileged --net=host \
  -v /:/rootfs:ro -v $CONFIG_DIR:$CONFIG_DIR -v $LOG_DIR:/var/result \
  -e SKIP=MirrorPod \ # MirrorPodテスト以外のすべてのノード適合テストを実行します
  k8s.gcr.io/node-test:0.2

ノード適合テストは、node e2e testのコンテナ化されたバージョンです。 デフォルトでは、すべての適合テストが実行されます。

理論的には、コンテナを構成し必要なボリュームを適切にマウントすれば、どのノードのe2eテストも実行できます。しかし、不適合テストを実行するためにはより複雑な設定が必要となるため、適合テストのみを実行することを強く推奨します

注意事項

  • このテストでは、ノード適合テストイメージや機能テストで使用されるコンテナのイメージなど、いくつかのdockerイメージがノード上に残ります。
  • このテストでは、ノード上にデッドコンテナが残ります。これらのコンテナは機能テスト中に作成されます。

4 - PKI証明書とその要件

Kubernetesでは、TLS認証のためにPKI証明書が必要です。 kubeadmでKubernetesをインストールする場合、必要な証明書は自動で生成されます。 自身で証明書を作成することも可能です。例えば、秘密鍵をAPIサーバーに保持しないことで、管理をよりセキュアにする場合が挙げられます。 本ページでは、クラスターに必要な証明書について説明します。

クラスタではどのように証明書が使われているのか

Kubernetesは下記の用途でPKIを必要とします:

  • kubeletがAPIサーバーの認証をするためのクライアント証明書
  • APIサーバーのエンドポイント用サーバー証明書
  • クラスターの管理者がAPIサーバーの認証を行うためのクライアント証明書
  • APIサーバーがkubeletと通信するためのクライアント証明書
  • APIサーバーがetcdと通信するためのクライアント証明書
  • controller managerがAPIサーバーと通信するためのクライアント証明書およびkubeconfig
  • スケジューラーがAPIサーバーと通信するためのクライアント証明書およびkubeconfig
  • front-proxy用のクライアント証明書およびサーバー証明書
備考: front-proxy証明書は、Kubernetes APIの拡張をサポートするためにkube-proxyを実行する場合のみ必要です。

さらに、etcdはクライアントおよびピア間の認証に相互TLS通信を実装しています。

証明書の保存場所

kubeadmを使用してKubernetesをインストールする場合、証明書は/etc/kubernetes/pkiに保存されます。このドキュメントの全てのパスは、そのディレクトリの相対パスを表します。

手動で証明書を設定する

kubeadmで証明書を生成したくない場合は、下記の方法のいずれかで手動で生成可能です。

単一ルート認証局

管理者によりコントロールされた、単一ルート認証局の作成が可能です。このルート認証局は複数の中間認証局を作る事が可能で、作成はKubernetes自身に委ねます。

必要な認証局:

パス デフォルトCN 説明
ca.crt,key kubernetes-ca Kubernetes全体の認証局   
etcd/ca.crt,key etcd-ca etcd用              
front-proxy-ca.crt,key kubernetes-front-proxy-ca front-end proxy用   

上記の認証局に加えて、サービスアカウント管理用に公開鍵/秘密鍵のペア(sa.keysa.pub)を取得する事が必要です。

全ての証明書

CAの秘密鍵をクラスターにコピーしたくない場合、自身で全ての証明書を作成できます。

必要な証明書:

デフォルトCN 親認証局 組織        種類 ホスト名 (SAN)
kube-etcd etcd-ca server, client localhost, 127.0.0.1
kube-etcd-peer etcd-ca server, client <hostname>, <Host_IP>, localhost, 127.0.0.1
kube-etcd-healthcheck-client etcd-ca client
kube-apiserver-etcd-client etcd-ca system:masters client
kube-apiserver kubernetes-ca server <hostname>, <Host_IP>, <advertise_IP>, [1]
kube-apiserver-kubelet-client kubernetes-ca system:masters client
front-proxy-client kubernetes-front-proxy-ca client

[1]: クラスターに接続するIPおよびDNS名( kubeadmを使用する場合と同様、ロードバランサーのIPおよびDNS名、kuberneteskubernetes.defaultkubernetes.default.svckubernetes.default.svc.clusterkubernetes.default.svc.cluster.local)

kindは下記のx509の鍵用途のタイプにマッピングされます:

種類 鍵の用途    
server digital signature, key encipherment, server auth
client digital signature, key encipherment, client auth
備考: 上記に挙げられたホスト名(SAN)は、クラスターを動作させるために推奨されるものです。 特別なセットアップが求められる場合、全てのサーバー証明書にSANを追加する事ができます。
備考:

kubeadm利用者のみ:

  • 秘密鍵なしでCA証明書をクラスターにコピーするシナリオは、kubeadmドキュメントの外部認証局の項目で言及されています。
  • kubeadmでPKIを生成すると、kube-etcdkube-etcd-peerおよび kube-etcd-healthcheck-client証明書は外部etcdを利用するケースでは生成されない事に留意してください。

証明書のパス

証明書は推奨パスに配置するべきです(kubeadmを使用する場合と同様)。 パスは場所に関係なく与えられた引数で特定されます。

デフォルトCN 鍵の推奨パス        証明書の推奨パス       コマンド 鍵を指定する引数 証明書を指定する引数
etcd-ca etcd/ca.key etcd/ca.crt kube-apiserver --etcd-cafile
kube-apiserver-etcd-client apiserver-etcd-client.key apiserver-etcd-client.crt kube-apiserver --etcd-keyfile --etcd-certfile
kubernetes-ca ca.key ca.crt kube-apiserver --client-ca-file
kubernetes-ca ca.key ca.crt kube-controller-manager --cluster-signing-key-file --client-ca-file, --root-ca-file, --cluster-signing-cert-file
kube-apiserver apiserver.key apiserver.crt kube-apiserver --tls-private-key-file --tls-cert-file
kube-apiserver-kubelet-client apiserver-kubelet-client.key apiserver-kubelet-client.crt kube-apiserver --kubelet-client-key --kubelet-client-certificate
front-proxy-ca front-proxy-ca.key front-proxy-ca.crt kube-apiserver --requestheader-client-ca-file
front-proxy-ca front-proxy-ca.key front-proxy-ca.crt kube-controller-manager --requestheader-client-ca-file
front-proxy-client front-proxy-client.key front-proxy-client.crt kube-apiserver --proxy-client-key-file --proxy-client-cert-file
etcd-ca etcd/ca.key etcd/ca.crt etcd --trusted-ca-file, --peer-trusted-ca-file
kube-etcd etcd/server.key etcd/server.crt etcd --key-file --cert-file
kube-etcd-peer etcd/peer.key etcd/peer.crt etcd --peer-key-file --peer-cert-file
etcd-ca etcd/ca.crt etcdctl --cacert
kube-etcd-healthcheck-client etcd/healthcheck-client.key etcd/healthcheck-client.crt etcdctl --key --cert

サービスアカウント用の鍵ペアについても同様です。

秘密鍵のパス       公開鍵のパス     コマンド 引数
sa.key kube-controller-manager service-account-private
sa.pub kube-apiserver service-account-key

ユーザアカウント用に証明書を設定する

管理者アカウントおよびサービスアカウントは手動で設定しなければなりません。

ファイル名 クレデンシャル名 デフォルトCN 組織      
admin.conf default-admin kubernetes-admin system:masters
kubelet.conf default-auth system:node:<nodeName> (see note) system:nodes
controller-manager.conf default-controller-manager system:kube-controller-manager
scheduler.conf default-scheduler system:kube-scheduler
備考: kubelet.confにおける<nodeName>の値は必ずAPIサーバーに登録されたkubeletのノード名と一致しなければなりません。詳細は、Node Authorizationを参照してください。
  1. 各コンフィグ毎に、CN名と組織を指定してx509証明書と鍵ペアを生成してください。

  2. 以下のように、各コンフィグでkubectlを実行してください。

KUBECONFIG=<filename> kubectl config set-cluster default-cluster --server=https://<host ip>:6443 --certificate-authority <path-to-kubernetes-ca> --embed-certs
KUBECONFIG=<filename> kubectl config set-credentials <credential-name> --client-key <path-to-key>.pem --client-certificate <path-to-cert>.pem --embed-certs
KUBECONFIG=<filename> kubectl config set-context default-system --cluster default-cluster --user <credential-name>
KUBECONFIG=<filename> kubectl config use-context default-system

これらのファイルは以下のように利用されます:

ファイル名 コマンド コメント
admin.conf kubectl クラスターの管理者設定用
kubelet.conf kubelet クラスターの各ノードに1つ必要です。
controller-manager.conf kube-controller-manager manifests/kube-controller-manager.yamlのマニフェストファイルに追記する必要があります。
scheduler.conf kube-scheduler manifests/kube-scheduler.yamlのマニフェストファイルに追記する必要があります。