運維自動化之Ansible 和 HTTP協議和APACHE

雲計算運維工程師核心職能

Linux運維工程師職能劃分

企業實際應用場景分析

Dev開發環境
使用者:程序員
功能:程序員開發軟件,測試BUG的環境
管理者:程序員
測試環境
使用者:QA測試工程師
功能:測試通過Dev環境測試經過的軟件的功能
管理者:運維
說明:測試環境每每有多套,測試環境知足測試功能便可,不宜過多
一、測試人員但願測試環境有多套,公司的產品多產品線併發,即多個版本,意味着多個版本同步測試
二、一般測試環境有多少套和產品線數量保持同樣javascript

發佈環境:代碼發佈機,有些公司爲堡壘機(安全屏障)
使用者:運維
功能:發佈代碼至生產環境
管理者:運維(有經驗)
發佈機:每每須要有2臺(主備)
生產環境
使用者:運維,少數狀況開放權限給核心開發人員,極少數公司將權限徹底開放給開發人員並其維護
功能:對用戶提供公司產品的服務
管理者:只能是運維
生產環境服務器數量:通常比較多,且應用很是重要。每每須要自動工具協助部署配置應用php

灰度環境(生產環境的一部分)
使用者:運維
功能:在全量發佈代碼前將代碼的功能面向少許精準用戶發佈的環境,可基於主機或用戶執行灰度發佈
案例:共100臺生產服務器,先發布其中的10臺服務器,這10臺服務器就是灰度服務器
管理者:運維
灰度環境:每每該版本功能變動較大,爲保險起見特地先讓一部分用戶優化體驗該功能,待這部分用戶使用沒有重大問題的時候,再全量發佈至全部服務器css

程序發佈html

程序發佈要求:
不能致使系統故障或形成系統徹底不可用
不能影響用戶體驗
預發佈驗證:
新版本的代碼先發布到服務器(跟線上環境配置徹底相同,只是未接入到調度器)
灰度發佈:
基於主機,用戶,業務
發佈路徑:
/webapp/tuangou
/webapp/tuangou-1.1
/webapp/tuangou-1.2
發佈過程:在調度器上下線一批主機(標記爲maintanance狀態) --> 關閉服務 --> 部署新版本的應用程序 --> 啓動服務 --> 在調度器上啓用這一批服務器
自動化灰度發佈:腳本、發佈平臺java

特性

模塊化:調用特定的模塊,完成特定任務
有Paramiko,PyYAML,Jinja2(模板語言)三個關鍵模塊
支持自定義模塊
基於Python語言實現
部署簡單,基於python和SSH(默認已安裝),agentless
安全,基於OpenSSH
支持playbook編排任務
冪等性:一個任務執行1遍和執行n遍效果同樣,不因重複執行帶來意外狀況
無需代理不依賴PKI(無需ssl)
可以使用任何編程語言寫模塊
YAML格式,編排任務,支持豐富的數據結構
較強大的多層解決方案node

ansible架構

Ansible工做原理

Ansible主要組成部分

ANSIBLE PLAYBOOKS:任務劇本(任務集),編排定義Ansible任務集的配置文件,由Ansible順序依次執行,一般是JSON格式的YML文件
INVENTORY:Ansible管理主機的清單/etc/anaible/hosts
MODULES:Ansible執行命令的功能模塊,多數爲內置核心模塊,也可自定義
PLUGINS:模塊功能的補充,如鏈接類型插件、循環插件、變量插件、過濾插件等,該功能不經常使用
API:供第三方程序調用的應用程序編程接口
ANSIBLE:組合INVENTORY、API、MODULES、PLUGINS的綠框,能夠理解爲是ansible命令工具,其爲核心執行工具python

Ansible命令執行來源:
USER,普通用戶,即SYSTEM ADMINISTRATOR
CMDB(配置管理數據庫) API 調用
PUBLIC/PRIVATE CLOUD API調用
USER-> Ansible Playbook -> Ansibile
利用ansible實現管理的方式:
Ad-Hoc 即ansible命令,主要用於臨時命令使用場景
Ansible-playbook 主要用於長期規劃好的,大型項目的場景,須要有前期的規劃過程mysql

Ansible-playbook(劇本)執行過程
將已有編排好的任務集寫入Ansible-Playbook
經過ansible-playbook命令分拆任務集至逐條ansible命令,按預約規則逐條執行
Ansible主要操做對象
HOSTS主機
NETWORKING網絡設備
注意事項
執行ansible的主機通常稱爲主控端,中控,master或堡壘機
主控端Python版本須要2.6或以上
被控端Python版本小於2.4須要安裝python-simplejson
被控端如開啓SELinux須要安裝libselinux-python
windows不能作爲主控端linux

安裝

