Edited at

TerraFormでHHVMコンテナをAmazon ECS上で動かす

More than 3 years have passed since last update.

前回の続きです。

HHVMコンテナをFactCGIモードで動かしてみます。

構築はTerraFormを利用し、コンテナ実行環境はAmazon ECSを利用します。


構築イメージ

ELB(Public)より、apacheコンテナに流し、ELB(Internal)を経て、HHVMコンテナ(FactCGI)に接続します。

ECS.png


必要なもの


  • TerraForm

  • Amaozon AccessKey/SecretKey(secret.tfvars)

  • Amazon VPC

  • AWS セキュリティグループ

  • EC2キーペア

  • apacheコンテナイメージ


利用したDockerイメージ


事前準備(抜粋)

事前準備の一部を記載します。


  • セキュリティグループ


    以下3つのセキュリティグループ(※アウトバウンドはすべて許可)を用意します。





  1. Public ELB用(security_group1)


    インバウンド:HTTP、HTTPSのみすべて許可



  2. 内部 ELB用(security_group2)


    インバウンド:VPC内(private network)のみ9000(FactCGI)ポート許可



  3. EC2 container instance用(security_group3)


    インバウンド:VPC内(private network)のみ全ポート許可、接続元端末より(マイIP)全ポート許可(※各種確認用)




  • apacheコンテナイメージ


    dockerへのenv(environment)の引き回しがうまく動作しなかったため、apacheコンテナのELB(internal)接続はベタ書きしています。。。

    以下を動作させるにはhttps://github.com/Thirosue/docker-apache2をクローンして、以下を修正し、DocekrHubへプッシュしてください。(参考手順




hhvm_proxy_fcgi.conf

ProxyPassMatch ^/(.+\.(hh|php)(/.*)?)$ fcgi://{内部ELBのAレコードを記載}:9000/app/$1



構築

TerraFormで構築します。

EC2コンテナインスタンスは、Auto Scalingで構成します。

作成したELBをECS Service(Task Difinision)に紐付けます。

サンプルソース


  • plan

terraform plan -var-file=../secret.tfvars \

-var 'ssh_key_name=[EC2キーペア名]' \
-var 'security_groups_internal=[security_group3のIDを記載]' \
-var 'security_groups_dmz=[security_group3のIDを記載]' \
-var 'hhvm_vip=internal-hhvm-892282372.ap-northeast-1.elb.amazonaws.com'


  • apply

terraform apply -var-file=../secret.tfvars \

-var 'ssh_key_name=[EC2キーペア名]' \
-var 'security_groups_internal=[security_group3のIDを記載]' \
-var 'security_groups_dmz=[security_group3のIDを記載]' \
-var 'hhvm_vip=internal-hhvm-892282372.ap-northeast-1.elb.amazonaws.com'


variable.tf

#######################

# Required
#######################

variable "access_key" {}
variable "secret_key" {}

# SSH key
variable "ssh_key_name" {}

# security group internal
variable "security_groups_internal" {}

# security group dmz
variable "security_groups_dmz" {}

# internal elb for hhvm
variable "hhvm_vip" {}

#######################
# Option
#######################

variable "region" {
default = "ap-northeast-1"
}

variable "aws_amis" {
default = {
"ap-northeast-1" = "ami-2b08f44a"
}
}

# Instance Type
variable "instance_type" {
default = "t2.micro"
}



ecs_cluster.tf

provider "aws" {

access_key = "${var.access_key}"
secret_key = "${var.secret_key}"
region = "${var.region}"
}

resource "aws_ecs_cluster" "hhvm" {
name = "hhvm"
}


※以下詳細なソース


task_difinision.tf

resource "aws_ecs_task_definition" "hhvm" {

family = "hhvm"
container_definitions = "${file("task-definitions/hhvm.json")}"
}

resource "aws_ecs_task_definition" "httpd" {
family = "httpd"
container_definitions = "${file("task-definitions/httpd.json")}"
}



hhvm.json

[

{
"name": "hhvm",
"image": "mirrored1976/hhvm-sample",
"cpu": 10,
"memory": 300,
"essential": true,
"portMappings": [
{
"containerPort": 9000,
"hostPort": 9000
}
]
}
]


httpd.json

[

{
"name": "httpd",
"image": "[用意したapacheコンテナのイメージを指定]",
"cpu": 10,
"memory": 300,
"essential": true,
"portMappings": [
{
"containerPort": 80,
"hostPort": 80
}
],
"environment": [
{
"name": "HHVM_VIP",
"value": "internal-hhvm-892282372.ap-northeast-1.elb.amazonaws.com"
}
]
}
]


elb.tf

resource "aws_elb" "httpd" {

name = "httpd"
availability_zones = ["ap-northeast-1a"]
security_groups = ["${var.security_groups_dmz}"]

listener {
instance_port = 80
instance_protocol = "http"
lb_port = 80
lb_protocol = "http"
}

health_check {
healthy_threshold = 2
unhealthy_threshold = 10
timeout = 10
target = "HTTP:80/"
interval = 30
}

cross_zone_load_balancing = true
idle_timeout = 400
connection_draining = true
connection_draining_timeout = 400
}



auto_scaling.tf

resource "aws_launch_configuration" "hhvm" {

name = "hhvm"
image_id = "${lookup(var.aws_amis, var.region)}"
key_name = "${var.ssh_key_name}"
instance_type = "${var.instance_type}"
iam_instance_profile = "ecsInstanceRole"
security_groups = [
"${var.security_groups_internal}"
]
user_data = "${file("user_data/userdata.sh")}"
}

resource "aws_autoscaling_group" "hhvm" {
availability_zones = ["ap-northeast-1a"]
name = "hhvm"
max_size = 2
min_size = 2
desired_capacity = 2
health_check_grace_period = 300
health_check_type = "ELB"
force_delete = true
launch_configuration = "${aws_launch_configuration.hhvm.name}"
}



ecs_service.tf

resource "aws_ecs_service" "hhvm" {

name = "hhvm"
cluster = "${aws_ecs_cluster.hhvm.id}"
task_definition = "${aws_ecs_task_definition.hhvm.arn}"
desired_count = 2
iam_role = "ecsServiceRole"

load_balancer {
elb_name = "[用意した内部ELBの名前を記載]"
container_name = "hhvm"
container_port = 9000
}
}

resource "aws_ecs_service" "httpd" {
name = "httpd"
cluster = "${aws_ecs_cluster.hhvm.id}"
task_definition = "${aws_ecs_task_definition.httpd.arn}"
desired_count = 2
iam_role = "ecsServiceRole"

load_balancer {
elb_name = "${aws_elb.httpd.name}"
container_name = "httpd"
container_port = 80
}
}



確認


  • HTTP/FactCGI

    ブラウザで以下にアクセス。

    http://[Public ELBのIP]/phpinfo.php



  • dockerコンテナ

    各EC2 container Instanceへsshすると、apacheコンテナとhhvmコンテナ及びecs-agentコンテナが動いているのが確認できる。


$ ssh -i "[EC2キーペア名]" ec2-user@ec2-52-197-239-125.ap-northeast-1.compute.amazonaws.com

$ docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
ad616c73345f mirrored1976/apache2 "/usr/sbin/apachectl " About an hour ago Up About an hour 0.0.0.0:80->80/tcp ecs-httpd-11-httpd-88cea3affcb5c0c55e00
1d70ef3a503c mirrored1976/hhvm-sample "/start.sh" About an hour ago Up About an hour 0.0.0.0:9000->9000/tcp ecs-hhvm-23-hhvm-e2b583edaa80be909501
6172ac18f2af amazon/amazon-ecs-agent:latest "/agent" About an hour ago Up About an hour ecs-agent


後処理

サンプルを破棄します。


  • plan destroy

terraform plan -destroy -out=./terraform.tfstate -var-file=../secret.tfvars \

-var 'ssh_key_name=[EC2キーペア名]' \
-var 'security_groups_internal=[security_group3のIDを記載]' \
-var 'security_groups_dmz=[security_group3のIDを記載]' \
-var 'hhvm_vip=internal-hhvm-892282372.ap-northeast-1.elb.amazonaws.com'


  • do destroy

terraform apply ./terraform.tfstate


最後に

今回の構築はかなり手こずりましたが、お陰さまでAmazon ECSが大分理解できました。

初めは、ECSは難しいと感じましたが、理解できるとシンプルなので、実戦投入できるよう詰めていきます。