Slide 1

Slide 1 text

EASY DEVELOPMENT AND DEPLOYMENT Industry quality, self-service workflows with Otto

Slide 2

Slide 2 text

SETH VARGO @sethvargo

Slide 3

Slide 3 text

No content

Slide 4

Slide 4 text

VERSUS

Slide 5

Slide 5 text

Otto and the HashiCorp Ecosystem

Slide 6

Slide 6 text

No content

Slide 7

Slide 7 text

No content

Slide 8

Slide 8 text

Why Otto?

Slide 9

Slide 9 text

Automate Development Environments

Slide 10

Slide 10 text

$ otto dev ===> otto: detected app: ruby

Slide 11

Slide 11 text

$ otto dev ===> otto: detected app: python

Slide 12

Slide 12 text

Focus on Application Development

Slide 13

Slide 13 text

$ otto dev ssh vagrant@precise64:/vagrant$

Slide 14

Slide 14 text

Codify Deployments

Slide 15

Slide 15 text

No content

Slide 16

Slide 16 text

No content

Slide 17

Slide 17 text

Today's Best Practices WEB DB MICRO SERVICES PRIVATE SUBNET  PUBLIC SUBNET  INTERNAL NETWORK LB BASTION NAT

Slide 18

Slide 18 text

WEB DB MICRO SERVICES PRIVATE SUBNET  PUBLIC SUBNET  INTERNAL NETWORK LB BASTION NAT Today's Best Practices COMPLEXITY

Slide 19

Slide 19 text

No content

Slide 20

Slide 20 text

Simplify Microservices

Slide 21

Slide 21 text

Microservices Monolithic Microservices

Slide 22

Slide 22 text

Microservices

Slide 23

Slide 23 text

Microservices

Slide 24

Slide 24 text

application { name = "my-store" type = "ruby" dependency { source = "github.com/hashicorp/otto/examples/postgresql" } } customization "ruby" { ruby_version = "2.1" } Appfile

Slide 25

Slide 25 text

Doin' it Live1  1. Unless it breaks

Slide 26

Slide 26 text

BOOTSTRAP APP 1

Slide 27

Slide 27 text

$ vi Gemfile

Slide 28

Slide 28 text

source "https://rubygems.org" gem "pg", "~> 0.18" gem "shotgun", "~> 0.9" gem "sinatra", "~> 1.4" gem "sinatra-activerecord", "~> 2.0" Gemfile

Slide 29

Slide 29 text

CONFIGURE DEV 2

Slide 30

Slide 30 text

$ otto compile

Slide 31

Slide 31 text

$ otto compile ==> Loading Appfile... ==> No Appfile found! Detecting project information... No Appfile was found. If there is no Appfile, Otto will do its best to detect the type of application this is and set reasonable defaults. This is a good way to get started with Otto, but over time we recommend writing a real Appfile since this will allow more complex customizations, the ability to reference dependencies, versioning, and more. ==> Fetching all Appfile dependencies... Fetching dependency: git::github.com/hashicorp/otto.git//examples/postgresql ==> Compiling dependency 'postgresql'... ==> Compiling main application... ==> Detecting Ruby version to use... No desired Ruby version found! Will use the default: 2.2 ==> Compilation success!

Slide 32

Slide 32 text

$ otto compile ==> Loading Appfile... ==> No Appfile found! Detecting project information... No Appfile was found. If there is no Appfile, Otto will do its best to detect the type of application this is and set reasonable defaults. This is a good way to get started with Otto, but over time we recommend writing a real Appfile since this will allow more complex customizations, the ability to reference dependencies, versioning, and more. ==> Fetching all Appfile dependencies... Fetching dependency: git::github.com/hashicorp/otto.git//examples/postgresql ==> Compiling dependency 'postgresql'... ==> Compiling main application... ==> Detecting Ruby version to use... No desired Ruby version found! Will use the default: 2.2 ==> Compilation success!

Slide 33

