JAWS DAYS 2017 ワークショップ Docker on Elastic Beanstalk 〜Days after tomorrow〜 (1)

この記事では、複数のDockerコンテナで構成される環境を構築するための設定例を具体的に解説します。ワークショップのフォローアップではありますが、一般的な事柄を扱いますので、ワークショップに参加されていない方にもお読み頂ける内容です。

ワークショップ

こんにちは。Emotion Techの子安です。3月もそろそろ終わりだというのに、まだ寒い日が続きますね。陽だまりの恋しい今日このごろです。

さて、先日開催されたJAWS DAYS 2017にて、ワークショップ「Docker on Elastic Beanstalk 〜明日から本番で使えるかも〜」を担当いたしました。多数のお申込みとご参加ありがとうございました。

当日の様子はこんな感じでした。

P3110990.JPG

ハンズオンがメインということで、環境を構築して動かすことにフォーカスした内容だったのですが、終了後に記入して頂いたアンケートの中で、コンテナの設定や、ファイルの内容についてよく知りたいというご要望を頂きました。そこで、今回はワークショップで触れられなかった、そのあたりのことを解説したいと思います。(Dockerそのものについての解説は行いません) 長くなりそうなので、2,3回に分けて掲載する予定です。

リポジトリとコンテナの構成

リポジトリはこちらです。ハンズオンの手順書やコンテナの設定などが入っています。
https://github.com/akirakoyasu/elastic-beanstalk-workshop

コンテナの構成

workshop (1).png

静的コンテンツ配信かつRailsへのプロキシとなるwebコンテナがあり、Railsが動いているappコンテナがあり、更にdbコンテナがあるという構成です。

コンテナ定義ファイル

まずはコンテナを定義するファイルから具体的に見ていきます。 docker-compose.yml を参照ください。docker-compose.ymlは、大きく services volumes networks の3つのセクションに分けられます。

※ 実はElastic Beanstalkはdocker-compose.ymlファイルを参照しませんので、同様の内容をDockerrun.aws.jsonに記述しています。Dockerrun.aws.json固有の設定は次回以降に解説します。

services

コンテナをサービスとして定義するセクションです。ここで、 web app db コンテナをそれぞれ定義しています。

volumes

ホストからコンテナへマウントするディスク領域(ボリューム)を定義するセクションです。ここで、DBのデータ領域となるボリューム eb.workshop.db を名前付きボリュームとして定義しています。イメージがボリュームを要求する場合、定義しなくても自動的にボリュームが作成されますが、名前を付けて定義しておいたほうが後で扱いやすいので明示的に定義するようにしています。

networks

コンテナが接続するネットワークを定義するセクションです。ここで、ネットワーク eb.workshop を定義しています。docker-composeを使用した場合、定義しなくてもデフォルトで1つネットワークが作成されますが、定義しておいたほうが後で扱いやすいので明示的に定義するようにしています。

各コンテナの設定

以降では、順にそれぞれのコンテナで利用している設定を見ていきましょう。

webコンテナ

まずは一番単純なwebコンテナから行きます。

  • image: 公式のnginxイメージを指定しています。予期していない変更を予防するため、バージョンタグを必ず指定しましょう。
  • environment: 環境変数を指定します。コンテナの役割やDEV/PROD環境の区別などを持たせておくとよいでしょう。
  • labels: コンテナにつけるラベルを指定します。必須ではありませんが、付けておくとCLIでのフィルタリングなどがしやすくなります。
  • ports: ホスト側の80番ポートとコンテナ側の80番ポートをマッピングしています。
  • networks: コンテナが接続するネットワーク(networksのセクションで定義したもの)を指定します。
  • depends_on: このコンテナが依存するコンテナを指定します。webコンテナはappコンテナへプロキシしますので、appコンテナを指定しています。
  • volumes: コンテナにマウントするボリュームを指定します。ボリュームのマウントにはいくつか種類がありますが、ここではホスト側のディレクトリをdocker-compose.ymlファイルからの相対パスで指定して、nginxの設定ファイルと、配信する静的コンテンツをコンテナ側で読み込めるようにしています。

dbコンテナ

次はdbコンテナです。使用しているMySQLイメージの挙動による設定がいくつかあります。(webコンテナと重複する項目は割愛します)

  • image: 公式のmysqlイメージを指定しています。
  • environment: MySQLのrootユーザのパスワードを環境変数 MYSQL_ROOT_PASSWORD で指定する必要があります。
  • volumes: ここでは3つのマウントを指定しています。1つめはMySQLの設定ファイル、2つめは初期化時に実行されるSQLスクリプトファイル、3つめはデータ領域となるディレクトリです。

MySQLイメージの挙動により、 MYSQL_ROOT_PASSWORD 環境変数がrootパスワードとして使用され、初期化時に /docker-entrypoint-initdb.d/db-init.sql のSQLが実行されます。このあたりの挙動については、 Docker Hubのページ に記載されています。

次回へ

次はappコンテナですが、少し長くなりそうなので、つづきは次回にしたいと思います。

続きを読む

AWSの各サービスを雑に紹介する

えー、投稿しておいて何ですが、本稿本当に雑ですので、ご利用にあたってはあくまで自己責任ということで、よろしくお願いします。

