Network Security Internet Technology Development Database Servers Mobile Phone Android Software Apple Software Computer Software News IT Information

In addition to Weibo, there is also WeChat

Please pay attention

WeChat public account

Shulou

How does ansible initialize servers in batches

2025-01-19 Update From: SLTechnology News&Howtos shulou NAV: SLTechnology News&Howtos > Servers >

Share

Shulou(Shulou.com)06/03 Report--

How does ansible initialize servers in batches? In view of this problem, today's editor summarizes this article about ansible batch initialization of the server, friends in need can refer to, hope to help you.

1. The host to be initialized by ansible [root@nginx ansible] # tail-3 / etc/ansible/hosts # the initial host is as follows: [node] 192.168.20.4192.168.20.52, configure ssh secret-free login

The playbook file is as follows:

[root@nginx ansible] # cat ssh.yaml-name: configure ssh connection hosts: node gather_facts: false connection: local tasks:-name: configure ssh connection shell: | ssh-keyscan {{inventory_hostname}} > > ~ / .ssh/known_hosts sshpass-p '123.com' ssh-copy-id root@ {{inventory_hostname}}.

Note:

Gather_facts: if the value is false, the node information on the target host is not collected. By default, node information is collected. If node information is collected, it will be much slower. If the information on the node is not needed in the next operation, it can be set to false. Connection:local means that tasks are executed locally on the ansible side, and hosts:localhost and connection:local are easily confused. Although both effects are to execute tasks locally, hosts:localhost filters out the target node localhost from the inventory to execute the task, while connection:local filters out the target host to execute the task is the node in the node group. However, because the local connection type is specified, how many nodes in the node group will execute the play several times locally. 3. Configure hostname

You can use the shell module to configure hostnames, but for less professional cases, ansible provides a module dedicated to configuring hostnames: the hostname module.

Of course, to use ansible to set multiple hostnames requires that the target host and target name are already associated, otherwise multiple hosts and multiple host names cannot be set accordingly.

For example, set the hostnames of the two nodes in the node group to node01 and node02,playbook respectively as follows:

[root@ansible ansible] # cat test.yaml-name: set hostname hosts: false vars: hostnames:-host: 192.168.20.4 name: node01-host: 192.168.20.5 name: node02 tasks:-name: set hostname hostname: name: "{{item.name}}" when: item.host = = inventory_hostname loop: "{{hostnames}}"

In the above hostname module, you need to introduce the vars instruction as well as the when and loop instructions in detail.

1) vars setting variable

The vars directive can be used to set variables, and one or more variables can be set. The following ways are reasonable:

# set a single variable vars: var1: value1vars:-var1: value1# set multiple variables vars: var1: value1 var2: value2vars:-var1: value1-var2: value2

Vars can be set at the play level, or at the task level, or at the play level. Task within the play range can access these variables, while other play ranges cannot; set at the task level, only this task can access these variables, while other task and other play cannot.

For example:

[root@ansible ansible] # cat test.yaml-name: play1 hosts: localhost gather_facts: false vars:-var1: "value1" tasks:-name: access var1 debug: msg: "var1's value: {var1}}"-name: play2 hosts: localhost gather_facts: false tasks:-name: cat's access vars from play1 debug: var: var1-name: set and access var2 in this task Debug: var: var2 vars: var2: "value2"-name: cat't accesss var2 debug: var: var2

The implementation results are as follows:

[root@ansible ansible] # ansible-playbook test.yaml PLAY [play1] * TASK [access var1] * * * ok: [localhost] = > {"msg": "var1's value: value1"} PLAY [play2] * * * TASK [cat's access vars from play1] * ok: [localhost] = > {"var1": "VARIABLE IS NOT DEFINED!"} TASK [set and access var2 In this task] * ok: [localhost] = > {"var2": "value2"} TASK [cat't accesss var2] * * * ok: [localhost] = > {"var2": "VARIABLE IS NOT DEFINED!"} PLAY RECAP * * * localhost: ok=4 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0

Go back to our configuration vars directive to change the hostname:

Vars: hostnames:-host: 192.168.20.4 name: node01-host: 192.168.20.5 name: node02

Only one variable hostnames is set above, but the value of this variable is an array structure, and both elements of the array are object (dictionary / hash) structures.

So to access the hostname node01 and its IP address 192.168.20.4, you can:

Tasks:-debug: var: hostnames [0] .name-debug: var: hostnames [0] .host2) when condition judgment

In ansible, the only general conditional judgment provided is the when instruction. When the value of the when instruction is true, the task is executed, otherwise the task is not executed.

For example:

[root@ansible ansible] # cat test.yaml-name: play1 hosts: localhost gather_facts: false vars:-myname: "Ray" tasks:-name: task will skip debug: msg: "myname is: {myname}}" when: myname = = "lv"-name: task will execute debug: msg: "myname is: {myname}}" when: myname = "Ray"

In the above Myname value is set to Ray, the first task because the judgment condition of when is myname== "lv", so the result is false, the task is not executed, similarly, the second task is executed because the value of when is true.

The execution result of the playbook:

PLAY [play1] * * TASK [task will skip] * * * * skipping: [localhost] TASK [task will execute] * ok: [localhost] = > {"msg": "myname is: Ray"} PLAY RECAP * * localhost: ok=1 changed=0 unreachable=0 failed=0 skipped=1 rescued=0 ignored=0 4, Add DNS resolution records to each other [root@ansible ansible] # cat add_dns.yaml-name: play1 hosts: true tasks:-name: add DNS lineinfile: path: "/ etc/hosts" line: "{{item}} {{hostvars [item] .ansible _ hostname}}" when: item! = inventory_hostname loop: "{{play_hosts}}"

The implementation results are as follows:

TASK [Gathering Facts] * ok: [192.168.20.4] ok: [192.168.20.5] TASK [add DNS] * * skipping: [192.168.20.4] = > (item=192.168.20.4) changed: [192.168.20.4] = > (item=192.168.20.5) changed: [192.168.20.5] = > (item=192.168.20.4) skipping: [192.168.20.5] = > (item=192.168.20.5) 5, Configure the yum mirror source and install the software

The requirements are as follows:

Back up the original yum image source file, and configure the yum image source of Tsinghua University: OS source and Epel source to install common software, including lrzsz, dos2unix, wget, curl, vim, etc.

Playbook is as follows:

[root@ansible ansible] # cat config_yum.yaml-name: config yum repo add install software hosts: node gather_facts: false tasks:-name: backup origin yum repos shell: cmd: "mkdir bak Mv * .repo bak "chdir: / etc/yum.repos.d creates: / etc/yum.repos.d/bak-name: add os repo and epel repo yum_repository: name:" {{item.name}} "description:" {{item.name}} repo "baseurl:" {{item.baseurl}} "file:" {{item.name} " Enabled: 1 gpgcheck: 0 reposdir: / etc/yum.repos.d loop:-name: os baseurl: "https://mirrors.tuna.tsinghua.edu.cn/centos/7/os/$basearch"-name: epel baseurl:" https://mirrors.tuna.tsinghua.edu.cn/epel/7/$basearch"-name: install pkgs yum: name: lrzsz Vim,dos2unix,wget,curl state: present

In the yaml file above, the first task is to back up all system default repo files to the bak directory. The chdir parameter indicates that you change to the / etc/yum.repos.d directory before executing the command of the shell module, and the creates parameter indicates that the shell module is not executed if the bak directory exists.

The second task is to configure yum feeds using the yum_repository module, which adds or removes yum feeds.

The relevant parameters are as follows:

Name: specify the name of the repo, which corresponds to [name] in the repo file; the description information of the description:repo, corresponding to the name:xxx;baseurl in the repo file: specify the path to the repo; file: specify the file name of the repo, which does not need a .repo suffix, and will be added automatically; the directory where the reposdir:repo file is located, which defaults to the / etc/yum.repos.d directory; enabled: whether to enable the repo, corresponding to the enabled in the repo file Gpgcheck: whether the repo is gpgcheck enabled, corresponding to the gpgcheck;state:present in the repo file to guarantee the existence of the repo, and absent to remove the repo.

In the above configuration, a loop loop is used to add two repo:os and epel.

The third task is to install some rpm packages using the yum module, which can be updated, installed, removed, and downloaded by the yum module.

Description of yum common parameters:

Name: specifies that the package name to be operated can be a version number; it can be a single package name, a list of package names, or multiple package names separated by commas; url; can be the local rpm package state:present and installed: ensure that the package is installed, which are equivalent aliases; latest: ensure that the package has the latest version installed and updated if not; absent and removed: remove the package, which are equivalent aliases Download_only: download but not install packages only (ansible 2.7is supported) download_dir: in which directory the download packages are stored (ansible 2.8is supported)

The yum module is the package manager of the RHEL series, but it cannot be used if it is ubuntu. You can use another more general package manager module: package, which can automatically detect the package manager types of the target node and use them to manage the software. There is no problem using package instead of yum or apt-install most of the time, but some package names vary from operating system to operating system, which should be noted.

6. Time synchronization

Ensuring time synchronization can avoid a lot of metaphysical problems, especially for nodes in the cluster.

Ntpd time server is usually used to ensure time synchronization. Here, the time server provided by aliyun is used to ensure time synchronization and synchronize the synchronized time to the hardware.

The playbook file is as follows:

-name: sync time hosts: node gather_facts: false tasks:-name: install and sync time block:-name: install ntpdate yum: name: ntpdate state: present-name: ntpdate to sync time shell: | ntpdate ntp1.aliyun.com hwclock-w

A block directive is used to organize two related tasks as a whole. Block is more used for exception handling between multiple related tasks.

7. Close selinux

The playbook that closes selinux is as follows:

[root@ansible roles] # cat disable_selinux.yaml-name: disable selinux hosts: false tasks:-name: disable on the fly shell: setenforce 0 ignore_errors: true # since the return status code after the execution of the previous command is not necessarily 0, in order to prevent non-zero errors and stop the next task of palsybook So use ignore_errors to ignore errors-name: disable forever in config lineinfile: path: / etc/selinux/config line: "SELINUX=disabled" # modify the value in the configuration file to permanently close regexp:'^ SELINUX=' # what you want to modify

Note: ignore_errors is also often used in conjunction with block, because setting exception handling at the block level handles all errors within block.

8. Configure iptables rules

The playbook file is as follows:

-name: Set Firewall hosts: node gather_facts: false tasks:-name: set iptables rule shell: # backup existing rules iptables-save > / tmp/iptables.bak$ (date + "% Fmurf% T") # give it three axes iptables- X iptables- F iptables- Z # release lo network card and allow ping iptables- An INPUT-I Lo-j ACCEPT iptables-An INPUT-p icmp-j ACCEPT # release associated and connected packages Release port 22,443,80 iptables-An INPUT-m state-- state ESTABLISHED,RELATED-j ACCEPT iptables-An INPUT-p tcp-m tcp-- dport 22-j ACCEPT iptables-An INPUT-p tcp-m tcp-- dport 443-j ACCEPT iptables-An INPUT-p tcp-m tcp-- dport 80-j ACCEPT # configure three-chain default rules for filter table INPUT chain discards all packets iptables-P INPUT DROP iptables-P FORWARD DROP iptables-P OUTPUT ACCEPT9, remotely modifies sshd configuration files and restarts

Sometimes for the security of the server, the default configuration of the sshd service on the target node may be modified, such as prohibiting root users from logging in, prohibiting password authentication login and allowing only ssh password authentication, and so on.

There are generally several ways to modify the configuration file of a service:

Modify the configuration file by remotely executing commands such as sed; modify the configuration file through the lineinfile module; write the configuration file in the ansible local section, and then use the copy module or template module to transfer to the target node.

Relatively speaking, the third scheme is the most unified and easy to maintain.

In addition, for the service process, modifying the configuration file often means restarting the service to load a new configuration file, as well as for sshd, but sshd is more special than other services, because ansible is based on ssh connection by default, and restarting the sshd service will disconnect the ansible connection. Fortunately, ansible retries to establish a connection by default, just waiting for a few more seconds. However, rebuilding the connection may fail, for example, modifying the configuration file does not allow retry, modifying the listening port of sshd, and so on, which may prevent ansible from performing subsequent tasks due to connection failure.

Therefore, when modifying the sshd configuration file, the following suggestions are made:

Take this task as the last task to initialize the server, even if the connection fails; add exception handling of connection failure in playbook; if the destination node modifies the SSHD port number, it is recommended to modify the ssh connection port number in the inventory file automatically or manually through ansible.

For simplicity, I'm going to use the lineinfile module to modify the configuration file. There are only two things to change:

Set the PermitRootLogin directive to no to prohibit root users from logging in directly, and set the PasswordAuthentication directive to no to disallow login by password authentication.

The playbook content is as follows:

[root@ansible roles] # cat sshd_config.yaml-name: modify sshd_config hosts: node gather_facts: false tasks: # 1. Backup / etc/ssh/sshd_config file-name: backup sshd config shell: / usr/bin/cp-f {{path}} {{path}. Bak vars:-path: / etc/ssh/sshd_config # 2. Set PermitRootLogin no-name: disable root login lineinfile: path: "/ etc/ssh/sshd_config" line: "PermitRootLogin no" insertafter: "^ # PermitRootLogin" regexp: "^ PermitRootLogin" notify: "restart sshd" # 3. Set PasswordAuthentication no-name: disable password auth lineinfile: path: "/ etc/ssh/sshd_config" line: "PasswordAuthentication no" regexp: "^ PasswordAuthentication yes" notify: "restart sshd" handlers:-name: "restart sshd" service: name: sshd state: restarted

The functions of notify and handlers are as follows:

Ansible will monitor the status of the changed after the execution of playbook. If changed=1, the status of concern has changed, that is, the execution of this task is not idempotent. If changed=0, it means that either the task has not been executed, or it has been executed or has no impact, that is, the task is idempotent.

Ansible provides notify instruction and handlers function. If a notify instruction is defined in a task, when ansible monitors the task changed=1, it will trigger the handler defined by the notify instruction and then execute the handler. The so-called handler, in fact, is task, no matter in writing or function, it is no different from task, the only difference is that handler is triggered and executed passively, unlike ordinary task will follow the normal process.

The only thing to note is that the names of tasks in notify and handler must be the same. For example: notify: "restart sshd", then there must be a task in handlers with name: "restart sshd" set.

In addition, in the above playbook, both lineinfile tasks have the same notify set, but ansible does not restart the sshd multiple times, but restarts it for the last time. In fact, ansible does not execute the corresponding handler immediately after executing a certain task, but executes the handler after all the ordinary tasks in the current play are completed. This advantage is that the notify can be triggered many times, but the corresponding handler is executed only once in the end, thus avoiding multiple restarts.

10. Integrate all tasks into a single playbook

Here you aggregate all the previous playbook into a single playbook file so that you can perform all the tasks at once.

The integrated playbook is as follows:

