Ansible (底层是基于ssh连接的,每次操作其他主机需要输入密码 ,所以首先要实现基于key的公钥验证)
使用ansible:
ansible "192.168.60.3" -m shell -a 'ls /root' -k (单个用户在实现基于key的验证前)
安装ansible:
yum包的安装:
yum install ansible (此包依赖于base源和epel源,安装前确保两个yum源可以使用)
编译安装:
yum -y install python-jinja2 PyYAML python-paramiko python-babel python-crypto
tar xf ansible-1.5.4.tar.gz
cd ansible-1.5.4
python setup.py build
python setup.py install
mkdir /etc/ansible
cp -r examples/* /etc/ansible
相关文件
配置文件
/etc/ansible/ansible.cfg 主配置文件,配置ansible工作特性
/etc/ansible/hosts 主机清单 (将要连接操控的主机IP地址写在此配置文件的最下方)
/etc/ansible/roles/ 存放角色的目录
程序
/usr/bin/ansible 主程序,临时命令执行工具
/usr/bin/ansible-doc 查看配置文档,模块功能查看工具
/usr/bin/ansible-galaxy 下载/上传优秀代码或Roles模块的官网平台
/usr/bin/ansible-playbook 定制自动化任务,编排剧本工具/
usr/bin/ansible-pull 远 程执行命令的工具
/usr/bin/ansible-vault 文件加密工具
/usr/bin/ansible-console 基于Console界面与用户交互的执行工具
主机清单inventory (里面列有要操控服务器的IP地址,需要自己手动来添加)
配置文件路径:/etc/ansible/hosts
格式:可以一连串写下去,也可分组,组与组之间的所拥有的服务IP地址可重复:
[lvserver] (此为组名为自定义命名)
192.168.60.3
192.168.60.4
webserve] (此为组名为自定义 命名)
192.168.60.3
192.168.60.5
192.168.60.6
将上述IP地址添加到主机清单配置文件的最后一行就可以了。
ansible系列命令 (查看ansible里的各个模块的使用方法)
ansible-doc: 显示模块帮助
-a 显示所有模块的文档
-l, –list 列出可用模块
-s, –snippet 显示指定模块的playbook片段
示例:
ansible-doc –l 列出所有模块
ansible-doc ping 查看指定模块(ping)帮助用法
ansible-doc –s ping 查看指定模块(ping)帮助用法
如何使用ansible
1 实现基于key的公钥验证:(基于key的验证可以在装系统时写进脚本,装完系统后就可以实现了)
生成私钥对,之后再将其公钥发送到各台服务器上的指定位置就可以了:
ssh-keygen -t rsa (生成密钥)
ssh-copy-id 192.168.60.5 (发送密钥,如需要批量发送公钥文件到多台主机查看第九周的博客)
小结:如果不实现基于key的验证,则每次使用ansible操作远程服务器时都需要输入密码,而且需要所有服务器的密码是相同的,如果一组当中有一个服务器的密码不同,第一次连不上,改成相同的密码后还是会连不上的,除非单独先连接一次此IP的地址让他的密钥加进/root/.ssh/know_host里面,或者将know_host里的内容删掉。因为是基于ssh的连接。
ansible <host-pattern> [-m module_name] [-a args]
-m module 指定模块,默认为command (使用command模块时可以不用写commmand )
-v 详细过程 –vv -vvv更详细
–list-hosts 显示主机列表,可简写—list
-k, –ask-pass 提示连接密码,默认Key验证
-K, –ask-become-pass 提示输入sudo
-C, –check 检查,并不执行 (检查语法是否有错并不执行,在执行playbook剧本前使用)
-b, –become 代替旧版的sudo 切换
-T, –timeout=TIMEOUT 执行命令的超时时间,默认10s
-u, –user=REMOTE_USER 执行远程执行的用户
匹配主机的列表 :
ansible "192.168.60.5" -m command -a 'ls /root' (此为一个命令的示例)
All :表示所有Inventory(主机列表)中的所有主机
ansible all –m ping
* :通配符
ansible “*” -m ping (*代表所有)
ansible 192.168.1.* -m ping (匹配后面的一部分)
ansible “*srvs” -m ping (匹配组名的一部分)
或关系
ansible “websrvs:appsrvs” -m ping (取两个组的中IP地址的合集)
ansible “192.168.1.10:192.168.1.20” -m ping (两个IP地址都ping)
与的关系
ansible “websrvs:&dbsrvs” –m ping( 在websrvs组并且在dbsrvs组中的主机)
逻辑非
ansible ‘websrvs:!dbsrvs’ –m ping (在websrvs组,但不在dbsrvs组中的主机 )
ansible命令执行过程
1. 加载自己的配置文件 默认/etc/ansible/ansible.cfg
2. 加载自己对应的模块文件,如command
3. 通过ansible将模块或命令生成对应的临时py文件,并将该 文件传输至远程服务器 的对应执行用户$HOME/.ansible/tmp/ansible-tmp-数字/XXX.PY文件
4. 给文件+x执行
5. 执行并返回结果
6. 删除临时py文件,sleep 0退出
执行状态: (通过颜色来判断执行的结果)
绿色:执行成功并且 没有对目标主机进行更改操作
黄色:执行成功并且对目标主机做变更
红色:执行失败
ansible常用模块及其具体用法:
1 . Command模块:在远程主机执行命令的模块,此模块为默认模块可以不用加 -m选项
此命令不支持 $VARNAME < > | ; & 等,用shell模块实现
2 . Shell模块:ansible all -m shell -a '要执行的命令' ,可以执行bash里的所有命令,可添加各种符号。
3 . Script:运行脚本的模块
ansible all -m script -a f1.sh (脚本加上执行权限后,写上绝对路径)
4 . Copy: 从主控端复制文件到众多的操控端服务器的模块
ansible all -m copy -a "src=/root/f1.sh dest=/data/f2.sh owner=wang mode=600 backup=yes"
src:为源文件 dest:为要复制到的地方 owner:设置所有者 mode:文件的权限设置
backup=yes 如果不等于yes,如果此处与源文件有相同的文件,则会覆盖掉;相反的化backup=yes如果此处有与源文件相同的文件,会自动将此文件加上日期并改名后备份,源文件在复制到此处。
4.1 Fetch:从客户端取文件至服务器端,copy相反,目录可先用tar打包后再抓取
ansible all -m fetch -a ‘src=/root/(要抓取的文件) dest=/data/(抓取后存放的位置)
5 . Cron:计划任务任务模块:
支持时间:minute,hour,day,month,weekday
创建任务 计划任务:
ansible all -m cron -a “minute=*/5 job=‘/usr/sbin/ntpdate 172.16.0.1 &>/dev/null’ name=jobss1”
其他的时间不写默认为*(“每”的意思)命令要写全他在的路径 例如/bin/touch f1
删除计划任务 :
ansible all -m cron -a ‘ name=jobss1 state=absent ’
state=absent (state为状态 absent 删除)
name=jobss1 (为要删除的计划任务的名字,新建计划任务定义的名字)
6 . File模块:设置文件属性 (对文件来操作,删除,新建,软连接)
ansible all -m file -a "name=/root/a.sh state=touch owner=wang mode=755“ :新建文件
ansible all -m file -a ‘src=/app/testfile dest=/app/testfile-link state=link’ 两个文件建立硬链接
state=touch (新建文件)
state=directory (新建文件夹)
state=line (建立链接)
stste=absent (删除文件和文件夹以及链接)
具体及详细信息请查看帮助:ansible-doc -s file (前面为固定模式,后面为模块的名称)
7 . Yum模块:管理包
ansible all -m yum -a ‘name=httpd state=latest’ 使用yum模块安装httpd软件
ansible all -m yum -a ‘name=httpd state=absent’ 使用yum模块删除 httpd软件
ansible all -m yum -a 'name=/data/vftpd 3.0-27………………rpm' 安装单个rpm包。不依赖于yum仓库,但需要推送到每个被控端的主机。
8 . Service模块:管理服务 (启动,暂停,重启服务)
ansible all -m service -a 'name=httpd state=stopped' (停止服务)
ansible all -m service -a 'name=httpd state=started' (开启服务)
ansible all –m service –a ‘name=httpd state=reloaded’ (重新加载此服务)
ansible all -m service -a 'name=httpd state=restarted' (重启此服务)
9 . User模块:管理用户
ansible all -m user -a 'name=user1 comment=“test user” uid=2048 home=/app/user1 group=root‘新建用户 最简单的用法:ansible all -m user -a 'name=user2'
name:名字 comment: 属于测试语句可以不用写的 uid:uid号 home:家目录 group:属组
ansible all -m user -a 'name=sysuser1 system=yes home=/app/sysuser1 '
system=yes:意思时创建系统用户
ansible all -m user -a 'name=user1 state=absent remove=yes' :删除用户
10 . Group:管理组
ansible srv -m group -a "name=testgroup system=yes“
ansible srv -m group -a "name=testgroup state=absent"
11. 解压文件的模块
name: Extract invault-wallet.tar.gz to /opt/software/openresty/nginx/html/invault
unarchive:
src: /home/centos/release_static/mainnet/invault-wallet.tar.gz (源文件)
dest: /opt/software/openresty/nginx/html/invault (目标文件)
owner: "{{ file_user }}" (文件的所有者,在执行playbook时传递变量的值)
group: "{{ file_user }}" (文件的所有组变量,在执行playbook时传递变量的值)
become: true (切换到root去执行此命令)
become_method: su
become_user: root
when: backup_result is succeeded or backup_path_result.stat.exists == True
12. 判断文件是否存在的模块:
– name: Check backup path exists or not
stat:
path: /opt/software/openresty/nginx/html/invault{{ ansible_date_time.date }}
register: backup_path_result
become: true
become_method: su
become_user: root
此文件需要切换到root用户去查看
Ansible-playbook (剧本的介绍和写法)注意格式的缩进会使playbook报错。如果找不到报错的原因注意查看剧本的格式缩进。
playbook的编写及格式:
首先剧本的名字一般要以.yml为结尾 ;然后内容的开头第一行应该时3个横杠 – – – (可以不用写也行)
具体的格式书写如下图:
vim f1.yml
上图为playbook的书写方式;(上图中应该是tasks写错了)
执行playbook:
ansible-playbook -C f1.yml (检查剧本的执行,并不真实的来执行,只做检查)
ansible-playbook f1.yml : 执行此playbook剧本 (可以不需要加执行权限)
使用#号注释代码 缩进必须是统一的,不能空格和tab混用
缩进的级别也必须是一致的,同样的缩进代表同样的级别,程序判别配置的级别是通过缩进结 合换行来实现的
执行playbook时传递变量参数值:
ssh centos@52.74.137.28 '/usr/bin/ansible-playbook /home/centos/playbook/mainnet/tomcat/release-mainnet.yml –extra-vars \
"targets=tomcat-b-03-group user=centos child_project=invault-account-tomcat war_name=invault-account.war" -f 10'
ssh centos@52.74.137.28 :首先从Jenkins上连接到ansible上去执行已经写好的剧本,前提是做好免密登录。
–extra-vars :传递参数的设置,后面跟要传递的playbook里引用的变量的值
-f 10 : 并行执行的进程数。
具体的各部分信息及介绍:
Hosts 执行的远程主机列表
playbook中的每一个play的目的都是为了让某个或某些主机以某个指定的用户 身份执行任务。hosts用于指定要执行指定任务的主机,须事先定义在主机清 单中 。
Websrvs:dbsrvs 两个组的并集
Websrvs:&dbsrvs 两个组的交集
webservers:!phoenix 在websrvs组,但不在dbsrvs组
也可以这样使用:
ansible lv -m shell -a 'cat /etc/passwd' –limit 192.168.60.2 (只针对lv组中的单个主机来进行操控)
-v 显示过程 -vv -vvv 更详细
Tasks 任务集
playbook里的模块命令如果执行过一次有些情况下不会再次去执行的例如:yum安装包,如果已经跑过一遍的剧本第二次再执行一遍的话,默认就不会再安装一遍了。某些服务启过之后,也不会再次重启的。
案例:
示例:httpd.yml
– hosts: websrvs
remote_user: root
tasks:
– name: Install httpd
yum: name=httpd state=present (安装工具包)
– name: Install configure file
copy: src=files/httpd.conf dest=/etc/httpd/conf/ (复制配置文件)
– name: start service
service: name=httpd state=started enabled=yes (启动服务)
在此案例中如果将安装工具的配置文件做了修改后,再次执行此剧本,过程是:包已经安装过了,不会再安装了,配置文件更改了会再次执行一次将原来的文件覆盖掉,最后一步,服务已经起来了,则不会再次执行了,所以问题是:修改的配置文件无法让其生效了。接下来就需要用到标记的模块了具体如何使用请看下面的介绍:
handlers和notify结合使用触发条件 :具体请看下面示例:
httpd.yml
– hosts: websrvs
remote_user: root
tasks:
– name: Install httpd
yum: name=httpd state=present (安装工具包)
– name: Install configure file
copy: src=files/httpd.conf dest=/etc/httpd/conf/ (复制配置文件)
notify: restart httpd (在此处用notify做一下标记,如果发现此处再次执行或发生变化时)
– name: start service (会触发下面的handlers的执行)
service: name=httpd state=started enabled=yes (启动服务)
handlers: (在上面做的标记的地方 执行下面的命令)
– name: restart httpd
service: name=httpd status=restarted
一个notify对应handlers里的一个执行模块,可以写多个标记的notify,但是下面要对应的写上他的执行模块命令。
触发多个:可以连续跟两个notify,但handlers里的模块,每个name下面只能跟一个。
tags (标签)
再cation模块后添加标签后,执行剧本可以调用标签的模块单独使用:案例如下:
ansible-playbook -t tags标记的描述 f1.yml (-t 选项时调用tags标签的action ,-t 后面只跟tags后面的描述就可以了) 可以执行多个标签,中间用逗号隔开。
Playbook中变量使用
变量名:仅能由字母、数字和下划线组成,且只能以字母开头
1 ansible setup facts 远程主机的所有变量都可直接调用
2 在/etc/ansible/hosts中定义 普通变量:主机组中主机单独定义,优先级高于公共变量 公共(组)变量:针对主机组中所有主机定义统一变量
3 通过命令行指定变量,优先级最高 ,其次是playbook里,最后是主机列表清单里。
变量的定义及使用:
系统自带的变量:通过查看系统内部的setup模块:ansible all -m setup
在文件里定义变量然后调用:
1 . 新建一个name .yml的文件,在里面定义变量如:
var1: hhh
var2: tttt
2. 在新建一个playbook,并调用刚才添加在文件里的变量 : test.yml
– – –
– hosts: all
remote_user: root
var_files: (引用文件的变量,格式单词必须写成这样)
– name.yml (引用定义变量的文件,如果剧本和定义变量的文件在同一个目录下则不需要写路径)
(如果在不同目录下,引用定义变量的文件需要写全路径)
tasks:
-name: touch file (模块的描述信息)
file: name=/data/{{ var1 }} state=touch (新建文件的模块命令,新建的文件名调用变量var1的赋值)
执行剧本:ansible-playbook test.yml 执行结果为在all所有被控主机上新建了/data/hhh 的文件
在命令行里的定义和使用:(直接在命令行里定义,和引用)
ansible all -e var1=dddd -m shell -a 'touch /data/{{ var1 }}'
-e 为选项后面只能跟一个定义的变量,如果需要定义多个变量,在后面再添加一个-e然后定义变量就可以
在playbook中定义 变量 :
4 在playbook中定义
vars:
– var1: value1
– var2: value2
引用shell命令结果的变量:
例子:
– hosts: all
remote_user: root
tasks:
– name: Test
shell: date -d "-1 day" +%F (shell命令取值)
register: test1 (将取到的值传递给test1)
– name: touch file
shell: touch /data/{{ test1.stdout }}/tets33 (引用test1的变量必须要这种方式来引用)
执行的结果就是可以查找到昨天的日期并在目录下创建文件
模板templates (templates文件夹下的模板文件不能再单个ansible里调用,只能在playbook里用)
template:算是一个模板的模块,能够将自己定义的模板文件复制到,所需要模板文件的地方:
src:为源文件 dest:为目标要复制的文件 (此模块可以实现复制功能)
使用jinja2的语言,
一般和playbook文件同级的目录下创建一个模板文件夹(templates),然后将模板文件写在此文件夹下,并且模板文件的后缀名为.j2
下面一个示例来调用templates文件夹下的模板文件:(以nginx的服务为例)
本机装好nginx服务并将配置文件推送到被控断的主机上。
1 . 将nginx的配置文件拷贝到templates文件夹下,然后修改文件名添加后缀.j2
cp /etc/nginx/nginx.conf templates/nginx.conf.j2 (后缀必须添加j2)
2.编写脚本调用templates里的模板文件:
vim testtemplate.yml
– – –
– hosts: all
remote_user: root
tasks:
– name: install package
yum: name=nginx
– name: copy template
template: src=nginx.conf.j2 dest=/etc/nginx/nginx.conf (调用模板文件,将temlpates下的模板)
– name: start service (文件复制到新装的nginx下的配置文件)
sevice: name=nginx state=started enabled=yes (启用服务,且永久启用)
when :(条件测试语句)
在task后添加when子句即可使用条件测试;when语句支持Jinja2表达式语法
例如:
执行此剧本的结果是:如果系统的主版本是7则会创建此文件,如果是六的话则会跳过不会创建此文件。
具体执行结果如下图所示:
register :标记上一次执行结果,作为下一次执行的条件的判断,执行的结果一般为jesion格式的数据
案例:
– name: set
shell: date -d "-1 day" +%F
register: yesterday
– name: Check today backup path exists or not
stat:
path: /home/{{ user }}/backup/{{ child_project }}/{{ ansible_date_time.date }}/{{ war_name }}
register: backup_path_result (将上面shell模块执行的结果传递到 backup_path_result 里去)
– name: check yestady backup path exit or not (判断文件是否存在的模块)
stat:
path: /home/{{ user }}/backup/{{ child_project }}/{{ yesterday.stdout }}/{{ war_name }}
register: yestady_backup_path_result (将上面shell模块执行的结果传递到 backup_path_result 里去)
when: backup_path_result.stat.exits == False (执行此模块的条件是在backup_path_result.stat.exits为错误的时候)
– name: Stop tomcat
shell: setsid /bin/sh -i -c "/opt/{{ child_project }}/bin/stop.sh"
register: stop_result
when: backup_path_result.stat.exists == True or yestady_backup_path_result.stat.exits == True (多个条件的组合判断)
在命令行传递参数,然后在主机列表里添加密码切换用户的模块:
– name: roll-back-today
shell: /usr/bin/mv -f /opt/software/openresty/nginx/html/invault{{ ansible_date_time.date }} /opt/software/openresty/nginx/html/invault
become: true
become_method: su
become_user: root
when: backup_path_result.stat.exists == True
vim /etc/ansible/hosts
ansible-vault edit hosts (另一种打开此文件的方式,由于里面存放密码所以对文件进行了加密,只有这样可以打开)
[web-a-group]
web-01 ansible_port=65522 ansible_host=10.0.1.11 ansible_become_user=root ansible_become_pass=UL1PFZoMctplTuW0
[web-b-group]
web-02 ansible_port=65522 ansible_host=10.0.2.11 ansible_become_user=root ansible_become_pass=UL1PFZoMctplTuW0
在剧本里修改文件权限的方法,直接在外边传递playbook的变量参数的值即可:
ssh centos@52.74.137.28 'ansible-playbook /home/centos/playbook/mainnet/wallet/release_wallet.yml –extra-vars "targets=web-a-group user=centos file_user=www" -f 10'
src: /home/centos/release_static/mainnet/invault-wallet.tar.gz
dest: /opt/software/openresty/nginx/html/invault
owner: "{{ file_user }}"
group: "{{ file_user }}"
become: true
become_method: su
become_user: root
(当在playbook里新建或者解压文件时,切换到root操作,root就有权限来修改文件的所有者,只需在执行playbook时传递一个参数来更改文件的所有者就可以了)
迭代:with_items
当有需要重复性执行的任务时,可以使用迭代机制
对迭代项的引用,固定变量名为”item“
要在task中使用with_items给定要迭代的元素列表
列表格式:
字符串
字典
下面为一个案例:
– name: add several users
user: name={{ item }} state=present groups=wheel (创建用户,及指定组名,引用变量元素列表)
with_items: (此表头只是就是这样写,写成其他的变量则执行会失败)
– testuser1
– testuser2
使用迭代让其循环创建用户。
迭代嵌套子变量
roles
将各个命令模块分散单独存放到一个剧本中,然后组和调用:
这样做的目的使效率大大提高,重复的的命令模块不用再次编写,只需要调用就可以了。
以下具体案例:(官方建议目录在/etc/ansible/下就有roles文件夹,不强制要求使用)
1 .目录结构:找个文件夹例如:f1 在里面建一个roles的文件夹
2 .进到roles目录下在创建目录nginx(此目录为安装此应用单独分开的)
3 . 进到nginx目录下在创建各个使用模块的目录:tasks和templates的目录
4 . 进到tasks目录下去创建单个模块命令的playbook:
如: group.yml; user.yml; yum.yml ;
vim group.yml
– name: create group (模块功能描述)
group: name=nginx (创建组)
第一个创建组的剧本就写好了,如上所示来创建第二个命令模块,第三个命令模块,等 ;每个命令模块只执行一条命令。
vim user.yml
– name: create user
user: name=nginx group=nginx system=yes (system=yes的意思是创建系统账号,而不是普通账号)
此创建用户的剧本也写完了。
vim
– name: install package
yum: name=nginx
此安装包的剧本也写完了。
vim start service
– name: start service
service: name=nginx enabled=yes
此启动服务的剧本也写完了
最后在创建总的剧本来决定这些子剧本执行的先后顺序:
vim main.yml
– include: group.yml
– include: user.yml
– include: yum.yml
– include: start.yml
此总剧本也创建完了。
最后创建一个playbook调用总剧本,此playbook应该和roles文件夹是平级的。
返回到f1文件夹下,创建nginx的安装playbook
vim nginxrole.yml
– – –
– hosts: all
retome_user: root
roles:
– role: nginx
开始测试此剧本,安装nginx服务。到此roles已经完成了。
此目录结构为:
.
├── nginxroles.yml
└── roles
└── nginx
└── tasks
├── group.yml
├── main.yml
├── start.yml
├── user.yml
└── yum.yml
本文来自投稿,不代表Linux运维部落立场,如若转载,请注明出处:http://www.178linux.com/99680