コンピューティング

  • Elastic Compute Cloud (EC2)
    仮想専用サーバ、従量課金制 ≫公式

  • EC2 Container Registry (ECR)
    DockerHubみたいなやつ ≫英語公式 / Google翻訳 ≫Developers.IO

  • EC2 Container Service (ECS)
    Dockerオーケストレーション(デプロイ、起動停止制御) ≫公式 ≫@IT

  • Lightsail
    仮想専用サーバ、定額制 ≫公式

  • AWS Batch
    ECS対応バッチジョブスケジューラ ≫公式 ≫公式 ≫Developers.IO

  • Elastic Beanstalk
    プログラム実行環境 (Java, PHP, .NET, Node.js, Python, Ruby)、EC2を使用 ≫公式 ≫YouTube

  • AWS Lambda
    プログラム実行環境 (Node.js, Java, C#, Python)、サーバレス ≫公式

  • Auto Scaling
    EC2対応オートスケール制御 ≫公式

  • Elastic Load Balancing
    負荷分散、BIG-IPとかその手のヤツのクラウド版 ≫公式 ≫@IT

ストレージ

  • Amazon Simple Storage Service (S3)
    オブジェクトストレージ。ファイルサーバとしても一応使える ≫公式

  • Amazon Elastic Block Store (EBS)
    ブロックデバイス ≫CodeZine

  • Elastic File System (EFS)
    ファイルサーバ ≫公式

  • Glacier
    バックアップストレージ ≫公式

  • Snowball
    HDDをFedExで送るオフラインデータ転送

  • Storage Gateway
    バックアップデバイスはお客様各自のオンプレミスにてご用意下さい、AWSは対向するインターフェースを提供します、というもの ≫CodeZine ≫Developers.IO

データベース

ネットワーキング & コンテンツ配信

移行

  • Application Discovery Service
    オンプレミスサーバの構成管理情報を収集する ≫公式

  • Database Migration Service (DMS)
    RDBをオンプレミスからAWSへ乗り換えるときに使う支援ツール

  • Server Migration Service (SMS)
    サーバをオンプレミスからAWSへ乗り換えるときに使う支援ツール

開発者用ツール

  • CodeCommit
    GitHubみたいなやつ

  • CodeBuild
    従量課金制ビルド

  • CodeDeploy
    コードデプロイ

  • CodePipeline
    Continuous Integration (CI) オーケストレーション。ビルド→デプロイの自動実行フロー定義。

  • AWS X-Ray
    分散アプリケーションのトレース ≫Serverworks

管理ツール

セキュリティ、アイデンティティ、コンプライアンス

  • AWS Identity and Access Management (IAM)
    AWSの認証、権限管理単位 ≫Developers.IO

  • Inspector
    脆弱性検出 ≫公式

  • Certificate Manager
    X.509証明書の管理 ≫公式

  • AWS Cloud Hardware Security Module (HSM)
    秘密鍵の保管(暗号、署名) ≫公式

  • AWS Directory Service
    Active Directory ≫Developers.IO

  • AWS Web Application Firewall (WAF)
    ファイアーウォール ≫公式

  • AWS Shield
    DDoS対策 ≫公式

分析

人工知能

IoT

ゲーム開発

モバイルサービス

  • Mobile Hub
    AWSのいろんなmBaaS系サービスを統合的に使えるコンソール画面 ≫Qiita

  • Cognito
    ソーシャル認証+データ同期。FacebookログインとかTwitterログインとか ≫Cookpad

  • AWS Device Farm
    テスト環境。Android, iOSの実機にリモートアクセスしてテストができる ≫公式

  • Mobile Analytics
    アプリの使用データの測定、追跡、分析 ≫公式 ≫Developers.IO

  • Pinpoint
    プッシュ ≫Qiita

アプリケーションサービス

  • Step Functions
    フローチャートみたいなビジュアルワークフローを画面上に描いて分散アプリケーションを構築する、というもの ≫公式

  • Amazon Simple Workflow (SWF)
    旧世代サービス。現在はStep Functionsを推奨 ≫公式

  • API Gateway
    HTTP API化 ≫公式

  • Elastic Transcoder
    動画、音声のフォーマット変換。つんでれんこaaSみたいなヤツ ≫Serverworks

メッセージング

  • Amazon Simple Queue Service (SQS)
    メッセージキュー ≫公式

  • Amazon Simple Notification Service (SNS)
    プッシュ ≫公式

  • Amazon Simple Email Service (SES)
    E-mail配信。メルマガとか ≫公式

ビジネスの生産性

デスクトップとアプリケーションのストリーミング

  • Amazon WorkSpaces
    仮想デスクトップ ≫impress

  • Amazon WorkSpaces Application Manager (WAM)
    Amazon WorkSpaces端末にアプリを配信するツール ≫serverworks

  • AppStream 2.0
    Citrix XenAppみたいなやつ ≫Developers.IO

参考文献

AWS ドキュメント
https://aws.amazon.com/jp/documentation/

AWS re:Invent 2016 発表サービスを三行でまとめる
http://qiita.com/szk3/items/a642c62ef56eadd4a12c

続きを読む

Terraformを使って GCP Pub/Sub から AWS Lambda へのPush通知の仕組みを作成した

先日作ったのでその覚書的なものです。
簡単に言うとこんな感じのものを作りました。

GKE上のDockerアプリ -> Stackdriver logging -> Pub/Sub -> Lambda -> Slack

作成の動機

概ね以下の背景です。

  • GCPをメインに、AWSも多少織り交ぜつつな感じのアプリケーションを作っている。
  • Stackdriverでアプリの監視を行っているがエラーログを検知したらSlackに通知する仕組みが欲しかった。
  • Stackdriver単体だとログ内容をSlackに通知できなさそうだった。
  • StackdriverはフィルタリングしたログをPub/Subへ流すことができるらしい。
  • Pub/Subはキューにデータが流れてきたときに指定したエンドポイントにPush通知できるらしい。

と、こんなかんじの前提があり Pub/Sub から lambda に流して、そこからさらにSlackに流せば実現できると目論んだ次第です。

LambdaにもPub/Subにも今回始めて触ったということもあってか結構迷走してしまいました。。

以降から本題となります。

Terraformに読み込ませるHCL

これがほとんど全てな感じですが、実際に使ったHCLをコメントを交えつつ添付しておきます。
varになっているところは適宜置換が必要かと思われますのでご注意下さい。

基本的にはTerraformサイト上のサンプルを組み合わせているだけです。
Terraformマジ便利ですね、最高です。
もっといろいろな知見がネット上に溜まってくれるとうれしいです。

data "aws_caller_identity" "self" {}

#### ここから API Gateway 周り####
resource "aws_api_gateway_rest_api" "alert_api" {
  name = "alerter"
}

resource "aws_api_gateway_method" "root_post_method" {
  rest_api_id   = "${aws_api_gateway_rest_api.alert_api.id}"
  resource_id   = "${aws_api_gateway_rest_api.alert_api.root_resource_id}"
  http_method   = "POST"
  authorization = "NONE"
}

resource "aws_api_gateway_integration" "alert_integration" {
  rest_api_id             = "${aws_api_gateway_rest_api.alert_api.id}"
  resource_id             = "${aws_api_gateway_rest_api.alert_api.root_resource_id}"
  http_method             = "${aws_api_gateway_method.root_post_method.http_method}"
  integration_http_method = "POST"
  type                    = "AWS"
  uri                     = "arn:aws:apigateway:${var.aws_region}:lambda:path/2015-03-31/functions/${aws_lambda_function.alerter.arn}/invocations"
}

resource "aws_api_gateway_method_response" "alert_200_response" {
  rest_api_id = "${aws_api_gateway_rest_api.alert_api.id}"
  resource_id = "${aws_api_gateway_rest_api.alert_api.root_resource_id}"
  http_method = "${aws_api_gateway_method.root_post_method.http_method}"
  status_code = "200"
}

resource "aws_api_gateway_integration_response" "alert_response" {
  rest_api_id = "${aws_api_gateway_rest_api.alert_api.id}"
  resource_id = "${aws_api_gateway_rest_api.alert_api.root_resource_id}"
  http_method = "${aws_api_gateway_method.root_post_method.http_method}"
  status_code = "${aws_api_gateway_method_response.alert_200_response.status_code}"
}

## stage名に使う名前をランダム文字列として生成する
resource "random_id" "secret_path" {
  keepers = {
    ami_id = "${aws_lambda_function.alerter.id}"
  }

  byte_length = 40
}

resource "aws_api_gateway_deployment" "alert_deployment" {
  depends_on = ["aws_api_gateway_method.root_post_method"]

  rest_api_id = "${aws_api_gateway_rest_api.alert_api.id}"
  stage_name  = "${random_id.secret_path.hex}"
}

resource "aws_api_gateway_domain_name" "alert" {
  domain_name = "${var.alerter_domain}"

  certificate_name        = "alert-ssl"
  certificate_body        = "${file("cert_path")}"
  certificate_chain       = "${file("chain_path")}"
  certificate_private_key = "${file("key_path")}"
}

resource "aws_api_gateway_base_path_mapping" "alert" {
  api_id      = "${aws_api_gateway_rest_api.alert_api.id}"
  domain_name = "${aws_api_gateway_domain_name.alert.domain_name}"
}

#### ここから IAM 周り####
resource "aws_iam_role" "lambda_alert_role" {
  name               = "lambda_alert_role"
  assume_role_policy = <<POLICY
{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Sid": "",
      "Effect": "Allow",
      "Action": "sts:AssumeRole",
      "Principal": {
        "Service": "lambda.amazonaws.com"
      }
    }
  ]
}
POLICY
}