-name: Configure ssh Connection hosts: node gather_facts: false connection: local tasks:-name: configure ssh connection shell: | ssh-keyscan {{inventory_hostname}} > > ~ / .ssh/known_hosts sshpass-pendant 123.com ssh-copy-id root@ {{inventory_hostname}}-name: Set Hostname hosts: node gather_facts: false vars: hostnames:-host: 192.168.20.4 name: node01 -host: 192.168.20.5 name: node02 tasks:-name: set hostname hostname: name: "{{item.name}}" when: item.host = = inventory_hostname loop: "{{hostnames}}"-name: Add DNS For Each hosts: node gather_facts: true tasks:-name: add DNS lineinfile: path: "/ etc/hosts" line: "{{item}} {{hostvars [item] .ansible _ hostname}}" when: item! = inventory_hostname loop: "{{play_hosts}}"-name: Config Yum Repo And Install Software hosts: node gather_facts: false tasks:-name: backup origin yum repos shell: cmd: "mkdir bak Mv * .repo bak "chdir: / etc/yum.repos.d creates: / etc/yum.repos.d/bak-name: add os repo and epel repo yum_repository: name:" {{item.name}} "description:" {{item.name}} repo "baseurl:" {{item.baseurl}} "file:" {{item.name} " Enabled: 1 gpgcheck: 0 reposdir: / etc/yum.repos.d loop:-name: os baseurl: "https://mirrors.tuna.tsinghua.edu.cn/centos/7/os/$basearch"-name: epel baseurl:" https://mirrors.tuna.tsinghua.edu.cn/epel/7/$basearch"-name: install pkgs yum: name: lrzsz Vim,dos2unix,wget Curl state: present- name: Sync Time hosts: node gather_facts: false tasks:-name: install and sync time block:-name: install ntpdate yum: name: ntpdate state: present- name: ntpdate to sync time shell: | ntpdate ntp1.aliyun.com hwclock-w-name: Disable Selinux hosts: node gather_facts: false tasks :-block:-name: disable on the fly shell: setenforce 0-name: disable forever in config lineinfile: path: / etc/selinux/config line: "SELINUX=disabled" regexp:'^ SELINUX=' ignore_errors: true- name: Set Firewall hosts: node gather_facts: false tasks:-name: set iptables rule shell: | # backup existing rules iptables-save > / tmp/iptables.bak$ (date + "% FMI% T") # give it three axes iptables- X iptables- F iptables- Z # release lo network card and allow ping iptables- An INPUT-I lo-j ACCEPT iptables- An INPUT-p icmp-j ACCEPT # release associated and connected packages Release port 22,443,80 iptables-An INPUT-m state-- state ESTABLISHED,RELATED-j ACCEPT iptables-An INPUT-p tcp-m tcp-- dport 22-j ACCEPT iptables-An INPUT-p tcp-m tcp-- dport 443-j ACCEPT iptables-An INPUT-p tcp-m tcp-- dport 80-j ACCEPT # configure three-chain default rules for filter table INPUT chain discards all packets iptables-P INPUT DROP iptables-P FORWARD DROP iptables-P OUTPUT ACCEPT- name: Modify sshd_config hosts: node gather_facts: false tasks:-name: backup sshd config shell: / usr/bin/cp-f {{path}} {{path}. Bak vars:-path: / etc/ssh/sshd_config-name: disable root login lineinfile: Path: "/ etc/ssh/sshd_config" line: "PermitRootLogin no" insertafter: "^ # PermitRootLogin" regexp: "^ PermitRootLogin" notify: "restart sshd"-name: path: "/ etc/ssh/sshd_config" line: "PasswordAuthentication no" regexp: "^ PasswordAuthentication yes" notify: "restart sshd "handlers:-name:" restart sshd "service: name: sshd state: restarted

After reading this article, have you learned how to initialize the server in batch by ansible? If you want to learn more skills or want to know more about it, you are welcome to follow the industry information channel. Thank you for reading.

Welcome to subscribe "Shulou Technology Information " to get latest news, interesting things and hot topics in the IT industry, and controls the hottest and latest Internet news, technology news and IT industry trends.

Views: 0

*The comments in the above article only represent the author's personal views and do not represent the views and positions of this website. If you have more insights, please feel free to contribute and share.

Share To

Servers

Wechat

© 2024 shulou.com SLNews company. All rights reserved.

12
Report