Terraformで
ECS+ECRする話
TechTalk #4, 2017/02/14
Satoshi.Hirayama
@Galapagos, Inc.
- 平山 聡
- @株式会社ガラパゴス(←5社目
- サーバーサイド&インフラ文系エンジニア
- 先日Swiftデビューもしました
- 社内ポエマー
- 前職以前は無駄にいろんな言語で無駄にいろんなターゲットを相手に
- 68Kアセンブラ, C, C++, Java, Javascript, Objective-C, Object Pascal, Pascal, Ruby, VB, etc
- 4D, FileMaker, Oracle, PostgreSQL, etc
- iOS, iTron, Mac OS(Classic), Mac OS X, RHEL, Solaris, Windows, etc
- 官公庁, 金融機関, 公共機関, 研究機関, 企業, プロシューマー, コンシューマー, etc
自己紹介
- 主な事業
- スマートフォンアプリの受託開発
- 機械学習で何かする
- 主な技術
- Java、Rails、Swift、Tensorflow、AWS...など
- 自社アプリも開発してます!
- エンジニアブログ
- http://gtech.hatenablog.com/
ガラパゴスの紹介
Start fit
「脱・三日坊主」始めて続く ダイエットフィットネスアプリ
iOS / Apple Watch
ひっそり40万+DL
https://itunes.apple.com/jp/app/tuo-san-ri-fang-zhu-shimete/id985618426?mt=8
今回のゴール
- AWSリソースはTerraformで
どーんします
- ECSコンテナインスタンスは以
下の環境に構築します
- Proxyを使ったプライベートサブ
ネット
- Amazon ECS Optimized AMIは
使わずにUbuntu上に構築
- ECS (Amazon EC2 Container Service)
- docker
- コンテナAをクラスタ(インスタンス) 1で動かす、というような管理
- ECR (Amazon EC2 Container Registry)
- docker repository
- docker hubと異なり容量と転送量で課金( S3的なイメージ)
- Terraform
- インフラどーんするやつ
- VPC以下のAWSリソースを一気に
ざっくりすぎる要素の説明
承前:普通に環境を作る時
- VPCを作って……
- サブネットを作って……
- ルートテーブルを作って……
- セキュリティグループを作って……
- ELBとかEC2とかRDSとかNATとかのインスタンスを作って……
ECR環境の準備
- すべてのサービス→コンピューティング→EC2 Container Service
- リポジトリ→リポジトリの作成→名前を入れるだけ
- プッシュコマンドの表示→ガイドにしたがうだけ
- めっちゃ簡単
ECS環境の準備
- クラスターの作成
- ECSのコンソールで入力項目を埋めてクラスターを作成
- Amazon ECS-Optimized AMIのEC2インスタンスが自動で希望した分だけできる
- タスク定義の作成
- どのコンテナをどのクラスターで動かすか指定
- CPUやメモリの割り当てなども設定できる
UbuntuでECSするときの前提知識
- ECSクラスターインスタンス
- ecs-agentが入ってる
- ecs-agent自体もdocker container
- amazon-ecs-initが入ってる → インスタンス起動時に ecs-agentを起動
- ecs-agentには「どのクラスタに属しているのか」を指定する必要がある
- ecs-agentが動作しているEC2インスタンス=ECSクラスターインスタンス
ロール設定
- インスタンスで以下のロールを許可する必要がある
- ecs:
- CreateCluster, DeregisterContainerInstance, DiscoverPollEndpoint, Poll,
RegisterContainerInstance, StartTelemetrySession, Submit*, StartTask
- ecr:
- BatchCheckLayerAvailability, BatchGetImage, GetDownloadUrlForLayer,
GetAuthorizationToken
- ec2:
- Describe*, AuthorizeSecurityGroupIngress
- LB配下に置く場合は、加えて以下も必要
- elasticloadbalancing:
- Describe*, DeregisterInstancesFromLoadBalancer, RegisterInstancesWithLoadBalancer
Proxy環境でのecs-agent設定
- dockerインストール時の注意
- docker自身も環境変数etcのproxy設定を読まないので proxyを使うように設定ファイルを作る必要
がある
- ecs-agentインストール時の注意
- ecs-agentも環境変数やdockerに設定したproxy設定を読まないので( ry
- NO_PROXYを指定する必要がある
- 169.254.169.254,169.254.170.2,/var/run/docker.sock
- この設定値は公式ドキュメント参照
- http://docs.aws.amazon.com/AmazonECS/latest/developerguide/http_proxy_config.html
- これらのIPはiptableも編集する必要がある
UbuntuでECSする時
- クラスター作成時に「空のクラスター」を選ぶ
- 普通にUbuntuのEC2インスタンスを作る
- dockerをインストールしてamazon-ecs-agentをdocker pull & docker startする
ECSが設定された時の図
クラスター→登録済みインスタンスと実行中のタスクが 1に
なる
sshしてdocker psするとecs-agentと登録したタスクが表示
される
簡単
じゃあ同じのもう一つ作って
えっ
さっき簡単だと言ったな
あれは嘘だ
ECR(+ECS)ハマりポイント
-
-
-
- ロールの設定が反映されるのに時間がかかる
- ECRからのdocker pullでコケる
- LBにコンテナをアタッチする場合、コンテナを実行できないと LBからデタッチされる
- 通常のEC2でヘルスチェックがエラーになった時のような Out of serviceではなく、インスタンスがな
い状態になる
←こういうエラーで
 コンテナが起動しない
- docker imageを更新した時
- docker push後、タスク定義を最新にしても、古いタスクが動いたままになって新しいコンテナが動
かない
- deployment_minimum_healthy_percent(最小ヘルス率)を満たす分だけ古いコンテナを残し
て入れ替わる
- deployment_minimum_healthy_percentを満たす分だけ新しいコンテナに入れ替わると残り
も全部入れ替わる
- デフォルトでは100%が指定されているので入れ替わらない
- 複数のコンテナインスタンスがある場合は適切に設定する
- このとき、手動でタスクを停止すると、 LBからインスタンスがデタッチされてしまう
ECSハマりポイント
そもそも:コンソールでAWSする時のつらみ
- このリソースなんだっけ的なことが割とよくある
- 名前を知りたいのに IDしか出てこないとか
- AZで選びたいのにIDしか出てこないとか
- タグをつけ忘れて何だかわからなくなる
- デフォルトで作られるリソースにはタグがなくてイミフになる
- デフォルト設定でリソースを作ってしまう
- RDSのパラメータグループとか後から変えられないので泣きたくなる
- ちょっとした設定の変更とか忘れる
手順書をk……
滅びろ
そこでTerraformですよ
- https://www.terraform.io/
Terraform
- インフラの構築・変更・廃棄を効率的に行うためのツール
- サーバ構成をコード化
- 有名どころのサービスにはいろいろ対応
- AWS, GCP, Azure, BitBacket, DigitalOcean, Heroku, ...
- 非クラウドな仮想環境にも対応
- OpenStack, VMWare, …
- Hashicorp社製
Terraformを使った作業の流れ
- tfファイルを作る
- 作られるリソースを確認する
- 実際にリソースを作る
tfファイルの作成
- 割と1:1で対応している
→ resource “aws_subnet”
→ resource “aws_route_table”
→ resource “aws_security_group”
→ resource “aws_instance”
→ resource “aws_s3_bucket”
tfファイルの作成
resource "aws_instance" "app" {
ami = "ami-0567c164"
associate_public_ip_address = "false"
availability_zone = "ap-northeast-1a"
instance_type = "t2.micro"
key_name = "techtalk"
root_block_device = {
volume_size = "20"
volume_type = "gp2"
}
subnet_id = "${aws_subnet.private_1.id}"
tags {
Name = "techtalk_app"
}
vpc_security_group_ids = ["${aws_security_group.private.id}"]
}
- リソースの設定はそのまま key = “value” の
形式で書く
- あっちゃこっちゃタブを行き来したりしなくてい
い
- 依存するリソースの値を変数として参照できる
tfファイルの作成
- easy
- コンソールを使ったことがあれば迷わないはず
- AWS SDKを使ったことがあればもっと迷わないはず
ECSリソース
- aws_instanceリソース
- ECSクラスタを動かすインスタンス
- 通常はAmazon ECS Optimized AMIを指定する
- aws_ecs_clusterリソース
- Amazon ECS -> クラスターに相当
- aws_ecs_task_definitionリソース
- Amazon ECS -> タスク定義に相当
- aws_ecs_serviceリソース
- Amazon ECS -> クラスター -> サービスに相当
ECRリソース
- aws_ecr_repositoryリソース
- リポジトリを指定する
- aws_ecr_repository_policyリソース
- リポジトリのアクセス許可を指定する
ECSでECRを使うときは先にECRだけ作る
resource "aws_ecs_task_definition" "task_definition" {
container_definitions = <<EOS
[
{
"name": "nginx",
"image": "nginx",
...
ここにECRリポジトリのURIを入れる
ex.
“image”: “xxxxxxxxxxxx.dkr.ecr.ap-northeast-1.amazonaws.com/techtalk”
実行時に依存するリソースが必要なので、
ECRを作成→aws ecr get-loginして必要な情報を得る →docker push→その
他のリソースを作成、
という手順を踏む必要がある
← タスク定義のJSON
作られるリソースの確認
- terraform plan すると実行計画を確認できる
$ terraform plan
Refreshing Terraform state in-memory prior to plan…
(略)
+ aws_ecr_repository.repo
arn: "<computed>"
name: "techtalk"
registry_id: "<computed>"
repository_url: "<computed>"
(略)
Plan: 2 to add, 0 to change, 0 to destroy.
$
- terraform apply したら一式できる
- リソース追加しいときはtfファイルに追加してapply
リソースの作成
$ terraform apply
aws_ecr_repository.repo: Creating...
arn: "" => "<computed>"
name: "" => "techtalk"
registry_id: "" => "<computed>"
repository_url: "" => "<computed>"
(略)
Apply complete! Resources: 2 added, 0 changed, 0 destroyed.
$
$ terraform destroy
Do you really want to destroy?
Terraform will delete all your managed infrastructure.
There is no undo. Only 'yes' will be accepted to confirm.
Enter a value: yes
aws_ecr_repository.repo: Refreshing state... (ID: techtalk)
(略)
aws_ecr_repository.repo: Destroying...
aws_ecr_repository.repo: Destruction complete
Destroy complete! Resources: 2 destroyed.
$
- 一部だけ消したいときはそのリソースをtfファイルから消してapply
- terraform destroyで全部消える
リソースの削除
- インフラをコードに記述
- 論理的一貫性がある
- 冪等性がある
- コンソール上での悩みの多くが解決
- easy
- 独自言語だがJSON拡張
- AWS SDKでイチから書くのに比べてはるかに少なくシンプルな記述
- tfファイルは使い回しできる
- 同じような構成のインフラを何度でも作れる
- tfファイル自体にはAWSアカウントの情報は含まれないので別のアカウントに適用できる
- 分割できるので要素ごとに書いておいて必要なぶんだけ使うようにできる
しあわせになれるところ
ハマりポイント
- 不用意にパラメタを変更するとdestroyしてcreateになることがある
- planをよく見る
- 管理コンソールから手で作ったリソースがあるとエラーになることがある
- 競合しないようにtfファイルを管理する必要がある
リソースのprovisioning
- Terraformにもprovisionerがある
- ファイルを転送してコマンドを実行するくらいのことができる
- または、リモートでChef clientを実行できる
- ただし、リソースの作成時しか実行されない
- プロビジョニングしたいのはリソース作成時とは限らない
- → ChefでもAnsibleでもJujuでもお好みで
今回のサンプルコード
- https://github.com/satoshi-hirayama/techtalk4
- 入っているもの
- Terraform
- ECRリソースを作る
- ECSクラスタインスタンスを作る
- Ansible
- Proxy設定する
- dockerをインストールする
- Ubuntu Xenial XerusをECSコンテナインスタンスにする
- Docker
- Dockerfile
- html
最後に
- ガラパゴスではエンジニアを募集しています!
- コンピュータに頑張ってもらってエンジニアは楽をするための努力を惜しまない方
- 業務での保守的すぎる技術選択(言語、ライブラリ、 etc)に嫌気がさしている方
- いろいろチャレンジしたい方
- AWSピタゴラスイッチしたい方
- オフィスハックしたい方
- インフラの妖精さんな方
- 人類の進化に貢献したい方、もしくは人類を滅ぼしたい方
- おとめな方(老若男女問わず)
- OSSコミュニティに敬意を持つ方 (必須)
- ガラパゴスではエンジニアを募集しています!
- https://www.glpgs.com/recruit/
- まずは話を聞いてみたいという方も御気楽に遊びに来ていただければ!
ご静聴ありがとうございました

TerraformでECS+ECRする話