Help us understand the problem. What is going on with this article?

t2.micro 1台でEKSを起動してみた

More than 1 year has passed since last update.

AWSの無料枠といえばt2.microです。
ということで、EKSをWorkerがt2.micro 1台という構成で構築してみました。1
(2018/06/12) CloudFormationテンプレートのMaxPodsの設定が影響している可能性を考慮していなかったため、追記しました。

結論

EKSのWorkerは、t2.microでも特に問題なく構築でき、Podの起動も可能でした。
ただし、IPアドレス数の制限により、Podは2つ以上起動できませんでした。
IPアドレスが枯渇するとWorkerもPodもスケールできなくなると思われるので、IPアドレス数の制限には注意が必要そうです。
インスタンスタイプごとに、IPアドレス数の制限と、MaxPodsによる制限と、他にも何らかの制限があり、Podの起動数が制限されているようです。
スケールを考えるうえで、Podの起動数の制限には注意が必要そうです。

やったこと

Workerがt2.micro 1台構成なEKSの構築

Workerの構築の手前まで

Amazon EKS の使用開始 に従い、「ステップ 3: Amazon EKS ワーカーノードを起動して設定する」の手前まで構築を進めます。

CloudFormationテンプレートの修正

Amazon EKS の使用開始 に掲載されているテンプレートを、以下のように2箇所書き換えます。

---
AWSTemplateFormatVersion: '2010-09-09'
Description: 'Amazon EKS - Node Group'

Parameters:

  KeyName:
    Description: The EC2 Key Pair to allow SSH access to the instances
    Type: AWS::EC2::KeyPair::KeyName
    :
    :
    :
  NodeInstanceType:
    Description: EC2 instance type for the node instances
    Type: String
    Default: t2.medium
    AllowedValues:
    # t2.microを追加
    - t2.micro
    - t2.small
    - t2.medium
    - t2.large
    - t2.xlarge
    - t2.2xlarge
    :
    :
    :
      MaxPods: 234
    r4.8xlarge:
      MaxPods: 234
    r4.16xlarge:
      MaxPods: 737
    # t2.microを追加
    t2.micro:
      # MaxPodsは適当に設定
      MaxPods: 4
    t2.small:
      MaxPods: 8
    t2.medium:
      MaxPods: 17
    t2.large:
    :
    :
    :

修正したテンプレートでWorkerを構築

変更したテンプレートを使ってWorkerを構築します。
NodeAutoScalingGroupMaxSizeは1、NodeInstanceTypeはt2.microとします。

eks-worker-stack-parameter.png

ConfigMapの作成

Amazon EKS の使用開始 に記載されている「ワーカーノードをクラスターと結合するには」に従って、ConfigMapを作成します。

Worker構築完了の確認

kubectlでワーカーが1台表示されれば構築完了です。

$ kubectl get nodes
NAME                                           STATUS    ROLES     AGE       VERSION
ip-192-168-157-38.us-west-2.compute.internal   Ready     <none>    1m        v1.10.3

Podの起動

まずはPodを1つ起動してみる

NginxのPodを1つ起動してみます。

$ kubectl run my-nginx --image=nginx:alpine
deployment.apps "my-nginx" created

無事起動しました。

$ kubectl get all
NAME                            READY     STATUS    RESTARTS   AGE
pod/my-nginx-6947c57698-tjt6p   1/1       Running   0          25s

NAME                 TYPE        CLUSTER-IP   EXTERNAL-IP   PORT(S)   AGE
service/kubernetes   ClusterIP   10.100.0.1   <none>        443/TCP   24m

NAME                       DESIRED   CURRENT   UP-TO-DATE   AVAILABLE   AGE
deployment.apps/my-nginx   1         1         1            1           25s

NAME                                  DESIRED   CURRENT   READY     AGE
replicaset.apps/my-nginx-6947c57698   1         1         1         25s

ポートフォワードして動作確認します。

$ kubectl port-forward deployment.apps/my-nginx 8080:80
Forwarding from 127.0.0.1:8080 -> 80
Forwarding from [::1]:8080 -> 80

ブラウザから http://localhost:8080 に接続すると、画面が表示されました。

nginx.png

t2.microでもPodを起動できることが確認できました。

Podを増やしてみる

Podを2つに増やしてみます。

$ kubectl scale deployment.apps/my-nginx --replicas=2
deployment.apps "my-nginx" scaled