rpm包安裝: EPEL源
yum install ansible
編譯安裝:
yum -y install python-jinja2 PyYAML python-paramiko python-babel python-crypto
tar xf ansible-1.5.4.tar.gz
cd ansible-1.5.4
python setup.py build
python setup.py install
mkdir /etc/ansible
cp -r examples/* /etc/ansiblenginx

Git方式:
git clone git://github.com/ansible/ansible.git --recursive
cd ./ansible
source ./hacking/env-setup
pip安裝: pip是安裝Python包的管理器,相似yum
yum install python-pip python-devel
yum install gcc glibc-devel zibl-devel rpm-bulid openssl-devel
pip install --upgrade pip
pip install ansible --upgrade
確認安裝:
ansible --version

相關文件

配置文件
/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界面與用戶交互的執行工具

主機清單inventory

Inventory 主機清單
ansible的主要功用在於批量主機操做,爲了便捷地使用其中的部分主機,能夠在inventory file中將其分組命名
默認的inventory file爲/etc/ansible/hosts
inventory file能夠有多個,且也能夠經過Dynamic Inventory來動態生成

/etc/ansible/hosts文件格式
inventory文件遵循INI文件風格,中括號中的字符爲組名。能夠將同一個主機同時歸併到多個不一樣的組中;此外,當如若目標主機使用了非默認的SSH端口,還能夠在主機名稱以後使用冒號加端口號來標明
ntp.magedu.com
[webservers]
www1.magedu.com:2222
www2.magedu.com
[dbservers]
db1.magedu.com
db2.magedu.com
db3.magedu.com

若是主機名稱遵循類似的命名模式,還可使用列表的方式標識各主機
示例:
[websrvs]
www[1:100].example.com
[dbsrvs]
db-[a:f].example.com

ansible 配置文件

Ansible 配置文件/etc/ansible/ansible.cfg (通常保持默認)
[defaults]
#inventory = /etc/ansible/hosts # 主機列表配置文件
#library = /usr/share/my_modules/ # 庫文件存放目錄
#remote_tmp = $HOME/.ansible/tmp #臨時py命令文件存放在遠程主機目錄
#local_tmp = $HOME/.ansible/tmp # 本機的臨時命令執行目錄
#forks = 5 # 默認併發數
#sudo_user = root # 默認sudo 用戶
#ask_sudo_pass = True #每次執行ansible命令是否詢問ssh密碼
#ask_pass = True
#remote_port = 22
#host_key_checking = False # 檢查對應服務器的host_key,建議取消註釋
#log_path=/var/log/ansible.log #日誌文件
#module_name = command #默認模塊

ansible系列命令

Ansible系列命令
ansible ansible-doc ansible-playbook ansible-vault ansible-console
ansible-galaxy ansible-pull
ansible-doc: 顯示模塊幫助
ansible-doc [options] [module...]
-a 顯示全部模塊的文檔
-l, --list 列出可用模塊
-s, --snippet顯示指定模塊的playbook片斷
示例:
ansible-doc -l 列出全部模塊
ansible-doc ping 查看指定模塊幫助用法
ansible-doc -s ping 查看指定模塊幫助用法

ansible

ansible經過ssh實現配置管理、應用部署、任務執行等功能,建議配置ansible端能基於密鑰認證的方式聯繫各被管理節點
ansible <host-pattern> [-m module_name] [-a args]
--version 顯示版本
-m module 指定模塊,默認爲command
-v 詳細過程 –vv -vvv更詳細
--list-hosts 顯示主機列表,可簡寫 --list
-k, --ask-pass 提示輸入ssh鏈接密碼,默認Key驗證
-C, --check 檢查,並不執行
-T, --timeout=TIMEOUT 執行命令的超時時間,默認10s
-u, --user=REMOTE_USER 執行遠程執行的用戶
-b, --become 代替舊版的sudo 切換
--become-user=USERNAME 指定sudo的runas用戶,默認爲root
-K, --ask-become-pass 提示輸入sudo時的口令

ansible的Host-pattern

ansible的Host-pattern
匹配主機的列表
All :表示全部Inventory中的全部主機
ansible all –m ping
* :通配符
ansible 「*」 -m ping
ansible 192.168.1.* -m ping
ansible 「*srvs」 -m ping
或關係
ansible 「websrvs:appsrvs」 -m ping
ansible 「192.168.1.10:192.168.1.20」 -m ping

邏輯與
ansible 「websrvs:&dbsrvs」 –m ping
在websrvs組而且在dbsrvs組中的主機
邏輯非
ansible ‘websrvs:!dbsrvs’ –m ping
在websrvs組,但不在dbsrvs組中的主機
注意:此處爲單引號
綜合邏輯
ansible ‘websrvs:dbsrvs:&appsrvs:!ftpsrvs’ –m ping
正則表達式
ansible 「websrvs:&dbsrvs」 –m ping
ansible 「~(web|db).*\.magedu\.com」 –m ping

ansible命令執行過程

ansible命令執行過程
1. 加載本身的配置文件 默認/etc/ansible/ansible.cfg
2. 加載本身對應的模塊文件,如command
3. 經過ansible將模塊或命令生成對應的臨時py文件,並將該文件傳輸至遠程服務器的對應執行用戶$HOME/.ansible/tmp/ansible-tmp-數字/XXX.PY文件
4. 給文件+x執行
5. 執行並返回結果
6. 刪除臨時py文件,退出
執行狀態:
綠色:執行成功而且不須要作改變的操做
黃色:執行成功而且對目標主機作變動
紅色:執行失敗

ansible使用示例

示例
以wang用戶執行ping存活檢測
ansible all -m ping -u wang -k
以wang sudo至root執行ping存活檢測
ansible all -m ping -u wang -k -b
以wang sudo至mage用戶執行ping存活檢測
ansible all -m ping -u wang -k -b --become-user=mage
以wang sudo至root用戶執行ls
ansible all -m command -u wang -a 'ls /root' -b --become-user=root
-k -K

ansible經常使用模塊

Command:在遠程主機執行命令,默認模塊,可忽略-m選項
ansible srvs -m command -a ‘service vsftpd start’
ansible srvs -m command -a ‘echo magedu |passwd --stdin wang’
此命令不支持 $VARNAME < > | ; & 等,用shell模塊實現
Shell:和command類似,用shell執行命令
ansible srv -m shell -a ‘echo magedu |passwd –stdin wang’
調用bash執行命令 相似 cat /tmp/stanley.md | awk -F‘|’ ‘{print $1,$2}’ &> /tmp/example.txt 這些複雜命令,即便使用shell也可能會失敗,解決辦法:寫到腳本時,copy到遠程,執行,再把須要的結果拉回執行命令的機器
Script:在遠程主機上運行ansible服務器上的腳本
-a "/PATH/TO/SCRIPT_FILE「
ansible websrvs -m script -a /data/f1.sh

Copy:從主控端複製文件到遠程主機
ansible srv -m copy -a 「src=/root/f1.sh dest=/tmp/f2.sh owner=wang mode=600 backup=yes」
如目標存在,默認覆蓋,此處指定先備份
ansible srv -m copy -a 「content=‘test content\n’ dest=/tmp/f1.txt」 指定內容,直接生成目標文件
Fetch:從遠程主機提取文件至主控端,copy相反,目前不支持目錄
ansible srv -m fetch -a ‘src=/root/a.sh dest=/data/scripts’
File:設置文件屬性
ansible srv -m file -a "path=/root/a.sh owner=wang mode=755「
ansible web -m file -a ‘src=/app/testfile dest=/app/testfile-link state=link’

unarchive:解包解壓縮,有兩種用法:
一、將ansible主機上的壓縮包在本地解壓縮後傳到遠程主機上,設置copy=yes.
二、將遠程主機上的某個壓縮包解壓縮到指定路徑下,設置copy=no
常見參數:
copy:默認爲yes,當copy=yes,拷貝的文件是從ansible主機複製到遠程主機上,若是設置爲copy=no,會在遠程主機上尋找src源文件
src:源路徑,能夠是ansible主機上的路徑,也能夠是遠程主機上的路徑,若是是遠程主機上的路徑,則須要設置copy=no
dest:遠程主機上的目標路徑
mode:設置解壓縮後的文件權限
示例:
ansible srv -m unarchive -a 'src=foo.tgz dest=/var/lib/foo'
ansible srv -m unarchive -a 'src=/tmp/foo.zip dest=/data copy=no mode=0777'
ansible srv -m unarchive -a 'src=https://example.com/example.zip dest=/data copy=no'

Archive:打包壓縮
ansible all -m archive -a 'path=/etc/sysconfig dest=/data/sysconfig.tar.bz2 format=bz2 owner=wang mode=0777'
Hostname:管理主機名
ansible node1 -m hostname -a 「name=websrv」
Cron:計劃任務
支持時間:minute,hour,day,month,weekday
ansible srv -m cron -a 「minute=*/5 job=‘/usr/sbin/ntpdate 172.16.0.1 &>/dev/null’ name=Synctime」 建立任務
ansible srv -m cron -a ‘state=absent name=Synctime’ 刪除任務
Yum:管理包
ansible srv -m yum -a ‘name=httpd state=present’ 安裝
ansible srv -m yum -a ‘name=httpd state=absent’ 刪除

