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


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

Linux運維工程師職能划分

企業實際應用場景分析

Dev開發環境
使用者:程序員
功能:程序員開發軟件,測試BUG的環境
管理者:程序員
測試環境
使用者:QA測試工程師
功能:測試經過Dev環境測試通過的軟件的功能
管理者:運維
說明:測試環境往往有多套,測試環境滿足測試功能即可,不宜過多
1、測試人員希望測試環境有多套,公司的產品多產品線並發,即多個版本,意味着多個版本同步測試
2、通常測試環境有多少套和產品線數量保持一樣

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

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

程序發布

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

特性

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

ansible架構

Ansible工作原理

Ansible主要組成部分

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

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

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

安裝

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/ansible

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:解包解壓縮,有兩種用法:
1、將ansible主機上的壓縮包在本地解壓縮后傳到遠程主機上,設置copy=yes.
2、將遠程主機上的某個壓縮包解壓縮到指定路徑下,設置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設置開機啟動


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM