面经 - OpenStack(Docker、Django、K8S、SDN)知识点
文章目錄
- 概述
- OpenStack
- 虛擬化
- kvm
- 網絡虛擬化
- 基本技術
- Memcached
- Etcd
- 消息隊列
- 概念
- 交換機類型
- 缺點
- 重復投遞問題
- 順序投遞問題
- restful api
- Horizon
- Nova
- nova-api
- nova-scheduler
- 過濾器類型
- nova-compute
- 基本操作
- Keystone
- Glance
- Neutron
- 一些虛擬的網絡設備
- 架構
- Neutron Server
- ML2 Plugin
- Linux Bridge實現
- local network
- flat network
- vlan network
- vxlan
- DHCP服務
- NameSpace
- Routing
- 底層實現
- router連接外網
- floating IP
- Fwaas
- OpenvSwitch
- local network
- flat network
- VLAN 網絡
- Roting
- VxLAN
- Cinder
- Swift
- Zun
- Kuryr-libnetwork
- SDN
- OpenFlow
- OF 1.0
- OF 1.3
- Django
- 概述
- MVC和MTV
- 和Flask Tornado的區別
- Django請求生命周期
- 常見的web應用程序
- 框架組件
- RestFramework
- 緩存機制
- WSGI,uwsgi,uWSGI
- 請求的生命周期
- 中間件的作用和應用場景
- 默認的中間件
- django中的csrf實現機制
- 基于django的ajax發送請求給后端如何攜帶token
- ajax請求的csrf解決方法
- 為什么不使用django的runserver部署(runserver和uWSGI的區別)
- Kubernetes
- Pod
- Pod控制器
- Docker
- NameSpace
- Cgroups
- 驅動
- 啟動一個容器的步驟
- 基礎
- 什么是Docker
- Docker與虛擬機的不同
- Docker和普通進程的區別
- 鏡像
- 什么是Docker鏡像和Docker容器
- Docker鏡像分層
- bootfs
- 容器分層、寫時復制(copy-on-write)
- DockerFile常見指令
- build
- Dockerfile的COPY和ADD
- Docker容器的狀態
- 網絡
- Docker的網絡類型
- docker常用命令
- 面經
- OpenStack
- 一些命令行
- OpenStack中計算節點上虛擬機默認保存路徑在哪?
- OpenStack中Glance鏡像的默認保存路徑在哪?
- OpenStack中計算節點的集成橋(br-int)的作用是什么?
- OpenStack中計算節點的隧道橋(br-tun)的作用是什么?
- OpenStack中外部OVS橋(br-ex)的作用是什么?
- OpenStack和Docker區別
- OpenStack和kvm的區別
- kvm和xen區別
- Neutron
- vlan和vxlan的區別
- Docker
- 命名空間
概述
云計算是一種采用按量付費的模式,基于虛擬化技術,將相應計算資源(如網絡、存儲等)池化后,提供便捷的、高可用的、高擴展性的、按需的服務(如計算、存儲、應用程序和其他 IT 資源)。
云計算基本特征:
- 自主服務:可按需的獲取云端的相應資源(主要指公有云);
- 網路訪問:可隨時隨地使用任何聯網終端設備接入云端從而使用相應資源。
- 資源池化:
- 快速彈性:可方便、快捷地按需獲取和釋放計算資源。
- 按量計費:
常見的部署模式
- 公有云
- 私有云
- 社區云
- 混合云
三種服務模式
- IaaS:云服務商將IT系統的基礎設施(如計算資源、存儲資源、網絡資源)池化后作為服務進行售賣;
- PaaS:云服務商將IT系統的平臺軟件層(數據庫、OS、中間件、運行庫)作為服務進行售賣;
- SaaS:云服務商將IT系統的應用軟件層作為服務進行售賣。
云計算和虛擬化
云計算:IT能力服務化,按需使用,按量計費,多租戶隔離,是一個系統的輕量級管理控制面。
虛擬化:環境隔離,資源復用,降低隔離損耗,提升運行性能,提供高級虛擬化特性。
虛擬化是實現云計算的技術支撐之一,但并非云計算的核心關注點。
IT架構的三個發展階段
OpenStack
一個開源云操作系統內核,用于構建云平臺,主要實現以下五個主要特點:
- 資源抽象:OpenStack將各類硬件資源,通過虛擬化與軟件定義的形式,抽象成虛擬的資源池;
- 資源調度:OpenStack根據管理員/用戶的需求,將資源池中的資源分配給不同的用戶,承載不同的應用;
- 應用生命周期管理:OpenStack可以提供初步的應用部署/撤銷、自動規模調整等功能;
- 系統運維:OpenStack可以提供一定的系統監控能力;
- 人機交互:OpenStack提供人機接口,外界可通過API、CLI或圖形界面的方式與OpenStack進行交互。
組件間交互是消息隊列,組件內部交互是restful api。
虛擬化
Ⅰ型虛擬化是:hypervisor直接安裝在物理機,就像是vmware的EXSi,底下是基于硬件層的
Ⅱ型虛擬化是:在物理機的正常操作系統,hypersivor作為一個程序模塊運行管理虛擬機,如kvm,virtual box,vmware woerkstation。對硬件虛擬化特別優化,性能好,靈活性高。
kvm
基于linux內核實現的。有一個kvm.so,只需好管理虛擬cpu和內存等;IO外設交給linux內核和Qemu。
Libvirt是一個kvm管理工具,除了能管理kvm還可以xen,virtualBox,openstack底層也是libvirt。
libvirt:
- libvirtd:守護進程:接受處理API請求
- API庫:提供API調用,然后開發一些高級工具,比如virt-manager,可視化管理工具
- virsh:命令行工具
kvm虛擬機是需要CPU硬件支持的,一個kvm虛擬機實質上就是一個qemu-kvm進程,一個vcpu對應一個進程里的一個線程。一個cpu可以調度進程里的多個線程,也就是cvpu數量實際上可以超過cpu,叫CPU超配。可以充分利用宿主機的資源。
通過內存虛擬化共享物理系統內存,動態分配給虛擬機。實現虛擬內存->物理內存->機器內存的映射。虛擬機系統只能實現虛擬內存到物理內存,最后一步無法真正訪問機器內存,因此需要kvm進行一個映射。
存儲虛擬化通過存儲池和卷實現的,卷在虛擬機里就是一塊硬盤。
網絡虛擬化
Linex Bridge是Linux上的TCP/IP二層協議交換設備,二層交換機,多個網絡設備連接到同一個bridge時,有數據包傳來beidge會轉發給其他設備。
br-ctl show查看當前網橋配置。
比如在eth0網卡上配置一個網橋br0,然后虛擬機的網卡可以選擇br0,啟動以后,br0底下會掛載一個inet0的設備,這就是虛擬機的虛擬網卡,但是在虛擬機內部來說虛擬網卡時eth0,inet0是在宿主機的時候標識的名稱。
virbr0是kvm默認創建的一個Bridge,作用是給連接的虛擬網卡提供NAT訪問外網的功能,默認192.168.122.1,如果網絡選擇默認,就會掛載在這個上面。
virbr和br的區別:
- virbr會NAT,發出去的數據包的源IP會被替換為宿主機的IP,只能發不能收
- br直接使用自己的IP通信,可收可發,不用NAT
VLAN
LAN是本地局域網,通產使用hub或者switch連接其中的主機。一個LAN是一個廣播域,所有成員都能收到其他成員的廣播包。
VLAN是Virtual LAN,一個帶有VLAN功能的switch可以將端口劃分出很多個LAN??梢詫⒁粋€交換機劃分為多個交換機,在二層進行隔離,隔離到不同VLAN中。
一般交換機端口有兩種配置方式
- Access:端口被打上VLAN標簽,表明該端口是屬于哪個VLAN的,不同VLAN通過VLANID區分,范圍是1~4096.Access口是直接和網卡相連接的。Access口只能屬于一個VLAN,網卡流出的數據包經過這個端口后直接打上一個VLAN標簽
- Trunk:一個端口可以同時傳輸轉發多個VLAN標簽的數據包,在傳輸的過程中數據包始終攜帶VLAN ID
總結:
基本技術
Memcached
是一個高性能分布式內存對象緩存系統,在OpenStack中用于緩存認證系統的令牌,減少高并發下對于數據庫的訪問壓力,提高訪問速度。
將需要存取的數據或對象緩存在內存中,內存中緩存數據可以通過API進行操作,數據經過Hash操作以后存在一個Hash表中,是K-V形式存儲。
memcached沒有訪問控制和安全管理,因此需要使用防火墻等安全功能進行相應防護
使用最近最少使用算法LRU對最近不活躍的數據進行清理,從而得到新的內存空間。
對于大規模數據緩存有著較為明顯的優勢而且通過開放API多種語言可以直接操作memcached。OpenStack的keystone就是用memcached緩存租戶的身份等信息、從而在租戶登錄驗證的時候無需重復訪問數據庫即可查詢得到相應數據。Horizon和Swift也用到了這個來進行數據的緩存以提高客戶端的訪問請求速率。
操作的過程
- 檢查數據是否存在memcached,如果有直接返回
- 如果數據不存在memcached,去數據庫查詢,同時將數據庫緩存到memcached
- 每次更新數據庫的時候同步更新memcached的數據保證一致性
- 如果分配的內存空間滿了,使用LRU算法對失效的數據進行處理
功能特點
- 協議簡單:基于文本行進行操作
- 基于libevent事件處理:將epoll等事件處理封裝成一個接口,保證服務器端的連接數,使用這個庫進行異步事件處理
- 內置的內存管理方式:有自己特有的一套內存管理方式,很高效;但是不考慮容災,重啟數據丟失
- 節點之間相互獨立:各個服務器之間互不通信,獨立存取數據不共享,通過客戶端實現其分布式,支持海量緩存和大規模應用
缺點
- 單點故障:因為每個節點是獨立存取數據的,服務器之間沒有通信,即不會進行數據的同步和備份,如果一個節點down了,節點的數據全部丟失且無法恢復
- 存儲空間限制:會受到尋址空間大小限制,32位系統可緩存2G,64位可緩存無限,只要物理內存足夠大
- 存儲單元限制:K-V的key最大250字節,value最大1MB
- 數據碎片:內存存儲單元按照Chunk分配的,會造成內存碎片,因為不可能所有存儲的value大小都是一個Chunk大小
- 不安全
Etcd
是一個go語言開發的開源的高可用的K-V存儲系統,用于配置共享和服務的注冊和發現。
集群部署一般使用奇數個服務器配置,因為Raft決策時候需要多節點投票。
有幾個特點:
- 高可用:避免因為單點故障或者網絡故障造成服務down
- 一致性:每次讀取都會返回跨多個主機的最新寫入
- 完全復制:每個節點都可以使用完整數據歸檔
- 安全:提供一個帶有可選的客戶端證書身份驗證的自動化TLS
- 快速:每秒一萬次寫入的基準速度
- 可靠:使用Raft算法實現強一致、高可用的服務存儲目錄
應用場景
- 服務發現:同一個分布式集群中找到是否有進程在監聽端口
- 配置中心:講一些數據放在Etcd集中管理,比如在啟動的時候主動從etcd獲取配置信息,并且設置一個Watcher,有更新的時候etcd會主動通知訂閱者獲取最新配置信息
- 分布式鎖:使用Raft實現數據的強一致性,某次操作存儲必須是全局一致性的。有兩種:保持獨占(始終只有一個用戶可以獲得,實現了一套分布式原子操作CAS的API)、控制時序(所有想獲得鎖的用戶都會被安排執行,獲得鎖的順序也是全局唯一,決定了執行的順序)
相比榮譽zookeeper和doozer,有如下特點:
- 簡單:基于HTTP+JSON,提供API便于調用
- 安全:使用SSL客戶認證機制
- 快速:實例每秒支持一萬次寫操作
- 可信:Raft算法實現分部署
消息隊列
rabbitmq屬于AMQP(高級消息隊列協議)的一種實現,應用層的一個開放標準。
特點:
- 較高的靈活性
- 高可擴展性,多個rabbitmq可以組成集群
- 支持常見的編程語言
- 提供可視化界面便于管理
- 支持多種協議,不只是AMQP
- 提供了多種插件
AMQP的三大組件:
- Exchange交換機:把消息路由到隊列
- Queue隊列:存儲消息等待消費,多個消費者可以訂閱同一個隊列
- Binding綁定:將交換機和隊列進行綁定,告知交換機應該投遞到哪個隊列
優點:
- 異步:如果阻塞式的話,A給B發請求,B如果處理需要很長時間,那么A也需要等待很久,顯然是不合理的,還會資源浪費,可以通過消息隊列先發送一個請求命令給B ,然后A直接進行下一步,當B有結果時會通知A
- 解耦:如果每一個組件之間通過直接通信的話,都需要維護一套比如接口代碼,會有很多重復冗余的代碼,,而且還需要考慮比如對方是否接到消息,消息是否丟失之類的。使用消息隊列就不需要考慮這些了,把消息投遞進入就好了,剩下的消息隊列做
- 削鋒:如果短時間內有大量請求直接到服務器,可能會造成擁塞甚至崩潰。放入消息隊列里,消費者可以依次取出消息進行消費,相當于一個緩沖,雖然會慢一點,但是會很高效穩定
概念
有幾個概念關鍵詞
- Exchange:消息交換機,它指定消息按什么規則,路由到哪個隊列
- Queue:消息隊列載體,每個消息都會被投入到一個或多個隊列,多個消費者可以訂閱同一個隊列
- Binding:綁定,它的作用就是把exchange和queue按照路由規則綁定起來
- Routing Key:路由關鍵字, exchange根據這個關鍵字進行消息投遞
- producer:消息生產者,就是投遞消息的程序
- consumer:消息消費者,就是接受消息的程序
- channel:消息通道,在客戶端的每個連接里,可建立多個channel,每個channel代表一個會話任務。
交換機類型
- Direct Exchange(直連交換機):交換機和隊列一對一匹配
- Fanout Exchange(扇型交換機):消息會被發送至所有與該交換機綁定的隊列,不會按照指定的路由鍵進行投遞,類似廣播
- Topic Exchange(主題交換機):交換機會將消息的路由鍵和綁定到自身的隊列進行匹配,將消息投遞到匹配上的隊列中去。比如如果寫成這樣log.#,那么可以匹配log.開頭的routingkey
- Headers Exchange:類似主題交換機,但是是使用消息頭部的屬性進行分發,而不是routingkey
缺點
系統可用性降低,rabbitmq掛了以后系統就崩了。
如何解決消息重復投遞或者丟失的問題
如何解決消息按順序發送的問題
重復投遞問題
給每一個消息設置一個類似唯一標識的一個ID,接收者去除消息以后先在數據庫中對比一下是否存在,如果不存在,就正常消費。
順序投遞問題
還是使用一個ID,一般這個會出現在比如說訂單的場景,生成訂單,制作訂單,訂單號都是一樣的,把這些消息投遞到一個訂單隊列里面,取出的時候就是順序的了。
restful api
restful api是一種軟件架構設計的風格,不是標準,提供了一組設計的原則和約束條件,是一套編寫接口的協議,協議規定如何編寫,返回值和狀態碼等,主要用于客戶端和服務器端的交互。
最顯著的特點就是一個url可以通過不同的HTTP方法實現不同的功能,而no rest則需要使用多個url分別實現多個功能。
- 還可以使用https
- 不同版本可以有不同接口
- 可以根據不同http方法執行不同操作
- 返回格式應該統一為json,還有狀態碼
django中的erest框架叫django rest framework
能夠生成符合restful規范的api
- 在開發restful api的時候,雖然具體業務流程不一樣,但是基本增刪改查操作差不多,這部分代碼可以簡寫復用
- 序列化和反序列化的時候代碼流程也差不多,,也可以簡寫
傳統的URL需要在鏈接里加上操作的動作等;
而restful api則用URI統一資源標識符唯一標識服務器的一個資源,并且使用HTTP方法對其進行操作
Horizon
提供一個Web前端控制臺,從而實現通過web管理云平臺,建云主機,分配網絡,配安全組等。
Region(區域):地理上的概念可以理解為是兩個不同區域的數據中心,是完全隔離的,但是可以共享同一套keystone和horizon了用戶可以選擇距離自己更近的域使用服務
Nova
端口
- nova-api:通過接口對外提供服務,接受請求處理操作調度資源等。接收傳來的HTTP請求校驗參數,然后調用其他子服務實現請求操作,之后處理結果返回
- nova-compute:Nova的核心服務,,負責管理虛擬機的整個生命周期如創建相應銷毀等,通過調用Hypervisor API
- nova-scheduler:虛擬機調度服務,決定虛擬機應該創建在哪個節點。通過過濾器選擇合適的計算節點,然后計算節點權重,選擇最優的節點(默認權值是計算空閑內存量,內存越大權值越大)
- nova-conductor:負責數據庫的訪問控制,避免compute直接訪問數據庫。避免計算節點出現故障導致數據庫出現問題,可以擴展配置多個conductor更好的應對更多計算節點對于數據庫的訪問
創建一個虛擬機大概的流程:
這里的消息發送全部都是通過消息隊列實現的,進行異步調用,不會阻塞服務;解耦各個子模塊功能;提高可擴展性;提高性能,可以處理多個請求,提高吞吐量
使用API的好處:
- 對外提供了一個統一的調用方法,隱藏實現細節
- 提供了restful風格的服務,便于和第三方集成
- 通過運行多個api進程實現高可用
OpenStack的開放性,一個重要方面就是基于Driver的框架。比如說nov-acompute中為hypervisor定義了統一的接口,支持多種Hypervisor,如Xen、VirtualBox、Hyper-V、Docker等
nova-api
對外暴露若干個Restful API,用戶可以發送請求到指定Endpoint
- 收到HTTP請求后,會先進行參數校驗
- 調用nova其他子服務開始執行相應操作
- 再返回執行的結果
和虛擬機生命周期的指定請求nova-api都可以收到并處理。
nova-scheduler
在創建虛擬機的時候需要指定一個flavor也就是規格,其中規定了vcpu、ram、disk等參數,隨后將falvor信息傳入到noca-scheduler中,會根據flavor選擇一個合適的節點創建虛擬機。
Filer scheduler是默認調度器,過程分為兩步,第一是通過過濾器計算出滿足條件的計算節點,通過權重計算,在權重最大(最優)的節點創建虛擬機。
同樣可以使用第三方的scheduler,只需要配置一個scheduler_driver即可,再次體現出OpenStack開放性。
過濾器類型
nova可以配置默認使用全部過濾器acheduler_availiable_filters,但是真正使用到的是這個參數scheduler_default_filters
- RetryFilter:如果AB節點通過了第一步過濾,然后A權重最大,但是在A創建失敗了,那么下一次調度的時候,就會在第一步將A刷掉,避免再次失敗
- AvailabilityZoneFilter:為了提高容災和隔離,將計算節點可以劃分到不同的AvailablittZone中,每個AZ都可能有著各自獨立的電力系統、獨立的網絡和機柜等,為了應對故障的發生,一個Region可以有多個AZ,默認是nova。這里會判斷將不屬于指定AZ的計算節點刪除
- RamFilter:將不滿足flavor中內存規格的計算節點除去。OpenStack允許overcommit,可以在nova里面改這個參數ram_allocation_ratio=1.5,如果某個計算節點有10G內存,OpenStack會認為其有15G內存
- DiskFilter:同上,同樣允許overcommit,默認參數值為1
- CPUFilter:同上,允許overcommit,默認參數值為16.也就是如果一個計算節點有8vcpu,那么OpenStack會默認其有128vcpu。默認過濾器是不包含這個過濾器,需要手動添加
- ComputeFilter:保證工作正常的計算節點才會被篩選出來,是必須的一個過濾器
- ComputeCapabilitiesFilter:根據計算節點的特性篩選,如計算節點有x86_64和ARM架構,如果指定ARM架構,就需要這個過濾器,這個需要在flavor的Metadata中指定
- ImagePropertiesFilter:image同樣具有metadata,根據這個元數據篩選出匹配的計算節點。比如可以選擇hypervisor_type=kvm,那么使用這個鏡像過濾就只能篩選出kvm的節點
- ServerGroupAntiAffinityFilter:盡可能將實例分散到不同的節點上。需要創建一份server group,把實例添加進來才有用
- ServerGroupAffinityFilter:盡可能創建實例在一個計算節點上。
nova-compute
compute和hypervisor一起共同管理虛擬機生命周期。
定義了很多統一的接口,hypervisor實現這些接口就可以在openstack里面了。
一個計算節點只能指定一種虛擬類型。
主要有兩種功能:
- 報告計算節點狀態
- 實現虛擬機生命周期管理
需要實時報告計算節點可用內存、vcpu等數量,scheduler才可有進行過濾調度的依據,通過hypervisor api獲取虛虛擬機的資源信息。
管理生命周期包括如下:
- 為實例準備資源
- 創建實例鏡像文件
- 創建實例的.xml定定義文件
- 創建網絡并啟動實例
在下載鏡像的時候,如果存在就直接使用,會很快,不存在會先下載。比如是qcow2格式的鏡像,由qemu-img轉為raw格式然后進行backing file,這個不能是qcow2格式。
基本操作
- 軟硬重啟其實就分別是reboot重啟和關機再開機
- Pause/Resume:可以暫停虛擬機,并將狀態保存到內存中,需要的時候再resume讀取內存恢復虛擬機
- Suspend和Pause:前者可以暫停虛擬機并將狀態保存在磁盤上,后者保存到內存中,相對較快;前者狀態會變成shutdown,后者是paused;前者對應的恢復操作叫resume,后者其實是unpaused
- rescure/Unrecure:救援。當因為斷電或者誤操作導致操作系統出現故障不能啟動實例了,一般會使用一張引導盤進入系統,然后試圖恢復系統,比如忘記密碼或者刪除了某個文件。rescure可以將某個image作為啟動盤,然就將原系統盤掛載到這個操作系統上,fdisk可以看到,新的image是vda,原系統盤就是vdb,修好以后unrescure恢復引導盤
- snapshot:快照的原理就是對實例的鏡像文件進行全量備份,保存到glance。
- rebuild:當損壞嚴重的時候,可以使用快照恢復。rebuild會使用快照替換當前實例的系統盤,并且保持實例原有的網絡、資源等信息
Keystone
常用的5000端口,以及沒怎么用過的35357端口
為OpenStack其他服務提供身份驗證、服務規則和服務令牌的功能,管理Domains、Projects、Users、Groups、Roles。
- User:代指任何使用gopenstack的實體,可以是真正的用戶,也可以是一個系統服務,在訪問openstack的時候,keystone會對User進行身份認證
- Credentials:User用來表明自己身份的憑證,可以是用戶名密碼、token或者API Key等
- Authentication:是keystone驗證User身份的一個過程,User訪問openstack的時候向keystone發送用戶名密碼等信息,keystone驗證成功后返回一個token,作為用戶的Credentials
- Token:是一串數字和字母組成的字符串,用戶在keystone驗證身份后會得到,在訪問其他服務的時候會被用來驗證身份有效性,一般默認24小時。
- Project:用于將OpenStack的資源進行分組和隔離,可以是一個客戶或者部門。一個用戶需要掛載到Project后才能訪問其中的資源
- Service:Nova、Glance等就是OpenStack的服務,每個Service會提供若干個Endpoints供用戶去訪問資源和執行操作
- Endpoint:是一個可以訪問的地址,通過Endpoint暴露自己的API,keystone維護
- Role:對用戶進行鑒權,每個User會被分配一個或多個Role,該用戶擁有Role指定的權限。如果修改權限需要修改/etc{service_name}/policy.json
Glance
監聽端口:
- glance-api:9292
- glance-registry:9191
傳統的安裝一個系統可能需要從CD或者ghost工具進行安裝,非常繁瑣。二運計算環境中有一個更高效地解決方案,就是Image。
每個Image中裝有操作系統以及相應的配套軟件環境,用戶可以直接使用安裝即可快速創建一個虛擬機。
比如云計算中可以有這么一個場景:當我們需要有一個新的系統需求的時候,我們可以先手動創建一個虛擬機然后安裝好相應的操作系統和需要的軟件環境,然后創建一個snapshot保存在云中,后續如果有用戶需要使用可以直接使用這個snapshot快速創建虛擬機,這都是可以自動完成了。
為云主機提供不同系統鏡像,支持多種虛擬機鏡像格式(AKI、AMI、ARI、ISO、QCOW2、Raw、VDI、VHD、VMDK),有創建上傳鏡像、刪除鏡像、編輯鏡像基本信息的功能。
glance-api對外提供restful api接口調用,當有請求來以后,api不會自己主動處理,而是會調用glance-registry處理有關元數據的操作,調用store backend處理有關鏡像的操作。
Image默認存儲在/var/lib/glance/images。
glance-registry負責處理有關metadata的操作,如存取。比如image的大小或者類型,支持多種格式:QCOW2、RAW、vmdk、ISO等,元數據默認保存到mysql
store-backend:glance自己不保存鏡像,而是使用backend存儲,glance支持多種backend,如默認的local filesystem本地文件系統、ceph、swift、cinder、EXSI等
Neutron
端口9292
提供云計算的網絡虛擬化技術,為OpenStack其他服務提供網絡連接服務。為用戶提供接口,可以定義Network、Subnet、Router,配置DHCP、DNS、負載均衡、L3服務,網絡支持GRE、VLAN。插件架構支持許多主流的網絡廠家和技術,如OpenvSwitch。
根據網絡類型的不同有以下幾種網絡:
- Flat network:基于不使用 VLAN 的物理網絡實現的虛擬網絡。每個物理網絡最多只能實現一個虛擬網絡。
- local network(本地網絡):一個只允許在本服務器內通信的虛擬網絡,不進行跨服務器的通信。主要用于單節點上測試。
- VLAN network(虛擬局域網) :基于物理 VLAN 網絡實現的虛擬網絡。共享同一個物理網絡的多個 VLAN 網絡是相互隔離的,甚至可以使用重疊的 IP 地址空間。每個支持 VLAN network 的物理網絡可以被視為一個分離的 VLAN trunk,它使用一組獨占的 VLAN ID。有效的 VLAN ID 范圍是 1 到 4094。
- GRE network (通用路由封裝網絡):一個使用 GRE 封裝網絡包的虛擬網絡。GRE 封裝的數據包基于 IP 路由表來進行路由,因此 GRE network 不和具體的物理網絡綁定。
- VXLAN network(虛擬可擴展網絡):基于 VXLAN 實現的虛擬網絡。同 GRE network 一樣, VXLAN network 中 IP 包的路由也基于 IP 路由表,也不和具體的物理網絡綁定。
網絡轉發
一般架構是控制節點、計算節點和網絡節點。
網絡節點就dhcp服務之類的,計算節點是各種agent,控制節點是neutron-server一個組件。
然后如果跨子網通信的話,流量需要從計算節點到網絡節點,通過router路由一下,轉發到對應的計算節點的實例上。而如果需要配置NAT的話是需要在router上面配置的,也就是網路節點,如果有需要流量轉發出去的話,都需要通過網絡節點。
但是這樣的話網絡節點的壓力就比較大,一旦網絡節點崩潰了,整個網絡就崩了;還有一個就是即便兩個實例在同一個計算節點上,如果不在一個網絡中,還需要經過網絡節點路由一下才能回來,很麻煩。
那么就有一個東西DVR(Distributed Virtual Routing),部署在計算節點,可以直接使用浮動IP訪問外網,不需要經過網絡節點了。是通過openflow規則進行判斷的。
Neutron功能:
- 二層交換:實例通過虛擬交換機連接到虛擬二層網絡,Nova支持多種交換機,Linux Bridge和OpenvSwitch(開源虛擬交換機)
- 三層路由:給實例配置不同網段的IP,router(虛擬路由器)可以實現跨網段通信,使用IP forwarding、iptables等實現路由和NAT
- 負載均衡
- 防火墻:一個是security group使用的iptables、另一個是firewall-as-a-service,也是基于iptables的
一些概念
- network:二層廣播域,支持多種類型網絡:local、flat、vlan、vxlan、gre
-
- local:這個網絡與其他網絡節點隔離,只能和同一節點的同一網絡實例通信
-
- flat:沒有vlan tag的網絡,網絡中的實例可以和其他實例通信
-
- vlan:802.1q標簽的網絡,一個二層廣播域,同一個vlan中的實例可以相互通信,不同vlan只能通過router通信。vlan可以跨界點,標簽數為1-4096
-
- vxlan:基于隧道技術的overlay網絡,VxLAN網絡使用唯一的段ID與其他VxLAN進行隔離。會通過VNI封裝為UDP數據包傳輸,二層包通過封裝可以在三層傳輸,因此克服了物理網絡基礎設施的限制
-
- gre:是和VxLAN類似的overlay網絡,區別在于使用IP包封裝而不是UDP
一些虛擬的網絡設備
Veth pair
Veth是linux系統虛擬出來的一個網絡設備,總是成對出現的,功能類似虛擬網線的功能,在創建兩個Veth設備,假設放在兩個namespace里面,那么通過這個Veth設備可以實現相互通信,默認情況下是不通的。
通常鏈接網絡的namespace,也鏈接linuxbridge,一般用于連接兩個linuxbridge或者一個linuxbridge和ovs,兩個ovs一般不太用這個,一般用patch連接兩個ovs bridge,效率更好。
實際操作
在這里創建一個新的namespace,然后創建一對Veth pair試一下,單純記錄,我沒有操作過。
TUN、TAP
Veth是兩端都一樣的虛擬網線,而這個就是兩端都不一樣的虛擬網先,相當于一邊是水晶頭,另一端是USB接口,是用戶空間和內核空間傳輸報文使用到的“網線”,一邊是普通的網卡比如eth0,另一端是文件描述符,用戶空間使用的。
實例的本質是qemu進程,因此TUN、TAP網線一般是給VM用的,所以這個文件描述符一般是VM,另一端則是虛擬出來的TAP設備,這也就是為什么Neutron幾種網絡模型里面的VM或者linuxbridge連接router的時候都是通過TAP設備的
Bridge
是一種虛擬集線器的實現方式,多個網卡連接到這個上面,一個發送報文其他都能接收到。
把TUN/TAP或者Veth pair放在Bridge上面,就可以實現相互通信。Docker就是用linuxbridge將所有的容器連接在一起,bridge模式,就是docekr0網卡
架構
Neutron主要有以下幾個部分:
- Neutron Server:對外提供API,接收請求,調用Plugins處理請求
- Plugin:處理來自Server的請求,并且轉發調用Agent處理請求
- Agent:處理來自Plugin的請求,并且在network provider上具體實現每個網絡功能
- network provider:提供網絡服務的虛擬網絡設備或物理網絡設備,比如Linux Bridge或者OpenvSwitch或者其他支持Neutron的物理交換機
- Queue:組件之間交互的消息隊列
- Database:存放網絡狀態信息
架構這么多層次有兩個原因
- 為了支持現有或者未來出現的網絡技術
- 為了支持分布式的靈活擴展性
plugin有一個功能時需要維護數據庫中的網絡狀態信息,如果有多個插件的話,每一個provider的plugin都要寫一套類似的數據庫操作代碼,會很繁瑣,因此現有版本使用了ML2 plugin,對plugin進行了抽象。只需要實現響應driver就行了,不需要具體實現plugin了。
plugin主要分為兩種(均有對應的agent):
- core plugin:比如linux bridge或者openvswitch
- service plugin:比如routing、firewall、load balance等
物理架構
有兩種。
第一種:控制節點+計算節點
控制節點配置neutron server、core plugin、service plugin和兩個對應的agent
計算節點配置core plugin的agrnt,負責二層網絡功能。
通過agent實現控制節點和計算節點之間的二層網絡通信,可以部署多個控制節點和計算節點
第二種:控制節點+網絡節點+計算節點
控制節點配置neutron server
網絡節點配置core plugin、service plugin和對應的agent
計算節點配置core plugin,負責二層網絡功能
- 將agent從控制節點分離出來,控制節點只通過neutron server處理分發api請求
- 可以通過增加網絡節點的個數提高負載
- 使用獨立的節點實現數據交換,并且可以配置路由、負載均衡等高級功能
- 適合大規模環境
Neutron Server
由上而下分別是
- Core API:對內提供restful api,如管理子網網絡端口等
- Extension API:對外提供restful api,如管理router、firewall-as-a-service、負載均衡等
- Common Service:認證校驗API
- Core Plugin API:定義個Core Plugin抽象功能,通過API調用對應plugin
- Neutron Core:Neutron的核心處理程序,調用相應Plugin處理
- Extension Plugin API:定義。。。
- Service Plugin:維護管理router、負載均衡等資源狀態信息,調用agent在network privider上實現相應功能
但是提出了兩個問題
ML2 Plugin
主要解決上面說的兩個問題
允許網絡中使用多種二層網絡技術,不同節點直接按可以使用不同的網絡實現機制。
可以在不同節點上使用不同的agent了,而且不用重新開發core plugin,實現mechanism driver就可以了。
ML2對二層網絡進行了抽象解耦,type driver和mechanism driver使得其具有非常好的彈性,能夠靈活支持多種agent(type或者mechanism)
每一種網絡都有這么兩種driver
Type Driver
負責管理網絡狀態、創建網絡等。
有這么集中網絡類型:local、flat、vlan、vxlan、gre
mechanism driver
獲取由type維護的網絡狀態,并且確保其在物理或者虛擬設備上的實現
比如創建一個VLAN100,VLAN的type driver負責將數據保存在數據庫里,然后linux bridge的mechanism driver負責在各個節點上調用agent創建相應的vlan設備和bridge。
Mechanism Driver有三種:
- Agent-based:就是基于agent的,比如linux bridge和openvswitch
- Controller-based:基于控制器的,如opendaylight,就是sdn
- 基于物理交換機:如思科的設備
Linux Bridge實現
local network
local網絡不會和任何物理網卡連接,也不會有VLAN ID。
對于每一個local網絡都會創建一個網橋,將實例的tap設備綁定到網橋上。
同一網橋上的實例可以相互通信。每個local網絡都有自己的網橋,互不影響,因此同一個節點上不同往前的實例不能通信。
其實只有admin創建網絡可以選擇type driver,普通用戶在自己租戶里創建網絡的時候默認使用/etc/neutron/plugins/mk2/ml2_conf.ini里面的一個參數tenant_networks_type=local,默認是local,需要修改一下,可以指定多個,如vxlan,local,會從左到右按照順序依次創建,如果vxlan的id用完了,就會創建local。
命名
brqxxxxxx對應的是網絡,表明這是網絡id為xxxxx創建的一個網橋
tapyyyyy,其實就是虛擬機的一個虛擬網卡,對應的是port,說明這是id為yyyy的port的tap接口設備,tap將連接到brq上
在創建實例的時候,neutron-linubgridge-agent根據port信息創建一個tap設備,連接到local網絡所在的bridge網橋上。這個tap設備就會映射為實例的虛擬網卡。
flat network
不帶tag的,要求和物理網卡連接,所以需要在ml2的配置文件里寫physical_interface_mappings=default:thh0,前面式一個label,用來標識flat,可以是任意字符粗漢,就是表明和物理網卡的對應關系,因為可能每個節點使用的物理網卡不一樣,因此這里的default就映射為配置好的物理網卡。
如果不同節點的實例連接到同一個網絡,他們所處的網橋名稱一致,通過provider network通信。
vlan network
vlan是帶tag的網絡。
如下所示,多個tap連接到brq網橋上。eth1網卡上創建了一個eth1.100的vlan interface接口,可以連接到這個brq上,然后通過eth1.100到eth1的數據包就會被標記一個100的vlan tag。
如果有多個eth1.xxx接口連載eth1網卡上,就可以通過這個tag標簽相互隔離不同的vlan。
如果需要這么設置的話,物理機連接的交換機端口需要設置為trunk,不能是access,因為需要流過多個tag數據包
vxlan
OpenStack支持VxLAN和GRE這兩種overlay網絡,overlay網絡指建立在其他網絡之上的網絡。
linuxbridge只支持vxlan,ovs兩個都支持。
優點
- VLAN使用12bit標記tag,最多4096個,而VxLAN支持24bit,最多16777216個二層網段
- 能夠很好利用已有路徑,封裝UDP通過三層傳輸和轉發,可以使用所有路徑。(VLAN用了Spanning Tree Protocol避免環路,有一半路徑用不成)
- 避免物理交換機MAC表耗盡,因為用了隧道技術,不需要再MAC表里記錄虛擬機信息
缺點
其實也是有一些缺點的
- 比如強制在三層傳輸數據包可能路徑不是最優傳輸速度慢
- 雖然避免了物理交換機記錄大量的虛擬機MAC,但是可能會造成路由器的ARP表有較多的記錄,影響正常的性能
- 而且標準規定VxLAN不能分片,要求物理鏈路層的MTU足夠大才行
VxLAN是將二層建立在三層上的網絡,把二層數據封裝在UDP數據包里擴展二層網絡。IP+UDP
DHCP服務
通過DHCP agent實現DHCP服務。運行在網絡節點,dnsmasq
當 創建一個網絡的子網開啟dhcp功能后,agent會啟動一個dnsmasq進程提供服務,其實dnsmasq和network是對應的,一個進程可以給所有的子網提供dhcp服務。
通過dnsmasq獲取IP信息。
在創建實例的時候,實例會綁定一個port,有MAC和IP信息,dnsmasq會把這個記錄在一個host文件里。
實例啟動以后,會發送DHCPDISCOVER廣播,然后廣播消息會在flat網絡里傳播,通過veth paur到達另一個namesapce里面,dhsmasq監聽到了,然后返回對應的IP信息,DHCPOFFER,包含IP地址、租期時間等給實例
最后實例返回一個DHCPREQUEST消息接收DNSOFFER。
NameSpace
二層網絡上可以通過VLAN將物理交換機分割為多個虛擬交換機。
而namespace可以將物理的三層網絡劃分為多個隔離的虛擬三層網絡,有這幾個字的網絡棧、防火墻規則、路由表等。
Neutron就是通過namespace為每個network提供DHCP服務和路由,讓租戶之間的網絡可以重疊不沖突,提高了靈活性。
每個namesapce里有各自的dnsmasq,ip nets list可以查看。
管理員可以將brq或者tap添加到某個namesapce里面。
如何讓兩個namespace相互通信呢
默認是不能通信的,Neutron里面使用了 veth pair,相當于虛擬網線,連接兩個namespace,這邊輸入另一邊接收。
Routing
路由提供了跨子網的通信。這里有兩個實例
vm1 - 172.16.100.3 - vlan100
vm3 - 172.16.101.3 - vlan101
這兩個實例是兩個不同vlan的,他們之間不能通過二層交換進行通信,必須借助router。
虛擬router由L3 Agent在控制節點或者網絡節點運行。
底層實現
通過配置一個router,vm1和vm3就可以進行通信了。
首先vlan101的bridge網橋上多了一個tap設備,這個設備就是路由器的interface接口
同樣vlan100所在的網橋也有這么個接口設備。
L3 Agent會給每個router配置一個namespace,使用veth pair和tap設備連起來。對應的gateway ip在namesapce內的veth interface上。叫qr-…
其中namespace里的qr-xxxx和tap-xxxx組成veth pair進行通信。
如下圖所示
引入namespace而不直接使用網關的作用
為了使得租戶之間的網絡可以重疊提高靈活性。
不然如果A和B都有相同子網,只用網關的話需要在控制節點的路由表上加兩項,而且目的IP可能一致,無法區分了。
router連接外網
給router配置好一個外部網絡(一般是flat或者vlan類型)的網關以后,router多一個接口,通過這個接口可以連接到外網,ip比如是10.10.10.2。
然后連接外部網絡的bridge的tap-xxxx設備,通過veth pair和路由器namesapce內的qg-xxxx接口連接
冷知識,router的內部網絡的接口叫qr-xxxxx,外部網絡叫qg-yyyyy
此時看ip nets exec qrouter-xxxx route,會看到10.10.10.1有一個qg的接口。說明如果是外網流量的話,router會通過這個接口將流量轉發到這個網關,然后到linuxbrige的brq網橋上轉發到網卡上。。
從qg-xxxxx出去的話會進行一個SNAT的轉換,將源IP修改為router的源IP 10.10.10.2,以便回來的時候可以找到路由器
floating IP
SNAT可以讓實例訪問外網,但是還不能讓外網訪問實例,使用浮動IP可以解決這個。
floating ip可以提供一個一對一映射的靜態NAT。
創建好一個floating ip以后,會配置到router的外網的qg接口,然后iptables會添加兩個規則
- 如果是內網IP到達路由器,轉換為對應的floating ip發送出去
- 如果是floating ip對應的數據包到達路由器,會修改為對應的內網IP
Fwaas
讓用戶可以創建和管理防火墻,在子網的邊界進行流量過濾。傳統的防火墻是在網關上的,隔離子網,而這個是在router上配置的,控制租戶網絡進出的流量。
分為:
- Firewall:必須關聯某個Policy
- Firewall Policy:是Rule的集合,會按照Policy中的順序依次過濾
- Firewall Rule:訪問控制規則,包括源IP和端口、目的IP和端口,協議類型以及操作
安全組的對象是虛擬網卡,L2 Agent實現,對通過iptables實現對實例虛擬網卡流量的過濾。而fwaas是配置在虛擬路由器上的,在到達安全組之前可以先過濾一下,但是同一個subnet內部的虛擬網卡間不會過濾,因為不通過router。
fwaas沒有單獨的agent,是在L3 Agent中配置的,driver為IP tables,要在service plugins啟用fwaas。
FWaaS v2
上面說的是v1,Stein版本以后,v1廢棄了,是v2了。
Firewall概念變為Firewall Group了,而且不像v1是唯一綁定一個路由器,v2需要指定路由器的某個接口。
可以同時管理ingress和egress進口和出口兩種流量。v1則不區分,對雙向流量進行過濾,安全組區分流量。
OpenvSwitch
ovs是除了linuxbridge外的另一種虛擬化交換機技術。
安裝ovs agent,修改ml2的mechanism_drivers。
初始狀態有三個網橋:
- br-int:連接所有虛擬機的虛擬網卡或和其他虛擬網絡設備
- br-ex:連接外部網絡的網橋
- br-tun:隧道技術用這個,比如VxLAN或者GRE
計算節點沒有br-ex,因為計算節點的外網流量是通過網絡節點的虛擬路由器轉發的,所以br-ex在網絡節點上。
local network
同樣的local網絡不會和網卡連接,流量被限制在宿主機內,只有同一個網橋上的才可以通信。
創建了一個local網絡以后,br-int網橋上有一個tap設備,是dhcp的接口,tap設備是在這個命名空間里的。
創建一個實例以后,Neutron在子網subnet中創建一個port,分配IP和MAC,綁定在實例上,會創建一個tap-xxxx設備作為實例的虛擬網卡。
然后在linuxbridge上創建一個qbr-xxxx網橋,和tap設備相連。
然后通過veth pair連接到br-int,即qvb-xxxx與qvo-xxxx。
為什么需要使用一個linuxbridge中轉不能直接使用tap設備連接到br-int呢
因為ovs不支持將iptables規則放在與其相連的tap設備上,因此為了實現security group安全組的功能,需要引入linuxbridge作為一個中轉
如下圖所示
一個實例的網絡設備連接情況如下(以次連接):
- tap-xxxx:虛擬網卡
- qbr-xxxx:tap連接到linuxbridge的qbr,為了使用security group功能
- qbr通過一對veth pair(qvb-xxxx和qvo-xxxx)連接到br-int網橋
<font color="red>如果此時創建第二個local 網絡,然后創建一個虛擬機,其虛擬網卡同樣會連接到br-int上,那么可以通信嗎。
不可以。
ovs會將每個網橋看成一個虛擬機,然后可以支持vlan,每個local網絡的djcp和虛擬網卡都有一個tag,這個tag就是VLAN ID,相互之間隔離。僅用于隔離網橋中的port。
flat network
flat網絡的話是不帶tag的,而且一個flat網路需要和一個物理網卡相連。
這里在修改配置文件的bridge_mappings的時候,不是標簽:物理網卡了,而是標簽:連接網卡的網橋名。
因此需要先創建一個br-eth1網橋,連接到物理網卡eth1。
此時在br-int和br-eth1會分別多出一個接口int-br-eth1和phy-br-eth1,是patch類型的,用來連接br-int和br-eth1,可以訪問外網。
如下所示
在linuxbridge里面用veth pair連接br-int和linuxbridge,而這里使用patch連接br-int和br-eth1。
veth pair 和 patch
兩者都可以作為一個類似虛擬網線的功能連接網橋。
- patch port是連接兩個ovs bridge的專屬,而且性能更好
- veth pair只能用于連接兩個linuxbridge或者linuxbridge與ovs連接
底層實現
創建一個flat網絡與后,會創建一個dhcp的接口,tap-xxxx連接到br-int網橋。
創建一個虛擬機后,同樣的,先創建一個tap設備作為虛擬機的虛擬網卡,然后連接到linuxbridge的qbr網橋上,然后qbr通過一對veth pair連接到br-int網橋。
VLAN 網絡
ovs中是所有虛擬網卡都連接到br-int網橋,而linuxbridge里面則是不同VLAN連接到不同網卡的VLAN網橋。因此物理交換機連接eth1的口也要設置為trunk。
ovs通過flow rule對流過br-int的數據包進行轉發處理,比如打上tag或者去掉tag等。
ovs-ofctl dump-flow查看流規則。
比如br-eth1網橋的流規則如下,這里的in_port編號可以在ovs-ofctl show 查看到。
這里就是說從br-eth1網橋的phy-br-eth1(port=2)端口進來的vlan為1的數據包,修改vlan id為100然后發送出去
br-int網橋的規則同理
這里的tag和VLAN其實是不一樣的,tag是ovs內部進行網絡隔離使用的,在接收到數據包的時候,需要進行vlan的一個映射,Neutron維護VLAN ID的映射關系。
Roting
兩個子網之間的實例通信需要使用路由器進行通信。
創建一個路由器以后,將 子網可以添加到路由器的接口上,接口的IP分別為子網的網關。
br-int網橋上多了兩個接口port,叫qr-xxxx。router也是運行在自己的namesapce里面。
如果路由器需要連接外網,需要綁定一個外部網關,然后router就多了一個接口10.10.10.2,用于連接外網。也就是路由器的qg-xxxx接口。
VxLAN
可以設置VxLAN 的vni也就是tag,需要在配置文件的[ovs]配置tunnel_bridge。
br-int和br-tun是通過patch port連接的,其中patch-tun在br-int上,patch-int在br-tun上。
底層實現
創建網絡以后,dhcp也會通過tap設備連接到br-int上。
實例的虛擬網卡tap設備還是連接到linuxbridge的網橋qbr上,通過veth pair(qvb和qvo)連接到br-int上。
而br-tun上則多了一個vxlan-xxxx的東西,比如用于連接控制節點和計算節點的,制定了VTEP的IP。
此時br-int充當了一個二層交換機,查看flow rule以后可以看到是通過vlan和mac轉發數據包的。
而br-tun的flow-rule才是進行真正轉發數據包的。
Cinder
為運行實例提供穩定持久化的數據塊存儲服務,如創建卷、刪除卷,在實例上掛載和卸載卷。
cinder-api:接收http請求調用cinder-volume
cinder-volume:管理volume服務,管理卷的生命周期
cinder-schedule:通過算法為卷調度一個合適的節點
Swift
Zun
openstack租戶管理_OpenStack容器服務Zun初探與原理分析
Keystone、Neutron以及Kuryr-libnetwork是運行Zun必備的服務。分別提供了身份認證以及網絡的功能支持。
zun-api負責接收api請求進行處理。
zun-compute服務調用container driver進行docker的創建,目前只實現了Docker Driver。
流程步驟
zun/api/controllers/v1/containers.py
進行參數校驗,如用戶是否具有policy權限,網絡、安全組、配額等是否符合。
zun/compute/api.py
先schedule調度一個合適的計算節點,返回host對象,這個功能集成在zun-api里面了。
檢查鏡像是否存在,遠程調用zun-compute的image search方法,其實就是調用了docker search,為了實現快速失敗,避免到計算節點才發現錯誤。
然后遠程調用zun-compute進行后續工作
zun/compute/manager.py
創建卷或者掛載硬盤,然后下載鏡像,創建端口,調用docker啟動容器。
其中調用docker啟動容器的操作的代碼位于zun/container/docker/driver.py,這個部分其實就是對于Docker SDK for python的一個封裝。
如import docker
Kuryr-libnetwork
這個項目的目的是將容器網絡與neutron進行融合,提供接口南向連接neutron,北向連接容器網絡。
開始目的是為了提供Docker與Neutron的連接。將Neutron的網絡服務帶給Docker。隨著容器的發展,容器網絡的發展也出現了分歧。主要分為兩派,一個是Docker原生的CNM(Container Network Model),另一個是兼容性更好的CNI(Container Network Interface)。Kuryr相應的也出現了兩個分支,一個是kuryr-libnetwork(CNM),另一個是kuryr-kubernetes(CNI)。
kuryr-libnetwork是運行在Libnetwork框架下的一個plugin,替換了原有的docker engine,成為一個kuryr就是libnetwork的一個remote-driver,現在是docker的推薦remote-driver。
其實實際上kuryr起了一個http服務,23750端口,提供了libnetwork的所有接口,docker找到以后通過這個與kuryr通信。
kuryr借用了neutron的subnetpool,保證了子網間ip的不重復
實現原理
在上面zun調用docker模塊創建容器的時候,也會進行網絡的配置,就在這里。
先檢查docker網絡是否存在,不存在就創建,創建的docker網絡name就是neutron的uuid,會調用neutron創建一個port,即容器的port是zun創建的,不是kuryr創建的。
然后對于虛擬網卡,會虛擬出一個tap設備,其中容器內部命名空間有一個t_cxxxx的設備,兩個通過veth pair連接起來。然后tap設備會連接到qbr的linuxbridge網橋,隨后網橋通過qvb和qvo的veth連接到br-int集成網橋。
其實哦在那個接一下kuryr的作用就是把neutron的port綁定在容器上。
SDN
軟件定義網絡,是網絡虛擬化的一種實現方式。
主要體現在如下三個方面:
- 轉發與控制分離:SDN具有轉發與控制分離的特點,采用SDN控制器實現網絡拓撲的收集、路由的計算、流表的生成及下發、網絡的管理與控制等功能;而網絡層設備僅負責流量的轉發及策略的執行。通過這種方式可使得網絡系統的轉發面和控制面獨立發展,轉發面向通用化、簡單化發展,成本可逐步降低;控制面可向集中化、統一化發展,具有更強的性能和容量。
- 控制邏輯集中:轉發與控制分離之后,使得控制面向集中化發展。控制面的集中化,使得SDN控制器擁有網絡的全局靜態拓撲,全網的動態轉發表信息,全網絡的資源利用率,故障狀態等。因此,SDN控制器可實現基于網絡級別的統一管理、控制和優化,更可依托全局的拓撲的動態轉發信息幫助實現快速的故障定位和排除,提高運營效率。
- 網絡能力開放化:SDN還有一個重要特征是支持網絡能力開放化。通過集中的SDN控制器實現網絡資源的統一管理、整合以及虛擬化后,采用規范化的北向接口為上層應用提供按需分配的網絡資源及服務,進而實現網絡能力開放。這樣的方式打破了現有網絡對業務封閉的問題,是一種突破性的創新。
OpenFlow
OpenFlow是一種網上通信協議,屬于數據鏈路層,允許控制器直接訪問和操作網絡設備的轉發平面,借此改變數據包的走向。這些設備可以是物理設備也可以是虛擬交換機。
轉發平面基于流的方式轉發。
網絡設備會維護若干個流表,數據流只按照流表進行轉發,而流表的生成與維護都是控制器做的事。
這里的流表不僅僅是IP五元組,而是還有這一些關鍵詞和執行動作等。在實際使用中可以根據需要的粒度進行一個限制,比如如果想要粗粒度,只需要設置IP就好了,不需要設置其他的參數比如端口之類的。
OF 1.0
一個流表包含一個流表項的集合(包頭域)、活動計數器以及一個操作集。
所有流過交換機的數據包都需要進行流表的匹配,如果匹配成功,執行相應的操作,如果沒有匹配上,將其轉發到控制器,由控制器決定如何處理這個數據包。
這個包頭域會根據數據包的信息進行相應的匹配,使用的是12元組
- 入口:交換機端口
- 以太網源端口
- 以太網源IP
- 以太網類型:VLAN是0x8100,ARP是0x0806、IP是0x0800
- VLAN ID
- VLAN優先級
- 源IP
- 目的IP
- IP協議:TCP6、UDP7、ICMP1
- IP ToS位
- 源端口
- 目的端口
活動計數器包含有多個計數器,會根據匹配的數據包進行一個更新。
- 流表:流表的匹配數據包數
- 流表項flow:每一項接收的數據包字節數、數據包個數、延遲等
- 端口:每個端口接收到的數據包數、字節數、轉發的數據包數、字節數等
- 隊列:轉發的數據包數
操作集規定了對匹配成功數據包進行什么操作,可以有0到多個操作,如果沒有相應操作,丟棄數據包。
一些基本的操作有:
- ALL:給除了入口的所有接口發出數據包
- Controller:發給控制器
- INN PORT:往入口發送數據包
- DROP:丟棄
還有一些可選的
- NORMAL:傳統交換機的正常轉發
- FLOOD:泛洪至除了入口以外的所有出口
- 修改域:這個功能比較厲害,它可以對數據包里面的信息進行修改隨后轉發,比如可以修改VLAN ID、VLAN優先級、源IP和目的IP、源端口和目的端口等信息
OF 1.3
主要添加了多級流表(流水線),增加了一些多控制器的支持,增加了對數據包處理的動作
一個流表項的組成
- 匹配域
- 優先級
- 計數器
- 超時時間
- 指令
- cookie
將原來的動作變更為指令,然后允許數據包在流表之間跳轉。
不同于1.0的十二元組,這里其實有四十多個字段,但是一般大多數用不到,主要也就是那么些。
有一個指令是go-to-table:轉向另一個流表
如果沒有這個,會有以下幾個動作
- output:指定端口轉發出去
- drop:丟棄
- push-tag或者pop-tag:對VLAN等ID進行處理
- setField:識別匹配的字段,并且可以修改
- change-TTL:修改數據包的TTL值
同時 還需要支持table-miss,就是說如果沒有匹配成功,進行什么樣的動作,轉給控制器還是丟棄。
Django
概述
Django是一個開放源代碼的web應用框架,使用python寫成。本身是基于MVC模型的,實際采用了MTV的框架模式,即模型(Model)、模(Templates)板和視圖(Views)。其中:
- 模型:數據存取曾,處理所有與數據有關的事務,比如如何存取數據、驗證有效性等
- 模板:表現層,比如如何在頁面或者其他類型文檔中顯示
- 視圖:業務邏輯層,處理數據存儲以及調用模板的邏輯
簡單流程:
用戶通過瀏覽器向我們的服務器發起一個請求(request),這個請求會去訪問視圖函數:
a.如果不涉及到數據調用,那么這個時候視圖函數直接返回一個模板也就是一個網頁給用戶。
b.如果涉及到數據調用,那么視圖函數調用模型,模型去數據庫查找數據,然后逐級返回。
視圖函數把返回的數據填充到模板中空格中,最后返回網頁給用戶。
Django的主要目的是簡單快捷的開發數據驅動的網站,強調代碼復用,多個組件可以很方便的以插件形式服務與整個框架。
有以下幾個特點:
MVC和MTV
MVC:
核心思想是解耦
- model:對數據庫的底層封裝
- view:向用戶展示結果
- controller:核心,處理請求、獲取數據、返回結果
MVT:
- model:與數據庫進行交互
- views:核心,接受請求,獲取處理數據,返回結果
- template:呈現內容到瀏覽器上
views里處理業務邏輯比如登錄驗證、數據處理等
model里面不需要編寫一句sql,ORM會自動轉為sql去執行。
數據庫里每一行數據就是一個對象,每一個表是一個集合,python用列表表示這個集合
template呈現頁面,用css和js渲染html等
還需要一個 URL 分發器,它的作用是將一個個 URL 的頁面請求分發給不同的 View 處理,View 再調用相應的 Model 和 Template,MTV 的響應模式如下所示
和Flask Tornado的區別
Django提供了更多的組件支持,讓開發變得更加方便。
比如
- ORM對象關系映射,對數據庫進行操作,不需要編寫sql語句
- Admin管理后臺
- 模板
- 表單
- 認證權限
- 緩存
- session機制
Flask輕量級輕在它本身是一個內核,其他功能都需要擴展實現。比如可以引入其他模塊實現ORM,也沒有默認數據庫,但是可以自行配置使用mysq或者nosql,性能比Django好。依賴于Werkzurg WSGI路由模塊和jinja2模板。
對于路由的匹配
- Django使用過urls.py種對路由進行字符串的匹配,選擇匹配的views.py函數進行業務處理
- Flask則是使用裝飾器給一個函數配置一個路由,然后進行處理
Tornado
功能少而精,非阻塞式異步設計方式。
- iostream:對非阻塞式socket進行封裝
- ioloop:對IO多路復用進行封裝,實現單例
Tornado是一個使用python開發的全棧式的web框架和一部網絡庫,使用非阻塞式IO,可以處理數以萬計的開放鏈接,常用于long polling、web sockets和其他需要維護長連接應用的選擇。
主要分為四個部分
- Web框架(RequestHandler,用于創建Web的基類支持各種類)
- 實現HTTP的客戶端和服務器端(HTTPServer、AsyncHTTPClient)
- 異步網絡庫(IOLoop、IOStream)
- 協程庫(tornado.gen),使得異步調用代碼可以更好編寫
tornado的性能比django和flask好就是因為其底層io處理機制是根本不同。
- tornado、gevent、syncio、aiohttp:事件循環+協程
- django、flask:
Django請求生命周期
瀏覽器輸入網址,發送請求到服務器
匹配路由
url經過uWSGI->WSGI,然后經過中間件的處理,在urls.py路由映射中找到一個匹配的路由,從上到下依次匹配,匹配一個就可以停了
視圖處理
匹配到url以后,跳轉到對應的視圖函數進行相應的業務處理,比如操作數據庫等
返回響應
先經過中間件對返回的數據再進行處理,然后返回相應的頁面文件,由瀏覽器渲染以后顯示給用戶,同時將模板內容填充到html空白處。
一些額外的
在匹配路由的時候,有兩種方式,是CBV、FBV
- FBV(function base views):一個url對應一個視圖函數
- CBV(class base views):一個url對應一個類,會根據請求的方法調用對應的函數
CBV,url匹配成功后會自動去找dispatch方法,然后Django會通過dispatch反射的方式找到類中對應的方法并執行,類方法執行完成以后,返回的結果回傳給dispatch()
對應類的話如下所示
常見的web應用程序
框架組件
RestFramework
面向資源是REST最明顯的特征,資源是一種看待服務器的方式,將服務器看作是由很多離散的資源組成。每個資源是服務器上一個可命名的抽象概念。因為資源是一個抽象的概念,所以它不僅僅能代表服務器文件系統中的一個文件、數據庫中的一張表等等具體的東西,可以將資源設計的要多抽象有多抽象,只要想象力允許而且客戶端應用開發者能夠理解。
可以使用URI統一資源標識符標記一個服務器的資源,通過不同的http方法對資源進行相應的操作。這里的資源可以是一個文本文件、視頻、圖片等。
符合REST架構設計的API就是restful api。
繼承APIView
@api_view([‘POST’],[‘GET’])
在這個類中,傳入的參數是rest framework的request實例,不是django的httprequest。
可以返回rest framework的resonse,而不是HttpResponse。
傳入的請求可以進行一些認證
可以指定解析器Parser對傳入的數據進行解析,如JSON、Form等解析。
一些功能模塊
認證、權限和頻率
dispatch()方法中進行一個判定。
認證和權限需要檢查request.user和request.auth是否合法,是否允許請求。
緩存機制
網站訪問量過大的時候,響應速度可能會大大降低,出現卡死的狀況,可以使用緩存解決這類問題。
緩存是將一個請求的響應內容保存到內存、數據庫、文件或者高速緩存系統(memcached),如果接下來一段時間再次來同一個請求,就不需要執行相應過程,只需要讀取內存或者高速緩存系統就可以了。
Django提供5種緩存方式:
- Memcached:一個高性能的分布式內存對象緩存系統,用于動態網站,減輕數據庫負載。適合在內存中緩存數據和對象減少讀取數據庫的次數,適合超大型網站
- 數據庫緩存:將緩存的信息存儲在網站數據庫的緩存表中,適合中型網站
- 文件系統緩存:緩存的信息以文本文件的格式保存下來,適合中小型網站
- 本地內存緩存:默認保存緩存的方式,緩存存放于內存中,僅用于測試
- 虛擬緩存:Django內置的虛擬緩存,實際上只是提供一個接口,不實際緩存數據,用于測試
WSGI,uwsgi,uWSGI
WSGI
是python定義實現的一個web服務器和web應用程序之間交互的一個接口,是一種規范,描述定義了服務器和應用程序之間通信的規范。
WSGI包括server和applicatioon兩部分。
其中server負責接收客戶端請求,把request轉發給application,接收application的response返回給客戶端。
WSGI其實是一種server和application解耦的規范,有多個實現server的服務器,也有多個可以實現WSGI application的框架,可以自由組合。比如uWSGI、Gunicorn就是實現了WSGI server,而Django和Flask則實現了WSGI application的框架,可以自由組合,比如uWSGI+Django。
WSGI除了監聽端口進行解析http,還有流量轉發和管理application進程。一般WSGI內置的WSGI server都是單進程,一次只能處理一個請求,而通用的比如gunicorn或者uwsgi都是pre fork模型,會有一個master進行監聽,啟動多個slave(一個slave就是一個WSGI application)處理請求。
uwsgi
也是一種協議,用于定義傳輸信息的類型,可以和nginx等代理服務器通信
uWSGI
是一個web服務器,實現了WSGI協議、uwsgi和HTTP協議,把接收到的HTTP協議轉為支持的網絡協議,比如可以轉為WSGI協議,然后python可以直接使用。
比如可以使用nginx處理靜態內容,使用uWSGI處理動態內容。
對于Django和Flask其實自己本身帶有一個簡單的WSGI server,一般用于服務器調試,生產環境下建議使用其他的,比如manage.py runserver就是啟動一個WSGI,只用于本地開發,生產環境建議nginx+uwsgi+django
請求的生命周期
中間件的作用和應用場景
介于request和response中間對數據處理的一個流程,用于全局范圍改變django的輸入和輸出,中間件就是在視圖函數執行之前或者之后可以執行額外的操作。
比如
中間件的五個方法:
- process_request:請求進來,進行認證等
- process_view:路由匹配后得到視圖函數
- process_exception:異常的時候執行
- process_template_responseprocess:渲染模板的時候執行
- process_response:請求有響應的時候執行
這五個方法分別大概以下功能
中間件
- process_request(request):收到request以后,按照settings.py文件中的中間件順序依次執行,如果返回None,則繼續,如果返回HttpResponse,就返回不繼續了,也就是報錯了
- process_view(request, view_func, view_args, view_kwargs):執行完上一步的方法以后,在url里面找到對應的視圖函數,然后獲取到相應參數,在執行視圖函數之前執行這一步。如果返回為None,則繼續執行這個方法剩下的操作,如果返回HttpResponse,不執行這個方法和視圖函數,繼續后面的函數
- process_exception(request, exception):如果執行視圖函數出錯,按照settings.py中的中間件順序,倒序執行這個方法,如果返回None,就繼續上一個方法的process_exception方法,如果返回HttpResponse,則不會被調用。也就是說,如果沒有響應,就說明報錯,倒序一級一級報錯,如果有返回值說明還是正常的,就繼續往下執行后面兩個函數
- process_template_response(request, response):response是視圖或者某一中間件的返回,只有response實現了render才能執行,所有中間件的這個函數執行完了,調用render()方法
- process_response(request, response):在視圖函數執行完以后執行,必須有響應HttpResponse
默認的中間件
有幾個默認配置的中間件,主要功能如下
- django.middleware.security.SecurityMiddleware:防止xss腳本過濾的安全改進
- django.contrib.sessions.middleware.SessionMiddleware:開始session會話支持,可以使用session,不開啟就不能session保存數據
- django.contrib.messages.middleware.MessageMiddleware:提供cookie的功能支持
- django.middleware.common.CommonMiddleware:用來重寫URL。如果APPEND_SLASH為True,那么URL末尾沒有斜杠或者沒有找到對應匹配的時候,會自動添加末尾斜杠;PREPEND_WWW為True則會將沒有www.開頭的URL重定向到同樣的www.開頭的URL路由
- django.middleware.csrf.CsrfViewMiddleware:跨站請求偽造就不說了
- django.contrib.auth.middleware.AuthenticationMiddleware:收到request后,可以對user對象添加相應的HttpRequest屬性,表示當前用戶身份呢
django中的csrf實現機制
基于django的ajax發送請求給后端如何攜帶token
CSRF跨站請求偽造,是一種對網站的惡意利用、竊取網站用戶信息制造惡意請求。
為了防護這類攻擊,在用戶提交表單的時候,表單中會自動加入一個叫csrfmiddlewaretoken的隱藏控件,后臺也保存有這個控件的值,當請求到達后端時,服務器會檢查這個值,如果匹配則進行后續處理,否則不處理。
原理:
但是XSRF防護一般只適用于POST請求,不能防護GET,因為GET一般是制度性是訪問網頁資源,不會涉及資源的更新和修改等操作。
在前端的form表單中添加{% csrf_token %}即可
如果不想使用csrf防護,前端取消這個模板語法,后端在對應視圖函數簽名添加一個裝飾器@csrf_execpt即可。如果只刪除前者不修改后者,訪問會報錯403未授權。
如果需要對整個網站取消CSRF,settings.py里面刪除這個中間件即可。
ajax請求的csrf解決方法
在POST請求中設置請求參數csrfmiddlewaretoken,否則會認為是惡意請求,需要獲取這個控件的值。
如下
為什么不使用django的runserver部署(runserver和uWSGI的區別)
WSGI Server 運行,主要在測試和開發中使用,并且 runserver 開啟的方式也是單進程 。
Kubernetes
k8s是為容器而生的一個可以指容器的編排管理工具,主要應用于云原生領域。
主要提供了以下幾種功能:
- 服務發現與調度
- 負載均衡
- 服務自愈
- 服務彈性擴容
- 橫向擴容
- 存儲卷掛載
集群主要由Master節點和Node節點組成。
Master節點是集群控制節點,接收控制命令進行具體執行,主要包括kube-controller-manager和kube-scheduler和etcd,前者負責管理所有資源對象、維護集群狀態(故障檢測和自動擴展等);后者負責資源調度,按照相應策略將Pod調度到對應的機器上,主要包括kube-proxy代理pod網絡定期從etcd獲取service信息相應執行、kubelet作為agent接受分配pods任務和管理容器定期獲取容器數據傳給kube-apiserver;etcd則負責保存整個集群的狀態。
是自動化容器操作的開源平臺,主要包括:部署、調度和節點集群間擴展
具體功能:
- 自動化容器部署和復制
- 實時彈性收縮容器規模
- 容器編排成組并提供負載均衡
- 調度,決定容器在哪個節點運行
什么是容器編排
可以使用某種工具配置完成一組容器以及相應的資源如網絡、CPU等資源的定義、配置、創建、刪除等管理工作。
服務配置
Master節點部署
- controller manager:負責容器編排,可以通過restful api給api server發起請求,獲取集群內所有對象的信息,當檢測到一些故障的時候可以進行相應的干預。Controller一般包括:Namespace Controller、Node Controller、Service Controller、Token Controller等
- api server:對外提供api,接受請求
- scheduler:接收來自api-server發來的請求,準備床創建Pod任務,之后會檢索出符合這個Pod的Node節點,中選擇一個合適的進行調度創建
- etcd:k8s沒有使用單獨的數據庫,而是使用etcd作為數據存儲。因為k8s中數據是隨時會變化的,比如用戶提交了一個任務、創建新Node、節點宕機等都需要對數據庫進行操作,然后同時新的變化也需要讓各個服務能夠感知到。etcd的其中一個特性就是可以調用api監聽到相應的數據i需改情況,有修改etcd會自動推送到客戶端,有什么通知scheduler和controller manager只需要把消息放在etcd里面就行了不需要挨個通知
Node節點部署
- kubelet:相當于agent,負責維護容器的生命周期、卷和網絡的管理。通過api-server監聽scheduler是否有pod綁定事件,有的話就從etcd獲取相應信息創建Pod。同時進行Pod的監視,定期將狀態或發生的事件告知給其他各個組件
- kube-proxy:負責微Service提供集群內的服務發現和負載均衡。是一個守護進程,以Watcher的方式不斷監控Pod,如果有什么變動比如IP變了,就會修改相應的規則策略,比如IP變了會修改相應的iptables。之后負載均衡的時候就會根據proxy制定下發的策略進行實現了。
- Networking
- Volume Plugin
- Container Runtime:負責運行容器的軟件,支持多個Docker、Container等任何實現接口的
Pod
Pod是k8s最基本的操作單元,包含一個或多個相關的容器,是最小部署單元,其實代表一個集群中運行的一個進程。
一個Pod可以被一個容器化的環境看成應用層的邏輯宿主機,一個Pod內的多個容器通常緊密耦合,在Node上被創建、啟動或者銷毀,每個Pod還運行一個特殊的Volume掛載卷,使得容器間數據通信比較方便。
同一個Pod的使用localhost就可以通信,共享一下五種資源:
- 進程號命名空間:Pod中不同應用程序可以看到其他應用程序的進程ID
- 網絡命名空間:多個容器訪問同一個IP和端口范圍,每個Pod共享一個IP
- UTS命名空間:共享一個主機名。使用Pod名作為主機名
- 進程間通信命名空間:可以使用SystemV IC和POSIX消息隊列通信
- Volume:共享存儲卷,各個容器可以訪問
Pod控制器
kubernetes的控制器
稱為工作負載,用于實現管理Pod的中間層,確保Pod的運行時符合預期的,以及出現故障后應該采取什么策略措施,比如重啟或者重建。
Controller在集群上運行和管理各個Pod
Pod控制器實現Pod的運維,伸縮等
控制器類型
- ReplicaSet(RS):保證一定數量的Pod運行,并且監控Pod的狀態,當出現故障的時候,會進行重啟,如果重啟失敗則會重新創建。(也就是自愈機制)
- Deployment:工作在ReplicaSet之上,管理無狀態應用,是最好用的控制器,提供有滾動更新和回滾的功
- DaemonSet:確保集群中的每一個節點只運行特定的Pod副本,常用于實現系統級后臺任務;服務是無特性的,必須要守護進程
- StatefulSet:管理有應用
- Job:一旦完成任務就會立刻退出,不需要重啟或者中間(一次性)
- CronJob:周期任務,不需要手動執行,自動定期運行
Replica Set和Replica Controller的區別
功能都差不多,都是保證一定數量的Pod的運行,不同之處在于兩者對于Pods的復制策略不同。
前者使用基于集合的選擇器,后者使用基于權限的選擇器。
后者允許通過標簽鍵值進行選擇。
Set是更好的,可以對多個標簽進行選擇匹配
云控制器的理解
最初目的是使得云服務商的代碼和k8s的核心代碼獨立解耦,使得云控制器可以和k8s的組件(controller manager或者api等)一起使用,也可以作為插件在k8s中使用。其設計是基于插件機制的,所以很容易和k8s集成
- 節點控制器:從云服務提供商獲取到集群中運行的節點信息,并且對節點初始化。
-
- 以云服務特定區域/低于標簽初始化
-
- 以云服務特定的實例詳細信息(如類型和規格等)初始化
-
- 獲取節點的網絡地址和hostname
-
- 檢查狀態,看節點是否還存在于云服務中,如果不存在在k8s中也將其刪除
- 卷控制器:在創建卷比如AWS的卷的時候,添加相應的標簽,用戶不需要手動添加標簽了。因為只有處于同一個區域地區才有用,用標簽保證吧
- 路由控制器:負責在云服務中配置相應的路由,使得k8s中的容器可以相互之間進行通信,只適用于谷歌計算引擎集群
- 服務控制器:監聽服務的創建、刪除和修改事件。比如說基于當前的k8s狀態配置云負載均衡服務,可以保證服務后端始終是最新狀態
支持四種服務類型
- Cluster IP(集群IP):啟動多個集群內的Pod通信服務,相當于是一個內部通信,可以進行內部調試之類的
- Node Port(節點端口):將主機上的隨機端口流量準發到路由器的隨機端口去。有些缺點:外部不能用locahhost、每次Pod啟動IP都會變,無法設置DNS
- LoadBalancer(負載均衡):
- Ingress:是一個規則集合,作為集群的入口點,主要負責將入站鏈接配置為可達的URL,負載平衡流量以及基于名稱的對外提供虛擬服務器功能。其實像一個API服務,對外提供API進行調用
什么是Headless Service
又叫無頭服務,是一種特殊的服務類型。
ClusterIP是None,運行時不會給分配IP,可以通過查詢Server的DNS獲得所有Server和Pod的地址信息,可以根據自己的需求決定使用哪個Server
一般結合StatefulSet來部署有狀態的應用,比如kafka集群,mysql集群,zk集群等
服務發現
k8s使用兩種方式進行服務發現:
- 環境變量:創建一個Pod以后,kubelet會在Pod中注入集群內所有Service相關環境變量,要求Service先于Pod創建
- DNS:通過claster add-on方式創建kubeDNS對集群Service進行服務發現
CNI
Container Network Interface,容器網絡接口式Linux容器網絡配置的一組標準和庫,可以根據這些開發自己的容器網絡插件。只專注于容器網絡連接和容器銷毀時的資源釋放,支持大量不同的網絡模式。
kuryr-libnetwork
四層、七層負載均衡
- 二層負載均衡:基于MAC地址
- 三層負載均衡:基于IP地址
- 四層負載均衡:基于IP+端口號
- 七層負載均衡:基于URL等應用層信息
網絡模型
每個Pod都有一個獨立IP,不管是否運行在一個Node上的容器都可以通過IP直接訪問
由docker0實際分配IP;內部看到的IP與端口和外部一致;同一個Pod內不同容器共享網絡可以通過localhost通信,相當于一個虛擬機中的多個進程。
Docker
一些參考
Docker 核心技術與實現原理
Docker進階之Cgroup介紹
CSDN的云原生入門技能樹/容器(docker)/安裝docker
NameSpace
這個在linux知識點章節有
當一個容器運行時,會創建一系列namespace,使用命名空間將容器間進行隔離。
- IPC命名空間(進程間通信):將消息隊列分離出來
- 進程命名空間:命名空間內的虛擬PID可能會和外面的pid重復,會映射到哇面的另一個pid
- 網絡命名空間:用來隔離網絡資源,可以虛擬出網卡,而且后臺進程可以運行在不同的命名空間的相同端口
- 掛載命名空間:可以將掛載點與系統分離
- UTS命名空間:獨立出主機名和網絡信息服務
- 用戶命名空間:不同空間可以存在相同ID的用戶
命名空間的缺點:
隔離不徹底,因為還是共享宿主機的操作系統和內核,有可能通過容器的某些操作可以直接影響到宿主機(給應用暴露的攻擊面太大)
有的資源沒法進行命名空間隔離,比如修改容器的時間宿主機的時間也會修改。
Cgroups
可以對程序使用的資源進行限制??梢韵拗艭PU、內存、磁盤讀寫速率、網絡帶寬等系統資源。Linux使用文件系統來實現Cgroups,cgroup是內核提供的分組化管理的功能和接口。
有如下幾個特點:
- API以偽文件系統的方式實現,用戶態程序可以通過操作文件實現Cgroups的組織管理
- 單元細粒度可以精確到線程級別,可以創建銷毀Cgroup,實現資源再分配和管理
- 所有的資源管理以子系統的方式實現,接口統一
- 子任務剛創建的時候和父任務的Cgroups一致
cgroups是內核附加在程序上的一系列鉤子,通過程序運行時對資源的調度觸發相應的鉤子以達到資源追蹤和限制的目的。
提供以下幾個功能:
- 資源限制,對任務使用的資源進行限制,比如限制了內存以后,超過內存限制會報錯OOM
- 優先級分配,通過分配CPU時間片和IO帶寬大小,相當于控制了任務運行優先級。
- 資源統計:可以統計資源使用情況,比如CPU使用時間,內存使用量
- 任務控制:可以對任務掛起、恢復
有幾個概念:
- task:任務,指一個進程或者線程
- cgroup:控制組,按照某種資源控制情況劃分的任務組,包含有一個或者多個子系統,一個任務可以加入某個cgroup,也可以從一個cgroup遷移到另一個cgroup
- subsystem(子系統):每個子系統就是一個資源控制器,比如CPU子系統控制CPU使用的時間
- hierarchy(層級):層級由一系列cgroup以樹狀結構排列,每層綁定對應子系統實現資源控制
有幾個規則關系:
- 同一個層級可以附加多個子系統,比如一個cgroup可以有CPU和Memory子系統
- 一個子系統可以附加到多個層級,當且僅當目標層級只有唯一一個子系統,比如如果B層級有內存子系統,不能附加CPU子系統了
- 每次新建一個層級的時候,所有任務默認加入到這個初始cgroup
- frok、clone自身創建的子任務默認與原任務在一個cgroup里,子任務允許被移動到不同的cgroups
子系統
有如下
- blkio:為塊設備設置輸入、輸出限制,比如物理驅動設備(磁盤、USB等)
- cpu:設置CPU使用時間,用于調度程序
- cpuset:多處理器系統可以為任務分配相應的處理器和內存
- cpuset:對cpu資源的使用情況生成報告
- memory:對任務的任務使用量進行限制,同時生成內存使用情況的報告
- devices:開啟或者管理cgroup里任務對設備的訪問
- freezer:掛起或者恢復cgroup的任務
- perf_event:使得cgroup里的任務可以進行性能測試
- net_cls:標記網絡數據包,允許流量控制程序識別cgroup里生成的數據包
比如對于cpu子系統,/sys/fs/cgroup/cpu里面有一些控制組的文件,創建一個控制組文件夾以后,會出現一些文件。
限制一個指定進程的cpu使用配額
先添加進程PID,然后添加具體配置
在創建容器時,daemon會在單獨掛載的子系統控制目錄下創建一個對應的docker控制組,然后再創建一個容器控制組名為Docker ID,容器的所有進程好都會寫在這個的tasks里面,在對應的控制文件里寫相應的資源配額信息。
對于內存如果超過cgroup最大限制以后,如果設置了OOM Control(內存超限控制),進程就會收到OOM信號然后結束,否則會一直掛起,直到其他進程釋放對應的內存資源。
cgroup.procs可以對線程進行配置,寫入線程組中的第一個進程的PID,也就是把相關線程都加到cgroup里面
驅動
docker的daemon進程通過接收相應的API請求,然后將去轉為使用相應的系統調用,從而創建和管理容器。docker將這些系統調用抽象為了一些操作接口方便調用,包括:容器執行驅動、volume存儲驅動以及鏡像存儲驅動三種。
execdriver
對namesapce、cgroups等進行了二次封裝,是默認的libcontainer庫
volumedriver
負責volume的增刪改查,屏蔽不同驅動帶來的差異,為上層提供一個統一的接口調用。
graphdriver
和鏡像有關,維護一個一組與鏡像曾對應的目錄,以及相應的元數據,用戶對鏡像的操作會對應位對這些目錄文件以及元數據的增刪改查,屏蔽不同文件存儲實現帶來的差異。
docker daemon的主要啟動步驟如下三步
- 啟動API Server,工作在宿主機的HOST上
- 使用NewDaemon方法創建daemon對象,保存信息和處理業務邏輯
- 將API Server和daemon綁定起來,接受處理client的請求
啟動一個容器的步驟
從client 到 daemon,docker run舉例
最后創建容器的時候會使用到libcontainer。
在準備好配置文件以后,會創建一個container對象,這里面存儲的是配置信息的對象,然后才是有Container邏輯容器對象,libcontainer會根據信息創建相應的namespace,以及cgroups,然后創建docker。
基礎
什么是Docker
Docker是一個容器化平臺,以容器的形式將應用程序和其環境依賴打包,可以在任何Docker環境中無縫銜接運行
Docker與虛擬機的不同
Docker不是虛擬化,依賴于實際實現基于容器的虛擬話或者操作系統級虛擬化的其他工具,最初使用LXC驅動,后來移動到libcontainer重命名為runc。
專注于應用程序容器內自動部署應用程序,應用程序指打包和運行一個應用程序,操作系統容器則設計為運行多個進程,如虛擬機。
特點:
虛擬機底層是需要使用hypervisor來模擬硬件虛擬化的,可以虛擬出一個操作系統所需的各種硬件資源比如cpu、ram、disk,在其上安裝目標操作系統。
Docker和普通進程的區別
當一個程序代碼被編譯為二進制文件,然后這個文件被加載到內存然后得到cpu的使用權時,這個程序就變成了一個正在運行的進程,會去對寄存器進行操作,對堆棧進行操作以實現相應功能。
而容器則是通過約束和修改進程的動態表現,給其創造一個邊界。cgroups主要用來進行約束,而namespace則主要用來創造邊界
鏡像
什么是Docker鏡像和Docker容器
鏡像就是容器的源代碼,用于創建容器。
Docker容器包含了應用程序和其所需的以來,作為操作系統的一個獨立進程運行的。
鏡像保存在/var/lib/docker/
Docker鏡像分層
是基于UnionFs(聯合文件系統),這是一種分層的、輕量級的而且高性能的文件系統,支持對文件系統的修改作為一次提交來一層一層提交,而且可以把不同目錄掛載到同一個虛擬文件系統下。
實際上一次會加載多個文件系統,但是使用上只能看到一個文件系統,聯合加載會把每層文件系統疊加起來,最終的文件系統就會包含所有的底層文件和目錄。
實質上就是一層一層的文件系統。
所有docker都初始于一個基礎鏡像層,增加或者修改內容的時候,會在這個基礎上新增一層。
舉個例子
如果需要基于ubuntu18.04配置新鏡像,第一層就是ubuntu18.04
我們需要安裝python,第二層就是python包
我們需要安裝一個安全補丁,這個補丁就是第三層
Docker鏡像是只讀的,在啟動容器的時候,會把一個可寫層加到鏡像頂部,就是容器層,容器層。下面都是鏡像層。
bootfs
boot file system。有一個bootloader和kernel,loader負責加載kernel,linux剛系統的時候就會加載bootfs,docker的底層就是bootfs,bootfs加載完成以后,內核就在內存里了,內存的使用權就由bootfs交給內核了,然后就可以卸載bootfs了。
rootfs,root file system在bootfs之上,包含有linux中的/dev、/proc、/bin、/etc等標準目錄和文件,這個其實就是各種linux發行版。
對于精簡os,rootfs只需要包含最基本的命令、工具和程序庫,因為可以直接使用底層kernel,所以只需要rootfs,而對于不同的發行版,bootfs都是差不多的,所以可以公用
容器分層、寫時復制(copy-on-write)
容器和鏡像的區別其實就是容器會在最頂層有一個可寫層,對于容器的所有寫操作都會記錄在這里面,容器刪除的話這個可寫層就刪除了。
每個容器都有著自己的可寫層,所以多個容器可以共享一個鏡像
對于多個鏡像來說,鏡像的分層會出現公用的情況,所以不能單純看docker images列出來的大小。
多個容器之間可以共享鏡像,在啟動容器的時候不必單獨復制一份,而是把所有鏡像層以只讀的形式掛載到一個掛載點上,在最上層加一個可讀寫的容器層,在沒有更改的時候所有容器共享一份數據,只有對文件系統進行修改的時候,會把相應的內容寫到可讀寫層里,并且隱藏只讀層里的老版本文件,用心的覆蓋,減少了鏡像對磁盤空間的占用和容器的啟動時間。
DockerFile常見指令
Dockerfile 是一個用來構建鏡像的文本文件,文本內容包含了一條條構建鏡像所需的指令和說明。
- FROM:指定基礎鏡像,基于什么鏡像
- LABEL:指定鏡像的標簽
- RUN:運行指定命令
- CMD:啟動容器的時候執行什么命令,類似自啟動,如果有多個指令,只執行最后一條
- ENTRYPOINT:類似于CMD指令,但是不會被覆蓋掉,
build
docker build -t {name}:{tag} .
最后的點就表示上下文路徑。
docker在構造的時候會使用到本機文件,比如復制進去,他會在這個上下文路徑中去尋找,把里面的文件都打包進去,不寫就默認Dockerfile所在的目錄。
步驟時:
- 發送請求個Server端,然后創建臨時目錄讀取Dockerfile
- 根據解析的結果遍歷命令,將其分發給不同模塊進行執行。
- parser會給每個指令創建一個臨時容器,在臨時容器中執行當前指令,然后使用commit生成一個鏡像層
- 所有指令對應的層的集合,就是build的而結果。最后一次commit生成的鏡像ID就是最后的鏡像ID
Dockerfile的COPY和ADD
COPY指的是從上下文目錄中復制文件到容器里的指定路徑。
ADD也是復制文件。
COPY的SRC只能是本地文件。
而且ADD會自動解壓一些格式的文件gzip等,不解壓的時候tar就不能復制進去,會使得構建失敗。
ADD還可以給容器里添加遠程文件。但是建議用curl或者wget命令下載文件,因為ADD的話會給鏡像加一層,導致體積變大臃腫。
Docker容器的狀態
運行、退出、已暫停、重新啟動
網絡
docker的網絡部分已經被獨立為libnetwork了。使用的CNM(容器網絡羋姓)提供了多種網絡接口可以使用。
daemon通過調用libnetwork對外提供的API完成網絡的創建和管理,libcontainer則使用CNM。libcontainer里面提供了五種網絡驅動可以使用,有三個核心組件。
- 沙盒:包含一個容器網絡棧信息,可以對容器接口、路由和DNS等進行管理,具體實現可以是namespace
- 端點:一個端點可以加入一個沙盒和一個網絡,具體實現有veth pair、ovs內部端口等
- 網絡:是一組可以互聯互通的端點,具體實現可以是lunexbridge、vlan,一個網絡可以有多個端點
驅動:
- bridge:默認配置,會將創建出來的容器連接到docker0網橋上,和外界通信使用NAT,復雜場景下使用會有不少限制
- host:不會為容器創建網絡協議棧,不會有獨立的namespace,處于宿主機的網絡環境中,共用宿主機的namesapace,如IP、網卡端口等信息。較好的解決了與外界通信的地址轉換問題,但是降低了容器和宿主機或者容器之間的網絡隔離問題,網絡資源的使用可能會出現競爭沖突。
- overlay:vxlan比如大型云計算虛擬化環境里的SDN Controller模式
- remote:這個欸有實現真正的網絡服務,而是會調用用戶所提供的網絡驅動插件,比如Kuryr-libnetwork。根據libnetwork提供的標準實現相應的接口就可以找daemon進行注冊使用
- null:容器有自己的namespace,只有lo網卡,需要用戶自己配置網卡IP等信息,優點時配置使用非常自由,缺點就是 不配置不能使用,使用要求高。
docker0本質上就是網橋,而且這里的網橋概念可以相當于時交換機,可以為連接在其上的設備進行數據幀的轉發,容器的網卡eth0通過veth連接到docker0網橋上,不需要配置IP地址就可以進行數據幀的轉發。
Docker的網絡類型
有4種類型,bridge、host、container以及none
bridge:默認情況創建容器是使用網橋bridge去連接,docker0,容器之間通過網橋通信。對外通信的話網橋會與宿主機進行一個IP轉換。這里的虛擬連接也是使用類似與虛擬網線的那樣,就虛擬機里面的eth0連接到網橋對應的veth。如果需要外部訪問進來,得通過端口映射,然后使用宿主機的端口和這個映射的端口進行訪問
host:會默認使用宿主機的網絡,不會有自己的命名空間虛擬機網卡之類的,在網絡上是沒辦法隔離的。使用了host就只能指定端口了,訪問進來的話用宿主機的IP和這個映射的端口
container:指定新創建的容器和已有的容器共享namespace,同樣不會自己創建網卡和IP地址,和這個特定容器一起共享,進程間通過lo通信。
none:會創建一個命名空間 ,但是ip、虛擬網卡之類的都得自己配置,很不好用不方便。但是隔離安全性非常好
docker常用命令
- docker images:查看鏡像
- docker rm / rmi:刪除容器/鏡像
- docker pull / push:拉取/上傳鏡像
- docker ps -a:列出所有鏡像,不帶參數只列出開機鏡像
- docker cp {path} {docker_id}:{docker_path}:復制文件到指定容器的路徑下,也可以返回來復制出文件
- docker run -d --name container cirros -p 5000:5050:啟動容器
面經
OpenStack
一些命令行
- 命令啟動虛擬機:openstack server create --flaver {name} --nic net-id={network-id} --security-group {id} {name}
命令上傳下載鏡像:opensatck image create --disk-format qcow2 --container-format bare --public --file {local-path} {name}
glance image-download --file {id} {local-path} - 修改實例狀態為活動狀態:比如有時候實例會卡住,比如刪除的時候因為某些故障卡住了,處于deleting狀態一直卡住,這個操作可以使其變為活動狀態,然后他大概會進入error,然后就可以正常刪除了。nova restet-state --active {server-id}
- 指定集群和節點:–availiable-zone {region}:{host},指定在哪個集群的哪個節點創建
- 查看實例的日志和控制臺url:openstack console log {id}和openstack console url show {id}
OpenStack中計算節點上虛擬機默認保存路徑在哪?
在計算節點的/var/lib/nova/instances目錄。
OpenStack中Glance鏡像的默認保存路徑在哪?
控制節點的/var/lib/glance/images目錄。
OpenStack中計算節點的集成橋(br-int)的作用是什么?
對通過實例的流量進行標記和取消標記的操作,VLAN網絡。
OpenStack中計算節點的隧道橋(br-tun)的作用是什么?
隧道橋(br-tun)根據 OpenFlow 規則將 VLAN 標記的流量從集成網橋轉換為隧道 ID。
隧道橋允許不同網絡的實例彼此進行通信。隧道有利于封裝在非安全網絡上傳輸的流量,它支持兩層網絡,即 GRE 和 VXLAN。
OpenStack中外部OVS橋(br-ex)的作用是什么?
用于轉發來往的網絡流量,允許實例與外部網絡進行通信
OpenStack和Docker區別
OpenStack是一個成熟的完整的云資源管理的平臺??梢越y一管理平臺中的計算、存儲以及網絡等資源,提供對于虛擬機的調度管理。底層默認使用kvm和qemu去管理虛擬機,但是同樣可以管理容器。
而docker則是負責管理計算機中需要與其他進程相互隔離的容器,容器的開銷相比于虛擬機更少,本質上就是一個操作系統進程,可以將自己的環境或者應用程序部署在容器里,然后打包分發之類的,可以實現快速部署。
docker應該和虛擬機是一個類別的。
OpenStack和kvm的區別
OpenStack本質只是一個云管理平臺,不具備比如虛擬化這種功能。虛擬化是通過系統底層實現的hypervisior(kvm、qemu和Xen、virtual box等)實現的。
如果沒有OpenStack同樣可以使用其他工具來管理kvm,比如libvirt提供的vish-manager。
kvm和xen區別
kvm是一個內核提供的輕量級虛擬化管理解決方案,需要虛擬化支持(Intel-VT或者AMD-V)。
Xen是運行支持的Xen內核,可以在系統上使用qemu模擬多個虛擬機。
kvm可以使用通常的linux調度和內存管理
Xen更新以后需要重新編譯內核,而kvm只需要重新安裝模塊即可,更加精簡,避免出錯的幾率。
Neutron
vlan和vxlan的區別
vlan的vni是12位:1-4096,vxlan是24位,最大可以一一千六百多萬個vni。
vxlan是基于隧道技術在屋里三層網絡中模擬二層網絡,對二層數據包的一個封裝,使用UDP在三層網絡進行一個轉發。
vlan只能用于廣播域的隔離,但是解決不了IP地址和MAC的重疊問題,vxlan可以做到不同租戶獨立組網,通信地址分配以及多租戶的地址沖突問題可以解決。
交換機一個端口對應一個物理設備以及一個MAC地址,但是現在雖然一個端口還是連接一個物理機,但是可能會連接到多個虛擬機,傳統交換機收到一個數據幀以后,根據vlan和目的MAC找到相應端口,將數據包轉發出去。同時交換機會記住學習這個MAC記錄,但是交換機內存是有限的,隨著虛擬化的實現,網絡中的MAC地址非常多的,交換機如果不足以支持的話,可能會移除,然后就不能正常工作,如果找不到MAC會進行flood,增加其他網絡設備的負擔和網絡擁塞。
使用VxLAN,以太幀會被VTEP封裝在UDP里面,一個VTEP可以被一個物理及的所有虛擬機使用,對于交換機,他看到的只是VTEP之間傳遞信息,并看不到實際虛擬機傳遞信息。所以交換機只需要記錄VTEP的信息即主機信息即可。
Docker
命名空間
- 網絡命名空間:網絡設備端口等
- 進程命名空間:進程編號
- 用戶命名空間:用戶和用戶組
- 掛載命名空間:掛載點、文件系統
- UTS命名空間:主機名和域名
- IPC命名空間:信號量、消息隊列共享內存
總結
以上是生活随笔為你收集整理的面经 - OpenStack(Docker、Django、K8S、SDN)知识点的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: php判断是否夏令时,关于php:时区和
- 下一篇: Shell 脚本 一键安装/一键卸载/一