#### ここから Lambda 周り####
resource "aws_lambda_permission" "apigw_alerter" {
  statement_id  = "AllowExecutionFromAPIGateway"
  action        = "lambda:InvokeFunction"
  function_name = "${aws_lambda_function.alerter.arn}"
  principal     = "apigateway.amazonaws.com"

  source_arn    = "arn:aws:execute-api:${var.aws_region}:${data.aws_caller_identity.self.account_id}:${aws_api_gateway_rest_api.alert_api.id}/*/${aws_api_gateway_method.root_post_method.http_method}/"
}

resource "aws_lambda_function" "alerter" {
  filename         = "${var.path_to_lambda_source}"
  function_name    = "alerter"
  role             = "${aws_iam_role.lambda_alert_role.arn}"
  handler          = "index.handler"
  runtime          = "nodejs4.3"
  source_code_hash = "${base64sha256(file(${var.path_to_lambda_source}))}"
  environment {
    variables = {
      webhook_url = "${var.slack_webhook_url}"
      channel = "${var.slack_channel}"
    }
  }
}

#### ここから Route53 周り ####
resource "aws_route53_record" "alerter" {
  zone_id = "${aws_route53_zone.primary.zone_id}"

  name = "${aws_api_gateway_domain_name.alert.domain_name}"
  type = "A"

  alias {
    name    = "${aws_api_gateway_domain_name.alert.cloudfront_domain_name}"
    zone_id = "${aws_api_gateway_domain_name.alert.cloudfront_zone_id}"
    evaluate_target_health = true
  }
}

####
#### ここから GCP
####

