一、基本概念
1.什麼是ansible?
ansible是新出現的自動化運維工具,基於Python開發,集合了衆多運維工具(puppet、chef、func、fabric)的優點,實現了批量系統配置、批量程序部署、批量運行命令等功能。
ansible是基於 paramiko 開發的,並且基於模塊化工作,本身沒有批量部署的能力。真正具有批量部署的是ansible所運行的模塊,ansible只是提供一種框架。ansible不需要在遠程主機上安裝client/agents,因爲它們是基於ssh來和遠
程主機通訊的。ansible目前已經已經被紅帽官方收購,是自動化運維工具中大家認可度最高的,並且上手容易,學習簡單。是每位運維工程師必須掌握的技能之一。
2.ansible 任務執行
ansible 任務執行模式
Ansible 系統由控制主機對被管節點的操作方式可分爲兩類,即adhoc和playbook:
-
ad-hoc模式(點對點模式)
使用單個模塊,支持批量執行單條命令。ad-hoc 命令是一種可以快速輸入的命令,而且不需要保存起來的命令。就相當於bash中的一句話shell。 -
playbook模式(劇本模式)
是Ansible主要管理方式,也是Ansible功能強大的關鍵所在。playbook通過多個task集合完成一類功能,如Web服務的安裝部署、數據庫服務器的批量備份等。可以簡單地把playbook理解爲通過組合多條ad-hoc操作的配置文件。
二、ansible安裝
1.獲得資源包安裝ansible(此處會有依賴性)
[root@server1 ~]# ls
ansible
[root@server1 ~]# cd ansible/
[root@server1 ansible]# ls
ansible-2.7.8-1.el7.noarch.rpm #單裝這個會產生依賴性缺失
ansible-tower-setup-bundle-3.4.2-1.el7.tar.gz
libtomcrypt-1.17-25.el7.x86_64.rpm
libtommath-0.42.0-5.el7.x86_64.rpm
python2-crypto-2.6.1-13.el7.x86_64.rpm
python2-jmespath-0.9.0-1.el7.noarch.rpm
python-httplib2-0.9.2-0.1.el7.noarch.rpm
python-keyczar-0.71c-2.el7.noarch.rpm
python-paramiko-2.1.1-0.9.el7.noarch.rpm
roles
sshpass-1.06-1.el7.x86_64.rpm
[root@server1 ansible]# yum install -y *.rpm #所以此處都安裝(其他的是依賴性包)
2.查看版本
[root@server1 ansible]# ansible --version
3.建立用戶,(ansible不推薦用root進行管理)
[root@server1 ansible]# useradd devops
[root@server1 ansible]# cd /etc/ansible/ #ansible的配置文件目錄
[root@server1 ansible]# ls
ansible.cfg hosts roles
在server2、server3、server4上也建立用戶,修改密碼
[root@server2 ~]# useradd devops
[root@server2 ~]# echo westos | passwd --stdin devops
[root@server3 ~]# useradd devops
[root@server3 ~]# echo westos | passwd --stdin devops
[root@server4 ~]# useradd devops
[root@server4 ~]# echo westos | passwd --stdin devops
4.切換到普通用戶,建立新的ansible目錄(方便以後修改配置,針對當前用戶的)
root@server1 ansible]# su - devops
[devops@server1 ~]$ ls
[devops@server1 ~]$ mkdir ansible
5.編寫當前用戶的inventory,編寫配置文件(讀取順序是先讀取當前的配置文件)
[devops@server1 ansible]$ vim inventory
[dev]
server2
[test]
server3
[prod]
server4
[webservers:children]
dev
test
prod
[devops@server1 ansible]$ vim ansible.cfg
[defaults]
inventory=inventory
測試:
[devops@server1 ansible]$ ansible-inventory --list all#查看組的定義(uground表示默認組)
[devops@server1 ansible]$ ansible dev --list-host #顯示定義組下的主機
5.測試主機之間網絡的連通性
[devops@server1 ansible]$ cat ansible.cfg
[defaults]
inventory=inventory
host_key_checking=False #不要key
[devops@server1 ansible]$ ansible all -m ping
[devops@server1 ansible]$ ansible all -m ping -k #此處輸入的密碼是普通用戶的密碼
此時在進行,則成功
[devops@server1 ansible]$ ansible all -m ping
測試:此時可在中控機上查看各目標主機的信息
[devops@server1 ansible]$ ansible all -a “hostname”
[devops@server1 ansible]$ ansible all -m shell -a “df -h”
6.配置免密連接
[devops@server1 ansible]$ ssh-keygen
Generating public/private rsa key pair.
Enter file in which to save the key (/home/devops/.ssh/id_rsa):
Enter passphrase (empty for no passphrase):
Enter same passphrase again:
Your identification has been saved in /home/devops/.ssh/id_rsa.
Your public key has been saved in /home/devops/.ssh/id_rsa.pub.
The key fingerprint is:
cc:c5:66:64:22:60:b2:97:eb:f6:ec:e5:19:be:e2:88 devops@server1
The key's randomart image is:
+--[ RSA 2048]----+
| . o.. . o |
| + . . = |
| . o = |
| . . o + |
| . S |
| . |
| o o |
| o +.+ o |
| E .o=.=. |
+-----------------+
[devops@server1 ~]$ l.
. .. .ansible .bash_logout .bash_profile .bashrc .ssh .viminfo
[devops@server1 ~]$ ssh-copy-id server2
[devops@server1 ~]$ ssh-copy-id server3
[devops@server1 ~]$ ssh-copy-id server4
三、ad-hoc管理
1.安裝httpd服務,並測試
幫助文檔查看:
[devops@server1 ansible]$ ansible-doc -l #查看模塊
[devops@server1 ansible]$ ansible-doc -l | grep ssh
[devops@server1 ansible]$ ansible-doc yum #查看服務使用
安裝httpd服務,但是會出現報錯
[devops@server1 ansible]$ ansible dev -m yum -a "name=httpd state=present" -b
注意:報錯是因爲目標主機的普通用戶需要密碼切換到超戶,進行設置
[root@server2 ~]# vim /etc/sudoers
[root@server3 ~]# vim /etc/sudoers
[root@server4 ~]# vim /etc/sudoers
再次進行安裝
[devops@server1 ansible]$ ansible dev -m yum -a “name=httpd state=present” -b
在server2上查看是否已經安裝
[root@server2 ~]# rpm -q httpd
httpd-2.4.6-45.el7.x86_64
2.設置開機自啓:
[devops@server1 ansible]$ ansible dev -m service -a "name=httpd state=started enabled=yes" -b
在server2上查看
[root@server2 ~]# netstat -antlp
3.開啓防火牆,開機自啓
[devops@server1 ansible]$ ansible dev -m service -a "name=firewalld state=started enabled=yes" -b
在server2上查看
[root@server2 ~]# firewall-cmd --list-services
dhcpv6-client ssh
[root@server2 ~]# systemctl status firewalld
4.編寫規則,將httpd寫進防火牆策略
[devops@server1 ansible]$ ansible dev -m firewalld -a "service=http permanent=yes immediate=yes state=enabled" -b
在server2上查看
[root@server2 ~]# firewall-cmd --list-services
dhcpv6-client ssh http
[root@server2 ~]# iptables -L
[devops@server1 ansible]$ curl server2 #此時查看的是httpd默認發佈頁
5.寫文件(寫默認發佈頁)
[devops@server1 ansible]$ ansible dev -m copy -a 'content="<h1>www.westos.org</h1>\n" dest=/var/www/html/index.html' -b
測試:
[devops@server1 ansible]$ curl server2
不用加-b操作:
[devops@server1 ansible]$ vim /etc/ansible/ansible.cfg #複製信息
[devops@server1 ansible]$ vim ansible.cfg
[defaults]
inventory=inventory
host_key_checking=False
[privilege_escalation]
become=True
become_method=sudo
become_user=root
become_ask_pass=False
[devops@server1 ansible]$ ansible dev -m copy -a 'content="<h1>www.westos.org</h1>\n" dest=/var/www/html/index.html'
四、playbook
playbook是嚴格按照縮進執行的,因此進行定義:
[devops@server1 ~]$ vim .vimrc
autocmd filetype yaml set ai ts=2 sw=2 et ##寫table的縮進,yml類型的文件,一個tab鍵代表兩個空格
1.編寫通過playbook執行的內容
[devops@server1 ~]$ cd ansible/
[devops@server1 ansible]$ vim playbook.yml
---
- name: apache playbook
hosts: test ##組,寫在inventory 文件下,即針對哪些主機
tasks: ##任務
- name: install httpd ##任務簡介
yum:
name: httpd
state: present
- name: start httpd
service:
name: httpd
state: started
enabled: true
- name: enabled firewalld
service:
name: firewalld
state: started
enabled: true
- name: configure firewalld
firewalld:
service: http
state: enabled
permanent: true
immediate: true
- name: copy index.html
copy:
content: "<h1>www.westos.org</h1>\n"
dest: /var/www/html/index.html
2.安裝http服務
語法檢測:
[devops@server1 ansible]$ ansible-playbook --syntax-check playbook.yml
playbook: playbook.yml #表示語法正確
執行內容,用ansible進行推送
[devops@server1 ansible]$ ansible-playbook playbook.yml
測試:
[devops@server1 ansible]$ curl server3
- 當對httpd配置文件進行修改時,需要重新加載服務
把httpd服務所需的配置文件複製
[devops@server1 ansible]$ mkdir files
[devops@server1 ansible]$ cd files/
[devops@server1 files]$ scp server2:/etc/httpd/conf/httpd.conf .
[devops@server1 files]$ vim httpd.conf #將端口改爲8000
添加任務
[devops@server1 ansible]$ vim playbook.yml
[devops@server1 ansible]$ vim playbook.yml
---
- name: apache playbook
hosts: test
tasks:
- name: install httpd
yum:
name: httpd
state: present
- name: configure httpd
copy:
src: files/httpd.conf
dest: /etc/httpd/conf/httpd.conf
owner: root
group: root
mode: '0644'
- name: start httpd
service:
name: httpd
state: started
enabled: true
- name: enabled firewalld
service:
name: firewalld
state: started
enabled: true
- name: configure firewalld
firewalld:
service: http
state: enabled
permanent: true
immediate: true
- name: copy index.html
copy:
content: "<h1>www.westos.org</h1>\n"
dest: /var/www/html/index.html
handlers: #觸發器(沒遇到notify的時候,觸發器不會觸發)
- name: restart httpd
service:
name: httpd
state: restarted
[devops@server1 ansible]$ ansible-playbook --syntax-check playbook.yml
playbook: playbook.yml
[devops@server1 ansible]$ ansible-playbook playbook.yml
注意:此時,改變一個地方;
[root@server3 ~]# vim /etc/httpd/conf/httpd.conf #配置文件更改了
[root@server3 ~]# netstat -antlp #但是此時仍然是80
添加動作,讓觸發器生效
[devops@server1 ansible]$ vim files/httpd.conf #改爲80
[devops@server1 ansible]$ vim playbook.yml
---
- name: apache playbook
hosts: test
tasks:
- name: install httpd
yum:
name: httpd
state: present
- name: configure httpd
copy:
src: files/httpd.conf
dest: /etc/httpd/conf/httpd.conf
owner: root
group: root
mode: '0644'
notify: restart httpd #僅添加此行
- name: start httpd
service:
name: httpd
state: started
enabled: true
- name: enabled firewalld
service:
name: firewalld
state: started
enabled: true
- name: configure firewalld
firewalld:
service: http
state: enabled
permanent: true
immediate: true
- name: copy index.html
copy:
content: "<h1>www.westos.org</h1>\n"
dest: /var/www/html/index.html
handlers:
- name: restart httpd
service:
name: httpd
state: restarted
[devops@server1 ansible]$ ansible-playbook --syntax-check playbook.yml
playbook: playbook.yml
[devops@server1 ansible]$ ansible-playbook playbook.yml
注意:此時改變兩次信息
[root@server3 ~]# vim /etc/httpd/conf/httpd.conf #配置文件和端口一致
注意:是基於md5碼的信息機進行比對,進行推送
[devops@server1 ansible]$ md5sum files/httpd.conf
f5e7449c0f17bc856e86011cb5d152ba files/httpd.conf
[root@server3 ~]# md5sum /etc/httpd/conf/httpd.conf
f5e7449c0f17bc856e86011cb5d152ba /etc/httpd/conf/httpd.conf
此時是一致的,再次進行推送不會有所更改
- 虛擬主機的配置
1.創建虛擬主機配置文檔 #模板在/usr/share/doc/httpd-2.4.6(可以rpm -ql httpd)
[devops@server1 ansible]$ cd files/
[devops@server1 files]$ ls
httpd.conf
[devops@server1 files]$ vim vhosts.conf
<VirtualHost *:80>
DocumentRoot /var/www/html
ServerName server3
</VirtualHost>
<VirtualHost *:80>
DocumentRoot /var/www/vhosts/example.com
ServerName server3.example.com
ErrorLog "/var/log/httpd/example.com-error_log"
CustomLog "/var/log/httpd/example.com-access_log" common
</VirtualHost>
<Directory "/var/www/vhosts/example.com">
Options Indexes FollowSymLinks
AllowOverride None
Require all granted
</Directory>
2.編寫playbook
---
- name: apache playbook
hosts: test
tasks:
- name: install httpd
yum:
name: httpd
state: present
- name: configure httpd
copy:
src: files/httpd.conf
dest: /etc/httpd/conf/httpd.conf
owner: root
group: root
mode: '0644'
notify: restart httpd
- name: start httpd
service:
name: httpd
state: started
enabled: true
- name: enabled firewalld
service:
name: firewalld
state: started
enabled: true
- name: configure firewalld
firewalld:
service: http
state: enabled
permanent: true
immediate: true
- name: copy index.html
copy:
content: "<h1>www.westos.org</h1>\n"
dest: /var/www/html/index.html
- name: create /var/www/vhosts/example.com
file:
path: /var/www/vhosts/example.com
state: directory
mode: '0755'
- name: create vhost.html
copy:
content: "server3.example.com-vhosts\n"
dest: /var/www/vhosts/example.com/vhost.html
- name: copy vhosts.conf
copy:
src: files/vhosts.conf
dest: /etc/httpd/conf.d/vhosts.conf
notify: restart httpd
handlers:
- name: restart httpd
service:
name: httpd
state: restarted
[devops@server1 ansible]$ ansible-playbook --syntax-check playbook.yml
playbook: playbook.yml
[devops@server1 ansible]$ ansible-playbook playbook.yml
測試:
[root@server1 ansible]# vim /etc/hosts
172.25.254.3 server3 server3.example.com
- playbook多個軟件的安裝
採用定義變量的方法:
1.在playbook文件裏定義變量
[devops@server1 ansible]$ vim playbook.yml
---
- name: apache playbook
hosts: test
vars:
web_package: httpd
web_service: httpd
firewalld_service: firewalld
tasks:
- name: install httpd
yum:
name: "{{ web_package }}"
state: present
- name: configure httpd
copy:
src: files/httpd.conf
dest: /etc/httpd/conf/httpd.conf
owner: root
group: root
mode: '0644'
notify: restart httpd
- name: start httpd
service:
name: "{{ web_service }}"
state: started
enabled: true
- name: enabled firewalld
service:
name: "{{ firewalld_service }}"
state: started
enabled: true
- name: configure firewalld
firewalld:
service: http
state: enabled
permanent: true
immediate: true
- name: copy index.html
copy:
content: "<h1>www.westos.org</h1>\n"
dest: /var/www/html/index.html
- name: create /var/www/vhosts/example.com
file:
path: /var/www/vhosts/example.com
state: directory
mode: '0755'
- name: create vhost.html
copy:
content: "server3.example.com-vhosts\n"
dest: /var/www/vhosts/example.com/vhost.html
- name: copy vhosts.conf
copy:
src: files/vhosts.conf
dest: /etc/httpd/conf.d/vhosts.conf
notify: restart httpd
handlers:
- name: restart httpd
service:
name: "{{ web_service }}"
state: restarted
[devops@server1 ansible]$ ansible-playbook --syntax-check playbook.yml
playbook: playbook.yml
[devops@server1 ansible]$ ansible-playbook playbook.yml
注意:此時不會有更改,因爲信息沒變,只是採用了定義變量的方式
2.局外定義變量
[devops@server1 ansible]$ mkdir vars
[devops@server1 ansible]$ cd vars/
[devops@server1 vars]$ vim web.yml
---
web_package: httpd
web_service: httpd
firewalld_service: firewalld
[devops@server1 ansible]$ vim playbook.yml
1 ---
2 - name: apache playbook
3 hosts: test
4 vars_files:
5 - vars/web.yml
6 tasks:
7 - name: install httpd
8 yum:
9 name: "{{ web_package }}"
10 state: present
[devops@server1 ansible]$ ansible-playbook --syntax-check playbook.yml
playbook: playbook.yml
[devops@server1 ansible]$ ansible-playbook playbook.yml
注意:也不會改變
3.想要在現有基礎上添加服務進火牆策略(方法一)
[root@server3 ~]# firewall-cmd --list-service
dhcpv6-client ssh http
[devops@server1 ansible]$ vim playbook.yml
1 ---
2 - name: apache playbook
3 hosts: test
4 vars:
5 firewalld_svc:
6 - http
7 - https
8 vars_files:
9 - vars/web.yml
10 tasks:
11 - name: install httpd
12 yum:
13 name: "{{ web_package }}"
14 state: present
37 - name: configure firewalld
38 firewalld:
39 service: "{{ item }}"
40 state: enabled
41 permanent: true
42 immediate: true
43 loop: "{{ firewalld_svc }}"
[devops@server1 ansible]$ ansible-playbook --syntax-check playbook.yml
playbook: playbook.yml
[devops@server1 ansible]$ ansible-playbook playbook.yml
在server3查看
4.想要在現有基礎上添加服務進火牆策略(方法二)
[devops@server1 ansible]$ vim playbook.yml
1 ---
2 - name: apache playbook
3 hosts: test
4 vars:
5 firewalld_svc:
6 - http
7 - https
8 vars_files:
9 - vars/web.yml
10 tasks:
11 - name: install httpd
12 yum:
13 name: "{{ web_package }}"
14 state: present
37 - name: configure firewalld
38 firewalld:
39 service: "{{ item }}"
40 state: enabled
41 permanent: true
42 immediate: true
43 loop:
44 - http
45 - https
46 - ftp
[devops@server1 ansible]$ ansible-playbook --syntax-check playbook.yml
playbook: playbook.yml
[devops@server1 ansible]$ ansible-playbook playbook.yml
在server3上查看
- 不同主機安裝不同的服務
[devops@server1 ansible]$ vim playbook.yml
37 - name: configure firewalld
38 firewalld:
39 service: "{{ item }}"
40 state: enabled
41 permanent: true
42 immediate: true
43 loop: "{{ firewalld_svc }}"
[devops@server1 vars]$ cp web.yml ftp.yml
[devops@server1 vars]$ vim ftp.yml
---
ftp_package: vsftpd
ftp_service: vsftpd
firewalld_service: firewalld
[devops@server1 ansible]$ cp playbook.yml vsftp.yml
[devops@server1 ansible]$ vim vsftp.yml
---
- name: vsftp playbook
hosts: prod
vars:
firewalld_svc:
- ftp
vars_files:
- vars/ftp.yml
tasks:
- name: install vsftpd
yum:
name: "{{ ftp_package }}"
state: present
- name: configure vsftpd
copy:
src: files/vsftpd.conf
dest: /etc/vsftpd/vsftpd.conf
owner: root
group: root
mode: '0600'
notify: restart vsftpd
- name: start vsftpd
service:
name: "{{ ftp_service }}"
state: started
enabled: true
- name: enabled firewalld
service:
name: "{{ firewalld_service }}"
state: started
enabled: true
- name: configure firewalld
firewalld:
service: "{{ item }}"
state: enabled
permanent: true
immediate: true
loop: "{{ firewalld_svc }}"
handlers:
- name: restart vsftpd
service:
name: "{{ ftp_service }}"
state: restarted
[devops@server1 files]$ ls
httpd.conf vhosts.conf vsftpd.conf
[devops@server1 files]$ ll
total 24
-rw-r--r-- 1 devops devops 11753 May 10 22:57 httpd.conf
-rw-rw-r-- 1 devops devops 474 May 10 23:02 vhosts.conf
-rw-r--r-- 1 root root 5030 May 11 00:03 vsftpd.conf
[root@server1 files]# chown devops.devops vsftpd.conf
[devops@server1 ansible]$ cp playbook.yml apache.yml
[devops@server1 ansible]$ vim playbook.yml
---
- import_playbook: apache.yml
- import_playbook: vsftp.yml
[devops@server1 ansible]$ rm -rf playbook.retry
[devops@server1 ansible]$ ansible-playbook --syntax-check vsftp.yml
playbook: vsftp.yml
[devops@server1 ansible]$ ansible-playbook --syntax-check apache.yml
playbook: apache.yml
[devops@server1 ansible]$ ansible-playbook playbook.yml
- 讓按照需求在對應的主機安裝對應的服務
[devops@server1 ansible]$ vim test.yml
---
- name: test
hosts:
- prod
- test
tasks:
- name: deploy apache
yum:
name: httpd
state: latest
when: ansible_hostname in groups['test']
- name: deploy vsftpd
yum:
name: vsftpd
state: present
when: ansible_hostname in groups['prod']
[devops@server1 ansible]$ ansible-playbook --syntax-check test.yml
playbook: test.yml
[devops@server1 ansible]$ ansible-playbook test.yml
- 用戶的創建針創建不同用戶(用戶和密碼對應)
[devops@server1 ansible]$ cd vars/
[devops@server1 vars]$ vim user.yml
---
userlist:
- name: user1
pass: westos
- name: user2
pass: redhat
[devops@server1 ansible]$ vim test.yml
---
- name: test
hosts:
- test
vars_files:
- vars/user.yml
tasks:
- name: create user
user:
name: "{{ item.name }}"
state: present
password: "{{ item.pass }}"
loop: "{{ userlist }}"
[devops@server1 ansible]$ ansible-playbook --syntax-check test.yml
playbook: test.yml
[devops@server1 ansible]$ ansible-playbook test.yml
注意:此時有警告,是因爲密碼是明文的
採用加密的方式:
[devops@server1 ansible]$ vim test.yml
---
- name: test
hosts:
- test
vars_files:
- vars/user.yml
tasks:
- name: create user
user:
name: "{{ item.name }}"
state: present
password: "{{ item.pass | password_hash('sha512') }}"
loop: "{{ userlist }}"
[devops@server1 ansible]$ ansible-playbook --syntax-check test.yml
playbook: test.yml
[devops@server1 ansible]$ ansible-playbook test.yml
測試: