簡介
? ansible是新出現的自動化運維工具,基于Python開發,集合了眾多運維工具(puppet、chef、func、fabric)的優點,實現了批量系統配置、批量程序部署、批量運行命令等功能。
ansible是基于 paramiko 開發的,并且基于模塊化工作,本身沒有批量部署的能力。真正具有批量部署的是ansible所運行的模塊,ansible只是提供一種框架。ansible不需要在遠程主機上安裝client/agents,因為它們是基于ssh來和遠程主機通訊的。ansible目前已經已經被紅帽官方收購,是自動化運維工具中大家認可度最高的,并且上手容易,學習簡單。是每位運維工程師必須掌握的技能之一。
ansible 特點
- 部署簡單,只需在主控端部署Ansible環境,被控端無需做任何操作;
- 默認使用SSH協議對設備進行管理;
- 有大量常規運維操作模塊,可實現日常絕大部分操作;
- 配置簡單、功能強大、擴展性強;
- 支持API及自定義模塊,可通過Python輕松擴展;
- 通過Playbooks來定制強大的配置、狀態管理;
- 輕量級,無需在客戶端安裝agent(代理),更新時,只需在操作機上進行一次更新即可;
- 提供一個功能強大、操作性強的Web管理界面和REST API接口——AWX平臺。
- Ansible適用于中小型應用環境;SaltStack適合大型(Ansible由于不需要代理,只是通過ssh,因此只能性能不如Saltstack高)
Ansible安裝
法1.在已有python-pip
的情況下
$ pip install ansible
法2:
sudo apt-get install software-properties-common
sudo apt-add-repository ppa:ansible/ansible
sudo apt-get update
sudo apt-get install ansible
如果安裝失敗請換源sudo sed -i -re 's/\w+\.archive\.ubuntu\.com/archive.ubuntu.com/g' /etc/apt/sources.list
,更新安裝庫sudo apt-get update
ansible 架構圖
上圖中我們看到的主要模塊如下:
Ansible
:Ansible核心程序。
HostInventory
:主機清單 , 記錄由Ansible管理的主機信息,包括端口、密碼、ip等。
Playbooks
:“劇本”YAML格式文件,多個任務定義在一個文件中,定義主機需要調用哪些模塊來完成的功能。
CoreModules
:核心模塊,主要操作是通過調用核心模塊來完成管理任務。
CustomModules
:自定義模塊,完成核心模塊無法完成的功能,支持多種語言。
ConnectionPlugins
:連接插件,Ansible和Host通信使用
ansible配置文件查找順序
- 檢查環境變量
ANSIBLE_CONFIG
指向的路徑文件(export ANSIBLE_CONFIG=/etc/ansible.cfg); - HOME目錄下的配置文件
~/.ansible.cfg
- 檢查當前目錄下的ansible.cfg配置文件;
-
/etc/ansible.cfg
檢查etc目錄的配置文件。
使用特性
- 模塊化:調用特定的模塊,完成特定任務
- 有Paramiko,PyYAML,Jinja2(模板語言)三個關鍵模塊支持自定義模塊
- 基于Python語言實現
- 部署簡單,基于python和SSH(默認已安裝),agentless安全,基于OpenSSH支持playbook編排任務
- 冪等性:一個任務執行1遍和執行n遍效果一樣,不因重復執行帶來意外情況
- 無需代理不依賴PKI(無需ssl)可使用任何編程語言寫模塊
- YAML格式,編排任務,支持豐富的數據結構
- 較強大的多層解決方案
管理方式:
- Ad-Hoc,及Ansible命令,主要用于臨時命令使用場景
- Ansible-Playbook,腳本,用于長期規劃好,大型項目的場景,需要有提前的規劃
Ansible-playbook(劇本)執行過程:
- 將已有編排好的任務集寫入Ansible-Playbook
- 通過ansible-playbook命令分拆任務集至逐條ansible命令,按預定規則逐條執行
相關文件
配置文件
/etc/ansible/ansible.cfg 主配置文件,配置ansible工作特性
/etc/ansible/hosts 主機清單
/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界面與用戶交互的執行工具
1.設置被管理的主機清單vim /etc/ansible/hosts
2.1口令驗證方式.ansible 192.168.30.101 -m ping -k
用賬號密碼去確認受控端的身份
▲如果出現了這樣的情況,需要先安裝sshpass , sudo apt install sshpass
192.168.100.180 | FAILED! => {
"failed": true,
"msg": "ERROR! to use the 'ssh' connection type with passwords, you must install the sshpass program"
}
2.2基于key驗證
$ ssh-keygen
$ ssh-copy-id 192.168.30.101
Generating public/private rsa key pair.
Enter file in which to save the key (/xxxxxx/):
Enter passphrase (empty for no passphrase):
Enter same passphrase again:
Your identification has been saved in xxxxxxxxx.
Your public key has been saved in xxxxx.
The key fingerprint is:
SHA256:xxxxxxxxxxxxxx
The key's randomart image is:
如果設置了passphrase,那么鏈接時需要輸入passphrase,如果是ad-hoc就相當麻煩,而playbooks中有解決方法
ad-hoc使用
將host_key_checking
取消注釋,否則鏈接對象必須在known_hosts中
$ sudo vim /etc/ansible/ansible.cfg
uncomment this to disable SSH key host checking
#host_key_checking = False
顯示日志,取消注釋log_path = /var/log/ansible.log
△.ansible不是長期執行的服務,不長期執行,因此修改配置后不需要重啟服務
ansible <host-pattern>[-m module_name][-a args]
ansible dbsrvs -m command -a 'ls /root'-u wang-k -b-K
-u 以wang的身份登錄,-b將wang切換成root,-K 輸入root密碼.
-m 指定模塊名,-a指定模塊參數
ansible的Host-pattern即匹配主機的列表
All:表示所有Inventory中的所有主機
ansible all-m ping
:通配符
ansible""-m ping
ansible 192.168.1.-m ping
ansible"srvs"-m ping
或關系
ansible"websrvsiappsrvs"-m ping
ansible"192.168.1.10:192.168.1.20"-m ping
邏輯與
ansible "websrvs:&dbsrvs" -m ping
在websrvs組并且在dbsrvs組中的主機,單引號、雙引號都行
邏輯非
ansible 'websrvs:ldbsrvs'-m ping
在websrvs組,但不在dbsrvs組中的主機
注意:此處為單引號
綜合邏輯
ansible 'websrvs:dbsrvs:&appsrvs:lftpsrvs'-m ping
正則表達式
ansible "websrvs:&dbsrvs" -m ping
ansible "~(webldb).*\.magedu\.com" -m ping
ansible command
- creates=
- 存在,不執行
- removes=
- 不存在,不執行
- chdir=
- 切換目錄后執行
命令返回顏色說明
綠色: 表示查看信息,對遠程主機未做改動的命令
紅色: 批量管理產生錯誤信息
黃色: 對遠程主機做了相應改動
紫色: 對操作提出建議或忠告
常用模塊
- command
- shell : 遠程節點執行模塊
ansible all -m shel1 -a 'getenforce'
- script: 在遠程執行本地的腳本
ansible test -m script -a "/sh/test.sh"
- copy : 復制模塊
ansible all -m copy -a 'src=/root/ansible/selinux dest=/etc/selinux/config backup=yes'
ansible all -m copy-a 'src=/etc/shadow dest=/data/mode=000 owner=wang'
- fetch : 遠程獲取
ansible srv-m fetch -a 'src=/root/a. sh dest=/data/scripts'
- file : 文件操作,刪除、創建
ansible test -m file -a "dest=/tmp/hello state=touch"
- unarchieve、achieve : 壓縮解壓
ansible test -m unarchive -a 'src=/srv/tomcat8/apache-tomcat-8.0.29.tar.gz dest=/usr/local copy=no mode=0755'
- cron
- 開啟
ansible all-m cron -a 'minute=* weekday=1,3,5 jcb="/usr/bin/wall FBI warning" name=warningcron'
- 禁用
ansible all -m cron -a 'disabled=true job="/usr/bin/wall FBI warning"name=warningcron'
、啟用ansible all -m cron -a 'disabled=falsejob="/usr/bin/wall FBI warning"name=warningcron'
- 刪除
ansible all -m cron -a 'job="/usr/bin/wall FBI warning"name=warningcron state=absent'
- 開啟
- apt、yum
ansible all -m apt 'name=vim update_cache=yes'
- user
- group
- service
service:name=httpd state=started enabled=yes
- setup
ansible websrvs -m setup -a 'filter=*address*'
- template(不能放在ad-hoc)中,只能在playbook中使用
command模塊在針對管道、重定向有…*有問題==>使用shell模塊
▲一般 present 表示生成、下載, absent 表示刪除或卸載。
系列命令
galaxy
ansible-galaxy install geerlingguy.nginx
其中geerlingguy
為角色在./ansible/roles/
playbooks
Yaml
YAML Ain't Markup Language,即YAML不是XML。不過,在開發的這種語言時,YAML的意思其實是:"Yet Another Markup Language"(仍是一種標記語言)
核心元素
- Hosts 執行的遠程主機列表
- Tasks 任務集
- Varniables 內置變量或自定義變量在playbook中調用Templates 模板,可替換模板文件中的變量并實現一些簡單邏輯的文件Handlers 和notity結合使用,由特定條件觸發的操作,滿足條件方才執行,否則不執行
- tags 標簽指定某條任務執行,用于選擇運行playbook中的部分代碼。
- ansible具有冪等性,因此會自動跳過沒有變化的部分,即便如此,有些代碼為測試其確實沒有發生變化的時間依然會非常地長。此時,如果確信其沒有變化,就可以通過tags跳過此些代碼片斷
ansible-playbook-t tagsname useradd.yml
- ansible具有冪等性,因此會自動跳過沒有變化的部分,即便如此,有些代碼為測試其確實沒有發生變化的時間依然會非常地長。此時,如果確信其沒有變化,就可以通過tags跳過此些代碼片斷
加密
加密ansible-vault encrypt hello.yml
解密查看ansible-vault view hello.yml
重新制定口令ansible-vault rekey hello.yml
基礎組件
如果命令或腳本的退出碼不為零,可以使用如下方式替代
tasks:
- name:run this command and ignore the result
shell: /usr/bin/somecommand || /bin/true
或者使用ignore_errors來忽略錯誤信息:
tasks:
- name:run this command and ignore the result
shell:/usr/bin/somecommand
ignore_errors:True
運行playbook的方式
ansible-playbook <filename.yml>..[options]
常見選項
-check(-C)
只檢測可能會發生的改變,但不真正執行操作
--list-hosts
列出運行任務的主機
--limit
主機列表只針對主機列表中的主機執行
-V
顯示過程-vw-vwv更詳細
handlers和notify
tasks:
- name: install httpd package
yum: name=httpd
- name: copy conf file copy:src=files/httpd.conf dest=/etc/httpd/conf/backup=yes
notify: restart service
- name: start service
service: name=httpd state=started enabled=yes
handlers:
- name:restart service
service:name=httpd state=restarted
標簽
指定標簽來執行指定任務
ansible-playbook -t rshttp,xxxx httpd.yml
變量使用
jinjia2語法
{{ var }}
- 法一:ansible setup facts 遠程主機的所有變量都可直接調用
- 法二:在
/etc/ansible/hosts
中定義普通變量:主機組中主機單獨定義,優先級高于公共變量公共(組)變量:針對主機組中所有主機定義統一變量
[websrvs]
192.168.30.101 http_port=81
192.168.30.102 http_port=82
[websrvs:vars]
nodename=www
domainname=magedu.com
- 法三:
ansible-playbook -e 'var=xxx' app.html
,優先級比法二高 - 法四:
- hosts:
remote_user: root
vars:
- var: xxx
tasks:
- name:
yum: ...
迭代機制
tasks:
- name:
file: name=/data/{{ item }}
with_items:
- file1
- file2
- file3
迭代嵌套自變量
- hosts: websrvs
remote_user: root
tasks:
- name: add some groups
group: name={{ item ]} state=present
with_items:
- group1
- group2
- group3
- name: add some users
user: name={{ item. name ]} group={{ item. group )} state=present
with items:
- { name: user1, group:' group1'}
- { name: 'user2, group:' group2'}
- { name: 'user3', group:' group3'}
{% for vhost in nginx_vhosts%}
server{
listen{{ vhost }}
{% endfor %}
- hosts: websrvs
remote_user: root
vars:
ports:
- listen_port: 81
- listen_port: 82
- listen_port: 83
tasks:
- name: copy conf
template: src=forl.conf.j2 dest=/data/for1.conf
條件判斷
- hosts: all
remote_user: root
tasks:
#如果系統中存在主機名為nfs或者backup的主機,則創建文件
- name: Create File
file: path=/tmp/this_is_{{ ansible_hostname }}_file state=touch
when: (ansible_hostname == "nfs") or (ansible_hostname == "backup")
#系統為centos的主機才會執行
- name: Centos Install httpd
yum: name=httpd state=present
when: (ansible_distribution == "CentOS")
#系統為ubuntu的主機才會執行
- name: Ubuntu Install httpd
yum: name=httpd2 state=present
when: (ansible_distribution == "Ubuntu")
tasks:
- name: run df -h
sudo_user: test
sudo: yes
shell: name=df -h
ansible sudo 即將變更為become
[s21]
#代替原來192.168.1.21 ansible_ssh_user=i ansible_ssh_pass=i的寫法
192.168.1.21 ansible_ssh_user=i
ansible_ssh_private_key_file=/home/i/.ssh/id_rsa
ansible_become=true
ansible_become_user=root
ansible_become_pass='i'
獲取執行命令的輸出 –Register[轉]
- name: echo date
command: date
register: date_output
- name: echo date_output
command: echo "30"
when: date_output.stdout.split(' ')[2] == "30"
判斷文件是否存在[轉]
- name: judge a file or dir is exits
shell: ls /home/sfy
ignore_errors: True
register: result
- shell: echo "file exit"
when: result|succeeded
- shell: echo "file not exit"
when: result|failed
權限問題
關于權限問題,可以通過ansible -h
查看
Privilege Escalation Options:
control how and which user you become as on target hosts
-s, --sudo run operations with sudo (nopasswd) (deprecated, use
become)
-U SUDO_USER, --sudo-user=SUDO_USER
desired sudo user (default=root) (deprecated, use
become)
-S, --su run operations with su (deprecated, use become)
-R SU_USER, --su-user=SU_USER
run operations with su as this user (default=None)
(deprecated, use become)
-b, --become run operations with become (does not imply password
prompting)
--become-method=BECOME_METHOD
privilege escalation method to use (default=sudo),
valid choices: [ sudo | su | pbrun | pfexec | doas |
dzdo | ksu | runas | pmrun ]
--become-user=BECOME_USER
run operations as this user (default=root)
--ask-sudo-pass ask for sudo password (deprecated, use become)
--ask-su-pass ask for su password (deprecated, use become)
-K, --ask-become-pass
ask for privilege escalation password
▲其中deprecated表示是將被棄用的,將全部被become代替,(即參數-b)
關于-b和-K的作用,可以通過如下命令進行測試
$ ansible test -m shell -a "whoami" -K
mrli身份使用sudo權限
$ ansible test -m shell -a "whoami" -b
切換到root身份
$ ansible test -m shell -a "whoami" -b -K
▲這個權限問題在ansible執行shell腳本的時候需要特別注意
個人寫過的Playbook-demo
- hosts: 192.168.100.190
remote_user: apollo3d
become: yes
vars:
spark: /home/apollo3d/SimSpark/spark/build
rcssserver3d: /home/apollo3d/SimSpark/rcssserver3d/build
tasks:
- name: judge former platform directory Exsit
shell: 'ls /home/apollo3d/simspark-0.3.0/build'
ignore_errors: True
register: formerDirExsit
- name: uninstall
command: 'chdir={{ item }} make uninstall'
with_items:
- /home/apollo3d/simspark-0.3.0/build
- /home/apollo3d/rcssserver3d-0.7.1/build
when: formerDirExsit|succeeded
- name: remove
file:
dest: '{{ item }}'
state: absent
with_items:
- /home/apollo3d/simspark-0.3.0/
- /home/apollo3d/rcssserver3d-0.7.1/
when: formerDirExsit|succeeded
- name: judge new zip
shell: ls /home/apollo3d/SimSpark.tar.gz
ignore_errors: True
register: zipExsit
- name: jieya
unarchive:
src: /home/apollo3d/SimSpark.tar.gz
dest: /home/apollo3d/
copy: no
mode: 0755
when: zipExsit|succeeded
- name: mk dirs
file: "dest={{ item }} state=directory"
with_items:
- /home/apollo3d/SimSpark/spark/build
- /home/apollo3d/SimSpark/rcssserver3d/build
when: zipExsit|succeeded
- name: install1
command: 'chdir={{ spark }} {{ item }}'
with_items:
- cmake ..
- make -j4
- make install
when: zipExsit|succeeded
- name: install2
command: 'chdir={{ rcssserver3d }} {{ item }}'
with_items:
- cmake ..
- make -j4
- make install
when: zipExsit|succeeded
- name: config
shell: '{{ item }}'
with_items:
- echo '/usr/local/lib/simspark\n/usr/local/lib/rcssserver3d' | sudo tee /etc/ld.so.conf.d/spark.conf
- ldconfig
when: zipExsit|succeeded
roles
ansilbe自1.2版本引入的新特性,用于層次性、結構化地組織playbook。roles能夠根據層次型結構自動裝載變量文件、tasks以及handlers等。要使用roles只需要在playbook中使用include指令即可。簡單來講,roles就是通過分別將變量、文件、任務、模板及處理器放置于單獨的目錄中,并可以便捷地include它們的一種機制。角色一般用于基于主機構建服務的場景中,但也可以是用于構建守護進程等場景中
復雜場景:建議使用roles,代碼復用度高
- 變更指定主機或主機組
- 如命名不規范維護和傳承成本大
- 某些功能需多個Playbook,通過Includes即可實現
roles目錄結構:
playbook.yml
roles/
project/
tasks/
files/
vars/不常用
default/不常用
templates/
handlers/
meta/不常用
附錄
Ansible 配置SSH公鑰認證
安裝好Ansible之后,要開始工作,還需要創建一個被控制主機列表清單.默認讀取/etc/ansible/hosts,如果該文件不存在,則要收到進行創建.
也可以通過環境變量 ANSIBLE_INVENTORY 來設置默認清單文件,1.9版本之前用 ANSIBLE_HOSTSexport ANSIBLE_INVENTORY=~/ansible_hosts
創建SSH認證文件
該操作是在控制主機中進行。
SSH認證文件創建成功之后,將控制主機的公鑰文件 id_rsa.pub 添加到被控制主機的~/.ssh/authorized_keys。
\ ~
指的是控制主機和被控制主機通信的用戶家目錄。
\ id_rsa
是控制主機的私鑰文件,要嚴格保管。
\ id_rsa.pub
是控制主機的公鑰文件,可隨意分發。
法一:ansible all -m shell -a "cat /tmp/authorized_keys >> /root/.ssh/authorized_keys" -k
▲注意
如果被控制主機中用戶家目錄中不存在.ssh目錄,就創建。
然后將上傳的公鑰文件追加到用戶的authorized_keys文件中
法二: (親測)
通過authorized_key模塊來進行添加
ansible para -i /tmp/inventory.txt -m authorized_key -a "user=root key='{{ lookup('file','/root/.ssh/id_rsa.pub') }}'" -k
lookup('file','/root/.ssh/id_rsa.pub')
是讀取/root/.ssh/id_rsa.pub的內容
使用公鑰密鑰對驗證的方法登錄
1. 在本地也創建一個 apple 用戶,并創建 /home/apple/.ssh/ 目錄
$ useradd apple -s /bin/bash -d /home/apple/
創建 .ssh 目錄mkdir /home/apple/.ssh
修改 .ssh 目錄的權限chmod 700 /home/apple/.ssh
創建 /home/apple/.ssh/known_hosts 文件
2.收集所有遠程主機的公鑰,保存在上 /home/apple/.ssh/known_hosts 文件。這一步的作用,是為了在后面第一次ssh 連接時,不需要再輸密碼。
收集所有遠程主機的 公鑰,主要是利用 ssh-keyscan 命令:ssh-keyscan -f ip.txt >> /home/apple/.ssh/known_hosts
說明: ip.txt 文件存放所有的遠程主機 ip 地址,一行代表一臺主機。
3.創建公鑰私鑰對:
一般在對應用戶的 /home/apple/.ssh/ 目錄下創建。這也不是強制的,因為在ssh 發起連接時,可以指定使用的私鑰文件。 ssk-keygen -t rsa 一直按回車鍵就可以了。但要注意生成的 id_rsa 和 id_rsa.pub 存放的路徑。
4.將公鑰推送到所有的遠程主機
我們編寫playbook 文件,利用authorized_key 模塊就可以快速完成:
[root@centos_7 roles]$ cat ssh-addkey.yml ---- hosts: apps 對apps 組里的所有遠程主機
gather_facts: False
tasks:
- name: install sshkey
authorized_key:
user: apple
key: "{{ lookup('file', '/home/apple/.ssh/id_rsa.pub') }}"
state: present
說明: 在前面1,2,3步中,我們已經準備好了公私鑰對了。推送到遠程主機,可以手動推送,或者使用scp 復制到遠程主機。但是利用scp 復制之后,還需要修改遠程主機上的 /home/apple/.ssh/authorize_keys 文件的權限等等。 ansible 的 authorized_key 模塊就自動幫我們做了這些工作。 執行, ansible-playbook ssh-addkye.yml
在多臺遠程主機中創建用戶
不用ansible,單個操作
在 root 用戶下運行這條命令創建一個新用戶,yangxg 是用戶名
因為我叫楊學光,所以我取的用戶名是 yangxg
選擇一個你喜歡的用戶名,不一定非得和我的相同
root@localhost:~ useradd -m -s /bin/bash yangxg
把新創建的用戶加入超級權限組
root@localhost:~ usermod -a -G sudo yangxg
為新用戶設置密碼
注意在輸密碼的時候不會有字符顯示,不要以為鍵盤壞了,正常輸入即可
root@localhost:~ passwd yangxg
切換到創建的新用戶
root@localhost:~ su - yangxg
切換成功,@符號前面已經是新用戶名而不是 root 了
yangxg@localhost:~$
ansible
---
- hosts: all
vars:
user: test
password: "$6$rounds=100000$O2BHfT2XIF6oDb9w$8Hhv4vOrLN6JF/nRVYDd8zZdnn9TNkQutyYYywIcPF2kRiHgkwAjqHIN7sDUkd1DcjLRABWT9ULHZPBOF2bZS/"
remote_user: root
tasks:
- name: Add user {{ user }}
user: name={{user}} comment="ceph user" password={{ password }}
- name: Config /etc/sudoers
lineinfile: dest=/etc/sudoers state=present line='{{item}}' validate='visudo -cf %s'
with_items:
- "{{ user}} ALL=(ALL) NOPASSWD: ALL"
- "Defaults: {{user}} !requiretty"
$ python -c 'import crypt; print crypt.crypt("rescue", "hadoop")'
hadoop為salt,可以改成其他的。rescue是需要加密的內容
$ ansible rescue -m user -a "name=rescue shell=/bin/bash home=/home/rescue password= state=present" -b -K
$ ansible rescue -m shell -a "usermod -a -G sudo rescue" -b -K
user模塊增加 update_password=always時,可以更新密碼
一鍵掛載NFS:
ansible full -m mount -a "name=/data src=192.168.100.179:/data fstype=nfs state=mounted" -b -K
掛載需要用SUDO權限,所以-K必不可少.同時,在這之前已經使用過ssh進行了配對因此不需要輸入登錄用戶密碼.
其他命令記錄
ss -ntl | grep 80
vim /etc/sysconfig/network-scripts/ifcfg-eth0
建議可以使用Alias
service network restart
重啟網絡服務