Ansible入门教程

1、环境准备

1.1、准备主机

这里使用3台主机做为演示
# IP地址:
192.168.10.15 【控制机】 hostnamectl set-hostname ansible-control # IP地址:192.168.10.14 hostnamectl set-hostname nfs1 # IP地址:192.168.10.13 hostnamectl set-hostname web1

1.2、时间同步服务端

# 安装软件包
yum install chrony -y

# 修改如下配置
vi /etc/chrony.conf 
makestep 10 -1
allow
local stratum 10

systemctl enable chronyd
systemctl start chronyd

# 带星表示同步成功
chronyc sources -v

# 查看是否同步成功
[root@k8s-master ~]# timedatectl 
      Local time: Tue 2023-01-03 13:40:23 CST
  Universal time: Tue 2023-01-03 05:40:23 UTC
        RTC time: Tue 2023-01-03 05:40:23
       Time zone: Asia/Shanghai (CST, +0800)
     NTP enabled: yes
NTP synchronized: yes
 RTC in local TZ: no
      DST active: n/a

1.3、安装python

1.3.1、下载软件

https://www.python.org/ftp/python/3.10.10/Python-3.10.10.tgz

1.3.2、安装依赖包

yum install gcc gcc-c++ glibc-devel glibc zlib-devel zlib sqlite-devel readline-devel bzip2-devel libffi-devel -y

1.3.3、安装openssl-3.0.8【根据python版本选择】 

# 下载openssl
wget --no-check-certificate https://www.openssl.org/source/openssl-3.0.8.tar.gz

# 安装perl和所需要的模板块
yum install perl perl-CPAN -y

# 进入perl环境
perl -MCPAN -e shell

# 往perl安装此模板
cpan[1]> install IPC/Cmd.pm


# 解压安装
tar xvf openssl-3.0.8.tar.gz && cd openssl-3.0.8 &&  ./config --prefix=/usr/local/openssl-3.0.8 && make && make install

1.3.4、安装openssl-1.1.1【此python版本使用这教程】

# 下载openssl
wget --no-check-certificate https://www.openssl.org/source/openssl-1.1.1t.tar.gz 

# 安装perl和所需要的模板块
yum install perl

# 解压安装
wget --no-check-certificate https://www.openssl.org/source/openssl-1.1.1t.tar.gz && ./config --prefix=/usr/local/openssl-1.1.1 && make && make install

# 创建软链接,方便管理 ln -s /usr/local/openssl-1.1.1 /usr/local/openssl # 增加动态链接库 echo " /usr/local/openssl/lib" >>/etc/ld.so.conf ldconfig -v # 更换openssl mv /usr/bin/openssl /usr/bin/openssl.old ln -s /usr/local/openssl/bin/openssl /usr/bin/openssl

1.3.5、安装Python软件

tar xvf Python-3.10.10.tgz && cd Python-3.10.10 && ./configure --prefix=/usr/local/Python-3.10.10 --with-openssl=/usr/local/openssl  && make && make install

注意事项:
    Python2 在编译安装时,可以通过参数 --enable-unicode=ucs2 或 --enable-unicode=ucs4,分别用于指定使用2个字节,4个字节表示一个unicode字符。
    Python3 无需进行选择,默认使用ucs4。

# 查看当前Python中表示unicode字符串时占用的空间
import sys
print(sys.maxunicode)
#如果值是 65535 ,表示使用ucs4标准,即:2个字节表示
#如果值是 1114111 ,表示使用ucs4标准,即:4个字节表示

1.3.6、配置Python动态链接库

cat >/etc/ld.so.conf.d/Python-3.10.10.conf <<'EOF'
/usr/local/Python-3.10.10/lib/
EOF
ldconfig 

1.3.7、配置环境变量

ln -s /usr/local/Python-3.10.10/bin/python3 /usr/bin/python3
ln -s /usr/local/Python-3.10.10/bin/pip3 /usr/bin/pip3

1.4、安装ansible

1.4.1、安装

# 创建副本
python3 -m venv ansible-env

# 加载该环境
source ansible-env/bin/activate

# 安装ansible
python3 -m pip install --upgrade pip
python3 -m pip install ansible

# 检查安装的版本
[root@ansible-control bin]# pip list
Package Version
------------ -------
ansible 7.2.0
ansible-core 2.14.2
cffi 1.15.1
cryptography 39.0.1
Jinja2 3.1.2
MarkupSafe 2.1.2
packaging 23.0
pip 23.0.1
pycparser 2.21
PyYAML 6.0
resolvelib 0.8.1

 

1.4.2、创建配置目录、配置主机组

# 创建配置文件目录
mkdir /etc/ansible/

# 使用密码登陆
cat > /etc/ansible/hosts << 'EOF'
[web1]
192.168.10.13 ansible_ssh_user=root ansible_ssh_pass='root1234'
[nfs1]
192.168.10.14 ansible_ssh_user=root ansible_ssh_pass='root1234'
EOF

1.4.3、检查是否加载配置成功

(ansible-env) [root@ansible-control ~]# ansible all --list-hosts
  hosts (2):
    192.168.10.13
    192.168.10.14

1.4.4、ping所有主机是否是通

yum install sshpass -y

 (ansible-env) [root@ansible-control ~]# ansible all -m ping
192.168.10.14 | SUCCESS => {
    "ansible_facts": {
        "discovered_interpreter_python": "/usr/bin/python"
    },
    "changed": false,
    "ping": "pong"
}
192.168.10.13 | SUCCESS => {
    "ansible_facts": {
        "discovered_interpreter_python": "/usr/bin/python"
    },
    "changed": false,
    "ping": "pong"
}

1.4.5、ansible常用命令参数

[root@ansible-control ~]# ansible --version
ansible [core 2.14.2]
  # 配置文件位置
  config file = /etc/ansible/ansible.cfg
  # 模板搜索位置
  configured module search path = ['/root/.ansible/plugins/modules', '/usr/share/ansible/plugins/modules']
  ansible python module location = /usr/local/Python-3.10.10/ansible-env/lib/python3.10/site-packages/ansible
  ansible collection location = /root/.ansible/collections:/usr/share/ansible/collections
  executable location = /usr/local/Python-3.10.10/ansible-env/bin/ansible
  python version = 3.10.10 (main, Feb 19 2023, 21:10:13) [GCC 4.8.5 20150623 (Red Hat 4.8.5-44)] (/usr/local/Python-3.10.10/ansible-env/bin/python3)
  jinja version = 3.1.2
  libyaml = True


