はじめに
以前に前編の記事を書きました。
【AWS】EKS on Fargateでゲームをデプロイしてみたので解説してみる(with Ingress Controller, 2048)vol.1
本当は1つの記事にまとめる予定でしたが、
記事が長くなってしまったことと、作成に時間がかかってしまったこと(主に検証)から、やむなく2部制とさせていただいておりました。
前編の記事では、EKSクラスターとFargateプロファイルを作成するところまでを解説しました。
後編では、 kubectl
コマンドでサービスをデプロイするところを解説していきます。
よろしくお願いします!
当記事でのゴール(再掲)
EKS on Fargateを使って、
2048ゲームをデプロイして遊べるようにしたいと思います。
2048とはこのようなゲームです。
きっと皆さん見たこと、遊んだことのあるゲームだと思います。
前提条件(再掲)
- AWSのアカウントを所持している
- macOS
-
eksctl
コマンドではなく、マネジメントコンソールを使用して構築する- サービスの理解を深めるため
実際にはeksctl
コマンドで一発でクラスターを作成できたりします。
$ eksctl create cluster
それでは何もわからないまま終わってしまうので、
一つ一つ解説を入れながらマネジメントコンソールで作っていきたいと思います。
全体の流れ(再掲)
- クラスターの作成
- Fargateプロファイルの作成
-
kubectl
コマンドでサービスをデプロイ
3. kubectl
コマンドでサービスをデプロイ
作成したクラスターに向けてサービスをデプロイしていきます。
ここからはAWSマネジメントコンソールではなく、kubectl
コマンドを中心に使っていきます。
3.1.kubectl
、awscli
、eksctl
のインストール
以下のサイトを参照してインストールしてください。
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」は付与されています。
これを、以下のコマンドを実行することによってIAMに登録します。
eksctl utils associate-iam-oidc-provider \
--region ap-northeast-1 \
--cluster eks_handson \
--approve
マネジメントコンソールのIAMのページを確認すると、IDプロバイダーが作成されています。
マネジメントコンソールから作成する場合には、
- プロバイダーのタイプ: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を選択します。
ポリシーに先ほど作成したALBIngressControllerIAMPolicy
を選択します。
ロール名を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にアクセスすると、、、
出ました!!
画面にアクセスできるまで少し時間がかかるケースもあります。少し待ってからアクセスしてみましょう。
ロードバランサーについて
マネジメントコンソールのEC2のページからロードバランサーを選択すると、
Ingress Controllerによって作成されたロードバランサーを確認できます。
DNS名を確認すると、先ほどアクセスしたURLと同じものになっていると思います。
このロードバランサーに設定されたセキュリティグループも、Ingress Controllerによって作成されたものです。
このセキュリティグループの設定を変えてあげることで、アクセスできるIPアドレスを限定したり、ポートを増やしてあげたりすることができます。
(おまけ)HTTPSを実装する
今のままだとHTTPのみでセキュリティ的によろしくありません。
HTTPSでもアクセスできるようにする方法も紹介します。
ついてに、HTTPでアクセスしたらHTTPSの方にリダイレクトする設定も行なっていきます。
1. 証明書の作成
少し面倒ですが、AWS Certificate Manager上に証明書を作成しなければなりません。
手段は2通りで、
- マネジメントコンソールから作成(CA作成→証明書作成)
- オレオレ証明書を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公式
その他記事