LoginSignup
3
2

More than 3 years have passed since last update.

Amazon EKSのチュートリアルをやってみて、Kubernetesによるコンテナ管理に触れてみる

Last updated at Posted at 2020-04-01

Kubernetesをローカル環境で使用したことはありましたが、複数ホストをまたいだコンテナ管理に触れてみたいということで、Amazon EKSのチュートリアル をやってみました。ハマりポイントもあったので、勘所をまとめています。

前提

  • クライアント側の作業はmacOSで実施
  • macOSにはAWS CLIとkubectlをインストールしていること

たとえば、クライアントがv1.2であれば、v1.1、v1.2、v1.3のマスターで動作するはずです。最新バージョンのkubectlを使うことで、不測の事態を避けることができるでしょう。

今回のゴール

今回構築するシステムの構成図はこちらです。
eks_schedule.png
AWSリソースとKubernetesリソースを一緒に表現しているため、分かりにくいかもしれませんが、3つのAZ(サブネット)にまたがるWeb+Redisアプリケーションを構築します。EKSクラスターとは、Kubernetesの様々なリソースを管理する集合体のことを指します。

Kubernetesリソースの基本説明

リソース名 用途
Node コンテナを配置するためのホスト(EC2に相当)
Pod 複数のコンテナの集合体(単体のケースもある)
Service Podの集合体への通信経路を定義

EKSの利用方法

2通りの方法が存在しますが、今回はAWSマネジメントコンソールで実施しています。

  • eksctlを使用
  • AWSマネジメントコンソールを使用

作業手順

以下の作業を順番に実施していきます。
※ 詳細は AWSマネジメントコンソールの開始方法 を参照

EKSサービスロールを作成する

EKSクラスターが各種AWSリソースを参照・作成するために必要なIAMロールです。
下記のテンプレートを使用して、AWS CloudFormationコンソールでスタックを作成します。

eks-service-role.yml
---
AWSTemplateFormatVersion: '2010-09-09'
Description: 'Amazon EKS Service Role'


Resources:

  eksServiceRole:
    Type: AWS::IAM::Role
    Properties:
      AssumeRolePolicyDocument:
        Version: '2012-10-17'
        Statement:
        - Effect: Allow
          Principal:
            Service:
            - eks.amazonaws.com
          Action:
          - sts:AssumeRole
      ManagedPolicyArns:
        - arn:aws:iam::aws:policy/AmazonEKSServicePolicy
        - arn:aws:iam::aws:policy/AmazonEKSClusterPolicy

Outputs:

  RoleArn:
    Description: The role that Amazon EKS will use to create AWS resources for Kubernetes clusters
    Value: !GetAtt eksServiceRole.Arn
    Export:
      Name: !Sub "${AWS::StackName}-RoleArn"

EKSワーカーノードロールを作成する

EKSワーカーノードが各種AWSリソースを参照・作成するために必要なIAMロールです。
下記のS3テンプレートURLを指定して、AWS CloudFormationコンソールでスタックを作成します。

EKSクラスターVPCを作成する

下記のS3テンプレートURLを指定して、AWS CloudFormationコンソールでスタックを作成します。

今回、AZ (ap-northeast-1aap-northeast-1cap-northeast-1d) にまたがる3つのパブリックサブネットを持つVPCを構築します。

スタック作成中に Template error: Fn::Select cannot select nonexistent value at index 2 エラーが発生した場合
使用しているAWSアカウントでは、default subnetにap-northeast-1dが含まれていない可能性が高いので、以下のコマンドを実行してから、再度スタックの作成をしてみてください。

$ aws ec2 create-default-subnet --availability-zone ap-northeast-1d

EKSクラスターを作成する

任意のクラスター名を入力して、事前に作成したEKSサービスロール、VPC、サブネット、セキュリティーグループを指定します。
スクリーンショット 2020-03-29 22.27.50.png
スクリーンショット 2020-03-29 22.28.09.png

kubeconfigファイルを作成する

$ aws eks --region ap-northeast-1 update-kubeconfig --name <cluster name>
Added new context arn:aws:eks:ap-northeast-1:************:cluster/<cluster name> to /Users/********/.kube/config

上記コマンドでkubectlのカレントの接続先にEKSクラスターが上書き設定されます。
※ kubeconfigについては、kubectlの接続設定ファイル(kubeconfig)の概要 を参照

EKSノードグループを起動する

EKSクラスター上に、ノードグループを起動します。
スクリーンショット 2020-03-29 23.08.43.png
任意のノードグループ名を入力して、事前に作成したEKSワーカーノードロール、サブネットを指定します。

