wangwengwu 发表于 2018-7-30 10:22:29

ansible 系列教程

ansible 核心组件介绍
Architecture Diagram

[*]  ansible core
[*]  host iventory
[*]  core modules
[*]  custom modules
[*]  playbook (yaml)
[*]  connetc plugin
ansibles 的特性

[*]  基于python语言实现,有paramiko,Pyyaml和jinjia2 三个关键模块
[*]  部署简单,agegtlees,默认使用SSH协议

[*]  基于密钥认证
[*]  在inventory 文件中指定账号和密码
支持playbook基于”模块“完成各种任务ansible install
# install the epel-release RPM if needed on CentOS, RHEL, or Scientific Linux  
$ sudo yum install ansible
ansible config
  配置文件:/etc/ansible/ansible.cfg
  inventory:/etc/ansible/hosts
  定制被管理主机:
cat /etc/ansible/host  

  
192.168.0.101
  
192.168.0.102
  管理master 创建ssh密钥
root@node2 ansible]# ssh-keygen  
Generating public/private rsa key pair.
  
Enter file in which to save the key (/root/.ssh/id_rsa):
  
# ls /root/.ssh/
  
/root/.ssh/id_rsa/root/.ssh/id_rsa.pub
  将公钥复制给slave节点,并验证ssh证书登录是否成功。
#ssh-copy-id -i /root/.ssh/id_rsa.pub root@192.168.0.102  
# ssh-copy-id -i /root/.ssh/id_rsa.pub root@192.168.0.101
  
# ssh root@192.168.0.102 'date'
  
Wed Feb3 19:53:04 CST 2016
  
# ssh root@192.168.0.101 'date'
  
Wed Feb3 19:53:58 CST 2016
ansible-doc - show documentation on Ansible modules
# ansible-doc -l  
cronManage cron.d and crontab entries.
  
crypttabEncrypted Linux block devices
  
datadog_event Posts events to DataDogservice
  
debconf   Configure a .deb package
  
debug Print statements during execution
  
digital_ocean Create/delete a droplet/SSH_key in DigitalOcean
  
digital_ocean_domainCreate/delete a DNS record in DigitalOcean
  查看模块说明
# ansible-doc -s cronansible命令应用基础
  语法: ansible <host-pattern> [-f forks] [-m module_name] [-a args]

[*]  -f forks:启动的并发数
[*]  -m module_name:使用的模块
[*]  -args:模块特有参数
  EX:使用command模块执行date指令,ansible 默认模块,不支持变量传递。
# ansible webserver -m command -a "date"  
192.168.0.101 | success | rc=0 >>
  
Wed Feb3 20:06:50 CST 2016
  

  
192.168.0.102 | success | rc=0 >>
  
Wed Feb3 20:06:03 CST 2016
  
# ansible webserver -a "date"
  
192.168.0.102 | success | rc=0 >>
  
Wed Feb3 20:10:35 CST 2016
  
192.168.0.101 | success | rc=0 >>
  
Wed Feb3 20:11:22 CST 2016
  EX:cron模块:每十分钟运行“hello”

[*]  state
  present 添加任务 absent 删除任务
# ansible webserver -m cron -a 'minute="*/10" job="/bin/echo hello word" name="ansibile cron lession"'  验证结果
# ansible webserver -a "crontab -l"  
192.168.0.101 | success | rc=0 >>
  
#Ansible: ansibile cron lession
  
*/10 * * * * /bin/echo hello word
  
192.168.0.102 | success | rc=0 >>
  
#Ansible: ansibile cron lession
  
*/10 * * * * /bin/echo hello word
  删除一个cron任务:
# ansible webserver -m cron -a 'minute="*/10" job="/bin/echo hello word" name="ansibile cron lession" state=absent'  创建一个mysql 系统用户
  home: Check that parent folder is missing and run
# ansible webserver -m user -a "name=mysql system=yes shell='/sbin/nologin' home='/date/mysql'"  
192.168.0.102 | success >> {
  
"append": false,
  
"changed": true,
  
"comment": "",
  
"group": 497,
  
"home": "/date/mysql",
  
"move_home": false,
  
"name": "mysql",
  
"shell": "/sbin/nologin",
  
"state": "present",
  
"uid": 497
  
}
  

  
192.168.0.101 | success >> {
  
"append": false,
  
"changed": true,
  
"comment": "",
  
"group": 498,
  
"home": "/date/mysql",
  
"move_home": false,
  
"name": "mysql",
  
"shell": "/sbin/nologin",
  
"state": "present",
  
"uid": 498
  
}
  删除一个mysql用户
