Amazon Elastic Kubernetes Service (EKS) の利用方法(3/3)


Amazon EKS とは
--
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2920213/68e963ac-056f-85c1-b7ce-40a9b05b1c4e.png)
https://docs.aws.amazon.com/ja_jp/eks/latest/userguide/what-is-eks.html

__EKS（Elastic Kubernetes Service）は、Amazon Web Services（AWS）が提供する、マネージドKubernetesサービスの1つです。EKSは、Kubernetesのコントロールプレーンを自動的にデプロイして管理することで、クラスターの構成、スケーリング、アップグレード、パッチ適用などのタスクを簡素化し、開発者やシステム管理者がKubernetesをより簡単に利用できるようにします。__

EKSは、KubernetesのワーカーノードをAWS上で実行するために必要なリソース（EC2インスタンス、ネットワーク、セキュリティグループ、ロードバランサーなど）を自動的にプロビジョニングすることができます。EKSクラスターを作成するには、AWS Management Console、AWS CLI、またはAWS SDKを使用できます。

EKSは、多くのAWSサービスと統合されており、例えばAmazon EC2、Amazon EBS、Amazon VPC、AWS IAM、Amazon CloudWatchなどのリソースとシームレスに連携して利用できます。また、EKSはオープンソースのKubernetesと互換性があり、既存のKubernetesアプリケーションやツールをEKS上で動作させることができます。

今回取り上げる内容
1.ReplicaSet作成
2.Deployment作成
3.Service作成
4.ConfigMap作成
5.Secret作成
6.永続データ作成
7.StatefulSetの作成
8.Ingressの作成

追加説明
◆Podに入ってコマンド実行
kubectl exec
kubectl run
kubectl attach
◆Pod⇔ホスト間のファイル転送
kubectl cp
◆ログ確認
kubectl describe
kubectl logs

1.ReplicaSet作成
--
1. ReplicaSetマニフェストファイル作成
2. リソース作成
3. 手動スケールアウト

__ReplicaSetを作成し、手動でスケールアウトする手順です。__

1.ReplicaSetマニフェストファイルを作成する
nginx:latestイメージを使用してReplicaSetを作成するための例です。
~~~
apiVersion: apps/v1
kind: ReplicaSet
metadata:
  name: example-replicaset
spec:
  replicas: 3
  selector:
    matchLabels:
      app: nginx
  template:
    metadata:
      labels:
        app: nginx
    spec:
      containers:
      - name: example-container
        image: nginx:latest
~~~
このマニフェストファイルでは、3つのレプリカを持つReplicaSetを作成し、
nginx:latestイメージを使用してコンテナを実行します。

__2.リソース作成__
kubectlコマンドを使用して、ReplicaSetを作成します。
上記のマニフェストファイルを使用してReplicaSetを作成するためのkubectlコマンドの例です。
~~~
kubectl apply -f example-replicaset.yaml
~~~
このコマンドは、example-replicaset.yamlファイルで指定されたReplicaSetを作成します。

__3.手動スケールアウト__
ReplicaSetを手動でスケールアウトするには、kubectlコマンドを使用します。
ReplicaSetを5つのレプリカにスケールアウトするためのkubectlコマンドの例です。
~~~
kubectl scale replicaset example-replicaset --replicas=5
~~~
このコマンドは、example-replicasetという名前のReplicaSetを5つのレプリカにスケールアウトします。

このように、ReplicaSetを作成し、手動でスケールアウトすることができます。

2.Deployment作成
--
1. Deploymentマニフェストファイル作成
2. リソース作成
3. ロールアウト履歴確認
4. Deployment修正
5. ロールアウト履歴確認
6. ロールバック


__1.Deploymentマニフェストファイル作成__
Deploymentは、Podを管理するリソースの一つであり、複数のPodを作成してスケーリングすることができます。
例としてnginxイメージを使用したDeploymentマニフェストファイルの例です。
~~~
apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx-deployment
  labels:
    app: nginx
spec:
  replicas: 3
  selector:
    matchLabels:
      app: nginx
  template:
    metadata:
      labels:
        app: nginx
    spec:
      containers:
      - name: nginx
        image: nginx:latest
        ports:
        - containerPort: 80
~~~

__2.リソース作成__
作成したDeploymentマニフェストファイルをkubectlコマンドを使用してクラスタに適用します。
~~~
$ kubectl apply -f nginx-deployment.yaml
~~~

__3.ロールアウト履歴確認__
Deploymentを作成すると、自動的にロールアウトが開始されます。
ロールアウトの進捗状況を確認するには、以下のようにkubectlコマンドを使用します。
~~~
$ kubectl rollout status deployment/nginx-deployment
~~~

__4.Deployment修正__
Deploymentを修正する場合は、マニフェストファイルを更新します。
例えば、replicasを5に変更する場合は、次のようにします。
~~~
apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx-deployment
  labels:
    app: nginx
spec:
  replicas: 5
  selector:
    matchLabels:
      app: nginx
  template:
    metadata:
      labels:
        app: nginx
    spec:
      containers:
      - name: nginx
        image: nginx:latest
        ports:
        - containerPort: 80
~~~

__5.ロールアウト履歴確認__
Deploymentを修正した場合、自動的にロールアウトが開始されます。
ロールアウトの進捗状況を確認するには、次のようにkubectlコマンドを使用します。
~~~
$ kubectl rollout status deployment/nginx-deployment
~~~
__6.ロールバック__
Deploymentの修正がうまくいかなかった場合、以前のバージョンにロールバックすることができます。
次のようにkubectlコマンドを使用します。
~~~
$ kubectl rollout undo deployment/nginx-deployment
~~~
ロールバックする際に、特定のリビジョンに戻したい場合は、
次のように--to-revisionオプションを使用します。
~~~
$ kubectl rollout undo deployment/nginx-deployment --to-revision=2
~~~

3.Service作成
--
1. NodePortのServiceマニフェストファイル作成
2. リソース作成
3. ブラウザからアクセスして動作確認

Kubernetes上でNodePortタイプのServiceを作成する手順を説明します。

__1.NodePortのServiceマニフェストファイル作成__
ポート番号が30000であるServiceを定義する例です。
~~~
apiVersion: v1
kind: Service
metadata:
  name: example-service
spec:
  type: NodePort
  selector:
    app: example-app
  ports:
    - name: http
      protocol: TCP
      port: 80
      targetPort: 8080
      nodePort: 30000
~~~
このマニフェストファイルでは、Serviceの種類をNodePortに指定し、selectorによってServiceが関連付けられるPodを指定しています。portsでServiceが使用するポートを指定し、nodePortで外部からServiceにアクセスするためのポート番号を指定しています。

__2.リソース作成__
作成したマニフェストファイルをkubectl applyコマンドで適用してリソースを作成します。
~~~
kubectl apply -f example-service.yaml
~~~

__3.ブラウザからアクセスして動作確認__
Serviceが作成されたら、外部からServiceにアクセスするために、ServiceがデプロイされているKubernetesクラスタのノードのIPアドレスを調べます。
~~~
kubectl get nodes -o wide
~~~
これで、Serviceが公開しているポート番号(例: 30000)を指定して、ブラウザからアクセスして動作確認ができます。

4.ConfigMap作成
--
1. ConfigMapとPodを含むマニフェストファイル作成
2.マニフェストファイルを適用してPodを作成します
3. Podに入ってConfigMapが接続されていることを確認

1.ConfigMapの定義を記述したマニフェストファイルを作成します。
例えば、次のようなconfigmap.yamlというファイルを作成します。

~~~
apiVersion: v1
kind: ConfigMap
metadata:
  name: my-config
data:
  my-key: my-value
~~~
この例では、my-configという名前のConfigMapが作成され、その中にmy-keyというキーとmy-valueという値が格納されます。

__マニフェストファイルを適用してConfigMapを作成します。__
~~~
$ kubectl apply -f configmap.yaml
~~~
Podを含むマニフェストファイルを作成します。
例えば、次のようなpod-with-configmap.yamlというファイルを作成します。
~~~
apiVersion: v1
kind: Pod
metadata:
  name: my-pod
spec:
  containers:
    - name: my-container
      image: nginx
      volumeMounts:
        - name: config-volume
          mountPath: /etc/config
  volumes:
    - name: config-volume
      configMap:
        name: my-config
~~~
この例では、my-podという名前のPodが作成され、その中にnginxというコンテナが定義されます。
config-volumeという名前のボリュームが作成され、その中にはmy-configという名前のConfigMapがマウントされます。
my-containerコンテナは/etc/configディレクトリにConfigMapがマウントされたボリュームをマウントしています。

__2.マニフェストファイルを適用してPodを作成します。__
~~~
$ kubectl apply -f pod-with-configmap.yaml
~~~