スクリーンショット 2020-03-29 23.10.19.png
ここではインスタンスタイプを指定しますが、重要なポイントとして、KubernetesはPod単位でプライベートIPアドレスが割り振られるため、ノード(=ホスト)に配置するPod数を計算して、適切なインスタンスタイプを選ぶ必要があります。

例)T3系の最大IP数

インスタンスタイプ 最大ENI数(1) ENIあたりIP数(2) 最大IP数(1)×(2)
t3.micro 2 2 4
t3.small 3 4 12
t3.medium 3 6 18
t3.large 3 12 36

※ 詳細はElastic Network Interface を参照

なお、kube-systemと呼ばれるシステム用のNamespace上でもIPアドレスは利用されているため、それらを引いた数がPodで使用できるIP数となります。

$ kubectl get pod --namespace kube-system -o wide
NAME                       READY   STATUS    RESTARTS   AGE   IP                NODE                                                 NOMINATED NODE   READINESS GATES
aws-node-d5krq             1/1     Running   0          62m   192.168.220.97    ip-192-168-220-97.ap-northeast-1.compute.internal    <none>           <none>
aws-node-flh75             1/1     Running   0          62m   192.168.152.228   ip-192-168-152-228.ap-northeast-1.compute.internal   <none>           <none>
aws-node-mnpxl             1/1     Running   0          62m   192.168.113.251   ip-192-168-113-251.ap-northeast-1.compute.internal   <none>           <none>
coredns-58986cd576-kc8xv   1/1     Running   0          95m   192.168.171.225   ip-192-168-152-228.ap-northeast-1.compute.internal   <none>           <none>
coredns-58986cd576-rqwqs   1/1     Running   0          95m   192.168.225.139   ip-192-168-220-97.ap-northeast-1.compute.internal    <none>           <none>
kube-proxy-j9lk5           1/1     Running   0          62m   192.168.152.228   ip-192-168-152-228.ap-northeast-1.compute.internal   <none>           <none>
kube-proxy-jgmfb           1/1     Running   0          62m   192.168.220.97    ip-192-168-220-97.ap-northeast-1.compute.internal    <none>           <none>
kube-proxy-rfjtd           1/1     Running   0          62m   192.168.113.251   ip-192-168-113-251.ap-northeast-1.compute.internal   <none>           <none>

スクリーンショット 2020-03-29 23.10.59.png
最後にノード数ですが、こちらも事前に作成したサブネットや配置するリソースに応じて、適切な数を指定する必要があります。

サンプルアプリケーションを起動する

ここからサンプルのゲストブックアプリケーションを作成します。
※ 詳細は ゲストブックアプリケーションを起動する を参照

Redisマスターレプリケーションコントローラーを作成 (Pod作成)

$ kubectl apply -f https://raw.githubusercontent.com/kubernetes/examples/master/guestbook-go/redis-master-controller.json

Redisマスターサービスを作成 (Service作成)

$ kubectl apply -f https://raw.githubusercontent.com/kubernetes/examples/master/guestbook-go/redis-master-service.json

RedisマスターPodがノードグループのうち1ノードに配置され、そのPodへの通信経路であるServiceも作成されています。

$ kubectl get pod,svc -o wide
NAME                     READY   STATUS    RESTARTS   AGE     IP               NODE                                                 NOMINATED NODE   READINESS GATES
pod/redis-master-5l8nr   1/1     Running   0          9m25s   192.168.74.238   ip-192-168-113-251.ap-northeast-1.compute.internal   <none>           <none>

NAME                   TYPE        CLUSTER-IP     EXTERNAL-IP   PORT(S)    AGE     SELECTOR
service/kubernetes     ClusterIP   10.100.0.1     <none>        443/TCP    11h     <none>
service/redis-master   ClusterIP   10.100.59.64   <none>        6379/TCP   4m31s   app=redis,role=master

PodとServiceの関係性について、もう少し触れておくと、実行した下記の定義ファイルにあるように、PodのラベルとServiceのセレクタが合致した場合、対象のPodはそのServiceのターゲットとなり、Serviceを経由してトラフィックが流れる仕組みになっています。

