准备(前戏)
安装
yum install ansible
查看与ansible相关的文件信息
rpm -ql ansible|less
命令与选项
hosts基本语法
主机与组
[webserver] www.exaple.com test.exaple.com [dbserver] one.example.com two.example.com
备注:端口号不是默认的时候,可以表示为
www.exaple.com:5122
主机别名
如果有些静态IP地址,希望设置一些别名,但不是在系统的host文件中做解析
test_name ansible_ssh_port=5122 ansible_ssh_host=192.168.100.1
主机名扩展
可以像bash那样设置一组名称类似的主机
[webserver] web[01:50].example.com db-[a:f].example.com
自定连接
对于每一个host,还可以选择连接类型和连接用户名
[targets] other1.example.com ansible_connection=ssh ansible_ssh_user=sam other2.example.com ansible_connection=ssh ansible_ssh_user=mdehaan
主机变量
在hosts中给主机设置变量,这样可以在playbook中使用
[web] host1 http_port=80 maxRequestsPerChild=808 host2 http_port=303 maxRequestsPerChild=909
组变量
通过关键字vars
[webserver] host1 host2 [webserver:vars] ntp_server=ntp.atlanta.example.com proxy=proxy.atlanta.example.com
把一个组作为另个组的子成员
[webserver] host1 host2 [dbserver] host3 host4 [saas:children] webserver dbserver [saas:vars] some_server=foo.southeast.example.com halon_system_timeout=30 self_destruct_countdown=60 escape_pods=2
Inventory参数说明
要连接的远程主机与设定的主机别名不同时
ansible_ssh_host
指定ssh端口号
ansible_ssh_port
指定连接用户名
ansible_ssh_user
指定连接密码(建议使用–ask-pass)
ansible_ssh_pass
指定sudo密码(建议–ask-sudo-pass)
ansibl_sudo_pass
指定sudo执行命令的路径
ansible_sudo_exe
指定与主机的连接类型
ansible_connection
使用指定密钥文件
ansible_privte_key_file
指定目标系统的shell类型
ansible_shell_type
指定目标主机的python路径(相同的方式可以指定ruby、perl)
ansible_python_interpreter
常用指令与选项
ansible
-u # 指定用户名 -k # 提示密码 -i # 使用指定主机清单 -m # 使用指定module,默认command -a # module参数
ansible-doc
-l # 列出所有module -s # 列出指定模块的使用方法
常用模块及使用方法
(1)配置hosts文件
[webserver] 192.168.100.131 192.168.100.132 [dbserver] 192.168.100.133
(2)配置ansible主机与个客户机间密钥认证(这里直接使用copy模块完成)
copy模块
ansible all -m copy -a 'src="/root/.ssh/id_rsa.pub" dest="/root/.ssh/authorized_keys" mode=600 backup="yes"' --ask-pass 说明: src # 源文件或文件夹(如果是源文件以/结尾,则只拷贝该目录下的内容) dest # 目标文件或目录(父目录不存在时会报错) mode # 权限 backup # 是否需要备份目标目录原来的文件
command模块
该模块是默认模块,示例分显示所有主机的时间
ansible all -m command -a "date"
user模块、group模块
例:在webserver组的每台主机上创建一个用户web1
ansible webserver -m user -a "name='web1' home='/home/test' system='yes' state='present'" 说明: name # 用户名 home # 用户home目录 system # 是否为系统用户 state # present或absent(present添加,absent删除)
cron模块
例:创建每周一12点执行echo "sam 你好"
ansible webserver -m cron -a "minute=0 hour=12 weekday=1 job='echo "sam 你好"' name='echo' state='present'" 说明: minute # 分钟(0-59,*/2) hour # 小时(0-23,*/2) day # 日(1-31,*/2) month # 月(1-12,*/2) weekday # 星期(0-6) name # 任务名称 backup # 是否需要备份原来的任务
copy模块
例:拷贝/etc/fstab到/tmp/fstab.ansible
ansible webserver -m copy -a "src=/etc/fstab dest=/tmp/fstab.ansible owner=root mode=644" 说明: src # 源文件 dest # 目标文件 owner # 文件属主 mode # 权限 content # 为目标文件指定内容,此时省略src ansible webserver -m copy -a "content='Hello sam' dest=/tmp/sam.txt "
file模块
例如:将webserver服务器/tmp/fstab.ansible 的文件权限更改为600
ansible webserver -m file -a "path=/tmp/fstab.ansible mode=600" 说明: path # 源文件(可以用name,dest) mode # 权限 owner # 属主 state # 如果是link,则表示要创建软连接(此时源文件用src表示) src # 源文件 ansible webserver -m file -a "path=/tmp/fstab.link state=link src=/tmp/fstab.ansible"
yum模块
例如:在webserver组安装httpd服务
ansible webserver -m yum -a "name=httpd state=present " ansible dbserver -m yum -a "name='*' state=latest" 说明: name # 包名称,如果state=latest,那么name可以为*表示运行yum update -y ;如果state=present,那么name可以指定本地的一个软件包路径; 也可以是一个用 逗号 分隔的软件包列表 state # (`present' or `installed', `latest'), or remove (`absent' or `removed') list # 等效于yum list
service模块
例如:启动webserver组的httpd服务,并设置为开机启动
ansible webserver -m service -a "name=httpd enabled=yes state=started " 说明: name # 服务名称 enabled # 是否开机启动 state # started,stopped,restarted,reloaded
shell模块
例如:查看正在运行的httpd服务的进程号
ansible webserver -m shell -a "ps axu|grep httpd"
script模块
首先创建一个shell脚本文件test.sh,内容如下:
#!/bin/bash a=`pwd` echo "This is $a" echo "Hello sam ansible from script" >/tmp/script.txt
然后执行ansible调用该脚本
ansible webserver -m script -a "/tmp/test.sh" 说明: 参数为脚本名,可以是绝对路径
功能模块ping、setup
ansible webserver -m ping 说明: 测试ansible主机与其他节点的连通性,成功返回 pong ansible webserver -m setup 说明: 返回节点的facts信息,这些变量可以在playbook中直接使用
playbook使用与配置
注意这里对于yml的配置文件有着严格的语法要求,缩进必须是2个空格(由于基础较差坑了我2个小时,python的4空格缩进0.0)
1、一个简单的playbook剧本:(注意复制的时候一定注意格式,缩进2个用空格)
- hosts: webserver # 主机组 remote_user: root # 远程连接用户 tasks: # 任务列表关键字 - name: Test connection # 任务名称 ping: # 模块名称
2、在webserver组创建一个组账户名称为nginx-group,创建个账户为nginx-user,并且nginx-user的基本组为nginx-group;然后拷贝当前主机/etc/fstab文件到dbserver组的/tmp目录并命名为fstab-name.ansible。
- hosts: webserver remote_user: root tasks: - name: Add nginx-group group: name=nginx-group gid=2018 system=yes - name: Add nginx-user user: name=nginx-user uid=2018 system=yes group=nginx-group home=/home/nginx shell=/bin/nologin - hosts: dbserver remote_user: root tasks: - name: Copy File to dbserver copy: src=/etc/fstab dest=/tmp/fstab-name.ansible mode=600
HANDLERS
1、现在我们需要在webserver组安装httpd服务,并且需要将其启动并设置为开机自启,并且使用我当前机器上httpd.conf文件作为其配置文件。
- hosts: webserver remote_user: root tasks: - name: Instarll httpd yum: name=httpd state=present - name: Configuration httpd file copy: src=/etc/httpd/conf/httpd.conf dest=/etc/httpd/conf/httpd.conf - name: Start service httpd service: name=httpd state=started enabled=yes
2、继续上面操我现在修改下本地的httpd.conf的监听端口为8080,然后重新执行playbook,并查看websever服务器的httpd端口启动情况。
[root@localhost ~]# ansible-playbook httpd.yml PLAY [webserver] ******************************************************************************************************************************** TASK [Gathering Facts] ************************************************************************************************************************** ok: [192.168.100.131] ok: [192.168.100.132] TASK [Instarll httpd] *************************************************************************************************************************** ok: [192.168.100.131] ok: [192.168.100.132] TASK [Configuration httpd file] ***************************************************************************************************************** changed: [192.168.100.132] changed: [192.168.100.131] TASK [Start service httpd] ********************************************************************************************************************** ok: [192.168.100.131] ok: [192.168.100.132] PLAY RECAP ************************************************************************************************************************************** 192.168.100.131 : ok=4 changed=1 unreachable=0 failed=0 192.168.100.132 : ok=4 changed=1 unreachable=0 failed=0 [root@localhost ~]# ansible webserver -a "ss -tnpl" 192.168.100.131 | SUCCESS | rc=0 >> State Recv-Q Send-Q Local Address:Port Peer Address:Port LISTEN 0 128 *:22 *:* users:(("sshd",pid=968,fd=3)) LISTEN 0 100 127.0.0.1:25 *:* users:(("master",pid=1079,fd=13)) LISTEN 0 128 :::80 :::* users:(("httpd",pid=2550,fd=4),("httpd",pid=2549,fd=4),("httpd",pid=2548,fd=4),("httpd",pid=2547,fd=4),("httpd",pid=2546,fd=4),("httpd",pid=2545,fd=4)) LISTEN 0 128 :::22 :::* users:(("sshd",pid=968,fd=4)) LISTEN 0 100 ::1:25 :::* users:(("master",pid=1079,fd=14)) 192.168.100.132 | SUCCESS | rc=0 >> State Recv-Q Send-Q Local Address:Port Peer Address:Port LISTEN 0 128 *:22 *:* users:(("sshd",pid=971,fd=3)) LISTEN 0 100 127.0.0.1:25 *:* users:(("master",pid=1078,fd=13)) LISTEN 0 128 :::80 :::* users:(("httpd",pid=2519,fd=4),("httpd",pid=2518,fd=4),("httpd",pid=2517,fd=4),("httpd",pid=2516,fd=4),("httpd",pid=2515,fd=4),("httpd",pid=2514,fd=4)) LISTEN 0 128 :::22 :::* users:(("sshd",pid=971,fd=4)) LISTEN 0 100 ::1:25 :::* users:(("master",pid=1078,fd=14))
如上所示,配置文件发生了更改但是httpd服务的启动端口并未发生更改,原因在于更了配置文件,可是httpd服务并未重启。
这时候我们就需要用HANDLERS功能,简单点说该功能就是在某个任务执行完成后自动触发指定任务。据说不仅仅可以使用任务触发还可以使用某些主机触发(比如某些主机执行完一些任务后,主要区别在于notify的位置),下面我就用任务触发举个例子
- hosts: webserver remote_user: root tasks: - name: Instarll httpd yum: name=httpd state=present - name: Configuration httpd file copy: src=/etc/httpd/conf/httpd.conf dest=/etc/httpd/conf/httpd.conf notify: # handlers触发关键字 - Restart httpd # handlers中的任务名 - name: Start service httpd service: name=httpd state=started enabled=yes handlers: # 和tasks同级 - name: Restart httpd service: name=httpd state=restarted
playbook中使用变量
自定义变量
我们现在定义两个变量,分别为package_name、service_name,然后分别给这两个变量赋值,最后通过引用这两个变量在执行playbook。
1、例如:现在我需要停掉webserver组服务器的httpd服务,最后要卸载httpd服务(其实引用变量的方法很简单就是{{变量名}})
- hosts: webserver remote_user: root vars: - package_name: httpd - service_name: httpd tasks: - name: Stopped {{service_name}} service: name={{service_name}} state=stopped - name: remove {{package_name}} yum: name={{package_name}} state=removed
facts中的变量
1、例如,我们将webserver中每台主机的IP地址写到/tmp/ip.txt文件(这里借助copy模块中content完成)
- hosts: webserver remote_user: root tasks: - name: copy file for ip address copy: content={{ansible_all_ipv4_addresses}} dest=/tmp/ip.txt mode=600
playbook中使用条件测试
我们继续上面的例子,在webserver组中,删除ip地址为192.168.74.131主机的/tmp目录下的ip.txt文件
- hosts: webserver remote_user: root tasks: - name: Delete ip.txt shell: rm -rf /tmp/ip.txt when: ansible_all_ipv4_addresses==["192.168.100.131"]
playbook中使用迭代
1、例如:要在webserver组分别创建web1和sam1账户(当然你也可以建立多个tasks任务,显然这不是我们希望的样子)
- hosts: webserver remote_user: root tasks: - name: Add web1 sam1 user: name={{item}} state=present # 使用关键字变量item with_items: # 定义关键字变量值的列表 - web1 - sam1
2、除了单个变量的迭代,还可以支持成组的变量迭代,比如创建用户web2并且所数组为web3,创建用户sam2,所属组为sam3
- hosts: webserver remote_user: root tasks: - name: Add group sam3 web3 group: name={{item}} state=present with_items: - sam3 - web3 - name: Add web1 sam1 user: name={{item.name}} group={{item.group}} state=present # 用item引用字典的键做变量 with_items: # 以字典序列的形式定义变量 - {name: sam2, group: sam3} - {name: web2, group: web3}
在playbook中使用Templates
简单描述下,Templates
(1)用定义的变量替换模板中的具体参数
(2)在plabook中用关键字template代替copy模块名
例:我们在hosts文件中为两个webserver分别指定不同的httpd端口,并且希望httpd配置文件中的hostname为本机的fqdn
(1)首先我们先在INVENTORY文件中分别为两个webserver主机创建两个变量,httpd_port、web_root分别为httpd的端口、网站根目录并且定义ServerName为本机主机名(引用ansible facts中的ansible_fqdn变量)
[webserver] 192.168.100.131 http_port=9000 web_root="/home/web1" 192.168.100.132 http_port=8000 web_root="/home/web2"
(2)在两台webserver分别创建网站根目录/home/web1、/home/web2
ansible 192.168.100.131 -a "mkdir /home/web1" ansible 192.168.100.132 -a "mkdir /home/web2"
我们需要在ansible服务端创建一个/tmp/httpd.conf.j2格式的模板文件,我们直接选用httpd.conf的配置文件为基础模板,只在下面几个特殊地方写入变量代替
Listen {{http_port}} ServerName {{ansible_fqdn}} DocumentRoot "{{web_root}}"
playbook中使用tags(标签)
在playbook中可以为某个或某些任务定义一个“标签”,在执行此playbook时,通过为ansible-playbook命令使用–tags选项能实现仅运行指定的taks而非所有的。
例如
- hosts: webserver remote_user: root tasks: - name: Uninstarll httpd yum: name=httpd state=absent - name: Configuration httpd file template: src=/tmp/httpd.conf.j2 dest=/etc/httpd/conf/httpd.conf notify: - Restart httpd - name: Stop service httpd service: name=httpd state=stopped tags: # 关键字 - stop # 标签名 handlers: - name: Restart httpd service: name=httpd state=restarted
运行方式:
ansible-playbook template.yml --tags='start'
roles
(1)目录名同角色名
(2)目录结构有固定格式:files、templates、tasks、handlers、vars、meta
(3)site.yml中定义playbook,额外也可以定义其它的yml文件。
例:
(1)定义个web角色
(2)该角色包含安装httpd服务,
(3)定义该服务一个httpd的模板文件,使httpd的ServerName为启动服务器的本机名
(4)并且在vars中定义个变量http_port,web_root分别为"81","/home"
(5)启动该服务,并设置开机自
(6)先使用webserver组调用该角色,然后在使用dbserver调用该角色
(1)创建角色及相关目录
mkdir -pv /etc/ansible/roles/web/{tasks,files,templates,meta,handlers,vars}
(2)编辑/etc/ansible/roles/web/tasks/main.yml文件
- name: Install httpd yum: name=httpd state=present - name: Install httpd.conf template: src=httpd.conf.j2 dest=/etc/httpd/conf/httpd.conf notify: - Restart httpd - name: Start httpd service: name=httpd state=started enabled=yes
(3)编辑/etc/ansible/roles/web/handlers/main.yml文件
- name: Restart httpd service: name=httpd state=restarted
(4)编辑/etc/ansible/roles/web/templates/httpd.conf.j2
我们需要在ansible服务端创建一个/tmp/httpd.conf.j2格式的模板文件,我们直接选用httpd.conf的配置文件为基础模板,只在下面几个特殊地方写入变量代替
Listen {{http_port}} ServerName {{ansible_fqdn}} DocumentRoot "{{web_root}}"
(5)编辑/etc/ansible/roles/web/vars/main.yml
http_port: 81 web_root: "/home"
(7)编辑/etc/ansible/roles/site.yml
- hosts: webserver remote_user: root roles: - web - hosts: dbserver remote_user: root roles: - web
(8)执行playbook
ansible-playbook /etc/ansible/roles/site.yml
生活真难,因为工作原因熬夜到2,连续3天才总结出来,如果你学会了点个赞吧。