# 常用的命令
[root@ansible-control ~]# ansible --help
# 模板参数
#使用的模块参数,模块的具体动作参数
-a MODULE_ARGS, --args MODULE_ARGS
                    The action's options in space separated k=v format: -a
                    'opt1=val1 opt2=val2' or a json string: -a '{"opt1": "val1",
                    "opt2": "val2"}'

#提示输入ssh密码,而不使用基于ssh的密钥认证#模拟执行测试,但不会真的执行
-k, --ask-pass        ask for connection password

# 指定主机清单文件
-i INVENTORY
                    
# 模拟执行测试
-C, --check     don't make any changes; instead, try to predict some of the changes that may occur    

# 模板名字    (default=command)                    
-m MODULE_NAME, --module-name MODULE_NAME
                    
#执行命令的超时
-T TIMEOUT, --timeout TIMEOUT

#显示详细信息
-v, --verbose       包含插件日志 -vvvvvv.
                    正常日志 -vvv
                    debug -vvvv

1.4.6、普通用户需要配置提权的方法

# 普通用户需要配置提权的方法
[root@ansible-control ~]# cat /etc/ansible/ansible.cfg 
[privilege_escalation]
become_ask_pass=False
become_method=sudo
become_user=root

1.4.7、配置子组

[root@ansible-control ~]# cat /etc/ansible/hosts 
[web1]
192.168.10.13

[nfs1]
192.168.10.14

[webnfs:children]
web1
nfs1

2、ansible认证方式

# 关闭key检查
cat >> /etc/ansible/ansible.cfg << 'EOF'
[defaults]
# (boolean) Set this to "False" if you want to avoid host key checking by the underlying tools Ansible uses to connect to the host
host_key_checking=False
EOF

2.1、基于主机密码认证

2.1.2、配置方法

# 旧版本配置
ansible_ssh_user
ansible_ssh_pass
ansible_ssh_port

# 旧版本配置
ansible_user
ansible_password
ansible_port

# 新版兼容旧版的配置,配置如下:

cat >/etc/ansible/hosts <<'EOF' 
[web1]
192.168.10.13 ansible_ssh_user=root ansible_ssh_pass='root1234' ansible_ssh_port=22

[nfs1]
192.168.10.14 ansible_user=root ansible_password='root1234' ansible_port=22
EOF

2.1.2、测试验证

(ansible-env) [root@ansible-control ~]# ansible all -m ping
192.168.10.14 | SUCCESS => {
    "ansible_facts": {
        "discovered_interpreter_python": "/usr/bin/python"
    },
    "changed": false,
    "ping": "pong"
}
192.168.10.13 | SUCCESS => {
    "ansible_facts": {
        "discovered_interpreter_python": "/usr/bin/python"
    },
    "changed": false,
    "ping": "pong"
}

2.2、基于公密钥-免密认证

2.2.1、配置方法

[root@ansible-control ~]# cat /etc/ansible/hosts
[web1]
192.168.10.13

[nfs1]
192.168.10.14 

2.2.2、配置免密登陆

# 在ansible控制主机创建的密钥文件
[root@ansible-control ~]# ssh-keygen -t rsa -b 2048

# 将公钥复制到免密登陆的主机节点
[root@ansible-control ~]# ssh-copy-id root@192.168.10.13
# 需要输入登陆密码

[root@ansible-control ~]# ssh-copy-id root@192.168.10.14
# 需要输入登陆密码

2.2.3、测试验证

(ansible-env) [root@ansible-control ~]# ansible all -m ping
192.168.10.14 | SUCCESS => {
    "ansible_facts": {
        "discovered_interpreter_python": "/usr/bin/python"
    },
    "changed": false,
    "ping": "pong"
}
192.168.10.13 | SUCCESS => {
    "ansible_facts": {
        "discovered_interpreter_python": "/usr/bin/python"
    },
    "changed": false,
    "ping": "pong"
}

3、Ansible查询帮忙

3.1、查询模板使用方法

[root@ansible-control ~]# ansible-doc -s ping
- name: Try to connect to host, verify a usable python and return `pong' on success
  ping:
      data:                  # Data to return for the `ping' return value. If this parameter is set to `crash', the module will cause an exception.

3.2、查询所有模板

[root@ansible-control ~]# ansible-doc -l
amazon.aws.autoscaling_group                                                                    Create or delete AWS AutoScaling Groups (ASGs)                                         
amazon.aws.autoscaling_group_info                                                               Gather information about EC2 Auto Scaling Groups (ASGs) in AWS                         
amazon.aws.aws_az_info                                                                          Gather information about availability zones in AWS   
...

4、模块

4.1、command

此模块是不支持管道符过滤,一般使用shell模块

4.1.1、给远程主机创建文件、查看、删除

# 创建文件
[root@ansible-control ~]# ansible nfs1 -m command -a 'touch /root/test.txt'
192.168.10.14 | CHANGED | rc=0 >>

# 查看是否创建成功
[root@ansible-control ~]# ansible nfs1 -m command -a 'ls -l /root'
192.168.10.14 | CHANGED | rc=0 >>
-rw-r--r-- 1 root root 0 Feb 23 11:46 test.txt

# 删除文件
[root@ansible-control ~]# ansible nfs1 -m command -a 'rm -f /root/test.txt'
192.168.10.14 | CHANGED | rc=0 >>

# 查看是否删除成功
[root@ansible-control ~]# ansible nfs1 -m command -a 'ls -l /root'
192.168.10.14 | CHANGED | rc=0 >>
total 0

4.2、shell

支持复杂语法,如管道符、过滤等

4.2.1、查ens33网卡的子网掩码信息

