35
CloudFormation でででででででで

Cloud Formationで既存のインフラを増築した話

Embed Size (px)

Citation preview

Page 1: Cloud Formationで既存のインフラを増築した話

CloudFormation でインフラを増築

Page 2: Cloud Formationで既存のインフラを増築した話

自己紹介名前:五島僚太郎勤務先:株式会社ベーシック開発部

Qiita とブログをときどき書いています・ http://qiita.com/g_ryotaro

・緊張すると涙がでる人のブログ〜 1 リットルの目汗〜@510_five

Page 3: Cloud Formationで既存のインフラを増築した話

CloudFormation って ?

Page 4: Cloud Formationで既存のインフラを増築した話
Page 5: Cloud Formationで既存のインフラを増築した話

関連する AWS リソースの集約を整った予測可能な方法でプロビジョニングおよび更新し、開発者やシステム管理者が容易にそれらを作成・管理できるようになる AWS のサービス

Page 6: Cloud Formationで既存のインフラを増築した話

つまり

Page 7: Cloud Formationで既存のインフラを増築した話

JSON ファイル => ポチッ => インフラ

Page 8: Cloud Formationで既存のインフラを増築した話

“Resources” : {

“WebServer”: { “Type”: “AWS::EC2::Instance”, “Properties”: { “ImageId”: “ami-10101010”, とか…いろいろ書く } } }

Page 9: Cloud Formationで既存のインフラを増築した話

インフラを JSON ファイルで管理できる

Page 10: Cloud Formationで既存のインフラを増築した話

こんな感じ

Page 11: Cloud Formationで既存のインフラを増築した話

