先日、Application Load Balancer (ALB)が HTTP/2 および gRPC に対応するようになったという発表がありました。これをEKS上で稼働するアプリケーションにも適用できるかを試してみました。
ALB の HTTP/2 および gRPC 対応
- ALB の HTTP/2 および gRPC 対応についてはこの辺が分かりやすい
EKS で ALB を利用するには?
- 以前は ALB Ingress Controller と呼ばれるものを利用したが、最近 AWS Load Balancer Controller となった(後継のバージョン扱い)
- gRPCのサポートは v2.1.0 で入った Release v2.1.0 · kubernetes-sigs/aws-load-balancer-controller
Supports gRPC workloads with end to end HTTP/2 for ALB
- このバージョンを使って試してみた
想定構成
- 2つのService
- helloworld service
- grpc-go レポジトリの例を利用した https://github.com/grpc/grpc-go/blob/master/examples/helloworld
- type: NodePort
- routeguide service
- こちらも grpc-go レポジトリの例を利用した https://github.com/grpc/grpc-go/blob/master/examples/route_guide
- type: NodePort
- helloworld service
- ドメインは共通
- ALBでパスによってルーティング
作成手順
- EKS クラスターが作成済みという前提で...
- バージョンは 1.18
- aws-load-balancer-controllerのインストール
- ここの手順に沿って行った Installation Guide - AWS LoadBalancer Controller
$ eksctl utils associate-iam-oidc-provider \ --region ap-northeast-1 \ --cluster floral-mongoose-1607656608 \ --approve [ℹ] eksctl version 0.32.0 [ℹ] using region ap-northeast-1 [ℹ] will create IAM Open ID Connect provider for cluster "floral-mongoose-1607656608" in "ap-northeast-1" [✔] created IAM Open ID Connect provider for cluster "floral-mongoose-1607656608" in "ap-northeast-1" # AWS Load Balancer Controller 用 IAM Policy の作成 $ curl -o iam-policy.json https://raw.githubusercontent.com/kubernetes-sigs/aws-load-balancer-controller/v2.1.0/docs/install/iam_policy.json $ aws iam create-policy \ --policy-name AWSLoadBalancerControllerIAMPolicy \ --policy-document file://iam-policy.json { "Policy": { "PolicyName": "AWSLoadBalancerControllerIAMPolicy", "PolicyId": "ANPA3TVC4QV7DOBMICOZQ", "Arn": "arn:aws:iam::accoundid:policy/AWSLoadBalancerControllerIAMPolicy", "Path": "/", "DefaultVersionId": "v1", "AttachmentCount": 0, "PermissionsBoundaryUsageCount": 0, "IsAttachable": true, "CreateDate": "2020-12-11T03:40:45+00:00", "UpdateDate": "2020-12-11T03:40:45+00:00" } } # 先ほど作成した IAM Policy にひもづける ServiceAccount を作成 $ eksctl create iamserviceaccount \ --cluster=floral-mongoose-1607656608 \ --namespace=kube-system \ --name=aws-load-balancer-controller \ --attach-policy-arn=arn:aws:iam::accountid:policy/AWSLoadBalancerControllerIAMPolicy \ --approve [ℹ] eksctl version 0.32.0 [ℹ] using region ap-northeast-1 [ℹ] 1 existing iamserviceaccount(s) (kube-system/aws-node) will be excluded [ℹ] 1 iamserviceaccount (kube-system/aws-load-balancer-controller) 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/aws-load-balancer-controller", create serviceaccount "kube-system/aws-load-balancer-controller" } } [ℹ] building iamserviceaccount stack "eksctl-floral-mongoose-1607656608-addon-iamserviceaccount-kube-system-aws-load-balancer-controller" [ℹ] deploying stack "eksctl-floral-mongoose-1607656608-addon-iamserviceaccount-kube-system-aws-load-balancer-controller" [ℹ] created serviceaccount "kube-system/aws-load-balancer-controller" # Controller をクラスターにインストール $ helm repo add eks https://aws.github.io/eks-charts "eks" has been added to your repositories $ kubectl apply -k "github.com/aws/eks-charts/stable/aws-load-balancer-controller//crds?ref=master" customresourcedefinition.apiextensions.k8s.io/targetgroupbindings.elbv2.k8s.aws created # helm install eks/aws-load-balancer-controller だと上手くいかなかった... # see https://github.com/aws/eks-charts/tree/master/stable/aws-load-balancer-controller $ helm upgrade \ -i aws-load-balancer-controller \ eks/aws-load-balancer-controller \ -n kube-system \ --set clusterName=floral-mongoose-1607656608 \ --set serviceAccount.create=false \ --set serviceAccount.name=aws-load-balancer-controller Release "aws-load-balancer-controller" does not exist. Installing it now. NAME: aws-load-balancer-controller LAST DEPLOYED: Fri Dec 11 12:52:57 2020 NAMESPACE: kube-system STATUS: deployed REVISION: 1 TEST SUITE: None NOTES: AWS Load Balancer controller installed!
- ACM で TLS証明書の作成
- ALB で gRPC を利用する場合はリスナープロトコルを HTTPS にする必要がある
- Target groups for your Application Load Balancers - Elastic Load Balancing
Considerations for the gRPC protocol version
The only supported listener protocol is HTTPS.
- このため ACM で証明書を用意した
- ALB で gRPC を利用する場合はリスナープロトコルを HTTPS にする必要がある
# --validation-method は DNS も選べるが、今回は都合によりeメール認証を選んだ # この ARN を後ほど使うのでコピーしておく $ aws acm request-certificate --domain-name albgrpcsample.niboshino-tech.net --validation-method EMAIL { "CertificateArn": "arn:aws:acm:ap-northeast-1:accountid:certificate/f49ed98b-935e-4adc-ab82-b7f35c293f9c" }
- manifest作成、適用
# helloworld.yml apiVersion: v1 kind: Service metadata: name: helloworld spec: selector: app: helloworld ports: - port: 50051 targetPort: 50051 type: NodePort --- apiVersion: apps/v1 kind: Deployment metadata: name: helloworld spec: selector: matchLabels: app: helloworld template: metadata: labels: app: helloworld spec: containers: - name: helloworld image: accountid.dkr.ecr.ap-northeast-1.amazonaws.com/albgrpcsample/helloworld:v0.0.1 resources: limits: memory: "128Mi" cpu: "500m" ports: - containerPort: 50051
# routeguide.yml apiVersion: v1 kind: Service metadata: name: routeguide spec: selector: app: routeguide ports: - port: 10000 targetPort: 10000 type: NodePort --- apiVersion: apps/v1 kind: Deployment metadata: name: routeguide spec: selector: matchLabels: app: routeguide template: metadata: labels: app: routeguide spec: containers: - name: routeguide image: accountid.dkr.ecr.ap-northeast-1.amazonaws.com/albgrpcsample/route_guide:v0.0.1 resources: limits: memory: "128Mi" cpu: "500m" ports: - containerPort: 10000
# alb-grpc-sample-ingress.yml apiVersion: networking.k8s.io/v1beta1 kind: Ingress metadata: name: alb-grpc-sample annotations: kubernetes.io/ingress.class: alb alb.ingress.kubernetes.io/scheme: internet-facing alb.ingress.kubernetes.io/backend-protocol-version: GRPC # このアノテーションがあることでリスナープロトコルのデフォルトが HTTPS (443) になる # see https://kubernetes-sigs.github.io/aws-load-balancer-controller/latest/guide/ingress/annotations/#listen-ports alb.ingress.kubernetes.io/certificate-arn: arn:aws:acm:ap-northeast-1:accountid:certificate/f49ed98b-935e-4adc-ab82-b7f35c293f9c spec: rules: - http: paths: - backend: serviceName: helloworld servicePort: 50051 path: /helloworld.Greeter/* - backend: serviceName: routeguide servicePort: 10000 path: /routeguide.RouteGuide/*
- これらを適用したところ ALB が作成された
- 動作確認
- ドメインの管理が Route53 以外で行われているので /etc/hosts を編集して確認した
- 正常にレスポンスが返ってくることを確認できた
# /etc/hostsを書き換えるため、ALBのIPアドレスを取得 $ dig k8s-default-albgrpcs-5fb02487bb-383351884.ap-northeast-1.elb.amazonaws.com +short 52.198.135.63 18.182.181.161 13.230.14.197 $ sudo vi /etc/hosts # 以下追加 52.198.135.63 albgrpcsample.niboshino-tech.net $ grpcurl -d '{"name": "foo"}' -proto helloworld/helloworld/helloworld.proto albgrpcsample.niboshino-tech.net:443 helloworld.Greeter/SayHello { "message": "Hello foo" } $ grpcurl -d '{"latitude": 407838351, "longitude": -746143763}' -proto route_guide/routeguide/route_guide.proto albgrpcsample.niboshino-tech.net:443 routeguide.RouteGuide/GetFeature { "name": "Patriots Path, Mendham, NJ 07945, USA", "location": { "latitude": 407838351, "longitude": -746143763 } }
まとめ
AWS Load Balancer Controller をインストールして Ingress に特定の annotation を追加したものを適用すると ALB が作成されることが分かりました。Ingress で指定したパスごとにターゲットグループが対応しているので理解しやすく感じました。EKS で gRPC を利用するシステムにおいてルーティングや負荷分散を担う要素として選択肢の一つになりそうです。