AWS re:Invent 2017で発表されたコンテナ関連サービス(EKS、Fargate)のまとめと自社サービスへの活用

この記事は RECRUIT MARKETING PARTNERS Advent Calendar 2017 の投稿記事です。

こんにちは、開発支援Gでインフラ運用をしている大島です。アドベントカレンダー 2017 の記念すべき1日目は AWS re:Invent in ラスベガス からお届けします。

AWS re:InventはAmazon Web Service, Inc.が毎年開催している技術とマーケティングののカンファレンスで、今回は6回目の開催となります。新しいサービスや機能のアップデートが基調講演で発表されたり、1000以上のセッションが行われたりするなどお楽しみが盛り沢山な5日間のイベントです。

開発支援Gが管轄しているサービスのインフラは主にAWS上に構築されており、DockernizeしたアプリケーションをAmazon Elastic Container Service(以下ECS)上で運用しています。しかし、運用していく中で様々な問題点や課題が浮き彫りとなり、それらを解決するソリューションとしてKubernetesに注目していました。

今回発表されたAWS Fargateに触れつつ、Elastic Container Service for Kubernetes(以下EKS)が自社サービスにどう活かせるかについてご紹介します。

AWSでコンテナオーケストレーションといえばECS

ECSの正式名称はElastic Container Serviceです。EC2インスタンスをベースにクラスターを組んでコンテナをオーケストレーションできるサービスです。

ECSを使うメリット

  • 基本的にAWSのスタックを組み合わせて作られている
  • VPC内に建てられるため、AWS上のRDSやElasticacheなど他のManaged Serviceとの接続が容易
  • Elastic Load Balancing(以下ELB)と組み合わせることで、セキュリティグループによる細かなアクセス制限が容易

デメリット

  • ELBに依存する
    • コストがかかる
    • AWSのリソース制限を受けるため、気軽にサービスを増やせない
  • awsvpcモードが出たが動的ポートマッピング、サービス間の名前解決にroute53やELBが必要になってくることは避けられない
  • CPUやメモリ、ENIのlimitがコンテナインスタンス1台の上限に縛られてしまう
    • 結局コストがかる
    • クラスタ全体で仮想的に調整できない
  • デプロイ時にELBとコンテナが紐づくタイミングを厳密に設定できない
  • cliやAPIが発展途上
    • 複数のサービスを一括でimport出来ない
    • imageだけ更新することが出来ない

上記のようにAWS上でコンテナを管理するには優れたサービスですが、細かいところで課題を感じていました。そこで、それらの課題を解決できるKubernetesも検討してきました。

コンテナオーケストレーションのデファクトスタンダード Kubernetes

先日KubernetesをDockerと統合・サポートするとの発表がありました。コンテナオーケストレーション界隈では一層デファクトに近づいてきたのではないかと思います。

Kubernetesのメリット

  • Clusterさえ建ててしまえば、内部のロードバランシングやサービスの追加の度にリソースを追加する必要がない
  • サービス間通信はservice.namespaceで接続できるようにdnsが設定される
  • livenessProbeやreadinessProbe、maxSurgeやmaxUnabailableなどの値を使ってデプロイを細かくコントロールできる
  • JobやCron Jobというoneshotなタスクをバッチで実行できる
  • kubectlで細かい操作やhelmでの一発インストールなど、ツールがとても洗練されている

デメリット

  • Google Cloud Platform(以下GCP)やAzureでもMangaed Kubernetesがある中でAWSだけなかった
  • etcdの冗長化や障害時のリカバリなどKubernetes自体を運用するというのがハードルが高い

上記のようにECSで挙げた問題点については解決出来ていてるので社内開発環境では試しているのですが、本番に完全に移行するまでには踏み切れない状況でした。

ついに出た!!Managed KubernetesとなるAmazon EKS

Managed Kubernetesが出る出るという噂は流れていましたがついに出ました!!!

そのときの会場の興奮の様子はこちら

これでついに公式にAWS、GCP、AzureそれぞれでManaged Kubernetesが出揃い、ますます面白くなってきました。

早速使ってみましょうと言いたいところですが・・・

EKSは現在previewなのでまだ使うことはできないのですが、セッションに参加できた方のこちらのtweetで開発中のconsoleを見ることができました。また、スレッド形式でセッション内容もtweetしていただいてるので、気になる方は参考になるかと思います。