#### ここから Pub/Sub 周り ####
resource "google_pubsub_topic" "log_alert_topic" {
  name = "log-alert-topic"
}

## CAUTION: 以下のリンクの「他のエンドポイントの登録」の手順を行っていないドメインをendpointに入れているとapplyに失敗します
## https://cloud.google.com/pubsub/advanced#push_endpoints
resource "google_pubsub_subscription" "aws_lambda_subscription" {
  name  = "default-subscription"
  topic = "log-alert-topic"

  ack_deadline_seconds = 10

  push_config {
    push_endpoint = "https://${aws_api_gateway_domain_name.alert.domain_name}/${aws_api_gateway_deployment.alert_deployment.stage_name}"

    attributes {
      x-goog-version = "v1"
    }
  }
}

ハマったところとか困ったところを何点か

これだけだと味気ないので、いくつかハマってしまった点を記録しておきます

Pub/Sub へ Push Subscriber への外部ドメインの登録

(おそらく)セキュリティ上の理由から Pub/Sub でPush通知するためにはそのエンドポイントの所有者であることを証明しないといけません。

HCLの方にもコメントをしていますが、AppEngine等のPub/Subと同じGCPプロジェクト内で管理されている以外のドメインを利用したい場合には事前に手作業でドメイン認証が必要となります。
このドメイン認証を行うために、 API Gateway をカスタムドメインで公開してやる必要がありました。
若干面倒ではありますが、認証できないエンドポイントにリクエストを投げられるようにしてしまうとDOS攻撃みたいなことにつかえてしまうのでこれは仕方がないのだと思います。

ともかく事前この作業をやっておかないと terraform apply に失敗してしまいます。
作業内容は別に難しいものではなく、大きく分けて以下の2ステップで完了します。

  • Google Search Console をつかってRoute53をイジイジしてドメイン認証

    • DNSのTXTレコードを使ったよくある感じの認証です。
  • GCP Console の API Manager から API Gateway に設定したカスタムドメインを登録

Pub/Sub と Lambda 間の認証

こちらは、単に自分の Pub/Sub と Lambda の知識不足な可能性があります。
HTTPヘッダーの中身をカスタムする等の方法による認証方法が見つけられずかなり悩んでしました。

結局、当座の対応としてHCL内で生成したランダム文字列を公開URLに含ませておき、これを知らないとAPIを叩けないという仕様にしています。
正直これについてはもっと上手な解決策があるような気がしてなりません。。

続きを読む

ECSのチュートリアル – コンテナ運用を現実のものにする

皆さんこんにちは

以前にコンテナの何がいいのかを説明する資料を作りました。
「やっぱりコンテナ運用しか無いな」
「コンテナを使わざるを得ない」
「とりあえずdocker入れとけばいいや」
という声が聞こえてきそうです(幻聴)

一方で、コンテナで運用するとなると、新たなる監視体制が必要となります。
例えば、Dockerのコンテナが突然停止した場合、その状況を検知し、新しくコンテナを立ち上げる必要があります。
また、そもそもコンテナが乗っている環境をスケールする必要が出たりして、その場合は新しくスケールされた環境でもコンテナを立ち上げなければならないし、その設定をサーバに書かなければならないけど、そうなると結局コンテナが乗っているサーバがブラックボックス化したりするわけで、なんとかうまく回そうとすると、それなりに気を配ることが多くなってきます。

最近はlaradockを使用する開発者が増えてきた(ような気がする)ので、コンテナ運用で幸せになるためにECSを使ってみた記録をチュートリアル形式で再現しておきます。

え?備忘録?ははは

ECSとは

ECSはAWSが提供しているコンテナ運用サービスです。
ECSの概念のちょっとしたものは以前に書いたECSで困ったときに読むための俺的Q&Aに書いてありますが、今回はECSでたてるWEBサーバに絞って超かんたんなポンチ絵を作ってみました。

ecs.png

あまりややこしいところはなさそうですが、簡単に見ていきましょう。

クラスター、コンテナインスタンス

コンテナインスタンスはdockerのコンテナのホストになるインスタンスで、クラスターはこのコンテナインスタンスの群れ( オートスケーリンググループ )です。
コンテナインスタンスにはdockerとコンテナの状態を監視してこちらに伝えてくれるエージェントが入っています。
コンテナ運用時には、個々のインスタンスには興味が無いので、「クラスター」と一括りにしてしまいます。

タスク、ECR

タスクはアプリケーションのまとまりを一つ以上のコンテナ動作で定義します。
今回の例ではnginxを動かすコンテナとphp-fpmを動かすコンテナのふたつで、webサーバのタスクを定義していて、nginxが外部からのリクエストを受け付け、php-fpmに渡しています。
コンテナを定義するイメージはECRというAWSが提供しているプライベートなdockerイメージのレジストリから取得しています。

サービス

サービスは3つの仕事をします。
1つ目はタスクが現在必要とされている個数を保っているかを監視し、その数を下回っていた場合、タスクを立ち上げて必要数を保つことです。
2つ目は現在の負荷状況を鑑みて、タスクを増減させます。この設定はCloudWatchのアラーム機能と連携させます。
3つ目はtarget groupと立ち上がったタスクを紐付けることです。

また、タスクの配置を各AZに均等に配置したりと、よく気配りのきくやつです。

ALB、target group

ALBはロードバランサーです。昔のクラシックなELBと違って、間にtarget groupと言うものを設置して、細かくルーティングできるようになっています。
target groupは実際のサーバへの振り分けを実施し、ヘルスチェックもします。

