Kubernetes(Amazon EKS)に入門してみた
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上で実行するアプリケーションのことをワークロードリソースと呼びます。これには、Pod、ReplicaSet、Deployment、DaemonSet、Jobなどのリソースが含まれます。これらのリソースは、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を管理するためです。
ワークロードリソースにおける親子関係
ワークロードリソースには親子関係があります。DeploymentがReplicaSetの親リソースであり、ReplicaSetがPodの親リソースです。以下の図に示すように、ワークロードリソースの親子関係を理解することが重要です。
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 ControllerやAWS 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