Service:管理服務
ansible srv -m service -a 'name=httpd state=stopped'
ansible srv -m service -a 'name=httpd state=started enabled=yes'
ansible srv -m service -a 'name=httpd state=reloaded’
ansible srv -m service -a 'name=httpd state=restarted'
User:管理用戶
ansible srv -m user -a 'name=user1 comment=「test user」 uid=2048 home=/app/user1 group=root‘
ansible srv -m user -a 'name=sysuser1 system=yes home=/app/sysuser1 ’
ansible srv -m user -a ‘name=user1 state=absent remove=yes‘
刪除用戶及家目錄等數據
Group:管理組
ansible srv -m group -a "name=testgroup system=yes「
ansible srv -m group -a "name=testgroup state=absent"

ansible-galaxy
鏈接 https://galaxy.ansible.com 下載相應的roles
列出全部已安裝的galaxy
ansible-galaxy list
安裝galaxy
ansible-galaxy install geerlingguy.redis
刪除galaxy
ansible-galaxy remove geerlingguy.redis

ansible-pull
推送命令至遠程,效率無限提高,對運維要求較高
ansible-playbook
執行playbook
示例:ansible-playbook hello.yml
cat hello.yml
#hello world yml file
- hosts: websrvs
remote_user: root
tasks:
- name: hello world
command: /usr/bin/wall hello world

ansible-vault
功能:管理加密解密yml文件
ansible-vault [create|decrypt|edit|encrypt|rekey|view]
ansible-vault encrypt hello.yml 加密
ansible-vault decrypt hello.yml 解密
ansible-vault view hello.yml 查看
ansible-vault edit hello.yml 編輯加密文件
ansible-vault rekey hello.yml 修改口令
ansible-vault create new.yml 建立新文件