[root@ansible-control ~]# ansible nfs1 -m shell -a "ifconfig ens33 | grep netmask"
192.168.10.14 | CHANGED | rc=0 >>
        inet 192.168.10.14  netmask 255.255.255.0  broadcast 192.168.10.255

4.3、script

4.3.1、调用nfs1组安装wget脚本

mkdir /opt/script

cat > /opt/script/install_wget.sh <<'EOF'
#!/bin/bash
yum install wget -y
EOF

# 把控制机的脚本,发往被控制主机运行脚本
ansible nfs1 -m script -a '/opt/script/install_wget.sh'

4.4、yum

4.4.1、参数介绍

name=              # rpm名字
state=             # 安装(`present' or `installed', `latest'), 删除 (`absent' or `removed')
enablerepo=        # 指定仓库安装
disablerepo=       # 禁用指定仓库安装
list=              # 查询rpm包信息
download_only=true # 仅下载软件包,不安装
exclude # 排除安装的包

4.4.2、安装

ansible web1 -m yum -a 'name=wget state=present'

4.4.3、安装rpm包

ansible web1 -m yum -a 'name=https://repo.zabbix.com/zabbix/6.2/rhel/7/x86_64/zabbix-agent2-6.2.1-1.el7.x86_64.rpm state=installed'

4.4.4、更新

ansible web1 -m yum -a 'name=wget state=latest'

4.4.5、删除

ansible web1 -m yum -a 'name=wget state=removed'

4.4.6、查询

ansible web1 -m yum -a 'list=wget'

4.4.7、指定仓库安装

ansible web1 -m yum -a 'name=epel-release state=installed'
ansible web1 -m yum -a "list=ansible enablerepo=epel"

4.5、copy

4.5.1、参数介绍

src     # 推送数据的源文件信息
dest    # 推送数据的目标路径
backup  # 对推送传输过去的文件,进行备份
content # 直接批量在被管理端文件中添加内容
group   # 将本地文件推送到远端,指定文件属组信息
owner   # 将本地文件推送到远端,指定文件属主信息
mode    # 将本地文件推送到远端,指定文件权限信息

4.5.2、复制文件

ansible nfs1 -m copy -a "src=/etc/hosts dest=/tmp/test.txt"

4.5.3、复制文件并且备份

# 如果文件内容变化则,备份文件
ansible nfs1 -m copy -a "src=/etc/hosts dest=/tmp/test.txt backup=yes"

4.5.4、content内容写入硬盘

ansible nfs1 -m copy -a "content=hello dest=/tmp/test.txt"

4.5.5、复制文件并且设置权限

 ansible nfs1 -m copy -a "src=/etc/hosts dest=/tmp/test.txt owner=nobody group=nobody mode=600"

4.6、file

4.6.1、参数介绍

path    # 文件路径
state   # 删除"absent"、目录"directory"、文件"file"、硬链接"hard"、软链接"link"、创建文件"touch"
owner   # 所属者
recurse # 递归操作 state=directory
group   # 组
mode    # 权

4.6.2、创建目录

ansible nfs1 -m file -a "path=/tmp/1/2/3 state=directory"

4.6.3、创建文件

ansible nfs1 -m file -a "path=/tmp/touch.txt state=touch"

4.6.4、创建目录并且修改权限

# 注意:如目录存在,则只修改权限

# 只修改目录权限,不会修改目录里面文件的权限
ansible nfs1 -m file -a "path=/tmp/nfs/ state=directory owner=nobody"

# 目录权限以及目录所有文件的权限
ansible nfs1 -m file -a "path=/tmp/nfs/ state=directory owner=nobody recurse=true"

4.7、get_url

4.7.1、参数介绍

作用:下载HTTP, HTTPS, FTP的文件

url      # 下载地址
dest     # 保存的位置
checksum # md5校验

4.7.2、下载文件

ansible nfs1 -m get_url -a "url=https://repo.zabbix.com/zabbix/6.2/rhel/7/x86_64/zabbix-release-6.2-3.el7.noarch.rpm dest=/tmp validate_certs=false"

4.8、yum_repository

4.8.1、参数介绍

作用:配置yum仓库
name          # yum源名字
baseurl       # yum的地址
file          # 指定yum配置文件的路径和名称。
enable yes/no # 是否开启yum源
state         # absent(删除)/present(安装,默认)

4.8.2、给控制主机配置zabbix源

ansible nfs1 -m yum_repository -a 'name=zabbix description="php repo" baseurl=http://repo.zabbix.com/zabbix/3.2/rhel/7/x86_64/ enabled=yes state=present'

4.9、service

4.9.1、参数介绍

作用:管理服务的启动与停止,开机自启动

name          # 服务名字
state
    started   # 启动服务
    stopped   # 停止服务
    restarted # 重启服务
    reloaded  # 重新加载服务
enabled       # 开机自启动

4.9.2、启动&开启开机自启动

ansible nfs1 -m service -a 'name=crond state=started enabled=yes

4.9.3、停止&关闭开机自启动

ansible nfs1 -m service -a 'name=crond state=stopped enabled=no'

4.9.4、重启

ansible nfs1 -m service -a 'name=crond state=restarted'

4.9.5、重新加载

ansible nfs1 -m service -a 'name=crond state=reloaded'

4.10、group

4.10.1、参数介绍

作用:创建系统的组

name # 指定创建的组名
gid # 指定组的gid
state
absent # 删除远端的主机的组
present # 创建远端的主机的组

4.10.2、创建组

ansible nfs1 -m group -a 'name=nfs gid=1200'

4.11、user

4.11.1、参数介绍

创建用户

uid         # 指定用户ID
group       # 指定用户组的名称
groups      # 指定用户组的名移,可以指定多个
password    # 用户的密码(记得单引号括起来)
shell       # 指定用户的登陆shell
create_home # 是否创建家目录

4.11.2、创建nfs用户指定组并且不创建家目录

ansible nfs1 -m user -a 'name=nfs uid=1200 group=1200 shell=/sbin/nologin create_home=no'

4.11.3、删除nfs用户

ansible nfs1 -m user -a 'name=nfs state=absent'

4.11.4、创建用户并且生成密钥对

ansible nfs1 -m user -a 'name=nfs uid=1200 group=nfs generate_ssh_key=yes ssh_key_bits=2048 ssh_key_file=.ssh/id_rsa'

4.11.5、创建用户并且设置密码

# 设置密码
[root@ansible-control ~]# ansible localhost -m debug -a "msg={{ '123456' | password_hash('md5','salt') }}"
[DEPRECATION WARNING]: Encryption using the Python crypt module is deprecated. The Python crypt module is deprecated and will be removed from Python 3.13. Install 
the passlib library for continued encryption functionality. This feature will be removed in version 2.17. Deprecation warnings can be disabled by setting 
deprecation_warnings=False in ansible.cfg.
localhost | SUCCESS => {
    "msg": "$1$salt$638tR8bROOvPnPklDQ9Vf/"
}

# 创建用户
ansible nfs1 -m user -a 'name=nfs password="$1$salt$638tR8bROOvPnPklDQ9Vf/" shell=/bin/bash create_home=yes shell=/bin/bash'

4.12、cron

4.12.1、参数介绍

name    # 任务名字
state   # [删除 absent, 增加 present]
job     # 命令
minute  # 分钟
hour    # 小时
day     # 每天
month   # 月
weekday # 每周几

disabled # 禁用定时任务 

# 安装ntpdate工具,定时同步时间,用于演示
ansible nfs1 -m yum -a 'name=ntpdate state=present'

4.12.2、增加定时任务

ansible nfs1 -m cron -a 'name=time ntpdate sync state=present minute=*/1 job=/usr/sbin/ntpdate ntp5.aliyun.com  2>&1 > /dev/null"

[root@ansible-control ~]# ansible nfs1 -m command -a 'crontab -l'
192.168.10.14 | CHANGED | rc=0 >>
#Ansible: time ntpdate sync
*/1 * * * * /usr/sbin/ntpdate ntp5.aliyun.com  2>&1 > /dev/null

4.12.3、删除定时任务

ansible nfs1 -m cron -a "name='time ntpdate sync' state=absent"

4.12.4、注释定时任务

ansible nfs1 -m cron -a "name='time ntpdate sync' disabled=yes minute=*/1 job='/usr/sbin/ntpdate ntp5.aliyun.com  2>&1 > /dev/null'"

(ansible-env) [root@ansible-control ~]# ansible nfs1 -m command -a 'crontab -l'
192.168.10.14 | CHANGED | rc=0 >>
#Ansible: time ntpdate sync
#*/1 * * * * /usr/sbin/ntpdate ntp5.aliyun.com  2>&1 > /dev/null

4.13、mount

4.13.1、参数介绍

作用:挂载硬盘,支持设置开机自动挂的功能

src       # 挂载哪个硬盘
path      # 挂载路径
fstype    # 文件系统类型

state
present   # 开机挂载,仅将挂载配置写入/etc/fstab
mounted   # 挂载设备,并将配置写入/etc/fstab
unmounted # 卸裁设备,不会清除/etc/fstab写入的配置
absent    # 卸载设备,会清理/etc/fstab写入的配置

4.13.2、挂载nfs的实践

# 安装nfs服务
ansible nfs1 -m yum -a 'name=nfs-utils state=present'

# 创建共享的目录
ansible nfs1 -m file -a 'path=/data state=directory'

# 配置共享的目录
ansible nfs1 -m copy -a 'content="/data 192.168.10.0/24(rw,sync,no_all_squash)" dest=/etc/exports'

# 启动nfs服务【两个命令都是一样作用,选择其一即可】
ansible nfs1 -m systemd -a 'name=nfs state=started enabled=yes'
ansible nfs1 -m service -a 'name=nfs state=started enabled=yes'

# 将nfs挂载至web服务器上
ansible web1 -m mount -a 'src=192.168.10.14:/data path=/data fstype=nfs state=mounted'

# 卸载nfs,不会删除开机自启动
ansible web1 -m mount -a 'src=192.168.10.14:/data path=/data fstype=nfs state=unmounted'

# 完整卸载nfs
ansible web1 -m mount -a 'src=192.168.10.14:/data path=/data fstype=nfs state=absent'

4.14、firewalld

4.14.1、参数介绍

作用:firewalld防火墙的配置

service    # 指定开放或关闭的服务名称
port       # 指定开放或关闭的端口
masquerade # 开启地址伪装
immediate  # 临时生效
permanent  # 是否添加永久生效
state      # 开启或是关闭
zone       # 指定配置某个区域
rich_rule  # 配置富规则
source     # 指定来源IP

4.14.2、放行指定的端口与服务

# 开启firewalld服务
ansible web1 -m systemd -a 'name=firewalld state=started'

# 放行http服务
ansible web1 -m firewalld  -a 'service=http immediate=yes permanent=yes state=enabled'

# 放行8080-8090的端口
ansible web1 -m firewalld -a 'port=8080-8090/tcp immediate=yes permanent=yes state=enabled'

4.15、selinux

4.15.1、开启

ansible web1 -m selinux -a 'state=enforcing'

4.15.2、关闭

ansible web1 -m selinux -a 'state=disabled'

4.16、iptables

4.16.1、安装iptables

# 安装iptables
systemctl disable firewalld
systemctl stop firewalld

yum install iptables-services
systemctl start iptables

4.16.2、放行80端口的配置

[root@ansible-control ~]# ansible web1 -m iptables -a 'action=insert table=filter chain=INPUT protocol=tcp source=192.168.10.0/24  destination_port=80 jump=ACCEPT state=present'
192.168.10.13 | CHANGED => {
    "ansible_facts": {
        "discovered_interpreter_python": "/usr/bin/python"
    },
    "chain": "INPUT",
    "chain_management": false,
    "changed": true,
    "flush": false,
    "ip_version": "ipv4",
    "rule": "-p tcp -s 192.168.10.0/24 -j ACCEPT --destination-port 80",
    "state": "present",
    "table": "filter"
}

# 增加
state=present
# 删除 state
=absent

# 插入规则
action=insert
# 追加规则
action=append

4.14.17、实践安装nginx

