一.Ansible簡介
1.什麼是Ansible
- Ansible是一個開源部署工具
- 開發語言:Python
- 特點:SSH協議通訊,全平臺,無需編譯,模塊化部署管理
2.Ansible與Chef,Saltstack的不同
- Chef:Ruby語言編寫,C/S架構,配置需要Git依賴,Recipe腳本編寫規範需要編程經驗
- Saltstack:Python語言編寫,C/S架構,模塊化配置管理,YAML腳本編寫規範,適合大規模集羣部署
- Ansible:Python語言編寫,無Client,模塊化配置管理,Playbook腳本編寫規範,易於上手,適合中小規模快速部署
二.Ansible的優勢和應用場景
1.Ansible的優勢
- 輕量級無客戶端Agentless
- 開源免費,學習成本低,快速上手
- 使用Playbook作爲核心配置架構,統一的腳本格式批量化部署
- 完善的模塊化擴展,支持目前主流的開發場景
- 強大的穩定性和兼容性
- 活躍的官方社區問題討論,方便Trubleshooting與DEBUG問題
三.Ansible安裝配置
1.安裝配置
- Python3.7.0+Ansible2.7.1
brew install ansible
- 查看Ansible是否安裝完成
ansible --version
四.Ansible playbooks入門和編碼規範
1.Playbooks框架與格式
- TestPlaybooks
- Inventory/ 目錄下存放一個或多個Server詳細清單目錄,用來保存目標部署主機的相關域名或ip地址,及該主機的變量參數。通常我們會採用具體清單與變量聲明文件,如dev/qc/prod
- testenv意味着在testenv的主機部署到testenv環境中
- roles/ 用於保存我們要部署的詳細任務列表,下方可以存放一個或多個role,通常會命名爲具體部署的app或項目名稱
- testbox/作爲項目名稱【詳細任務】
- tasks/用於存放任務內容文件
- main.yml主任務文件
- tasks/用於存放任務內容文件
- testbox/作爲項目名稱【詳細任務】
- deploy.yml作爲Playbook任務入口文件,將調度roles下需要部署的項目,以及該項目下的所有任務,最後將該項目部署到Inventory下定義的目標主機中
- Inventory/ 目錄下存放一個或多個Server詳細清單目錄,用來保存目標部署主機的相關域名或ip地址,及該主機的變量參數。通常我們會採用具體清單與變量聲明文件,如dev/qc/prod
2.Playbooks編寫規範
-
詳細目錄testenv【testenv環境下的server清單】
[testservers] -> Server組列表 test.example.com -> 目標部署服務器主機名 [testserver:vars] -> Server組列表參數,用來定義目標主機所用到的所有key/value參數對,作爲Server的變量聲明 server_name=test.example.com user=root output=/root/test.txt
-
主任務文件main.yml【特定role下面具體執行的任務樂章,保存一個或多個task作爲音符】
-name: Print server name and user to remote testbox -> 任務名稱,表示task是做什麼的 shell: "echo 'Currently {{user}} is logining {{server_name}}' > {{output}}" -> 執行的任務,使用shell模塊(調用Ansible內嵌模塊)執行命令,其中的變量使用的是inventory/testenv文件中的變量聲明值 以上代碼的含義是執行上述的task,通過Ansible的shell模塊在目標主機下打印一句話並重定向到目標主機下對應output文件中
-
任務入口文件deploy.yml【作爲核心文件直接與Ansible Playbook命令直接對話,將Playbook下所有編排命令全部展示給Ansible進行最終的play演奏,執行到最終的主機中】
- hosts: "testservers" -> Server列表對應inventory下的文件中的server主標籤,聲明要部署的目標主機爲test.example.com的主機 gather_facts: true -> 獲取Server基本信息 remote_user: root -> 目標服務器系統用戶指定 roles: - testbox -> 進入roles/testbox任務目錄執行裏面的所有tasks
-
在使用Ansible執行命令之前,由於Ansible是使用SSH作爲通信協議,爲了保證Ansible服務器可以操作目標服務器,我們需要配置Ansible主機與目標主機的密鑰認證,保證Ansible主機與目標主機可以實現部署操作
- 在Ansible主機配置DNS記錄,將對應test.example.com域名解析到對應目標主機的ip地址。【配置hosts文件,添加DNS記錄如
106.54.32.234 test.example.com
】 - 配置SSH免密碼密鑰認證
- Ansible服務器端創建SSH本地密鑰認證對
ssh-keygen -t rsa
,一路回車創建對應的私鑰[id_rsa]和公鑰[id_rsa.pub] - Ansible服務器端建立與目標部署機器的密鑰認證(將Ansible中的密鑰傳遞到目標機器中)
ssh-copy-id -i /home/deploy/.ssh/id_rsa.pub [email protected]
,其中[email protected]
表示目標主機用戶名@目標主機域名
。執行命令後需要輸入yes確認連接,且輸入目標主機root用戶名的密碼,輸入完密碼後就可以將本地的ssh公鑰傳遞到目標主機中,從而建立了Ansible服務器端與目標主機間的密鑰認證,實現免密登錄
- Ansible服務器端創建SSH本地密鑰認證對
- 執行Playbooks
- 部署到testenv環境
ansible-playbook -i inventory/testenv ./deploy.yml
- 確認是否執行成功
- 命令執行後輸出ok個數和changed個數
- 使用
ssh [email protected]
並查看/root/test.txt
文件有對應的輸出內容
- 在Ansible主機配置DNS記錄,將對應test.example.com域名解析到對應目標主機的ip地址。【配置hosts文件,添加DNS記錄如
五.Ansible playbooks常用模塊介紹
1.File模塊
-
在目標主機創建文件或目錄,並賦予其系統權限
-
實例:使用file模塊執行Ansible Task任務
- name: create a file file: 'path=/root/foo.txt state=touch mode=0755 owner=foo group=foo'
- name定義任務名稱
- file聲明任務語句調用file模塊
- path定義文本文件在目標主機上的位置
- state定義要去創建一個文件
- mode定義要給文件0755的權限
- owner定義文件的所屬用戶
- group定義文件的所屬組
2.Copy模塊
-
實現Ansible服務端到目標主機的文件傳送
-
實例:使用copy模塊執行Ansible Task任務
- name: copy a file copy: 'remote_src=no src=roles/testbox/files/foo.sh dest=/root/foo.sh mode=0644 force=yes'
- name定義任務名稱
- copy聲明任務語句調用copy模塊
- remote_src=no表示要從Ansible主機中的文件傳遞到目標主機中
- src聲明源文件的路徑(Ansible服務器)
- dest聲明目標文件的路徑(目標服務器)
- mode聲明目標文件的權限
- force=yes定義當前的Copy任務強制執行
3.Stat模塊
-
獲取遠程文件狀態信息,並將信息保存到環境變量下供隨後使用
-
實例
- name: check if foo.sh exists stat: 'path=/root/foo.sh' register: script_stat
stat: 'path=/root/foo.sh'
表示要獲取文件狀態信息的路徑register: script_stat
將stat獲取的文件信息傳遞給script_stat變量
4.Debug模塊
-
打印語句到Ansible執行輸出
-
實例
- debug: msg="foo.sh exists" -> 定義使用debug模塊輸出的語句內容爲foo.sh exists when: script_stat.stat.exists -> when是Ansible內嵌的條件語句,script_stat.stat.exists判斷變量中的值是否存在,若存在則打印上述信息
5.Command/Shell模塊
-
用來執行Linux目標主機命令行,Shell模塊可以調用Linux系統下的/bin/bash,可以使用系統環境變量、重定向符和管道符等
-
實例
- name: run the script command: "sh /root/foo.sh" - name: run the script shell: "echo 'test' > /root/test.txt" -> 推薦使用shell模塊
6.Template模塊
-
實現Ansible服務端到目標主機的jinja2模板傳送
-
實例
- name: write the nginx config file template: src=roles/testbox/templates/nginx.conf.j2 dest=/etc/nginx/nginx.conf -> src指定模板文件,dest指定目標文件路徑,其中傳遞過程中會替換對應的變量信息
7.Packaging模塊
-
調用目標主機系統包管理工具(yum,apt)進行安裝,常用這個模塊去安裝對應發行版下的app安裝包
-
實例
- name: ensure nginx is at the latest version yum: pkg=nginx state=latest -> 使用yum安裝,安裝包是nginx包,版本是最新[此方式適用於CentOS/Rethat系統] - name: ensure nginx is at the latest version apt: pkg=nginx state=latest -> 使用apt安裝,安裝包是nginx包,版本是最新[此方式適用於Debian/Ubuntu系統]
8.Service模塊
-
管理目標主機系統服務
-
實例
- name: start nginx service service: name=nginx state=started -> 啓動nginx服務
六.Ansible playbooks常用模塊案例操作
1.案例操作
-
到目標服務器上執行如下命令進行預配置工作
useradd foo useradd deploy #添加兩個系統用戶 mkdir /etc/nginx #創建目錄 rpm -Uvh http://nginx.org/packages/centos/7/noarch/RPMS/nginx-release-centos-7-0.el7.ngx.noarch.rpm #給yum源添加nginx安裝包
-
修改roles/testbox/tasks/main.yml
- name: create a file file: 'path=/root/foo.txt state=touch mode=0755 owner=foo group=foo'
-
執行ansible-playbook執行上述任務創建foo文件
ansible-playbook -i inventory/testenv ./deploy.yml
-
在role/testbox下添加test目錄,並創建foo.sh文件添加文件內容
mkdir roles/testbox/files vi roles/testbox/files/foo.sh # 添加文件內容如下 # echo "This is a test script"
-
在main.yml中添加新的Copy任務
- name: Create a file file: 'path=/root/foo.txt state=touch mode=0755 owner=foo group=foo' - name: Copy a file copy: 'remote_src=no src=roles/testbox/files/foo.sh dest=/root/foo.sh mode=0644 force=yes'
-
執行ansible-playbook執行上述任務拷貝文件
ansible-playbook -i inventory/testenv ./deploy.yml
-
在main.yml中添加獲取文件狀態和判斷文件是否存在並打印輸出信息任務
- name: Create a file file: 'path=/root/foo.txt state=touch mode=0755 owner=foo group=foo' - name: Copy a file copy: 'remote_src=no src=roles/testbox/files/foo.sh dest=/root/foo.sh mode=0644 force=yes' - name: Check if foo.sh exists stat: 'path=/root/foo.sh' register: script_stat - debug: msg="foo.sh exists" when: script_stat.stat.exists
-
執行ansible-playbook執行上述任務進行文件是否存在的判斷
ansible-playbook -i inventory/testenv ./deploy.yml
-
在main.yml中添加執行腳本文件的任務
- name: Create a file file: 'path=/root/foo.txt state=touch mode=0755 owner=foo group=foo' - name: Copy a file copy: 'remote_src=no src=roles/testbox/files/foo.sh dest=/root/foo.sh mode=0644 force=yes' - name: Check if foo.sh exists stat: 'path=/root/foo.sh' register: script_stat - debug: msg="foo.sh exists" when: script_stat.stat.exists - name: Run the script command: "sh /root/foo.sh"
-
執行ansible-playbook運行上述任務執行shell腳本
ansible-playbook -i inventory/testenv ./deploy.yml
-
添加變量參數到testenv中
[testservers] test.example.com [testservers:vars] server_name=test.example.com user=root output=/root/test.txt port=80 user=deploy worker_processes=4 max_open_file=65505 root=/www
-
在roles/testbox下創建templates目錄
mkdir roles/testbox/templates
-
在templates文件創建nginx.conf.j2模板文件,使用nginx.conf文件並修改對應字段爲
{{變量}}
# For more information on configuration, see: user {{ user }}; worker_processes {{ worker_processes }}; error_log /var/log/nginx/error.log; pid /var/run/nginx.pid; events { worker_connections {{ max_open_file }}; } http { include /etc/nginx/mime.types; default_type application/octet-stream; log_format main '$remote_addr - $remote_user [$time_local] "$request" ' '$status $body_bytes_sent "$http_referer" ' '"$http_user_agent" "$http_x_forwarded_for"'; access_log /var/log/nginx/access.log main; sendfile on; #tcp_nopush on; #keepalive_timeout 0; keepalive_timeout 65; #gzip on; # Load config files from the /etc/nginx/conf.d directory # The default server is in conf.d/default.conf #include /etc/nginx/conf.d/*.conf; server { listen {{ port }} default_server; server_name {{ server_name }}; #charset koi8-r; #access_log logs/host.access.log main; location / { root {{ root }}; index index.html index.htm; } error_page 404 /404.html; location = /404.html { root /usr/share/nginx/html; } # redirect server error pages to the static page /50x.html # error_page 500 502 503 504 /50x.html; location = /50x.html { root /usr/share/nginx/html; } } }
-
在main.yml中添加傳送替換後的nginx.conf文件模板任務、yum安裝nginx任務和啓動遠程nginx服務任務
- name: Create a file file: 'path=/root/foo.txt state=touch mode=0755 owner=foo group=foo' - name: Copy a file copy: 'remote_src=no src=roles/testbox/files/foo.sh dest=/root/foo.sh mode=0644 force=yes' - name: Check if foo.sh exists stat: 'path=/root/foo.sh' register: script_stat - debug: msg="foo.sh exists" when: script_stat.stat.exists - name: Run the script command: "sh /root/foo.sh" - name: Write the nginx config file template: src=roles/testbox/templates/nginx.conf.j2 dest=/etc/nginx/nginx.conf - name: Ensure nginx is at the latest version yum: pkg=nginx state=latest - name: Start nginx service service: name=nginx state=started
-
執行ansible-playbook運行上述模塊任務
ansible-playbook -i inventory/testenv ./deploy.yml
-
進入目標主機查看nginx.conf文件是否成功替換模板,且通過
ps -ef | grep nginx
命令查看是否啓動nginx服務