以下の通り、2つ目のPodが起動していません。

$ kubectl get all
NAME                            READY     STATUS    RESTARTS   AGE
pod/my-nginx-6947c57698-5lnxj   0/1       Pending   0          16s
pod/my-nginx-6947c57698-tjt6p   1/1       Running   0          6m

NAME                 TYPE        CLUSTER-IP   EXTERNAL-IP   PORT(S)   AGE
service/kubernetes   ClusterIP   10.100.0.1   <none>        443/TCP   29m

NAME                       DESIRED   CURRENT   UP-TO-DATE   AVAILABLE   AGE
deployment.apps/my-nginx   2         2         2            1           6m

NAME                                  DESIRED   CURRENT   READY     AGE
replicaset.apps/my-nginx-6947c57698   2         2         1         6m

詳細を確認します。

$ kubectl describe pod/my-nginx-6947c57698-5lnxj
Name:           my-nginx-6947c57698-5lnxj
Namespace:      default
Node:           <none>
Labels:         pod-template-hash=2503713254
                run=my-nginx
Annotations:    <none>
Status:         Pending
IP:
Controlled By:  ReplicaSet/my-nginx-6947c57698
Containers:
  my-nginx:
    Image:        nginx:alpine
    Port:         <none>
    Host Port:    <none>
    Environment:  <none>
    Mounts:
      /var/run/secrets/kubernetes.io/serviceaccount from default-token-8xb9r (ro)
Conditions:
  Type           Status
  PodScheduled   False
Volumes:
  default-token-8xb9r:
    Type:        Secret (a volume populated by a Secret)
    SecretName:  default-token-8xb9r
    Optional:    false
QoS Class:       BestEffort
Node-Selectors:  <none>
Tolerations:     node.kubernetes.io/not-ready:NoExecute for 300s
                 node.kubernetes.io/unreachable:NoExecute for 300s
Events:
  Type     Reason            Age               From               Message
  ----     ------            ----              ----               -------
  Warning  FailedScheduling  19s (x8 over 1m)  default-scheduler  0/1 nodes are available: 1 Insufficient pods.

何かの不足でPodが起動できていないようです。

考察

2つ目のPodが起動できなかった理由

ポッドネットワーキング によると...

Amazon EKS は、Kubernetes の Amazon VPC CNI プラグインを使用した従来の VPC ネットワーキングをサポートしています。この CNI プラグインを使用すると、Kubernetes ポッドは VPC ネットワーク上と同じ IP アドレスをポッド内に持つことができます。この CNI プラグインは、GitHub で管理されているオープンソースのプロジェクトです。
:
:
:
Elastic Network Interface と、Amazon EC2 インスタンスタイプによるセカンダリ IP アドレス制限が適用されます。一般的に、インスタンスが大きいほど、より多くの IP アドレスをサポートできます。詳細については、Linux インスタンス用 Amazon EC2 ユーザーガイドの「各インスタンスタイプのネットワークインターフェイスごとの IP アドレス」を参照してください。

各インスタンスタイプのネットワークインターフェイスごとの IP アドレス を参照すると...

インスタンスタイプ ネットワークインターフェイスの最大数 インターフェイスあたりの IPv4 アドレス インターフェイスあたりの IPv6 アドレス
t2.micro 2 2 2
t2.small 2 4 4
t2.midium 3 6 6

ということで、t2.microは 2 × 2 = 4 つまでしかIPアドレスを持てないようです。

他のNamespaceでどれだけIPアドレスを使っているのか確認すると...

$ kubectl get pod --namespace kube-system -o wide
NAME                       READY     STATUS    RESTARTS   AGE       IP                NODE
aws-node-2tqc2             1/1       Running   0          30m       192.168.157.38    ip-192-168-157-38.us-west-2.compute.internal
kube-dns-7cc87d595-bqdjk   3/3       Running   0          52m       192.168.170.125   ip-192-168-157-38.us-west-2.compute.internal
kube-proxy-zkd2n           1/1       Running   0          30m       192.168.157.38    ip-192-168-157-38.us-west-2.compute.internal

上記のように、kube-systemでIPアドレスを2つ使っています。

インスタンスがそもそも1つIPアドレスを使っているので、各ノードに対して自動的に3個のIPアドレスが消費されてしまうようです。

その結果、合計で4つまでしかIPアドレスを持てないt2.microは、Podを1つしか起動できなかったようです。