# 1、配置nginx yum源
ansible web1 -m yum_repository -a 'name=nginx description="nginx repo" baseurl=http://nginx.org/packages/centos/7/x86_64/ enabled=no gpgkey=https://nginx.org/keys/nginx_signing.key gpgcheck=true state=present'

# 2、安装nginx
ansible web1 -m yum -a 'name=nginx state=present enablerepo=nginx'

# 3、修改html内容 
ansible web1 -m copy -a 'content="hello test nginx" dest=/usr/share/nginx/html/index.html backup=yes'

# 4、启动nginx服务
ansible web1 -m systemd -a 'name=nginx state=started enabled=yes'

# 5、放开80端口
ansible web1 -m iptables -a 'action=insert table=filter chain=INPUT protocol=tcp source=192.168.10.0/24  destination_port=80 jump=ACCEPT state=present'

5、ansible-playbook

5.1、playbook入门语法介绍

5.1.1、yaml语法的介绍

缩进:YAML使用固定的缩进风格表示层级结构,每个缩进由两个空格组成,不能使用tabs
冒号:以冒号结尾的除外,其他所有冒号后面所有必须有空格。
短横线:表示列表项,使用一个短横杠加一个空格。多个项使用同样的缩进级别作为同一列表。

5.1.2、playbook常用关键字的介绍

host             # 对哪些主机进行操作
remote_user      # 我要使用什么用户执行
tasks            # 具体执行什么任务

5.2、playbook入门示例

5.2.1、查询所有主机名

# 1、Ad-hoc[点对点模板]的语法
ansible all -m command -a 'hostname'

# 2、创建存放playbook的文件目录
mkdir /opt/playbook && cd /opt/playbook

# 3、编写playbook
cat > query_hostname.yaml <<'EOF' 
---
- name: query all hostname
  hosts: all
  remote_user: root

  tasks:
  - name: execute hostname commond
    command: hostname
EOF

# 4、检查playbook语法是否正确
ansible-playbook query_hostname.yaml -C

5.2.2、创建一个文件的示例

# 1、Ad-hoc[点对点模板]的语法
ansible all -m file -a 'name=/tmp/test_all.txt state=touch'

# 2、创建一个文件的playbook
cat > create_file.yaml << 'EOF'
---
- name: touch file
  hosts: all
  remote_user: root
  vars:
    file_name: cyc_test

  tasks:
  - name: exe file mod
    file: name=/tmp/{{file_name}} state=touch
EOF

# 3、执行或调试测试
ansible-playbook create_file.yaml -C
ansible-playbook create_file.yaml

5.3、nfs-playbook实践

5.3.1、安装nfs

# 创建nfs配置文件
cat > exports.0225 <<'EOF'
/data 192.168.10.0/24(rw,sync,no_all_squash)
EOF

# 编写安装nfs的playbook
cat > nfs_install.yaml <<'EOF' 
---
- name: install nfs package
  hosts: nfs1,web1
  remote_user: root

  tasks:
  - name: install nfs server
    yum: name=nfs-utils,rpcbind state=installed

- name: configure nfs server
  hosts: nfs1
  remote_user: root

  tasks:
  - name: configure nfs1
    copy: src=./exports.0225 dest=/etc/exports

  - name: create share directory
    file: path=/data state=directory owner=nfsnobody group=nfsnobody recurse=yes

  - name: start rpcbind server
    systemd: name=rpcbind state=started enabled=yes

  - name: start nfs server
    systemd: name=nfs state=started enabled=yes

- name: mount nfs dir
  hosts: nfs1,web1
  remote_user: root

  tasks:
  - name: mount dir
    mount: src=192.168.10.14:/data path=/mnt/nfs_data fstype=nfs state=mounted
EOF

# 查看是否挂载成功
[root@ansible-control playbook]# ansible all -m command -a 'tail -1 /etc/fstab'
192.168.10.14 | CHANGED | rc=0 >>
192.168.10.14:/data /mnt/nfs_data nfs defaults 0 0
192.168.10.13 | CHANGED | rc=0 >>
192.168.10.14:/data /mnt/nfs_data nfs defaults 0 0

5.3.2、卸载nfs

cat > nfs_uninstall.yaml <<'EOF'
---
- name: unmount nfs dir
  hosts: nfs1,web1
  remote_user: root
  tasks:
  - name: unmount dir
    mount: src=192.168.10.14:/data path=/mnt/nfs_data fstype=nfs state=absent

- name: configure nfs server
  hosts: nfs1
  remote_user: root

  tasks:
  - name: delete exports
    file: path=/etc/exports state=absent

  - name: delete directory
    file: path=/data state=absent

  - name: stop nfs server
    systemd: name=nfs state=stopped enabled=no

  - name: stop rpcbind server
    systemd: name=rpcbind state=stopped enabled=no

- name: uninstall nfs package
  hosts: nfs1,web1
  remote_user: root
tasks:
- name: uninstall nfs server yum: name=nfs-utils,rpcbind state=absent EOF

5.3.3、安装nfs【notify、handler】

cat > nfs_notify_install.ymal << 'EOF' 
---
- name: install nfs package
  hosts: nfs1,web1
  remote_user: root
  tasks:
  - name: install nfs server
    yum:
      name: nfs-utils,rpcbind
      state: installed

- name: configure nfs server
  hosts: nfs1
  remote_user: root

  tasks:
  - name: configure nfs1
    copy:
      src: ./exports.0225
      dest: /etc/exports
      backup: yes

  - name: create share directory
    file:
      path: /data
      state: directory
      owner: nfsnobody
      group: nfsnobody
      recurse: yes

  - name: start rpcbind server
    systemd:
      name: rpcbind
      state: started
      enabled: yes

  - name: start nfs server
    systemd:
      name: nfs
      state: started
      enabled: yes

- name: mount nfs dir
  hosts: nfs1,web1
  remote_user: root
  vars:
    umount_path: /opt/nfs_data
    mount_path: /opt/nfs_share
  tasks:
  - name: mount dir
    mount:
      src: 192.168.10.14:/data
      path: "{{mount_path}}"
      fstype: nfs
      state: mounted
    notify:
      - nfs absent
      - nfs mounted

  handlers:
  - name: nfs absent
    mount:
      src: 192.168.10.14:/data
      path: "{{umount_path}}"
      fstype: nfs
      state: absent

  - name: nfs mounted
    mount:
      src: 192.168.10.14:/data
      path: "{{mount_path}}"
      fstype: nfs
      state: mounted
EOF

5.4、nginx-playbook实践

5.4.1、安装nginx playbook

cat > www.conf << 'EOF' 
server {
  listen 80;
  server_name ansible.test.com;
  location / {
    root /usr/share/nginx/html;
    index index.html;
  }
}
EOF

cat > nginx_install.yaml << 'EOF'
---
- name: install nginx
  hosts: web1
  remote_user: root
  tasks:
  - name: configure nginx repo
    yum_repository:
      name: nginx
      description: "nginx repo"
      enabled: no
      baseurl: http://nginx.org/packages/centos/7/x86_64/
      gpgkey: https://nginx.org/keys/nginx_signing.key
      gpgcheck: true
      state: present

  - name: install nginx
    yum:
      name: nginx
      state: present
      enablerepo: nginx

  - name: edit index.html
    copy:
      content: "playbook install show"
      dest: /usr/share/nginx/html/index.html
      backup: yes

  - name: config nginx
    copy:
      src: ./www.conf
      dest: /etc/nginx/conf.d/default.conf
      backup: yes

  - name: start nginx service
    systemd:
      name: nginx
      state: started
      enabled: yes

  - name: pass 80 port
    iptables:
      action: insert
      table: filter
      chain: INPUT
      protocol: tcp
      source: 192.168.10.0/24
      destination_port: 80
      jump: ACCEPT
      state: present
EOF

5.4.2、安装nginx playbook【notify、handler】

notify # 监听文件是否变化,变化则执行handlers里面对应的任务
handlers

cat > www.conf << 'EOF' 
server {
  listen 80;
  server_name ansible.test.com;
  location / {
    root /usr/share/nginx/html;
    index index.html;
  }
}
EOF

cat nginx_install.yaml 
---
- name: install nginx
  hosts: web1
  remote_user: root
  tasks:
  - name: configure nginx repo
    yum_repository:
      name: nginx
      description: "nginx repo"
      enabled: no
      baseurl: http://nginx.org/packages/centos/7/x86_64/
      gpgkey: https://nginx.org/keys/nginx_signing.key
      gpgcheck: true
      state: present

  - name: install nginx
    yum:
      name: nginx
      state: present
      enablerepo: nginx

  - name: edit index.html
    copy:
      content: "playbook install show notify"
      dest: /usr/share/nginx/html/index.html
      backup: yes
    notify: Restart Nginx

  - name: config nginx
    copy:
      src: ./www.conf
      dest: /etc/nginx/conf.d/default.conf
      backup: yes
    notify: Restart Nginx

  - name: start nginx service
    systemd:
      name: nginx
      state: started
      enabled: yes

  - name: pass 80 port
    iptables:
      action: insert
      table: filter
      chain: INPUT
      protocol: tcp
      source: 192.168.10.0/24
      destination_port: 80
      jump: ACCEPT
      state: present

  handlers:
    - name: Restart Nginx
      systemd:
        name: nginx
        state: restarted

5.5、ansible变量

5.5.1、ymal文件内定义变量

cat > var_ymal.yaml << 'EOF'
---
- hosts: nfs1,web1
  vars:
    - nc_pkg: nc
    - nmap_pkg: nmap
  tasks:
    - name: Install nc nmap pkg
      yum:
        name:
          - "{{nc_pkg}}"
          - "{{nmap_pkg}}"
        state: present
EOF

5.5.2、外部ymal文件内定义变量

cat > vars.yaml << 'EOF' 
nc_pkg: nc
nmap_pkg: nmap
EOF

cat > var_ymal.yaml << 'EOF' 
---
- hosts: nfs1,web1
  vars_files: ./vars.yaml
  tasks:
    - name: Install nc nmap pkg
      yum:
        name:
          - "{{nc_pkg}}"
          - "{{nmap_pkg}}"
        state: present
EOF

5.5.3、从/etc/ansible/hosts定义变量

cat > /etc/ansible/hosts << 'EOF' 
[web1]
192.168.10.13

[nfs1]
192.168.10.14

[webnfs:children]
web1
nfs1

[webnfs:vars]
nc_pkg=nc
nmap_pkg=nmap
EOF

cat > var_ymal.yaml << 'EOF' 
---
- hosts: nfs1,web1
  tasks:
    - name: Install nc nmap pkg
      yum:
        name:
          - "{{nc_pkg}}"
          - "{{nmap_pkg}}"
        state: present
EOF

5.5.4、按组和主机名定义变量

host_vars  # 文件名就是/etc/ansible/hosts里面定义的主机名
group_vars # 这里的文件名就是/etc/ansible/hosts里面定义的组名

mkdir group_vars
cat > group_vars/webnfs << 'EOF' 
nc_pkg: nc
nmap_pkg: nmap
EOF


cat > /etc/ansible/hosts << 'EOF' 
[web1]
192.168.10.13

[nfs1]
192.168.10.14

[webnfs:children]
web1
nfs1

[webnfs:vars]
nc_pkg=nc
nmap_pkg=nmap
EOF

cat > var_ymal.yaml << 'EOF' 
---
- hosts: nfs1,web1
  tasks:
    - name: Install nc nmap pkg
      yum:
        name:
          - "{{nc_pkg}}"
          - "{{nmap_pkg}}"
        state: present
EOF

5.5.5、注册变量,自定义显示内容

cat > register.yaml <<'EOF'
---
- hosts: all
  tasks:
    - name:
      shell: hostname
      register: run_status
    - name: get run status
      debug:
        msg: "status:{{run_status.rc}} result:{{run_status.stdout}}"
EOF

5.5.6、facts变量

# Facts介绍
Ansible facts是在被管理主机上通过ansible自动采集发现的变量。
facts包含每台特定的主机信息。比如被控端主机的主机名、IP地址、系统版本、CPU数量、内存状态、磁盘状态等。

facts使用场景:
1、通过facts检查CPU,来生成对应的Nginx配置文件。
2、通过facts检查主机名信息,来生成不同的Zabbix配置文件。
3、通过act检索的内存情况来自定义mysql的配置文件。

# 查看主机的详细信息
ansible nfs1 -m setup

# 获取采集信息
cat > facts.yaml <<'EOF' 
---
- hosts: nfs1
  tasks:
    - name: show varibales ansible facts
      debug:
        msg:
        -  "IP地址:{{ansible_default_ipv4.address}}"
        -  "CPU物理核数:{{ansible_processor_cores}}"
        -  "总内存:{{ansible_memtotal_mb}}MB"
EOF


# 关闭采集信息
- hosts: nfs1
  gather_facts: no
  tasks:
    ...
    
# filter用法
ansible nfs1 -m setup -a 'filter="ens33"'
ansible nfs1 -m setup -a 'filter="*ens33*"'

5.6、Task控制

5.6.1、when语法介绍

when使用and或or多条件判断的语法
# OR
when: ( ansible_hostname is match("web*") or ansible_hostname is match("nfs*") )

# AND
when: ( ansible_hostname is match("web*") and ansible_hostname is match("nfs*") )
when:
  - ansible_hostname is match("web*")
  - ansible_hostname is match("nfs*")

5.6.2、when实战1-根据不同操作系统安装相同的软件包

# 根据不同操作系统,安装相同的软件包
cat > when_system.yaml << 'EOF' 
---
- hosts: web1
  tasks:
    - name: Centos install httpd
      yum:
        name:
        - httpd
        state: present
      when: ( ansible_distribution == "CentOS" )
    - name: ubuntu install httpd
      yum:
        name:
        - httpd2
        state: present
      when: ( ansible_distribution == "Ubuntu" )
EOF

5.6.3、when实战2-根据判断主机名配置nginx yum源

cat > when_nginx.yaml << 'EOF' 
---
- name: install nginx
  hosts: all
  remote_user: root
  tasks:
  - name: configure nginx repo
    yum_repository:
      name: nginx
      description: "nginx repo"
      enabled: no
      baseurl: http://nginx.org/packages/centos/7/x86_64/
      gpgkey: https://nginx.org/keys/nginx_signing.key
      gpgcheck: true
      state: present
    when: ( ansible_hostname is match("web*") )
EOF

5.6.4、when实战3-判断httpd服务没有开启则重启服务

cat > when_is_active.yaml <<'EOF'
- hosts: web1
  tasks:
    - name: Check Http Server
      command: systemctl is-active httpd
      ignore_errors: yes
      register: check_httpd

    - name: debug outprint
      debug: var=check_httpd

    - name: Httpd Restart
      systemd:
        name: httpd
        state: restarted
      when: ( check_httpd.rc != 0 )
EOF

5.6.5、loop实战1-使用循环启动多个服务【with_items】

cat > 01_loop.yaml <<'EOF'
- hosts: web1
  tasks:
    - name: restart httpd crond sshd server
      service:
        name: "{{ item }}"
        state: restarted
        enabled: yes
      with_items:
        - httpd
        - crond
        - sshd
EOF

5.6.6、loop实战2-使用自定义变量名的方式循环重启服务【vars】

cat > 02_loop_var.yaml <<'EOF'
- hosts: web1
  tasks:
    - name: install wget lrzsz pkg
      yum:
        name: "{{ pkg_name }}"
        state: present
      vars:
        pkg_name:
          - wget
          - lrzsz
EOF

5.6.7、loop实战3-使用字典循环方式创建多个用户【with_items】

cat > 03_create_user_loop.yaml <<'EOF'
- hosts: web1
  tasks:
    - name: create many user
      user:
        name: "{{ item.name }}"
        groups: "{{ item.groups }}"
        state: present
      with_items:
        - { name: 'test01',groups: 2000 }
        - { name: 'test02',groups: 2000 }
EOF

5.6.8、tags实战1-使用标签控制运行流程

# 语法介绍
--list-tags # 查询yaml标签的数量
-t          # 指定运行的标签
--skip-tags # 忽略运行标签

# 标签示例
cat > nfs_tags.yaml << 'EOF' 
- hosts: nfs1
  remote_user: root
  tasks:
    - name: install nfs server
      yum:
        name: nfs-utils
        state: present
      tags:
        - install_nfs
        - install_nfs_server
    - name: server nfs server
      service:
        name: nfs-server
        state: started
        enabled: yes
      tags: start_nfs_server
EOF

5.6.9、include实战1-文件复用

# 作用:实现配置文件分离,方便管理

# 主配置文件
cat > main.yaml << 'EOF' 
- hosts: all
  remote_user: root
  tasks:
    - include_tasks: create_file_01.yaml
    - include_tasks: create_file_02.yaml
EOF

# create_file_01.yaml
cat > create_file_01.yaml <<'EOF' 
- name: create file 01
  file:
    path: /root/file_01.txt
    state: touch
EOF

# create_file_02.yaml
cat > create_file_02.yaml <<'EOF' 
- name: create file 02
  file:
    path: /root/file_02.txt
    state: touch
EOF

5.6.10、ignore_errros实战1-忽略错误 

cat > test_ignore_errors.yaml <'EOF'
- hosts: all
  tasks:
    - name: Ignore False
      command: /bin/false
      ignore_errors: yes

    - name: touch new file
      file:
        path: /root/ignore.txt
        state: touch
EOF

5.7、JinJa2-模板

5.7.1、语法

