Ansible基础,[rootserve


配置环境

yum install wget -y
wget -O /etc/yum.repos.d/epel.repo http://mirrors.aliyun.com/repo/epel-7.repo

下载ansible

yum install ansible -y

安装与了解

查看版本与配置文件

# 查看版本
[root@server ~]# ansible --version
ansible 2.9.27
  config file = /etc/ansible/ansible.cfg
  configured module search path = [u'/root/.ansible/plugins/modules', u'/usr/share/ansible/plugins/modules']
  ansible python module location = /usr/lib/python2.7/site-packages/ansible
  executable location = /usr/bin/ansible
  python version = 2.7.5 (default, Apr 11 2018, 07:36:10) [GCC 4.8.5 20150623 (Red Hat 4.8.5-28)]
​
# 查看配置文件所在位置
[root@server ~]# rpm -qc ansible
/etc/ansible/ansible.cfg        //全局配置文件
/etc/ansible/hosts              //全局主机清单文件

生成秘钥

[root@server ~]# ssh-keygen 
[root@server ~]# cat /root/.ssh/id_rsa.pub 
ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDWhVpJQgu8npiXHLMb81w2ZseUFkADQslYpreoKw0n4bpWqE8iEtV6bYfIBoHb5sr1bMz945H9tzh+qmmuPMT9FLy/LBDXRcDvnZfRPLGyftrO+Zt/FMySxpmeQbcRMHggpIyiQePC4zo/6nrROSh1CRj/05KhYBbjNJSS9z9WnUSOfWa4CVzSRr67JFpgCTOxD1tsxzOLs1AhguUXrPGbgbLva5fW9IQO/kGBH6ZaLzWY1+diy6VP+B3gJx+w+Lllp1pqvO/mjGvqWG8Ib7MtP7M39UttkCutZmPC688v03VurufxuNPm/qlWwrShl0weO5VSl4gRvUHiVjFlhEXh root@server
​
# 复制到server_1到server_2里可以直接免密码登录
[root@server ~]# ssh-copy-id 192.168.100.30
[root@server ~]# ssh-copy-id 192.168.100.40

配置ansible

# 创建主机组(可以创建多个)
[root@server ~]# vim /etc/ansible/hosts
## db-[99:101]-node.example.com
[server]
192.168.100.30
192.168.100.40
​
# 远程链接模块(-m:使用模块 -f:使用交互式输入ssh的密码)
[root@server ~]# ansible -m ping 192.168.100.30
192.168.100.30 | SUCCESS => {
    "ansible_facts": {
        "discovered_interpreter_python": "/usr/bin/python"
    }, 
    "changed": false, 
    "ping": "pong"
}
​
# 查看主机组里的主机内存使用情况
[root@server ~]# ansible -m shell -a "free -m" server
192.168.100.40 | CHANGED | rc=0 >>
              total        used        free      shared  buff/cache   available
Mem:           3773         125        3457          11         189        3412
Swap:          3071           0        3071
192.168.100.30 | CHANGED | rc=0 >>
              total        used        free      shared  buff/cache   available
Mem:           3773         125        3458          11         189        3413
Swap:          3071           0        3071

ansible命令参数

参数                      功能
-i                      指定hosts文件路径,默认在/etc/ansible/hosts
-m                      指定使用的module名称,默认command模块
-a                      指定模块参数
-k(小写)                  提示输入ssh密码,并非基于ssh密钥认证
-K(大写)                  提示输入sudo密码
-b                      使用sudo执行命令
-become-user=               指定sudo的用户
-f,-forks=NUM               NUM默认是整数5,指定fork开启同步进程的个数
-u                          指定远程主机的执行用户
-v                      详细模式,如果执行成功,输出详细结果,-vv -vvv更详细过程
-C                      预执行检测
-T                      执行命令的超时时间,默认10s
--list                  显示主机列表,也可以用--list-hosts
--version               显示版本

ansible配置清单

构建清单

[root@server ~]# cd /etc/ansible/
[root@server ansible]# vim skk
server2
​
[test]
192.168.100.30[demo]
192.168.100.40
​
# 查看 skk 清单中的主机
[root@server ansible]# ansible all -i skk --list-hosts
  hosts (3):
    server2
    192.168.100.30
    192.168.100.40
​
# 查看 skk 清单中未定义组的主机
[root@server ansible]# ansible ungrouped -i skk --list-hosts
  hosts (1):
    server2
​
# 查看 skk 清单中组为test的主机
[root@server ansible]# ansible test -i skk --list-hosts
  hosts (1):
    192.168.100.30

嵌套清单

[root@server ansible]# cat skk
server2
​
[test]
192.168.100.30[demo]
192.168.100.40[westos:children]
test
demo
[root@server ansible]# ansible westos -i skk --list-hosts
  hosts (2):
    192.168.100.30
    192.168.100.40

主机范围化

[root@server ansible]# cat end
[end]
192.168.100.[1:10]
[root@server ansible]# ansible end -i end --list-hosts
  hosts (10):
    192.168.100.1
    192.168.100.2
    192.168.100.3
    192.168.100.4
    192.168.100.5
    192.168.100.6
    192.168.100.7
    192.168.100.8
    192.168.100.9
    192.168.100.10

指定清单的正则表达式

*               所有
:               逻辑或
:&              逻辑与
:!              逻辑非
~               以关键字开头
~(str1|str2)     以条件1或条件2开头
[root@server ansible]# cat inventory 
[wes_list1]
192.168.100.100
192.168.100.101
[wes_list2]
192.168.0.100
192.168.0.101
[wes_list3]
172.166.0.2
172.166.0.1
192.168.100.200
192.160.0.20
[wes_all:children]
wes_list2
wes_list3
​
[root@server ansible]# ansible '192.*' -i inventory --list
  hosts (6):
    192.160.0.20
    192.168.100.200
    192.168.0.101
    192.168.0.100
    192.168.100.100
    192.168.100.101
[root@server ansible]# ansible '~wes' -i inventory --list
  hosts (8):
    172.166.0.2
    172.166.0.1
    192.168.100.200
    192.160.0.20
    192.168.0.100
    192.168.0.101
    192.168.100.100
    192.168.100.101
[root@server ansible]# ansible 'wes_list1:wes_list3' -i inventory --list 
  hosts (6):
    192.168.100.100
    192.168.100.101
    172.166.0.2
    172.166.0.1
    192.168.100.200
    192.160.0.20

ansible常用模块

模块文档

[root@server ~]# cat /etc/ansible/hua
[hua]
192.168.100.30
192.168.100.40Command:在远程主机执行命令,默认模块,可忽略-m选项(注:此命令不支持 $varname < > | ; $等命令)
    > ansible hua -m command -a "systemctl start httpd"
    > ansible all -m command -a "ls /root"
    
Shell:和 command 命令相似,用 shell 执行命令
    > ansible all -m shell -a "getenforce"
    > ansible all -m shell  -a "sed -i 's/SELINUX=.*/SELINUX=disabled' /etc/selinux/config"
    
Script:在远程主机上运行 ansible 服务器上的脚本
    > ansible hua -m scrpit -a /data/test.sh
    
Copy:从主控端复制文件到远程主机
      src : 源文件  指定拷贝文件的本地路径  (如果有/ 则拷贝目录内容,比拷贝目录本身)
      dest: 指定目标路径
      mode: 设置权限
      backup: 备份源文件
      content: 代替src  指定本机文件内容,生成目标主机文件
      
      > ansible hua -m copy -a "src=/root/test1.sh dest=/tmp/test2.showner=wang mode=600 backup=yes"
        如果目标存在,默认覆盖,此处指定先备份
      > ansible hua -m copy -a "content='test content\nxxx' dest=/tmp/test.txt"
        指定内容,直接生成目标文件
​
Fetch:从远程主机提取文件至主控端,copy相反,目前不支持目录,可以先打包,再提取文件
     > ansible hua -m fetch -a 'src=/root/test.sh dest=/data/scripts'
     会生成每个被管理主机不同编号的目录,不会发生文件名冲突
     
     > ansible all -m shell -a 'tar jxvf test.tar.gz /root/test.sh'
     > ansible all -m fetch -a 'src=/root/test.tar.gz dest=/data/'
​
File:设置文件属性
    path: 要管理的文件路径 (强制添加)
    recurse: 递归,文件夹要用递归
    src:  创建硬链接,软链接时,指定源目标,配合'state=link' 'state=hard' 设置软链接,硬链接
    state: 状态
          absent 缺席,删除
          
    > ansible hua -m file -a 'path=/app/test.txt state=touch'       创建文件
    > ansible hua -m file -a "path=/data/testdir state=directory"   创建目录    
    > ansible hua -m file -a "path=/root/test.sh owner=wang mode=755"  设置权限755
    > ansible hua -m file -a 'src=/data/testfile dest=/data/testfile-link state=link' 创建软链接
    
    
unarchive:解包解压缩,有两种用法:
    1、将ansible主机上的压缩包传到远程主机后解压缩至特定目录,设置copy=yes.
    2、将远程主机上的某个压缩包解压缩到指定路径下,设置copy=no
​
    常见参数:
        copy:默认为yes,当copy=yes,拷贝的文件是从ansible主机复制到远程主机上,
              如果设置为copy=no,会在远程主机上寻找src源文件
        src: 源路径,可以是ansible主机上的路径,也可以是远程主机上的路径,
              如果是远程主机上的路径,则需要设置copy=no
        dest:远程主机上的目标路径
        mode:设置解压缩后的文件权限
    
    示例:
        ansible hua -m unarchive -a 'src=foo.tgz dest=/var/lib/foo'  
          #默认copy为yes ,将本机目录文件解压到目标主机对应目录下
        ansible hua -m unarchive -a 'src=/tmp/foo.zip dest=/data copy=no mode=0777'
          # 解压被管理主机的foo.zip到data目录下, 并设置权限777
        ansible hua -m unarchive -a 'src=https://example.com/example.zip dest=/data copy=no'
​
Archive:打包压缩
    > ansible all -m archive -a 'path=/etc/sysconfig dest=/data/sysconfig.tar.bz2 format=bz2 owner=wang mode=0777'
    将远程主机目录打包 
        path:   指定路径
        dest:   指定目标文件
        format: 指定打包格式
        owner:  指定所属者
        mode:   设置权限
​
Hostname:管理主机名
    ansible appsrvs -m hostname -a "name=app.adong.com"  更改一组的主机名
    ansible 192.168.100.30 -m hostname -a "name=app2.adong.com" 更改单个主机名
​
Cron:计划任务
    支持时间:minute,hour,day,month,weekday
    > ansible hua -m cron -a "minute=*/5 job='/usr/sbin/ntpdate 172.16.0.1 &>/dev/null' name=Synctime" 
    创建任务
    > ansible hua -m cron -a 'state=absent name=Synctime' 
    删除任务
    > ansible hua -m cron -a 'minute=*/10 job='/usr/sbin/ntpdate 172.30.0.100" name=synctime disabled=yes'
    注释任务,不在生效
   # 另一种创建定时文件类型
   ansible hua -m cron -a "name='test cron'job='/tmp/test.sh'weekday=6 state=present"Yum:管理包
    ansible hua -m yum -a 'list=httpd'  查看程序列表
    
    ansible hua -m yum -a 'name=httpd state=present' 安装
    ansible hua -m yum -a 'name=httpd state=absent'  删除
    可以同时安装多个程序包
    
Service:管理服务
    ansible hua -m service -a 'name=httpd state=stopped'  停止服务
    ansible hua -m service -a 'name=httpd state=started enabled=yes' 启动服务,并设为开机自启
    ansible hua -m service -a 'name=httpd state=reloaded'  重新加载
    ansible hua -m service -a 'name=httpd state=restarted' 重启服务
​
User:管理用户
    home   指定家目录路径
    system 指定系统账号
    group  指定组
    remove 清除账户
    shell  指定shell类型
    
    ansible hua -m user -a 'name=user1 comment="test user" uid=2048 home=/app/user1 group=root'
    ansible hua -m user -a 'name=sysuser1 system=yes home=/app/sysuser1'
    ansible hua -m user -a 'name=user1 state=absent remove=yes'  清空用户所有数据
    ansible hua -m user -a 'name=app uid=88 system=yes home=/app groups=root shell=/sbin/nologin password="$1$zfVojmPy$ZILcvxnXljvTI2PhP2Iqv1"'  创建用户
    ansible websrvs -m user -a 'name=app state=absent'  不会删除家目录
    
    安装mkpasswd 
    yum insatll expect 
    mkpasswd 生成口令
    openssl passwd -1  生成加密口令
    
​
删除用户及家目录等数据
    Group:管理组
        ansible srv -m group -a "name=testgroup system=yes"   创建组
        ansible srv -m group -a "name=testgroup state=absent" 删除组

ansible配置文件

分类配置于优化

/etc/ansible/ansible.cfg基本配置文件,找不到其他配置文件此文件有效
~/.ansible.cfg用户当前目录中没有ansible.cfg此文件生效
./ansible.cfg优先级最高

常用配置参数

[default]                       基本配置信息
inventory=                      指定清单路径
remote_user=                    在远程主机上登陆的用户名称,未指定使用当前用户
ask_pass=                       是否提示输入SSH密码,如果公钥登陆设定为false
library=                        库文件存放目录
local_tmp=                      本机临时命令执行目录
remote_tmp=                     远程主机临时py命令文件存放目录
forks=                          默认并发数量
host_key_checking=              第一次连接远程主机时是否要输入yes建立host_key
sudo_user=                      默认sudo用户
ask_sudo_pass=                  每次在远程主机执行ansible命令时是否询问sudo密码
module_name=                    默认模块,默认使用command,可以修改为shell
log_path=                       日志文件路径
[privilege_escalation]              身份信息设定
become=                         连接后是否自动切换用户
become_method=                  设定切换用户的方式,通常用sudo
become_user=                    在远程主机中切换到的用户,通常为root
become_ask_pass                 是否需要为become_method提示输入密码,默认为false
​
建议优化项: 
host_key_checking = False               # 检查对应服务器的host_key,建议取消注释
log_path=/var/log/ansible.log           # 日志文件,建议取消注释
module_name   = command                 # 默认模块

python储存文件

remote_tmp和local_tmp是远端的本地临时文件路径;当执行ansible命令后,主机生成py临时脚本,通过ssh发送到远程主机,远程主机执行完删除该临时文件,主机也会删除临时文件。

[root@server ansible]# vim ansible.cfg
    17 remote_tmp     = ~/.ansible/tmp
    18 local_tmp      = ~/.ansible/tmp
# 执行远程主机等待60秒的命令,监控两边是否有临时文件产生,等待50秒后,生成的两个临时文件自动消失
[root@server ansible]# ansible 192.168.100.30 -m shell -a 'sleep 50' -u root -b 
192.168.100.30 | CHANGED | rc=0 >>
​
# 查看是否升成文件,50秒后是否删除
[root@server_1 ~]# ls -l /root/.ansible/tmp/
总用量 0
drwx------ 2 root root 34 419 15:13 ansible-tmp-1650352382.93-13031-164002468046075
[root@server_1 ~]# ls -l /root/.ansible/tmp/
总用量 0

默认执行become模块

执行命令时,连接远程主机的用户为devops,在远程主机中操作指令时转换用户身份,并用sudo调用为root用户,执行sudo调用命令时不提示输入密码。不需要加-b和 -K

[root@server ansible]# vim ansible.cfg 
    107 remote_user = root
    341 become=True
    342 become_method=sudo
    343 become_user=root
    344 become_ask_pass=False[root@server ansible]# ansible 192.168.100.30 -m shell -a 'hostname' -v
Using /etc/ansible/ansible.cfg as config file
192.168.100.30 | CHANGED | rc=0 >>
server_1

不同用户配置

ansible 只有一个主配置文件,不同用户的配置不同时,需要把配置独立出来,一个用户一个配置文件。需要该用户创建配置目录及配置文件,只有在配置目录时,才会优先读取该用户的配置文件。

创建用户及配置

[root@server ~]# useradd hua
[root@server ~]# passwd hua
[root@server ~]$ mkdir /home/hua/ansible
[root@server ~]# su hua
[hua@server root]$ cd /home/hua/ansible/
[hua@server ansible]$ cat ansible.cfg 
    [defaults]
    inventory               = ~/ansible/inventory
    host_key_checking       = False
    ask_pass                = False
    remote_user             = root
    module_name             = shell
​
    [privilege_escalation]
    become=True
    become_method=sudo
    become_user=root
    become_ask_pass=False
[hua@server ansible]$ cat inventory 
[test]
192.168.100.30
192.168.100.40

把ansible主机秘钥给用户

[hua@server ansible]$ su root
[root@server ~]# scp ~/.ssh/id_rsa hua@192.168.100.20:~/.ssh/

测试

[root@server ~]# su hua
[hua@server ~]$ cd ansible/
[hua@server ansible]$ ansible test -m ping -v
Using /home/hua/ansible/ansible.cfg as config file
192.168.100.40 | SUCCESS => {
    "ansible_facts": {
        "discovered_interpreter_python": "/usr/bin/python"
    }, 
    "changed": false, 
    "ping": "pong"
}
192.168.100.30 | SUCCESS => {
    "ansible_facts": {
        "discovered_interpreter_python": "/usr/bin/python"
    }, 
    "changed": false, 
    "ping": "pong"
}

playbook

根本上说playbook和shell脚本没有任何的区别,playbook就像shell一样,也是把一堆的命令组合起来,然后加入对应条件判断等等,在shell脚本中是一条一条的命令,而在playbook中是一个一个的task任务构成,每个task任务可以看做shell中的一条命令;shell脚本一般只是在当前服务器上执行,而playbook则是在不止一个服务器上执行,因此playbook需要在其中指定运行该playbook的服务器名。

YAML语法

  • 缩进表示层级关系
  • 不支持制表符Tab缩进,只能使永空格缩进
  • 通常开头缩进2个空格
  • 字符后缩进1个空格,如冒号,逗号等
  • “—”表示YAML格式,一个文件的开始
  • “#”注释

handlers命令

是上一条命令未执行就不执行下面的命令

  • notify:在任务结束时触发
  • handlers:由特定条件触发Taskes

注:ansible-playbook会检测文件是否于上一次一样

# text.txt 拷贝到远程主机 /root 目录下。 notify:Copy text 执行完触发 notify 上面的执行成功就执行下面 handlers。 他俩是配合使用的
[root@elk-1 ~]# cat ansible_text.yml 
---
 - hosts: hua
  gather_facts: no
​
  tasks:
    - name: Copy text
      copy: 
        src: /root/text.txt
        dest: /root/ttt.txt
        notify: 
          - restart HTTPD
​
  handlers:
    - name: restart HTTPD
      shell: systemctl start httpd

tags任务控制

  • 指定只执行某个模块
  • 跳过某个模块执行
指定执行:ansible-playbook +文件.yml --tages "+tags模块名"
跳过执行:ansible-playbook +文件.yml--skip-tages "+tags模块名"
[root@elk-1 ~]# cat ansible_text.yml 
---
- hosts: hua
  gather_facts: no
​
  tasks:
    - name: ECHO
      shell: echo 123 > /etc/profile
      tags: ECHO
​
    - name: YUM 
      yum: name=httpd
      tags: YUM
​
# 他就执行 YUM这个命令
[root@elk-1 ~]# ansible-playbook ansible_text.yml --tags "YUM"
​
PLAY [hua] ************************************************************************************
​
TASK [YUM] ************************************************************************************
changed: [192.168.100.30]
​
PLAY RECAP ************************************************************************************
192.168.100.30             : ok=1    changed=1    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0 

文件调试

调试语法

anible-playbook +执行文件.yml --syntax-check

打印语法:bebug

# 直接就会打印出来目标执行组这个名字变量
[root@elk-1 ~]# cat ansible_text.yml 
---
 - hosts: hua
​
  tasks:
    - name: DEBUG
      debug: msg="{{group_names}}"
      
[root@elk-1 ~]# ansible-playbook ansible_text.yml
​
PLAY [hua] ********************************************************************************************************
​
TASK [Gathering Facts] ********************************************************************************************
ok: [192.168.100.30]
​
TASK [DEBUG] ******************************************************************************************************
ok: [192.168.100.30] => {
    "msg": [
        "hua"
    ]
}
​
PLAY RECAP ********************************************************************************************************
192.168.100.30             : ok=2    changed=0    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0 

变量

  • linux有内置的变量(linux里自带的变量)
  • hosts文件中定义变量
/etc/ansible/hosts 文件里创建变量
  • playbook中定义变量
[root@elk-1 ~]# cat ansible_text.yml 
---
- hosts: hua
  gather_facts: no
  remote_user: root
  vars:
    - cd_data: /usr/local/
    - date_time: date +"%F_%T"
​
  tasks:
    - name: Touch
      file: dest={{cd_data}}/{{date_time}} state=touch

相关内容