Saturday, June 30, 2018

Implementasi Ansible Playbook

Halo, kali ini saya akan melanjutkan pembahasan mengenai ansible yang sebelumnya dibuat rekan saya. Pada post sebelumnya sudah ada pengenalan ansible dan ansbile playbook. Sedikit mengulang kembali Ansible adalah sebuah provisioning tool yang dikembangkan oleh RedHat. Dimana kamu dapat mencatat setiap proses deployment ataupun konfigurasi yang biasa dilakukan berulang - ulang terhadap beberapa server. Saat ini saya akan membahas lebih dalam lagi mengenai ansible roles dimana task-task ini akan menjalankan modul-modul yang sudah dibuat. Beberapa contoh task yang akan saya berikan seperti task untuk user provisioning, set hostname, nginx, nodejs.


Directory Layout


Untuk memudahkan kita dalam menggunakan ansible kita perlu mengetahui susunan direktori dan file-file dari ansible. Berikut contoh susunan file-file script ansible

 production        # inventory file for production servers  
 staging          # inventory file for staging environment  
 group_vars/  
   group1.yml       # here we assign variables to particular groups  
   group2.yml  
 host_vars/  
   hostname1.yml     # here we assign variables to particular systems  
   hostname2.yml  
 library/         # if any custom modules, put them here (optional)  
 module_utils/       # if any custom module_utils to support modules, put them here (optional)  
 filter_plugins/      # if any custom filter plugins, put them here (optional)  
 site.yml         # master playbook  
 webservers.yml      # playbook for webserver tier  
 dbservers.yml       # playbook for dbserver tier  
 roles/  
   common/        # this hierarchy represents a "role"  
     tasks/      #  
       main.yml   # <-- tasks file can include smaller files if warranted  
     handlers/     #  
       main.yml   # <-- handlers file  
     templates/    # <-- files for use with the template resource  
       ntp.conf.j2  # <------- templates end in .j2  
     files/      #  
       bar.txt    # <-- files for use with the copy resource  
       foo.sh    # <-- script files for use with the script resource  
     vars/       #  
       main.yml   # <-- variables associated with this role  
     defaults/     #  
       main.yml   # <-- default lower priority variables for this role  
     meta/       #  
       main.yml   # <-- role dependencies  
     library/     # roles can also include custom modules  
     module_utils/   # roles can also include custom module_utils  
     lookup_plugins/  # or other types of plugins, like lookup in this case  
   webtier/       # same kind of structure as "common" was above, done for the webtier role  
   monitoring/      # ""  
   fooapp/  


Pada ansible ada beberapa istilah seperti inventories, tasks, playbook, roles, vars, files, templates, handlers, tags.

inventories:  berisi host-host dan variable host var atau grup var yang digunakan pada environment seperti production, staging, atau environtment lainnya

tasks: berisi perintah-perintah yang akan dijalakan dalam role secara berurutan yang dipanggil didalam ansible playbook

playbook: berisi kumpulan role-role ansible yang akan dijalankan untuk mengkonfigurasi sebuah server atau hal lainnya.

roles: berisi semua task-task, files, handlers, vars, atau templates

variables: variabel yang bisa berupa kata yang bisa kita set nilainya

files: berisi file-file yang akan di transfer ke server

templates:
handlers: berisikan langkah yang akan dieksekusi dalam tasks bila task tersebut sudah dilakukan. seperti start, stop, restart, dll.

tags: pemberian nama pengenal pada setiap task sehingga pada waktu menjalankan ansible playbook kita dapat memilih task-task apa saja yang akan digunakan dengan memilih tag-tag yang kita butuhkan.


Implementasi Ansible

Untuk memulainya saya sudah siapkan 3 buah vm yang sudah terpasang ansible di dalamnya.
  • 192.16.10.11 = ansible server
  • 192.16.10.12 = server target 1
  • 192.16.10.13 = server target 2
susunan file ansible kali ini seperti di bawah ini:
 ├── ansible.cfg  
 ├── files  
 │  └── install_node.sh  
 ├── inventories  
 │  └── production  
 │    ├── group_vars  
 │    │  └── ansible.yml  
 │    └── hosts  
 ├── playbook  
 │  ├── nodejs.yml  
 │  └── webserver.yml  
 ├── roles  
 │  ├── add-user  
 │  │  └── tasks  
 │  │    └── main.yml  
 │  ├── common  
 │  │  └── tasks  
 │  │    └── main.yml  
 │  ├── nginx  
 │  │  └── tasks  
 │  │    └── main.yml  
 │  └── nodejs  
 │    └── tasks  
 │      ├── install.yml  
 │      └── main.yml  
 ├── scripts  
 │  └── production  
 │    ├── nodejs.sh  
 │    └── webserver.sh  
 └── templates  
   ├── nginx.conf.j2  
   └── service1.conf  


