1、ansible概述
Ansible是一款爲類Unix系統開發的自由開源的配置和自動化工具。它用Python寫成,相似於saltstack和Puppet,可是有一個不一樣和優勢是咱們不須要在節點中安裝任何客戶端。它使用SSH來和節點進行通訊。Ansible基於 Python paramiko 開發,分佈式,無需客戶端,輕量級,配置語法使用 YMAL 及 Jinja2模板語言,更強的遠程命令執行操做。php
2、ansible的特色
一、部署簡單,只需在主控端部署Ansible環境,被控端無需作任何操做;python
二、默認使用SSH協議對設備進行管理;mysql
三、主從集中化管理;linux
四、配置簡單、功能強大、擴展性強;nginx
五、支持API及自定義模塊,可經過Python輕鬆擴展;web
六、經過Playbooks來定製強大的配置、狀態管理sql
七、對雲計算平臺、大數據都有很好的支持shell
3、ansible的工做機制
Ansible 在管理節點將 Ansible 模塊經過 SSH 協議推送到被管理端執行,執行完以後自動刪除,可使用 SVN 等來管理自定義模塊及編排。vim
由上面的圖能夠看到 Ansible 的組成由 5 個部分組成:安全
Ansible : ansible核心
Modules : 包括 Ansible 自帶的核心模塊及自定義模塊
Plugins : 完成模塊功能的補充,包括鏈接插件、郵件插件等
Playbooks : 劇本;定義 Ansible 多任務配置文件,由Ansible自動執行**
Inventory : 定義 Ansible 管理主機的清單 [ˈɪnvəntri]清單
4、ansible安裝與配置
一、安裝並配置ansible
1.1 實驗環境以下
1.2 安裝ansible
yum install -y epel-releaseyum install -y ansible
1.3 ansible語法參數
1.3.1 ansible的命令語法
ansible [-i 主機文件] [-f 批次] [組名] [-m 模塊名稱] [-a 模塊參數]
1.3.2 ansible的詳細參數
-v,--verbose # 詳細模式,若是命令執行成功,輸出詳細的結果(-v,-vv,-vvv)-i PATH,--inventory=PATH # 指定host文件路徑,默認是/etc/ansible/hosts-f NUM,--forks=NUM # NUM是整數,默認是5,指定fork開啓同步進程的個數-m NAME,--module-name=NAME # 指定module名稱,默認使用command模塊-a,MODULE_ARGS # 指定module模塊的參數-k,--ask-pass # 提示輸入ssh密碼,而不是使用基於ssh的密鑰認證-sudo # 指定使用sudo獲取root權限-K,--ask-sudo-pass # 提示輸入sudo密碼,和-sudo一塊兒使用-u USERNAME,--user=USERNAME # 指定移動端的執行用戶-C,--check # 測試此命令執行會產生什麼效果,不會真的執行
1.3.3 ansible-doc的詳細參數
-l # 列出全部模塊列表-s MODULE-NAME # 查看指定模塊參數
1.4 ansible的主機清單
1.4.1 基於端口,用戶,密碼定義的主機清單
ansible基於ssh鏈接,-i(--inventory)參數後面指定遠程主機時,也能夠寫端口,用戶,密碼。
其格式參數以下:
ansible_ssh_port # 指定ssh端口ansible_ssh_user # 指定ssh用戶ansible_ssh_pass # 指定ssh用戶的認證密碼(明文,不安全)ansible_sudo_pass # 指定sudo時候的認證密碼(明文,不安全)
例子(配置文件默認在/etc/ansible/hosts裏):
[web-server]172.16.2.101 ansible_ssh_port=22 ansible_ssh_user=root ansible_ssh_pass=P@ssW0rd
測試:
ansible -i /etc/ansible/hosts web-server -m ping# 報下面錯誤172.16.2.101 | FAILED! => { "msg": "Using a SSH password instead of a key is not possible because Host Key checking is enabled and sshpass does not support this. Please add this host's fingerprint to your known_hosts file to manage this host."}# 解決辦法1:手動鏈接一下客戶端,ssh root@172.16.2.101# 解決辦法2:在/etc/ansible/ansible.cfg下,將host_key_checking=false啓用# 再運行上面命令測試172.16.2.101 | SUCCESS => { "changed": false, "ping": "pong"}
1.4.2 基於ssh密鑰來訪問主機清單
通常來講,經過明文密碼訪問是不安全的,因此通常使用密鑰的形式進行訪問。
(1)、生產密鑰
[root@ansible-server ansible]# ssh-keygenGenerating public/private rsa key pair.Enter file in which to save the key (/root/.ssh/id_rsa):Enter passphrase (empty for no passphrase):Enter same passphrase again:Your identification has been saved in /root/.ssh/id_rsa.Your public key has been saved in /root/.ssh/id_rsa.pub.The key fingerprint is:SHA256:Hs3bs9rMZ5gW67WEdO7DpKJv1FzcZZkAj7G3iDm1XAI root@ansible-serverThe key's randomart image is:+---[RSA 2048]----+| E o... o|| . = oo|| = = o.|| o= * + .|| S+o*.o. || . .o+++. || ... +O+ || o+**=. || .+o=*oo. |+----[SHA256]-----+
(2)、分發密鑰
# 配置ansible的hosts文件[dev]172.16.2.185172.16.2.186172.16.2.187172.16.2.188[dev:vars]# 上面定義的幾臺服務器的用戶,端口,密碼都同樣,因此就單獨提出來寫ansible_ssh_user=rootansible_ssh_port=22ansible_ssh_pass=HJKJ123456hjkj# 分發密碼ansible dev -m authorized_key -a "user=root key='{{lookup('file','/root/.ssh/id_rsa.pub')}}'"# 刪除hosts配置文件中的密碼配置# 測試[root@ansible-server ansible]# ansible dev -m ping172.16.2.186 | SUCCESS => { "changed": false, "ping": "pong"}172.16.2.185 | SUCCESS => { "changed": false, "ping": "pong"}172.16.2.187 | SUCCESS => { "changed": false, "ping": "pong"}172.16.2.188 | SUCCESS => { "changed": false, "ping": "pong"}
1.5 ansible模塊
1.5.1 command模塊
command模塊爲ansible默認模塊,不指定-m參數時,使用的就是command模塊。command模塊比較簡單,經常使用的命令均可以使用,但其命令的執行不是經過shell腳本,因此,像 "<", ">", "|", and "&"操做都不能夠。不支持管道,不能批量執行命令。
相關選項以下:
creates # 一個文件名,當該文件存在,則該命令不執行free_from # 要執行的linux命令chdir # 在執行命令前,先切換到改目錄removes # 一個文件名,當該文件不存在時,則該選項不執行executable # 切換shell來執行命令, 該命令的路徑是一個絕對值
例子:
ansible dev -m command -a "uptime"
1.5.2 shell模塊
使用shell模塊,在遠程經過/bin/bash來執行,因此在終端使用Linux下各類命令都是能夠的。
例子:
ansible dev -m shell -a "free -m | grep Swap"
可是咱們在/.bash_profile中的環境變量shell因爲沒有加載,因此沒法識別。若是須要使用自定義的環境變量,須要在執行的開始加載環境變量。
例子:
ansible dev -m shell -a "source ~/.bash_profile && free -m | grep Swap"
對shell模塊使用能夠分爲兩類:
(1)、執行語句少,能夠直接寫在一句話中,如上。
(2)、若是語句較多,能夠寫成一個腳本,經過copy模塊將腳本拷貝到遠端,再用shell模塊去執行腳本
例子:
vim /tmp/joker_test.sh#!/bin/bashdate +%F_%H:%M:%Schmod +x /tmp/joker_test.shansible dev -m copy -a "src=/tmp/joker_test.sh dest=/tmp/joker_test.sh owner=root group=root mode=0755"ansible dev -m shell -a "/tmp/joker_test.sh"
1.5.3 script模塊
使用script模塊,在本地寫一個腳本,在遠端執行,恰好解決shell遠端執行腳本的問題。
例子:
vim /root/joker/test.sh#!/bin/bashdate +F%chmod +x /root/joker/test.shansible dev -m script -a "/root/joker/test.sh"
1.5.4 copy模塊
copy模塊的主要做用就是實現主控端向目標主機拷貝文件,相似scp的功能。
相關的選項以下:
backup # 在覆蓋以前,將源文件備份,備份文件包含事件信息,選項有(yes|no)content # 用於替代src,能夠直接設定指定文件的值dest # 必選項,遠程主機的絕對路徑,若是源文件是目錄,那麼該路徑也必須是一個目錄directory_mode # 遞歸設置目錄的權限,默認爲系統默認的權限force # 若是是yes,強制覆蓋;若是是no,只有當目標位置不存在時才複製others # 全部file模塊裏的選項均可以在這裏使用src # 本地目錄,能夠是相對路徑,也能夠是絕對路徑,'/'結尾賦值裏的內容,否則包括目錄在內
例子:
ansible dev -m copy -a "src=/root/joker/test.sh dest=/tmp/ owner=root group=root mode=755"ansible dev -a "ls /tmp/test.sh"
1.5.5 file模塊
file模塊是用來設置文件的屬性。
相關選項以下:
force # 會在兩種狀況下建立軟鏈接:一、源文件不存在,但以後會創建。二、目標軟鏈接已經存在,先取消再建立group # 定義文件/目錄的屬組owner # 定義文件/目錄的屬主mode # 定義文件/目錄的q權限path # 必選項,定義文件/目錄的路徑recurse # 遞歸設置屬性,只對目錄有效src # 被軟連接的源文件路徑,只應用在state=link的狀況下dest # 被軟連接的目標文件路徑,只應用在state=link的狀況下stat directory # 若是目錄不存在,就建立目錄 file # 即便文件不存在,也不會被建立 link # 建立軟連接 hard # 建立硬連接 touch # 若是文件不存在,就建立文件,若是文件存在,更新修改時間 absent # 刪除目錄、文件或取消l連接文件
例子:
# 遠程建立符號連接ansible dev -m file -a "src=/etc/resolv.conf dest=/tmp/resolv.conf state=link"# 查看ansible dev -a "ls -l /tmp/resolv.conf"172.16.2.187 | SUCCESS | rc=0 >>lrwxrwxrwx 1 root root 16 Jan 29 16:16 /tmp/resolv.conf -> /etc/resolv.conf# 刪除符號連接ansible dev -m file -a "path=/tmp/resolv.conf state=absent"# 查看ansible dev -a "ls -l /tmp/resolv.conf"172.16.2.187 | FAILED | rc=2 >>ls: cannot access /tmp/resolv.conf: No such file or directorynon-zero return code
1.5.6 stat模塊
stat模塊的做用是獲取遠程文件的信息,包括atime,ctime等等。
例子:
ansible dev -m stat -a "path=/etc/resolv.conf"
1.5.7 get_url模塊
get_url模塊實現從遠程主機下載指定的url到本地,支持sha256sum文件校驗。
force=yes 強制覆蓋;force=no,目標文件不存在時才下載。
例子:
# 下載ansible dev -m get_url -a "url=https://dl.fedoraproject.org/pub/epel/epel-release-latest-7.noarch.rpm dest=/tmp/ mode=0440"# 查看ansible dev -a "ls -l /tmp/"
1.5.8 yum模塊
yum模塊可提供status狀態,status狀態有:latest,present,installed(這三個表明安裝),removed,absent(這兩個表明卸載)
其選項以下:
name # 用於指定軟件包的名字,好比nginxstat # 用於指定軟件包的狀態status,其狀態如上說明。
例子:
ansible dev -m yum -a "name=nginx stat=latest"
1.5.9 cron模塊
cron模塊應用於配置遠程主機crontab。
其選項參數以下:
name # 爲crontab設置一個名字環境變量minute # 分hour # 時day # 天weekday # 周month # 月job # 執行的命令
例子:
ansible dev -m cron -a "name='list dir' minute='*/30 job='ls /tmp'"
1.5.10 service模塊
service模塊應用遠程主機系統服務的管理。想要使用這個模塊啓動服務,被啓動的服務可使用service啓動或關閉服務。
經常使用的選項參數以下:
name # 指定須要操做的服務名稱,好比nginx,httpdstat # 指定服務的狀態,started,restarted,stoped,reloadedenable # 若是設置爲yes表示開機啓動,若是是no表示開機不啓動
例子:
ansible dev -a "name=httpd stat=restarted enable=yes"
1.5.11 sysctl模塊
sysctl模塊應用在遠程主機sysctl配置。
經常使用選項參數以下:
name # 須要設置的內核參數名value # 參數值reload # 若是是yes,至關於執行了sysctl -p命令,是no表示不從新加載
例子:
# 爲系統添加路由轉發功能ansible dev -m sysctl -a "name=net.ipv4.ip_forward value=1 reload=yes"
1.5.12 user模塊
user模塊應用於遠程主機用戶管理。
例子:
# 添加用戶ansible dev -m user -a "name=joker state=present"# 刪除用戶ansible dev -m user -a "name=joker state=absent remove=yes"
1.5.13 mount模塊
mount模塊應用於被控端分區掛載。
例子:
ansible dev -m mount -a "name=/mnt/data src=/dev/sd1 fstype=nfs opts=ro state=present"
1.6 playbook
1.6.1 用法示例
---- hosts: webserver remote_user: root vars: app_package: httpd service_name: httpd tasks: - name: Install {{ app_package }} package yum: name={{ app_package }} - name: copy conf copy: src=files/httpd.conf dest=/etc/httpd/conf/ backup=yes notify: restart {{ service_name }} - name: start {{ service_name }} services service: name={{ service_name }} state=started handers: - name: restart {{ service_name }} service: name={{ service_name }} state=restarted
說明:
hosts: 主機列表remote_user: 遠程執行用戶vars: 變量定義tasks: 具體執行任務name: 任務名字notify: 若是該task改變,則會觸發notify執行handers任務handers: notify通知執行的任務
1.6.2 playbook中的變量
一、變量的定義方式
(1)、經過命令指定
ansible-playbook -e "app_package=httpd" app.yml
(2)、在playbook中定義,經過vars參數,見上面的示例
(3)、在/etc/ansible/hosts中定義
[webserver]10.1.11.11 httpd_port=8010.1.11.12[webserver:vars]httpd_post=81
(4)、內置變量,能夠經過setup模塊查看
ansible 10.1.11.12 -m setup
二、變量的優先級
直接經過命令傳入的變量的優先級最高,其次是在playbook中定義的變量,再次是在/etc/ansible/hosts中的主機清單中定義的變量(主機清單的局部變量的優先級大於它全局變量的優先級),最後是內置變量。
三、變量的統一管理
在不少時候咱們但願將變量放在一個文件裏統一管理,這時候能夠單獨定義一個yml文件存放變量,而後在主playbook中導入便可。好比
variable.yml---- app_package: httpd- app_port: 80app.yml---- hosts: webserver remote_user: root include_vars: file: variable.yml name: variable
1.6.3 template
模板的功能就是能夠建立一個模板文件,模板文件必須以.j2結尾,並且模板裏面支持變量,好比以nginx.conf爲例:
// 根據機器的CPU不一樣,配置不一樣的work_processvim templates/nginx.conf.j2....work_process {{ ansible_processor_vcpus * 2 }}....vim nginx.yml---- hosts: web remote_user: root tasks: - name: copy conf template: src=nginx.conf.j2 dest=/etc/nginx/nginx.conf
template裏還支持for,if等語法,好比:
vim test.yml---- hosts: web remote_user: root vars: ports: - web1: port: 81 server_name: web1.joker.com - web2: port: 82 server_name: web2.joker.com - web3: port: 83 tasks: - name: copy file template: src=test.j2 dest=/data/test.confvim tempates/test.j2{% for p in ports%} server { listen {{ p.port }}; {% if p.server_name if defined %} server_name p.server_name; {% endif %} }{% endfor %}
1.6.4 with_items
不少時候須要同事進行屢次操做,這時候with_items就頗有幫助,例如:
// 建立多個用戶組,並將用戶加入組---- hosts: web remote_user: root tasks: - name: create some group group: name={{ item }} with_items: - group1 - group2 - group3 - name: create some user user: name={{ item.user }} group={{ item.group }} with_items: - {user: "user1", group: "group1"} - {user: "user2", group: "group2"} - {user: "user3", group: "group3"}
1.7 roles
1.7.1 roles目錄規範
ansible_playbooks/└── roles 必須叫roles ├── dbsrvs -------------role1名稱 │ ├── defaults ---------必須存在的目錄,存放默認的變量,模板文件中的變量就是引用自這裏。defaults中的變量優先級最低,一般咱們能夠臨時指定變量來進行覆蓋 │ │ └── main.yml │ ├── files -------------ansible中unarchive、copy等模塊會自動來這裏找文件,從而咱們沒必要寫絕對路徑,只需寫文件名 │ │ ├── mysql.tar.gz │ │ └── nginx.tar.gz │ ├── handlers -----------存放tasks中的notify指定的內容 │ │ └── main.yml │ ├── meta │ ├── tasks --------------存放playbook的目錄,其中main.yml是主入口文件,在main.yml中導入其餘yml文件,要採用import_tasks關鍵字,include要棄用了 │ │ ├── install.yml │ │ └── main.yml -------主入口文件 │ ├── templates 存放模板文件。template模塊會將模板文件中的變量替換爲實際值,而後覆蓋到客戶機指定路徑上 │ │ └── nginx.conf.j2 │ └── vars └── websrvs -------------role2名稱 ├── defaults │ └── main.yml ├── files │ ├── mysql.tar.gz │ └── nginx.tar.gz ├── handlers │ └── main.yml ├── meta ├── tasks │ ├── install.yml │ └── main.yml ├── templates │ └── nginx.conf.j2 └── vars
1.7.2 簡要說明
roles的好處就是將我們之前一個Playbook乾的不少活細分化,這樣方便管理,特別是對於複雜的任務。
1.7.3 基本用法示例
// 安裝nginx// 目錄結構ansible_playbook/├── nginx_role.yml└── roles └── app ├── defaults --- 存放變量 │ └── main.yml ├── files --- 存放須要拷貝得文件 │ └── python3.tar.gz ├── handlers --- 存放handler觸發文件 │ └── main.yml ├── tasks --- 存放具體得劇本 │ ├── copyfile.yml --- 拷貝文件 │ ├── groupAdd.yml --- 添加用戶 │ ├── main.yml --- 主配置文件 │ ├── start.yml --- 啓動服務 │ ├── template.yml --- 拷貝模板 │ ├── userAdd.yml --- 添加用戶 │ └── yum.yml --- 安裝軟件 └── templates --- 存放模板文件 └── nginx.conf.j2//具體配置/*nginx_role.yml*/- hosts: web remote_user: root roles: - app/*defultes/main.yml*/username: appusergroup: appuid: 520gid: 520/*handlers/main.yml*/- name: restart nginx service: name=nginx state=reload/*tasks/copyfile.yml*/- name: copy file copy: src=python3.tar.gz dest=/data/ owner=app group=app/*tasks/groupAdd.yml*/- name: create group group: name={{ usergroup }} gid={{ gid }} system=yes/*tasks/userAdd.yml*/- name: create user user: name={{ username }} uid={{ uid }} group={{ usergroup }} system=yes shell=/sbin/nologin/*tasks/yum.yml*/- name: install package yum: name=nginx/*tasks/template.yml*/- name: copy template template: src=nginx.conf.j2 dest=/etc/nginx/nginx.conf notify: restart nginx/*tasks/start.yml*/- name: start nginx service: name=nginx state=started/*tasks/main.yml*/- include: groupAdd.yml- include: userAdd.yml- include: yum.yml- include: template.yml- include: copyfile.yml- include: start.yml
1.7.4 調用多個roles
//調用多個roles,只須要在主配置文件裏指定就能夠了,好比/*nginx_role.yml*/- hosts: web remote_user: root roles: - app - mysql - php
1.7.5 role之間相互調用
//好比以下結構.├── nginx_role.yml└── roles ├── app │ ├── defaults │ │ └── main.yml │ ├── files │ │ └── python3.tar.gz │ ├── handlers │ │ └── main.yml │ ├── tasks │ │ ├── copyfile.yml │ │ ├── groupAdd.yml │ │ ├── main.yml │ │ ├── start.yml │ │ ├── template.yml │ │ ├── userAdd.yml │ │ └── yum.yml │ └── templates │ └── nginx.conf.j2 └── mysql └── tasks └── test.yml// app要調用MySQL中的test.yml,只須要在app的tasks中的main.yml中引用就能夠了,以下:vim main.yml- include: groupAdd.yml- include: userAdd.yml- include: yum.yml- include: template.yml- include: copyfile.yml- include: start.yml- include: roles/mysql/tasks/test.yml
本文分享自微信公衆號 - 極客運維圈(qiaobiangushi)。
若有侵權,請聯繫 support@oschina.cn 刪除。
本文參與「OSC源創計劃」,歡迎正在閱讀的你也加入,一塊兒分享。