こちらのtweetや公式docを通じて、他のManaged Kubernetesとの違い、AWSらしさというものが見えてきたのでまとめてみました。

他のMangaed Kubernetesと比較したときのEKSの特徴

  • Google Kubernetes Engineのようにnodeごと丸ごと管理というわけではなく、masterのみの提供
  • Nodeのインスタンスにはoptimized AMIを提供予定
  • AWS IAMの機能で認証できる
  • ログはcloudwatch logsと統合されている

個人的には、あえてNodeを管理外においてECSらしい管理の仕方をしているところがむしろ良いのではないかと思いました。これによって、好きなタイプのインスタンスや立ち上げの方法(autoscaling、spot fleet、手動でインスタンス立てる)を採用することができ、構築の自由度が上がるのではと思います。また、IAMやcloudwatch logsとの統合という、AWSユーザーにとってはとても嬉しい内容ではないでしょうか。

previewだけど想像で実際にKubernetesをサービスに活用してみる

では、実際に弊社の英語学習サービスのスタディサプリENGLISH環境を丸ごとKubernetesにデプロイするまでを、想像上ですが1)だいたい合ってる自信はあるやってみようと思います。

スタディサプリENGLISHは、日常英会話アプリ、TOEIC学習アプリ、テキスト販売などこれからさらに新サービスも増えていっています。また、弊社 釘宮の記事にもあるように内部通信はgRPCで行っておりサービスは下図の参考図のような形でたくさんのサービスが稼働しています。

このような状況ですと、ECSの場合は各サービスごとにELBが必要になります。本番環境ならば構いませんが、気軽に開発環境を増やせません、一方、Kubernetesならサービス定義をしておけば、ELBなど別の物理的なリソースを別途作る必要もなくコマンド一発で出来上がってしまいます。これからサービスが拡大していくと考えると、ここはとても重要なポイントだと考えています。

1. Kubernetesのクラスターを作る

previewなのであくまでも想像ですが、まずは画面上からmaster componentを作っていくとになるかと思います。このコンポーネントはclusterをコントロールする重要な要素ですが、これを冗長化含めてAWSが面倒を見てくれるということにとても意義があるわけです。

そして、masterが出来た後はクラスターを構成するNodeをterraformのコードやGUIコンソールなどでautoscalingやAWS spot fleetなどを使って建てていくことになります。masterとnodeを別で作ることができるのがポイントですね。

2. Chartを書いてhelmコマンドで一発でデプロイする

KubernetesのリソースをインストールするためにHelmというツールがあるのですが、Chartというのはそれの設定ファイルのような存在です。Helmはギリシャ語で船の舵という意味で、Chartは海図という意味があります。おしゃれですね。

Kubernetesではservicedeploymentというresourceを定義していきます。下記のyamlはあくまでも参考ですが、このようにresourceを定義します。ここではdeploymentというコンテナを動かす部分のresourceのyamlの例をご紹介します。

apiVersion: extensions/v1beta1
kind: Deployment
metadata:
  name: api-server
  labels:
    app: api-server
    chart: {{ .Chart.Name }}-{{ .Chart.Version | replace "+" "_" }}
    release: {{ .Release.Name }}
    heritage: {{ .Release.Service }}
spec:
  replicas: 2
  template:
    metadata:
      labels:
        app: api-server
        release: {{ .Release.Name }}
    spec:
      containers:
        - name: api-server
          image: {{ .Values.image.registry }}/api-server-image:{{ .Values.ServerImageTag }}
          imagePullPolicy: IfNotPresent
          ports:
            - containerPort: 9000
          env:
            - name: JAVA_OPTS
              value: "-Dconfig.resource=dev.conf"
            - name: GRPC_INTERNAL_SERVICE_HOST
              value: "internalService.myNameSpace"

このようにgolangのtemplateを使いつつコンテナが起動する設定を書いていきます。ここでは、yamlファイルだけでロードバランサーやコンテナの数や環境変数などが設定できるぐらいに思ってください。

deployment以外にもserviceやingressなどloadBalancerとなるresourceなどの設定ファイルを書いたら、あとはhelm installコマンドで一発でインストールできます。

詳細は割愛しますが、ECSでやろうとすると内部用のDNSの解決のためにroute53やELBの設定などを別途terraformやcloudformationで定義する必要があるところを、Kubernetesであればクラスターさえ作ったらあとは基本的にKubernetesの世界の中で完結するというところがすごいところです。