redis-master-controller.json
"template":{
   "metadata":{
      "labels":{
         "app":"redis",
         "role":"master"
      }
   },
redis-master-service.json
"selector":{
   "app":"redis",
   "role":"master"
}

Redisスレーブレプリケーションコントローラーを作成 (Pod作成)

$ kubectl apply -f https://raw.githubusercontent.com/kubernetes/examples/master/guestbook-go/redis-slave-controller.json

Redisスレーブサービスを作成 (Service作成)

$ kubectl apply -f https://raw.githubusercontent.com/kubernetes/examples/master/guestbook-go/redis-slave-service.json

RedisスレーブPod(レプリカ数2)がノードグループのうち2ノードに配置され、そのPodへの通信経路であるServiceも作成されています。

$ kubectl get pod,svc -o wide
NAME                     READY   STATUS    RESTARTS   AGE     IP                NODE                                                 NOMINATED NODE   READINESS GATES
pod/redis-master-5l8nr   1/1     Running   0          28m     192.168.74.238    ip-192-168-113-251.ap-northeast-1.compute.internal   <none>           <none>
pod/redis-slave-hqpd2    1/1     Running   0          4m48s   192.168.192.184   ip-192-168-220-97.ap-northeast-1.compute.internal    <none>           <none>
pod/redis-slave-nrnwk    1/1     Running   0          4m48s   192.168.133.49    ip-192-168-152-228.ap-northeast-1.compute.internal   <none>           <none>

NAME                   TYPE        CLUSTER-IP       EXTERNAL-IP   PORT(S)    AGE     SELECTOR
service/kubernetes     ClusterIP   10.100.0.1       <none>        443/TCP    11h     <none>
service/redis-master   ClusterIP   10.100.59.64     <none>        6379/TCP   23m     app=redis,role=master
service/redis-slave    ClusterIP   10.100.106.145   <none>        6379/TCP   4m34s   app=redis,role=slave

ゲストブックレプリケーションコントローラーを作成 (Pod作成)

$ kubectl apply -f https://raw.githubusercontent.com/kubernetes/examples/master/guestbook-go/guestbook-controller.json

ゲストブックサービスを作成 (Service作成)

$ kubectl apply -f https://raw.githubusercontent.com/kubernetes/examples/master/guestbook-go/guestbook-service.json

ゲストブックPod(レプリカ数3)がノードグループのうち3ノードに均等に配置され、そのPodへの通信経路であるServiceも作成されています。

$ kubectl get pod,svc -o wide
NAME                     READY   STATUS    RESTARTS   AGE     IP                NODE                                                 NOMINATED NODE   READINESS GATES
pod/guestbook-2wcm6      1/1     Running   0          4m20s   192.168.222.236   ip-192-168-220-97.ap-northeast-1.compute.internal    <none>           <none>
pod/guestbook-cnl46      1/1     Running   0          4m20s   192.168.124.194   ip-192-168-113-251.ap-northeast-1.compute.internal   <none>           <none>
pod/guestbook-smjjm      1/1     Running   0          4m20s   192.168.160.43    ip-192-168-152-228.ap-northeast-1.compute.internal   <none>           <none>
pod/redis-master-5l8nr   1/1     Running   0          38m     192.168.74.238    ip-192-168-113-251.ap-northeast-1.compute.internal   <none>           <none>
pod/redis-slave-hqpd2    1/1     Running   0          14m     192.168.192.184   ip-192-168-220-97.ap-northeast-1.compute.internal    <none>           <none>
pod/redis-slave-nrnwk    1/1     Running   0          14m     192.168.133.49    ip-192-168-152-228.ap-northeast-1.compute.internal   <none>           <none>

NAME                   TYPE           CLUSTER-IP       EXTERNAL-IP                                                                    PORT(S)          AGE     SELECTOR
service/guestbook      LoadBalancer   10.100.186.33    ac867331c722611ea8bc70e5c3799917-1903484356.ap-northeast-1.elb.amazonaws.com   3000:32317/TCP   4m13s   app=guestbook
service/kubernetes     ClusterIP      10.100.0.1       <none>                                                                         443/TCP          12h     <none>
service/redis-master   ClusterIP      10.100.59.64     <none>                                                                         6379/TCP         33m     app=redis,role=master
service/redis-slave    ClusterIP      10.100.106.145   <none>                                                                         6379/TCP         14m     app=redis,role=slave

システム構成も冒頭に説明した 今回のゴール 通りに作られているようです。

ゲストブックアプリケーションにブラウザでアクセス

http://ac867331c722611ea8bc70e5c3799917-1903484356.ap-northeast-1.elb.amazonaws.com:3000
スクリーンショット 2020-03-30 10.44.11.png

無事、ゲストブックアプリケーションが表示されました。

さいごに

今回のチュートリアルでは、作成したRedisおよびゲストブックPodが、均等に各ノードに配置されています。これにはタネも仕掛けも分からず、どこか釈然としない気持ちになってしまいましたが、Kubernetesの公式ドキュメントに以下の一節を見つけました。
Node上へのPodのスケジューリング

Podが稼働するNodeを特定のものに指定したり、優先条件を指定して制限することができます。 これを実現するためにはいくつかの方法がありますが、推奨されている方法はラベルでの選択です。 スケジューラーが最適な配置を選択するため、一般的にはこのような制限は不要です。

柔軟な指定もできるようですが、スケジューラー(Podのノードへの割り当てをつかさどるマスターコンポーネント)が頑張ってくれるようです。流石。

3
2
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
3
2