今回はこれらを利用して簡単なWEBサーバを運用できる状況に持っていきましょう

コンテナの準備

とりあえずコンテナを作る

運用したくとも、そのもととなるコンテナイメージがないと何も始まりません。
そこで、例によってLaraDockを利用してlaravelアプリを作ってみましょう。
プロジェクトの作成はここを見てもらうとして(ダイマ)、LaraDockとほぼ同じ動作をしてもらうために、Dockerfileをコピーしちゃいましょう。

$ cp -r ../laradock/nginx ./
$ cp -r ../laradock/php-fpm ./

これでDockerfileと設定ファイルをコピーできます。

今回、コンテナの中は完全に固定化…つまり、スクリプトを内部に含ませてしまうため、各Dockerfileの後部に

COPY ./ /var/www/

これを追加しておきます
また、nginxのdefaultのコンフィグファイルも必要なので、nginxのDockerfileには

COPY nginx/sites/default.conf /etc/nginx/conf.d/

も追加しておきます。
なにはともあれ、イメージを作成してみましょう。

$ cp nginx/Dockerfile ./ && docker build -t niisan/nginx .
$ cp php-fpm/Dockerfile-70 ./Dockerfile && docker build -t niisan/php-fpm .

これでイメージが作られているので、試しにサーバを立ててみましょう。

$ docker run -d --name php-fpm niisan/php-fpm
$ docker run -d --link php-fpm:php-fpm -p 80:80  niisan/nginx
$ curl 127.0.0.1
<!DOCTYPE html>
<html lang="en">
    <head>
...

うまく動いているようです。

コンテナをアップロードする

次にECRにコンテナをアップロードするのですが、初めての場合、ちょっとビビります。
けばけばしいタイトルとともに「今すぐ始める」ボタンが登場し、その次のページで妙な選択肢を迫ってきます。

ECSを始めることを。。。強いられているんだ!

(こういうところ、あまり好きじゃないです)
ここではとりあえず、「Amazon ECR によりコンテナイメージをセキュアに保存する」だけを選択しておきます。
すると、リポジトリの作成用のウイザードが迫ってきます。

ECR

とりあえずリポジトリ名にnginxと入れて次のステップへ
今度はECRにイメージをアップロードする手順が出てきますので、この通りにやってみます。
前回の記事でも言及したように、ここだけはAWS CLIを使用する必要がありますので、頑張って入れておきましょう。

$ aws ecr get-login

これで出てくるログインコマンドをコマンドラインにコピーして実行すればログイン完了です。
既にイメージは作ってあるので、タグを張り替え、アップロードしましょう。

$ docker tag niisan/nginx:latest **************.ecr.ap-northeast-1.amazonaws.com/nginx:latest
$ docker push *****************.ecr.ap-northeast-1.amazonaws.com/nginx:latest

これで完了です。
手順ページの完了ボタンを押すと、いまアップロードしたイメージのレジストリができていることを確認できます。

そのまま、左のバーにあるリポジトリを選択し、同じようにphp-fpmもアップロードしてみましょう。
1分もかからず終わるでしょう。

ECR登録済み

デプロイ

タスクを定義する

コンテナのイメージもアップロードできたことですし、早速タスクを定義していきましょう。
と言っても、今回の場合、内容は異様なほど簡単ですんで、すぐに終わるでしょう。

タスクの名前は適当に決めていいと思います。(今回は webtest という名前にしました。)
早速コンテナを入れていきましょう。まずはphp-fpmから行きます。「コンテナを追加」ボタンを押すと次のモーダルが出てきます。

タスクを設定

php-fpmの設定はこれだけで十分でしょう。
次にnginxを設定します。基本的にはphp-fpmと同様にイメージと名前を設定するわけですが、二つほど、違う設定があります。

ポートフォワード

まずはポートの設定です。
nginxは外部から接続できなければならないので、ホストからポートフォワードするように設定しました。

内部リンク

もう一つはphp-fpmへのリンクです。
これで、タスクの定義は完了しました。

クラスターを作る

タスクを作ったので、こいつを動かしてみましょう。
こいつを動かすためには、動作環境が必要となりますが、それがクラスターです。
早速クラスターを作っていきましょう。

クラスターの作成

せこいですが、コンテナが動作するインスタンスは一番ちっちゃいやつを使います。
次にネットワーキングの設定ですが、これはデフォルトのvpcを使ってお茶を濁しておきます。

商用環境では独自のVPC使おう

では作成しましょう。

クラスター作成完了

クラスターが出来上がりました。

作ったクラスターを選択して、早速タスクを動かしてみましょう。
クラスター名を選択し、タスクタブからタスクの開始ボタンを押すと、動作するタスクを選択する画面になります。

タスクの実行

では動作してみましょう。
しばらくすると、次のような状態になっていると思います。

動いているっぽい

どうやら動いているようです。
ECSインスタンスからコンテナのホストになっているインスタンスを参照して、public dnsを調べましょう。
それをブラウザにはっつけると、Laravelのページが表示されます。
Webアプリのデプロイ完了
うまくいきました!

サービスを使う

とりあえずデプロイできて、動作も確認できました。
とはいえ、これを運用するのはまだまだ厳しいところです。

  • タスクが死んだ場合の復旧をどうすればいいのか
  • コンテナを更新したときのデプロイ方法はどうなるのか
  • コンテナのスケーリングはどうするのか

この辺をサービスに解決してもらうとしましょう。

タスクを停止してみる

とりあえず、タスクを停止します。クラスターのタスクタブで、先ほど動かしたタスクを落とします。
当然ですが、落としたタスクは復活したりしないので、この時点で先に動かしたWEBサーバはダウン状態となります。

