Pro Yearly is on sale from $80 to $50! »

AWSとTerraform初心者が やってみたこと

F8865f41777ef3caced0e4e6801ff83a?s=47 masa-ita
December 21, 2019

AWSとTerraform初心者が やってみたこと

F8865f41777ef3caced0e4e6801ff83a?s=128

masa-ita

December 21, 2019
Tweet

Transcript

  1. AWSとTerraform初⼼者が やってみたこと 板垣 正敏@JAWS-UG Niigata 2019/12/21

  2. ⾃⼰紹介 • 板垣 正敏 • 県内IT企業の技術顧問(2020/3まで) • 中⼩企業診断⼠ • ⽇本Rubyの会

    • 新潟オープンソース協会 • Python機械学習勉強会 in 新潟 • TensorFlow Users Group • @itagakim • https://github.com/masa-ita • AWS歴 2017年〜
  3. システムの全体像

  4. なんのためのシステムか? • 社内でのディープラーニング 実習のための環境 • GPUマシンをたくさん⽤意で きない • GPUインスタンスは使うとき だけ起動して、コストを抑え

    たい • IPアドレスを意識せずに使い たい • 当初はGUIコンソールとSSHで ⼿作業で構築 • Dynamic DNSとLet’s Encryptで 構成 • 現在はELBとCertificate Managerを使⽤
  5. AWS Lambda EC2起動・停⽌指⽰ Amazon API Gateway DDNS登録・削除 Amazon DynamoDB Amazon

    EC2 Amazon Route 53 Application Load Balancer Amazon CloudWatch Amazon Elastic Block Store Amazon Elastic File System EC2起動・停⽌完了通知 EC2稼働定期通知 AWS Identity and Access Management Generic group Event (time-based) Event (event-based) Event (event-based) AWS Certificate Manager VPC WebHook API call API call API call
  6. 本題:Terraformとは?

  7. Infrastructure AS Code • コードとしてのインフラ(構成) • 再現・再利⽤性 • 設定ミス・設定漏れの防⽌ •

    GUIによらないドキュメント化 • バージョン管理
  8. なぜTERRAFORM? • AWSならCloudFormationがあるが・・・ • Azure, GCP, オンプレ(Vmware, Nutanix, etc.):ワークフ ローの統⼀

    • https://www.terraform.io/docs/providers/index.html
  9. TERRAFORMのしくみ • terraform init • terraform validate • terraform plan

    • terraform apply .tf .tfstate .tfplan Target System terraform plan terraform apply
  10. TERRAFORMのインストール • プラットフォームごとにZIPファイルで提供 • シングルバイナリでパスが通っていればOK • MacOSならHomebrewでもインストール可能 • tfenvでバージョン管理も

  11. 構成例 Labmdaを⽤いたDynamic DNSの部分のみを紹介

  12. プロバイダ設定 • クレデンシャルは環境変数か awscliの設定ファイルに保存 すべき • バージョンアップでの⾮互換 を防ぐため、Terraformやプロ バイダのバージョン指定が有 効

    • 右の例では、.tfstateファイル をS3バケットに保存している (共同作業やリモート参照の ため) terraform { required_version = "0.12.17” backend "s3" { bucket = "tfstate-terraform-demo” key = "network/terraform.tfstate” region = "ap-northeast-1” } } provider "aws" { version = "~> 2.41” region = "ap-northeast-1” }
  13. variable "name" {} variable "policy" {} variable "identifier" {} resource

    "aws_iam_role" "default" { name = var.name assume_role_policy = data.aws_iam_policy_document.assume_role.json } data "aws_iam_policy_document" "assume_role" { statement { actions = ["sts:AssumeRole"] principals { type = "Service” identifiers = [var.identifier] } } } resource "aws_iam_policy" "default" { name = var.name policy = var.policy } resource "aws_iam_role_policy_attachment" "default" { role = aws_iam_role.default.name policy_arn = aws_iam_policy.default.arn } output "iam_role_arn" { value = aws_iam_role.default.arn } output "iam_role_name" { value = aws_iam_role.default.name } IAM設定⽤モジュール定義
  14. data "aws_iam_policy_document" "for_ddns_lambda" { statement { effect = "Allow” actions

    = ["ec2:Describe*"] resources = ["*"] } statement { effect = "Allow” actions = ["dynamodb:*"] resources = ["*"] } statement { effect = "Allow” actions = [ "logs:CreateLogGroup", "logs:CreateLogStream", "logs:PutLogEvents” ] resources = ["*"] } statement { effect = "Allow” actions = ["route53:*"] resources = ["*"] } } module "role_for_ddns_lambda" { source = "./iam_role” name = "role_for_ddns_lambda” identifier = "lambda.amazonaws.com” policy = data.aws_iam_policy_document.for_ddns_lambda.json } Lambda関数⽤IAM定義
  15. data "archive_file" "lambda_function" { type = "zip” source_dir = "lambda/function”

    output_path = "lambda/upload/lambda_function.zip” } resource "aws_lambda_function" "ddns_lambda" { filename = data.archive_file.lambda_function.output_path function_name = "ddns_lambda” role = module.role_for_ddns_lambda.iam_role_arn handler = "union.lambda_handler” source_code_hash = data.archive_file.lambda_function.output_base64sha256 runtime = "python2.7” memory_size = 128 timeout = 120 } resource "aws_lambda_permission" "allow_cloudwatch" { statement_id = "AllowExecutionFromCloudWatch” action = "lambda:InvokeFunction” function_name = aws_lambda_function.ddns_lambda.function_name principal = "events.amazonaws.com” source_arn = aws_cloudwatch_event_rule.ec2_lambda_ddns_rule.arn } Lambda関数定義
  16. resource "aws_vpc" "main" { cidr_block = "10.0.0.0/16” enable_dns_support = true

    enable_dns_hostnames = true tags = { Name = "main” } } resource "aws_subnet" "main" { vpc_id = aws_vpc.main.id cidr_block = "10.0.1.0/24” map_public_ip_on_launch = true availability_zone = "ap-northeast-1d” tags = { Name = "main” } } resource "aws_internet_gateway" "gw" { vpc_id = aws_vpc.main.id tags = { Name = "main” } } resource "aws_route_table" "public" { vpc_id = aws_vpc.main.id } resource "aws_route" "public" { route_table_id = aws_route_table.public.id gateway_id = aws_internet_gateway.gw.id destination_cidr_block = "0.0.0.0/0” } resource "aws_route_table_association" "public" { subnet_id = aws_subnet.main.id route_table_id = aws_route_table.public.id } resource "aws_vpc_dhcp_options" "aws_subdomain" { domain_name = "aws.rails.to” domain_name_servers = ["AmazonProvidedDNS"] tags = { Name = "aws_subdomain” } } output "vpc_id" { value = aws_vpc.main.id } output "main_subnet_id" { value = aws_subnet.main.id } VPC定義
  17. variable "name" {} variable "vpc_id" {} variable "port" {} variable

    "cidr_blocks" { type = list(string) } resource "aws_security_group" "default" { name = var.name vpc_id = var.vpc_id } resource "aws_security_group_rule" "ingress" { type = "ingress” from_port = var.port to_port = var.port protocol = "tcp” cidr_blocks = var.cidr_blocks security_group_id = aws_security_group.default.id } resource "aws_security_group_rule" "egress" { type = "egress” from_port = 0 to_port = 0 protocol = "-1” cidr_blocks = ["0.0.0.0/0"] security_group_id = aws_security_group.default.id } output "security_group_id" { value = aws_security_group.default.id } Security Group定義⽤モジュール
  18. module "web_server_sg" { source = "./security_group” name = "web-sg” vpc_id

    = data.terraform_remote_state.network.outputs.vpc_id port = 80 cidr_blocks = ["0.0.0.0/0"] } resource "aws_instance" "web" { ami = "ami-0c3fd0f5d33134a76” instance_type = "t3.nano” vpc_security_group_ids = [module.web_server_sg.security_group_id] subnet_id = data.terraform_remote_state.network.outputs.main_subnet_id user_data = <<EOF #!/bin/bash yum install -y httpd systemctl start httpd.service EOF tags = { ZONE = "aws.rails.to.” CNAME = "web.aws.rails.to.” } } Security Group と EC2 インスタンスの定義
  19. まとめ

  20. Terraform は強⼒なツール • 何よりも構成の再現性がありがたい • GUIが時々変わるクラウドには必須のツールか • プロビジョニングの機能はそれほど便利ではない(ファイル コピーとコマンド実⾏) •

    モジュールの使い⽅(使いどころ)がよくわかってません • 最適なリソース分割やディレクトリ配置がまだわかってませ ん
  21. 参考図書 • 「実践Terraform」野村友規著 • オンデマンド / Kindle • https://www.amazon.co.jp/dp/4844378139

  22. 参照サイト • Terraform Documentation • https://www.terraform.io/docs/index.html • Lamdaを⽤いたDynamic DNSの参考事例 •

    https://aws.amazon.com/jp/blogs/compute/building-a-dynamic-dns-for- route-53-using-cloudwatch-events-and-lambda/ • https://github.com/aws-samples/aws-lambda-ddns-function
  23. おまけ: Python機械学習勉強会 in 新潟 Restart #10 やり ます • 2020年1⽉11⽇(⼟)

    • 新潟市中央公⺠館(クロスパル) • 「(仮)ディープラーニングで芸術はできるか?〜⽣成系ネッ トワークの進展〜」(itagakim) • 「機械学習による動作認識」(Oh!No!さん) • 「産学連携セミナー報告とインフラWG設⽴の提案」 (haru_fujitaさん) • 「Deep Learningを⽤いた残存⻭の⾃動認識」(historoidさん)