Amazon EKSでAWS Fargateを動かす
EKSでFargateを動かしてみたので、その記録です。
セットアップ
fargate起動向けのクラスタを作成する
eksctlを使います。クラスタの設定は下記です。
cluster.yaml
apiVersion: eksctl.io/v1alpha5 kind: ClusterConfig metadata: name: fargate-cluster region: ap-northeast-1 fargateProfiles: - name: fp-default selectors: - namespace: default - namespace: kube-system
fargateProfiles
を定義すると、該当のnamespaceのPodがfargateで起動されます。
クラスタを作成します。
$ eksctl create cluster --config-file cluster.yaml
ALB Ingress Controllerをセットアップする
今のところ、fargateで利用可能なロードバランサーはALB Ingress Controllerしかないようです。
ALB Ingress Controllerをクラスタ内で動作させるために、ALB Ingress Controllerに対してAWS APIを実行できるようにAWSの権限を設定します。
これはサービスアカウントにIAM ロールを関連づけることで実現します。
クラスタでサービスアカウントのIAMロールを有効化します。
$ eksctl utils associate-iam-oidc-provider --region ap-northeast-1 --cluster fargate-cluster --approve
ALB Ingress Controllerに許可するIAM policyをALBIngressControllerIAMPolicy
という名前で作成します。
iam-policy.json
{ "Version": "2012-10-17", "Statement": [ { "Effect": "Allow", "Action": [ "acm:DescribeCertificate", "acm:ListCertificates", "acm:GetCertificate" ], "Resource": "*" }, { "Effect": "Allow", "Action": [ "ec2:AuthorizeSecurityGroupIngress", "ec2:CreateSecurityGroup", "ec2:CreateTags", "ec2:DeleteTags", "ec2:DeleteSecurityGroup", "ec2:DescribeAccountAttributes", "ec2:DescribeAddresses", "ec2:DescribeInstances", "ec2:DescribeInstanceStatus", "ec2:DescribeInternetGateways", "ec2:DescribeNetworkInterfaces", "ec2:DescribeSecurityGroups", "ec2:DescribeSubnets", "ec2:DescribeTags", "ec2:DescribeVpcs", "ec2:ModifyInstanceAttribute", "ec2:ModifyNetworkInterfaceAttribute", "ec2:RevokeSecurityGroupIngress" ], "Resource": "*" }, { "Effect": "Allow", "Action": [ "elasticloadbalancing:AddListenerCertificates", "elasticloadbalancing:AddTags", "elasticloadbalancing:CreateListener", "elasticloadbalancing:CreateLoadBalancer", "elasticloadbalancing:CreateRule", "elasticloadbalancing:CreateTargetGroup", "elasticloadbalancing:DeleteListener", "elasticloadbalancing:DeleteLoadBalancer", "elasticloadbalancing:DeleteRule", "elasticloadbalancing:DeleteTargetGroup", "elasticloadbalancing:DeregisterTargets", "elasticloadbalancing:DescribeListenerCertificates", "elasticloadbalancing:DescribeListeners", "elasticloadbalancing:DescribeLoadBalancers", "elasticloadbalancing:DescribeLoadBalancerAttributes", "elasticloadbalancing:DescribeRules", "elasticloadbalancing:DescribeSSLPolicies", "elasticloadbalancing:DescribeTags", "elasticloadbalancing:DescribeTargetGroups", "elasticloadbalancing:DescribeTargetGroupAttributes", "elasticloadbalancing:DescribeTargetHealth", "elasticloadbalancing:ModifyListener", "elasticloadbalancing:ModifyLoadBalancerAttributes", "elasticloadbalancing:ModifyRule", "elasticloadbalancing:ModifyTargetGroup", "elasticloadbalancing:ModifyTargetGroupAttributes", "elasticloadbalancing:RegisterTargets", "elasticloadbalancing:RemoveListenerCertificates", "elasticloadbalancing:RemoveTags", "elasticloadbalancing:SetIpAddressType", "elasticloadbalancing:SetSecurityGroups", "elasticloadbalancing:SetSubnets", "elasticloadbalancing:SetWebACL" ], "Resource": "*" }, { "Effect": "Allow", "Action": [ "iam:CreateServiceLinkedRole", "iam:GetServerCertificate", "iam:ListServerCertificates" ], "Resource": "*" }, { "Effect": "Allow", "Action": [ "cognito-idp:DescribeUserPoolClient" ], "Resource": "*" }, { "Effect": "Allow", "Action": [ "waf-regional:GetWebACLForResource", "waf-regional:GetWebACL", "waf-regional:AssociateWebACL", "waf-regional:DisassociateWebACL" ], "Resource": "*" }, { "Effect": "Allow", "Action": [ "tag:GetResources", "tag:TagResources" ], "Resource": "*" }, { "Effect": "Allow", "Action": [ "waf:GetWebACL" ], "Resource": "*" }, { "Effect": "Allow", "Action": [ "wafv2:GetWebACL", "wafv2:GetWebACLForResource", "wafv2:AssociateWebACL", "wafv2:DisassociateWebACL" ], "Resource": "*" }, { "Effect": "Allow", "Action": [ "shield:DescribeProtection", "shield:GetSubscriptionState", "shield:DeleteProtection", "shield:CreateProtection", "shield:DescribeSubscription", "shield:ListProtections" ], "Resource": "*" } ] }
ALB Ingress Controller向けのサービスアカウントをalb-ingress-controller
という名前で作成します。
そのほか、RBACのリソースをALB Ingress Controllerで用意されるものをそのまま利用します。
rbac-role.yaml
--- apiVersion: rbac.authorization.k8s.io/v1 kind: ClusterRole metadata: labels: app.kubernetes.io/name: alb-ingress-controller name: alb-ingress-controller rules: - apiGroups: - "" - extensions resources: - configmaps - endpoints - events - ingresses - ingresses/status - services - pods/status verbs: - create - get - list - update - watch - patch - apiGroups: - "" - extensions resources: - nodes - pods - secrets - services - namespaces verbs: - get - list - watch --- apiVersion: rbac.authorization.k8s.io/v1 kind: ClusterRoleBinding metadata: labels: app.kubernetes.io/name: alb-ingress-controller name: alb-ingress-controller roleRef: apiGroup: rbac.authorization.k8s.io kind: ClusterRole name: alb-ingress-controller subjects: - kind: ServiceAccount name: alb-ingress-controller namespace: kube-system --- apiVersion: v1 kind: ServiceAccount metadata: labels: app.kubernetes.io/name: alb-ingress-controller name: alb-ingress-controller namespace: kube-system ...
ALB Ingress ControllerのサービスアカウントとIAM Policyを紐づけたIAM Roleを作成します。
$ eksctl create iamserviceaccount --region ap-northeast-1 --name alb-ingress-controller --namespace kube-system --cluster fargate-cluster --attach-policy-arn arn:aws:iam::111122223333:policy/ALBIngressControllerIAMPolicy --override-existing-serviceaccounts --approve
ALB Ingress Controllerをデプロイします。
下記のようにyamlを用意します。
# Application Load Balancer (ALB) Ingress Controller Deployment Manifest. # This manifest details sensible defaults for deploying an ALB Ingress Controller. # GitHub: https://github.com/kubernetes-sigs/aws-alb-ingress-controller apiVersion: apps/v1 kind: Deployment metadata: labels: app.kubernetes.io/name: alb-ingress-controller name: alb-ingress-controller # Namespace the ALB Ingress Controller should run in. Does not impact which # namespaces it's able to resolve ingress resource for. For limiting ingress # namespace scope, see --watch-namespace. 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: # Limit the namespace where this ALB Ingress Controller deployment will # resolve ingress resources. If left commented, all namespaces are used. # - --watch-namespace=your-k8s-namespace # Setting the ingress-class flag below ensures that only ingress resources with the # annotation kubernetes.io/ingress.class: "alb" are respected by the controller. You may # choose any class you'd like for this controller to respect. - --ingress-class=alb # REQUIRED # Name of your cluster. Used when naming resources created # by the ALB Ingress Controller, providing distinction between # clusters. - --cluster-name=fargate-cluster # AWS VPC ID this ingress controller will use to create AWS resources. # If unspecified, it will be discovered from ec2metadata. - --aws-vpc-id=vpc-111122223333 # AWS region this ingress controller will operate in. # If unspecified, it will be discovered from ec2metadata. # List of regions: http://docs.aws.amazon.com/general/latest/gr/rande.html#vpc_region - --aws-region=ap-northeast-1 # Enables logging on all outbound requests sent to the AWS API. # If logging is desired, set to true. # - --aws-api-debug # Maximum number of times to retry the aws calls. # defaults to 10. # - --aws-max-retries=10 env: # AWS key id for authenticating with the AWS API. # This is only here for examples. It's recommended you instead use # a project like kube2iam for granting access. #- name: AWS_ACCESS_KEY_ID # value: KEYVALUE # AWS key secret for authenticating with the AWS API. # This is only here for examples. It's recommended you instead use # a project like kube2iam for granting access. #- name: AWS_SECRET_ACCESS_KEY # value: SECRETVALUE # Repository location of the ALB Ingress Controller. image: docker.io/amazon/aws-alb-ingress-controller:v1.1.6 serviceAccountName: alb-ingress-controller
fargateで起動する場合、vpcとregionの指定が必要です。
デプロイします。
$ kubectl apply -f alb-ingress-controller.yaml
アプリをデプロイする
myapp.yaml
apiVersion: apps/v1 kind: Deployment metadata: name: myapp spec: replicas: 1 selector: matchLabels: ingress-app: myapp template: metadata: labels: ingress-app: myapp spec: containers: - name: myapp image: hi1280/myapp ports: - containerPort: 3000 --- apiVersion: v1 kind: Service metadata: name: myapp labels: app: myapp spec: type: NodePort ports: - protocol: TCP port: 80 targetPort: 3000 selector: ingress-app: myapp --- apiVersion: extensions/v1beta1 kind: Ingress metadata: name: myapp annotations: kubernetes.io/ingress.class: alb alb.ingress.kubernetes.io/scheme: internet-facing alb.ingress.kubernetes.io/target-type: ip alb.ingress.kubernetes.io/healthcheck-path: /healthz labels: app: myapp spec: rules: - http: paths: - path: /* backend: serviceName: "myapp" servicePort: 80
Ingressリソースを作成することで、ALB Ingress ControllerがALBを作成してアプリに疎通するようにしてくれます。
fargateではalb.ingress.kubernetes.io/target-type: ip
を指定する必要があります。
$ kubectl apply -f myapp.yaml
参考
Amazon EKS での AWS Fargate の開始方法 - Amazon EKS
Amazon EKS の ALB Ingress Controller - Amazon EKS
Setup - AWS ALB Ingress Controller
所感
Podの起動には時間がかかるようです。
コストを抑える目的である場合、EC2のスポットインスタンスを使うといった他の選択肢もありそうです。
最大限コストを抑える場合にfargateを利用するといった用途になるかもしれません。