今回、作成するもの
- 今回はEKSクラスターにMattermostをデプロイする前に、設定しておくと便利なものの残りを対応していきたいと思います。
- external dns
- Metrics Server
- Amazon EFS CSI ドライバー
復習
-
external dns
- ロードバランサーのDNS名を、指定したドメイン名に自動で割り振ってくれる機能
-
Metrics Server
- 負荷が高まった時にコンテナの数をオートスケールしてくれる機能
-
Amazon EFS CSI ドライバー
- Mattermostで利用されるデータを共有ストレージに保管する機能
external dnsの設定
- ではexternal dnsの設定をしていきます。まずRoute53を操作するためのPolicyを作成します。
- 以下のjsonを用意してCLIで実行していきます。
- iam-policy-external-dns.json
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"route53:ChangeResourceRecordSets"
],
"Resource": [
"arn:aws:route53:::hostedzone/*"
]
},
{
"Effect": "Allow",
"Action": [
"route53:ListHostedZones",
"route53:ListResourceRecordSets"
],
"Resource": [
"*"
]
}
]
}
- 実行
shell
$ aws iam create-policy \
--policy-name ExternalDNSIAMPolicy \
--policy-document file://iam-policy-external-dns.json
- 次に上記で作成したIAMポリシーを紐付けるサービスアカウントを作成します。
- 以下のyamlを用意して実行していきます。
- sa-external-dns.yaml
yaml
apiVersion: eksctl.io/v1alpha5
kind: ClusterConfig
metadata:
name: ver-Mattermost-eks
region: ap-northeast-1
iam:
withOIDC: true
serviceAccounts:
- metadata:
name: external-dns
namespace: kube-system
labels:
app.kubernetes.io/name: external-dns
attachPolicyARNs:
- "arn:aws:iam::394923402640:policy/ExternalDNSIAMPolicy"
- 上記yamlを適用
yaml
eksctl create iamserviceaccount -f sa-external-dns.yml --approve
$ eksctl create iamserviceaccount -f sa-external-dns.yaml --approve
[ℹ] eksctl version 0.29.1
[ℹ] using region ap-northeast-1
[ℹ] 2 existing iamserviceaccount(s) (kube-system/alb-ingress-controller,kube-system/aws-node) will be excluded
[ℹ] 1 iamserviceaccount (kube-system/external-dns) was included (based on the include/exclude rules)
[ℹ] 1 iamserviceaccount (kube-system/aws-node) was excluded (based on the include/exclude rules)
[!] serviceaccounts that exists in Kubernetes will be excluded, use --override-existing-serviceaccounts to override
[ℹ] 1 task: { 2 sequential sub-tasks: { create IAM role for serviceaccount "kube-system/external-dns", create serviceaccount "kube-system/external-dns" } }
[ℹ] building iamserviceaccount stack "eksctl-ver-Mattermost-eks-addon-iamserviceaccount-kube-system-external-dns"
[ℹ] deploying stack "eksctl-ver-Mattermost-eks-addon-iamserviceaccount-kube-system-external-dns"
[ℹ] created serviceaccount "kube-system/external-dns"
- サービスアカウントができたことを確認します
shell
$ kubectl get sa -n kube-system | grep external
external-dns 1 46s
- サービスアカウントとクラスターロールを繋げていきます。Rolebindingと呼ぶみたいです。
- 参考:KubernetesのRBACについて - Qiita
- この辺りもっと勉強しないと、、、違いや役割がまだ理解できていません
- 以下のyamlを実行していきます。
- clusterrole-external-dns.yaml
- 参考:KubernetesのRBACについて - Qiita
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
name: external-dns
labels:
app.kubernetes.io/name: external-dns
rules:
- apiGroups: [""]
resources: ["services","endpoints","pods"]
verbs: ["get","watch","list"]
- apiGroups: ["extensions","networking.k8s.io"]
resources: ["ingresses"]
verbs: ["get","watch","list"]
- apiGroups: [""]
resources: ["nodes"]
verbs: ["list","watch"]
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
name: external-dns
labels:
app.kubernetes.io/name: external-dns
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
name: external-dns
subjects:
- kind: ServiceAccount
name: external-dns
namespace: kube-system
-
実はここのClusterRoleのrulesではまりました、、、参考にした記事の通りのrulesだと権限が足りないようでエラーになり続けたのです。
- external-dns/aws.md at master · kubernetes-sigs/external-dnsの記述内容を参考にしたらうまくいきました!
-
上記のyamlを適用していきます。
$ kubectl apply -f clusterrole-external-dns.yaml
clusterrole.rbac.authorization.k8s.io/external-dns created
clusterrolebinding.rbac.authorization.k8s.io/external-dns created
- ExternalDNSの処理を実行してくれるpodを作成してデプロイしていきます。
- deploy-external-dns.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: external-dns
namespace: kube-system
spec:
strategy:
type: Recreate
selector:
matchLabels:
app: external-dns
template:
metadata:
labels:
app: external-dns
spec:
serviceAccountName: external-dns
containers:
- name: external-dns
image: registry.opensource.zalan.do/teapot/external-dns:latest
args:
- --source=service
- --source=ingress
- --domain-filter=xxxx.xxxxx.co.jp # ここに自動で作成してほしいFQDNを入力します
- --provider=aws
- --policy=upsert-only # would prevent ExternalDNS from deleting any records, omit to enable full synchronization
- --aws-zone-type=public # only look at public hosted zones (valid values are public, private or no value for both)
- --registry=txt
- --txt-owner-id=xxxxxxxxxxxxxxxxxxx # ここに適用先のドメインのowner-idを入力
securityContext:
fsGroup: 65534 # For ExternalDNS to be able to read Kubernetes and AWS token files
- 適用します。
$ kubectl apply -f deploy-external-dns.yaml
deployment.apps/external-dns created
- 確認します。
$ kubectl get pod -n kube-system
NAME READY STATUS RESTARTS AGE
alb-ingress-controller-869744b58-s6blb 1/1 Running 0 23h
- 正常にPodが動いていることが確認できました。
metrics serverの設定
- 次はmetrics serverです。これを利用する目的はpodの負荷を検知してオートスケール(Horizontal Pod Autoscaler)をするために、podの負荷を確認しないといけないのですが、その
podの負荷を確認
するために必要なのがmetrics serverになります。 - なので、metrics serverをデプロイする前は
kubectl top node
やkubectl top pod
といったコマンドが実行できません。
shell
$ kubectl top node
Error from server (NotFound): the server could not find the requested resource (get services http:heapster:)
- ということなので、metrics serverをデプロイして上記コマンドを使えるようにしていきましょう。
- インストール
kubectl apply -f https://github.com/kubernetes-sigs/metrics-server/releases/download/v0.3.6/components.yaml
shell
$ kubectl apply -f https://github.com/kubernetes-sigs/metrics-server/releases/download/v0.3.6/components.yaml
clusterrole.rbac.authorization.k8s.io/system:aggregated-metrics-reader created
clusterrolebinding.rbac.authorization.k8s.io/metrics-server:system:auth-delegator created
rolebinding.rbac.authorization.k8s.io/metrics-server-auth-reader created
apiservice.apiregistration.k8s.io/v1beta1.metrics.k8s.io created
serviceaccount/metrics-server created
deployment.apps/metrics-server created
service/metrics-server created
clusterrole.rbac.authorization.k8s.io/system:metrics-server created
clusterrolebinding.rbac.authorization.k8s.io/system:metrics-server created
- デプロイできていそうなので、コマンドを実行してみましょう。
shell
$ kubectl top node
NAME CPU(cores) CPU% MEMORY(bytes) MEMORY%
ip-10-0-21-171.ap-northeast-1.compute.internal 59m 3% 635Mi 23%
ip-10-0-22-50.ap-northeast-1.compute.internal 69m 3% 757Mi 27%
-
kubectl top node
が無事に使えるようになっています!もちろんkubectl top pod
も使えるようになっています。
$ kubectl top pod alb-ingress-controller-869744b58-s6blb -n kube-system
NAME CPU(cores) MEMORY(bytes)
alb-ingress-controller-869744b58-s6blb 2m 13Mi
- 次はCPU負荷がXX%になったらpodをXX個増やす、みたいな設定が必要になってくるのですが、それはMattermostをデプロイする時の設定になるので、metrics serverの設定は一旦ここでおしまいです。
Amazon EFS CSI ドライバーの設定
- これは特に何も考えずにMattermostをデプロイするとMattermostの機能を提供するpodのデータはEC2に繋がっているEBSに保存されます。EBSはEKSクラスターを形作るEC2に繋がっているストレージです。
- これの何が問題かと言うと、例えばEC2を2台でクラスターを組んでいる今の構成では、Mattermostの機能を提供するpodが2つ各EC2で稼働しているとして、こっちのEC2で稼働しているMattermostからAというデータは見れるけど、あっちのEC2で稼働しているMattermostからはAというデータは見れない、というような事態が起こりうるということです。
- そんな時の解決策といえば、
共有ストレージ
ですよね。ここでAWSで共有ストレージのサービスを提供しているEFSを利用するということになります。 - なのでまずEFSを利用できるようにしておかないといけません。
EFSの作成をしていきます。
- 事前準備:ネットワーク関連の設定
shell
# VPC ID を取得する
$ aws eks describe-cluster --name ver-Mattermost-eks --query "cluster.resourcesVpcConfig.vpcId" --output text
vpc-xxxxxxxxxxxxxxx
# VPC クラスターの CIDR 範囲を取得する
$ aws ec2 describe-vpcs --vpc-ids vpc-xxxxxxxxxxxxxxx --query "Vpcs[].CidrBlock" --output text
10.0.0.0/16
# Amazon EFS マウントポイントのインバウンドネットワークファイルシステム (NFS) トラフィックを許可するセキュリティグループを作成する
$ aws ec2 create-security-group --description efs-sg --group-name efs-sg --vpc-id vpc-xxxxxxxxxxxxxxx
{
"GroupId": "sg-xxxxxxxxxxxxxxx"
}
# NFS インバウンドルールを追加して、VPC のリソースが EFS と通信できるようにする
$ aws ec2 authorize-security-group-ingress --group-id sg-xxxxxxxxxxxxxxx--protocol tcp --port 2049 --cidr 10.0.0.0/16
- Amazon EFS ファイルシステムを作成
shell
$ aws efs create-file-system --creation-token eks-efs
{
"OwnerId": "xxxxxxxxxxxxxxx",
"CreationToken": "eks-efs",
"FileSystemId": "fs-xxxxxxxx",
"CreationTime": "2020-08-30T07:44:27+00:00",
"LifeCycleState": "creating",
"NumberOfMountTargets": 0,
"SizeInBytes": {
"Value": 0,
"ValueInIA": 0,
"ValueInStandard": 0
},
"PerformanceMode": "generalPurpose",
"Encrypted": false,
"ThroughputMode": "bursting",
"Tags": []
}
- EFSのマウント (各AZで実行する)
shell
aws efs create-mount-target --file-system-id fs-xxxxxxxx--subnet-id subnet-0ad4ab16f800797fa --security-group sg-xxxxxxxxxxxxxxx
aws efs create-mount-target --file-system-id fs-xxxxxxxx--subnet-id subnet-0d0c2821bd833ab40 --security-group sg-xxxxxxxxxxxxxxx
aws efs create-mount-target --file-system-id fs-xxxxxxxx --subnet-id subnet-00a0740f60c9fd5e1 --security-group sg-xxxxxxxxxxxxxxx
Amazon EFS CSI ドライバーをデプロイする
- 以下のようにデプロイします。
kubectl apply -k "github.com/kubernetes-sigs/aws-efs-csi-driver/deploy/kubernetes/overlays/stable/?ref=master"
$ kubectl apply -k "github.com/kubernetes-sigs/aws-efs-csi-driver/deploy/kubernetes/overlays/stable/?ref=master"
daemonset.apps/efs-csi-node created
csidriver.storage.k8s.io/efs.csi.aws.com created
- 確認します。
$ kubectl get daemonsets efs-csi-node --namespace=kube-system
NAME DESIRED CURRENT READY UP-TO-DATE AVAILABLE NODE SELECTOR AGE
efs-csi-node 2 2 2 2 2 kubernetes.io/os=linux 53s
-
efs-csi-node
が正常に稼働していればOKです。 - この後に、StorageClassやPV、PVCを作っていきますが、それはMattermostのデプロイ時にやっていきたいと思います。
まとめ
- これでようやくMattermostをデプロイする準備が整ってきました。
- こういった
EKSクラスターでアプリケーションを稼働させる前にセットアップしておくべきツール
をもっと効率よく準備できるような方法も考えないといけないなあと感じました。