Slide 33 text

$ otto dev ==> Creating development environment layers... Otto uses layers to speed up building development environments. Each layer only needs to be built once. We've detected that the layers below aren't created yet. These will be built this time. Future development environments will use the cached versions to be much, much faster.

Slide 34

Slide 34 text

$ otto dev ==> Creating layer: consul Bringing machine 'default' up with 'virtualbox' provider... ...

Slide 35

Slide 35 text

$ otto dev ==> Creating layer: ruby2.2 Bringing machine 'default' up with 'virtualbox' provider... ... ==> default: [otto] Installing supporting packages... ==> default: [otto] Installing Ruby 2.2. This can take a few minutes... ==> default: [otto] Installing Bundler...

Slide 36

Slide 36 text

$ otto dev ==> Creating local development environment with Vagrant ... ==> default: [otto] Bundling gem dependencies... ==> default: Fetching version metadata from https://rubygems.org/... ==> default: Resolving dependencies... ==> default: Installing rack 1.6.4 ==> default: Installing tilt 2.0.2 ==> default: Using bundler 1.11.2 ==> default: Installing rack-protection 1.5.3 ==> default: Installing shotgun 0.9.1 ==> default: Installing sinatra 1.4.7 ==> default: Bundle complete! 5 Gemfile dependencies, 24 gems now installed. ==> default: Use `bundle show [gemname]` to see where a bundled gem is installed.

Slide 37

Slide 37 text

$ otto dev ==> Development environment successfully created! IP address: 100.117.7.132 A development environment has been created for writing a generic Ruby-based app. Ruby is pre-installed. To work on your project, edit files locally on your own machine. The file changes will be synced to the development environment. When you're ready to build your project, run 'otto dev ssh' to enter the development environment. You'll be placed directly into the working directory where you can run 'bundle' and 'ruby' as you normally would. You can access any running web application using the IP above.

Slide 38

Slide 38 text

$ otto dev ==> Verifying created layer: consul ==> Verifying created layer: ruby2.2 ...

Slide 39

Slide 39 text

DEVELOP LOCALLY 3

Slide 40

Slide 40 text

$ vi app.rb

Slide 41

Slide 41 text

require "bundler" Bundler.require get "/" do "The app is running!" end app.rb

Slide 42

Slide 42 text

$ vi config.ru

Slide 43

Slide 43 text

require "./app" run Sinatra::Application config.ru

Slide 44

Slide 44 text

$ otto dev ssh ==> Executing SSH. This may take a few seconds... Welcome to Ubuntu 12.04 LTS (GNU/Linux 3.2.0-23-generic x86_64)

Slide 45

Slide 45 text

vagrant@precise64:/vagrant$ shotgun --host 0.0.0.0 config.ru == Shotgun/WEBrick on http://0.0.0.0:9393/ [2020-01-01 20:49:36] INFO WEBrick 1.3.1 [2020-01-01 20:49:36] INFO ruby 2.2.4 (2015-12-16) [x86_64-linux] [2020-01-01 20:49:36] INFO WEBrick::HTTPServer#start: pid=2183 port=9393

Slide 46

Slide 46 text

$ curl http://100.117.7.132:9393/ The app is running!

Slide 47

Slide 47 text

$ curl http://$(otto dev address):9393/ The app is running!

Slide 48

Slide 48 text

$ curl -I http://$(otto dev address):9393/ HTTP/1.1 200 OK Content-Type: text/html;charset=utf-8 Content-Length: 19 X-Xss-Protection: 1; mode=block X-Content-Type-Options: nosniff X-Frame-Options: SAMEORIGIN Server: WEBrick/1.3.1 (Ruby/2.2.4/2015-12-16) Date: Mon, 01 Jan 2020 20:50:35 GMT Connection: Keep-Alive

Slide 49

Slide 49 text

$ psql ...?

Slide 50

Slide 50 text