Ansible-console:2.0+新增,可交互執行命令,支持tab
root@test (2)[f:10] $
執行用戶@當前操做的主機組 (當前組的主機數量)[f:併發數]$
設置併發數: forks n 例如: forks 10
切換組: cd 主機組 例如: cd web
列出當前組主機列表: list
列出全部的內置命令: ?或help
示例:
root@all (2)[f:5]$ list
root@all (2)[f:5]$ cd appsrvs
root@appsrvs (2)[f:5]$ list
root@appsrvs (2)[f:5]$ yum name=httpd state=present
root@appsrvs (2)[f:5]$ service name=httpd state=started

playbook

playbook是由一個或多個「play」組成的列表
play的主要功能在於將預約義的一組主機,裝扮成事先經過ansible中的task定義好的角色。Task實際是調用ansible的一個module,將多個play組織在一個playbook中,便可以讓它們聯合起來,按事先編排的機制執行預約義的動做
Playbook採用YAML語言編寫

 YAML介紹

YAML是一個可讀性高的用來表達資料序列的格式。YAML參考了其餘多種語言,包括:XML、C語言、Python、Perl以及電子郵件格式RFC2822等。Clark Evans在2001年在首次發表了這種語言,另外Ingy döt Net與Oren Ben-Kiki也是這語言的共同設計者
YAML Ain't Markup Language,即YAML不是XML。不過,在開發的這種語言時,YAML的意思實際上是:"Yet Another Markup Language"(還是一種標記語言)
特性
YAML的可讀性好
YAML和腳本語言的交互性好
YAML使用實現語言的數據類型
YAML有一個一致的信息模型
YAML易於實現
YAML能夠基於流來處理
YAML表達能力強,擴展性好
更多的內容及規範參見:http://www.yaml.org

YAML語法簡介

在單一檔案中,可用連續三個連字號(——)區分多個檔案。另外,還有選擇性的連續三個點號( ... )用來表示檔案結尾
次行開始正常寫Playbook的內容,通常建議寫明該Playbook的功能
使用#號註釋代碼
縮進必須是統一的,不能空格和tab混用
縮進的級別也必須是一致的,一樣的縮進表明一樣的級別,程序判別配置的級別是經過縮進結合換行來實現的
YAML文件內容是區別大小寫的,k/v的值均需大小寫敏感
多個k/v可同行寫也可換行寫,同行使用,分隔
v但是個字符串,也但是另外一個列表
一個完整的代碼塊功能需最少元素需包括 name 和 task
一個name只能包括一個task
YAML文件擴展名一般爲yml或yaml

List:列表,其全部元素均使用「-」打頭
示例:
# A list of tasty fruits
- Apple
- Orange
- Strawberry
- Mango

Dictionary:字典,一般由多個key與value構成
示例:
---
# An employee record
name: Example Developer
job: Developer
skill: Elite
也能夠將key:value放置於{}中進行表示,用,分隔多個key:value
示例:
---
# An employee record
{name: Example Developer, job: Developer, skill: Elite}

YAML的語法和其餘高階語言相似,而且能夠簡單表達清單、散列表、標量等數據結構。其結構(Structure)經過空格來展現,序列(Sequence)裏的項用"-"來表明,Map裏的鍵值對用":"分隔
示例
name: John Smith
age: 41
gender: Male
spouse:
name: Jane Smith
age: 37
gender: Female
children:
- name: Jimmy Smith
age: 17
gender: Male
- name: Jenny Smith
age 13
gender: Female

Playbook核心元素

Hosts 執行的遠程主機列表
Tasks 任務集
Varniables 內置變量或自定義變量在playbook中調用
Templates 模板,可替換模板文件中的變量並實現一些簡單邏輯的文件
Handlers 和 notity 結合使用,由特定條件觸發的操做,知足條件方纔執行,不然不執行
tags 標籤 指定某條任務執行,用於選擇運行playbook中的部分代碼。ansible具備冪等性,所以會自動跳過沒有變化的部分,即使如此,有些代碼爲測試其確實沒有發生變化的時間依然會很是地長。此時,若是確信其沒有變化,就能夠經過tags跳過此些代碼片段
ansible-playbook –t tagsname useradd.yml

playbook基礎組件

Hosts:
playbook中的每個play的目的都是爲了讓特定主機以某個指定的用戶身份執行任務。hosts用於指定要執行指定任務的主機,須事先定義在主機清單中
能夠是以下形式:
one.example.com
one.example.com:two.example.com
192.168.1.50
192.168.1.*
Websrvs:dbsrvs 或者,兩個組的並集
Websrvs:&dbsrvs 與,兩個組的交集
webservers:!phoenix 在websrvs組,但不在dbsrvs組
示例: - hosts: websrvs:dbsrvs

remote_user: 可用於Host和task中。也能夠經過指定其經過sudo的方式在遠程主機上執行任務,其可用於play全局或某任務;此外,甚至能夠在sudo時使用sudo_user指定sudo時切換的用戶
- hosts: websrvs
remote_user: root
tasks:
- name: test connection
ping:
remote_user: magedu
sudo: yes 默認sudo爲root
sudo_user:wang sudo爲wang

task列表和action
play的主體部分是task list,task list中的各任務按次序逐個在hosts中指定的全部主機上執行,即在全部主機上完成第一個任務後,再開始第二個任務
task的目的是使用指定的參數執行模塊,而在模塊參數中可使用變量。模塊執行是冪等的,這意味着屢次執行是安全的,由於其結果均一致
每一個task都應該有其name,用於playbook的執行結果輸出,建議其內容能清晰地描述任務執行步驟。若是未提供name,則action的結果將用於輸出

