kylin-ansible自动化

ansible自动化

一、ansible主机架构

1、连接插件 connection plugins 用于连接主机 用来连接被管理端
2、核心摸块 core modues 连接主机实现操作,它依赖于具体的模块来做具体的事情
3、自定义模块 custom modules 根据自己的需求编写具体的模块
4、插件 plugins 完成模块功能的补充
5、剧本 playbook ansible的配置文件,将多个任务定义在剧本中,由ansible自动执行
6、主机清单 invenlory 定义ansible需要操作主机的范围
最重要的一点是 ansible是模块化的 它所有的操作都依赖于模块

二、安装配置ansible

第一步:安装
Centos系统直接yum安装或pip安装
kylin系统使用如下步骤安装:
1.yum -y install ansible
2.编译安装Python3.8
1)下载Python3.8安装包
wget https://www.python.org/ftp/python/3.8.2/Python-3.8.2.tar.xz
2)解压缩
xz -d Python-3.8.2.tar.xz
tar xvf Python-3.8.2.tar
3)配置
cd /root/Python-3.8.2
./configure --prefix=/usr/local/python38 --enable-shared
4)编译安装
 make && make install
5)配置python3.8的lib到ldconfig
vi /etc/ld.so.conf.d/python3.conf,添加如下内容
/usr/local/python38/lib
然后执行:ldconfig
6)创建Python软链接
ln -s /usr/local/python38/bin/pip3 /usr/local/bin/pip3
ln -s /usr/local/python38/bin/python3 /usr/local/bin/python3
7)设置PATH
echo 'export PATH=/usr/local/bin:$PATH' >> /etc/profile
8) 重新加载环境变量
source /etc/profile
到此,Python3.8环境安装完毕~
python3 -V  #查看python版本
3.pip3 install ansible

第二步:配置
[root@ansible ~]# cat /etc/ansible/ansible.cfg 
#[defaults]
#跳过检查主机指纹
#不显示弃用警告
#指定Python解释器的路径
[defaults]
host_key_checking = False				
deprecation_warnings = False			
interpreter_python = /usr/bin/python3	
[inventory]
[privilege_escalation]
[paramiko_connection]
[ssh_connection]
[persistent_connection]
[accelerate]
[selinux]
[colors]
[diff]

三、Ansible主机清单---Inventory

  • /etc/ansible/hosts 是ansible默认主机资产清单文件,用于定义被管理主机的认证信息, 例如ssh登录用户名、密码以及key相关信息。Inventory文件中填写需要被管理的主机与主机组信息。
  • 还可以自定义Inventory主机清单的位置,使用-i指定文件位置即可。

1.基于用户密码方式连接

使用用户名和密码定义主机清单

  • 语法格式
IP  ansible_ssh_user=  ansible_ssh_port=   ansible_ssh_pass=''
  • 示例
[root@ansible ~]# vim  /etc/ansible/hosts
10.0.0.31 ansible_ssh_user=root ansible_ssh_port=22 ansible_ssh_pass='dezyan123.com'
#测试
[root@ansible ~]# ansible 10.0.0.31 -m ping
10.0.0.31 | SUCCESS => {
    "changed": false,
    "ping": "pong"
}

使用别名定义主机清单

  • 语法格式
别名 ansible_ssh_host=  ansible_ssh_user=  ansible_ssh_port= ansible_ssh_pass=''
  • 示例
nfs ansible_ssh_host=10.0.0.31  ansible_ssh_user=root ansible_ssh_port=22 ansible_ssh_pass='dezyan123.com'
#测试
[root@ansible ~]# ansible nfs -m ping
10.0.0.31 | SUCCESS => {
    "changed": false,
    "ping": "pong"
}

2.基于密钥方式连接

生成密钥对

1.生成秘钥对
[root@ansible ~]# ssh-keygen
2.发送到客户端
[root@ansible ~]# ssh-copy-id 10.0.0.31
[root@ansible ~]# ssh-copy-id 10.0.0.41
3.测试ssh免密
[root@ansible ~]# ssh 10.0.0.41
[root@ansible ~]# ssh 10.0.0.31

使用别名定义主机清单

[root@ansible ~]# vim /etc/ansible/hosts
nfs ansible_ssh_host=10.0.0.31
backup ansible_ssh_host=10.0.0.41
#测试
[root@ansible ~]# ansible nfs -m ping
nfs | SUCCESS => {
    "changed": false,
    "ping": "pong"
}

定义主机清单组

[root@ansible ~]# vim /etc/ansible/hosts
#直接写IP也可以,无需配置别名
[test]
nfs ansible_ssh_host=10.0.0.31
backup ansible_ssh_host=10.0.0.41
#测试
[root@ansible ~]# ansible test -m ping
backup | SUCCESS => {
    "changed": false,
    "ping": "pong"
}
nfs | SUCCESS => {
    "changed": false,
    "ping": "pong"
}

定义子组

[root@ansible ~]# vim /etc/ansible/hosts
[test01]
nfs ansible_ssh_host=10.0.0.31
[test02]
backup ansible_ssh_host=10.0.0.41

[test:children]
test01
test02

#测试
[root@ansible ~]# ansible test -m ping
backup | SUCCESS => {
    "changed": false,
    "ping": "pong"
}
nfs | SUCCESS => {
    "changed": false,
    "ping": "pong"
}

四、Ansible ad-hoc

  • Ansible提供的一种快速执行单个命令或一系列命令的方式
  • ansible执行命令都是以模块的方式执行
  • 基本语法格式
ansible 主机名称 -m 指定模块的名称 -a  具体执行的命令动作

ansible内置命令帮助文档

ansible-doc 模块名
底行输入:/EXAMPLE查看示例

模块1:yum(安装软件包)

  • 动作
    • name=软件包名
    • state=执行的动作
      • present 安装
      • absent 卸载
  • 示例