__3.Podに入ってConfigMapが接続されていることを確認します。__
~~~
$ kubectl exec -it my-pod -- /bin/bash
root@my-pod:/# cat /etc/config/my-key
my-value
~~~
この例では、my-podという名前のPodにexecコマンドを実行してコンテナに入り、/etc/config/my-keyというファイルを読み込んでいます。このファイルには、ConfigMapで定義されたmy-keyの値であるmy-valueが格納されていることが確認できます。

5.Secret作成
--
1. SecretとPodを含むマニフェストファイル作成
2. リソース作成
3. Podに入ってSecretが接続されていることを確認

1.SecretとPodを含むマニフェストファイル作成
KubernetesにおいてSecretとPodを作成するためのマニフェストファイルの例です。
~~~
apiVersion: v1
kind: Secret
metadata:
  name: mysecret
type: Opaque
data:
  username: <base64-encoded-username>
  password: <base64-encoded-password>
---
apiVersion: v1
kind: Pod
metadata:
  name: mypod
spec:
  containers:
  - name: mycontainer
    image: myimage
    env:
    - name: USERNAME
      valueFrom:
        secretKeyRef:
          name: mysecret
          key: username
    - name: PASSWORD
      valueFrom:
        secretKeyRef:
          name: mysecret
          key: password
~~~

__2.リソース作成__
~~~
$ kubectl apply -f mypod.yaml
~~~

__3.Podに入ってSecretが接続されていることを確認__
~~~
$ kubectl exec -it mypod -- /bin/bash
$ env | grep USERNAME
USERNAME=<decoded-username>
$ env | grep PASSWORD
PASSWORD=<decoded-password>
~~~
この例では、Secretにはusernameとpasswordという2つのキーがあり、それぞれbase64でエンコードされた値が含まれています。
Podでは、envセクションを使用して、Secretの値を環境変数として読み込むように設定されています。
最後に、kubectl execコマンドを使用して、Pod内で環境変数が正しく設定されていることを確認します。

6.永続データ作成
--
1. PVとPVCを含むマニフェストファイル作成
2. リソース作成

1.PVとPVCを含むマニフェストファイル作成
Kubernetesにおいて永続データを作成するためのマニフェストファイルの例です。
~~~
apiVersion: v1
kind: PersistentVolume
metadata:
  name: my-pv
spec:
  capacity:
    storage: 1Gi
  accessModes:
    - ReadWriteOnce
  persistentVolumeReclaimPolicy: Retain
  storageClassName: slow
  hostPath:
    path: /mnt/data

---
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: my-pvc
spec:
  accessModes:
    - ReadWriteOnce
  resources:
    requests:
      storage: 1Gi
  storageClassName: slow

~~~

__2.リソース作成__
~~~
$ kubectl apply -f my-pv-pvc.yaml
~~~
この例では、永続化されるデータのための永続ボリューム(PV)と永続ボリュームクレーム(PVC)を作成しています。
PVは、hostPathを使用してホストのファイルシステムにマウントされ、PVCはPVを要求して永続化されるデータを格納する場所を指定します。
この例では、PVCはmy-pvcという名前で1Giのストレージを要求し、slowストレージクラスを使用します。
PVはmy-pvという名前で1Giのストレージを提供し、ReadWriteOnceアクセスモードを持ち、再利用する場合のポリシーを指定するRetainポリシーを使用します。

マニフェストを作成した後は、kubectl applyコマンドを使用してリソースを作成できます。


7.StatefulSetの作成
--
1. StatefulSetおよびServiceのマニフェストを作成
2. デバッグ用PodからService経由でPodにアクセス

__1.StatefulSetおよびServiceのマニフェストを作成__
KubernetesにおいてStatefulSetとServiceを作成するためのマニフェストファイルの例です。
~~~
apiVersion: apps/v1
kind: StatefulSet
metadata:
  name: my-statefulset
spec:
  serviceName: my-service
  replicas: 3
  selector:
    matchLabels:
      app: my-app
  template:
    metadata:
      labels:
        app: my-app
    spec:
      containers:
      - name: my-container
        image: my-image
        ports:
        - containerPort: 8080
        volumeMounts:
        - name: my-pvc
          mountPath: /data
  volumeClaimTemplates:
  - metadata:
      name: my-pvc
    spec:
      accessModes: [ "ReadWriteOnce" ]
      resources:
        requests:
          storage: 1Gi

---
apiVersion: v1
kind: Service
metadata:
  name: my-service
spec:
  selector:
    app: my-app
  ports:
  - name: http
    port: 80
    targetPort: 8080