"Resources" : {

"WebServer": { "Type": "AWS::EC2::Instance", "Metadata" : { "AWS::CloudFormation::Init" : { "configSets" : { "full_install" : [ "install_cfn", "install_mysql", "configure_mysql", "install_ruby", "install_application" ] },

"install_cfn" : { "files" : { "/etc/cfn/cfn-hup.conf" : { "content" : { "Fn::Join" : ["", [ "[main]\n", "stack=", { "Ref" : "AWS::StackId" }, "\n", "region=", { "Ref" : "AWS::Region" }, "\n" ]]}, "mode" : "000400", "owner" : "root", "group" : "root" },

"/etc/cfn/hooks.d/cfn-auto-reloader.conf" : { "content": { "Fn::Join" : ["", [ "[cfn-auto-reloader-hook]\n", "triggers=post.update\n", "path=Resources.WebServer.Metadata.AWS::CloudFormation::Init\n", "action=/opt/aws/bin/cfn-init -v ", " --stack ", { "Ref" : "AWS::StackName" }, " --resource WebServer ", " --configsets full_install ", " --region ", { "Ref" : "AWS::Region" }, "\n", "runas=root\n" ]]} } },

"services" : { "sysvinit" : { "cfn-hup" : { "enabled" : "true", "ensureRunning" : "true", "files" : ["/etc/cfn/cfn-hup.conf", "/etc/cfn/hooks.d/cfn-auto-reloader.conf"]} } } },

"install_mysql" : { "packages" : { "yum" : { "mysql" : [], "mysql-server" : [], "mysql-devel" : [], "mysql-libs" : [] } },

"files" : { "/tmp/setup.mysql" : { "content" : { "Fn::Join" : ["", [ "CREATE USER '", { "Ref" : "DBUser" }, "'@'localhost' IDENTIFIED BY '", { "Ref" : "DBPassword" }, "';\n", "GRANT ALL ON ", { "Ref" : "DBName" }, ".* TO '", { "Ref" : "DBUser" }, "'@'localhost';\n", "FLUSH PRIVILEGES;\n" ]]}, "mode" : "000400", "owner" : "root", "group" : "root" } },

"services" : { "sysvinit" : { "mysqld" : { "enabled" : "true", "ensureRunning" : "true" } } } },

"configure_mysql" : { "commands" : { "01_set_mysql_root_password" : { "command" : { "Fn::Join" : ["", ["mysqladmin -u root password '", { "Ref" : "DBRootPassword" }, "'"]]}, "test" : { "Fn::Join" : ["", ["$(mysql ", { "Ref" : "DBName" }, " -u root --password='", { "Ref" : "DBRootPassword" }, "' >/dev/null 2>&1 </dev/null); (( $? != 0 ))"]]} }, "02_create_database" : { "command" : { "Fn::Join" : ["", ["mysql -u root --password='", { "Ref" : "DBRootPassword" }, "' < /tmp/setup.mysql"]]}, "test" : { "Fn::Join" : ["", ["$(mysql ", { "Ref" : "DBName" }, " -u root --password='", { "Ref" : "DBRootPassword" }, "' >/dev/null 2>&1 </dev/null); (( $? != 0 ))"]]} }, "03_cleanup" : { "command" : "rm /tmp/setup.mysql" } } },

"install_ruby" : { "packages" : { "yum" : { "gcc-c++" : [], "make" : [], "ruby-devel" : [], "rubygems" : [], "rubygem-io-console" : [], "patch" : [] } }, "commands" : { "01_update_gems" : { "command" : "gem update --system" }, "02_reload_nokogiri" : { "command" : "gem install --no-ri --no-rdoc nokogiri" } } },

"install_application" : { "packages" : { "rubygems" : { "rails" : [] } }, "files" : { "/tmp/database.yml" : { "content" : { "Fn::Join" : ["", [ "development:\n", " adapter: mysql2\n", " encoding: utf8\n", " reconnect: false\n", " pool: 5\n", " database: ", { "Ref" : "DBName" }, "\n", " username: ", { "Ref" : "DBUser" }, "\n", " password: ", { "Ref" : "DBPassword" }, "\n", " socket: /var/lib/mysql/mysql.sock\n" ]]}, "mode" : "000400", "owner" : "root", "group" : "root" }, "/tmp/install_application" : { "content" : { "Fn::Join" : ["", [ "#!/bin/bash -e\n", "export HOME=/home/ec2-user\n", "export PATH=$PATH:/usr/local/bin\n", "cd /home/ec2-user\n",

"# Kill the rails server if it is running to allow update\n", "if pgrep ruby &> /dev/null ; then pkill -TERM ruby ; fi\n",

"# This sample template creates a new application inline\n", "# Typically you would use files and/or sources to download\n", "# your application package and perform any configuration here.\n",

"# Create a new application, with therubyracer javascript library\n", "rails new sample -d mysql --skip-spring --skip-bundle --force\n", "cd /home/ec2-user/sample\n", "sed -i 's/^# \\(.*therubyracer.*$\\)/\\1/' Gemfile\n", "bundle install\n",

"# Create a sample scoffold\n", "rails generate scaffold Note title:string body:text --force\n",

"# Configure the database connection\n", "mv /tmp/database.yml config\n", "rake db:create db:migrate\n" ]]}, "mode" : "000500", "owner" : "root", "group" : "root" }, "/home/ec2-user/start-application" : { "content" : { "Fn::Join" : ["", [ "#!/bin/bash -e\n", "export HOME=/home/ec2-user\n", "export PATH=$PATH:/usr/local/bin\n", "cd /home/ec2-user/sample\n",

"# Startup the application\n", "rails server --binding 0.0.0.0 -p 80 -d\n" ]]}, "mode" : "000500", "owner" : "root", "group" : "root" } }, "commands" : { "01_install_application" : { "command" : "/tmp/install_application > /var/log/install_application.log" }, "02_configure_reboot" : { "command" : "echo /home/ec2-user/start-application >> /etc/rc.local" }, "03_start_application" : { "command" : "/home/ec2-user/start-application" }, "04_cleanup" : { "command" : "rm /tmp/install_application" } } } } }, "Properties": { "ImageId" : { "Fn::FindInMap" : [ "AWSRegionArch2AMI", { "Ref" : "AWS::Region" }, { "Fn::FindInMap" : [ "AWSInstanceType2Arch", { "Ref" : "InstanceType" }, "Arch" ] } ] }, "InstanceType" : { "Ref" : "InstanceType" }, "SecurityGroups" : [ {"Ref" : "WebServerSecurityGroup"} ], "KeyName" : { "Ref" : "KeyName" }, "UserData" : { "Fn::Base64" : { "Fn::Join" : ["", [ "#!/bin/bash -xe\n", "yum update -y aws-cfn-bootstrap\n",

"/opt/aws/bin/cfn-init -v ", " --stack ", { "Ref" : "AWS::StackId" }, " --resource WebServer ", " --configsets full_install ", " --region ", { "Ref" : "AWS::Region" }, "\n",

"/opt/aws/bin/cfn-signal -e $? ", " --stack ", { "Ref" : "AWS::StackId" }, " --resource WebServer ", " --region ", { "Ref" : "AWS::Region" }, "\n" ]]}} }, "CreationPolicy" : { "ResourceSignal" : { "Timeout" : "PT30M" } } }, "WebServerSecurityGroup" : { "Type" : "AWS::EC2::SecurityGroup", "Properties" : { "GroupDescription" : "Enable HTTP and SSH access", "SecurityGroupIngress" : [ {"IpProtocol" : "tcp", "FromPort" : "80", "ToPort" : "80", "CidrIp" : "0.0.0.0/0"}, {"IpProtocol" : "tcp", "FromPort" : "22", "ToPort" : "22", "CidrIp" : { "Ref" : "SSHLocation"}} ] } } },