tasks:任務列表
兩種格式:
(1) action: module arguments
(2) module: arguments 建議使用
注意:shell和command模塊後面跟命令,而非key=value
某任務的狀態在運行後爲changed時,可經過「notify」通知給相應的handlers
任務能夠經過"tags「打標籤,可在ansible-playbook命令上使用-t指定進行調用
示例:
tasks:
- name: disable selinux
command: /sbin/setenforce 0

若是命令或腳本的退出碼不爲零,可使用以下方式替代
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 列出運行任務的主機
--list-tags 列出tag
--list-tasks 列出task
--limit 主機列表 只針對主機列表中的主機執行
-v -vv -vvv 顯示過程
示例
ansible-playbook file.yml --check 只檢測
ansible-playbook file.yml
ansible-playbook file.yml --limit websrvs

Playbook VS ShellScripts

SHELL腳本
#!/bin/bash
# 安裝Apache
yum install --quiet -y httpd
# 複製配置文件
cp /tmp/httpd.conf /etc/httpd/conf/httpd.conf
cp/tmp/vhosts.conf /etc/httpd/conf.d/
# 啓動Apache,並設置開機啓動
service httpd start
chkconfig httpd on
Playbook定義
---
- hosts: all
remote_user: root
tasks:
- name: "安裝Apache"
yum: name=httpd
- name: "複製配置文件"
copy: src=/tmp/httpd.conf dest=/etc/httpd/conf/
- name: "複製配置文件"
copy: src=/tmp/vhosts.conf dest=/etc/httpd/conf.cd/
- name: "啓動Apache,並設置開機啓動"
service: name=httpd state=started enabled=yes

示例

示例:sysuser.yml
---
- hosts: all
remote_user: root
tasks:
- name: create mysql user
user: name=mysql system=yes uid=36
- name: create a group
group: name=httpd system=yes

Playbook示例

示例:httpd.yml
- hosts: websrvs remote_user: root
tasks: - name: Install httpd yum: name=httpd state=present - name: Install configure file copy: src=files/httpd.conf dest=/etc/httpd/conf/
- name: start service
service: name=httpd state=started enabled=yes

handlers和notify結合使用觸發條件

Handlers
是task列表,這些task與前述的task並無本質上的不一樣,用於當關注的資源發生變化時,纔會採起必定的操做
Notify此action可用於在每一個play的最後被觸發,這樣可避免屢次有改變發生時每次都執行指定的操做,僅在全部的變化發生完成後一次性地執行指定操做。在notify中列出的操做稱爲handler,也即notify中調用handler中定義的操做

Playbook中handlers使用

hosts: websrvs remote_user: root tasks: - name: Install httpd yum: name=httpd state=present - name: Install configure file copy: src=files/httpd.conf dest=/etc/httpd/conf/ notify: restart httpd
- name: ensure apache is running
service: name=httpd state=started enabled=yes
handlers:
- name: restart httpd
service: name=httpd state=restarted

- hosts: websrvs
remote_user: root
tasks:
- name: add group nginx
tags: user
user: name=nginx state=present
- name: add user nginx
user: name=nginx state=present group=nginx
- name: Install Nginx
yum: name=nginx state=present
- name: config
copy: src=/root/config.txt dest=/etc/nginx/nginx.conf
notify:
- Restart Nginx
- Check Nginx Process
handlers:
- name: Restart Nginx
service: name=nginx state=restarted enabled=yes
- name: Check Nginx process
shell: killall -0 nginx > /tmp/nginx.log

Playbook中tags使用

示例:httpd.yml
- hosts: websrvs remote_user: root tasks: - name: Install httpd yum: name=httpd state=present - name: Install configure file copy: src=files/httpd.conf dest=/etc/httpd/conf/ tags: conf - name: start httpd service tags: service service: name=httpd state=started enabled=yes
ansible-playbook –t conf httpd.yml

Playbook中變量使用

變量名:僅能由字母、數字和下劃線組成,且只能以字母開頭
變量來源:
1 ansible setup facts 遠程主機的全部變量均可直接調用
2 在/etc/ansible/hosts中定義
普通變量:主機組中主機單獨定義,優先級高於公共變量
公共(組)變量:針對主機組中全部主機定義統一變量
3 經過命令行指定變量,優先級最高
ansible-playbook –e varname=value
4 在playbook中定義
vars:
- var1: value1
- var2: value2
5 在獨立的變量YAML文件中定義
6 在role中定義

變量命名
變量名僅能由字母、數字和下劃線組成,且只能以字母開頭
變量定義:key=value
示例:http_port=80
變量調用方式:
經過{{ variable_name }} 調用變量,且變量名先後必須有空格,有時用「{{ variable_name }}」才生效
ansible-playbook –e 選項指定
ansible-playbook test.yml -e "hosts=www user=magedu"

示例:使用setup變量

示例:var.yml
- hosts: websrvs
remote_user: root
tasks:
- name: create log file
file: name=/var/log/ {{ ansible_fqdn }} state=touch
ansible-playbook var.yml

示例:變量

示例:var.yml
- hosts: websrvs
remote_user: root
tasks:
- name: install package
yum: name={{ pkname }} state=present
ansible-playbook –e pkname=httpd var.yml