イメージを更新する

これからロードバランサーを使用するに当たり、ヘルスチェック用のルーティングをします。
今回はlaravel5.4を使う(使っちゃってる)ので次のようなroutingを用意します。

routes/web.php
Route::get('/healthcheck', function () {
    return ['health'=>'ok'];
});

この状態で、Dockerのイメージビルドを再実行します。
コンテナを再度動かすと次のような挙動を示します。

$ docker run -d --name php-fpm niisan/php-fpm
$ docker run -d --link php-fpm:php-fpm -p 80:80  niisan/nginx
curl 127.0.0.1/healthcheck
{"health":"ok"}

これをECRに再アップロードしておきます。

タスクを更新する

次に、タスクを更新していきます。
タスクはバージョン管理されていて、タスクはの更新は正確には新しいリビジョンを作るということになります。

例えば、今動いているリビジョンのタスクを新しいリビジョンのタスクに置き換えることで、サーバを更新したことと同じ状況にできますし、いざ新しいリビジョンが障害を起こすようなものであった場合は古いリビジョンに戻してロールバックすることもできます。

タスク定義->webtestでタスク定義のリビジョン一覧が現れます。今は一個しか無いと思うので、それを選択し、新しいリビジョンの作成ボタンを押しましょう。
今回の変更はnginxのポートの部分になります。

ダイナミックポート

なんとホストポートが空欄になっていますが、これがダイナミックポートという仕組みになります。
これはコンテナインスタンスで開いているポートを選んで、nginxコンテナの80ポートに繋げる仕組みで、ALB + target groupと組み合わせるときに使用します。

ALBを用意する

ひとまずコンテナの調整はこの辺にしておいて、ロードバランサーの設定を始めましょう。
まず、サービス -> EC2 -> サイドバーのロードバランサーを選択し、ロードバランサーを作成ボタンを押しましょう。
ALBの設定
Application load balancer を選択して、次へを押すとロードバランサーの設定に移ります。
今回はデフォルトのVPCを使うので、名前以外は全部デフォルトで問題なしです。
サブネットも二つあると思うので、両方共チェックしておきましょう。
一応、プロトコルはHTTPにしておきましょう。
セキュリティの警告は、今回は別に秘密通信でもないので、必要ないです。

セキュリティブループの設定

セキュリティグループはとにかく設定しておきましょう。
覚えやすい名前にしておくと、後で便利かもしれません。

空のターゲットグループ

ターゲットの登録画面になりますが、今はターゲットがないので、そのまま次へで、作成を完了させます。
これで、とりあえずロードバランサーの作成が完了しました。

最後に、ロードバランサーのセキュリティグループからコンテナインスタンスのセキュリティグループへの通信経路を確保しておきましょう。
コンテナインスタンスのセキュリティグループ( EC2ContainerService-*** )のinboundを編集しておきましょう。

セキュリティグループの設定

ロードバランサーからのinboundで全てのtcpを選択しておきましょう。
ダイナミックポートを使うと、開いているポートを使うのでどのポートが割り当てられるかわかりません。

サービスの作成

ここまで来てようやくサービスの作成が初められます。
再びEC2 Container Serviceから先程作成したクラスターを選択し、サービスを選択します。
作成ボタンがあるので、これを押しましょう。
サービス作成
まず、タスクはWebtestを選ぶわけですが、ここではリビジョンを含めて指定することになります。
サービス名は・・・とりあえずタスクのファミリー名と同じにしています。
画面下部に行くとELBを設定するボタンがあるので押してみましょう。
スクリーンショット 2017-03-18 22.39.45.png
するとこんな画面になるので、さっき作ったALBを選択し、負荷分散用のコンテナがnginxで、ポートが0:80になっていることを確認したら、ELBへの追加ボタンを押しましょう
スクリーンショット 2017-03-18 22.41.36.png
するとこんな画面になるのでターゲットグループを先程追加したものに変更して保存を押しましょう。

すると、サービスにALBの情報が登録されるので、この状態でサービスを作成しましょう。

スクリーンショット 2017-03-18 23.41.08.png

クラスターの状態がこのようになれば、成功です。
あとは、ロードバランサーのDNSにアクセスして、
Webアプリのデプロイ完了
これが出れば成功です。

まとめ

実はこれ書き始めたのって随分と前なのですが、途中でコンテナ運用の何がいいのかを説明するための資料作りしていたら、時間が立ってしまったのです。
まあ、ECSって使ってみるとすごく楽で、更にスケーリングしたり、他のサービスと相乗りさせたりマイクロサービス化させたりがすごく簡単にできるのですが、Webアプリを動かすに当たっては、わりとハマりどころが多いので、一貫したチュートリアル形式のものを作ってみました。
特にハマりどころなのは、ALB -> コンテナインスタンスにおけるセキュリティグループの設定だと思います。
考えてみれば当たり前なのですが、まあ、忘れることが多いです。
とはいえ、そんなところを超えてしまえば、後はコンテナで簡単に運用できる環境を量産できるので、皆さん是非とも使ってみてください。

今回はそんなところです。

参考

コンテナに挫折したあなたへ – 超わかりやすい発表資料です!師匠と呼びたい

続きを読む

ECS 導入における三つの明確な傾向

Datadog 上の原典ポストへのリンク:
https://www.datadoghq.com/blog/3-clear-trends-in-ecs-adoption/