$ otto dev ssh vagrant@precise64:/vagrant$ nslookup postgresql.service.consul Server: 127.0.0.1 Address: 127.0.0.1#53 Name: postgresql.service.consul Address: 10.0.2.15

Slide 51

Slide 51 text

vagrant@precise64:/vagrant$ ./scripts/createdb.sh

Slide 52

Slide 52 text

$ vi app.rb

Slide 53

Slide 53 text

require "bundler" Bundler.require configure do ActiveRecord::Base.establish_connection( adapter: "postgresql", host: "postgresql.service.consul", username: "postgres", database: "demo", encoding: "utf8", ) end class Post < ActiveRecord::Base; end app.rb

Slide 54

Slide 54 text

$ vi app.rb # ... get "/posts", provides: :json do Post.all.to_json end post "/posts", provides: :json do if post = Post.create(params) post.to_json else status 422 post.errors.to_json end end

Slide 55

Slide 55 text

vagrant@precise64:/vagrant$ rake db:migrate == 20160406140708 CreatePosts: migrating ====================================== -- create_table(:posts) -> 0.0782s == 20160406140708 CreatePosts: migrated (0.0788s) =============================

Slide 56

Slide 56 text

$ curl http://$(otto dev address):9393/posts []

Slide 57

Slide 57 text

$ curl -XPOST http://$(otto dev address):9393/posts -F "title=hello" -F "body=world" { "id": 1, "title": "hello", "body": "world", "created_at": "2016-04-06T19:34:01.998Z", "updated_at": "2016-04-06T19:34:01.998Z" }

Slide 58

Slide 58 text

$ curl http://$(otto dev address):9393/posts [ { "id": 1, "title": "hello", "body": "world", "created_at": "2016-04-06T19:34:01.998Z", "updated_at": "2016-04-06T19:34:01.998Z" }, ]

Slide 59

Slide 59 text

CONSTRUCT INFRA 4

Slide 60

Slide 60 text

$ otto infra ==> Detecting infrastructure credentials for: demo (aws) Existing infrastructure credentials were not found! Otto will now ask you for infrastructure credentials. These will be encrypted and saved on disk so this doesn't need to be repeated. IMPORTANT: If you're re-entering new credentials, make sure the credentials are for the same account, otherwise you may lose access to your existing infrastructure Otto set up.

Slide 61

Slide 61 text

$ otto infra AWS Access Key AWS access key used for API calls. Enter a value: ... AWS Secret Key AWS secret key used for API calls. Enter a value: ... SSH Public Key Path Path to an SSH public key that will be granted access to EC2 instances Default: ~/.ssh/id_rsa.pub Enter a value: ... Password for Encrypting Credentials This password will be used to encrypt and save the credentials so they don't need to be repeated multiple times. Enter a value: ...

Slide 62

Slide 62 text

$ otto infra ==> Building main infrastructure... ==> Executing Terraform to manage infrastructure... Raw Terraform output will begin streaming in below. Otto does not create this output. It is mirrored directly from Terraform while the infrastructure is being created. Terraform may ask for input. For infrastructure provider credentials, be sure to enter the same credentials consistently within the same Otto environment.

Slide 63

Slide 63 text

$ otto infra ... Apply complete! Resources: 6 added, 0 changed, 0 destroyed. Outputs: infra_id = efa4b38b key_name = otto-efa4b38b region = us-east-1 subnet_public = subnet-5435b57e vpc_cidr = 10.0.0.0/16 vpc_id = vpc-efa4b38b ==> Infrastructure successfully created! The infrastructure necessary to deploy this application is now available. You can now deploy using `otto deploy`.

Slide 64

Slide 64 text

$ otto status ==> App Info Application: demo (ruby) Project: demo Infrastructure: aws (simple) ==> Component Status Dev environment: CREATED Infra: READY Build: NOT BUILT Deploy: NOT DEPLOYED

Slide 65

Slide 65 text

BUILD APP 5

Slide 66

