Follow me, follow me, reader, and I will take you to the fascinating world of automating the deployment of environments on servers running Linux from the RHEL family.
One of our java-projects has grown, has become quite an adult and now occupies 4 circuits:
Dev - contour for the development team,
Qa - contour for the testing team,
Stage - a contour for demonstrating new features to the customer,
Production - combat circuit.
Each contour contains two identical servers with an identical set of environmental components for our application:
Oracle linux - operating system
jdk is a set of Java applications,
haproxy - proxy server
nginx is a web server for statics,
mysql - subd.
The operational team had a reasonable question: how to set up environmental management on eight servers and maintain an optimistic attitude to life.
After a brief comparison of configuration management systems, Ansible was selected. The simplicity, flexibility, and lack of agents on the managed servers played in his favor.
Now let's talk a little about the architecture of the Ansible roles for the project.
For installation and initial setup of each component of the environment a separate role is written. Subsequent customization of the settings of each component of the environment is also highlighted in an additional role. This allowed us to avoid duplication of common standard roles for other projects.
A playbook with a sequence of executable roles for connecting a new node to the loop looks like this:
- hosts: - project_group user: username become: yes gather_facts: true roles: - rhel_install_new_server - rhel_install_java - rhel_install_haproxy - rhel_install_nginx - rhel_install_mysql
And now we will tell about each role in more detail.
Performs general configuration of the operating system and installation of system utilities.
The roles / rhel_install_new_server / tasks / main.yml file
--- # tasks file for rhel_install_new_server # : - name: yum update yum: name: "*" state: latest update_cache: yes # EPEL repository: - name: install EPEL repository yum: name: https://dl.fedoraproject.org/pub/epel/epel-release-latest-7.noarch.rpm state: present update_cache: yes # . tools_packages: - name: install tools yum: name: '{{ item.name }}' state: present update_cache: yes with_items: '{{ tools_packages }}' # : - name: set autoload for default interface lineinfile: path: "/etc/sysconfig/network-scripts/ifcfg-{{ansible_default_ipv4.interface}}" regexp: '^ONBOOT=' line: 'ONBOOT="yes"' # IPv6 : - name: disable IPv6 for eth0 replace: path: "/etc/sysconfig/network-scripts/ifcfg-{{ansible_default_ipv4.interface}}" regexp: '^(IPV6.*=).*$' replace: '\1"no"' # IPv6: - name: disable IPv6 blockinfile: path: /etc/sysctl.d/disableipv6.conf create: yes marker: no block: | net.ipv6.conf.all.disable_ipv6 = 1 net.ipv6.conf.default.disable_ipv6 = 1 # SELinux: - name: disable SELinux selinux: state: disabled # firewall: - name: disable firewall systemd: name: firewalld enabled: no state: stopped ignore_errors: yes # . timezone: - name: set timezone to UTC timezone: name: '{{ timezone }}' # : - name: set synchronize time in cron cron: name: "set synchronize time by ansible" minute: 1 job: "/usr/sbin/ntpdate -u pool.ntp.org >/dev/null 2>&1" # : - name: Remove old kernels shell: "rpm -q kernel | grep -v `uname -r` | grep -v `/sbin/grubby --default-kernel | sed -r 's#^/boot/vmlinuz-##'` | xargs rpm -e || true"
--- # vars file for rhel_install_new_server tools_packages: - name: vim - name: mc - name: less - name: sysstat - name: iotop - name: strace - name: traceroute - name: screen - name: rsync - name: curl - name: python - name: wget - name: zlib - name: unzip - name: bind-utils - name: ntp - name: ntpdate - name: telnet - name: nmap - name: tcpdump - name: logrotate - name: net-tools - name: bash-completion - name: yum-utils - name: mtr timezone: UTC
Our project uses the jdk package version 8u60. Additionally, we previously downloaded and placed in the roles / rhel_install_java / files / folder the JCE files: US_export_policy.jar and local_policy.jar.
--- # vars file for roles/rhel_install_java java_dst_path: "/opt/dst/java" download_url: "http://download.oracle.com/otn/java/jdk/8u60-b27/jdk-8u60-linux-x64.rpm" java_cookie: "Cookie:' gpw_e24=http%3A%2F%2Fwww.oracle.com%2F; oraclelicense=accept-securebackup-cookie'"
The roles / rhel_install_java / tasks / main.yml file
--- # tasks file for roles/rhel_install_java # : - name: java | create java dst directory file: path: "{{ java_dst_path }}" state: directory recurse: yes owner: root group: root mode: 0755 # jdk: - name: java | download java get_url: url: "{{ download_url }}" dest: "{{ java_dst_path }}" tmp_dest: "{{ java_dst_path }}" headers: "{{ java_cookie }}" validate_certs: no owner: root group: root mode: 0744 force: yes ignore_errors: True # jdk : - name: java | register java rpm find: paths: "{{ java_dst_path }}" patterns: "*.rpm" register: java_rpm # : - debug: msg={{ java_rpm.files.0.path }} # : - name: java | install java rpm yum: name: "{{ java_rpm.files.0.path }}" state: present # Java Cryptography Extension: - name: java | copy JCE copy: src: files/{{ item }} dest: /usr/java/default/jre/lib/security/ owner: root group: root mode: 0644 backup: yes with_items: - US_export_policy.jar - local_policy.jar
The roles / rhel_install_haproxy / tasks / main.yml file
--- # tasks file for install_haproxy # haproxy: - name: install the latest version of haproxy yum: name: haproxy state: latest # rsyslog.conf: - name: backup rsyslog.conf copy: src: /etc/rsyslog.conf dest: /etc/rsyslog.conf_orig force: no remote_src: true # udp rsyslog: - name: format rsyslog | set UDP options blockinfile: path: /etc/rsyslog.conf block: | $ModLoad imudp $UDPServerAddress 127.0.0.1 $UDPServerRun 514 state: present insertafter: '^#\$UDPServerRun.*$' notify: - restart rsyslog # haproxy rsyslog: - name: create rsyslog for haproxy blockinfile: path: /etc/rsyslog.d/haproxy.conf content: | if $programname == 'haproxy' and $syslogseverity <= '4' then /var/log/haproxy/haproxy.out if $programname == 'haproxy' and $syslogseverity > '4' then /var/log/haproxy/haproxy.log & stop state: present create: yes notify: - restart rsyslog # logrotate: - name: backup logrotate file haproxy copy: src: /etc/logrotate.d/haproxy dest: /etc/logrotate.d/haproxy_orig force: no remote_src: true # logrotate haproxy: - name: copy logrotate file for haproxy copy: src: files/logrotate_haproxy dest: /etc/logrotate.d/haproxy force: yes # : - name: enable and start haproxy systemd: name: haproxy daemon_reload: yes enabled: yes state: started
Rhel_install_haproxy / handlers / main.yml file
--- # handlers file for install_haproxy - name: restart rsyslog systemd: name: rsyslog state: restarted - name: reload haproxy systemd: haproxy: name state: reloaded
File rhel_install_nginx / tasks / main.yml
--- # tasks file for roles/rhel_install_nginx # nginx: - name: add nginx repo yum_repository: name: nginx description: nginx official repo state: present baseurl: "http://nginx.org/packages/rhel/{{ansible_distribution_major_version}}/{{ansible_userspace_architecture}}/" gpgkey: http://nginx.org/keys/nginx_signing.key gpgcheck: yes enabled: yes # nginx: - name: install nginx yum: name: nginx state: present update_cache: yes # : - name: create folders file: path: '/etc/nginx/{{ item }}' state: directory mode: 0755 with_items: - conf-available - sites-available - sites-enabled # sites-enabled nginx: - name: enable sites-enabled dir lineinfile: dest: /etc/nginx/nginx.conf state: present insertafter: "(.*)include /etc/nginx/(.*)" line: " include /etc/nginx/sites-enabled/*.conf;" # default.conf: - name: stat /etc/nginx/conf.d/default.conf stat: path=/etc/nginx/conf.d/default.conf register: defaultconf_stat # , : - name: Move default.conf command: mv /etc/nginx/conf.d/default.conf /etc/nginx/sites-available/default.conf when: defaultconf_stat.stat.exists # : - name: enable and started nginx systemd: name: nginx.service enabled: yes state: started
Here it was necessary to suffer with primary authorization in mysql.
The roles / rhel_install_mysql / vars / main.yml file
--- # vars file for roles/rhel_install_mysql mysql_repo_rpm: https://dev.mysql.com/get/mysql57-community-release-el7-11.noarch.rpm mysql_packets: - mysql-community-server - mysql-community-common - MySQL-python mysql_log: /var/log/mysqld.log
The roles / rhel_install_mysql / handlers / main.yml file
--- # handlers file for roles/rhel_install_percona_mysql - name: restarted mysql systemd: name: mysqld state: restarted
The roles / rhel_install_mysql / templates / root.cnf.j2 file
[client] user=root password={{ mysql_root_password }}
The roles / rhel_install_mysql / tasks / main.yml file
-- - # tasks file for roles/rhel_install_mysql # yum: - name: install mysql repo yum: name: "{{ mysql_repo_rpm }}" state: installed # mysql: - name: install mysql yum: name: "{{ mysql_packets }}" state: installed # mysql : - name: enable mysql systemd: daemon_reload: yes name: mysqld.service enabled: yes state: started # mysql , . mysql_root_temp_password. - name: take default root password from mysql log file shell: > awk -F': ' '$0 ~ "temporary password"{print $2}' {{ mysql_log }} | tail -1 register: mysql_root_temp_password # , : - name: check mysql_root_temp_password debug: msg={{ mysql_root_temp_password.stdout }} when: mysql_root_temp_password is defined # : - name: Set temp root pass as root password set_fact: mysql_root_password: "{{ mysql_root_temp_password.stdout }}" when: mysql_root_temp_password is defined # : - name: Copy the root credentials as .my.cnf file template: src: root.cnf.j2 dest: "~/.my.cnf" mode: 0600 # , : - name: register password expire shell: mysql --defaults-file=~/.my.cnf -e "SELECT NOW();" register: password_expired ignore_errors: True - name: check password_expired debug: msg={{ password_expired.stdout }} when: password_expired is defined # - localhost: - name: ALTER USER root@localhost shell: mysql --defaults-file=~/.my.cnf --connect-expired-password -e "ALTER USER root@localhost IDENTIFIED BY '{{ mysql_root_password }}';" when: password_expired.stdout.find("expired") != -1 # : - name: Update MySQL root password for all root accounts mysql_user: name: root host: "{{ item }}" password: "{{ mysql_root_password }}" state: present priv: "*.*:ALL,GRANT" with_items: - "{{ ansible_hostname }}" - 127.0.0.1 - ::1 - localhost when: mysql_root_temp_password is defined # : - name: Ensure Anonymous user(s) are not in the database mysql_user: name: '' host: "{{ item }}" state: absent with_items: - localhost - "{{ ansible_hostname }}" # : - name: Remove the test database mysql_db: name: test state: absent
At this stage, we received a “clean” environment, the settings of which need to be customized for our project. We do this with the additional project_configuration role.
Before performing the role, check that all necessary components are installed in the system.
File roles / project_configuration / tasks / main.yml
######### check java - name: register installed java shell: java -version args: warn: no register: java_present failed_when: java_present.rc > 1 changed_when: no tags: check_installed - debug: msg: "{{ java_present.rc }}" tags: check_installed - fail: msg="Please install java first" when: java_present.rc == 1 tags: check_installed ######### check haproxy - name: register installed haproxy shell: rpm -q haproxy args: warn: no register: haproxy_present failed_when: haproxy_present.rc > 1 changed_when: no tags: check_installed - debug: msg: "{{ haproxy_present.rc }}" tags: check_installed - fail: msg="Please install haproxy first" when: haproxy_present.rc == 1 tags: check_installed - include: tasks/project_haproxy.yml when: haproxy_present.rc == 0 tags: check_installed ######### check nginx - name: register installed nginx shell: rpm -q nginx args: warn: no register: nginx_present failed_when: nginx_present.rc > 1 changed_when: no tags: check_installed - debug: msg: "{{ nginx_present.rc }}" tags: check_installed - fail: msg="Please install nginx first" when: nginx_present.rc == 1 tags: check_installed - include: tasks/project_nginx.yml when: nginx_present.rc == 0 tags: check_installed ######### check mysql - name: register installed mysql shell: rpm -q mysql57-community-release args: warn: no register: mysql_present failed_when: mysql_present.rc > 1 changed_when: no tags: check_installed - debug: msg: "{{ mysql_present.rc }}" tags: check_installed - fail: msg="Please install mysql first" when: mysql_present.rc == 1 tags: check_installed - include: tasks/project_mysql.yml when: mysql_present.rc == 0 tags: check_installed
If checks are successful, the following files are connected:
tasks / project_haproxy.yml
tasks / project_nginx.yml
tasks / project_mysql.yml
In them we prescribe the installation of configuration files using templates, the installation of ssl certificates, the establishment of the necessary system users, the creation of databases, etc.
As a result: after all the manipulations, we got a working environment for our application. Now you can start the application deployment procedure, but this is a completely different story, which we will share in the next article.
Source: https://habr.com/ru/post/348682/
All Articles