Dari susunan di atas saya ingin memperlihatkan isi dari file-file tersebut:

file ./files/install_node.sh. adalah script untuk menginstall nodejs pada server. isi file tersebut seperti di bawah ini
 #!/bin/bash  
 curl -sL https://rpm.nodesource.com/setup_8.x | bash -  
 yum install -y nodejs  
 sudo npm install pm2 -g  

file inventories/production/group_vars/ansible.yml , file ini berisi variabel-variabel yang akan digunakan pada ansible. isi file tersebut seperti di bawah ini
 nginx_port: 80  
 server_name.default: horas.tk  

isi file inventories/production/group_vars/nginx.yml
 web_dir: /usr/share/nginx  

isi dari file inventories/production/hosts seperti di bawah ini
 [all]  
 server2          ansible_host=192.16.10.12  
 server3          ansible_host=192.16.10.13  

isi dari file ./playbook/nodejs.yml
 - hosts: all  
  remote_user: root  
  become: yes  
  roles:  
   - nodejs  

isi dari file ./playbook/webserver.yml
 - hosts: all  
  remote_user: root  
  become: yes  
  roles:  
   - add-user  
   - common  
   - nginx  

isi dari file ./roles/add-user/tasks/main.yml
 - name: Allow 'wheel' group to have passwordless sudo  
  lineinfile:  
   dest: /etc/sudoers  
   state: present  
   regexp: '^%wheel'  
   line: '%wheel ALL=(ALL) NOPASSWD: ALL'  
   validate: visudo -cf %s  
  when: ansible_os_family == "RedHat"  
  tags: sudoers  
 - name: Allow 'sudo' group to have passwordless sudo  
  lineinfile:  
   dest: /etc/sudoers  
   state: present  
   regexp: '^%sudo'  
   line: '%sudo ALL=(ALL) NOPASSWD: ALL'  
   validate: visudo -cf %s  
  when: ansible_os_family == "Debian"  
  tags: sudoers  
 - name: Ensure group "developer" exists  
  group:  
   name: developer  
   state: present  
  tags: add_group  
 - name: Create user  
  user: name="{{ item.name}}" comment="Create user with ansible" groups=developer append=yes shell=/bin/bash  
  with_items:  
   - { name: land }  
   - { name: regar }  
  tags: create_user  
 - name: Placing SSH Key to Authorized Key  
  authorized_key: user="{{item.name}}" key="{{ item.key}}"  
  with_items:  
   - {name: land, key: ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQCm2wey+RyM81ZWgyEU7npsEUq0NQmtNjIMGPzxPQfxidHkzkMOp0xTyBFJFb95CwQMYxEQz5gzDv5TWZjT0u/1yxfck8pPgotNpPzGbgVTEDmuN/P5SgEhF1gpotYimRomMsMiAf6NEyV5VqUk+dS+F1xbwsdbwwfGle4eI1QeaLXSCnlb9xwDuDcFe+nz0X7m8dnzYtglEIkXPfbXlJUDtxQCBSgVDMnHukJABAwCNdbZgxnr/ZL7zjSOTkQxB2zSQR6+aY01oVj39A4kdw4x/xsoZ5zjeAC5/viYimfLppF1vCLlPLSCIQrsp0D6ym5Em6Xq1huHkLozfjutsdD7 land@latihan1}  
   - {name: regar, key: ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQCm2wey+RyM81ZWgyEU7npsEUq0NQmtNjIMGPzxPQfxidHkzkMOp0xTyBFJFb95CwQMYxEQz5gzDv5TWZjT0u/1yxfck8pPgotNpPzGbgVTEDmuN/P5SgEhF1gpotYimRomMsMiAf6NEyV5VqUk+dS+F1xbwsdbwwfGle4eI1QeaLXSCnlb9xwDuDcFe+nz0X7m8dnzYtglEIkXPfbXlJUDtxQCBSgVDMnHukJABAwCNdbZgxnr/ZL7zjSOTkQxB2zSQR6+aY01oVj39A4kdw4x/xsoZ5zjeAC5/viYimfLppF1vCLlPLSCIQrsp0D6ym5Em6Xq1huHkLozfjutsdD7 regar@latihan1}  
  tags: create_user  
 - name: Add group user to sudo  
  user: name="{{ item.name}}" groups=wheel append=yes shell=/bin/bash  
  with_items:  
   - { name: land }  
   - { name: regar }  
  when: ansible_os_family == "RedHat"  
  tags: add_sudo  
 - name: Add group user to sudo  
  user: name="{{ item.name}}" groups=sudo append=yes shell=/bin/bash  
  with_items:  
   - { name: land }  
   - { name: regar }  
  when: ansible_os_family == "Debian"  
  tags: add_sudo  