示例:var.yml
- hosts: websrvs
remote_user: root
vars:
- username: user1
- groupname: group1
tasks:
- name: create group
group: name={{ groupname }} state=present
- name: create user
user: name={{ username }} state=present
ansible-playbook var.yml
ansible-playbook -e "username=user2 groupname=group2」 var2.yml

變量

主機變量
能夠在inventory中定義主機時爲其添加主機變量以便於在playbook中使用
示例:
[websrvs]
www1.magedu.com http_port=80 maxRequestsPerChild=808
www2.magedu.com http_port=8080 maxRequestsPerChild=909

組變量
組變量是指賦予給指定組內全部主機上的在playbook中可用的變量
示例:
[websrvs]
www1.magedu.com
www2.magedu.com
[websrvs:vars]
ntp_server=ntp.magedu.com
nfs_server=nfs.magedu.com

示例:變量

普通變量
[websrvs] 192.168.99.101 http_port=8080 hname=www1 192.168.99.102 http_port=80 hname=www2
公共(組)變量
[websvrs:vars] http_port=808
mark=「_」 [websrvs] 192.168.99.101 http_port=8080 hname=www1 192.168.99.102 http_port=80 hname=www2
ansible websvrs –m hostname –a ‘name={{ hname }}{{ mark }}{{ http_port }}’
命令行指定變量:
ansible websvrs –e http_port=8000 –m hostname –a
‘name={{ hname }}{{ mark }}{{ http_port }}’

使用變量文件

cat vars.yml
var1: httpd
var2: nginx
cat var.yml
- hosts: web
remote_user: root
vars_files:
- vars.yml
tasks:
- name: create httpd log
file: name=/app/{{ var1 }}.log state=touch
- name: create nginx log
file: name=/app/{{ var2 }}.log state=touch

模板template

文本文件,嵌套有腳本(使用模板編程語言編寫)
Jinja2語言,使用字面量,有下面形式
字符串:使用單引號或雙引號
數字:整數,浮點數
列表:[item1, item2, ...]
元組:(item1, item2, ...)
字典:{key1:value1, key2:value2, ...}
布爾型:true/false
算術運算:+, -, *, /, //, %, **
比較操做:==, !=, >, >=, <, <=
邏輯運算:and,or,not
流表達式:For,If,When

template

template功能:根據模塊文件動態生成對應的配置文件
template文件必須存放於templates目錄下,且命名爲 .j2 結尾
yaml/yml 文件需和templates目錄平級,目錄結構以下:
./
├── temnginx.yml
└── templates
└── nginx.conf.j2

template示例

示例:利用template 同步nginx配置文件
準備templates/nginx.conf.j2文件
vim temnginx.yml
- hosts: websrvs
remote_user: root
tasks:
- name: template config to remote hosts
template: src=nginx.conf.j2 dest=/etc/nginx/nginx.conf
ansible-playbook temnginx.yml

 

TCP/IP協議

跨網絡的主機間通信

在創建通訊鏈接的每一端,進程間的傳輸要有兩個標誌:
 IP地址和端口號,合稱爲套接字地址 socket address
 客戶機套接字地址定義了一個惟一的客戶進程
 服務器套接字地址定義了一個惟一的服務器進程

Socket套接字

Socket:套接字,進程間通訊IPC的一種實現,容許位於不一樣主機(或同一主機)上不一樣進程之間進行通訊和數據交換,SocketAPI出現於1983年,4.2 BSD實現
Socket API:封裝了內核中所提供的socket通訊相關的系統調用
Socket Domain:根據其所使用的地址
AF_INET:Address Family,IPv4
AF_INET6:IPv6
AF_UNIX:同一主機上不一樣進程之間通訊時使用
Socket Type:根據使用的傳輸層協議
SOCK_STREAM:流,tcp套接字,可靠地傳遞、面向鏈接
SOCK_DGRAM:數據報,udp套接字,不可靠地傳遞、無鏈接
SOCK_RAW: 裸套接字,無須tcp或udp,APP直接經過IP包通訊

客戶/服務器程序的套接字函數

客戶/服務器程序的套接字函數

系統調用

套接字相關的系統調用:
socket(): 建立一個套接字
bind(): 綁定IP和端口
listen(): 監聽
accept(): 接收請求
connect(): 請求鏈接創建
write(): 發送
read(): 接收
close(): 關閉鏈接

Socket通訊示例:服務器端tcpserver.py