1.安装unzip命令
[root@ansible ~]# ansible backup -m yum -a 'name=unzip state=present'
2.卸载unzip命令
[root@ansible ~]# ansible backup -m yum -a 'name=unzip state=absent'
3.安装指定目录下存放的rpm包
[root@ansible ~]# ansible backup -m yum -a 'name=rpm包具体路径 state=present'
4.安装rsync服务
[root@ansible ~]# ansible backup -m yum -a 'name=rsync state=present'

模块2:copy(拷贝文件更改文件内容)

  • 动作
    • src=源文件(ansible服务器上的位置)
    • dest=目标地址(目标主机的位置)
    • owner=属主
    • group=属组
    • mode=权限数字
    • backup=yes (给当前的文件做一个以时间命名的备份文件,存放在目标主机上)
    • content=字符串(将字符串写入到目标文件中)
  • 示例
1.将本地/etc/hosts文件拷贝到41服务器的/opt目录下
[root@ansible ~]# ansible backup -m copy -a 'src=/etc/hosts dest=/opt/'
2.编写rsync匿名用户的密码文件
[root@ansible ~]# ansible backup -m copy -a 'content=backup:123 dest=/etc/passwd.txt mode=600'

模块3:user(创建用户)

  • 动作
    • name=用户名
    • uid=用户uid
    • group=组名称
    • shell=指定解释器
    • create_home=false(默认不写此参数为创建家目录)
    • state=状态
      • present 创建用户
      • absent 删除用户
    • remove=yes 删除用户并且删除其家目录(userdel -r)
  • 示例
1.创建普通用户dzy,指定uid为1016
[root@ansible ~]# ansible backup -m user -a 'name=dzy uid=1016 state=present'
[root@backup ~]# id dzy
uid=1016(dzy) gid=1016(dzy) groups=1016(dzy)

2.创建虚拟用户ding,指定uid为777,组名为ding
[root@ansible ~]# ansible backup -m group -a 'name=ding gid=777 state=present'
[root@ansible ~]# ansible backup -m user -a 'name=ding uid=777 group=ding shell=/sbin/nologin create_home=false state=present'

3.删除普通用户dzy,并删除其家目录
[root@ansible ~]# ansible backup -m user -a 'name=dzy remove=yes state=absent'

模块4:group(创建组)

  • 动作
    • name=组名名称
    • gid=组id
    • state=状态
      • present 创建
      • absent 删除
  • 示例
创建ding用户组,指定gid为777
[root@ansible ~]# ansible backup -m group -a 'name=ding gid=777 state=present'

模块5:file(创建删除文件目录,修改权限)

  • 动作
    • path=文件路径
    • state=状态
      • touch(文件)
      • directoty(目录)
      • absent(删除文件或目录)
    • owner=属主
    • group=属组
    • mode=权限数字(0600)
    • recurse=yes(递归修改)
  • 示例
1.创建普通文件test.txt,并将其属主属组改为dezyan,权限为0600
[root@ansible ~]# ansible backup -m file -a 'path=/root/test.txt state=touch owner=dezyan group=dezyan mode=0600'

2.创建一个名为dir的目录
[root@ansible ~]# ansible backup -m file -a 'path=/root/dir state=directory'

3.递归修改dir目录下所有文件的属主属组为dezyan
[root@ansible ~]# ansible backup -m file -a 'path=/root/dir owner=dezyan group=dezyan recurse=yes'

4.删除dir目录及目录下的所有文件
[root@ansible ~]# ansible backup -m file -a 'path=/root/dir state=absent'

模块6:systemd(修改服务状态)

  • 动作
    • name=服务名
    • state=状态
      • started(启动)
      • stopped(停止)
      • restarted(重启)
      • reloaded(重载)
    • enabled=yes(开机自启)
  • 示例
1.启动rsync服务并设置开机自启
[root@ansible ~]# ansible backup -m systemd -a 'name=rsyncd state=started enabled=yes'

模块7:yum_repository(添加系统yum源)

  • 动作

    • name=文件名
    • description=描述(备注)
    • baseurl=存储库的基本URL
    • enabled=yes(启用该yum源)
    • gpgcheck=no(不启用GPG签名检查)
    • gpgkey=存储库GPG密钥的URL或文件路径
  • 示例

1.配置一个nginx的yum源
ansible backup -m yum_repository -a 'name="nginx stable repo"  description='nginx YUM repository'   baseurl=http://nginx.org/packages/centos/7/$basearch/ gpgcheck=0 enabled=1 gpgkey=https://nginx.org/keys/nginx_signing.key module_hotfixes=true'

模块8:mount(磁盘操作)

  • 动作
    • src=挂载目录
    • path=挂载点
    • fstype=分区类型
    • opts=挂载选项
    • state=状态
      • present(开机挂载,仅将挂载配置写入/etc/fstab)
      • mounted(挂载设备,并将配置写入/etc/fstab)
      • umounted(卸载设备,不会清除/etc/fstab写入的配置)
      • absent(卸载设备,会清理/etc/fstab写入的配置)
  • 示例

模块9:cron(定时任务)

  • 动作
    • minute=* hour=* day=* month=* weekday=*
    • job=任务
  • 示例
#设置一条定时任务,每分钟执行一次test.sh脚本
[root@ansible ~]# ansible web_group -m cron -a "minute=* hour=* day=* month=* weekday=* job='/bin/sh /server/scripts/test.sh'"

模块10:firewalld(防火墙)

  • 动作
    • service=指定开放或关闭的服务名称
    • port=指定开放或关闭的端口
    • permanent=yes(是否添加永久生效)
    • state=状态
      • enabled
      • disabled
    • masquerade=yes(开启地址伪装)
    • source=192.169.0.0/24(指定来源IP)
    • immediate

模块11:selinux

  • 动作
    • state=状态
      • disabled(关闭)
      • permissive(开启)
  • 示例
#关闭selinux
[root@ansible ~]# ansible nfs -m selinux -a 'state=disabled' 