# ansible webserver -m user -a "user=mysql remove='yes' state=absent"  
192.168.0.102 | success >> {
  
"changed": true,
  
"force": false,
  
"name": "mysql",
  
"remove": true,
  
"state": "absent"
  
}
  

  
192.168.0.101 | success >> {
  
"changed": true,
  
"force": false,
  
"name": "mysql",
  
"remove": true,
  
"state": "absent"
  
}
  EX:copy 模块:复制文件/etc/fstab 到/tmp/fstab.ansbile,文件所有者为root,所属组为roo并且文件权限为600
# ansible webserver -m copy -a "src=/etc/fstab dest=/tmp/fstab.ansible owner=root group=root mode=600"  
192.168.0.101 | success >> {
  
"changed": true,
  
"checksum": "f24c68dfd84aa1d30c325285d7aedc26a50e7078",
  
"dest": "/tmp/fstab.ansible",
  
"gid": 0,
  
"group": "root",
  
"md5sum": "05e29801d839073ed23aa6164e58646f",
  
"mode": "0600",
  
"owner": "root",
  
"secontext": "unconfined_u:object_r:admin_home_t:s0",
  
"size": 779,
  
"src": "/root/.ansible/tmp/ansible-tmp-1454504173.49-88392224178700/source",
  
"state": "file",
  
"uid": 0
  
}
  

  
192.168.0.102 | success >> {
  
"changed": true,
  
"checksum": "f24c68dfd84aa1d30c325285d7aedc26a50e7078",
  
"dest": "/tmp/fstab.ansible",
  
"gid": 0,
  
"group": "root",
  
"md5sum": "05e29801d839073ed23aa6164e58646f",
  
"mode": "0600",
  
"owner": "root",
  
"secontext": "unconfined_u:object_r:admin_home_t:s0",
  
"size": 779,
  
"src": "/root/.ansible/tmp/ansible-tmp-1454504173.49-145879281527954/source",
  
"state": "file",
  
"uid": 0
  
}
  EX:生成文件/tmp/test,内容为"hello word"
# ansible webserver -m copy -a "content='hello word' dest=/tmp/test "  
# ansible all -m shell -a 'cat /tmp/test'
  
192.168.0.102 | success | rc=0 >>
  
hello word
  

  
192.168.0.101 | success | rc=0 >>
  
hello word
  EX:文件权限管理
# ansible all -m file -a 'owner=mysql group=mysql mode=600 path=/tmp/fstab.ansible'  EX:创建软连接文件
# ansible all -m file -a 'path=/tmp/fstab.link src=/tmp/fstab.ansible state=link'  
# ll /tmp/*
  
lrwxrwxrwx. 1 rootroot18 Feb3 21:21 /tmp/fstab.link -> /tmp/fstab.ansible
  EX:service 服务管理模块
  enabled: Whether the service should start on boot
# ansible webserver -m service -a 'enabled=true name=nginx state=started'  EX: SHELL 指令模块,可以使用变量及参数传递
# ansible all -m shell -a 'echo redhat| passwd --stdin mysql'  
192.168.0.102 | success | rc=0 >>
  
Changing password for user mysql.
  
passwd: all authentication tokens updated successfully.
  

  
192.168.0.101 | success | rc=0 >>
  
Changing password for user mysql.
  
passwd: all authentication tokens updated successfully.
  EX:script 在远端执行本地脚本
# ansible all -m script -a '/tmp/test.sh'  EX:YUM 安装软件
# ansible all -m yum -a 'name=nginx'  EX: setup 收集远程主机facts,每个被管理几点在接受并运行管理命令之前,会将自己主机相关信息,如系统版本、IP报告给远程的ansible主机。
# ansible all -m setupansible的YAML介绍
  YAML是"YAML Ain't a Markup Language"(YAML不是一种置标语言)的递归缩写。 YAML是一个类似GNU的递归式定义。GNU对Unix说“No”,YMAL则是对XML说“No”。而在Ruby的世界里,YAML可以说是Ruby流动的血液。YAML 之于Ruby,犹如XML之于Java。

[*]  YAML的可读性好。
[*]  YAML和脚本语言的交互性好。
[*]  YAML使用宿主语言的数据类型。
[*]  YAML有一个一致的信息模型。
  YAML实例
# MySQL (default setup).Versions 4.1 and 5.0 are recommended.  
# 此处省略一些注释。
  
development:
  
adapter: mysql
  
database: demo_development
  
username: root
  
password:
  
host: localhos
ansible的基础元素、变量、组嵌套
变量

[*]  变量命名:变量名仅能由字母、数字和下划线组成、且只能以字母开头
[*]  facts 信息被保存在ansible变量中,可以引用使用
[*]  register:把任务的输出定义为变量,
  实例如下
task:  
shell:/usr/bin/foo
  
register:foo_result
  
ignore_error:True
ansible playbook 介绍
  playbooks 是 Ansible的配置,部署,编排语言.他们可以被描述为一个需要希望远程主机执行命令的方案,或者一组IT程序运行的命令集合. 如果 Ansible 模块你是工作室中的工具,那么 playbooks 就是你设置的方案计划. 在基础层面, playbooks 可以被用来管理用于部署到远程主机的配置文件.在更高的层面上,playbooks 可以依次对多层式架构上的服务器执行上线包括滚动更新在内的操作并可以将操作委托给其他主机包括在此过程中发生的与监视服务器,负载均衡服务器的交互操作在内.
  实例
- hosts: webservers  
vars:
  
http_port: 80
  
max_clients: 200
  
remote_user: root
  
tasks:
  
- name: ensure apache is at the latest version
  
yum: pkg=httpd state=latest
  
- name: write the apache config file
  
template: src=/srv/httpd.j2 dest=/etc/httpd.conf
  
notify:
  
- restart apache
  
- name: ensure apache is running
  
service: name=httpd state=started
  
handlers:
  
- name: restart apache
  
service: name=httpd state=restarted
ansible playbook 基础组件

[*]  Inventor
[*]  Modules
[*]  Ad hot commands
[*]  Playbooks
[*]  Tasks:任务,及调佣模块完成基础操作
[*]  variables:变量
[*]  tempalates:模板
[*]  handlers:处理器。由某事件触发执行的操作
[*]  roles:角色
主机与用户
  playbook 中的每一个 play,个别地选择操作的目标机器是哪些,以哪个用户身份去完成要执行的步骤。hosts 行的内容是一个或多个组或主机的 patterns,以逗号为分隔符,
  实例:
- hosts: webservers  
remote_user: root
Tasks 任务列表
  每一个 play 包含了一个 task 列表(任务列表).一个 task 在其所对应的所有主机上(通过 host pattern 匹配的所有主机)执行完毕之后,下一个 task 才会执行.有一点需要明白的是(很重要),在一个 play 之中,所有 hosts 会获取相同的任务指令,这是 play 的一个目的所在,也就是将一组选出的 hosts 映射到 task
  每个 task 的目标在于执行一个 moudle, 通常是带有特定的参数来执行.在参数中可以使用变量(variables).
  每个task都应该有name,用于playboo的执行结果输出,建议其内容尽可能详细描述任务步骤。如果未提供name,测action 的结果将用于输出
  modules 具有”幂等”性,意思是如果你再一次地执行 moudle(译者注:比如遇到远端系统被意外改动,需要恢复原状),moudle 只会执行必要的改动,只会改变需要改变的地方.所以重复多次执行 playbook 也很安全.
  对于 command module 和 shell module,重复执行 playbook,实际上是重复运行同样的命令.如果执行的命令类似于 ‘chmod’ 或者 ‘setsebool’ 这种命令,这没有任何问题.也可以使用一个叫做 ‘creates’ 的 flag 使得这两个 module 变得具有”幂等”特性
  下面是一种基本的 task 的定义,service moudle 使用 key=value 格式的参数,这也是大多数 module 使用的参数格式:
tasks:  
- name: make sure apache is running
  
    service: name=httpd state=running
  比较特别的两个 modudle 是 command 和 shell ,它们不使用 key=value 格式的参数,而是这样
tasks:  
- name: disable selinux
  
    command: /sbin/setenforce 0
  EX:
- hosts: webserver  
remote_user: root
  
tasks:
  
- name: create nginx group
  
    group: name=nginx system=yes gid=208
  
- name: create nginx user
  
    user: name=nginx uid=208 group=nginx system=yes
  
- hosts: dbserver
  
remote_user: root
  
tasks:
  
- name: copy file to dbserver
  
    copy: src=/etc/inittab dest=/tmp/initab.ans
handlers
  用于当关注的资源发生变化时采取一定的操作。'notify'这个action可用于在每个play的最后被触发,这样可以避免多次有改变发生时每次都执行指定的操作,取而代之仅在所有的变化发生完成后一次性地执行操作。在‘notify’中列出的操作称之为handler。
  EX: 步骤1,写一个playbook 要求如下

[*]  自动部署一个httpd服务
[*]  提供一个特殊的配置文件端口监听8080
[*]  开机自动启动
- hosts: webserver  
remote_user: root
  
tasks:
  
- name: install httpd package
  
    yum: name=httpd state=latest
  
- name: install congfiguration file for httpd
  
    copy: src=/root/playboos/conf/httpd.conf dest=/etc/httpd/conf/httpd.conf
  
- name: start httpd service
  
    service: enabled=true name=httpd state=started
  步骤2 修改配置文件端口监听为80。重新执行playbook查看端口是否被修改!
- hosts: webserver  
remote_user: root
  
tasks:
  
- name: install httpd package
  
    yum: name=httpd state=latest
  
- name: install congfiguration file for httpd
  
    copy: src=/root/playboos/conf/httpd.conf dest=/etc/httpd/conf/httpd.conf
  
    notify:
  
    - restart httpd
  
- name: start httpd service
  
    service: enabled=true name=httpd state=started
  
handlers:
  
- name: restart httpd
  
    service: name=httpd state=restarted
playbooks 变量的使用

[*]  自定变量引用
[*]  调用ansible系统变量
[*]  调用Inventor 定义的变量
  EX1:自定变量引用
- hosts: webserver  
remote_user: root
  
vars:
  
- package: httpd
  
- service: httpd
  
tasks:
  
- name: install httpd package
  
    yum: name={{ package }} state=latest
  
- name: install congfiguration file for httpd
  
    copy: src=/root/playboos/conf/httpd.conf 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
  EX2:调用ansible系统变量
  系统变量查看
# ansible all -m setup  调用ansible系统变量ansibleallipv4_addresses'
- hosts: webserver  
remote_user: root
  
tasks:
  
- name: copy file
  
copy: content="{{ ansible_all_ipv4_addresses }}" dest=/tmp/ip.ans
  EX3:调用Inventor 定义的变量
# Ex 1: Ungrouped hosts, specify before any group headers.  

  
192.168.0.101 testvar='0.101' ansible_ssh_user=root ansible_ssh_pass=redhat
  
192.168.0.102 testvar='0.102'
  

  
192.168.0.102
  

  
# cat vars.yml
  
- hosts: webserver
  
remote_user: root
  
tasks:
  
- name: copy file
  
    copy: content="{{ ansible_all_ipv4_addresses }}, {{ testvar }}" dest=/tmp/ip.ans
ansible之条件测试
  when语句:在task后添加when子句即可使用条件测试。
  EX:
tasks:  
- name: "shutdown Debian flavored systems"
  
    command: /sbin/shutdown -t now
  
    when: ansible_os_family == "Debian"
  EX:2
# cat cond.yml  
- hosts: all
  
remote_user: root
  
vars:
  
- username: major
  
tasks:
  
- name: create {{ username }} user
  
    user: name={{ username }}
  
    when: ansible_fqdn == "node3.huizhuang.com"
  迭代语句 当有需要重复性执行的任务时,可以使用迭代机制。 其使用格式为将需要迭代的内容定义为item变量引用,并通过with_items 语句来指明迭代的元素列表即可。
  EX:为了保持简洁,重复的任务可以用以下简写的方式。
  ` item ` 为固定变量名
- name: add several users  
user: name={{ item }} state=present groups=wheel
  
with_items:
  
    - testuser1
  
    - testuser2
  以上写法与下面是完全等同的
- name: add user testuser1  
user: name=testuser1 state=present groups=wheel
  
- name: add user testuser2
  
user: name=testuser2 state=present groups=wheel
  请note使用 ‘with_items’ 用于迭代的条目类型不仅仅支持简单的字符串列表.如果你有一个哈希列表,那么你可以用以下方式来引用子项:
- name: add several users  
user: name={{ item.name }} state=present groups={{ item.groups }}
  
with_items:
  
    - { name: 'testuser1', groups: 'wheel' }
  
    - { name: 'testuser2', groups: 'root' }
ansible之tempalates 使用
  要求为webserver两台主机安装httpd 服务要求如下 - 监听端口80 - 0.101主机maxclient 值为100 - 0.102主机maxclient 值为200 - ServerName 为各自主机名 定义 httpd template 模板文件httpd.conf.j2
MaxClients   {{ maxclient }}  
Listen {{ http_port }}
  
ServerName {{ ansible_fqdn}}:80
  在Inventor hosts文件定义变量值
# cat /etc/ansible/hosts  

  
192.168.0.101 http_port=80 maxclient=100
  
192.168.0.102 http_port=80 maxclient=200
  在http.yml 引用模板变量
- hosts: webserver  
remote_user: root
  
vars:
  
- package: httpd
  
- service: httpd
  
tasks:
  
- name: install httpd package
  
    yum: name={{ package }} state=latest
  
- name: install congfiguration file for httpd
  
    template: src=/root/playboos/templates/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标签 tags
  如果你有一个大型的 playbook,那能够只运行其中特定部分的配置而无需运行整个 playbook 将会很有用.
# cat httpd.yml  
- hosts: webserver
  
remote_user: root
  
vars:
  
- package: httpd
  
- service: httpd
  
tasks:
  
- name: install httpd package
  
    yum: name={{ package }} state=latest
  
- name: install congfiguration file for httpd
  
    template: src=/root/playboos/templates/httpd.conf.j2 dest=/etc/httpd/conf/httpd.conf
  
    tags:
  
    - conf
  
    notify:
  
    - restart httpd
  
- name: start httpd service
  
    service: enabled=true name={{ service }} state=started
  
handlers:
  
- name: restart httpd
  
    service: name=httpd state=restarted
  如果你只想运行一个非常大的 playbook 中的 “conf” 你可以这样做:
# ansible-playbook httpd.yml --tags='conf'  另一方面,如果你只想执行 playbook 中某个特定任务 之外 的所有任务,你可以这样做:
# ansible-playbook httpd.yml --skip-tags='conf'ansible之role运用
  创建role的步骤

[*]  创建以roles命名的目录
[*]  在roles目录中分别创建以各个角色名称的目录,如webserver
[*]  在每个角色命名的目录中分别创建files、handlers]meta、tasks、templates、vars目录;用不到的目录可以创建,也可以不创建。
[*]  在playbook文件中,调用各角色;
  创建目录树
  # mkdir -pv /root/ansible_playbooks/roles/{webservs,dbservs}/{tasks,files,templates,meta,handlers,vars}
tree /root/ansible_playbooks/  
roles/
  
├── dbservs
  
│   ├── files
  
│   ├── handlers
  
│   ├── meta
  
│   ├── tasks
  
│   ├── templates
  
│   └── vars
  
├── site.yml
  
└── webservs
  
├── files
  
│   └── httpd.conf
  
├── handlers
  
│   └── main.yml
  
├── meta
  
├── tasks
  
│   └── main.yml
  
├── templates
  
└── vars
  复制httpd配置文件到files目录
cp /etc/httpd/conf/httpd.conf files/  定义webservs tasks/main.yml
  注意copy src 使用相对路径
# cat /root/ansible_playbooks/roles/webservs/tasks/main.yml  
- name: install httpd package
  
yum: name=httpd
  
- name: install configureation file
  
copy: src=httpd.conf dest=/etc/httpd/conf/httpd.conf
  
tags:
  
- conf
  
notify:
  
- restart httpd
  
- name: start httpd
  
service: name=httpd state=started
  定义webservs handlers/main.yml
# cat /root/ansible_playbooks/roles/webservs/handlers/main.yml  
- name: restart httpd
  
service: name=httpd state=restarted
  复制mysql配置文件到files目录
# cp /etc/my.cnf /root/ansible_playbooks/roles/dbservs/files/  定义dbservs tasks/main.yml
# cat dbservs/tasks/main.yml  
- name: install mysql-server package
  
yum: name=mysql-server state=latest
  
- name: install configuration file
  
copy: src=my.cnf dest=/etc/my.cnf
  
tags:
  
- myconf
  
notify:
  
- restart mysqld
  
- name: start mysqld service
  
service: name=mysqld enabled=true state=started
  定义dbservs handlers/main.yml
- name: restart mysqld  
service: name=mysqld state=restarted
  定义主机 site.yml
  注意角色名等于roles目录下目录名
# cat /root/ansible_playbooks/roles/site.yml  
- hosts: 192.168.0.101
  
remote_user: root
  
roles:
  
- webservs
  

  
- hosts: 192.168.0.102
  
remote_user: root
  
roles:
  
- dbservs
页: [1]
查看完整版本: ansible 系列教程