运维工具:
OS provisioning(PXE(dhcp,tftp,ftp|http);cobbler(repository,distribution,profile));
OS config(puppet;saltstack;func);
task execute(fabric;func;saltstack);
deployment(fabric);
注:
dnsmasq替代dhcp,dnsmasq(可用于嵌入式环境,提供dhcp、dns服务);
cobbler若配置自身管理dhcp则会启动dnsmasq服务;
分类:
agent(puppet,saltstack,func);
agentless(ansible,fabric;基于ssh service);
www.ansible.com
Ansible, an open source community project sponsored by Red Hat, is the simplest way to
automate IT. Ansible is the only automation language that can be used across entire IT teams– from systems and network administrators to developers and managers. Ansible by Red Hat provides enterprise-ready solutions to automate your entire application lifecycle – from servers to clouds to containers and everything inbetween. Ansible Tower by Red Hat is a commercial offering that helps teams manage complex multi-tier deployments by adding control, knowledge,and delegation to Ansible-powered environments.
http://docs.ansible.com/ansible/latest/intro_installation.html
properties:
minimal learning curve,auditability;
no bootstrapping;
no DAG ordering,fails fast;
no agents(other than sshd),0 resourceconsumption when not in use;
no server;
no additinal PKI;
modules in any lanaguage;
YAML,not code;
SSH by default;
strong multi-tier solution;
特性:
基于python实现(paramiko,PyYAML,jinja2三个模块);
部署简单,agentless;
默认使用ssh协议(基于密钥认证(ansible默认);也可在inventory文件(/etc/ansible/hosts)中指定,如172.17.101.31 ansible_ssh_user=ane ansible_ssh_pass=ane123);
主从模式(master(ansible,ssh client),slave(ssh server));
支持自定义模块(支持各种编程语言);
playbook;
基于“模块”来完成各种“任务”;
ansible architecture:
ansible核心组件:
ansible core;
host inventory;
core modules;
custom modules;
playbook(YAML,jinja2);
connect plugin;
YAML是一个可读性高的用来表达资料序列的格式,YAML参考了其它多种语言(C、XML、python、perl、电子邮件格式的RFC2822等),clark evans在2001年首次发表了这种语言,另ingy dot net与oren ben-kiki也是这种语言的共同设计者;
YAML Ain‘t Markup Language,即YAML不是XML;
在开发这种语言时,YAML其实意思是:Yet Another Markup Language,仍是一种标记语言;
YAML的语法和其它语言类似,并可简单表达清单、散列表、标量等数据结构,其结构structure通过空格来展示,list列表(也称序列sequence)里的项用-,dictionary字典(也称map)里的键值对用:分隔,扩展名通常为*.yml;
特性:
可读性好,易于实现;
和脚本语言的交互性好;
使用实现语言的数据模型,有一个一致的数据模型;
可基于流来处理;
表达能力强;
扩展性好;
key-value对和缩进来表式;
例:
name: John Smith
age: 41
gender: Male
spouse:
name: Jane Smith
age: 37
gender: Female
children:
- name: Jimmy Smith
age: 17
gender: Male
- name: Jenny Smith
age: 13
gender: Female
例(list中的所有元素用-开头):
- apple
- orange
- strawberry
- mango
例(dictionary通过key: value进行标识):
name: Example Developer
job: Developer
skill: Elite
也可将key: value放置于{}中:
{name: Example Developer,job: Developer,skill: Elite}
ansible中YAML基础元素:
变量variable;
inventory;
条件测试;
迭代;
操作:
]# uname -rm
2.6.32-431.el6.x86_64 x86_64
]# cat /etc/redhat-release
Red Hat Enterprise Linux Server release 6.5(Santiago)
]# yum list all *ansible* #准备epel源;
ansible.noarch 2.3.1.0-1.el6 epel
ansible-doc.noarch 2.3.1.0-1.el6 epel
ansible-inventory-grapher.noarch 1.0.1-2.el6 epel
ansible-lint.noarch 3.4.12-1.el6 epel
]# yum -y install ansible
Installed:
ansible.noarch 0:2.3.1.0-1.el6
Dependency Installed:
PyYAML.x86_64 0:3.10-3.1.el6 libyaml.x86_640:0.1.3-4.el6_6
python-babel.noarch 0:0.9.4-5.1.el6 python-crypto2.6.x86_640:2.6.1-2.el6
python-httplib2.noarch 0:0.7.7-1.el6 python-jinja2-26.noarch0:2.6-3.el6
python-keyczar.noarch 0:0.71c-1.el6 python-markupsafe.x86_640:0.9.2-4.el6
python-pyasn1.noarch 0:0.0.12a-1.el6 python-six.noarch0:1.9.0-2.el6
sshpass.x86_64 0:1.06-1.el6
]# ansible --version
ansible 2.3.1.0
config file = /etc/ansible/ansible.cfg
configured module search path = Default w/o overrides
python version = 2.6.6 (r266:84292, Sep 4 2013, 07:46:00) [GCC 4.4.7 20120313 (Red Hat 4.4.7-3)]
]# ll /etc/ansible/
total 28
-rw-r--r-- 1 root root 18066 Jun 2 05:49 ansible.cfg
-rw-r--r-- 1 root root 1077 Aug 16 10:41 hosts
drwxr-xr-x 2 root root 4096 Jun 2 05:49 roles
]# vim /etc/ansible/hosts # ansible默认
[websrvs]
172.17.101.31 ansible_ssh_user=ane ansible_ssh_pass=ane123
172.17.101.75 ansible_ssh_user=ane ansible_ssh_pass=ane123
[dbsrvs]
172.17.101.70 ansible_ssh_user=ane ansible_ssh_pass=ane123
注:若有如下操作,/etc/ansible/hosts文件中的主机后不需跟anesible_ssh_user和anesible_ssh_pass变量
]# ssh-keygen -t rsa -f ~/.ssh/id_rsa -P ‘‘
]# ssh-copy-id 172.17.101.31
]# ssh-copy-id 172.17.101.75
]# ssh-copy-id 172.17.101.70
]# man ansible-doc # show documentation on Ansible modules
-l,--list List available modules
-s,--snippet Show playbook snippetfor specified module(s)
]# ansible-doc -l #列出所有模块;
]# ansible-doc -s MODULE_NAME #查看模块帮助;
]# man ansible #run a task on a target host(s)
Usage: ansible <host-pattern>[options]
-i INVENTORY, --inventory-file=INVENTORY
specify inventory hostpath
(default=/etc/ansible/hosts) or comma separated host
list.
-f FORKS, --forks=FORKS
specify number ofparallel processes to use
(default=5)
-m MODULE_NAME, --module-name=MODULE_NAME
module name to execute(default=command)
-a MODULE_ARGS, --args=MODULE_ARGS
module arguments
-C,--check don‘t make any changes;instead, try to predict some
of the changes thatmay occur
用法:
#ansible <host-pattern> [-f FORKS] [-m MODULE_NAME] [-a MODULES_ARGS]
]# man ansible-playbook #run an ansible playbook
Usage: ansible-playbook playbook.yml
常用模块:
1、command
]# ansible-doc -s command #命令模块,用于远程执行命令,使用ansible命令时不指模块名(-m MODULE_NAME),默认使用此模块;
- name: Executes a command on a remote node
例:
]# ansible 172.17.101.31 -m command -a ‘date‘
……
]# ansible websrvs -a ‘date‘
……
]# ansible all -a ‘date‘ #all指inventory中定义的所有主机;
172.17.101.31 | SUCCESS | rc=0 >>
Wed Aug 16 11:18:54 CST 2017
172.17.101.75 | SUCCESS | rc=0 >>
Wed Aug 16 11:18:54 CST 2017
172.17.101.70 | SUCCESS | rc=0 >>
Wed Aug 16 11:18:54 CST 2017
2、cron
]# ansible-doc -s cron
- name: Manage cron.d and crontab entries.
job # The command to execute or, ifenv is set, the value of environment
variable.Required if state=present.
state # Whetherto ensure the job or environment variable is present or absent.
user # The specific user whosecrontab should be modified.
例:
]# ansible websrvs -m cron -a ‘minute="*/2" job="/bin/echo hello" user=anename="test cron job"‘ #state=present默认即是此项,若要删除要加state=absent;
……
在101.{31,75}上用ane验证:
]# crontab -u ane -l
#Ansible: test cron job
*/2 * * * * /bin/echo hello
]# ansible websrvs -m cron -a ‘minute="*/2" job="/bin/echo hello" user=anename="test cron job" state=absent‘
]# ansible websrvs -m command -a ‘crontab-l‘
172.17.101.31 | SUCCESS | rc=0 >>
172.17.101.75 | SUCCESS | rc=0 >>
3、user
]# ansible-doc -s user
- name: Manage user accounts
name= # Name ofthe user to create, remove or modify.
例:
#ansible all -m user -a ‘name="user1"‘
4、group
]# ansible-doc -s group
- name: Add or remove groups
gid # Optional`GID‘ to set for the group.
name= # Name ofthe group to manage.
state # Whetherthe group should be present or not on the remote host.
system # If `yes‘, indicates that thegroup created is a system group.
例:
#ansible websrvs -m group -a ‘name=mysql gid=306 system=yes‘
#ansible websrvs -m user -a ‘name=mysql uid=306 group=mysql system=yes‘
5、copy,复制文件;
]# ansible-doc -s copy
- name: Copies files to remote locations.
src # Localpath to a file to copy to the remote server; can be absolute or relative. Ifpath is a directory, it is copied recursively. In this case, if path ends with"/", only inside contents of that directory are copied todestination.Otherwise, if it does not end with "/", the directoryitself with all contents is copied. This behavior is similar to Rsync.本地源文件,此处若指定目录,则复制该目录下的所有文件;
dest= # Remoteabsolute path where the file should be copied to. If src is a directory, thismust be a directory too.远程目标文件路径;
content # When usedinstead of ‘src‘, sets the contents of a file directly to the specified value.This is for simple values, for anything complex or with formatting pleaseswitch to the template module.取代src,用此处指定的信息生成目标文件内容;
owner # Name ofthe user that should own the file/directory, as would be fed to `chown‘.
group # Name of the group thatshould own the file/directory, as would be fed to `chown‘.
mode # Mode thefile or directory should be. For those used to `/usr/bin/chmod‘ remember thatmodes are actually octal numbers (like 0644). Leaving off the leading zero willlikely have unexpected results. As of version 1.8, the mode may be specified asa symbolic mode (for example, `u+rwx‘ or `u=rw,g=r,o=r‘).
例:
]# ansible websrvs -m copy -a ‘src=/etc/fstab dest=/tmp/fstab.ansible owner=ane group=ane mode=640‘
]# ansible websrvs -m copy -a ‘content="hello ansible\nhi i am jowin\n" dest=/tmp/test.an
sible‘
6、file,设定文件属性;
]# ansible-doc -s file
- name: Sets attributes of files
path= # path tothe file being managed. Aliases: `dest‘,`name‘
owner
group
mode
state # ……If `link‘, the symbolic linkwill be created or changed. Use `hard‘ for hardlinks. If `absent‘, directorieswill be recursively deleted, and files or symlinks will be unlinked.……state=link可创建符号链接文件;
例:
#ansible websrvs -m file -a ‘path=/tmp/fstab.ansible owner=zabbix group=zabbix mode=644‘
]# ansible websrvs -m file -a ‘src=/tmp/fstab.ansible path=/tmp/fstab.link state=link‘
7、ping,测试远程主机的连通性;
]# ansible-doc -s ping
- name: Try to connect to host, verify ausable python and return `pong‘ on success.
例:
]# ansible all -m ping
8、service
]# ansible-doc -s service
- name: Manage services.
enabled # Whetherthe service should start on boot. *At least one of state and enabled arerequired.*开机自启,true|false;
name= # Name ofthe service.服务名称;
state #`started‘/`stopped‘ are idempotent actions that will not run commands unless necessary. `restarted‘ will alwaysbounce the service. `reloaded‘ willalways reload. *At least one of state and enabled are required.* Note that reloaded will start the service if it is not already started, even if your chosen init system wouldn‘t normally.状态有started|stopped|restarted;
例:
#ansible websrvs -a ‘service httpd status‘
#ansible websrvs -a ‘chkconfig --listhttpd‘
#ansible websrvs -m service -a ‘enabled=true name=httpd state=started‘
9、shell,在远程主机上运行命令,尤其是要用到管道等功能的命令时用-m shell;
]# ansible-doc -s shell
- name: Execute commands in nodes.
chdir # cd intothis directory before running the command
例:
#ansible websrvs -m user -a ‘name=user10‘
#ansible websrvs -m shell -a ‘echo user10123| passwd --stdin user10‘
10、script,将本地脚本复制到远程并执行,要使用相对路径指定脚本;
]# ansible-doc -s shell
- name: Execute commands in nodes.
例:
#ansible websrvs -m script -a ‘test.sh‘ #test.sh在本地的当前路径下;
11、yum,安装程序包;
]# ansible-doc -s yum
- name: Manages packages with the `yum‘package manager
name= # Packagename, or package specifier with version, like `name-1.0‘. When usingstate=latest, this can be ‘*‘ which means run: yum -y update. You can also passa url or a local path to a rpm file (using state=present). To operate on several packages this canaccept a comma separated list of packages or (as of 2.0) a list of packages.指明要安装的程序包,可带上版本号;
state # Whether to install (`present‘ or `installed‘, `latest‘), or remove (`absent‘ or`removed‘) a package.安装用present|installed|latest,卸载用absent|removed;
例:
#ansible websrvs -m yum -a ‘name=zsh‘
12、setup,收集远程主机的facts,每个被管理节点在接收并运行管理命令之前,会将自己主机的相关信息,如os version、ip等信息报告给远程的ansible主机;
]# ansible-doc -s setup
- name: Gathers facts about remote hosts
]# ansible 172.17.101.31 -m setup
172.17.101.31 | SUCCESS => {
"ansible_facts": {
"ansible_all_ipv4_addresses": [
"172.17.101.31"
],
"ansible_all_ipv6_addresses": [
"fe80::250:56ff:feb2:775a"
],
"ansible_apparmor": {
"status": "disabled"
},
……
ansible playbook:
playbook是由一个或多个play组成的列表,play的主要功能在于将事先归并为一组的主机装扮成事先通过ansible中的task定义好的角色,从根本上讲,task无非是调用ansible的module将多个play组织在一个playbook中,即可让它们联同起来按事先编排的机制同唱一台大戏;
为满足模块执行幂等性,不是每次#ansible-playbook apache.yml都执行,只有满足一定的条件才执行,如配置文件改变;
playbook的组成结构:
inventory;
modules;
Ad Hoc command;
playbooks(tasks(调用module完成某操作);variables;templates;handlers(处理器,由某事件触发执行的操作);roles);
playbook中每一个play的目的都是为了让某个或某些主机以某个指定的用户身份执行任务;
例:
- hosts: websrvs
vars:
- http_port:80
- max_clients:256
remote_user: root
tasks:
- name: install httpd package
yum: name=httpd state=latest
- name: install configuration file for httpd
copy: src=/root/conf/httpd.conf dest=/etc/httpd/conf/httpd.conf
notify:
- restart httpd
- name: start httpd service
service: name=httpd state=started
handlers:
- name: restart httpd
service: name=httpd state=restarted
hosts,用于指定要执行指定任务的主机,其可以是一个或多个由冒号分隔的主机组;
remote_user,用于指定远程主机上的执行任务的用户,remote_user可用于各task中,也可通过sudo方式在远程主机上执行任务,用于play全局或某任务,此外可在sudo时使用sudo_user指定sudo时切换的用户;
task任务列表和action,play的主体部分是task list,task list中的各任务被次序逐个在hosts中指定的所有主机上执行,即在所有主机上完成第一个任务后再开始第二个,自上而下运行各任务,如果中途发生错误,所有已执行任务都可能回滚,在更正playbook后重新执行一次即可;
task的目的是使用指定的参数执行模块,而在模块参数中可使用变量,模块执行是幂等的,意味着多次执行是安全的,因为其结果一致;
每个task都应该有name,用于playbook的执行结果输出,建议其内容尽可能清晰的描述任务执行步骤,如果未提供name,则action的结果将用于输出;
定义task可使用"action: module options"或"module: options",建议使用后者,可实现向后兼容,如果action一行的内容过多,在行首使用空格换行;
在众多模块中,只能command和shell只需给定一个list,而无需使用-a ‘key=value‘格式,例如:
tasks:
- name: disable selinux
command: /sbin/setenforce 0
若命令和脚本的退出不为0,可使用如下方式替代(或使用ignore_errors来忽略错误信息),例如:
tasks:
- name: run this command and ignore the result
shell: /usr/bin/somcommand || /bin/true
或
tasks:
- name: run this command and ignore the result
shell: /usr/bin/somecommand
ignore_errors: Ture
handlers,用于当关注的资源发生变化时采取一定的操作;
notify这个action可用于在每个play最后被触发,这样可避免多次有改变发生时每次都执行指定的操作,取而代之,仅在所有的变化发生完成后一次性的执行指定操作,在notify中列出的操作称为handler,即notify中调用handler中定义的操作;
playbook中使用变量:
1、 自定义变量:
例:
- hosts: websrvs
remote_user: root
vars:
- package: httpd
- service: httpd
tasks:
- name: install httpd package
yum: name={{ httpd }} state=latest
2、直接使用ansible内置变量:
例:
- hosts: websrvs
remote_user: root
tasks:
- name: copy file
copy: content="{{ ansible_all_ipv4_address }}" dest=/tmp/vars.ansible
3、在inventory中定义(主机变量|组变量):
例(自定义主机变量):
[websrvs]
172.17.101.31 testvar="test"
例(自定义组变量):
[websrvs:vars]
ntp_server=ntp.example.com
nfs_server=nfs.example.com
4、若未作ssh密钥认证(ansible主机-->被管理client主机),可在/etc/ansible/hosts中直接用内置变量定义:
例:
[websrvs]
172.17.101.31 ansible_ssh_user=ane ansible_ssh_pass=ane123
playbook中使用条件测试:
如果需要根据变量、facts或此前任务执行结果来作为某task执行与否的前提时,要用到条件测试;
when语句:在task后添加when子句,when语句支持jinja2表达式语法;
例:
- hosts: websrvs
remote_user: root
vars:
- username: user10
tasks:
- name: create {{ username }} user
user: name={{ username }}
when: ansible_fqdn == "node2.example.com"
playbook中迭代:
当有需要重复性执行的任务时,可使用迭代机制;
使用格式为将需要迭代的内容定义为item变量(item是特殊变量),并通过with_items语句来指明迭代的元素列表;
调用用item,定义task循环列表用with_items,with_items中的列表值可以是字典,但引用时要用item.KEY;
例:
- name: add several users
user: name={{ item }} state=present groups=wheel
with_items:
- testuser1
- testuser2
例:
- name: add several users
user: name= {{ item.name }} groups={{item.groups }} state=present
with_items:
- {name: ‘testuser1‘,groups: ‘wheel‘ }
- {name: ‘testuser2‘,groups: ‘root‘ }
playbook中template:
例:
#vim template/httpd.conf.j2
Listen {{ http_port }}
MaxClients {{ maxClients }}
ServerName {{ ansible_fqdn }}
#vim /etc/ansible/hosts
[websrvs]
172.17.101.31 http_port=80 maxClients=100
172.17.101.75 http_port=8080 maxClients=200
#vim apache.yml
- hosts: websrvs
remote_user: root
vars:
- package: httpd
- service: httpd
tasks:
- name: install httpd package
yum: name:{{ package }} state=latest
- name: install configuration file for httpd
template: src=/root/template/httpd.conf.j2 dest=/etc/httpd/conf/httpd.conf
notify:
- restart httpd
- name: start httpd service
service: enabled=true name={{ service }} state=started
handlers:
- name: restart httpd
service: name=httpd state=restarted
#ansible-playbook apache.yml
playbook中tags:
为某个任务定义标签,在执行playbook时,通过为ansible-playbook命令使用--tags选项能实现仅运行指定的task而非所有的;
特殊tags:
- always
例:
#vim apache.yml
- hosts: websrvs
remote_user: root
vars:
- package: httpd
- service: httpd
tasks:
- name: install httpd package
yum: name:{{ package }} state=latest
tags:
- always
- name: install configuration file for httpd
template: src=/root/template/httpd.conf.j2dest=/etc/httpd/conf/httpd.conf
tags:
- conf
notify:
- restart httpd
- name: start httpd service
service: enabled=true name={{ service }} state=started
tags:
- service
handlers:
- name: restart httpd
service: name=httpd state=restarted
#ansible-playbook apache.yml
#ansible-playbook apache.yml --tags="conf"
playbook中roles:
1.2version引入的新特性,用于层次性、结构化的组织playbook,roles能根据层次型结构自动装载变量文件、tasks、handlerst等;
要使用roles只需在playbook中使用include指令即可,简单讲,roles就是通过分别将变量、文件、任务、模块、处理器放置于单独的目录中,并可便捷的include它们的一种机制;;
roles一般用于基于主机构建服务的场景中,也可用于构建守护进程等场景中;
创建roles的步骤:
1、创建以roles命名的目录;
2、在roles目录中分别创建以各角色名称命名的目录,如websrvs等;
3、在每个角色命名的目录中分别创建tasks、files、templates、handlers、vars、meta、default目录,用不到的目录可为空目录,也可不创建;
4、在playbook文件中调用各角色;
roles各目录:
tasks/,至少应包含一个名为main.yml的文件,其定义了此角色的任务列表,此文件可使用include包含其它的位于此目录中的task文件;
files/,存放由copy或script等模块调用的文件,静态文件;
templates/,template模块会自动在此目录中寻找jinja2模板文件;
handlers/,应包含一个main.yml文件,用于定义此角色用到的各handler,在handler中使用include包含的其它handler文件也应位于此目录中;
vars/,应包含一个main.yml文件,用于定义此角色用到的变量;
meta/,应包含一个main.yml文件,用于定义此角色的特殊设定及依赖关系,1.3以上version才支持;
default/,应用包含一个main.yml为当前角色设定默认变量时使用此目录;
注:
目录名同角色名;
目录结构有固定格式;
site.yml中定义playbook,也可有其它的yml文件;
roles间可定义依赖关系;
#mkdir -pv /etc/ansible/roles/{websrvs,dbsrvs}/{tasks,files,templates,handlers,vars,meta}
#cd /etc/ansible/roles/websrvs
#cp /etc/httpd/conf/httpd.conf files/
#vim tasks/main.yml
- name: install httpd package
yum:name=httpd
- name: install configuration file
copy: src=httpd.confdest=/etc/httpd/conf/httpd.conf
tags:
- conf
notify:
- restart httpd
- name: start httpd
service: name=httpd state=started
#vim handlers/main.yml
- name: restart httpd
service: name=httpd state=restarted
#vim vars/main.yml
- httpd_port: 80
- maxClients: 200
#vim /etc/ansible/roles/site.yml #和roles在同级路径下;
- hosts: websrvs
remote_user: root
roles:
- websrvs
- hosts: dbsrvs
remote_user:root
roles:
- dbsrvs
- hosts: 172.17.101.1
remote_user: root
roles:
- websrvs
- dbsrvs