模块12:unarchive(解压)

  • 支持tar、zip、bzip2、gzip多种解压模式
  • 动作
    • src=压缩包(ansible服务器上的位置或指定的URL链接 )
    • dest=目标解压地址
    • creates=目录(如果目标解压地址不存在,会创建该目录)
    • owner= group= mode= (设置解压后的文件权限)

模块13:get_url(主机信息)

  • 常用动作
1.查看所有详细信息
[root@ansible ~]# ansible web01 -m setup

2.获取IP地址
[root@ansible ~]# ansible web01 -m setup -a 'filter=ansible_default_ipv4'

3.获取主机名
[root@ansible ~]# ansible web01 -m setup -a 'filter=ansible_fqdn'

4.获取内存信息
[root@ansible ~]# ansible web01 -m setup -a 'filter=ansible_memory_mb'

5.获取磁盘信息
[root@ansible ~]# ansible web01 -m setup -a 'filter=ansible_devices'

  • 其他信息参数
ansible_all_ipv4_addresses:仅显示ipv4的信息。
ansible_devices:仅显示磁盘设备信息。
ansible_distribution:显示是什么系统,例:centos,suse等。
ansible_distribution_major_version:显示是系统主版本。
ansible_distribution_version:仅显示系统版本。
ansible_machine:显示系统类型,例:32位,还是64位。
ansible_eth0:仅显示eth0的信息。
ansible_hostname:仅显示主机名。
ansible_kernel:仅显示内核版本。
ansible_lvm:显示lvm相关信息。
ansible_memtotal_mb:显示系统总内存。
ansible_memfree_mb:显示可用系统内存。
ansible_memory_mb:详细显示内存情况。
ansible_swaptotal_mb:显示总的swap内存。
ansible_swapfree_mb:显示swap内存的可用内存。
ansible_mounts:显示系统磁盘挂载情况。
ansible_processor:显示cpu个数(具体显示每个cpu的型号)。
ansible_processor_vcpus:显示cpu个数(只显示总的个数)。

模块14:mysql_db(数据库操作)

  • 动作:

    • login_user=用户名
    • login_host=登录主机
    • login_port=数据端口
    • name=要操作的数据库名(all代表所有)
    • target=指定导出或导入的数据库文件
    • state=状态
      • present 创建数据库
      • absent 删除数据库
      • dump 导出数据库
      • import 导入数据库
  • 示例:

1.将all.sql导入到新数据库中
[root@ansible ~]# ansible db01 -m mysql_db -a 'login_user: root login_host: localhost login_port: 3306 name: all target: /root/db-all.sql state: import '

五、Ansible Playbook

①剧本文件

在 Ansible 中”剧本文件”是以yml结尾的文件,使用的都是 yaml 语法

②语法格式

  • 缩进:YAML使用固定的缩进风格表示层级结构,每个缩进由两个空格组成, 不能使用TAB
  • 冒号:以冒号结尾的除外,其他所有冒号后面所有必须有空格
  • 短横线:表示列表项,使用一个短横杠加一个空格,多个项使用同样的缩进级别作为同一列表
  • 层级关系
    • 第一层级:hosts属于最高层级
    • 第二层级:tasks、vars、handers同级,次于hosts
    • 第三层级:模块层级
    • 第四层级:模块动作
- hosts: hostname		#yaml语法中最顶层的结构,用于指定执行主机
  vars:					#次于hosts层级,属于角色层,定义下方要使用的变量
    pk: wget			#定义变量
  tasks:				#次于hosts层级,属于执行层,定义要执行的动作
    - name: Install wget		#定义动作名称
      yum: 						#定义要执行的动作(模块)
        name: wget				#使用模块内置动作实现自动化
        state: present
  • 语法检测:

    注意:语法检测只能检查缩进、冒号、短横线、空格的语法错误,无法检查单词(模块名)是否正确

[root@ansible ansible]# ansible-playbook  --syntax-check yml文件

playbook: wget.yml		#执行结果为此,无警告、报错即为语法正确
  • 执行yml文件
[root@ansible ansible]# ansible-playbook yml文件

③主机清单

  • 所有示例均以此列表清单的别名为准
nfs ansible_ssh_host=10.0.0.31
backup ansible_ssh_host=10.0.0.41

[webs]
web01 ansible_ssh_host=10.0.0.7
wen02 ansible_ssh_host=10.0.0.8

[mariadb]
db01 ansible_ssh_host=10.0.0.51

④第一层级

- hosts: hostname     #指定主机名、组名

⑤第二层级

1.Playbook-task执行层级

示例1:Playbook安装wget包

第一步:编写yml文件
[root@ansible playbook]# vim wget.yml
- hosts: backup					#定义执行操作的主机(在列表清单中定义)
  tasks:						#具体执行的任务
    - name: Install wget		#注释
      yum: 						#模块名
        name: wget				#模块内置动作、状态
        state: present
第二步:检查语法
[root@ansible playbook]# ansible-playbook --syntax-check wget.yml 

playbook: wget.yml
第三步:执行剧本
[root@ansible playbook]# ansible-playbook wget.yml

示例2:使用Playbook部署rsync服务

  • 需提前准备好rsyncd.conf配置文件
第一步:编写yml文件
[root@ansible playbook]# vim backup.yml
- hosts: backup
  tasks: 
    - name: install rsync server
      yum:
        name: rsync
        state: present
    
    - name: Configure rsync server
      copy: 
        src: /etc/ansible/serverconf/rsyncd.conf
        dest: /etc/rsyncd.conf

    - name: create group www
      group: 
        name: www
        gid: 666
    
    - name: create user www
      user:
        name: www
        uid: 666
        group: www
        shell: /sbin/nologin
        create_home: false

    - name: create passwd file
      copy:
        content: rsync_backup:123456
        dest: /etc/rsync.passwd
        mode: 0600

    - name: create backup directory
      file:
        path: /backup
        state: directory
        owner: www
        group: www

    - name: systemctl start rsync
      systemd:
        name: rsyncd
        state: started
        enabled: yes
        
第二步:检查语法
[root@ansible playbook]# ansible-playbook --syntax-check wget.yml 

