分发脚本 ansible
虽然也可以自己写 Shell 实现分发脚本,但由于缺乏运维系统概念,混乱、零碎的写法总是让人难受,一接触到 ansible 就知道很难回去了。
Ansible 是一个用来批量管理部署远程主机上服务的工具,它通过 SSH 协议实现管理节点与远程节点之间的通信,所以首先需要完成 SSH 配置。
需要注意的是 Ansible 需要开启公钥认证,也就是添加到 known_hosts
中,对于大批量的操作可以禁用该行为:
vim /etc/ansible/ansible.cfg
# 修改以下内容
host_key_checking = False # 取消注释
install
虽然可以很简单的直接使用 yum 安装,但由于 ansible 是一个 python 编写的工具,这样就会导致 ansible 依赖于全局的 python,当全局依赖发生变化的时候可能导致 ansible 出现冲突或潜在的安全问题,所以需要隔离 ansible 与其他应用。
1. 关闭限制
systemctl stop firewalld
systemctl disable firewalld
systemctl status firewalld # 验证
vim /etc/sysconfig/selinux
# 修改以下内容
SELINUX=disabled
reboot
getenforce # 验证 Disabled
python
2. 安装wget https://www.python.org/ftp/python/3.6.9/Python-3.6.9.tar.xz
tar xf Python-3.6.9.tar.xz
cd Python-3.6.9
./configure --prefix=/usr/local --with-ensurepip=install --enable-shared LDFLAGS="-Wl,-rpath /usr/local/lib"
make && make altinstall
which pip3.6
ln -s /usr/local/bin/pip3.6 /usr/local/bin/pip # 建立软连接
pip install virtualenv
3. 创建实例
需要创建一个 ansible 用户,并在该系统用户下创建一个 python3.6 版本的 virtualenv 实例。
useradd deploy
su - deploy
virtualenv -p /usr/local/bin/python3.6 .py3-a2.8-env # 创建实例
source /home/deploy/.py3-a2.8-env/bin/activate
pip install paramiko PyYAML jinja2 # 安装依赖,保持顺序
4. 安装 ansible
git clone https://gitee.com/shanyuhai123/ansible.git
mv ansible .py3-a2.8-env/
cd .py3-a2.8-env/ansible
git branch -a # 查看分支
git checkout stable-2.8
source /home/deploy/.py3-a2.8-env/ansible/hacking/env-setup -q
ansible --version # 验证
5. 启用 ansible
shutdown -r now # 重启
su - deploy
source .py3-a2.8-env/bin/activate # 加载 py3
source .py3-a2.8-env/ansible/hacking/env-setup -q # 加载 ansible
ansible --version # 验证
inventory
Ansible 可同事操作属于一个组的多台主机,组和主机之间的关系通过 inventory 文件配置。默认的文件路径为 /etc/ansible/hosts
,除默认文件外,还可以使用多个 inventory 文件,当然也可以从云上拉取配置信息。
1. INI-like
mail.example.com
[t1]
192.168.1.11
192.168.1.12
[web]
www[01:50].example.com
[db]
db-[a:f].example.com
[webservers]
foo.example.com
bar.example.com
[dbservers]
one.example.com
two.example.com
three.example.com:5309
2. YAML
all:
hosts:
mail.example.com:
children:
webservers:
hosts:
foo.example.com:
bar.example.com:
dbservers:
hosts:
one.example.com:
two.example.com:
three.example.com:
3. Inheriting variable values
在这种情况下自己书写规则 INI-like 风格更方便一些,但是接手他人的时候更希望看到 YAML 风格,更一目了然。
INI-like
[atlanta] host1 host2 [raleigh] host2 host3 [southeast:children] atlanta raleigh [southeast:vars] some_server=foo.southeast.example.com halon_system_timeout=30 self_destruct_countdown=60 escape_pods=2 [usa:children] southeast northeast southwest northwest
YAML
all: children: usa: children: southeast: children: atlanta: hosts: host1: host2: raleigh: hosts: host2: host3: vars: some_server: foo.southeast.example.com halon_system_timeout: 30 self_destruct_countdown: 60 escape_pods: 2 northeast: northwest: southwest:
4. 参数
参数 | 说明 |
---|---|
ansible_connection | 连接类型到主机。 |
ansible_host | 要连接的主机的名称。 |
ansible_port | 连接端口号。 |
ansible_user | 连接到主机时要使用的用户名。 |
ansible_password | 身份验证的密码。 |
ansible_ssh_private_key_file | ssh使用的私钥文件。 |
ansible_ssh_common_args | 此设置始终附加到sftp,scp和ssh的默认命令行。 |
ansible_sftp_extra_args | 此设置始终附加到默认的sftp命令行。 |
ansible_scp_extra_args | 此设置始终附加到默认scp命令行。 |
ansible_ssh_extra_args | 此设置始终附加到默认的ssh命令行。 |
ansible_ssh_pipelining | 确定是否使用SSH流水线。 |
ansible_ssh_executable | 此设置将覆盖使用系统ssh的默认行为。 |
ansible_shell_type | 目标系统的shell类型。 |
ansible_python_interpreter | 目标主机python路径。 |
ad-hoc
ad-hoc 可以帮助完成临时任务,很多时候并不需要 Ansible 的强大力量(playbook)。
命令格式:
ansible <pattern_goes_here> -m <module_name> -a <arguments>
仅列出部分示例。
command
1.Execute commands on targets。
实践:
ansible t1 -m command -a "free -m"
ansible t1 -m command -a "df -h"
ansible t1 -m command -a "ls /root"
ansible t1 -m command -a "cat redhat-release"
shell
2.Execute shell commands on targets。
实践:
ansible t1 -m shell -a "echo hello > /tmp/tmp.txt"
ansible t1 -m shell -a "cat /tmp/tmp.txt" # 验证
copy
3.Copy files to remote locations。
实践:
ansible t1 -m copy -a "src=/root/shell dest=/tmp"
ansible t1 -m shell -a "ls /tmp" # 验证
ansible t1 -m shell -a "wc -l /tmp/shell" # 验证
script
4.Runs a local script on a remote node after transferring it。
实践:
echo "echo hello" > /tmp/hello.sh
cat /tmp/hello.sh # 验证
ansible t1 -m script -a "/tmp/hello.sh"
file
5.Manage files and file properties。
yum
6.Manages packages with the yum package manager。
实践:
ansible webservers -m command -a "free -m" # 验证
ansible webservers -m yum -a "name=nginx state=installed"
ansible webservers -m command -a "nginx -v" # 验证 nginx version: nginx/1.12.2
# 可以注意到并非是最新版 nginx
# 参照示例 https://docs.shanyuhai.top/os/centos/install-the-latest-version-of-nginx.html
ansible webservers -m yum -a "name=yum-utils state=installed"
ansible webservers -m command -a "ll /etc/yum.repos.d/nginx.repo" # 验证
vim /etc/yum.repos.d/nginx.repo
cat /etc/yum.repos.d/nginx.repo # 验证
# 追加内容参考示例
ansible webservers -m copy -a "src=/etc/yum.repos.d/nginx.repo dest=/etc/yum.repos.d/nginx.repo"
ansible webservers -m command -a "cat /etc/yum.repos.d/nginx.repo" # 验证
ansible webservers -m command -a "yum-config-manager --enable nginx-mainline"
ansible webservers -m yum -a "name=nginx state=installed" # 更新
# installed 测试时未能更新,可能需要 present 参数
# 不推荐使用 yum 卸载
ansible webservers -m command -a "nginx -v" # 验证
systemd
7.Manage services。
实践:
# 最好将服务写完整
ansible t1 -m systemd -a "name=crond.service enabled=yes state=started"
ansible t1 -m command -a "systemctl status crond" # 验证
cron
8.Manage cron.d and crontab entries。
实践:
ansible webservers -m cron -a "name='sync time' minute=00 hour=00 job='/usr/sbin/ntpdate time.nist.gov > /dev/null 2>&1'"
ansible webservers -m command -a "crontab -l" # 验证
# 删除任务
ansible webservers -m cron -a "name='sync time' state=absent"
ansible webservers -m command -a "crontab -l" # 验证
playbooks
相对于 ad-hoc,playbooks 则强大的多,当然也复杂得多。playbook 由一个或多个 plays 组成,在 play 中,一组机器被映射为定义好的角色,其内容被称为 tasks(任务),在基本层次的应用中,一个任务是一个对 ansible 模块的调用。
对于如何良好的实践这些内容,有一些整套的 playbooks。
1. one play
---
- hosts: webservers
vars:
http_port: 80
max_clients: 200
remote_user: root
tasks:
- name: ensure apache is at the latest version
yum:
name: httpd
state: latest
- name: write the apache config file
template:
src: /srv/httpd.j2
dest: /etc/httpd.conf
notify:
- restart apache
- name: ensure apache is running
service:
name: httpd
state: started
handlers:
- name: restart apache
service:
name: httpd
state: restarted
2. multiple plays
---
- hosts: webservers
remote_user: root
tasks:
- name: ensure apache is at the latest version
yum:
name: httpd
state: latest
- name: write the apache config file
template:
src: /srv/httpd.j2
dest: /etc/httpd.conf
- hosts: databases
remote_user: root
tasks:
- name: ensure postgresql is at the latest version
yum:
name: postgresql
state: latest
- name: ensure that postgresql is started
service:
name: postgresql
state: started
3. Directory Layout
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/ # ""
备用方案:
inventories/
production/
hosts # inventory file for production servers
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
staging/
hosts # inventory file for staging environment
group_vars/
group1.yml # here we assign variables to particular groups
group2.yml
host_vars/
stagehost1.yml # here we assign variables to particular systems
stagehost2.yml
library/
module_utils/
filter_plugins/
site.yml
webservers.yml
dbservers.yml
roles/
common/
webtier/
monitoring/
fooapp/