以下は、Datadog が 2016 年末に公開した、”3 clear trends in ECS adoption” のポストを @jhotta が日本語化にしたものです。プロの翻訳ではなく、 もっぱら素早く ECS の普及状況を共有することを目的としています。技術的な要素で日本語の表記に問題がある場合は、コメントなどにより連絡をもらえますと助かります。


Last year, we published a study of Docker usage across our broad customer base. The data, which we then updated in June 2016, shows that the excitement around Docker is not just hype. Docker is being used at a large and ever-increasing number of organizations, and the companies that try Docker tend to stick with it.

As this young technology finds increasing use in production environments, we decided to take a deeper look at how organizations are managing their containerized application infrastructure. At Datadog, we have seen a tremendous amount of interest in container orchestration tools such as Kubernetes and Amazon ECS, but we wanted to see if our anecdotal observations were backed up by actual usage data.

Because we have thousands of customers running Docker, we can see usage and adoption trends emerging in real-time. In this article we’ll examine how organizations are using ECS specifically, although we plan to study container orchestration more broadly in the future. We’ve chosen to focus on ECS initially because Datadog’s integration with ECS has been generally available for well over a year, giving our customers plenty of time to start using it.

お客さまの利用状況を基に、2015年 Docker の使用状況に関する調査を公開しました。2016年6月に更新した同調査のデータでは、 Docker の周りで起きている盛り上がりは、単なる一時的な流行ではないことを示しています。 Docker は、ますます多くの組織で使用され、又 Docker を採用している組織の規模も大きくなってきています。そして、Docker を試してみた企業は、それを引き続き使い続ける傾向にあります。

公開されて間もないこのテクノロジーが実運用環境で次々と採用されるようになってきたのを踏まえ、 Docker を採用した組織が、コンテナ化されたアプリケーション インフラストラクチャを、どのように管理しているかを詳しく調査することにしました。 Datadog では、 Kubernetes や Amazon ECS などのコンテナ オーケストレーション ツールに、多くの技術者が関心を寄せているのを既に把握しています。しかし、この高い関心を、実際の利用状況のデータがバックアップしているかどうかを確認したいと考えました。

弊社には、Docker を使用している何千ものお客さまがいるため、利用状況と採用状況の傾向をリアルタイムで判定できます。将来的には、コンテナ オーケストレーションについてより広く検証していく予定ですが、この記事では Docker を採用した組織が ECS をどのように使用しているかについて検証していきます。今回、 ECS を選んだ理由は、ECS インテグレーションは一般的に利用できるようなってから一年以上が経過しており、組織が採用を決断するには十分な時間が経過していると判断したからです。

基礎知識: ECS の仕組み

Amazon’s EC2 Container Service (ECS) is a hosted service for managing and orchestrating Docker containers in the AWS cloud. As the name suggests, ECS allows you to run Docker containers on a cluster of EC2 instances. ECS handles the scheduling and placement of containers across your cluster, balances load across containerized services, and can be configured to automatically scale your container infrastructure based on demand. And of course ECS integrates neatly with other AWS services, such as CloudWatch, ELB (Elastic Load Balancing) and Auto Scaling.

Amazon の EC2 コンテナサービス(ECS)は、 AWS クラウドの Docker コンテナを管理およびオーケストレーションするためのホスト型サービスです。 その名前が示すように、 ECS では EC2 インスタンスのクラスタ上で Docker コンテナを実行できます。 ECS は、クラスタ全体のコンテナのスケジューリングと配置を処理し、コンテナ化されたサービス間の負荷のバランスをとり、需要に基づいてコンテナインフラストラクチャを自動的に拡張するように構成できます。 もちろん、 ECS は CloudWatch、ELB(Elastic Load Balancing)、自動スケーリングなどの他の AWS サービスときちんと統合されています。

トレンド 1: ECS は静かに、着実に人気を獲得している

ECS does not have the buzz or community that buoys the open source competitor Kubernetes, but our data shows that ECS is getting plenty of real-world use. In the year-plus since Datadog’s ECS integration was first released, ECS adoption has climbed steadily from zero to 15 percent of Docker organizations using Datadog. (And more than 10 percent of all Datadog customers are now using Docker.)

ECS is steadily gaining steam for Docker orchestration.

The graph of ECS adoption as a share of Docker users shows a slight flattening in recent months, but it’s important to note that this analysis may underestimate the share of Docker users in Datadog’s customer base who run ECS.1

ECS には、オープンソースの競合である Kubernetes のように、バズって人気を押し上げてくるコミュニティはありません。しかしデータは、 ECS が実際に多くの利用を獲得ていることを示しています。 Datadog が ECS インテグレーションをリリースしてからの一年ちょっとの期間で、Dcoker 採用組織内での ECS 採用組織の割合が 0% から 15% に安定的に増えていきました。(尚現在、Datadog の全利用者の 10% 以上が、 Docker を使用しています。)

ECS は Docker オーケストレーションを実現するツールとして着実に人気を集めています。

Docker ユーザ内の ECS ユーザの割合としての ECS 採用グラフは、ここ数ヶ月でわずかに平坦化しています。しかしこの分析結果は、Datadog の顧客ベース内で ECS を採用している Docker ユーザを過小評価している可能性があるこに注意してください。(脚注:1)

トレンド 2: コンテナの増加は、問題の増加

As you might expect, orchestration is more prevalent in organizations with more Docker. After all, manually shepherding your containers is fine for small projects, but can become untenable as the number of hosts and containers grows.