{{ 名称 }} # 变量使用名称
{% for i in EXPR %}...{% endfor %}      # 作为循环表达式
{% if EXPR %}...[% elif %}...{% endif%} # 作为条件判断
{# COMMENT #} # 表示注释

5.7.2、template实战1-替换数据分发到其它节点

# 模板文件
cat > motd.j2 << 'EOF' 
hostname: {{ ansible_hostname }}
total_memory is: {{ ansible_memtotal_mb }} MB
EOF

# 编写playbook
cat > cat jinja2_01.yaml << 'EOF' 
- hosts: web1
  tasks:
    - name: copy template file /etc/motd
      template:
        src: ./motd.j2
        dest: /etc/motd
EOF

# 运行结果
[root@ansible-control jinja2]# ansible web1 -m command -a 'cat /etc/motd'
192.168.10.13 | CHANGED | rc=0 >>
hostname: web1
total_memory is: 1819 MB

5.7.3、template实战2-使用for替换nginx模板

cat > jinja2_nginx.yaml << 'EOF' 
- hosts: web1
  vars:
    - server_name: ansible.test.org
    - http_port: 80
  tasks:
    - name: www.conf
      template:
        src: www.j2
        dest: /etc/nginx/conf.d/www.conf
        backup: yes
EOF

cat > www.j2 << 'EOF' 
upstream {{ server_name }} {
{% for i in range(7,10)  %}
    server 192.168.10.{{i}}:{{http_port}}} weight=1 max_fails=3 fail_timeout=30;
{% endfor %}
}

server {
    listen {{http_port}};
    server_name {{server_name}};
    location / {
        proxy_pass http:://{{server_name}};
        proxy_set_header Host $host;
        proxy_set_header X_Forwarded_For;
    }
}
EOF

5.8、Roles

5.8.1、roles介绍

按目录划分模块

5.8.2、实战1-打印hell

# 创建目录
mkdir base/basic/{tasks,templates,handlers,files,group_vars} -p && cd base

# 创建目录
mkdir base/basic/{tasks,templates,handlers,files,group_vars} -p && cd base

# 主入口
cat > run.yaml << 'EOF' 
- hosts: all
  roles:
    - role: basic
EOF

# task任务
cat > basic/tasks/main.yaml << 'EOF'
- name: print hello
  debug:
    msg: "Hello Roles"
EOF

# 目录结构base


├── ── group_vars
 

├── basic
│ ├── files
│ ├── handlers
│ ├── tasks
│ │ └── main.yaml
│ └── templates
└── run.yaml

6、playbook-项目

6.1、基础环境配置

# 入口
cat > run.yaml <<'EOF'
- hosts: all
  roles:
    - role: basic
EOF

# 目录结构
mkdir -p base/basic/{files,tasks,templates,handlers}
mkdir -p base/{group_vars}
tree /opt/playbook/base
├── base
│   ├── basic
│   │   ├── files
│   │   ├── handlers
│   │   ├── tasks
│   │   │   └── main.yaml
│   │   └── templates
│   ├── group_vars
│   │   └── all
cat > basic/tasks/main.yaml << 'EOF'
- name: set base yum repo
  yum_repository:
    name: CentOS-Base
    baseurl: http://mirrors.aliyun.com/centos/7.9.2009/os/x86_64/
    description: "Base repo"
    enabled: yes
    gpgkey: http://mirrors.aliyun.com/centos/RPM-GPG-KEY-CentOS-7
    gpgcheck: true
    state: present

- name: epel yum repo
  yum_repository:
    name: epel
    baseurl: http://mirrors.aliyun.com/epel/7/x86_64/
    description: "epel repo"
    enabled: no
    gpgkey: file:///etc/pki/rpm-gpg/RPM-GPG-KEY-EPEL-7 
    gpgcheck: false
    state: present

- name: zabbix yum repo
  yum_repository:
    name: zabbix
    baseurl: http://repo.zabbix.com/zabbix/3.2/rhel/7/x86_64/
    description: "zabbix repo"
    enabled: no
    state: present

- name: configure nginx repo
  yum_repository:
    name: nginx
    description: "nginx repo"
    enabled: no
    baseurl: http://nginx.org/packages/centos/7/x86_64/
    gpgkey: https://nginx.org/keys/nginx_signing.key
    gpgcheck: true
    state: present

- name: configure nginx repo
  yum_repository:
    name: php
    description: "php repo"
    enabled: no
    baseurl: https://us-east.repo.webtatic.com/yum/el7/x86_64/
    state: present

- name: install base software
  yum:
    name:
      - tree
      - vim
      - lrzsz
      - unzip
      - psmisc
      - net-tools
      - nc
      - nmap
      - ntpdate
    state: present

- name: stop firewalld
  systemd:
    name: firewalld
    state: stopped
    enabled: no

- name: disable selinux
  selinux:
    state: disabled

- name: groupadd
  group:
    name: www_nginx
    gid: 2000

- name: useradd
  user:
    name: www_nginx
    group: www_nginx
    shell: /sbin/nologin
    create_home: no

- name: config sync time
  cron:
    name: ali sync time
    minute: "*/2"
    job: "/sbin/ntpdate ntp1.aliyum.com &>/dev/null"
EOF

6.2、playbook-nginx安装

# 创建新目录
mkdir -p base/nginx/{files,tasks,templates,handlers}
mkdir -p base/{group_vars}

# 复制nginx 配置文件
scp root@192.168.10.13:/etc/nginx/nginx.conf /opt/playbook/base/nginx/templates/

# 目前只把下面两个值设置为变量
cat base/nginx/templates/nginx.conf.j2 
...
user {{ user }};
worker_processes {{ ansible_processor_vcpus }};
...

# 设置变量
cat > base/group_vars/all << 'EOF' 
user: www_nginx
EOF

# 运行入口
cat > base/run.yaml <<'EOF' 
- hosts: all
  roles:
    - role: basic
- hosts: web1
  roles:
    - role: nginx
EOF

# 定义运行任务
cat > base/nginx/tasks/main.yaml <<'EOF'
- name: install nginx
  yum:
    name: nginx
    state: present
    enablerepo: "nginx"

- name: copy configure nginx file
  template:
    src: nginx.conf.j2 
    dest: /etc/nginx/nginx.conf
    backup: yes
  notify:
    - restart nginx

- name: start nginx
  systemd:
    name: nginx
    state: started
    enabled: yes 
EOF

# 定义handlers
cat > base/nginx/handlers/main.yaml << 'EOF'
- name: restart nginx
  systemd:
    name: nginx
    state: reloaded
EOF

 

posted @ 2023-02-27 21:33  小粉优化大师  阅读(297)  评论(0编辑  收藏  举报