2
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

【AWS】EKS on Fargateでゲームをデプロイしてみたので解説してみる(with Ingress Controller, 2048)vol.2

Posted at

はじめに

以前に前編の記事を書きました。
【AWS】EKS on Fargateでゲームをデプロイしてみたので解説してみる(with Ingress Controller, 2048)vol.1

本当は1つの記事にまとめる予定でしたが、
記事が長くなってしまったことと、作成に時間がかかってしまったこと(主に検証)から、やむなく2部制とさせていただいておりました。

前編の記事では、EKSクラスターとFargateプロファイルを作成するところまでを解説しました。
後編では、 kubectl コマンドでサービスをデプロイするところを解説していきます。

よろしくお願いします!

当記事でのゴール(再掲)

EKS on Fargateを使って、
2048ゲームをデプロイして遊べるようにしたいと思います。

2048とはこのようなゲームです。
きっと皆さん見たこと、遊んだことのあるゲームだと思います。

2048_play.gif

前提条件(再掲)

  • AWSのアカウントを所持している
  • macOS
  • eksctlコマンドではなく、マネジメントコンソールを使用して構築する
    • サービスの理解を深めるため

実際にはeksctlコマンドで一発でクラスターを作成できたりします。

$ eksctl create cluster

それでは何もわからないまま終わってしまうので、
一つ一つ解説を入れながらマネジメントコンソールで作っていきたいと思います。

全体の流れ(再掲)

  1. クラスターの作成
  2. Fargateプロファイルの作成
  3. kubectlコマンドでサービスをデプロイ

3. kubectlコマンドでサービスをデプロイ

作成したクラスターに向けてサービスをデプロイしていきます。
ここからはAWSマネジメントコンソールではなく、kubectlコマンドを中心に使っていきます。

3.1.kubectlawsclieksctlのインストール

以下のサイトを参照してインストールしてください。
kubectlのインストールおよびセットアップ
macOS での AWS CLI バージョン 2 のインストール
eksctl の開始方法

3.2. kube.configにEKSクラスターを登録する

kubectlコマンドの向き先を、ローカルではなく前手順で作成したEKSクラスターに変更します。

$ aws eks --region ap-northeast-1 update-kubeconfig --name eks_handson

このようなメッセージが出力されたら成功です。

Added new context arn:aws:eks:ap-northeast-1:xxxxxx:cluster/eks_handson to ~/.kube/config

~/.kube/configというファイル作成されます。

ファイルの中身
apiVersion: v1
clusters:
- cluster:
    certificate-authority-data: xxxxxx
    server: https://xxxxxx.gr7.ap-northeast-1.eks.amazonaws.com
  name: arn:aws:eks:ap-northeast-1:xxxxxx:cluster/eks_handson
contexts:
- context:
    cluster: arn:aws:eks:ap-northeast-1:xxxxxx:cluster/eks_handson
    user: arn:aws:eks:ap-northeast-1:xxxxxx:cluster/eks_handson
  name: arn:aws:eks:ap-northeast-1:xxxxxx:cluster/eks_handson
current-context: arn:aws:eks:ap-northeast-1:xxxxxx:cluster/eks_handson
kind: Config
preferences: {}
users:
- name: arn:aws:eks:ap-northeast-1:xxxxxx:cluster/eks_handson
  user:
    exec:
      apiVersion: client.authentication.k8s.io/v1alpha1
      args:
      - --region
      - ap-northeast-1
      - eks
      - get-token
      - --cluster-name
      - eks_handson
      command: aws

認証が通っているか確認します。

$ kubectl get svc
NAME         TYPE        CLUSTER-IP   EXTERNAL-IP   PORT(S)   AGE
kubernetes   ClusterIP   10.100.0.1   <none>        443/TCP   4m27s

3.3. デプロイするアプリのマニュフェストを入手する

Kubernetesでは、マニュフェスト(設計書)を使用してコンテナをデプロイしていきます。
どんなserviceに対して、どのようなdeploymentを行うのかというのがマニュフェストには定義されています。
docker-compose.ymlのようなものです。

実際に、Komposeというdocker-compose.ymlをKubernetesマニュフェストに変換するサービスも存在します。
次回の記事ではその紹介したいですね。

そのマニュフェストをダウンロードしてきます。

$ mkdir 2048
$ cd 2048
$ curl -OL https://raw.githubusercontent.com/kubernetes-sigs/aws-alb-ingress-controller/v1.1.4/docs/examples/2048/2048-deployment.yaml
$ curl -OL https://raw.githubusercontent.com/kubernetes-sigs/aws-alb-ingress-controller/v1.1.4/docs/examples/2048/2048-service.yaml
$ curl -OL https://raw.githubusercontent.com/kubernetes-sigs/aws-alb-ingress-controller/v1.1.4/docs/examples/2048/2048-ingress.yaml

ダウンロードしてきたマニュフェストを少し編集します。

# Namespace(名前空間)の変更
$ sed -i -e "s/namespace: \"2048-game\"/namespace: \"handson\"/" ./*.yaml

2048-ingress.yamlにも1行追加します。
target-typeにはinstanceおよびipの2つのモードがあるのですが、
EKS on Fargateではipのみでしか動かないようです。
詳細はIngress annotations

  annotations:
    kubernetes.io/ingress.class: alb
    alb.ingress.kubernetes.io/scheme: internet-facing
    # 以下の1行を追加
    alb.ingress.kubernetes.io/target-type: ip

Namespaceには、手順2.3で設定したものを設定します。

Serviceの公開(タイプ)については、下記URLに説明がされています。
Service - Kubernetes

デフォルトでは静的なポートで公開する設定がされていたので、
ロードバランサーを使用してサービスが公開されるように設定しています。

3.4. Ingress Controllerのための設定

ロードバランサーとして、ALB Ingress Controllerなるものを使用します。
Amazon EKS の ALB Ingress Controller

基本的に上記URLの手順で設定を行なっていきます。

サブネットにタグを追加

  • パブリックサブネットに、kubernetes.io/role/elb : 1
  • プライベートサブネットに、kubernetes.io/role/internal-elb : 1

を設定していきます。
また、 kubernetes.io/cluster/eks_handson タグが設定されていることを確認していください。
EKSクラスター作成時に自動でタグが付けられているはずです。

IAMにOIDCプロバイダーを登録

OIDCとはOpenID Connectの略です。
EKSクラスターの認証に使用するIDになります。

EKSクラスター作成時に「OpenID Connect プロバイダー URL」は付与されています。

スクリーンショット 2020-03-30 22.17.15.png

これを、以下のコマンドを実行することによってIAMに登録します。

eksctl utils associate-iam-oidc-provider \
    --region ap-northeast-1 \
    --cluster eks_handson \
    --approve

マネジメントコンソールのIAMのページを確認すると、IDプロバイダーが作成されています。

スクリーンショット 2020-03-30 22.22.50.png

マネジメントコンソールから作成する場合には、

  • プロバイダーのタイプ:OpenID Connect
  • プロバイダーのURL:EKSクラスターのページからコピペ
  • 対象者:sts.amazonaws.com

を設定することで同様のものを作成できます。

Ingress ControllerのためのIAMポリシー作成

以下のコマンドを実行することでIAMポリシーが作成されます。

aws iam create-policy \
    --policy-name ALBIngressControllerIAMPolicy \
    --policy-document https://raw.githubusercontent.com/kubernetes-sigs/aws-alb-ingress-controller/v1.1.4/docs/examples/iam-policy.json

作成したIAMポリシーを持つIAMロールをマネジメントコンソールで作成します。

IAMロールの作成方法

IAMロール作成画面の信頼されたエンティティから「ウェブID」を選択し、
IDプロバイダーにEKSクラスターを、Audienceにstsを選択します。

スクリーンショット 2020-03-08 18.44.36.png

ポリシーに先ほど作成したALBIngressControllerIAMPolicyを選択します。

スクリーンショット 2020-03-08 18.48.31.png

ロール名をeks-alb-ingress-controllerとして、作成します。

次に信頼関係の編集を行います。

Principal > Federated の箇所にはEKSクラスターのページに記載されている
OpenID Connect プロバイダー URLをコピペします。

Condition > StringEquals の箇所にも編集を加えます。

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Principal": {
     # 以下の行を編集する。
        "Federated": "arn:aws:iam::xxxxxx:oidc-provider/oidc.eks.ap-northeast-1.amazonaws.com/id/xxxxxx"
      },
      "Action": "sts:AssumeRoleWithWebIdentity",
      "Condition": {
        "StringEquals": {
          # 以下の行を編集する。
          # aud -> sub
          # sts.amazonaws.com -> system:serviceaccount:kube-system:alb-ingress-controller
          "oidc.eks.ap-northeast-1.amazonaws.com/id/xxxxxx:sub": "system:serviceaccount:kube-system:alb-ingress-controller"
        }
      }
    }
  ]
}

この信頼関係によって、
alb-ingress-controller というKubernetesのサービスロールから、
指定のOIDCを持つリソースに対してのみ、
このIAMロールが付与されます。


Kubernetesのサービスアカウント追加

以下コマンドによって、alb-ingress-controller のサービスアカウントを作成します。

kubectl apply -f https://raw.githubusercontent.com/kubernetes-sigs/aws-alb-ingress-controller/v1.1.4/docs/examples/rbac-role.yaml

追加したサービスアカウントに、IAMロールeks-alb-ingress-controllerを適用させます。

kubectl annotate serviceaccount -n kube-system alb-ingress-controller \
eks.amazonaws.com/role-arn=arn:aws:iam::xxxxxxxx:role/eks-alb-ingress-controller

ALB Ingress Controllerのマニュフェスト入手

ALB Ingress Controllerのマニュフェストをダウンロードしてきます。

$ cd ..
$ mkdir ingress
$ cd ingress
$ curl -OL https://raw.githubusercontent.com/kubernetes-sigs/aws-alb-ingress-controller/v1.1.4/docs/examples/alb-ingress-controller.yaml

マニュフェストを編集し、下記の箇所を変更します。

  • クラスター名
  • VPCのID
  • リージョン
**変更箇所詳細**
apiVersion: apps/v1
kind: Deployment
metadata:
  labels:
    app.kubernetes.io/name: alb-ingress-controller
  name: alb-ingress-controller
  namespace: kube-system
spec:
  selector:
    matchLabels:
      app.kubernetes.io/name: alb-ingress-controller
  template:
    metadata:
      labels:
        app.kubernetes.io/name: alb-ingress-controller
    spec:
      containers:
        - name: alb-ingress-controller
          args:
            - --ingress-class=alb
            # クラスター名を変更
            - --cluster-name=eks_handson
            # VPCのIDを変更
            - --aws-vpc-id=vpc-xxxxxx
            # リージョンを変更
            - --aws-region=ap-northeast-1

3.5. CoreDNSのFargate適用

現時点ではデフォルトで作成されるPod、CoreDNSは常にPendingになっていると思います。
これを適用します。

kubectl patch deployment coredns -n kube-system --type json \
-p='[{"op": "remove", "path": "/spec/template/metadata/annotations/eks.amazonaws.com~1compute-type"}]'

少し待つと立ち上がるはずです。

NAMESPACE     NAME                      READY   STATUS    RESTARTS   AGE
kube-system   coredns-9c47646f9-nbc6k   1/1     Running   0          26h
kube-system   coredns-9c47646f9-vmm42   1/1     Running   0          26h

3.6. サービスをデプロイする

お待たせしました!
ついにサービスをデプロイしていきます。
その際、Namespaceを先に作成しています。

# Namespaceの作成
$ kubectl create namespace handson

# デプロイ
$ cd ..
$ kubectl apply -f ingress/
$ kubectl apply -f 2048/

デプロイまで少し時間がかかりますので、コーヒーでもすすりながら待ちます。

$ kubectl get pods -n handson
NAME                              READY   STATUS    RESTARTS   AGE
2048-deployment-7f77b47f7-8hqsw   1/1     Running   0          83s
2048-deployment-7f77b47f7-b9chm   1/1     Running   0          83s
2048-deployment-7f77b47f7-hhvt7   1/1     Running   0          83s
2048-deployment-7f77b47f7-k8m2x   1/1     Running   0          83s
2048-deployment-7f77b47f7-km4d6   1/1     Running   0          83s

STATUSがRunningになっていたらデプロイ成功です。
現在は5つのコンテナにスケールされてデプロイされています。

続いて、

$ kubectl get nodes -n handson
NAME                                                       STATUS   ROLES    AGE    VERSION
fargate-ip-172-31-48-253.ap-northeast-1.compute.internal   Ready    <none>   114s   v1.14.8-eks
fargate-ip-172-31-49-226.ap-northeast-1.compute.internal   Ready    <none>   107s   v1.14.8-eks
fargate-ip-172-31-59-36.ap-northeast-1.compute.internal    Ready    <none>   106s   v1.14.8-eks
fargate-ip-172-31-62-48.ap-northeast-1.compute.internal    Ready    <none>   114s   v1.14.8-eks
fargate-ip-172-31-63-145.ap-northeast-1.compute.internal   Ready    <none>   103s   v1.14.8-eks

ノードが5つ立ち上がっていることと、Fargateで立ち上がっていることがわかります。
ノードの名前は自動で作成されるので、そこでFargateなのかEC2なのか判別することができます。

次にサービスが公開されているURLを調べます。
Ingress

$ kubectl get ingress -n handson
NAMESPACE   NAME           HOSTS   ADDRESS                                   PORTS   AGE
handson     2048-ingress   *       xxxxxx.ap-northeast-1.elb.amazonaws.com   80      2m40s

ADDRESSに記載されているURLにアクセスすると、、、

スクリーンショット 2020-03-30 22.45.09.png

出ました!!
画面にアクセスできるまで少し時間がかかるケースもあります。少し待ってからアクセスしてみましょう。

ロードバランサーについて

マネジメントコンソールのEC2のページからロードバランサーを選択すると、
Ingress Controllerによって作成されたロードバランサーを確認できます。

DNS名を確認すると、先ほどアクセスしたURLと同じものになっていると思います。
このロードバランサーに設定されたセキュリティグループも、Ingress Controllerによって作成されたものです。

このセキュリティグループの設定を変えてあげることで、アクセスできるIPアドレスを限定したり、ポートを増やしてあげたりすることができます。

(おまけ)HTTPSを実装する

今のままだとHTTPのみでセキュリティ的によろしくありません。
HTTPSでもアクセスできるようにする方法も紹介します。
ついてに、HTTPでアクセスしたらHTTPSの方にリダイレクトする設定も行なっていきます。

1. 証明書の作成

少し面倒ですが、AWS Certificate Manager上に証明書を作成しなければなりません。
手段は2通りで、

  1. マネジメントコンソールから作成(CA作成→証明書作成)
  2. オレオレ証明書をCertificate Managerにインポート

前者は若干お金がかかります。
後者の場合、おあつらえのQiita記事があります。
AWS Certificate Managerでオレオレ証明書をインポートする

2. Ingressの設定変更

2048-ingress.yamlを編集します。

apiVersion: extensions/v1beta1
kind: Ingress
metadata:
  name: "2048-ingress"
  namespace: "handson"
  annotations:
    kubernetes.io/ingress.class: alb
    alb.ingress.kubernetes.io/scheme: internet-facing
    alb.ingress.kubernetes.io/target-type: ip
    # 以下のannotationを追加。1番上は証明書のARNを記載します。
    alb.ingress.kubernetes.io/certificate-arn: arn:aws:acm:ap-northeast-1:xxxxxx:certificate/xxxxxxxxxx
    alb.ingress.kubernetes.io/listen-ports: '[{"HTTP": 80}, {"HTTPS": 443}]'
    alb.ingress.kubernetes.io/actions.ssl-redirect:
      '{
        "Type": "redirect",
        "RedirectConfig": {
          "Protocol": "HTTPS",
          "Port": "443",
          "StatusCode": "HTTP_301"
        }
      }'
  labels:
    app: 2048-ingress
spec:
  rules:
    - http:
        paths:
          # pathを一つ追加。annotationに追加したactionに紐付けます。
          - path: /*
            backend:
              serviceName: ssl-redirect
              servicePort: use-annotation
          - path: /*
            backend:
              serviceName: "service-2048"
              servicePort: 80

修正したらデプロイしましょう。

$ kubectl apply -f 2048

再びIngressの情報を取得し、ADDRESSにアクセスすると自動的にHTTPSにリダイレクトされているはずです。
どうぞお試しください。

まとめ

想像以上に長くなってしまいました。
Ingress Controllerの設定周りでだいぶ苦戦しました。。

KubernetesやEKSを初見で触った時には、
数時間で完全理解!わりとゴツいKubernetesハンズオン!!
の記事に本当にお世話になりました。

図解付きで説明されていて、非常にわかりやすいと感じました。
こちらもぜひ、参考にしてみてください。

ご覧いただき、ありがとうございました。

参考

AWS公式

その他記事

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

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?