playbook: wget.yml
第三步:执行剧本
[root@ansible playbook]# ansible-playbook wget.yml

示例3:使用Playbook部署NFS服务

第一步:编写yml文件
[root@ansible playbook]# vim nfs.yml
- hosts: nfs
  tasks:
    - name: download nfs server 
      yum:
        name: nfs-utils
        state: present
    
    - name: configure nfs 
      copy:
        src: /etc/ansible/serverconf/exports
        dest: /etc/exports
    
    - name: create group www
      group:
        name: www
        gid: 666
        
    
    - name: create user www
      user: 
        name: www
        uid: 666
        group: www
        state: present
        shell: /sbin/nologin
        create_home: false

    - name: create nfs file
      file:
        path: /data/wordpress
        owner: www
        group: www
        state: directory

    - name: systemctl start nfs
      systemd:
        name: nfs
        state: started
        enabled: yes
    
        
第二步:检查语法
[root@ansible playbook]# ansible-playbook --syntax-check nfs.yml 

playbook: nfs.yml
第三步:执行剧本
[root@ansible playbook]# ansible-playbook nfs.yml

示例4:使用Playbook部署nginx服务

第一步:编写yml文件
[root@ansible playbook]# vim nginx.yml
- hosts: web01
  tasks:
    - name: create nginx.repo
      yum_repository:
        name: nignx 
        description: Nginx Yum repo 
        baseurl: http://nginx.org/packages/centos/7/$basearch/
        gpgcheck: no
        enabled: yes

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

    - name: create group www
      group:
        name: www
        gid: 666
        
    
    - name: create user www
      user: 
        name: www
        uid: 666
        group: www
        state: present
        shell: /sbin/nologin
        create_home: false

    - name: configure nginx 
      copy:
        src: /etc/ansible/serverconf/nginx.conf
        dest: /etc/nginx/nginx.conf 

    - name: systemctl start nginx 
      systemd:
        name: nginx
        state: started
        enabled: yes
    
        
第二步:检查语法
[root@ansible playbook]# ansible-playbook --syntax-check nginx.yml

playbook: nfs.yml
第三步:执行剧本
[root@ansible playbook]# ansible-playbook nginx.yml

示例5:使用Playbook部署php服务

第一步:编写yml文件
[root@ansible playbook]# vim php.yml
- hosts: web01
  tasks:
    - name: Install PHP Server
      yum:
        name: php,php-bcmath,php-cli,php-common,php-devel,php-embedded,php-fpm,php-gd,php-intl,php-mbstring,php-mysqlnd,php-opcache,php-pdo,php-process,php-xml,php-json
        state: present


    - name: Configure PHP Server
      copy:
        src: /etc/ansible/serverconf/www.conf
        dest: /etc/php-fpm.d/


    - name: Start PHP Server
      systemd:
        name: php-fpm
        state: started
        enabled: yes

第二步:检查语法
[root@ansible playbook]# ansible-playbook --syntax-check php.yml

playbook: nfs.yml
第三步:执行剧本
[root@ansible playbook]# ansible-playbook php.yml

示例6:使用Playbook部署mariadb

导出原数据库所有库
mysqldump -udzy -pdzy123.com -A > dump_file.sql
第一步:编写yml文件
[root@ansible playbook]# vim mysql.yml
- hosts: db01
  tasks:
    - name: Install mariadb Server
      yum:
        name: mariadb-server,python3-mysqlclient
        state: present

    - name: Start mariadb Server
      systemd:
        name: mariadb
        state: started
        enabled: yes

    - name: copy all.sql to 51
      copy:
        src: /etc/ansible/serverconf/db-all.sql
        dest: /root/

    - name: Configure Mmriadb Server
      mysql_db:
        login_user: root
        login_host: localhost
        login_port: 3306
        name: all
        target: /root/db-all.sql
        state: import       

    - name: Restart mariadb
      systemd: 
        name: mariadb
        state: restarted
    
第二步:检查语法
[root@ansible playbook]# ansible-playbook --syntax-check mysql.yml

playbook: nfs.yml
第三步:执行剧本
[root@ansible playbook]# ansible-playbook mysql.yml

示例7:使用Playbook部署wordpress

第一步:编写yml文件
[root@ansible playbook]# vim wp.yml
- hosts: web01
  tasks:
    - name: Delete Default default.conf
      file:
        path: /etc/nginx/conf.d/default.conf
        state: absent

    - name: Copy wp.conf 
      copy:
        src: /etc/ansible/serverconf/wp.conf
        dest: /etc/nginx/conf.d/

    - name: unarchive code.tar.gz
      unarchive:
        src: /etc/ansible/serverconf/code.tar.gz 
        dest: /
        creates: /code/wordpress

    - name: Restart Nginx Server
      systemd:
        name: nginx
        state: restarted
    
第二步:检查语法
[root@ansible playbook]# ansible-playbook --syntax-check wp.yml

playbook: nfs.yml
第三步:执行剧本
[root@ansible playbook]# ansible-playbook wp.yml

示例8:客户端挂载nfs共享目录

第一步:编写yml文件
[root@ansible playbook]# vim web01-mount.yml
- hosts: web01
  tasks:
    - name: install nfs server 
      yum:
        name: nfs-utils
        state: present 
    
    - name: create /code/wordpress/wp-content/uploads/
      file:
        path: /code/wordpress/wp-content/uploads/
        state: directory
       

    - name: mount nfs /data/wordpress
      mount:
        src: 172.16.1.31:/data/wordpress
        path: /code/wordpress/wp-content/uploads/
        state: mounted
        fstype: nfs

    - name: reload photo to server
      unarchive:
        src: /etc/ansible/serverconf/imag.tar.gz
        dest: /code/wordpress/wp-content/uploads/
        creates: /code/wordpress/wp-content/uploads/
    
        
第二步:检查语法
[root@ansible playbook]# ansible-playbook --syntax-check web01-mount.yml

playbook: nfs.yml
第三步:执行剧本
[root@ansible playbook]# ansible-playbook web01-mount.yml