Page 12: Cloud Formationで既存のインフラを増築した話

( ゚ д ゚ ) ポカーン

Page 13: Cloud Formationで既存のインフラを増築した話

か .. かけない ..

Page 14: Cloud Formationで既存のインフラを増築した話

すでに出来上がっている環境を増やす

Page 15: Cloud Formationで既存のインフラを増築した話

( ゚ д ゚ ) ポカーン

Page 16: Cloud Formationで既存のインフラを増築した話

さらに .. かけない ..

Page 17: Cloud Formationで既存のインフラを増築した話

 (∩ ` ・ д ・)  / ミつ /  ̄ ̄ ̄ /  ̄ ̄\ / ___ /

Page 18: Cloud Formationで既存のインフラを増築した話

\  __   /_ (m) _  ピコーン   | ミ |/ ` ´   \  ( ゚∀゚ ) ノヽノ |   <   <

Page 19: Cloud Formationで既存のインフラを増築した話

CloudFormer

Page 20: Cloud Formationで既存のインフラを増築した話

アカウントに既に存在する AWS リソースから AWS CloudFormation テンプレートを作成するテンプレート作成ツール

Page 21: Cloud Formationで既存のインフラを増築した話

これで本番環境と全く同じテスト環境がバンバン建てられる !!!!!!!!!!!!!!!!!!!!!!

Page 22: Cloud Formationで既存のインフラを増築した話

_人人人人_> 最強 < ̄ Y^Y^Y ̄    ∧∧キタ━━ ( ゚∀゚ )━━!!!  /   \ィ⌒ヽ i ii i⌒ ⌒ ィ⌒ヽ

( _ (( \ニニニニ/ )) _ ) _〜 l|(Θ)|l 〜_(  _ll ll_⌒   ) \ I|i i|I ⌒ / ⊂ニ∪ l   l∪ ニつ    i__j   ヴオン

Page 23: Cloud Formationで既存のインフラを増築した話

                  n                   l^l.| | / )                   | U レ '/ / )      ___      ノ    /    / ⌒  ⌒\  rニ      |    ありがとうだお〜   / (⌒)  (⌒) \  ヽ    / /   /// ( __ 人 __ ) /// \ / `   /  |        `Y y'´⌒     |   / \ .       ゙ー ′   , /  /   /⌒ ヽ   ー‐   ィ  /  / r ー ' ゝ        /  /, ノヾ  ,>          イ  |  ヽ〆          |

Page 24: Cloud Formationで既存のインフラを増築した話

しかし…そうはうまくいきません

Page 25: Cloud Formationで既存のインフラを増築した話

存在しないスナップショットや AMI を参照

Page 26: Cloud Formationで既存のインフラを増築した話

PrivateIP の指定がそのまま

Page 27: Cloud Formationで既存のインフラを増築した話

IAM などもそのまま参照

Page 28: Cloud Formationで既存のインフラを増築した話

ELB やサーバーの名前もそのまま

Page 29: Cloud Formationで既存のインフラを増築した話

CloudFormer で作った環境は完全にコピー

Page 30: Cloud Formationで既存のインフラを増築した話

作ったテンプレートを参考にカスタマイズ

Page 31: Cloud Formationで既存のインフラを増築した話

まとめ・ CloudFormation を使ってインフラを増築  - 既存のインフラのテンプレート作成   # CloudFormer   # 完全にコピーするためのテンプレート (IP 、 IAM 、 SG)    % あくまで参考に書き換えをする  - 新規のインフラのテンプレート作成   # ドラッグ & ドロップでできる DesignViewer

Page 32: Cloud Formationで既存のインフラを増築した話

新規のインフラだったら

Page 33: Cloud Formationで既存のインフラを増築した話
Page 34: Cloud Formationで既存のインフラを増築した話

便利 !!

Page 35: Cloud Formationで既存のインフラを増築した話

ご清聴ありがとうございました