Among Datadog users, we see very limited usage of ECS in organizations where fewer than five unique hosts report Docker metrics over the course of a month.2 But as the Docker infrastructure grows, so does the likelihood that a given organization will orchestrate its containers using ECS. Nearly 40 percent of organizations monitoring large Docker installations of more than 100 hosts are also monitoring ECS.

ECS usage correlates with larger, more complex Docker infrastructure.

Bucketing organizations by the number of unique Docker images in use, rather than unique hosts, reveals a similar pattern: The more images an organization uses, the higher the rate of ECS use.

予想が付くと思いますが、オーケストレーション ツールは、扱う Dcoker (コンテナ)が多い組織ほど、一般的に普及しています。結局のところ、コンテナを手動で取り扱うことは、小規模なプロジェクトではうまくいきますが、ホストやコンテナの数が増えるにつれて容認できなくなってきます。

Datadog ユーザの間では、一ヶ月間に 5 台以下のホストが Docker メトリックを送信してくる組織では、 ECS の使用が非常に限定されています。(脚注:2) しかし、 Docker インフラストラクチャが拡大するにつれて、組織が ECS を使ってコンテナを編成する可能性も高くなります。100 台以上の Docker ホストを有する大型の Docker 環境を監視するような組織では、40% 近くが ECS も監視しています。

ECS の使用は、より大きくより複雑な Docker インフラストラクチャと相関します。

ホスト単位ではなく、使用中の Docker イメージ単位で組織を分類しても同様のパターンが明らかになります: 組織が使用するイメージが多いほど、 ECS の使用率は高くなります。

トレンド 3: オーケストレーション == 多産家系

Whether increasingly complex infrastructure demands orchestration, or orchestration opens the door to more complex container infrastructure, one thing is clear: the typical organization’s container infrastructure grows significantly right around the time that they start using ECS.

The graphs below track the increase in running containers and Docker hosts associated with a typical organization’s adoption of ECS (as inferred from the first arrival of ECS metrics). The counts are normalized per organization so that a value of 1.0 represents the organization’s average value across the time window.

We include a 60-day “before” window to show that the baseline prior is fairly steady, then starts to increase around 10 days before ECS adoption. This early ramp-up could be explained by organizations making changes to their infrastructure in preparation for a cutover, or by a lag between the actual adoption of ECS and the start of monitoring ECS with Datadog.

Companies start using more containers and Docker hosts when they adopt ECS.

In the 30 days after an organization starts reporting ECS metrics, we see a 35 percent increase in the number of running containers as compared to the 60-day baseline that came before. Using the same parameters, we see a 27 percent increase in the number of running Docker hosts.

益々複雑化するインフラストラクチャがオーケストレーションに走らせるのか、又は、オーケストレーションが複雑なコンテナインフラストラクチャを可能にしているのかというという問いのたいして言えることは、典型的な組織のコンテナ インフラストラクチャは、 ECS の使用を開始する頃に大きく成長します。

以下のグラフは、標準的な組織の ECS 採用に関連したコンテナおよび Docker ホストの増加を追跡しています(ECS メトリクスを最初に受信した時を基準にしています)。カウントは組織ごとに正規化されるため、値の1.0 は、全の時間をサンプル対象にしたその組織の平均値になります。

ECS 導入の前のベースラインがほぼ安定していることを示すために、採用前 60 日を表示しています、その後 ECS 導入の約 10 日前に増加が始まります。この初期の立ち上げは、企業がカットオーバに備えるためにインフラストラクチャを変更することによって、またはECSの実際の採用とDatadogによるECSの監視の開始の遅れによって説明できます。

企業は、ECS を導入すると、より多くのコンテナと Docker ホストを使用し始める。

組織が ECS メトリクスの収集を開始してから 30 日後には、実行中のコンテナ数は、”60日間のベースライン”に比べて 35% 増加しています。 同じパラメータを使った場合、実行中の Docker ホスト数は、 27% 増加します。

オーケストラのチューニング (構成要素のチューニング)

Docker is still a young technology, and the tooling around it is younger still. But all indications from our ECS analysis and our larger Docker adoption study are that plenty of organizations are already getting serious about containerization.

As container orchestration marches closer to the mainstream, we will continue to keep an eye on emerging trends. Look out for new and updated analyses on Docker adoption, ECS usage, and other infrastructure trends in the coming months.

Docker はまだ若い技術であり、その周辺のツールもまだ若いです。しかし、今回の ECS の導入実態に関する分析と、これまでの Docker 導入調査からは、多くの組織がすでにコンテナ化について真剣に取り組んでいるということです。

コンテナ オーケストレーションが主流になっていくにつれ、新たな傾向が読み取れないか、引き続き注力していきたいと思います。
現在準備している 更新版の Docker の導入分析、 ECS の使用状況分析、及び今後のインフラストラクチャ動向に関する分析にもご期待ください。

脚注


  1. The percentages in this graph are calculated by selecting all the organizations that enabled the Docker integration in Datadog, and determining which of those organizations also have ECS enabled in their account. But some organizations may run ECS without native Docker instrumentation, so they are excluded from the calculation. [return]
  2. These percentages are calculated from host and image counts during the month of October 2016. [return]
  1. グラフのパーセンテージは、 Datadog で Docker インテグレーションを有効にしたすべての組織を抽出し、その中から ECS のアカウントで有効になっている組織を抽出して計算されています。しかし、一部の組織では、Docker インテグレーションなどの Datadog では一般的な Docker の監視方法を使用せずに ECS を起動していることがあるため、それらの組織については計算に含まれていません。
  2. これらのパーセンテージは、2016年10月の月間のホスト数とイメージ数から計算されます。

続きを読む