import socket
HOST='127.0.0.1'
PORT=9527
BUFFER=4096
sock=socket.socket(socket.AF_INET,socket.SOCK_STREAM)
sock.bind((HOST,PORT))
sock.listen(3)
print('tcpServer listen at: %s:%s\n\r' %(HOST,PORT))
while True:
client_sock,client_addr=sock.accept()
print('%s:%s connect' %client_addr)
while True:
recv=client_sock.recv(BUFFER)
if not recv:
client_sock.close()
break
print('[Client %s:%s said]:%s' %(client_addr[0],client_addr[1],recv))
client_sock.send(‘I am tcpServer and has received your message')
sock.close()

Socket通訊示例:服務器端tcpclient.py

import socket
HOST='127.0.0.1'
PORT=9527
BUFFER=4096
sock=socket.socket(socket.AF_INET,socket.SOCK_STREAM)
sock.connect((HOST,PORT))
sock.send(‘hello, tcpServer!,I am TcpClient')
recv=sock.recv(BUFFER)
print('[tcpServer said]: %s' % recv)
sock.close()

HTTP服務通訊過程

HTTP相關術語

http: Hyper Text Transfer Protocol, 80/tcp
html: Hyper Text Markup Language 超文本標記語言,編程語言
示例:
<html>
<head>
<title>html語言</title>
</head>
<body>
<img src="http://www.magedu.com/wp-content/uploads/2017/09/logo.png" >
<h1>你好</h1>
<p><a href=http://www.magedu.com>馬哥教育</a>歡迎你</p>
</body>
</html>
CSS: Cascading Style Sheet 層疊樣式表
js: javascript

Http相關術語

MIME: Multipurpose Internet Mail Extensions 多用途互聯網郵件擴展
/etc/mime.types
格式:major/minor
text/plain
text/html
text/css
image/jpeg
image/png
video/mp4
application/javascript
參考:http://www.w3school.com.cn/media/media_mimeref.asp

HTTP工做機制

工做機制:
http請求:http request
http響應:http response
一次http事務:請求<-->響應
Web資源:web resource
一個網頁由多個資源構成,打開一個頁面,會有多個資源展現出來,可是每一個資源都要單獨請求。所以,一個「Web 頁面」一般並非單個資源,而是一組資源的集合
靜態文件:無需服務端作出額外處理
文件後綴:.html, .txt, .jpg, .js, .css, .mp3, .avi
動態文件:服務端執行程序,返回執行的結果
文件後綴:.php, .jsp ,.asp

HTTP鏈接請求

串行和並行鏈接

串行,持久鏈接和管道

HTTP工做機制

提升HTTP鏈接性能
並行鏈接:經過多條TCP鏈接發起併發的HTTP請求
持久鏈接:keep-alive,長鏈接,重用TCP鏈接,以消除鏈接和關閉的時延,以事務個數和時間來決定是否關閉鏈接
管道化鏈接:經過共享TCP鏈接發起併發的HTTP請求
複用的鏈接:交替傳送請求和響應報文(實驗階段)

HTTP協議

http/0.9:1991,原型版本,功能簡陋,只有一個命令GET。GET /index.html ,服務器只能迴應HTML格式字符串,不能迴應別的格式
http/1.0: 1996年5月,支持cache, MIME, method
每一個TCP鏈接只能發送一個請求,發送數據完畢,鏈接就關閉,若是還要請求其餘資源,就必須再新建一個鏈接
引入了POST命令和HEAD命令
頭信息是 ASCII 碼,後面數據可爲任何格式。服務器迴應時會告訴客戶端,數據是什麼格式,即Content-Type字段的做用。這些數據類型總稱爲MIME 多用途互聯網郵件擴展,每一個值包括一級類型和二級類型,預約義的類型,也可自定義類型, 常見Content-Type值:text/xml image/jpeg audio/mp3

http/1.1:1997年1月
引入了持久鏈接(persistent connection),即TCP鏈接默認不關閉,能夠被多個請求複用,不用聲明Connection: keep-alive。對於同一個域名,大多數瀏覽器容許同時創建6個持久鏈接
引入了管道機制(pipelining),即在同一個TCP鏈接裏,客戶端能夠同時發送多個請求,進一步改進了HTTP協議的效率
新增方法:PUT、PATCH、OPTIONS、DELETE
同一個TCP鏈接裏,全部的數據通訊是按次序進行的。服務器只能順序處理迴應,前面的迴應慢,會有許多請求排隊,形成"隊頭堵塞"(Head-of-line blocking)
爲避免上述問題,兩種方法:一是減小請求數,二是同時多開持久鏈接。網頁優化技巧,如合併腳本和樣式表、將圖片嵌入CSS代碼、域名分片(domain sharding)等
HTTP 協議不帶有狀態,每次請求都必須附上全部信息。請求的不少字段都是重複的,浪費帶寬,影響速度

HTTP1.0和HTTP1.1的區別

緩存處理,在HTTP1.0中主要使用header裏的If-Modified-Since,Expires來作爲緩存判斷的標準,HTTP1.1則引入了更多的緩存控制策略例如Entity tag,If-Unmodified-Since, If-Match, If-None-Match等更多可供選擇的緩存頭來控制緩存策略
帶寬優化及網絡鏈接的使用,HTTP1.0中,存在一些浪費帶寬的現象,例如客戶端只是須要某個對象的一部分,而服務器卻將整個對象送過來了,而且不支持斷點續傳功能,HTTP1.1則在請求頭引入了range頭域,它容許只請求資源的某個部分,即返回碼是206(Partial Content),方便了開發者自由的選擇以便於充分利用帶寬和鏈接
錯誤通知的管理,在HTTP1.1中新增24個狀態響應碼,如409(Conflict)表示請求的資源與資源當前狀態衝突;410(Gone)表示服務器上的某個資源被永久性的刪除
Host頭處理,在HTTP1.0中認爲每臺服務器都綁定一個惟一的IP地址,所以,請求消息中的URL並無傳遞主機名(hostname)。但隨着虛擬主機技術的發展,在一臺物理服務器上能夠存在多個虛擬主機(Multi-homed Web Servers),而且它們共享一個IP地址。HTTP1.1的請求消息和響應消息都應支持Host頭域,且請求消息中若是沒有Host頭域會報告一個錯誤(400 Bad Request)
長鏈接,HTTP 1.1支持長鏈接(PersistentConnection)和請求的流水線(Pipelining)處理,在一個TCP鏈接上能夠傳送多個HTTP請求和響應,減小了創建和關閉鏈接的消耗和延遲,在HTTP1.1中默認開啓Connection: keep-alive,彌補了HTTP1.0每次請求都要建立鏈接的缺點

HTTP1.0和HTTP1.1的區別

HTTP1.0和1.1現存的問題

HTTP1.x在傳輸數據時,每次都須要從新創建鏈接,無疑增長了大量的延遲時間,特別是在移動端更爲突出
HTTP1.x在傳輸數據時,全部傳輸的內容都是明文,客戶端和服務器端都沒法驗證對方的身份,沒法保證數據的安全性
HTTP1.x在使用時,header裏攜帶的內容過大,增長了傳輸的成本,而且每次請求header基本不怎麼變化,尤爲在移動端增長用戶流量
 雖然HTTP1.x支持了keep-alive,來彌補屢次建立鏈接產生的延遲,可是keep-alive使用多了一樣會給服務端帶來大量的性能壓力,而且對於單個文件被不斷請求的服務(例如圖片存放網站),keep-alive可能會極大的影響性能,由於它在文件被請求以後還保持了沒必要要的鏈接很長時間

HTTPS

爲解決安全問題,網景在1994年建立了HTTPS,並應用在網景導航者瀏覽器中。 最初,HTTPS是與SSL一塊兒使用的;在SSL逐漸演變到TLS時(其實兩個是一個東西,只是名字不一樣而已),最新的HTTPS也由在2000年五月公佈的RFC 2818正式肯定下來。HTTPS就是安全版的HTTP,目前大型網站基本實現全站HTTPS
HTTPS協議須要到CA申請證書,通常免費證書不多,須要交費
HTTP協議運行在TCP之上,全部傳輸的內容都是明文,HTTPS運行在SSL/TLS之上,SSL/TLS運行在TCP之上,全部傳輸的內容都通過加密的
HTTP和HTTPS使用的是不一樣的鏈接方式,端口不一樣,前者是80,後者是443
HTTPS能夠有效的防止運營商劫持,解決了防劫持的一個大問題
HTTPS 中的SSL握手等過程下降用戶訪問速度,可是隻要通過合理優化和部署,HTTPS 對速度的影響徹底能夠接受

SPDY

SPDY:2009年,谷歌研發,綜合HTTPS和HTTP二者有點於一體的傳輸協議,主要特色:
下降延遲,針對HTTP高延遲的問題,SPDY優雅的採起了多路複用(multiplexing)。多路複用經過多個請求stream共享一個tcp鏈接的方式,解決了HOL blocking的問題,下降了延遲同時提升了帶寬的利用率
請求優先級(request prioritization)。多路複用帶來一個新的問題是,在鏈接共享的基礎之上有可能會致使關鍵請求被阻塞。SPDY容許給每一個request設置優先級,重要的請求就會優先獲得響應。好比瀏覽器加載首頁,首頁的html內容應該優先展現,以後纔是各類靜態資源文件,腳本文件等加載,能夠保證用戶能第一時間看到網頁內容
header壓縮。HTTP1.x的header不少時候都是重複多餘的。選擇合適的壓縮算法能夠減少包的大小和數量
基於HTTPS的加密協議傳輸,大大提升了傳輸數據的可靠性
服務端推送(server push),採用了SPDY的網頁,例如網頁有一個sytle.css的請求,在客戶端收到sytle.css數據的同時,服務端會將sytle.js的文件推送給客戶端,當客戶端再次嘗試獲取sytle.js時就能夠直接從緩存中獲取到,不用再發請求了

HTTP2

http/2.0:2015年
HTTP2.0是SPDY的升級版
頭信息和數據體都是二進制,稱爲頭信息幀和數據幀
複用TCP鏈接,在一個鏈接裏,客戶端和瀏覽器均可以同時發送多個請求或迴應,且不用按順序一一對應,避免了「隊頭堵塞「,此雙向的實時通訊稱爲多工(Multiplexing)
引入頭信息壓縮機制(header compression),頭信息使用gzip或compress壓縮後再發送;客戶端和服務器同時維護一張頭信息表,全部字段都會存入這個表,生成一個索引號,不發送一樣字段,只發送索引號,提升速度
HTTP/2 容許服務器未經請求,主動向客戶端發送資源,即服務器推送(server push)
HTTP2.0和SPDY區別:
HTTP2.0 支持明文 HTTP 傳輸,而 SPDY 強制使用 HTTPS
HTTP2.0 消息頭的壓縮算法採用 HPACK,而非 SPDY 採用的 DEFLATE

URI

URI: Uniform Resource Identifier 統一資源標識,分爲URL和URN
URN: Uniform Resource Naming,統一資源命名
示例: P2P下載使用的磁力連接是URN的一種實現
magnet:?xt=urn:btih:660557A6890EF888666
URL: Uniform Resorce Locator,統一資源定位符,用於描述某服務器某特定資源位置
二者區別:URN如同一我的的名稱,而URL表明一我的的住址。換言之,URN定義某事物的身份,而URL提供查找該事物的方法。URN僅用於命名,而不指定地址

 

源碼編譯安裝httpd-2.4.39.tar.bz2版本

 

將編譯安裝好http設置開機啓動

相關文章
相關標籤/搜索