t2.smallでも試してみる

t2.smallでも実験してみました。

t2.smallはIPアドレスを 2 × 4 = 8 個持てるはずです。
そのうち3個が消費されてしまうはずなので、5個だけPodが起動して、6個目は起動できないはずです。

実際にPodを6個起動しようとすると...

$ kubectl scale deployment.apps/my-nginx --replicas=6
deployment.apps "my-nginx" scaled
$ kubectl get all
NAME                            READY     STATUS    RESTARTS   AGE
pod/my-nginx-6947c57698-2cq6s   1/1       Running   0          34s
pod/my-nginx-6947c57698-6kdmb   1/1       Running   0          34s
pod/my-nginx-6947c57698-6xnfc   0/1       Pending   0          34s
pod/my-nginx-6947c57698-gl29s   1/1       Running   0          34s
pod/my-nginx-6947c57698-jfk58   1/1       Running   0          34s
pod/my-nginx-6947c57698-z5fh4   1/1       Running   0          34s

NAME                 TYPE        CLUSTER-IP   EXTERNAL-IP   PORT(S)   AGE
service/kubernetes   ClusterIP   10.100.0.1   <none>        443/TCP   1h

NAME                       DESIRED   CURRENT   UP-TO-DATE   AVAILABLE   AGE
deployment.apps/my-nginx   6         6         6            5           50m

NAME                                  DESIRED   CURRENT   READY     AGE
replicaset.apps/my-nginx-6947c57698   6         6         5         50m

たしかに5つまでしか起動できませんでした。

(2018/06/12) 追加調査

t2.mediumでも試してみる

実は、ここまでの確認方法では、t2.micro、t2.smallのPod起動制限がCloudFormationテンプレートで指定したMaxPodsに依存している可能性を排除できていませんでした。
そこで、t2.mediumでも試してみました。

t2.mediumはMaxPodsが17なので、この設定の影響があるならNginxのPodは14個まで起動できるはずです。
ENIの面では、 3 × 6 = 18 なので、こちらの設定が影響するならNginxのPodは15個まで起動できるはずです。

では、Podを16個起動しようとしてみます。

$ kubectl scale deployment.apps/my-nginx --replicas=16
deployment.apps "my-nginx" scaled
$ kubectl get all
NAME                            READY     STATUS    RESTARTS   AGE
pod/my-nginx-6947c57698-2dm68   1/1       Running   0          1m
pod/my-nginx-6947c57698-5zdkr   1/1       Running   0          1m
pod/my-nginx-6947c57698-6kx6c   1/1       Running   0          2m
pod/my-nginx-6947c57698-8mt2x   0/1       Pending   0          1m
pod/my-nginx-6947c57698-9lqmk   1/1       Running   0          1m
pod/my-nginx-6947c57698-dwpcz   1/1       Running   0          1m
pod/my-nginx-6947c57698-gxzft   1/1       Running   0          1m
pod/my-nginx-6947c57698-jf94r   1/1       Running   0          1m
pod/my-nginx-6947c57698-jnzd9   1/1       Running   0          1m
pod/my-nginx-6947c57698-k69fp   1/1       Running   0          1m
pod/my-nginx-6947c57698-nntk4   1/1       Running   0          1m
pod/my-nginx-6947c57698-rhdn6   1/1       Running   0          1m
pod/my-nginx-6947c57698-s47mq   1/1       Running   0          1m
pod/my-nginx-6947c57698-thc85   0/1       Pending   0          1m
pod/my-nginx-6947c57698-vkdpb   1/1       Running   0          1m
pod/my-nginx-6947c57698-vwvd6   1/1       Running   0          1m

NAME                 TYPE        CLUSTER-IP   EXTERNAL-IP   PORT(S)   AGE
service/kubernetes   ClusterIP   10.100.0.1   <none>        443/TCP   14m

NAME                       DESIRED   CURRENT   UP-TO-DATE   AVAILABLE   AGE
deployment.apps/my-nginx   16        16        16           14          2m

NAME                                  DESIRED   CURRENT   READY     AGE
replicaset.apps/my-nginx-6947c57698   16        16        14        2m

念のため詳細を見ておくと...

$ kubectl describe pod/my-nginx-6947c57698-8mt2x
Name:           my-nginx-6947c57698-8mt2x
Namespace:      default
Node:           <none>
Labels:         pod-template-hash=2503713254
                run=my-nginx
