🧢

Kubernetes(Amazon EKS)に入門してみた

2024/06/23に公開

EKSとKubernetesについて

EKS(Elastic Kubernetes Service)は、AWSが提供するマネージドなKubernetesサービスで、Kubernetesのコントロールプレーンをマネージドに利用できるため、運用の負担を大幅に軽減できます。これにより、Kubernetesのワークロードをはじめとするさまざまなリソースを簡単に利用できます。

Kubernetes(K8S)は、Google社内で開発された「Borg」を元にして開発されたオープンソースソフトウェア(OSS)です。Kubernetesはコンテナ化されたアプリケーションのデプロイ、自動スケーリング、管理を行うためのシステムであり、多くのクラウドプロバイダーで利用されています。

コントロールプレーンとワーカーノード

コントロールプレーン(マスターノード)

コントロールプレーンは、クラスタ内のワーカーノードやコンテナ情報を管理するためのノードです。EKSクラスターの中にはコントロールプレーンとワーカーノードが存在します。コントロールプレーンは、クラスタ内のKubernetesオブジェクトの状態を保持し、クライアントからのコマンドや設定ファイルを受け取り、APIアクションを呼び出してコンテナのデプロイや更新を行います。また、スケジューラがコントロールプレーン側で動作し、ワーカーノード上にKubeletというエージェントが動作します。Kubeletは、コントロールプレーンからの指示を受けてコンテナを起動します。

ワーカーノード

ワーカーノードは実際にコンテナが起動するノードであり、コントロールプレーンからの指示を受けてノード上にコンテナを起動します。ワーカーノードとしては、EC2またはFargateを選択できます。

EKSの構成

EKSのコントロールプレーンは、AWSが管理するVPC上に配置され、エンドポイントは公開されていません。そのため、前段にロードバランサーが配置されます。一方、ワーカーノードはユーザーが用意したVPC上でホスティングされ、コントロールプレーンとワーカーノードはAWSによって作成された**ENI(Elastic Network Interface)**を介して通信を行います。ENIは、AWSにおける仮想ネットワークインターフェースで、ネットワーク通信を行うためのリソースです。

ワークロードリソースについて

Kubernetes上で実行するアプリケーションのことをワークロードリソースと呼びます。これには、PodReplicaSetDeploymentDaemonSetJobなどのリソースが含まれます。これらのリソースは、kubectlコマンドを使い、リソース情報をyaml形式ファイルで定義した「マニフェスト」を読み込むことでデプロイされます。

kubectlについて

kubectlコマンドの基本的な形式は以下の通りです:

kubectl [command] [type] [name]

commandはリソースに対して実行したいアクション(例:apply, get, describe, delete)を指定し、typeはリソースタイプ(例:pod, replicasets, deployment)を指定します。nameは実際のリソース名を指定し、省略された場合は全てのリソース詳細が対象となります。例えば、以下のコマンドは、ワーカーノード上の全てのPodの一覧を出力します:

kubectl get pods

また、以下のコマンドは、マニフェスト「shun.yml」の定義を使用してリソースをデプロイします:

kubectl apply -f shun.yml

以下のコマンドは、ノード「shun」の詳細を表示します:

kubectl describe nodes shun

Podについて

PodはKubernetes内で作成、管理できるリソースの最小単位です。Podは1つまたは複数のコンテナのグループであり、複数のコンテナを含むPod内で補助的な役割を担うコンテナをサイドカーと呼びます。Podに含まれるコンテナ同士は同一のIPアドレスを共有し、Pod内での通信はlocalhostを使用します。

以下は、nginxのコンテナを含むPodの定義のサンプルです:

apiVersion: v1
kind: Pod
metadata:
  name: nginx
  namespace: ns-shun
spec:
  containers:
  - name: nginx
    image: nginx:1.14.1
    ports:
    - containerPort: 80

この例では、apiVersionは使用するKubernetes APIのバージョンを指定し、kindは作成するオブジェクトの種類(Pod, ReplicaSet, Deploymentなど)を指定します。metadataにはオブジェクトを一意に識別するための情報(タグやnamespace)が含まれ、specにはオブジェクト毎に定義する詳細情報(コンテナ名、コンテナイメージ、リッスンするポートなど)が含まれます。

Namespaceとは?

Namespaceは、Kubernetesのクラスター内で仮想的にリソースを分離する機能です。Namespaceを使用することで、ワーカーノード上に複数のコンテナを論理的に分割して管理できます。例えば、アプリケーションコンテナと監視用コンテナを分ける場合に利用します。Namespaceを指定しなかった場合、リソースはデフォルトのNamespace(default)に作成されます。

ReplicaSetについて

ReplicaSetは、指定した数のPodを常に稼働させるためのリソースです。ReplicaSetはPodの複製数を維持し、例えば3つのPodを常に稼働させることができます。ReplicaSetのSpec設定では、replicasに複製、維持するPodの台数を指定し、selectorでReplicaSetが管理するPodのラベルを指定します。以下は、ReplicaSetのサンプルです:

apiVersion: apps/v1
kind: ReplicaSet
metadata:
  name: nginx