2.Playbook-vars角色层级

定义方式1:Playbook中直接定义

示例1:定义单一变量(变量内只有一个值)
#动作内不包含路径
[root@ansible playbook]# vim test.yml
- hosts: nfs
  vars: 
    pkg: wget
  tasks:
    - name: Install Package
      yum:
        name: "{{ pkg }}"			#注意格式:"{{ 变量名 }}"
        state: present

#动作内包含路径
[root@ansible playbook]# vim test.yml
- hosts: nfs
  vars: 
    pkg: test
  tasks:
    - name: create file
      file:
       path: /root/{{ pkg }}		#注意格式:{{ 变量名 }}
       state: touch

  • 由此可见,在动作不包含路径时使用变量需要加"",包含路径时无需加""
示例2:定义多个变量(变量中包含多个值)
[root@ansible playbook]# vim test.yml
- hosts: nfs
  vars:
    pkg:
      - wget
      - lrzsz
      - unzip

  tasks:
    - name: create file
      yum:
       name: "{{ pkg }}"
       state: present
示例3:动作中使用多个变量
[root@ansible playbook]# vim test.yml
- hosts: nfs
  vars: 
    pkg: test
    msg: ding
  tasks:
    - name: create file
      file:
       path: /root/{{ pkg }}_{{ msg }}
       state: touch
       
#nfs中查看
[root@nfs ~]# ll
total 0
-rw-r--r-- 1 root root 0 Jan  1 19:41 test_ding

定义方式2:vars_files文件中定义

  • 创建并编写存放变量的文件
[root@ansible playbook]# vim vars.yml
pkg: test
msg: dingzhiyan
  • 在Playbook中调用
示例1:调用单一变量(创建单一文件)
[root@ansible playbook]# vim test.yml
- hosts: nfs
  vars_files: vars.yml					#使用vars_files指定变量文件
  tasks:
    - name: create file
      file:
       path: /root/{{ pkg }}
       state: touch
#执行测试查看
[root@nfs ~]# 
[root@nfs ~]# ll
-rw-r--r-- 1 root root 0 Jan  1 19:47 test
示例2:多用多个变量(批量创建多个文件)
[root@ansible playbook]# vim test.yml
- hosts: nfs
  vars_files: vars.yml
  tasks:
    - name: create file
      file:
        path: /root/{{ item }}
        state: touch
      loop:
         - "{{ pkg }}" 
         - "{{ msg }}"
    
#执行测试查看
[root@nfs ~]# ll
total 0
-rw-r--r-- 1 root root 0 Jan  1 20:01 dingzhiyan
-rw-r--r-- 1 root root 0 Jan  1 20:01 test

示例3:多个变量拼接使用
[root@ansible playbook]# vim test.yml
- hosts: nfs
  vars_files: vars.yml					#使用vars_files指定变量文件
  tasks:
    - name: create file
      file:
       path: /root/{{ pkg }}_{{ msg }}
       state: touch
#执行测试查看
[root@nfs ~]# 
[root@nfs ~]# ll
-rw-r--r-- 1 root root 0 Jan  1 19:47 test_dingzhiyan

定义方式3:直接使用内置变量

  • 内置变量通过setup模块来查看。
[root@ansible playbook]# ansible nfs -m setup
  • 查询、使用内置变量的方法