Annotations:    <none>
Status:         Pending
IP:
Controlled By:  ReplicaSet/my-nginx-6947c57698
Containers:
  my-nginx:
    Image:        nginx:alpine
    Port:         <none>
    Host Port:    <none>
    Environment:  <none>
    Mounts:
      /var/run/secrets/kubernetes.io/serviceaccount from default-token-t664j (ro)
Conditions:
  Type           Status
  PodScheduled   False
Volumes:
  default-token-t664j:
    Type:        Secret (a volume populated by a Secret)
    SecretName:  default-token-t664j
    Optional:    false
QoS Class:       BestEffort
Node-Selectors:  <none>
Tolerations:     node.kubernetes.io/not-ready:NoExecute for 300s
                 node.kubernetes.io/unreachable:NoExecute for 300s
Events:
  Type     Reason            Age               From               Message
  ----     ------            ----              ----               -------
  Warning  FailedScheduling  48s (x8 over 1m)  default-scheduler  0/1 nodes are available: 1 Insufficient pods.

ということで、Podは14個までしか起動できませんでした。
したがって、Podの起動数の制限はMaxPodsにも依存していたように思えます。

MaxPodsを変更して試してみる

ENIによる制限とMaxPodsによる制限のうち小さいほうに依存している可能性があるので、さらに検証します。

t2.mediumのMaxPodsを19に書き換えます。

      MaxPods: 737
    t2.micro:
      MaxPods: 4
    t2.small:
      MaxPods: 8
    t2.medium:
      # 17から19に書き換える
      MaxPods: 19
    t2.large:
      MaxPods: 35
    t2.xlarge:
      MaxPods: 44
    t2.2xlarge:

これでもMaxPodsが影響するなら 19 - 3 = 16 個のPodが起動するはずです。
ENIが影響するなら 18 - 3 = 15 個のPodが起動するはずです。

$ kubectl get all
NAME                            READY     STATUS              RESTARTS   AGE
pod/my-nginx-6947c57698-2k9kz   1/1       Running             0          6m
pod/my-nginx-6947c57698-4q8j7   0/1       ContainerCreating   0          6m
pod/my-nginx-6947c57698-5n4hn   1/1       Running             0          6m
pod/my-nginx-6947c57698-7ntlc   1/1       Running             0          6m
pod/my-nginx-6947c57698-96p94   1/1       Running             0          6m
pod/my-nginx-6947c57698-bxqfz   0/1       Pending             0          6m
pod/my-nginx-6947c57698-d4rt8   1/1       Running             0          6m
pod/my-nginx-6947c57698-f2bv7   1/1       Running             0          6m
pod/my-nginx-6947c57698-g2krs   0/1       ContainerCreating   0          6m
pod/my-nginx-6947c57698-kw2dq   1/1       Running             0          6m
pod/my-nginx-6947c57698-kzc4k   1/1       Running             0          6m
pod/my-nginx-6947c57698-mrv8m   1/1       Running             0          6m
pod/my-nginx-6947c57698-sq9td   1/1       Running             0          6m
pod/my-nginx-6947c57698-t9kfq   1/1       Running             0          6m
pod/my-nginx-6947c57698-wnvjf   1/1       Running             0          6m
pod/my-nginx-6947c57698-x8lkg   1/1       Running             0          6m
pod/my-nginx-6947c57698-zbkt7   1/1       Running             0          6m

NAME                 TYPE        CLUSTER-IP   EXTERNAL-IP   PORT(S)   AGE
service/kubernetes   ClusterIP   10.100.0.1   <none>        443/TCP   44m

NAME                       DESIRED   CURRENT   UP-TO-DATE   AVAILABLE   AGE
deployment.apps/my-nginx   17        17        17           14          31m

NAME                                  DESIRED   CURRENT   READY     AGE
replicaset.apps/my-nginx-6947c57698   17        17        14        31m

14個という、予想外の結果になりました。。。

PendingになっているPodの詳細は...

$ kubectl describe pod/my-nginx-6947c57698-bxqfz
Name:           my-nginx-6947c57698-bxqfz
Namespace:      default
Node:           <none>
Labels:         pod-template-hash=2503713254
                run=my-nginx