ここまでECSで稼働しているサービスをEKSに移すメリットを簡単に紹介してきました。続いて、新サービスのAWS Fargateについて自社サービスの構成における活用について説明していきます。

AWS Fargate

ECSがより進化していくか、Mangaed Kubernetesが出てくるか、どう出るかAWSさん・・ と期待して臨んだ今回のAWS re:Invent。なんとコンテナ関連で新しいサービスが出てきました!!その名もAWS Fargate!!

AWSの登場以来インフラ環境が次々と仮想化されてきましたが、今までのEC2インスタンスからの進化を粒度と抽象度という観点でまとめると以下のような図になります。

今回のサービスでいうと粒度・抽象度を適度に上げたちょうどいいサービスと言えます。

ECSは、EC2のコンテナインスタンスにecs-agentをdockerで起動してクラスターという構成を作り、ELBを組み合わせてクラスタで動くコンテナをオーケストレーションする仕組みでした。

Fargateはこのクラスターを作る部分をManagedにして抽象化することで、ユーザーにアプリケーションの作成に注力できるような仕組みとなっています。

Fargateは自社サービスにも活用できそう

時間単価で言えば、Fargateの方がEC2インスタンスでクラスターを作るよりもほんの少し割高になりそうです。
弊社ではECSで動かしている自社サービスはサーバーアプリケーションが多いため、一見EC2インスタンスで作ったクラスターの方がコスト面では有利のように見えます。

しかし、EC2で作ったECSの場合はCPUのリソースやメモリ、ENIの制限がコンテナインスタンスのクラスに依存しているので、結局余計にインスタンスを立ち上げる必要がありワークロードによってはFargateの方が安くなる可能性もあります

また、サービスをデプロイする際にタスクの数(desiredCount)を保ったままローリングアップデートがしやすくなったのではないかと思います。EC2で作ったクラスターの場合は、一時的に2倍の容量をあけておかないといけません。しかし、Fargateなら一時的にTaskが増えても課金は稼働してる間だけなので余計な容量を確保しておかなくてすみます
さらに、サービスを起動するresourceが足りなくなってしまった場合は、autoscalingなどで台数を増やしてあげる必要がありましたが、Fargateなら考える必要がありません。以前だと、コンテナインスタンスの数を減らすときもdrainingしてほしいインスタンスの指定もできなかったので気軽にdesiredCountを増減できるようになったかと思います。
弊社では開発環境はSpotFleetでコストカットをしていますが、Fargateの場合は夜中はdesiredCountを少なくしておくなど工夫すれば料金も抑えられるかもしれません。

Fargateの立ち上がり速度やENIの上限がネックか

下の画像はFargateをprivate sunbetで起動した場合のネットワーク構成図です。このようにsubnet内でTASKに対して一つのENIがattachされます。

上記を検証するために、実際にFargateでサンプルアプリを立ち上げて試してみたところ以下のようなポイントがネックになりそうでした。

  • awsvpcモードでENIがtask一つ一つにアタッチされるのでVPCのENI上限を気にする必要がある(VPCのデフォルト上限は350)
  • awsvpcモードなのでsunbet内のIPの数以上にタスクを起動できない(InsufficientFreeAddressesInSubnetというエラーになる)

また、タスクを起動するときに気づいたのですが、タスクの起動時にPROVISIONINGという状態が3分程度かかりました。

re:Inventで受けたセッションでも実行時間が長いバッチJobに有効と説明されていたので、ユースケースを見極める必要がありそうです。

最後に

コンテナ関連の抽象度はどんどん上がっていき、コンテナのオーケストレーションはインフラエンジニアがやらなくてもよい領域になっていくと思います。そのマイルストーンを辿るように期待していた内容のサービスの発表があり、私はAWS re:Invent初参加でしたがとても楽しめました。海外のエンジニアとも会話してみると、この発表はみんな待ちに待っていたようですべらない話題でした(笑)刺激をたくさん受けられたので引き続き自社サービスにAWSを活用していきたいと思いました。

弊社では様々なサービスの0から1のフェーズや1から10のフェーズなど面白い環境が揃っています。コンテナ関連サービスがやりたい、俺がもっとよくしてやるいう方、インフラエンジニア絶賛募集中ですのでお待ちしております!

脚注

脚注
1 だいたい合ってる自信はある
関連職種の採用情報
詳しくはこちら