<!doctype html> <html lang="en"> <head> <meta charset="utf-8"> <title>OpenStack works ... so now what?</title> <meta name="apple-mobile-web-app-capable" content="yes" /> <meta name="apple-mobile-web-app-status-bar-style" content="black-translucent" /> <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no"> <link rel="stylesheet" href="/css/reveal.css"> <link rel="stylesheet" href="/css/theme/openstack.css" id="theme"> <!-- For syntax highlighting --> <link rel="stylesheet" href="/lib/css/zenburn.css"> <!-- If the query includes 'print-pdf', include the PDF print sheet --> <script> if( window.location.search.match( /print-pdf/gi ) ) { var link = document.createElement( 'link' ); link.rel = 'stylesheet'; link.type = 'text/css'; link.href = '/css/print/pdf.css'; document.getElementsByTagName( 'head' )[0].appendChild( link ); } </script> </head> <body> <div class="reveal"><div class="slides"> <section data-state="cover"> <h1><span xmlns:dct="http://purl.org/dc/terms/" href="http://purl.org/dc/dcmitype/InteractiveResource" property="dct:title" rel="dct:type"> OpenStack works ... so now what? </span></h1> <h3 xmlns:cc="http://creativecommons.org/ns#" property="cc:attributionName">Monty Taylor</h3> <h4><a xmlns:cc="http://creativecommons.org/ns#" rel="cc:attributionURL" href='http://inaugust.com/talks/now-what.html'>http://inaugust.com/talks/now-what.html</a> </h4> <h3> twitter: @e_monty </h3> </section> <section id="who-am-i-hp" class="slide level2"> <h1>Who am I?</h1> <img style="float:right; margin-right:24pt" src="/images/hp-logo.png"/> <p> Distinguished Technologist </p> <p> HP Cloud </p> </section> <section id="who-am-i-openstack" class="slide level2"> <h1>Who am I?</h1> <img style="float:right; margin-right:24pt" src="/images/openstack-cloud-software-vertical-large.png" /> <p>Technical Committee</p> <p>Foundation Board of Directors</p> <p>Developer Infrastructure Core Team</p> </section> <section id="what-are-we-going-to-talk-about" class="slide level2"> <h1>What are we going to talk about?</h1> <ul> <li>OpenStack</li> <li>My application</li> <li>Your applications</li> </ul> </section> <section class="slide level2"> <img src="/images/openstack-software-diagram.png" alt="OpenStack" /> </section> <section class="slide level2"> <p>As an application developer,<br /> I want to deploy and run an application on the internet<br /> so that my customers all over the world can consume it.</p> </section> <section class="slide level2"> <p>As an application developer,<br /> I want to deploy the application across multiple clouds<br /> so that my service survives issues in any one of them.</p> </section> <section class="slide level2"> <h1>THIS WORKS</h1> <h3>I'm doing it myself as we speak</h3> <img style="float:right; margin-right:24pt" src="/images/graphite.openstack.org.png"/> <p class='fragment'>10-20k VMs per-day</p> <p class='fragment'>3 (soon to be 6) clouds</p> <p class='fragment'>Only using OpenStack APIs</p> </section> <section id="openstack-infra" data-transition='zoom'> <h1>OpenStack Infra</h1> </section> <section id="tooling-automation-and-ci-for-openstack-project" class="slide level2" data-transition='zoom'> <h1>Tooling, Automation and CI for OpenStack Project</h1> </section> <section id="developers" class="slide level2" data-transition='zoom'> <h1>2000 Developers</h1> </section> <section id="gated-commits" class="slide level2" data-transition='zoom'> <h1>Gated Commits</h1> <p>Every commit is fully integration tested (twice) before landing</p> </section> <section id="each-test-runs-on-a-single-use-cloud-slave" class="slide level2" data-transition='zoom'> <h1>Each Test Runs on a Single Use Cloud Slave</h1> <p>This is that "cloud scale out" part</p> </section> <section id="million-test-jobs-in-the-last-6-months" class="slide level2" data-transition='zoom'> <h1>1.7 Million Test Jobs in the last 6 Months</h1> </section> <section id="million-tests-in-a-month" class="slide level2" data-transition='zoom'> <h1>15 Million Tests in a month</h1> </section> <section id="terabytes-of-log-data-in-six-months" class="slide level2" data-transition='zoom'> <h1>18 Terabytes of Log Data in six months</h1> </section> <section id="we-have-no-servers" class="slide level2" data-transition='zoom'> <h1>We have no servers</h1> <p>It all runs across HP and Rackspace Public Clouds.</p> </section> <section id="architecture" class="slide level2"> <h1>Architecture</h1> <p><img src="/images/infra_architecture.jpg" alt="image" /></p> </section> <section class="slide level2"> <h1>Gerrit</h1> <ul> <li class="fragment"> Traditional 'Enterprise' Java Application</li> <li class="fragment">Single Nova VM, Cinder Volume</li> <li class="fragment">Scale out farm of git replicas</li> </ul> </section> <section class="slide level2"> <img src="/images/gerrit-graph.png" /> </section> <section class="slide level2"> <h1>Fun Numbers</h1> <ul> <li>2500 changes every week</li> <li>15000 change <em>revisions</em> every week</li> <li>10,000 new changes every 42 days</li> </ul> </section> <section class="slide level2"> <img src="/images/what-happens.png" /> </section> <section class="slide level2"> <h1>nodepool</h1> <ul> <li class="fragment">Cloud Native</li> <li class="fragment"> Purpose built in Python</li> <li class="fragment">Keeps a pool of ready to go nodes</li> <li class="fragment">Multi-cloud</li> <li class="fragment">Fully elastic - responds to demand</li> </ul> </section> <section class="slide level2"> <img style="float:left; margin-left:24pt; width:35%;" src="/images/gerrit-graph.png" /> <img style="float:right; margin-right:24pt; width: 50%;" src="/images/nodepool-graph.png" /> </section> <section class="slide level2"> <h1>OpenStack Works!</h1> <p class='fragment'>What next?</p> <p class='fragment'>Make it easier</p> </section> <section class="slide level2"> <h1>Basic things you want to do</h1> <p class='fragment'>Get (make/fetch/find) a base image</p> <p class='fragment'>Upload it to each cloud</p> <p class='fragment'>Boot a VM on one or more of the clouds</p> <p class='fragment'>Ensure it's on the Internet</p> </section> <section class="slide level2"> <h1>We've made this harder than it should be</h1> </section> <section class="slide level2"> <h1>Get a base image</h1> <p class='fragment'>OpenStack diskimage-builder</p> <p class='fragment'>packer</p> <p class='fragment'>Download pre-built image from Ubuntu/RedHat/SuSE</p> </section> <section class="slide level2"> <h1>Problem: hypervisor image file format</h1> <ul> <li class='fragment'> Rackspace uses VHD </li> <li class='fragment'> HP uses qcow2 </li> <li class='fragment'> DreamHost uses RAW </li> </ul> </section> <section class="slide level2"> <h1>Problem: image API version</h1> <ul> <li class='fragment'> HP uses v1 </li> <li class='fragment'> vexxhost uses v2 </li> </ul> <p class="fragment">Good news! We made a plan for this at the summit</p> </section> <section class="slide level2"> <h1>Problem: image task vs. PUT</h1> <pre> swift upload --object-name local-image-filename images image-name glance task-create --type=import --input='{"import_from": "images/image-name", "image_properties" : {"name": "My Image Name"}}' </pre> <pre> glance image-create --name=image-name --file=local-image-filename </pre> </section> <section class="slide level2"> <h1>Problem: Ensure it's on the Internet</h1> <ul> <li class='fragment'>Cloud has externally routable IP from neutron (RunAbove, OVH)</li> <li class='fragment'>Cloud has externally routable IP neutron AND supports optional private tenant networks (vexxhost)</li> <li class='fragment'>Cloud has private tenant network provided by neutron and requires floating IP (HP, Dreamhost)</li> <li class='fragment'>Cloud only has private tenant network provided by nova-network and requires floating-ip for external routing (auro)</li> <li class='fragment'>Cloud has externally routable IP from neutron but no neutron APIs (Rackspace)</li> </ul> </section> <section class="slide level2"> <h1>Maybe in code ...</h1> <pre> def get_server_external_ipv4(cloud, server): if cloud.has_service('network'): try: server_ports = cloud.search_ports( filters={'device_id': server.id}) ext_nets = cloud.search_networks(filters={'router:external': True}) except NeutronClientException as e: pass # fall through else: for net in ext_nets: for port in server_ports: if net['id'] == port['network_id']: for ip in port['fixed_ips']: if _utils.is_ipv4(ip['ip_address']): return ip['ip_address'] ext_ip = get_server_ip(server, key_name='public') if ext_ip is not None: return ext_ip for interfaces in server.addresses.values(): for interface in interfaces: if _utils.is_ipv4(interface['addr']) and \ _utils.is_globally_routable_ipv4(interface['addr']): return interface['addr'] return None </pre> </section> <section class="slide level2"> <h1>I think we can do better than that</h1> </section> <section class="slide level2"> <h1>What am I doing about it?</h1> </section> <section class="slide level2"> <h1>os-client-config</h1> <h3>http://git.openstack.org/cgit/openstack/os-client-config</h3> <p>A library to handle config information for openstack clients</p> <p>Tracks differences in vendors that can't be discovered</p> <p>In use in python-openstackclient and ansible</p> </section> <section class="slide level2"> <h1>os-client-config</h1> <p>~/.config/openstack/clouds.yaml</p> <pre> clouds: hp-mordred: profile: hp auth: username: mordred@inaugust.com password: XXXXXXXXXXXXX project_name: mordred@inaugust.com region_name: region-b.geo-1 dreamhost: profile: dreamhost auth: username: montay6 project_name: dhc2111978 password: XXXXXXXXXXXXX region_name: RegionOne </pre> </section> <section class="slide level2"> <h1>shade</h1> <h3>http://git.openstack.org/cgit/openstack-infra/shade</h3> <p>A library to wrap business logic around client libraries</p> <pre> cloud.create_image('image-name', filename='image-filename.qcow2') cloud.create_server('my-server', image='immage-name', auto_ip=True) </pre> <p>In use in Infra Nodepool and ansible</p> </section> <section class="slide level2"> <h1>ansible</h1> <p>Brand new modules, based on shade</p> <p>Coming in 2.0 release</p> <pre> - os_keypair: cloud: hp-mordred name: mordred public_key_file: ~/.ssh/id_rsa.pub - os_image: cloud: hp-mordred name: Monty Ubuntu file: ubuntu.vhd - os_server: cloud: hp-mordred name: my-server flavor_ram: 1024 image: Monty Ubuntu </pre> </section> <section class="slide level2"> <h1>ansible</h1> <p>multi-cloud support</p> <pre> - os_keypair: cloud: "{{ item }" name: mordred public_key_file: ~/.ssh/id_rsa.pub with-items: - vexxhost - rackspace - mordred-hp - ovh </pre> </section> <section class="slide level2"> <h1>What should we do about it?</h1> <ul> <li> Get back to basics </li><li> shade existence is a bug </li><li> Make some decisions about divergences in the basic levels </li><li> Take a stand even if one of our product managers disagrees </li><li> Ensure that simple things are simple </li> </ul> </section> <section> <h1> Thank you! </h1> <h4> <a href='http://inaugust.com/talks/now-what.html'>http://inaugust.com/talks/now-what.html</a> </h4> <h3> twitter: @e_monty </h3> </section> </div> <div class="footer"> <a rel="license" href="http://creativecommons.org/licenses/by/4.0/"> <img alt="Creative Commons License" style="border-width:0" src="https://i.creativecommons.org/l/by/4.0/88x31.png" /> </a><br /> Licensed under a <a rel="license" href="http://creativecommons.org/licenses/by/4.0/"> Creative Commons Attribution 4.0 International License </a>. <br /> Source code available at <a href='http://git.inaugust.com/cgit/inaugust.com'>http://git.inaugust.com/cgit/inaugust.com</a> </div> </div> <script src="/lib/js/head.min.js"></script> <script src="/js/reveal.js"></script> <script src="/js/this.js"></script> </body> </html>