~~~

__2.デバッグ用PodからService経由でPodにアクセス__
~~~
$ kubectl run -it --rm debug --image=busybox --restart=Never -- /bin/sh
/ # nslookup my-service
Server:    10.96.0.10
Address 1: 10.96.0.10 kube-dns.kube-system.svc.cluster.local

Name:      my-service.default.svc.cluster.local
Address 1: 10.244.2.2 my-statefulset-1.my-service.default.svc.cluster.local
Address 2: 10.244.3.3 my-statefulset-2.my-service.default.svc.cluster.local
Address 3: 10.244.4.4 my-statefulset-0.my-service.default.svc.cluster.local
/ # wget -O - http://my-service.default.svc.cluster.local:80
~~~
この例では、StatefulSetとServiceの2つのマニフェストファイルがあります。
StatefulSetは3つのレプリカを持ち、my-containerコンテナを含むPodテンプレートを使用しています。
このコンテナは、my-pvcという名前の永続ボリュームをマウントして、/dataディレクトリにアクセスできるようになっています。
Serviceは、my-appというラベルを持つPodにトラフィックを転送し、ポート80を使用します。

デバッグ用のPodを起動し、nslookupコマンドでServiceの名前解決を行い、結果を表示してから、wgetコマンドを使用して
Serviceにアクセスします。StatefulSetによって作成された3つのPodのうち、1つが応答するはずです。

8.Ingressの作成
--
1. Deployment, Service を準備
2. Ingress を作成
3. 外部からアクセス

KubernetesにおいてIngressを作成するための例です。

__1.Deployment, Service を準備__
DeploymentとServiceのマニフェストを作成します。
~~~
apiVersion: apps/v1
kind: Deployment
metadata:
  name: my-deployment
spec:
  replicas: 3
  selector:
    matchLabels:
      app: my-app
  template:
    metadata:
      labels:
        app: my-app
    spec:
      containers:
      - name: my-container
        image: my-image
        ports:
        - containerPort: 8080
---
apiVersion: v1
kind: Service
metadata:
  name: my-service
spec:
  selector:
    app: my-app
  ports:
  - name: http
    port: 80
    targetPort: 8080
~~~

__2.Ingress を作成__
Ingressのマニフェストを作成します。
~~~
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: my-ingress
  annotations:
    nginx.ingress.kubernetes.io/rewrite-target: /
spec:
  rules:
  - host: example.com
    http:
      paths:
      - path: /app
        pathType: Prefix
        backend:
          service:
            name: my-service
            port:
              name: http
~~~
この例では、Ingressを作成し、ホスト名example.comにアクセスした場合にServiceにルーティングするように指定しています。
また、/appというパスがある場合にServiceにルーティングするようにも指定しています。

__3.外部からアクセス__
Ingressを作成した後、外部からIngressにアクセスできるように設定する必要があります。
このためには、KubernetesクラスターにIngress Controllerをインストールする必要があります。
代表的なIngress Controllerには、NGINX、Traefik、GKE Ingressがあります。

NGINX Ingress Controllerを使用する場合は、次のコマンドを実行して、必要なリソースを作成します。
~~~
$ kubectl apply -f https://raw.githubusercontent.com/kubernetes/ingress-nginx/controller-v1.1.0/deploy/static/provider/cloud/deploy.yaml
~~~
Ingress Controllerをインストールしたら、Ingressにアクセスするために使用するIPアドレスまたはドメイン名を取得する必要があります。これは、Ingress Controllerによって異なります。たとえば、NGINX Ingress Controllerを使用する場合は、次のコマンドを使用して、Ingress ControllerのIPアドレスを取得できます。
~~~
$ kubectl get services -n ingress-nginx ingress-nginx-controller
~~~
取得したIPアドレスを使用して、ブラウザなどのクライアントからIngressにアクセスできます。
例えば、http://example.com/appにアクセスすると、IngressによってServiceにルーティングされます。

追加説明
==
◆Podに入ってコマンド実行
Kubernetesの場合、Podに入ってコマンドを実行するには、次のような方法があります。

__kubectl execを使用する方法__
kubectl execコマンドを使用して、Podに対してコマンドを実行できます。
Podに入ってlsコマンドを実行する例です。
~~~
kubectl exec -it <pod-name> -- ls

~~~
-itオプションは、対話的なモードで実行するためのオプションです。
<pod-name>には、実行したいPodの名前を指定します。コマンドを実行する際には、--の後にコマンドを指定します。