isi dari file ./roles/common/tasks/main.yml
 - name: Change the hostname  
  hostname:  
   name: "{{ inventory_hostname }}"  
  tags: hostname  
 - name: Creates directory app data  
  file:  
   path: /opt/land  
   state: directory  
   owner: root  
   group: root  
   mode: 0775  
   recurse: yes  
  tags: folder_app  
 - name: Ensure hostname is in /etc/hosts  
  lineinfile:  
   dest: /etc/hosts  
   line: "{{ansible_host}}  {{ inventory_hostname }}"  
   state: present  
  tags: hosts  

isi dari file ./roles/nginx/tasks/main.yml
 - name: Install the nginx  
  yum:  
   name: nginx  
   state: present  
  when: ansible_os_family == "RedHat"  
  tags: install  
 - name: Install the nginx  
  apt:  
   name: nginx  
   state: present  
  when: ansible_os_family == "Debian"  
  tags: install  
 - name: Enable nginx default.conf  
  template:  
   src: ../templates/nginx.conf.j2  
   dest: /etc/nginx/nginx.conf  
   owner: root  
   group: root  
   mode: 0644  
  tags: default  
 - name: restart nginx  
  service:  
   name: nginx  
   state: restarted  
   enabled: yes  
  tags: restart  

isi dari file ./roles/nodejs/tasks/main.yml
 - name: copy script install node  
  copy:  
   src: /etc/ansible/files/install_node.sh  
   dest: /home/ci/install_node.sh  
   mode: 0755  
  when: ansible_os_family == "RedHat"  
  tags: copy script  
 - name: install repo nodejs  
  shell: /home/ci/install_node.sh  
  when: ansible_os_family == "RedHat"  
  tags: nodejs  
 - name: Install the epel packages for EL distributions  
  package: name=epel-release state=present  
  when: ansible_os_family == "RedHat"  
  tags: install  
 - name: install nodejs v 8.6.0  
  shell: export NVM_DIR=/opt/app/.nvm && curl -o- https://raw.githubusercontent.com/creationix/nvm/v0.33.1/install.sh | bash && . /root/.bashrc && nvm install 8.6.0  
  when: ansible_os_family == "Debian"  
  tags: nodejs  
 - name: Creates directory app pm2  
  file:  
   path: /pm2  
   state: directory  
   owner: root  
   group: root  
   mode: 0777  
   recurse: yes  
  tags: folder  
 - name: install pm2 global  
  shell: ln -sf /opt/app/.nvm/versions/node/v8.6.0/bin/node /usr/bin/node && /opt/app/.nvm/versions/node/v8.6.0/bin/npm install pm2 -g  
  become: yes  
  when: ansible_os_family == "Debian"  
  tags: pm2  
 - name: Export PM2 home  
  lineinfile:  
   dest: /etc/profile  
   line: "export PM2_HOME=/pm2"  
   state: present  
  tags: pm2_home  

isi dari file ./templates/nginx.conf.j2
 server {  
   listen {{ nginx_port }} ;  
   listen [::]:{{ nginx_port }} ;  
   server_name {{ server_name.default }};  
   root {{ web_dir }};  
   index index.html index.htm index.nginx-debian.html;  
   location / {  
     try_files $uri $uri/ =404;  
   }  
 }  

isi dari file ./scipts/production/nodejs.sh
 #!/bin/bash  
 cd /etc/ansible  
 ansible-playbook -i inventories/production nodejs.yml  

isi dari file ./scipts/production/webserver.sh
 #!/bin/bash  
 cd /etc/ansible  
 ansible-playbook -i inventories/production webserver.yml  

Setelah kita membuat semua file tersebut sekarang kita akan menjalankan command ansbile playbook dari server ansible. Untuk menginstall web server nginx kita dapat menjalankan script bash ./scipts/production/webserver.sh yang di dalam file tersebut terdapat command ansible playbook.
 ./scipts/production/webserver.sh  
setelah selesai di run, maka task-task yang ada pada playbook webserver seperti create folder, add-user, add user to sudo,  set hostname, install nginx, copy nginx, dan run nginx.

untuk menginstall nodejs kita dapat menjalankan perintah di bawah ini
 ./scipts/production/nodejs.sh  
playbook tersebut akan menjalankan semua task-task yang dibutuhkan untuk instalasi nodejs.


Masih banyak lagi penggunaaan dan contoh-contoh ansible playbook untuk yang dapat digunakan untuk mempermudah kita karena tidak perlu melakukan hal yang sama berulang-ulang. Untuk lebih lengkapnya bisa mengunjungi link ini https://docs.ansible.com/ansible/latest/index.html . Untuk contoh playbook yang lain bisa kita dapatkan dari github atau blog-blog lain.

Sekian tutorial kali ini semoga bermanfaat.





No comments:

Post a Comment