前言:本篇博客紧承上一篇博客
一.ansible中playbook介绍
playbooks是 一个不同于使用Ansible命令行执行方式的模式,其功能更强大灵活。简单来说,playbook是一个非常简单的配置管理和多主机部署系统,不同于任何已经存在的模式,可作为一个适合部署复杂应用程序的基础。Playbook可以定制配置,可以按照指定的操作步骤有序执行,支持同步和异步方式。值得注意的是playbook是通过YAML格式来进行描述定义的。
- 核心元素
Tasks:任务,由模板定义的操作列表
Variables:变量
Templates:模板,即使用模板语法的文件
Handlers:处理器 ,当某条件满足时,触发执行的操作
Roles:角色
二.利用playbook搭建一个简单的httpd服务
1.编写playbook文件
为了方便书写,可以设置vim的tab键为两个空格
[devops@server1 ~]$ vim .vimrc
autocmd filetype yaml setlocal ai ts=2 sw=2 et
[devops@server1 ansible]$ vim playbook.yml ##名字可以自定义,要以yml结尾
---
# deploy apache
- hosts: webservers ##主机名称
tasks: ##创建任务
- name: install httpd
yum: ##安装httpd
name: httpd
state: latest
- name: create index.html
copy: ##复制模块
content: "www.servers.org\n" ##源文件路径,也可以直接写内容
dest: /var/www/html/index.html ##目的地文件路径
- name: start httpd ##启动服务
service:
name: httpd
state: started
2.推送执行
在推送之前可以检测语法,列出主机及任务
[devops@server1 ansible]$ ansible-playbook playbook.yml --syntax-check
[devops@server1 ansible]$ ansible-playbook playbook.yml --list-hosts
[devops@server1 ansible]$ ansible-playbook playbook.yml --list-tasks
[devops@server1 ansible]$ ansible-playbook playbook.yml
PLAY [webservers] *******************************************************************
TASK [Gathering Facts] **************************************************************
ok: [server2]
ok: [server3]
TASK [install httpd] ****************************************************************
ok: [server2]
ok: [server3]
TASK [create index.html] ************************************************************
changed: [server2]
changed: [server3]
TASK [start httpd] ******************************************************************
ok: [server3]
ok: [server2]
PLAY RECAP **************************************************************************
server2 : ok=4 changed=1 unreachable=0 failed=0
server3 : ok=4 changed=1 unreachable=0 failed=0
3.测试访问
[devops@server1 ansible]$ curl server2
www.servers.org
[devops@server1 ansible]$ curl server3
www.servers.org
4.修改配置文件
由于server1上没有安装httpd,配置文件从已经安装httpd的主机上拷贝一份
[devops@server1 files]$ scp server2:/etc/httpd/conf/httpd.conf .
httpd.conf 100% 11KB 11.5KB/s 00:00
[devops@server1 files]$ ll
total 12
-rw-r–r-- 1 devops devops 11753 Jun 18 22:29 httpd.conf
[devops@server1 ansible]$ vim playbook.yml
---
# deploy apache
- hosts: webservers
tasks:
- name: install httpd
yum:
name: httpd
state: latest
- name: create index.html
copy:
content: "{{ ansible_facts.hostname }}\n" ##显示主机名称
dest: /var/www/html/index.html
- name: configure httpd
copy:
src: files/httpd.conf
dest: /etc/httpd/conf/httpd.conf
owner: root
group: root
mode: 644
notify: restart httpd
- name: start httpd
service:
name: httpd
state: started
enabled: true
handlers:
- name: restart httpd
service:
name: httpd
state: restarted
- name: start firewalld ##启动火墙服务
service:
name: firewalld
state: started
enabled: true
- name: configure firewalld
firewalld:
service: http
state: enabled
permanent: yes
immediate: yes
5.再次推送访问
[devops@server1 ansible]$ curl server2
server2
[devops@server1 ansible]$ curl server3
server3
6.修改默认发布目录信息
添加以下内容
- name: create index.html
copy:
content: "{{ ansible_facts.hostname }} {{ ansible_facts['default_ipv4']['address']}}\n"
##获取主机ip地址
dest: /var/www/html/index.html
tags: one ##添加tags模块,执行的时候只运行此模块
[devops@server1 ansible]$ ansible-playbook playbook.yml -t one
PLAY RECAP **************************************************************************
server2 : ok=5 changed=1 unreachable=0 failed=0
server3 : ok=5 changed=1 unreachable=0 failed=0
[devops@server1 ansible]$ curl server2
server2 172.25.61.2
[devops@server1 ansible]$ curl server3
server3 172.25.61.3
三.playbook中如何取变量
[devops@server1 ansible]$ pwd
/home/devops/ansible
[devops@server1 ~]$ cd ansible/templates/
[devops@server1 templates]$ vim info.j2
[devops@server1 templates]$ cat info.j2
主机名:{{ ansible_facts['hostname'] }}
主机ip:{{ ansible_facts['eth0']['ipv4']['address'] }}
根分区大小:{{ ansible_facts['devices']['dm-0']['size'] }}
系统内核:{{ ansible_facts['kernel'] }}
[devops@server1 ansible]$ vim hostinfo.yml
---
- hosts: all
tasks:
- name: create infofile
template:
src: templates/info.j2 ##上面编写的文件地址
dest: /mnt/hostinfo ##存放地址
检测文件的语法是否有错误
[devops@server1 ansible]$ ansible-playbook hostinfo.yml --syntax-check
playbook: hostinfo.ym
l
进行推送
[devops@server1 ansible]$ ansible-playbook hostinfo.yml
PLAY [all] **************************************************************************
TASK [Gathering Facts] **************************************************************
ok: [server2]
ok: [server3]
TASK [create infofile] **************************************************************
changed: [server2]
changed: [server3]
PLAY RECAP **************************************************************************
server2 : ok=2 changed=1 unreachable=0 failed=0
server3 : ok=2 changed=1 unreachable=0 failed=0
查看运行结果
[devops@server1 ansible]$ ansible all -a ‘ls -l /mnt/hostinfo’
[devops@server1 ansible]$ ansible server2 -a ‘cat /mnt/hostinfo’
[devops@server1 ansible]$ ansible server3 -a ‘cat /mnt/hostinfo’
四.yml文件编写应用
1.下面我们来写一个软件安装的yml文件
[devops@server1 ansible]$ vim install.yml
---
- hosts: all
tasks:
- name: install httpd
yum:
name: httpd
state: present
when: ansible_facts['hostname'] == 'server2'
##### 安装时加了一个条件,就是当主机名为server2时才安装
[devops@server1 ansible]$ ansible-playbook install.yml
PLAY [all] **************************************************************************
TASK [Gathering Facts] **************************************************************
ok: [server2]
ok: [server3]
TASK [install httpd] ****************************************************************
skipping: [server3]
ok: [server2]
PLAY RECAP **************************************************************************
server2 : ok=2 changed=0 unreachable=0 failed=0
server3 : ok=1 changed=0 unreachable=0 failed=0
可以看到在执行的过程中跳过了server3,这样就可以灵活操作各个主机了
在不同的主机上安装不同的软件
[devops@server1 ansible]$ vim install.yml
---
- hosts: all
tasks:
- name: install httpd ##设置只在server2安装httpd等多个软件
yum:
name: "{{ item }}" ##固定变量
state: present
when: ansible_facts['hostname'] == 'server2'
loop:
- httpd
- mariadb
- php
- name: install vim ##设置在只server3安装vim
yum:
name: vim
state: present
when: ansible_facts['hostname'] == 'server3'
2.制作相互解析
[devops@server1 ansible]$ vim templates/hosts.j2
{% for host in groups ['webservers'] %}
{{ hostvars[host]['ansible_facts']['eth0']['ipv4']['address'] }} {{ hostvars[host]['ansible_facts']['hostname'] }}
{% endfor %}
[devops@server1 ansible]$ cat hosts.yml
---
- hosts: all
tasks:
- name: create hosts
template:
src: templates/hosts.j2
dest: /etc/hosts
[devops@server1 ansible]$ ansible-playbook hosts.yml
[root@server2 ~]# cat /etc/hosts
172.25.61.3 server3
172.25.61.2 server2
[root@server3 ~]# cat /etc/hosts
172.25.61.3 server3
172.25.61.2 server2
3.批量创建用户
[devops@server1 ansible]$ vim adduser.yml
---
- hosts: all
tasks:
- name: create users
user:
name: "{{ item }}"
state: present
password: redhat
loop:
- user1
- user2
- user3
但是这样创建的用户密码和和用户名是一样的,我们可以指定一个列表,将用户名和密码写在这个列表中
[devops@server1 ansible]$ vim vars/userlist.yml
---
userlist:
- user: user1
pass: redhat
- user: user2
pass: xinxin
- user: user3
pass: minmin
[devops@server1 ansible]$ vim adduser.yml
---
- hosts: all
vars_files:
- vars/userlist.yml
tasks:
- name: create users
user:
name: "{{ item.user }}" ##用户名
state: present
password: "{{ item.pass }}" ##密码
loop: "{{ userlist }}"
但是我们可以直接看到用户名和密码,这样不安全,ansible提供了加密的方法
[devops@server1 ansible]$ cat vars/userlist.yml
---
userlist:
- user: user1
pass: redhat
- user: user2
pass: xinxin
- user: user3
pass: minmin
[devops@server1 ansible]$ ansible-vault --help
Usage: ansible-vault [create|decrypt|edit|encrypt|encrypt_string|rekey|view] [options] [vaultfile.yml]
encryption/decryption utility for Ansible data files
Options:
--ask-vault-pass ask for vault password
-h, --help show this help message and exit
--new-vault-id=NEW_VAULT_ID
the new vault identity to use for rekey
--new-vault-password-file=NEW_VAULT_PASSWORD_FILE
new vault password file for rekey
--vault-id=VAULT_IDS the vault identity to use
--vault-password-file=VAULT_PASSWORD_FILES
vault password file
-v, --verbose verbose mode (-vvv for more, -vvvv to enable
connection debugging)
--version show program's version number and exit
See 'ansible-vault <command> --help' for more information on a specific
[devops@server1 ansible]$ ansible-vault encrypt vars/userlist.yml
New Vault password:
Confirm New Vault password:
Encryption successful
[devops@server1 ansible]$ cat vars/userlist.yml
$ANSIBLE_VAULT;1.1;AES256
39313465326237313737626233623131636263303538393936646363346666386134383362323639
3136623933613932353637313434616230373533356639330a303463626635336365353839613266
66643237343031396462333139356536333138333133376335313063366363656165303130393838
3964313962316539360a333831636538396431613931616538343866303738633030353166343830
66653631643630313637363235366338363531613338373766373562323262366261643334346430
64636534303663333032336339353636336434663763643332323437323938363637623538656138
36666533323135333735616231626338353261376333646334613865613134373837326461316139
61316331303565393562303436363566366239326465643661393966653031386331613532336364
30656339663066363766396533636334326662366164323139373465623334383365643230353738
3964366435373366376165383237646235326366383163653435
推送时需要你刚才设置的密码
[devops@server1 ansible]$ ansible-playbook adduser.yml --ask-vault-pass
Vault password:
但是又出现了一个问题,/etc/shadow密码是明文的,不安全
[devops@server1 ansible]$ vim adduser.yml
使用哈希加密
---
- hosts: all
vars_files:
- vars/userlist.yml
tasks:
- name: create users
user:
name: "{{ item.user }}"
state: present
password: "{{ item.pass | password_hash('sha512','mysecretsalt')}}"
loop: "{{ userlist }}"
[devops@server1 ansible]$ ansible-playbook adduser.yml --ask-vault-pass
[root@server2 ~]# cat /etc/shadow
可以看到已经加密