__kubectl runを使用する方法__
kubectl runコマンドを使用して、Podを新たに作成し、その中でコマンドを実行できます。
Podに入ってlsコマンドを実行する例です。
~~~
kubectl run -it --rm --image=<image-name> my-pod -- ls
~~~
-itオプションは、対話的なモードで実行するためのオプションです。--rmオプションは、コマンド実行後にPodを削除するためのオプションです。--imageオプションは、実行したいコマンドを含むコンテナイメージを指定します。my-podには、新たに作成されるPodの名前を指定します。コマンドを実行する際には、Podが作成された後に対話的なモードで入るため、--の後にコマンドを指定しません。

__kubectl attachを使用する方法__
kubectl attachコマンドを使用して、既に実行中のPodに対して入ってコマンドを実行できます。
Podに入ってlsコマンドを実行する例です。
~~~
kubectl attach -it <pod-name>
~~~
-itオプションは、対話的なモードで実行するためのオプションです。
<　pod-name　>には、入りたいPodの名前を指定します。Podに入った後に、コマンドを実行できます。

◆Pod⇔ホスト間のファイル転送
Kubernetesの場合、Podとホスト間でファイルを転送するには、次のような方法があります。

__kubectl cpを使用する方法__
kubectl cpコマンドを使用して、ファイルをPodとホスト間で転送できます。
Podからローカルのファイルをホストに転送する例です。
~~~
kubectl cp <pod-name>:<source-path> <destination-path>
~~~
< pod-name>には、転送元のPodの名前を指定します。< source-path>には、転送元のファイルのパスを指定します。
< destination-path>には、転送先のパスを指定します。

ホストからPodにファイルを転送する例です。
~~~
kubectl cp <source-path> <pod-name>:<destination-path>
~~~
< source-path> には、転送元のファイルのパスを指定します。< destination-path> には、転送先のパスを指定します。

Volumeを使用する方法
Volumeを使用して、Podとホスト間でデータを共有することができます。
Podとホストで同じディレクトリをマウントするVolumeを作成する例です。
~~~
apiVersion: v1
kind: Pod
metadata:
  name: my-pod
spec:
  containers:
  - name: my-container
    image: my-image
    volumeMounts:
    - name: shared-data
      mountPath: /data
  volumes:
  - name: shared-data
    hostPath:
      path: /host-data
      type: Directory
~~~
hostPathフィールドにホスト上のディレクトリを指定することで、Pod内の/dataディレクトリにホスト上のディレクトリがマウントされます。ホスト上のディレクトリにファイルを保存することで、Pod内からアクセスすることができます。

注意：Volumeを使用する場合、Podとホスト間で共有されるため、セキュリティ上のリスクが存在します。ファイルを共有する必要がある場合は、適切なアクセス制御を実施してください。


◆ログ確認
KubernetesでPodやDeploymentなどのリソースのログを確認するには、次のような方法があります。

kubectl describeコマンドを使用する方法
kubectl describeコマンドを使用することで、PodやDeploymentの詳細情報を確認できます。
ログに関する情報も含まれます。
Podの詳細情報を確認する例です。
~~~
kubectl describe pod <pod-name>
~~~
ログに関する情報は、Eventsセクションに表示されます。
ここには、Podがどのような状態になっているか、何が起こっているかなどが記録されます。

__kubectl logsコマンドを使用する方法__
kubectl logsコマンドを使用することで、Podのログを確認できます。
Podのログを確認する例です。
~~~
kubectl logs <pod-name>
~~~
デフォルトでは、最新のログが表示されます。-fオプションを付けることで、ログのリアルタイムな出力も可能です。
~~~
kubectl logs -f <pod-name>
~~~
DeploymentやReplicaSetなどの場合、Podの名前がランダムに生成されます。
そのため、kubectl logsコマンドで直接Podの名前を指定することはできません。
代わりに、-lオプションを使用して、ラベルを指定することができます。
特定のラベルを持つPodのログを確認する例です。
~~~
kubectl logs -l <label-key>=<label-value>
~~~

Amazon Elastic Kubernetes Service (EKS) の利用方法(1/3)
https://qiita.com/kimuni-i/items/656ca4d314a8982e70cb

Amazon Elastic Kubernetes Service (EKS) の利用方法(2/3)
https://qiita.com/kimuni-i/items/06c70de226cf074d8b23

Amazon Elastic Kubernetes Service (EKS) の利用方法(3/3)
https://qiita.com/kimuni-i/items/b2b3d07c2c76c95884a1