{"id":2959,"date":"2014-10-16T15:23:30","date_gmt":"2014-10-16T13:23:30","guid":{"rendered":"http:\/\/supportex.net\/blog\/?p=2959"},"modified":"2019-05-10T14:42:26","modified_gmt":"2019-05-10T12:42:26","slug":"ansible-quick-intro","status":"publish","type":"post","link":"https:\/\/supportex.net\/blog\/2014\/10\/ansible-quick-intro\/","title":{"rendered":"Ansible: quick intro"},"content":{"rendered":"<p><a href=\"http:\/\/docs.ansible.com\">Ansible <\/a>is a solution for remote server management. It&#8217;s pure Python and basically the only thing \u00a0it requires is SSH connection. Why you\u00a0might want to start using it? Well..<\/p>\n<ul>\n<li>For starters, it&#8217;s very simple. It&#8217;s possible to start using it after 10 minutes introduction. It doesn&#8217;t require to know anything special. All configuration is plain YAML. Don&#8217;t worry if you don&#8217;t know what YAML is. It&#8217;s so simple you don&#8217;t even imagine.<\/li>\n<li>It&#8217;s very handy and flexible. You can set up \/ update \/ remove \/ manage packages. You can deploy applications. You can deploy admin scripts. You can prepare an environment. You can fix security issues. You can check security updates.<\/li>\n<li>It supports all common Linux OS distributions (Centos, Debian, Ubuntu).<\/li>\n<li>It doesn&#8217;t require any host agents.<\/li>\n<li>There&#8217;s great dynamic community. On Github \u00a0you can find almost all typical tasks\u00a0prepared for you. Like LAMP setup, WordPress \u00a0\/ MySQL \/ nodejs deployment and so on.<\/li>\n<\/ul>\n<p>So let&#8217;s get started. We will use Centos servers, but it&#8217;s possible to use other ones.<\/p>\n<p>Obviously we need to install <strong>ansible<\/strong> on some server you can use as management one. We will run all commands from there. It&#8217;s possible to install it from the package (rpm or deb) or with use of pip. For Centos you might need to enable <a href=\"https:\/\/fedoraproject.org\/wiki\/EPEL\">EPEL repo.<\/a><\/p>\n<p><code class=\"EnlighterJSRAW\" data-enlighter-language=\"shell\">yum install ansible<br \/>\n<\/code><\/p>\n<p>Ok, our next step is creating of the inventory file. We will specify all our servers we want to manage. Let&#8217;s call it &#8216;hosts&#8217;.<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"shell\">[webservers]\nweb1.example.com\nweb2.example.com\n<\/pre>\n<p>At this point we are ready to run\u00a0our first command. It&#8217;s supposed that you log in as root. It&#8217;s insecure \u00a0since direct root login should be disabled, and you should never do that. In this case we assume it&#8217;s freshly built cloud servers and the root password is the same on both servers. Later we\u00a0will be able use different ones or SSH keys (better way).<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"shell\">[root@jump ~]# ansible webservers -i hosts -m ping -k\nSSH password:\nweb1.example.com | success &gt;&gt; {\n\"changed\": false,\n\"ping\": \"pong\"\n}\n\nweb2.example.com | success &gt;&gt; {\n\"changed\": false,\n\"ping\": \"pong\"\n}\n[root@jump ~]#\n<\/pre>\n<hr \/>\n<p>Quick tip. If you run<\/p>\n<p><code class=\"EnlighterJSRAW\" data-enlighter-language=\"shell\">export ANSIBLE_HOSTS=hosts<\/code><\/p>\n<p>you will not have to specify the inventory file each time you run <strong>ansible<\/strong>.<\/p>\n<hr \/>\n<p>Let&#8217;s consider our command. Here we force <strong>ansible<\/strong> to use our inventory file (&#8216;hosts&#8217;). We also use module <em>ping<\/em>. It&#8217;s the simplest one. If &#8216;-k&#8217; is specified <strong>ansible<\/strong> asks for the password. Pretty simple, isn&#8217;t it?<\/p>\n<p>One mode useful ansilbe module is <em>shell<\/em>:<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"shell\">[root@jump\u00a0~]# ansible webservers -i hosts -m shell -a 'hostname ' -k\nSSH password:\nweb1.example.com | success | rc=0 &gt;&gt;\nweb1.example.com\n\nweb2.examle.com | success | rc=0 &gt;&gt;\nweb2.example.com\n\n[root@jump\u00a0~]#\n<\/pre>\n<p>Useless, but you can specify basically any command you want.<\/p>\n<p>Let&#8217;s do something more complex now. We will create a new user and add our pre-generated SSH keys. For this task we can write our first <em>ansible<\/em> <em>playbook<\/em>.:<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"shell\">- hosts: webservers\n\n tasks:\n - name: add deploy user 'devops'\n user: name=devops group=wheel\n - name: Add RSA key to the remote host\n authorized_key: user='devops' key=\"{{ lookup('file', '~\/.ssh\/id_rsa.pub') }}\"\n\n - lineinfile: \"dest=\/etc\/sudoers state=present regexp='^%wheel' line='%wheel ALL=(ALL) NOPASSWD: ALL'\"<\/pre>\n<p>Yep, it&#8217;s that easy. I believe it&#8217;s pretty self-descriptive but let&#8217;s go through each line.<\/p>\n<p>At the very beginning we declare <em>task<\/em><em>s<\/em> section.<\/p>\n<p>We use\u00a0<em>name<\/em>\u00a0 \u00a0line just to comment each action.<\/p>\n<p><em>user<\/em>\u00a0 line is for users creating, and <em>authorized_key<\/em>\u00a0 adds our SSH key on the servers.<\/p>\n<p><em>lineinefile<\/em>\u00a0 makes sure we will be able to run command as root using our devops account with no password (although technically it&#8217;s possible to ask <strong>ansible<\/strong> to enter the password for you). We ommit <em>name \u00a0<\/em>line here, but of course you can always use it.<\/p>\n<p>This is how to check our playbook.<\/p>\n<p><code class=\"EnlighterJSRAW\" data-enlighter-language=\"shell\">ansible-playbook \u00a0ssh.yml --check -k<\/code><\/p>\n<p>Once everything is ok, run:<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"shell\">[root@jump ~]# ansible-playbook ssh.yml -k\n\nSSH password:\n\nPLAY [webservers] *************************************************************\n\nGATHERING FACTS ***************************************************************\nok: [web1.example.com]\nok: [web2.example.com]\n\nTASK: [add deploy user 'devops'] **********************************************\nchanged: [web1.example.com]\nchanged: [web2.example.com]\n\nTASK: [Add RSA key to the remote host] ****************************************\nchanged: [web1.example.com]\nchanged: [web1.example.com]\n\nTASK: [lineinfile dest=\/etc\/sudoers state=present regexp='^%wheel' line='%wheel ALL=(ALL) NOPASSWD: ALL'] ***\nok: [web1.example.com]\nok: [web2.example.com]\n\nPLAY RECAP ********************************************************************\n\nweb1.example.com : ok=3 changed=2 unreachable=0 failed=0\nweb1.example.com : ok=3 changed=2 unreachable=0 failed=0\n\n[root@jump ~]#\n\n<\/pre>\n<p>You can check: user &#8216;devops&#8217; was created on both servers and it&#8217;s able to run commands as root (via sudo). Let&#8217;s check:<\/p>\n<p><code class=\"EnlighterJSRAW\" data-enlighter-language=\"shell\">ansible-playbook  ssh.yml -u devops -s  --check<\/code><\/p>\n<p><em>-s<\/em> means &#8216;use sudo&#8217;. So far so good. Now let&#8217;s suppose we want to update some package on all servers. It&#8217;s easy:<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"shell\">[root@jump ~]# ansible webservers -m yum -a \"name=rsyslog state=installed\" -u devops -s\nweb1.example.com | success &gt;&gt; {\n\"changed\": false,\n\"msg\": \"\",\n\"rc\": 0,\n\"results\": [\n\"rsyslog-5.8.10-8.el6.x86_64 providing rsyslog is already installed\"\n]\n}\n\nweb1.example.com | success &gt;&gt; {\n\"changed\": false,\n\"msg\": \"\",\n\"rc\": 0,\n\"results\": [\n\"rsyslog-5.8.10-8.el6.x86_64 providing rsyslog is already installed\"\n]\n}\n\n[root@jump ~]#\n<\/pre>\n<hr \/>\n<p><strong>Important note<\/strong>. Ansible tries to be\u00a0<em>idempotent<\/em>. It means that ansible will not make any changes if there is already what you need to get, i. e. it won&#8217;t overwrite\u00a0config files every time, but only it a change is required.<\/p>\n<hr \/>\n<p>Now we can check if there are some security updates available (requires <em>yum-security\u00a0<\/em> installed):<\/p>\n<p><code class=\"EnlighterJSRAW\" data-enlighter-language=\"shell\">ansible webservers  -a 'yum check-update --security ' -s -u devops<\/code><\/p>\n<p>Or if you need to install some gem, you can do it this way:<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"shell\">- name: install ruby gem bundler\ngem: name=bundler state=present user_install=no<\/pre>\n<p>So if you still log in to servers to apply security updates or install some software, try <strong>ansible<\/strong>. It&#8217;s really great.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Ansible is a solution for remote server management. It&#8217;s pure Python and basically the only thing \u00a0it requires is SSH connection. Why you\u00a0might want to start using it? Well.. For starters, it&#8217;s very simple. It&#8217;s possible to start using it after 10 minutes introduction. It doesn&#8217;t require to know anything special. All configuration is plain&hellip; <\/p>\n<div class=\"readmore-wrapper\"><a href=\"https:\/\/supportex.net\/blog\/2014\/10\/ansible-quick-intro\/\" class=\"more-link\">Read <\/a><\/div>\n","protected":false},"author":4,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[152],"tags":[155,275],"class_list":["post-2959","post","type-post","status-publish","format-standard","hentry","category-linux","tag-ansible","tag-linux"],"yoast_head":"<!-- This site is optimized with the Yoast SEO plugin v26.8 - https:\/\/yoast.com\/product\/yoast-seo-wordpress\/ -->\n<title>Ansible: quick intro &#8211; Supportex.NET blog<\/title>\n<meta name=\"description\" content=\"Ansible quick intro. Ansible: review\" \/>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/supportex.net\/blog\/2014\/10\/ansible-quick-intro\/\" \/>\n<meta property=\"og:locale\" content=\"en_US\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"Ansible: quick intro &#8211; Supportex.NET blog\" \/>\n<meta property=\"og:description\" content=\"Ansible quick intro. Ansible: review\" \/>\n<meta property=\"og:url\" content=\"https:\/\/supportex.net\/blog\/2014\/10\/ansible-quick-intro\/\" \/>\n<meta property=\"og:site_name\" content=\"Supportex.NET blog\" \/>\n<meta property=\"article:published_time\" content=\"2014-10-16T13:23:30+00:00\" \/>\n<meta property=\"article:modified_time\" content=\"2019-05-10T12:42:26+00:00\" \/>\n<meta name=\"author\" content=\"Oleksii Tykhonov\" \/>\n<meta name=\"twitter:label1\" content=\"Written by\" \/>\n\t<meta name=\"twitter:data1\" content=\"Oleksii Tykhonov\" \/>\n\t<meta name=\"twitter:label2\" content=\"Est. reading time\" \/>\n\t<meta name=\"twitter:data2\" content=\"5 minutes\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\/\/schema.org\",\"@graph\":[{\"@type\":\"Article\",\"@id\":\"https:\/\/supportex.net\/blog\/2014\/10\/ansible-quick-intro\/#article\",\"isPartOf\":{\"@id\":\"https:\/\/supportex.net\/blog\/2014\/10\/ansible-quick-intro\/\"},\"author\":{\"name\":\"Oleksii Tykhonov\",\"@id\":\"https:\/\/supportex.net\/blog\/en\/#\/schema\/person\/0690c26a0266603129fc15eae6243251\"},\"headline\":\"Ansible: quick intro\",\"datePublished\":\"2014-10-16T13:23:30+00:00\",\"dateModified\":\"2019-05-10T12:42:26+00:00\",\"mainEntityOfPage\":{\"@id\":\"https:\/\/supportex.net\/blog\/2014\/10\/ansible-quick-intro\/\"},\"wordCount\":680,\"commentCount\":0,\"keywords\":[\"ansible\",\"linux\"],\"articleSection\":[\"linux\"],\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"CommentAction\",\"name\":\"Comment\",\"target\":[\"https:\/\/supportex.net\/blog\/2014\/10\/ansible-quick-intro\/#respond\"]}]},{\"@type\":\"WebPage\",\"@id\":\"https:\/\/supportex.net\/blog\/2014\/10\/ansible-quick-intro\/\",\"url\":\"https:\/\/supportex.net\/blog\/2014\/10\/ansible-quick-intro\/\",\"name\":\"Ansible: quick intro &#8211; Supportex.NET blog\",\"isPartOf\":{\"@id\":\"https:\/\/supportex.net\/blog\/en\/#website\"},\"datePublished\":\"2014-10-16T13:23:30+00:00\",\"dateModified\":\"2019-05-10T12:42:26+00:00\",\"author\":{\"@id\":\"https:\/\/supportex.net\/blog\/en\/#\/schema\/person\/0690c26a0266603129fc15eae6243251\"},\"description\":\"Ansible quick intro. Ansible: review\",\"breadcrumb\":{\"@id\":\"https:\/\/supportex.net\/blog\/2014\/10\/ansible-quick-intro\/#breadcrumb\"},\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\/\/supportex.net\/blog\/2014\/10\/ansible-quick-intro\/\"]}]},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\/\/supportex.net\/blog\/2014\/10\/ansible-quick-intro\/#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Home\",\"item\":\"https:\/\/supportex.net\/blog\/en\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"Ansible: quick intro\"}]},{\"@type\":\"WebSite\",\"@id\":\"https:\/\/supportex.net\/blog\/en\/#website\",\"url\":\"https:\/\/supportex.net\/blog\/en\/\",\"name\":\"Supportex.NET blog\",\"description\":\"Server and network management company\",\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"https:\/\/supportex.net\/blog\/en\/?s={search_term_string}\"},\"query-input\":{\"@type\":\"PropertyValueSpecification\",\"valueRequired\":true,\"valueName\":\"search_term_string\"}}],\"inLanguage\":\"en-US\"},{\"@type\":\"Person\",\"@id\":\"https:\/\/supportex.net\/blog\/en\/#\/schema\/person\/0690c26a0266603129fc15eae6243251\",\"name\":\"Oleksii Tykhonov\",\"image\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\/\/supportex.net\/blog\/en\/#\/schema\/person\/image\/\",\"url\":\"https:\/\/secure.gravatar.com\/avatar\/4fd5f58002717075c88963469b9babef?s=96&d=mm&r=g\",\"contentUrl\":\"https:\/\/secure.gravatar.com\/avatar\/4fd5f58002717075c88963469b9babef?s=96&d=mm&r=g\",\"caption\":\"Oleksii Tykhonov\"},\"url\":\"https:\/\/supportex.net\/blog\/author\/oleksiitykhonov\/\"}]}<\/script>\n<!-- \/ Yoast SEO plugin. -->","yoast_head_json":{"title":"Ansible: quick intro &#8211; Supportex.NET blog","description":"Ansible quick intro. Ansible: review","robots":{"index":"index","follow":"follow","max-snippet":"max-snippet:-1","max-image-preview":"max-image-preview:large","max-video-preview":"max-video-preview:-1"},"canonical":"https:\/\/supportex.net\/blog\/2014\/10\/ansible-quick-intro\/","og_locale":"en_US","og_type":"article","og_title":"Ansible: quick intro &#8211; Supportex.NET blog","og_description":"Ansible quick intro. Ansible: review","og_url":"https:\/\/supportex.net\/blog\/2014\/10\/ansible-quick-intro\/","og_site_name":"Supportex.NET blog","article_published_time":"2014-10-16T13:23:30+00:00","article_modified_time":"2019-05-10T12:42:26+00:00","author":"Oleksii Tykhonov","twitter_misc":{"Written by":"Oleksii Tykhonov","Est. reading time":"5 minutes"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"Article","@id":"https:\/\/supportex.net\/blog\/2014\/10\/ansible-quick-intro\/#article","isPartOf":{"@id":"https:\/\/supportex.net\/blog\/2014\/10\/ansible-quick-intro\/"},"author":{"name":"Oleksii Tykhonov","@id":"https:\/\/supportex.net\/blog\/en\/#\/schema\/person\/0690c26a0266603129fc15eae6243251"},"headline":"Ansible: quick intro","datePublished":"2014-10-16T13:23:30+00:00","dateModified":"2019-05-10T12:42:26+00:00","mainEntityOfPage":{"@id":"https:\/\/supportex.net\/blog\/2014\/10\/ansible-quick-intro\/"},"wordCount":680,"commentCount":0,"keywords":["ansible","linux"],"articleSection":["linux"],"inLanguage":"en-US","potentialAction":[{"@type":"CommentAction","name":"Comment","target":["https:\/\/supportex.net\/blog\/2014\/10\/ansible-quick-intro\/#respond"]}]},{"@type":"WebPage","@id":"https:\/\/supportex.net\/blog\/2014\/10\/ansible-quick-intro\/","url":"https:\/\/supportex.net\/blog\/2014\/10\/ansible-quick-intro\/","name":"Ansible: quick intro &#8211; Supportex.NET blog","isPartOf":{"@id":"https:\/\/supportex.net\/blog\/en\/#website"},"datePublished":"2014-10-16T13:23:30+00:00","dateModified":"2019-05-10T12:42:26+00:00","author":{"@id":"https:\/\/supportex.net\/blog\/en\/#\/schema\/person\/0690c26a0266603129fc15eae6243251"},"description":"Ansible quick intro. Ansible: review","breadcrumb":{"@id":"https:\/\/supportex.net\/blog\/2014\/10\/ansible-quick-intro\/#breadcrumb"},"inLanguage":"en-US","potentialAction":[{"@type":"ReadAction","target":["https:\/\/supportex.net\/blog\/2014\/10\/ansible-quick-intro\/"]}]},{"@type":"BreadcrumbList","@id":"https:\/\/supportex.net\/blog\/2014\/10\/ansible-quick-intro\/#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https:\/\/supportex.net\/blog\/en\/"},{"@type":"ListItem","position":2,"name":"Ansible: quick intro"}]},{"@type":"WebSite","@id":"https:\/\/supportex.net\/blog\/en\/#website","url":"https:\/\/supportex.net\/blog\/en\/","name":"Supportex.NET blog","description":"Server and network management company","potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/supportex.net\/blog\/en\/?s={search_term_string}"},"query-input":{"@type":"PropertyValueSpecification","valueRequired":true,"valueName":"search_term_string"}}],"inLanguage":"en-US"},{"@type":"Person","@id":"https:\/\/supportex.net\/blog\/en\/#\/schema\/person\/0690c26a0266603129fc15eae6243251","name":"Oleksii Tykhonov","image":{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/supportex.net\/blog\/en\/#\/schema\/person\/image\/","url":"https:\/\/secure.gravatar.com\/avatar\/4fd5f58002717075c88963469b9babef?s=96&d=mm&r=g","contentUrl":"https:\/\/secure.gravatar.com\/avatar\/4fd5f58002717075c88963469b9babef?s=96&d=mm&r=g","caption":"Oleksii Tykhonov"},"url":"https:\/\/supportex.net\/blog\/author\/oleksiitykhonov\/"}]}},"_links":{"self":[{"href":"https:\/\/supportex.net\/blog\/wp-json\/wp\/v2\/posts\/2959","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/supportex.net\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/supportex.net\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/supportex.net\/blog\/wp-json\/wp\/v2\/users\/4"}],"replies":[{"embeddable":true,"href":"https:\/\/supportex.net\/blog\/wp-json\/wp\/v2\/comments?post=2959"}],"version-history":[{"count":14,"href":"https:\/\/supportex.net\/blog\/wp-json\/wp\/v2\/posts\/2959\/revisions"}],"predecessor-version":[{"id":3122,"href":"https:\/\/supportex.net\/blog\/wp-json\/wp\/v2\/posts\/2959\/revisions\/3122"}],"wp:attachment":[{"href":"https:\/\/supportex.net\/blog\/wp-json\/wp\/v2\/media?parent=2959"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/supportex.net\/blog\/wp-json\/wp\/v2\/categories?post=2959"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/supportex.net\/blog\/wp-json\/wp\/v2\/tags?post=2959"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}