spec:
  replicas: 3
  selector:
    matchLabels:
      app: nginx
  template:
    metadata:
      labels:
        app: nginx
    spec:
      containers:
      - name: nginx
        image: nginx:1.14.1
        ports:
        - containerPort: 80

この例では、ReplicaSetの中でPodの定義が行われているのは、ReplicaSetがPodのテンプレートを使用してPodを管理するためです。

ワークロードリソースにおける親子関係

ワークロードリソースには親子関係があります。DeploymentReplicaSetの親リソースであり、ReplicaSetPodの親リソースです。以下の図に示すように、ワークロードリソースの親子関係を理解することが重要です。

Deploymentとは?

Deploymentは、ローリングアップデートやロールバックを実現するためのリソースです。ReplicaSetは直接ローリングアップデートをサポートしませんが、Deploymentを使用することでこれを実現できます。Deploymentは複数のReplicaSetを管理します。以下は、Deploymentのサンプルです:

apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx
spec:
  replicas: 3
  selector:
    matchLabels:
      app: nginx
  template:
    metadata:
      labels:
        app: nginx
    spec:
      containers:
      - name: nginx
        image: nginx:1.14.1
        ports:
        - containerPort: 80

この例では、バージョンアップ方法としてデフォルトでローリングアップデート(Rolling Update)が行われます。バージョンアップ方法には、すべてのPodを削除してから新しい

Podを作成するRecreateと、Podのアップデートを段階的に行うRolling Updateがあります。

その他のワークロードリソース

DaemonSetは、各ノードにPodを1台ずつ配置するリソースであり、監視用のエージェント(例:Datadog Agent, Fluentbit)として利用されることがあります。

Jobは、指定した回数分、処理を実行するジョブ用のリソースであり、ジョブを実行後に終了します。

CronJobは、指定した時間にJobを作成して実行します。

StatefulSetは、データベースなどのステートフルなリソースに使用され、Pod名が変わらず、サフィックスが連番で付与されます(例:shun-stateful-0, shun-stateful-1, shun-stateful-2)。

その他のAPIについて

Workloads APIsは、コンテナの実行に関するリソースで、今まで紹介したリソースが含まれます。

Service APIsは、システムを外部公開するためのリソースであり、L4、L7レイヤのロードバランシング機能などを提供します(Service, Ingressなど)。

Config & Storage APIsは、設定情報(ConfigMap)、機密情報の管理(Secret)、永続化ボリューム(PersistentVolumeClaim)などのリソースです。

Service APIs

Load Balancer(ロードバランサー)

EKSでは、ServiceタイプとしてLoadBalancerを使用すると、AWSのElastic Load Balancer(ELB)が自動的に作成されます。このロードバランサーは外部からのトラフィックを受け取り、適切なワーカーノード上のサービスにルーティングします。以下は、LoadBalancerタイプのServiceのサンプルです:

apiVersion: apps/v1
kind: Deployment
metadata:
  name: my-app
spec:
  replicas: 3
  selector:
    matchLabels:
      app: my-app
  template:
    metadata:
      labels:
        app: my-app
    spec:
      containers:
      - name: my-app
        image: my-app-image:latest
        ports:
        - containerPort: 8080
apiVersion: v1
kind: Service
metadata:
  name: my-service
spec:
  type: LoadBalancer  # または ClusterIP
  ports:
    - port: 80
      targetPort: 8080
  selector:
    app: my-app

IngressリソースとIngressコントローラー + Service

Ingressリソースを作成し、外部のHTTP/HTTPSトラフィックをクラスタ内のサービスにルーティングする場合には、Ingressコントローラーが必要です。EKSでは一般的にNginx Ingress ControllerAWS Load Balancer Controllerが使用されます。以下は、IngressリソースとServiceのサンプルです:

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: my-ingress
  annotations:
    kubernetes.io/ingress.class: alb  # or nginx
    alb.ingress.kubernetes.io/scheme: internet-facing
    alb.ingress.kubernetes.io/target-type: ip
    alb.ingress.kubernetes.io/listen-ports: '[{"HTTP": 80}]'
spec:
  ingressClassName: alb  # or nginx
  rules:
    - host: example.com
      http:
        paths:
          - path: /
            pathType: Prefix
            backend:
              service:
                name: my-service
                port:
                  number: 80
apiVersion: v1
kind: Service
metadata:
  name: my-service
spec:
  type: ClusterIP  # or LoadBalancer, if you want to expose the service externally
  ports:
    - port: 80
      targetPort: 8080
  selector:
    app: my-app
apiVersion: apps/v1
kind: Deployment
metadata:
  name: my-app
spec:
  replicas: 3
  selector:
    matchLabels:
      app: my-app
  template:
    metadata:
      labels:
        app: my-app
    spec:
      containers:
      - name: my-app
        image: my-app-image:latest
        ports:
        - containerPort: 8080

まとめ

Kubernetes(EKS)に入門してみました。
必要最低限のワーカーノードを中心にして解説しました。次回は実際にEKSクラスターを作成して、アプリケーションをデプロイしてみたいと思います。

Discussion