1.通过命令查看ansible提供的所有内置变量
#找到关于ipv4的段落
        "ansible_default_ipv4": {
            "address": "10.0.0.31",
            "alias": "ens33",
            "broadcast": "10.0.0.255",
            "gateway": "10.0.0.2",
            "interface": "ens33",
            "macaddress": "00:0c:29:04:17:cf",
            "mtu": 1500,
            "netmask": "255.255.255.0",
            "network": "10.0.0.0",
            "prefix": "24",
            "type": "ether"
2.观察层级关系,此处与yaml语法中的层级关系相同
ansible_default_ipv4属于其顶层,其余属于他的附属层

3.调用其中信息的方法为:
顶层名.附属层名
示例:调用IP信息
ansible_default_ipv4.address
示例1:使用内置变量创建以IP+主机名命名的文件
[root@ansible playbook]# vim test.yml
- hosts: nfs
  tasks:
    - name: create file
      file:
        path: /root/{{ ansible_default_ipv4.address }}_{{ ansible_hostname }}
        state: touch
        
#测试查看
[root@nfs ~]# ll
-rw-r--r-- 1 root root 0 Jan  1 20:07 10.0.0.31_nfs

定义方式4:在主机清单中定义(不建议使用)

[root@ansible playbook]# vim /etc/ansible/hosts
[webs]
web01 ansible_ssh_host=10.0.0.7
web02 ansible_ssh_host=10.0.0.8

[webs:vars]			#为上方组定义变量
pk1=wget
pk2=lrzsz
  • 调用:直接在Playbook文件中使用即可

定义方式5:ansible官方推荐使用方式

示例1:定义主机变量(针对单一主机的变量)
1.在当前目录中创建host_vars目录
[root@ansible ansible]# mkdir host_vars

2.创建、编写定义变量的文件
#注意!!
#文件名称必须要与列表清单中的主机名相同
#文件要放在host_vars目录中
[root@ansible ansible]# vim host_vars/nfs
name: ding
age: 23
sex: man

3.调用变量测试
[root@ansible ansible]# vim test.yml
- hosts: nfs
  tasks:
    - name: create file
      file:
        path: /root/{{ name }}_{{ age }}_{{ sex }}
        state: touch
        
[root@nfs ~]# ll
-rw-r--r-- 1 root root 0 Jan  1 20:32 ding_23_man       
示例2:定义组变量(多个主机)
  • 文件名称为all时,对所有主机都生效
1.在当前目录中创建group_vars目录
[root@ansible ansible]# mkdir group_vars
2.创建、编写定义变量的文件
#注意!!
#文件名称必须要与列表清单中的组名相同
#文件要放在group_vars目录中
[root@ansible ansible]# vim group_vars/webs
name: ding
age: 23
sex: man
3.调用方法与示例1相同,只不过是对多台主机生效了

定义方式6:变量注册(重要)

  • 使用Ansible执行命令,有一些是无法返回结果的
#执行后无法查看ls -l 所列出的信息
- hosts: web01
  tasks:
    - name: list /root
      command: ls -l
  • 通过变量注册返回详细信息
#使用register模块及debug模块中的msg动作实现
#以ls -l 为例
- hosts: web01
  tasks:
    - name:  list root file
      command: ls -l
      register: ng_re           #自定义变量名


    - name: print ng_re env
      debug:
        msg: "{{ ng_re }}"      #使用register定义的变量名
示例1:检查nginx的语法是否正确并返回结果
[root@ansible playbook]# vim test.yml
- hosts: web01
  tasks:
    - name: check nginx config
      command: nginx -t
      register: ng_check
      
    - name: print check result
      debug:
        msg: "{{ ng_check}}"
        
[root@ansible playbook]# ansible-playbook test.yml
#TASK [print check result]的结果中会打印信息
ok: [web01] => {
    "msg": {
…………
        "rc": 0,
…………
        "stderr_lines": [
            "nginx: the configuration file /etc/nginx/nginx.conf syntax is ok",
            "nginx: configuration file /etc/nginx/nginx.conf test is successful"
        ],
    }
}
示例2:获取返回结果中子集的值
  • 获取方法与系统变量的使用方法原理相同

  • 使用方法:

        msg: "{{ 变量名.子集名}}"
或	   msg: "{{ 变量名['子集名'] }}"     #官方推荐写法
  • 示例:
- hosts: web01
  tasks:
    - name: check nginx config
      command: nginx -t
      register: ng_check
      
    - name: print check result
      debug:
        msg: "{{ ng_check.stderr_lines}"
        
#这样,获取的就是如下信息
TASK [print check result] ******************************************************
ok: [web01] => {
    "msg": [
        "nginx: the configuration file /etc/nginx/nginx.conf syntax is ok",
        "nginx: configuration file /etc/nginx/nginx.conf test is successful"
    ]
}

3.Playbook-handlers任务触发层级

  • 监控文件(或其他)是否发生变化 如果一致不触发handlers,如果发生变化则触发handlers进行指定动作

  • 语法格式

  tasks:
    - name: Configure Nginx Server
      模块:
        动作:
      notify: name		#此处的name必须与handlers的name一致
      
  handlers:
    - name: Restart Nginx Server	#必须和notify后的名称一致
      模块:
        动作:
        ……
  • 示例:
#检测nginx配置文件变化,如果发生变化,切语法正确,启动nginx
- hosts: web02
  tasks:
    - name: Nginx Repo 
      yum_repository:
        name: nginx
        description: Nginx YUM repo
        baseurl: http://nginx.org/packages/centos/7/$basearch/
        gpgcheck: no
        enabled: yes

    - name: Install Nginx Server
      yum:
        name: nginx
        state: present

    - name: Configure Nginx Server
      copy:
        src: nginx.conf
        dest: /etc/nginx/
      notify: Restart Nginx Server		

    - name: check nginx conf
      shell: nginx -t
      ignore_errors: yes
      register: ng_re

    - name: create group www
      group:
        name: www
        gid: 666

    - name: Create www user
      user:
        name: www
        uid: 666
        group: www
        shell: /sbin/nologin
        create_home: false

    - name: Start Nginx Server
      systemd:
        name: nginx
        state: started
        enabled: yes

  handlers:
    - name: Restart Nginx Server		# 必须和notify后的名称一致
      systemd:
        name: nginx
        state: restarted
      when: ng_re.stderr_lines is search "ok"

⑥第三层级

1.when判断模块

判断机制1:精确判断-单一条件
  • 全部满足,才会执行
#以安装wget命令为例
- hosts: all
  tasks:
    - name: Install wget
      yum:
        name: wget
        state: absent
      when: ansible_hostname == "web01"   #系统内置变量名 == "字符串"
#该Playbook的含义是:当目标主机名为web01时才执行此模块及其动作
#若替换为:
	  when: ansible_default_ipv4.address == "10.0.0.8"
#代表只有目标IP为10.0.0.8时才会执行
判断机制2:精确判断-多个条件同时满足
  • 全部满足,才会执行
#以安装wget命令为例
- hosts: lnmp
  tasks:
    - name: Install wget
      yum:
        name: wget
        state: present
      when: 
        - ansible_default_ipv4.address == "10.0.0.7"
        - ansible_hostname == "web01"
        
#此时,目标主机的主机名必须为web01且IP地址为10.0.0.7时才会执行
判断机制3:精确判断-多个条件满足其一
  • 满足其一,就会执行
#以安装wget命令为例
- hosts: lnmp
  tasks:
    - name: Install wget
      yum:
        name: wget
        state: present
      when: ( ansible_default_ipv4.address == "10.0.0.7" ) or ( ansible_hostname == "web01" )
        
#此时,目标主机的主机名必须为web01 或者 IP地址为10.0.0.7时才会执行
  • 不能使用正则表达式

  • 变量中只要含有定义的字符串,就会执行

  • 注:search过滤器在Ansible 2.9中被弃用,并在Ansible 2.10中被移除

#以安装wget命令为例
- hosts: lnmp
  tasks:
    - name: Install wget
      yum:
        name: wget
        state: present
      when: ansible_hostname is search "web"
      
#此时,目标主机的主机名中包含web就会执行,例如web01 ,02web,01web02都会执行
判断机制5:模糊判断-match
  • 可以使用正则表达式
  • 变量中定义的字符串需满足正则,才会执行
[root@ansible dezyan]# cat w.yml
- hosts: lnmp
  tasks:
    - name: Install wget
      yum:
        name: wget
        state: present
      when: ansible_hostname is match "^web$"
      
#此时,只有目标主机为web时,才会执行
注意!!!

1.无论多少个task通知了相同的handlers,handlers仅会在所有tasks结束后运行一次。

2.Handlers只有在其所在的任务被执行时,才会被运行;如果一个任务中定义了notify调用Handlers,但是由于条件判断等原因,该任务未被执行,那么Handlers同样不会被执行。

3.Handlers只会在每一个play的末尾运行一次;如果想在一个playbook中间运行Handlers,则需要使用meta模块来实现。例如: -meta: flush_handlers。

4.如果一个play在运行到调用Handlers的语句之前失败了,那么这个Handlers将不会被执行。我们可以使用meta模块的–force-handlers选项来强制执行Handlers,即使Handlers所在的play中途运行失败也能执行。

5.不能使用handlers替代tasks

示例:
  • 在部署nginx业务时,我们需要修改配置文件,并检查语法是否正确才可重新启动
  • 在ansible的Playbook中,我们可以使用when判断nginx -t结果是否正确决定是否重新启动nginx
[root@ansible ansible]# cat nginx.yml
- hosts: web02
  tasks:
    - name: Nginx Repo 
      yum_repository:
        name: nginx
        description: Nginx YUM repo
        baseurl: http://nginx.org/packages/centos/7/$basearch/
        gpgcheck: no
        enabled: yes


    - name: Install Nginx Server
      yum:
        name: nginx
        state: present

    - name: Configure Nginx Server
      copy:
        src: nginx.conf
        dest: /etc/nginx/

    - name: check nginx conf
      shell: nginx -t
      ignore_errors: yes
      register: ng_re		#变量注册,将nginx -t的结果返回给ng_re

    - name: create group www
      group:
        name: www
        gid: 666

    - name: Create www user
      user:
        name: www
        uid: 666
        group: www
        shell: /sbin/nologin
        create_home: false

    - name: Start Nginx Server
      systemd:
        name: nginx
        state: restarted
        enabled: yes
      when: ng_re.stderr_lines is search "ok" #结果包含ok时,执行动作

2.ignore_errors忽略错误模块

  • 默认playbook会检测task执行的返回状态,如果遇到错误则会立即终止playbook的后续task执行,然而有些时候playbook即使执行错误了也要让其继续执行。
示例:检测nginx语法,如果错误,忽略并继续向下执行
…………
   - name: check nginx conf
      shell: nginx -t
      ignore_errors: yes		#添加此模块即可
      register: ng_re	
……………

3.item-loop-字典循环模块

  • 循环通过动作:{{ item }}以及他的子集{{ item.string }}进行定义
  • 使用loop或者with_items模块来调用
示例1:启动多个服务
- hosts: web02
  tasks:
    - name: Restart Nginx PHP
      systemd:
        name: "{{ item }}" 
        state: started
      loop:
        - nginx
        - php-fpm
示例2:创建多个文件(使用子集)
- hosts: web02
  tasks:
    - name: create file
      file:
        path: "{{ item.name }}"
        owner: "{{ item.owner }}"
        group: "{{ item.group }}"
        mode: "{{ item.mode }}"
        state: touch
      loop:
        - { name: a.txt,owner: www,group: www,mode: '0600' }
        - { name: b.txt,owner: root,group: root,mode: '0644' }

4.tags标签模块

  • 在我们使用ansible执行Playbook时,有时候有需求只执行其中一个动作,这时我们便可以使用tags模块并结合ansible命令来实现
  • 注意:可以给多个任务打相同的tag,在执行时就会执行多个动作
  • 查看标签
[root@ansible ansible]# ansible-playbook nfs.yml --list-tags
  • 执行标签
[root@ansible ansible]# ansible-playbook nfs.yml -t hehe
  • 配置示例
- name: Create "{{ dir }}"
      file:
        path: "{{ dir }}"
        state: directory
        owner: www
        group: www
      tags: hehe

5.include使多个tasks组合模块

  • 准备两个yml文件
[root@ansible ansible]# cat web.yml 
- name: create a.txt
  file:
    path: /root/a.txt
    state: touch
[root@ansible ansible]# cat mysql.yml 
- name: create file
  file:
    path: /root/php.txt
    state: touch
  • 使用include整合
[root@ansible dezyan]# cat web.yml
- hosts: all
  tasks:
    - include_tasks: web.yml
      when: ansible_hostname == "web02"
    - include_tasks: mysql.yml
      when: ansible_hostname == "backup"

6.template调用jinja2模版文件

yml调用方式
- name: Configure nfs Server
  template:
    src: exports.j2			#jinja2文件名,常以.j2结尾
    dest: /etc/exports		#目标路径及文件名
jinja2文件及其语法
  • 逻辑判断(使用较少)
#循环表达式
{% for i in EXPR %}
{% endfor %}

#条件判断
{% if EXPR %}
{% elif EXPR %}
{% else %}
{% endif %}

#注释
{# COMMENT #}
  • 变量引用
{{ 变量名 }}       #在文件中哪里使用往哪里填
示例1:推送一个欢迎界面
  • jinja2文件
{# 展示主机名,内存,IP地址 #}
Welcome to {{ ansible_hostname }}
This system total mem is : {{ ansible_memtotal_mb }} MB
This system ip address: {{ ansible_default_ipv4.address }}
  • yml文件调用
- hosts: web01
  tasks:
    - name: copy motd
      template:
        src: motd.j2
        dest: /etc/motd
示例2:使用for循环生成lb配置文件
  • jinja2文件:nginx.conf.j2
upstream {{ server_name }} {
{% for n in range(7,9) %}
        server 172.16.1.{{ n }}:{{ up_port }};
{% endfor %}
}

server {
        listen 80;
        server_name {{ server_name }};

        location / {
                proxy_pass http://{{ server_name }};
                proxy_set_header Host $http_host;
        }
}
  • yml文件:cp.yml(在此定义jinja2中的变量)
- hosts: lnmp
  vars:
    - server_name: www.wp.com
    - up_port: 80

  tasks:
    - name: copy motd
      template:
        src: nginx.conf
        dest: /root/
  • 执行查看结果
[root@web01 ~]# cat nginx.conf 
upstream www.wp.com {
        server 172.16.1.7:80;
        server 172.16.1.8:80;
}

server {
        listen 80;
        server_name www.wp.com;

        location / {
                root /code;
                index index.html;
                proxy_pass http://www.wp.com;
                proxy_set_header Host $http_host;
        }
}
示例3:使用if判断生成keepalived配置文件
  • jinja2:keep.j2
global_defs {
    router_id {{ ansible_fqdn }}
}

vrrp_instance VI_1 {
{% if ansible_fqdn == "web01" %}
    state MASTER
    priority 150
{% else %}
    state BACKUP
    priority 100
{% endif %}

    interface eth0
    virtual_router_id 50
    advert_int 1
    authentication {
        auth_type PASS
        auth_pass 1111
    }
    virtual_ipaddress {         
        10.0.0.3
    }
}
  • yml文件:cp.yml
- hosts: lnmp
  vars:
    - server_name: www.wp.com
    - up_port: 80

  tasks:
    - name: copy motd
      template:
        src: keep.j2
        dest: /root/
示例4:rsync配置文件使用jinja2模版
#1.定义jinja2变量配置文件
[root@ansible ansible]# cat rsyncd.conf.j2 
uid = {{ user }}
gid = {{ user }}
port = {{ rsync_port }}
fake super = yes
use chroot = no
max connections = 200
timeout = 600
ignore errors
read only = false
list = false
auth users = rsync_backup
secrets file = /etc/rsync.passwd
log file = /var/log/rsyncd.log
#####################################
[backup]
path = {{ rs_dir }}

#2.yml调用jinja2文件
[root@ansible ansible]# cat rs.yml
- hosts: backup
  vars:
    - user: www
    - rsync_port: 873
    - rs_dir: /backup
  tasks:
    - name: Install Rsync Server
      yum:
        name: rsync
        state: present
    
    - name: Configure Rsync Server
      template:
        src: "{{ item.src }}"
        dest: "{{ item.dest }}"
        mode: "{{ item.mode }}"
      loop:
        - { src: rsyncd.conf.j2, dest: /etc/rsyncd.conf,mode: '0644' }
        - { src: rsync.passwd, dest: /etc/,mode: '0600' }
      notify: Restart Rsync Server

    - name: Create "{{ user }}" group
      group:
        name: "{{ user }}"
        gid: 666

    - name: Create "{{ user }}" user
      user:
        name: "{{ user }}"
        uid: 666
        group: "{{ user }}"
        shell: /sbin/nologin
        create_home: false

    - name: Create "{{ rs_dir }}"
      file:
        path: "{{ rs_dir }}"
        state: directory
        owner: "{{ user }}"
        group: "{{ user }}"

    - name: Start Rsync Server
      systemd:
        name: rsyncd
        state: started
        enabled: yes
  handlers:
    - name: Restart Rsync Server
      systemd:
        name: rsyncd
        state: restarted

六、ansible roles 角色

  • 我们编写Playbook时,文件太多,又乱,不美观,所以我们可以使用roles来优化一下

1.创建roles

[root@ansible roles]# ansible-galaxy init rsync
- Role rsync was created successfully

2.roles创建的目录结构及详解

  • 目录结构
[root@ansible roles]# tree rsync/
rsync/
├── defaults
│   └── main.yml
├── files
├── handlers
│   └── main.yml
├── meta
│   └── main.yml
├── README.md
├── tasks
│   └── main.yml
├── templates
├── tests
│   ├── inventory
│   └── test.yml
└── vars
    └── main.yml
  • 目录详解
defaults		#用于定义角色的默认变量,一般在vars目录中定义,可删除
files			#用于存放文件,这些文件会在执行任务时被复制到远程主机上
handlers		#当我们在tasks中定义了handlers,要在这里写要执行的动作
meta			#用不到,删
tasks			#编写任务,动作,模块
templates		#用于存放jinja2文件
tests			#测试任务,删
vars			#定义全局变量
示例1:重构rsync服务
  • 编写tasks中的文件main.yml
- name: Install Rsync Server
  yum:
    name: rsync
    state: present

- name: Configure Rsync
  template:
    src: "{{ item.src }}"
    dest: "{{ item.dest }}"
    mode: "{{ item.mode }}"
  loop:
    - { src: rsyncd.conf.j2,dest: /etc/rsyncd.conf,mode: '0644' }
    - { src: rsync.passwd.j2,dest: /etc/rsync.passwd,mode: '0600' }
  notify: Restart Rsync Server

- name: Create "{{ user }}" group
  group:
    name: "{{ user }}"
    gid: 666

- name: Create "{{ user }}" user
  user:
    name: "{{ user }}"
    uid: 666
    group: "{{ user }}"
    shell: /sbin/nologin
    create_home: false

- name: Create "{{ rs_dir }}"
  file:
    path: "{{ rs_dir }}"
    state: directory
    owner: "{{ user }}"
    group: "{{ user }}"

- name: Start Rsync Server
  systemd:
    name: rsyncd
    state: started
    enabled: yes
  • 编写vars中的文件main.yml
user: www
rsync_port: 873
rs_dir: /backup
  • 编写handlers中的文件main.yml
- name: Restart Rsync Server
  systemd:
    name: rsyncd
    state: restarted
  • 编写jinja2配置文件rsyncd.conf.j2及匿名用户密码文件
uid = {{ user }}
gid = {{ user }}
port = {{ rsync_port }}
fake super = yes
use chroot = no
max connections = 200
timeout = 600
ignore errors
read only = false
list = false
auth users = rsync_backup
secrets file = /etc/rsync.passwd
log file = /var/log/rsyncd.log
#####################################
[backup]
path = {{ rs_dir }}

rsync_backup:123456
  • 在rsync目录的上一级编排调用
- hosts: all
  roles:
    - role: rsync
      when: ansible_hostname == "backup"
posted @ 2025-03-21 08:57  丁志岩  阅读(55)  评论(0)    收藏  举报