{"id":27307,"date":"2015-10-01T16:14:16","date_gmt":"2015-10-01T10:44:16","guid":{"rendered":"http:\/\/www.tothenew.com\/blog\/?p=27307"},"modified":"2017-05-01T15:14:36","modified_gmt":"2017-05-01T09:44:36","slug":"chef-bootstrapping-an-autoscaled-node-using-cloud-init-cloud-config-and-userdata","status":"publish","type":"post","link":"https:\/\/www.tothenew.com\/blog\/chef-bootstrapping-an-autoscaled-node-using-cloud-init-cloud-config-and-userdata\/","title":{"rendered":"Chef: Bootstrapping an autoscaled Node using Cloud-Init, Cloud-Config and UserData"},"content":{"rendered":"<p>This blog refers to the bootstrapping an autoscaled Node using Cloud-Init, Cloud-Config and UserData and get it available for serving requests. Here, in this blog I am bootstrapping a web server. We will be using a yaml file and a recipe to implement the same.<\/p>\n<h3>What is Cloud-Init?<\/h3>\n<p>Cloud-Init is the package which is already installed on the cloud environment, it is used to initialize the early stages of the cloud servers. It locates user-data and executes the instructions pre written on it. It understands only two userData formats &#8211; shell script and cloud-config directives.<\/p>\n<h3>What is Cloud-Config?<\/h3>\n<p>It is Cloud-Init script which defines the parameters which are required when the server boots up.<\/p>\n<h3>What is UserData?<\/h3>\n<p>UserData is a type of metadata that can be passed to an instance to perform different actions including executing scripts and Chef-recipes on boot. It is limited to 16KB.<\/p>\n<h3>Chef-Server<\/h3>\n<p>It is the configuration management tool written in Ruby and Erlang. It is used to manage and configure organisation&#8217;s servers.<\/p>\n<h3>Bootstrapping<\/h3>\n<p>While bootstrapping a node from Chef, user-data on the node will be called by the Cloud-Init program and chef-client will be installed which will register itself on <a title=\"Chef DevOps\" href=\"http:\/\/www.tothenew.com\/devops-chef-puppet-docker\">Chef Server<\/a> and will pull out all the configured recipes for that \u2018type\u2019 of node.<\/p>\n<h3>Use Case:<\/h3>\n<p>We had a requirement where we wanted an <a title=\"AWS Scaling\" href=\"http:\/\/www.tothenew.com\/blog\/aws-auto-scaling-lifecycle-hooks\/\">AWS autoscaling<\/a> node to automatically bootstrap and get itself ready for serving web requests via Nginx. Autoscaling node supposed to be a raw machine and will get its packages and services from Chef server via User data and Cloud-Init.<\/p>\n<h3><\/h3>\n<h3>User Data Dissection<\/h3>\n<p>[js]<\/p>\n<p>#cloud-config<\/p>\n<p># This example assumes the instance is 12.04 (precise)<br \/>\n# The default is to install from packages.<\/p>\n<p># Key from<br \/>\napt_upgrade: true<br \/>\napt_sources:<br \/>\n&#8211; source: &quot;deb  $RELEASE-0.10 main&quot;<br \/>\nkey: |<br \/>\n&#8212;&#8211;BEGIN PGP PUBLIC KEY BLOCK&#8212;&#8211;<br \/>\nVersion: GnuPG v1.4.9 (GNU\/Linux)<\/p>\n<p>mQGiBEppC7QRBADfsOkZU6KZK+YmKw4wev5mjKJEkVGlus+NxW8wItX5sGa6kdUu<br \/>\nzIhi7tKFo6WiwjKZq0dzctsJJjtIfr4K4vbiD9Ojg1iISQQYEQIACQUCSmkLtAIb<br \/>\n&#8230;&#8230;..<br \/>\nDAAKCRApQKupg++CauISAJ9CxYPOKhOxalBnVTLeNUkAHGg2gACeIsbobtaD4ZHG<br \/>\n0GLl8EkfA8uhluM=<br \/>\n=zKAm<br \/>\n&#8212;&#8211;END PGP PUBLIC KEY BLOCK&#8212;&#8211;<\/p>\n<p>#The above will verify that the we are downloading is from trusted source<\/p>\n<p>[\/js]<\/p>\n<p>&nbsp;<\/p>\n<p>The above will upgrade the package sources list and it will install chef client on the machine.<br \/>\n<strong>apt_upgrade<\/strong> :- It will upgrade the package sources.<br \/>\n<strong>apt_sources<\/strong> :- Here we specify the package which we are required to be installed.<br \/>\n<strong>key<\/strong> :- Key present here will verify the key that the package is being installed from trusted source.<\/p>\n<p>[js]<\/p>\n<p>chef:<br \/>\nrun_list:<br \/>\n&#8211; &quot;recipe[nginx]&quot;<\/p>\n<p># Valid values are &#8216;gems&#8217; and &#8216;packages&#8217; and &#8216;omnibus&#8217;<br \/>\ninstall_type: &quot;packages&quot;<\/p>\n<p># Boolean: run &#8216;install_type&#8217; code even if chef-client<br \/>\n# appears already installed.<br \/>\nforce_install: false<\/p>\n<p># Chef settings<br \/>\nserver_url: &quot;https:\/\/ip-X-X-X-X.ec2.internal\/organizations\/organisation-name&quot;<\/p>\n<p># Node Name<br \/>\n# Defaults to the instance-id if not present<br \/>\nnode_name: &quot;#{Socket.gethostname}-test&quot;<br \/>\n# Default validation name is organisation-validator<br \/>\nvalidation_name: &quot;organisation-validator&quot;<br \/>\nvalidation_key: |<br \/>\n&#8212;&#8211;BEGIN RSA PRIVATE KEY&#8212;&#8211;<br \/>\nMIIEowIBAAKCAQEAw75CltGJ1oYf980m1B9soHbDVK\/6l1dhgzd86aW8GjFpqfz8<br \/>\nQ9kXZ3wrLOxJ64+vIF1qouMzgtoGCayZ00t62MnCZodgPCzccHY0CZKOKx2V1dDW<br \/>\nPAt1veQkXODDLilFiGfTlwBud+O1JLoDa5Nxt6y9INL21IGx3sXi54Z7Df98ZS2z<br \/>\n5K5IzLjRsjmh2NhwG\/fB7xRYXaImHrjua7c309rH411Pgo1xcQb9xETU4WaOyl\/C<br \/>\n&#8230;&#8230;<br \/>\nQEo7WQKBgGKenUL\/CmBmehY6EBfsYyq1Pbwn\/f3n1D0w61ef+zBD0KVnO78dZozq<br \/>\nWd2pd4EHxp4+V1NEGCF47YVfiO+D9Lk3V4ic+1kVfYCsefygdbr5i1C4zUVOGcso<br \/>\nQcbwgH\/doZL7MfiofwHP8MupY410UQnnV2it72Ml+bJf9Q7ezjsX<br \/>\n&#8212;&#8211;END RSA PRIVATE KEY&#8212;&#8211;<\/p>\n<p>#The above key is organisation-validator.pem which is present on the chef server<\/p>\n<p>[\/js]<\/p>\n<p>&nbsp;<\/p>\n<p>The above code will be executed after chef-client has installed<br \/>\n<strong>run_list<\/strong> :- Here we specify the recipes which needs to be executed after Chef has booted.<br \/>\n<strong>install_type<\/strong> :- It specifies which type of installation you want which can be \u2018gems\u2019, \u2018packages\u2019 and \u2018omnibus\u2019.<br \/>\n<strong>server_url<\/strong> :- Here we specify the Chef server URL.<br \/>\n<strong>node_name<\/strong> :- Here we specify the name of the node which you want to be registered as.<br \/>\n<strong>validation_name<\/strong> :- Here we give the name organisation validator.<br \/>\n<strong>validation_key<\/strong> :- Here we specify the organisation validator key to authenticate the node with Chef server.<\/p>\n<p>[js]<\/p>\n<p># if install_type is &#8216;omnibus&#8217;, change the url to download<br \/>\nomnibus_url: &quot;https:\/\/www.opscode.com\/chef\/install.sh&quot;<\/p>\n<p># Capture all subprocess output into a logfile<br \/>\n# Useful for troubleshooting cloud-init issues<br \/>\noutput: {all: &#8216;| tee -a \/var\/log\/cloud-init-output.log&#8217;}<\/p>\n<p>[\/js]<\/p>\n<p>&nbsp;<\/p>\n<p><strong>omnibus_url<\/strong> :- Here we specify the URL from which we can download packages if install type omnibus is selected.<br \/>\n<strong>output<\/strong> :- It specifies where you want to store the logs of the above events.<br \/>\n<strong>runcmd<\/strong> :- Here we can write shell commands or scripts which will be executed on the machine.<\/p>\n<p>The above yaml script can be downloaded from <a title=\"here\" href=\"https:\/\/github.com\/aakash21\/UserData\/blob\/master\/userdata.yaml\">here<\/a><\/p>\n<h3>Troubleshooting<\/h3>\n<p>Logs can be checked at cloud-init-output.log and client.log.<\/p>\n<h4>cloud-init-output.log<\/h4>\n<p>This file would contain all the logs of the events occurred when the userdata.yaml is executed. This has specified in the userdata.yaml itself.<br \/>\noutput: {all: &#8216;| tee -a \/var\/log\/cloud-init-output.log&#8217;}<\/p>\n<h4>client.log<\/h4>\n<p>\/var\/log\/chef\/client.log<br \/>\nThis file contain the logs after Chef has installed and it tries to connect to Chef server. We can check here whether our node has connected to our Chef server.<\/p>\n<h3>What this UserData will do?<\/h3>\n<ul>\n<li>It will first update the package sources.<\/li>\n<li>Then it will download and install the chef-client on that node from the defined repository.<\/li>\n<li>For initial handshake and registration, it will use organization validator key and will generate a RSA Private key (client.pem) for further communication.<\/li>\n<li>After making connection with the Chef server, it will get its packages as configured on Chef server and execute the recipe which is passed as run_list.<\/li>\n<li>Once chef-client run is completed, Server is ready !!<\/li>\n<\/ul>\n<h3>Conclusion<\/h3>\n<p>We can bootstrap our servers automatically with the pre defined cookbooks without logging into that server instance or into chef-workstation to manually bootstrap it.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>This blog refers to the bootstrapping an autoscaled Node using Cloud-Init, Cloud-Config and UserData and get it available for serving requests. Here, in this blog I am bootstrapping a web server. We will be using a yaml file and a recipe to implement the same. What is Cloud-Init? Cloud-Init is the package which is already [&hellip;]<\/p>\n","protected":false},"author":261,"featured_media":0,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"iawp_total_views":6},"categories":[2348],"tags":[],"aioseo_notices":[],"_links":{"self":[{"href":"https:\/\/www.tothenew.com\/blog\/wp-json\/wp\/v2\/posts\/27307"}],"collection":[{"href":"https:\/\/www.tothenew.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.tothenew.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.tothenew.com\/blog\/wp-json\/wp\/v2\/users\/261"}],"replies":[{"embeddable":true,"href":"https:\/\/www.tothenew.com\/blog\/wp-json\/wp\/v2\/comments?post=27307"}],"version-history":[{"count":0,"href":"https:\/\/www.tothenew.com\/blog\/wp-json\/wp\/v2\/posts\/27307\/revisions"}],"wp:attachment":[{"href":"https:\/\/www.tothenew.com\/blog\/wp-json\/wp\/v2\/media?parent=27307"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.tothenew.com\/blog\/wp-json\/wp\/v2\/categories?post=27307"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.tothenew.com\/blog\/wp-json\/wp\/v2\/tags?post=27307"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}