Slide 66 text

$ otto build ... ==> Building deployment archive... Error building app: error detecting VCS: no VCS found for path: /demo

Slide 67

Slide 67 text

$ git init && git add -A && git commit -m "Initial commit" Reinitialized existing Git repository in /demo/.git/ [master (root-commit) 5e57d71] Initial commit 63 files changed, 1744 insertions(+)

Slide 68

Slide 68 text

$ otto build ==> Building deployment archive... ==> Building deployment artifact with Packer... Raw Packer output will begin streaming in below. Otto does not create this output. It is mirrored directly from Packer while the build is being run. ==> otto: Prevalidating AMI Name... ==> otto: Inspecting the source AMI... ==> otto: Creating temporary keypair: packer 5702de4a-4f50-a189-6afd-25b0cd447ae2 ==> otto: Creating temporary security group for this instance... ==> otto: Authorizing access to port 22 the temporary security group... ==> otto: Launching a source AWS instance... otto: Instance ID: i-d3796849 ==> otto: Waiting for instance (i-d3796849) to become ready...

Slide 69

Slide 69 text

$ otto build ... ==> Builds finished. The artifacts of successful builds are: --> otto: AMIs were created: us-east-1: ami-64f1e50e ==> Storing build data in directory... ==> Build success! The build was completed successfully and stored within the directory service, meaning other members of your team don't need to rebuild this same version and can deploy it immediately.

Slide 70

Slide 70 text

$ otto status ==> App Info Application: demo (ruby) Project: demo Infrastructure: aws (simple) ==> Component Status Dev environment: CREATED Infra: READY Build: BUILD READY Deploy: NOT DEPLOYED

Slide 71

Slide 71 text

DEPLOY APP 6

Slide 72

Slide 72 text

$ otto deploy ==> Detecting infrastructure credentials for: demo (aws) Cached and encrypted infrastructure credentials found. Otto will now ask you for the password to decrypt these credentials. ... Apply complete! Resources: 2 added, 0 changed, 0 destroyed. Outputs: url = http://ec2-54-164-91-52.compute-1.amazonaws.com/

Slide 73

Slide 73 text

$ export URL="http://ec2-54-164-91-52.compute-1.amazonaws.com" $ curl $URL The app is running! $ curl $URL/posts [] $ curl -XPOST $URL/posts -F "title=hello" -F "body=world" { "id": 1, "title": "hello", "body": "world", "created_at": "2016-04-06T19:34:01.998Z", "updated_at": "2016-04-06T19:34:01.998Z" }

Slide 74

Slide 74 text

DESTROY IT ALL 7

Slide 75

Slide 75 text

$ otto dev destroy ==> Destroying the local development environment... $ otto deploy destroy Do you really want to destroy? Otto will delete all resources associated with the deploy. There is no undo. Only 'yes' will be accepted to confirm. Enter a value: yes $ otto infra destroy Do you really want to destroy? Otto will delete all your managed infrastructure. There is no undo. Only 'yes' will be accepted to confirm. Enter a value: yes

Slide 76

Slide 76 text

COMPLEX REQS ?

Slide 77

Slide 77 text

$ vi Appfile

Slide 78

Slide 78 text

application { name = "demo" type = "ruby" dependency { source = "github.com/hashicorp/otto/examples/postgresql" } } customization "ruby" { ruby_version = "2.2" } Appfile

Slide 79

Slide 79 text

$ otto compile ==> Loading Appfile... ==> Fetching all Appfile dependencies... Fetching dependency: git::github.com/hashicorp/otto.git/examples/postgresql ==> Compiling... Application: demo (ruby) Project: demo Infrastructure: aws (simple) Compiling infra... Compiling foundation: consul ==> Compiling dependency 'postgresql'... ==> Compiling main application... ==> Compilation success!

Slide 80

Slide 80 text

No content

Slide 81

Slide 81 text

SETH VARGO @sethvargo QUESTIONS?