Annotations:    <none>
Status:         Pending
IP:
Controlled By:  ReplicaSet/my-nginx-6947c57698
Containers:
  my-nginx:
    Image:        nginx:alpine
    Port:         <none>
    Host Port:    <none>
    Environment:  <none>
    Mounts:
      /var/run/secrets/kubernetes.io/serviceaccount from default-token-t664j (ro)
Conditions:
  Type           Status
  PodScheduled   False
Volumes:
  default-token-t664j:
    Type:        Secret (a volume populated by a Secret)
    SecretName:  default-token-t664j
    Optional:    false
QoS Class:       BestEffort
Node-Selectors:  <none>
Tolerations:     node.kubernetes.io/not-ready:NoExecute for 300s
                 node.kubernetes.io/unreachable:NoExecute for 300s
Events:
  Type     Reason            Age               From               Message
  ----     ------            ----              ----               -------
  Warning  FailedScheduling  2m (x26 over 8m)  default-scheduler  0/1 nodes are available: 1 Insufficient pods.

今まで表示されていたのと同様のエラーです。

ContainerCreatingになっているPodの詳細は...

$ kubectl describe pod/my-nginx-6947c57698-4q8j7
Name:           my-nginx-6947c57698-4q8j7
Namespace:      default
Node:           ip-192-168-144-73.us-west-2.compute.internal/192.168.144.73
Start Time:     Tue, 12 Jun 2018 11:25:42 +0900
Labels:         pod-template-hash=2503713254
                run=my-nginx
Annotations:    <none>
Status:         Pending
IP:
Controlled By:  ReplicaSet/my-nginx-6947c57698
Containers:
  my-nginx:
    Container ID:
    Image:          nginx:alpine
    Image ID:
    Port:           <none>
    Host Port:      <none>
    State:          Waiting
      Reason:       ContainerCreating
    Ready:          False
    Restart Count:  0
    Environment:    <none>
    Mounts:
      /var/run/secrets/kubernetes.io/serviceaccount from default-token-t664j (ro)
Conditions:
  Type           Status
  Initialized    True
  Ready          False
  PodScheduled   True
Volumes:
  default-token-t664j:
    Type:        Secret (a volume populated by a Secret)
    SecretName:  default-token-t664j
    Optional:    false
QoS Class:       BestEffort
Node-Selectors:  <none>
Tolerations:     node.kubernetes.io/not-ready:NoExecute for 300s
                 node.kubernetes.io/unreachable:NoExecute for 300s
Events:
  Type     Reason                  Age                From                                                   Message
  ----     ------                  ----               ----                                                   -------
  Normal   Scheduled               9m                 default-scheduler                                      Successfully assigned my-nginx-6947c57698-4q8j7 to ip-192-168-144-73.us-west-2.compute.internal
  Normal   SuccessfulMountVolume   9m                 kubelet, ip-192-168-144-73.us-west-2.compute.internal  MountVolume.SetUp succeeded for volume "default-token-t664j"
  Warning  FailedCreatePodSandBox  8m (x12 over 9m)   kubelet, ip-192-168-144-73.us-west-2.compute.internal  Failed create pod sandbox: rpc error: code = Unknown desc = NetworkPlugin cni failed to set up pod "my-nginx-6947c57698-4q8j7_default" network: add cmd: failed to assign an IP address to container
  Normal   SandboxChanged          4m (x271 over 9m)  kubelet, ip-192-168-144-73.us-west-2.compute.internal  Pod sandbox changed, it will be killed and re-created.

IPアドレスを与えることに失敗しています。

どうやら、MaxPodsとENIの制限と、他にも何らかの制限があるようです。。。
これ以上は未調査です。

結論 (再掲)

EKSのWorkerは、t2.microでも特に問題なく構築でき、Podの起動も可能でした。
ただし、IPアドレス数の制限により、Podは2つ以上起動できませんでした。
IPアドレスが枯渇するとWorkerもPodもスケールできなくなると思われるので、IPアドレス数の制限には注意が必要そうです。
インスタンスタイプごとに、IPアドレス数の制限と、MaxPodsによる制限と、他にも何らかの制限があり、Podの起動数が制限されているようです。
スケールを考えるうえで、Podの起動数の制限には注意が必要そうです。


  1. GKEやAKSと違い、EKSはMasterノードが有料 ($0.20/hr。t2.xlargeよりも高額) なので、Workerを無料枠に入れても仕方ないというのは別のお話です。 

os1ma
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
No comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
ユーザーは見つかりませんでした