日韩av黄I国产麻豆传媒I国产91av视频在线观看I日韩一区二区三区在线看I美女国产在线I麻豆视频国产在线观看I成人黄色短片

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

Docker源码分析(四):Docker Daemon之NewDaemon实现

發布時間:2025/4/5 编程问答 38 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Docker源码分析(四):Docker Daemon之NewDaemon实现 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

http://www.infoq.com/cn/articles/docker-source-code-analysis-part4

1. 前言

Docker的生態系統日趨完善,開發者群體也在日趨龐大,這讓業界對Docker持續抱有極其樂觀的態度。如今,對于廣大開發者而言,使用Docker這項技術已然不是門檻,享受Docker帶來的技術福利也不再是困難。然而,如何探尋Docker適應的場景,如何發展Docker周邊的技術,以及如何彌合Docker新技術與傳統物理機或VM技術的鴻溝,已經占據Docker研究者們的思考與實踐。

本文為《Docker源碼分析》第四篇——Docker Daemon之NewDaemon實現,力求幫助廣大Docker愛好者更多得理解Docker 的核心——Docker Daemon的實現。

2. NewDaemon作用簡介

在Docker架構中有很多重要的概念,如:graph,graphdriver,execdriver,networkdriver,volumes,Docker containers等。Docker在實現過程中,需要將以上實體進行統一化管理,而Docker Daemon中的daemon實例就是設計用來完成這一任務的實體。

從源碼的角度,NewDaemon函數的執行完成了Docker Daemon創建并加載daemon的任務,最終實現統一管理Docker Daemon的資源。

3. NewDaemon源碼分析內容安排

本文從源碼角度,分析Docker Daemon加載過程中NewDaemon的實現,整個分析過程如下圖:

圖3.1 Docker Daemon中NewDaemon執行流程圖

由上圖可見,Docker Daemon中NewDaemon的執行流程主要包含12個獨立的步驟:處理配置信息、檢測系統支持及用戶權限、配置工作路徑、加載并配置graphdriver、創建Docker Daemon網絡環境、創建并初始化graphdb、創建execdriver、創建daemon實例、檢測DNS配置、加載已有container、設置shutdown處理方法、以及返回daemon實例。

下文會在NewDaemon的具體實現中,以12節分別分析以上內容。

4. NewDaemon具體實現

在《Docker源碼分析》系列第三篇中,有一個重要的環節:使用goroutine加載daemon對象并運行。在加載并運行daemon對象時,所做的第一個工作即為:

d, err := daemon.NewDaemon(daemonCfg, eng)

該部分代碼分析如下:

  • 函數名:NewDaemon;
  • 函數調用具體實現所處的包位置:./docker/daemon;
  • 函數具體實現源文件:./docker/daemon/daemon.go;
  • 函數傳入實參:daemonCfg,定義了Docker Daemon運行過程中所需的眾多配置信息;eng,在mainDaemon中創建的Engine對象實例;
  • 函數返回類型:d,具體的Daemon對象實例;err,錯誤狀態。

進入./docker/daemon/daemon.go中NewDaemon的具體實現,代碼如下:

func NewDaemon(config *Config, eng *engine.Engine) (*Daemon, error) {daemon, err := NewDaemonFromDirectory(config, eng)if err != nil {return nil, err}return daemon, nil }

可見,在實現NewDaemon的過程中,通過NewDaemonFromDirectory函數來實現創建Daemon的運行環境。該函數的實現,傳入參數以及返回類型與NewDaemon函數相同。下文將大篇幅分析NewDaemonFromDirectory的實現細節。

4.1. 應用配置信息

在NewDaemonFromDirectory的實現過程中,第一個工作是:如何應用傳入的配置信息。這部分配置信息服務于Docker Daemon的運行,并在Docker Daemon啟動初期就初始化完畢。配置信息的主要功能是:供用戶自由配置Docker的可選功能,使得Docker的運行更貼近用戶期待的運行場景。

配置信息的處理包含4部分:

  • 配置Docker容器的MTU;
  • 檢測網橋配置信息;
  • 查驗容器通信配置;
  • 處理PID文件配置。

4.1.1. 配置Docker容器的MTU

config信息中的Mtu應用于容器網絡的最大傳輸單元(MTU)特性。有關MTU的源碼如下:

if config.Mtu == 0 { config.Mtu = GetDefaultNetworkMtu()

可見,若config信息中Mtu的值為0的話,則通過GetDefaultNetworkMtu函數將Mtu設定為默認的值;否則,采用config中的Mtu值。由于在默認的配置文件./docker/daemon/config.go(下文簡稱為默認配置文件)中,初始化時Mtu屬性值為0,故執行GetDefaultNetworkMtu。

GetDefaultNetworkMtu函數的具體實現位于./docker/daemon/config.go:

func GetDefaultNetworkMtu() int {if iface, err := networkdriver.GetDefaultRouteIface(); err == nil {return iface.MTU}return defaultNetworkMtu }

GetDefaultNetworkMtu的實現中,通過networkdriver包的GetDefaultRouteIface方法獲取具體的網絡設備,若該網絡設備存在,則返回該網絡設備的MTU屬性值;否則的話,返回默認的MTU值defaultNetworkMtu,值為1500。

4.1.2. 檢測網橋配置信息

處理完config中的Mtu屬性之后,馬上檢測config中BridgeIface和BridgeIP這兩個信息。BridgeIface和BridgeIP的作用是為創建網橋的任務”init_networkdriver”提供參數。代碼如下:

if config.BridgeIface != "" && config.BridgeIP != "" {return nil, fmt.Errorf("You specified -b & --bip, mutually exclusive options. Please specify only one.") }

以上代碼的含義為:若config中BridgeIface和BridgeIP兩個屬性均不為空,則返回nil對象,并返回錯誤信息,錯誤信息內容為:用戶同時指定了BridgeIface和BridgeIP,這兩個屬性屬于互斥類型,只能至多指定其中之一。而在默認配置文件中,BridgeIface和BridgeIP均為空。

4.1.3. 查驗容器通信配置

檢測容器的通信配置,主要是針對config中的EnableIptables和InterContainerCommunication這兩個屬性。EnableIptables屬性的作用是啟用Docker對iptables規則的添加功能;InterContainerCommunication的作用是啟用Docker container之間互相通信的功能。代碼如下:

if !config.EnableIptables && !config.InterContainerCommunication {return nil, fmt.Errorf("You specified --iptables=false with --icc= false. ICC uses iptables to function. Please set --icc or --iptables to true.") }

代碼含義為:若EnableIptables和InterContainerCommunication兩個屬性的值均為false,則返回nil對象以及錯誤信息。其中錯誤信息為:用戶將以上兩屬性均置為false,container間通信需要iptables的支持,需設置至少其中之一為true。而在默認配置文件中,這兩個屬性的值均為true。

4.1.4. 處理網絡功能配置

接著,處理config中的DisableNetwork屬性,以備后續在創建并執行創建Docker Daemon網絡環境時使用,即在名為”init_networkdriver”的job創建并運行中體現。

config.DisableNetwork = config.BridgeIface == DisableNetworkBridge

由于config中的BridgeIface屬性值為空,另外DisableNetworkBridge的值為字符串”none”,因此最終config中DisableNetwork的值為false。后續名為”init_networkdriver”的job在執行過程中需要使用該屬性。

4.1.5. 處理PID文件配置

處理PID文件配置,主要工作是:為Docker Daemon進程運行時的PID號創建一個PID文件,文件的路徑即為config中的Pidfile屬性。并且為Docker Daemon的shutdown操作添加一個刪除該Pidfile的函數,以便在Docker Daemon退出的時候,可以在第一時間刪除該Pidfile。處理PID文件配置信息的代碼實現如下:

if config.Pidfile != "" {if err := utils.CreatePidFile(config.Pidfile); err != nil {return nil, err}eng.OnShutdown(func() {utils.RemovePidFile(config.Pidfile)}) }

代碼執行過程中,首先檢測config中的Pidfile屬性是否為空,若為空,則跳過代碼塊繼續執行;若不為空,則首先在文件系統中創建具體的Pidfile,然后向eng的onShutdown屬性添加一個處理函數,函數具體完成的工作為utils.RemovePidFile(config.Pidfile),即在Docker Daemon進行shutdown操作的時候,刪除Pidfile文件。在默認配置文件中,Pidfile文件的初始值為” /var/run/docker.pid”。

以上便是關于配置信息處理的分析。

4.2. 檢測系統支持及用戶權限

初步處理完Docker的配置信息之后,Docker對自身運行的環境進行了一系列的檢測,主要包括三個方面:

  • 操作系統類型對Docker Daemon的支持;
  • 用戶權限的級別;
  • 內核版本與處理器的支持。

系統支持與用戶權限檢測的實現較為簡單,實現代碼如下:

if runtime.GOOS != "linux" {log.Fatalf("The Docker daemon is only supported on linux") } if os.Geteuid() != 0 {log.Fatalf("The Docker daemon needs to be run as root") } if err := checkKernelAndArch(); err != nil {log.Fatalf(err.Error()) }

首先,通過runtime.GOOS,檢測操作系統的類型。runtime.GOOS返回運行程序所在操作系統的類型,可以是Linux,Darwin,FreeBSD等。結合具體代碼,可以發現,若操作系統不為Linux的話,將報出Fatal錯誤日志,內容為“Docker Daemon只能支持Linux操作系統”。

接著,通過os.Geteuid(),檢測程序用戶是否擁有足夠權限。os.Geteuid()返回調用者所在組的group id。結合具體代碼,也就是說,若返回不為0,則說明不是以root用戶的身份運行,報出Fatal日志。

最后,通過checkKernelAndArch(),檢測內核的版本以及主機處理器類型。checkKernelAndArch()的實現同樣位于./docker/daemon/daemon.go。實現過程中,第一個工作是:檢測程序運行所在的處理器架構是否為“amd64”,而目前Docker運行時只能支持amd64的處理器架構。第二個工作是:檢測Linux內核版本是否滿足要求,而目前Docker Daemon運行所需的內核版本若過低,則必須升級至3.8.0。

4.3. 配置工作路徑

配置Docker Daemon的工作路徑,主要是創建Docker Daemon運行中所在的工作目錄。實現過程中,通過config中的Root屬性來完成。在默認配置文件中,Root屬性的值為”/var/lib/docker”。

在配置工作路徑的代碼實現中,步驟如下:

(1) 使用規范路徑創建一個TempDir,路徑名為tmp;

(2) 通過tmp,創建一個指向tmp的文件符號連接realTmp;

(3) 使用realTemp的值,創建并賦值給環境變量TMPDIR;

(4) 處理config的屬性EnableSelinuxSupport;

(5) 將realRoot重新賦值于config.Root,并創建Docker Daemon的工作根目錄。

4.4. 加載并配置graphdriver

加載并配置存儲驅動graphdriver,目的在于:使得Docker Daemon創建Docker鏡像管理所需的驅動環境。Graphdriver用于完成Docker容器鏡像的管理,包括存儲與獲取。

4.4.1. 創建graphdriver

這部分內容的源碼位于./docker/daemon/daemon.go#L743-L790,具體細節分析如下:

graphdriver.DefaultDriver = config.GraphDriver driver, err := graphdriver.New(config.Root, config.GraphOptions)

首先,為graphdriver包中的DefaultDriver對象賦值,值為config中的GraphDriver屬性,在默認配置文件中,GraphDriver屬性的值為空;同樣的,屬性GraphOptions也為空。然后通過graphDriver中的new函數實現加載graph的存儲驅動。

創建具體的graphdriver是相當重要的一個環節,實現細節由graphdriver包中的New函數來完成。進入./docker/daemon/graphdriver/driver.go中,實現步驟如下:

第一,遍歷數組選擇graphdriver,數組內容為os.Getenv(“DOCKER_DRIVER”)和DefaultDriver。若不為空,則通過GetDriver函數直接返回相應的Driver對象實例,若均為空,則繼續往下執行。這部分內容的作用是:讓graphdriver的加載,首先滿足用戶的自定義選擇,然后滿足默認值。代碼如下:

for _, name := range []string{os.Getenv("DOCKER_DRIVER"), DefaultDriver} {if name != "" {return GetDriver(name, root, options)} }

第二,遍歷優先級數組選擇graphdriver,優先級數組的內容為依次為”aufs”,”brtfs”,”devicemapper”和”vfs”。若依次驗證時,GetDriver成功,則直接返回相應的Driver對象實例,若均不成功,則繼續往下執行。這部分內容的作用是:在沒有指定以及默認的Driver時,從優先級數組中選擇Driver,目前優先級最高的為“aufs”。代碼如下:

for _, name := range priority {driver, err = GetDriver(name, root, options)if err != nil {if err == ErrNotSupported || err == ErrPrerequisites || err == ErrIncompatibleFS {continue}return nil, err}return driver, nil }

第三,從已經注冊的drivers數組中選擇graphdriver。在”aufs”,”btrfs”,”devicemapper”和”vfs”四個不同類型driver的init函數中,它們均向graphdriver的drivers數組注冊了相應的初始化方法。分別位于./docker/daemon/graphdriver/aufs/aufs.go,以及其他三類driver的相應位置。這部分內容的作用是:在沒有優先級drivers數組的時候,同樣可以通過注冊的driver來選擇具體的graphdriver。

4.4.2. 驗證btrfs與SELinux的兼容性

由于目前在btrfs文件系統上運行的Docker不兼容SELinux,因此當config中配置信息需要啟用SELinux的支持并且driver的類型為btrfs時,返回nil對象,并報出Fatal日志。代碼實現如下:

// As Docker on btrfs and SELinux are incompatible at present, error on both being enabled if config.EnableSelinuxSupport && driver.String() == "btrfs" { return nil, fmt.Errorf("SELinux is not supported with the BTRFS graph driver!") }

4.4.3. 創建容器倉庫目錄

Docker Daemon在創建Docker容器之后,需要將容器放置于某個倉庫目錄下,統一管理。而這個目錄即為daemonRepo,值為:/var/lib/docker/containers,并通過daemonRepo創建相應的目錄。代碼實現如下:

daemonRepo := path.Join(config.Root, "containers") if err := os.MkdirAll(daemonRepo, 0700); err != nil && !os.IsExist(err) {return nil, err }

4.4.4. 遷移容器至aufs類型

當graphdriver的類型為aufs時,需要將現有graph的所有內容都遷移至aufs類型;若不為aufs,則繼續往下執行。實現代碼如下:

if err = migrateIfAufs(driver, config.Root); err != nil { return nil, err }

這部分的遷移內容主要包括Repositories,Images以及Containers,具體實現位于./docker/daemon/graphdriver/aufs/migrate.go。

func (a *Driver) Migrate(pth string, setupInit func(p string) error) error {if pathExists(path.Join(pth, "graph")) {if err := a.migrateRepositories(pth); err != nil {return err}if err := a.migrateImages(path.Join(pth, "graph")); err != nil {return err}return a.migrateContainers(path.Join(pth, "containers"), setupInit)}return nil }

migrate repositories的功能是:在Docker Daemon的root工作目錄下創建repositories-aufs的文件,存儲所有與images相關的基本信息。

migrate images的主要功能是:將原有的image鏡像都遷移至aufs driver能識別并使用的類型,包括aufs所規定的layers,diff與mnt目錄內容。

migrate container的主要功能是:將container內部的環境使用aufs driver來進行配置,包括,創建container內部的初始層(init layer),以及創建原先container內部的其他layers。

4.4.5. 創建鏡像graph

創建鏡像graph的主要工作是:在文件系統中指定的root目錄下,實例化一個全新的graph對象,作用為:存儲所有標記的文件系統鏡像,并記錄鏡像之間的關系。實現代碼如下:

g, err := graph.NewGraph(path.Join(config.Root, "graph"), driver)

NewGraph的具體實現位于./docker/graph/graph.go,實現過程中返回的對象為Graph類型,定義如下:

type Graph struct {Root stringidIndex *truncindex.TruncIndexdriver graphdriver.Driver }

其中Root表示graph的工作根目錄,一般為”/var/lib/docker/graph”;idIndex使得檢索字符串標識符時,允許使用任意一個該字符串唯一的前綴,在這里idIndex用于通過簡短有效的字符串前綴檢索鏡像與容器的ID;最后driver表示具體的graphdriver類型。

4.4.6. 創建volumesdriver以及volumes graph

在Docker中volume的概念是:可以從Docker宿主機上掛載到Docker容器內部的特定目錄。一個volume可以被多個Docker容器掛載,從而Docker容器可以實現互相共享數據等。在實現volumes時,Docker需要使用driver來管理它,又由于volumes的管理不會像容器文件系統管理那么復雜,故Docker采用vfs驅動實現volumes的管理。代碼實現如下:

volumesDriver, err := graphdriver.GetDriver("vfs", config.Root, config.GraphOptions) volumes, err := graph.NewGraph(path.Join(config.Root, "volumes"), volumesDriver)

主要完成工作為:使用vfs創建volumesDriver;創建相應的volumes目錄,并返回volumes graph對象。

4.4.7. 創建TagStore

TagStore主要是用于存儲鏡像的倉庫列表(repository list)。代碼如下:

repositories, err := graph.NewTagStore(path.Join(config.Root, "repositories-"+driver.String()), g)

NewTagStore位于./docker/graph/tags.go,TagStore的定義如下:

type TagStore struct {path stringgraph *GraphRepositories map[string]Repositorysync.MutexpullingPool map[string]chan struct{}pushingPool map[string]chan struct{} }

需要闡述的是TagStore類型中的多個屬性的含義:

  • path:TagStore中記錄鏡像倉庫的文件所在路徑;
  • graph:相應的Graph實例對象;
  • Repositories:記錄具體的鏡像倉庫的map數據結構;
  • sync.Mutex:TagStore的互斥鎖
  • pullingPool :記錄池,記錄有哪些鏡像正在被下載,若某一個鏡像正在被下載,則駁回其他Docker Client發起下載該鏡像的請求;
  • pushingPool:記錄池,記錄有哪些鏡像正在被上傳,若某一個鏡像正在被上傳,則駁回其他Docker Client發起上傳該鏡像的請求;

4.5. 創建Docker Daemon網絡環境

創建Docker Daemon運行環境的時候,創建網絡環境是極為重要的一個部分,這不僅關系著容器對外的通信,同樣也關系著容器間的通信。

在創建網絡時,Docker Daemon是通過運行名為”init_networkdriver”的job來完成的。代碼如下:

if !config.DisableNetwork {job := eng.Job("init_networkdriver")job.SetenvBool("EnableIptables", config.EnableIptables)job.SetenvBool("InterContainerCommunication", config.InterContainerCommunication)job.SetenvBool("EnableIpForward", config.EnableIpForward)job.Setenv("BridgeIface", config.BridgeIface)job.Setenv("BridgeIP", config.BridgeIP)job.Setenv("DefaultBindingIP", config.DefaultIp.String())if err := job.Run(); err != nil {return nil, err} }

分析以上源碼可知,通過config中的DisableNetwork屬性來判斷,在默認配置文件中,該屬性有過定義,卻沒有初始值。但是在應用配置信息中處理網絡功能配置的時候,將DisableNetwork屬性賦值為false,故判斷語句結果為真,執行相應的代碼塊。

首先創建名為”init_networkdriver”的job,隨后為該job設置環境變量,環境變量的值如下:

  • 環境變量EnableIptables,使用config.EnableIptables來賦值,為true;
  • 環境變量InterContainerCommunication,使用config.InterContainerCommunication來賦值,為true;
  • 環境變量EnableIpForward,使用config.EnableIpForward來賦值,值為true;
  • 環境變量BridgeIface,使用config.BridgeIface來賦值,為空字符串””;
  • 環境變量BridgeIP,使用config.BridgeIP來賦值,為空字符串””;
  • 環境變量DefaultBindingIP,使用config.DefaultIp.String()來賦值,為”0.0.0.0”。

設置完環境變量之后,隨即運行該job,由于在eng中key為”init_networkdriver”的handler,value為bridge.InitDriver函數,故執行bridge.InitDriver函數,具體的實現位于./docker/daemon/networkdriver/bridge/dirver.go,作用為:

  • 獲取為Docker服務的網絡設備的地址;
  • 創建指定IP地址的網橋;
  • 啟用Iptables功能并配置;
  • 另外還為eng實例注冊了4個Handler,如 ”allocate_interface”, ”release_interface”, ”allocate_port”,”link”。

4.5.1. 創建Docker網絡設備

創建Docker網絡設備,屬于Docker Daemon創建網絡環境的第一步,實際工作是創建名為“docker0”的網橋設備。

在InitDriver函數運行過程中,首先使用job的環境變量初始化內部變量;然后根據目前網絡環境,判斷是否創建docker0網橋,若Docker專屬網橋已存在,則繼續往下執行;否則的話,創建docker0網橋。具體實現為createBridge(bridgeIP),以及createBridgeIface(bridgeIface)。

createBridge的功能是:在host主機上啟動創建指定名稱網橋設備的任務,并為該網橋設備配置一個與其他設備不沖突的網絡地址。而createBridgeIface通過系統調用負責創建具體實際的網橋設備,并設置MAC地址,通過libcontainer中netlink包的CreateBridge來實現。

4.5.2. 啟用iptables功能

創建完網橋之后,Docker Daemon為容器以及host主機配置iptables,包括為container之間所需要的link操作提供支持,為host主機上所有的對外對內流量制定傳輸規則等。代碼位于./docker/daemon/networkdriver/bridge/driver/driver.go#L133-L137,如下:

// Configure iptables for link support if enableIPTables {if err := setupIPTables(addr, icc); err != nil {return job.Error(err)} }

其中setupIPtables的調用過程中,addr地址為Docker網橋的網絡地址,icc為true,即為允許Docker容器間互相訪問。假設網橋設備名為docker0,網橋網絡地址為docker0_ip,設置iptables規則,操作步驟如下:

(1) 使用iptables工具開啟新建網橋的NAT功能,使用命令如下:

iptables -I POSTROUTING -t nat -s docker0_ip ! -o docker0 -j MASQUERADE

(2) 通過icc參數,決定是否允許container間通信,并制定相應iptables的Forward鏈。Container之間通信,說明數據包從container內發出后,經過docker0,并且還需要在docker0處發往docker0,最終轉向指定的container。換言之,從docker0出來的數據包,如果需要繼續發往docker0,則說明是container的通信數據包。命令使用如下:

iptables -I FORWARD -i docker0 -o docker0 -j ACCEPT

(3) 允許接受從container發出,且不是發往其他container數據包。換言之,允許所有從docker0發出且不是繼續發向docker0的數據包,使用命令如下:

iptables -I FORWARD -i docker0 ! -o docker0 -j ACCEPT

(4) 對于發往docker0,并且屬于已經建立的連接的數據包,Docker無條件接受這些數據包,使用命令如下:

iptables -I FORWARD -o docker0 -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT

4.5.3. 啟用系統數據包轉發功能

在Linux系統上,數據包轉發功能是被默認禁止的。數據包轉發,就是當host主機存在多塊網卡的時,如果其中一塊網卡接收到數據包,并需要將其轉發給另外的網卡。通過修改/proc/sys/net/ipv4/ip_forward的值,將其置為1,則可以保證系統內數據包可以實現轉發功能,代碼如下:

if ipForward {// Enable IPv4 forwardingif err := ioutil.WriteFile("/proc/sys/net/ipv4/ip_forward", []byte{'1', '\n'}, 0644); err != nil {job.Logf("WARNING: unable to enable IPv4 forwarding: %s\n", err)} }

4.5.4. 創建DOCKER鏈

在網橋設備上創建一條名為DOCKER的鏈,該鏈的作用是在創建Docker container并設置端口映射時使用。實現代碼位于./docker/daemon/networkdriver/bridge/driver/driver.go,如下:

if err := iptables.RemoveExistingChain("DOCKER"); err != nil {return job.Error(err) } if enableIPTables {chain, err := iptables.NewChain("DOCKER", bridgeIface)if err != nil {return job.Error(err)}portmapper.SetIptablesChain(chain) }

4.5.5. 注冊Handler至Engine

在創建完網橋,并配置完基本的iptables規則之后,Docker Daemon在網絡方面還在Engine中注冊了4個Handler,這些Handler的名稱與作用如下:

  • allocate_interface:為Docker container分配一個專屬網卡;
  • realease_interface:釋放網絡設備資源;
  • allocate_port:為Docker container分配一個端口;
  • link:實現Docker container間的link操作。

由于在Docker架構中,網絡是極其重要的一部分,因此Docker網絡篇會安排在《Docker源碼分析》系列的第六篇。

4.6. 創建graphdb并初始化

Graphdb是一個構建在SQLite之上的圖形數據庫,通常用來記錄節點命名以及節點之間的關聯。Docker Daemon使用graphdb來記錄鏡像之間的關聯。創建graphdb的代碼如下:

graphdbPath := path.Join(config.Root, "linkgraph.db") graph, err := graphdb.NewSqliteConn(graphdbPath) if err != nil {return nil, err }

以上代碼首先確定graphdb的目錄為/var/lib/docker/linkgraph.db;隨后通過graphdb包內的NewSqliteConn打開graphdb,使用的驅動為”sqlite3”,數據源的名稱為” /var/lib/docker/linkgraph.db”;最后通過NewDatabase函數初始化整個graphdb,為graphdb創建entity表,edge表,并在這兩個表中初始化部分數據。NewSqliteConn函數的實現位于./docker/pkg/graphdb/conn_sqlite3.go,代碼實現如下:

func NewSqliteConn(root string) (*Database, error) {……conn, err := sql.Open("sqlite3", root)……return NewDatabase(conn, initDatabase) }

4.7. 創建execdriver

Execdriver是Docker中用來執行Docker container任務的驅動。創建并初始化graphdb之后,Docker Daemon隨即創建了execdriver,具體代碼如下:

ed, err := execdrivers.NewDriver(config.ExecDriver, config.Root, sysInitPath, sysInfo)

可見,在創建execdriver的時候,需要4部分的信息,以下簡要介紹這4部分信息:

  • config.ExecDriver:Docker運行時中指定使用的exec驅動類別,在默認配置文件中默認使用”native”,也可以將這個值改為”lxc”,則使用lxc接口執行Docker container內部的操作;
  • config.Root:Docker運行時的root路徑,默認配置文件中為”/var/lib/docker”;
  • sysInitPath:系統上存放dockerinit二進制文件的路徑,一般為”/var/lib/docker/init/dockerinit-1.2.0”;
  • sysInfo:系統功能信息,包括:容器的內存限制功能,交換區內存限制功能,數據轉發功能,以及AppArmor安全功能等。

在執行execdrivers.NewDriver之前,首先通過以下代碼,獲取期望的目標dockerinit文件的路徑localPath,以及系統中dockerinit文件實際所在的路徑sysInitPath:

localCopy := path.Join(config.Root, "init", fmt.Sprintf(" dockerinit-%s", dockerversion.VERSION)) sysInitPath := utils.DockerInitPath(localCopy)

通過執行以上代碼,localCopy為”/var/lib/docker/init/dockerinit-1.2.0”,而sysyInitPath為當前Docker運行時中dockerinit-1.2.0實際所處的路徑,utils.DockerInitPath的實現位于?./docker/utils/util.go。若localCopy與sysyInitPath不相等,則說明當前系統中的dockerinit二進制文件,不在localCopy路徑下,需要將其拷貝至localCopy下,并對該文件設定權限。

設定完dockerinit二進制文件的位置之后,Docker Daemon創建sysinfo對象,記錄系統的功能屬性。SysInfo的定義,位于./docker/pkg/sysinfo/sysinfo.go,如下:

type SysInfo struct {MemoryLimit boolSwapLimit boolIPv4ForwardingDisabled boolAppArmor bool }

其中MemoryLimit通過判斷cgroups文件系統掛載路徑下是否均存在memory.limit_in_bytes和memory.soft_limit_in_bytes文件來賦值,若均存在,則置為true,否則置為false。SwapLimit通過判斷memory.memsw.limit_in_bytes文件來賦值,若該文件存在,則置為true,否則置為false。AppArmor通過host主機是否存在/sys/kernel/security/apparmor來判斷,若存在,則置為true,否則置為false。

執行execdrivers.NewDriver時,返回execdriver.Driver對象實例,具體代碼實現位于?./docker/daemon/execdriver/execdrivers/execdrivers.go,由于選擇使用native作為exec驅動,故執行以下的代碼,返回最終的execdriver,其中native.NewDriver實現位于./docker/daemon/execdriver/native/driver.go:

return native.NewDriver(path.Join(root, "execdriver", "native"), initPath)

至此,已經創建完畢一個execdriver的實例ed。

4.8. 創建daemon實例

Docker Daemon在經過以上諸多設置以及創建對象之后,整合眾多內容,創建最終的Daemon對象實例daemon,實現代碼如下:

daemon := &Daemon{repository: daemonRepo,containers: &contStore{s: make(map[string]*Container)},graph: g,repositories: repositories,idIndex: truncindex.NewTruncIndex([]string{}),sysInfo: sysInfo,volumes: volumes,config: config,containerGraph: graph,driver: driver,sysInitPath: sysInitPath,execDriver: ed,eng: eng, }

以下分析Daemon類型的屬性:

屬性名

作用

repository

部署所有Docker容器的路徑

containers

用于存儲具體Docker容器信息的對象

graph

存儲Docker鏡像的graph對象

repositories

存儲Docker鏡像元數據的文件

idIndex

用于通過簡短有效的字符串前綴定位唯一的鏡像

sysInfo

系統功能信息

volumes

管理host主機上volumes內容的graphdriver,默認為vfs類型

config

Config.go文件中的配置信息,以及執行產生的配置DisableNetwork

containerGraph

存放Docker鏡像關系的graphdb

driver

管理Docker鏡像的驅動graphdriver,默認為aufs類型

sysInitPath

系統dockerinit二進制文件所在的路徑

execDriver

Docker Daemon的exec驅動,默認為native類型

eng

Docker的執行引擎Engine類型實例

4.9. 檢測DNS配置

創建完Daemon類型實例daemon之后,Docker Daemon使用daemon.checkLocaldns()檢測Docker運行環境中DNS的配置, checkLocaldns函數的定義位于./docker/daemon/daemon.go,代碼如下:

func (daemon *Daemon) checkLocaldns() error {resolvConf, err := resolvconf.Get()if err != nil {return err}if len(daemon.config.Dns) == 0 && utils.CheckLocalDns(resolvConf) {log.Infof("Local (127.0.0.1) DNS resolver found in resolv.conf and containers can't use it. Using default external servers : %v", DefaultDns)daemon.config.Dns = DefaultDns}return nil }

以上代碼首先通過resolvconf.Get()方法獲取/etc/resolv.conf中的DNS服務器信息。若本地DNS 文件中有127.0.0.1,而Docker container不能使用該地址,故采用默認外在DNS服務器,為8.8.8.8,8.8.4.4,并將其賦值給config文件中的Dns屬性。

4.10. 啟動時加載已有Docker containers

當Docker Daemon啟動時,會去查看在daemon.repository,也就是在/var/lib/docker/containers中的內容。若有存在Docker container的話,則讓Docker Daemon加載這部分容器,將容器信息收集,并做相應的維護。

4.11. 設置shutdown的處理方法

加載完已有Docker container之后,Docker Daemon設置了多項在shutdown操作中需要執行的handler。也就是說:當Docker Daemon接收到特定信號,需要執行shutdown操作時,先執行這些handler完成善后工作,最終再實現shutdown。實現代碼如下:

eng.OnShutdown(func() {if err := daemon.shutdown(); err != nil {log.Errorf("daemon.shutdown(): %s", err)}if err := portallocator.ReleaseAll(); err != nil {log.Errorf("portallocator.ReleaseAll(): %s", err)}if err := daemon.driver.Cleanup(); err != nil {log.Errorf("daemon.driver.Cleanup(): %s", err.Error())}if err := daemon.containerGraph.Close(); err != nil {log.Errorf("daemon.containerGraph.Close(): %s", err.Error())} })

可知,eng對象shutdown操作執行時,需要執行以上作為參數的func(){……}函數。該函數中,主要完成4部分的操作:

  • 運行daemon對象的shutdown函數,做daemon方面的善后工作;
  • 通過portallocator.ReleaseAll(),釋放所有之前占用的端口資源;
  • 通過daemon.driver.Cleanup(),通過graphdriver實現unmount所有layers中的掛載點;
  • 通過daemon.containerGraph.Close()關閉graphdb的連接。

4.12. 返回daemon對象實例

當所有的工作完成之后,Docker Daemon返回daemon實例,并最終返回至mainDaemon()中的加載daemon的goroutine中繼續執行。

5. 總結

本文從源碼的角度深度分析了Docker Daemon啟動過程中daemon對象的創建與加載。在這一環節中涉及內容極多,本文歸納總結daemon實現的邏輯,一一深入,具體全面。

在Docker的架構中,Docker Daemon的內容是最為豐富以及全面的,而NewDaemon的實現而是涵蓋了Docker Daemon啟動過程中的絕大部分。可以認為NewDaemon是Docker Daemon實現過程中的精華所在。深入理解NewDaemon的實現,即掌握了Docker Daemon運行的來龍去脈。

轉載于:https://www.cnblogs.com/davidwang456/articles/9579675.html

總結

以上是生活随笔為你收集整理的Docker源码分析(四):Docker Daemon之NewDaemon实现的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。

五月婷婷综合在线视频 | 麻豆精品在线视频 | 99久久精品免费看国产麻豆 | 超碰人人在线 | av片一区二区 | 九九热在线视频免费观看 | 色天天中文 | 一区二区三区三区在线 | 久久99视频免费 | 国产精品一区二区三区视频免费 | 亚洲免费av片 | 国产专区免费 | 黄污视频网站大全 | 国产精品久久久久久久午夜 | 国产精品一区二区三区四区在线观看 | 亚洲午夜久久久综合37日本 | 欧美日韩一区二区三区免费视频 | 99热在线精品观看 | 免费看的黄色小视频 | 激情文学丁香 | 亚洲爱av | 久久激情综合 | 久久亚洲综合国产精品99麻豆的功能介绍 | 国产综合小视频 | 中文字幕中文 | 青青河边草免费直播 | 91在线影视 | 狠狠狠色丁香婷婷综合久久五月 | 亚洲3级| 四虎永久免费 | 欧美亚洲成人免费 | 色美女在线 | 高清视频一区二区三区 | 日韩黄在线观看 | 国产成人精品午夜在线播放 | 国产一区二区电影在线观看 | 亚洲国产精久久久久久久 | 国产午夜精品一区二区三区四区 | 国产专区精品 | 国产专区视频 | 51久久夜色精品国产麻豆 | 国产黄色片免费 | 国内精品久久久久国产 | 中文乱幕日产无线码1区 | 久久亚洲福利 | 亚洲成人软件 | 91精品久久久久久综合五月天 | 免费黄色av | 免费三级网 | 三三级黄色片之日韩 | 五月婷av | 欧美资源| 韩国三级av在线 | 婷婷网五月天 | 免费成人av | 在线观看蜜桃视频 | 久草免费在线观看 | 国产精品尤物 | 一区中文字幕电影 | 超碰999 | 成人av手机在线 | 久久久国产精品人人片99精片欧美一 | 伊人干综合 | 久热精品国产 | 亚洲资源在线网 | 成人网色| 婷婷久久一区 | 亚洲欧洲精品一区二区精品久久久 | 成人久久久久久久久久 | 99热99| 国产精品一区二区你懂的 | 国产精品入口久久 | 色综合亚洲精品激情狠狠 | 欧美日韩中文视频 | av一级免费 | 日韩午夜精品 | 在线观看视频一区二区 | 亚洲精品国产精品久久99热 | 亚洲精品久久视频 | 中文字幕乱在线伦视频中文字幕乱码在线 | 久久在线观看 | 国产成人性色生活片 | 欧美一区,二区 | 色久av | 涩涩网站在线观看 | 二区三区毛片 | 国产剧在线观看片 | 日韩大陆欧美高清视频区 | 日韩av午夜在线观看 | 免费91麻豆精品国产自产在线观看 | 91尤物国产尤物福利在线播放 | 91麻豆视频网站 | 亚洲最大成人网4388xx | 一区二区三区四区在线 | 少妇超碰在线 | 久久久免费少妇 | 天天操天天射天天爱 | 天堂av免费观看 | av福利电影 | 精品国产1区2区3区 国产欧美精品在线观看 | 欧美日韩裸体免费视频 | 丁香亚洲 | 一区二区三区国产精品 | 色婷婷六月天 | 一区二区日韩av | 黄色激情网址 | 国产九色视频在线观看 | 91精品国产高清 | 波多野结衣一区三区 | 国产午夜精品一区二区三区嫩草 | 欧美一区日韩一区 | 一本一本久久a久久精品综合 | 91成人免费看片 | 国产综合片 | 中文字幕国产 | 97人人澡人人添人人爽超碰 | 国产韩国日本高清视频 | 欧美日韩一区二区三区免费视频 | 成人福利在线观看 | 欧美一区二区日韩一区二区 | 久久精品1区2区 | 天天干天天操天天 | 午夜免费福利视频 | 天天插视频 | 久草电影网 | 国产色女 | 久久精品第一页 | 视频福利在线 | 亚洲激情在线观看 | 超碰在线天天 | 欧美日韩国产在线 | 91精品蜜桃 | 亚州国产精品视频 | 亚洲免费色 | 2023年中文无字幕文字 | 亚洲午夜剧场 | av电影在线观看 | 一级淫片在线观看 | 在线播放视频一区 | 九九视频在线播放 | 免费观看成人 | 在线免费黄网站 | 久久精品国产一区二区 | 精品国产一区二区三区久久久 | 国产va饥渴难耐女保洁员在线观看 | 玖草影院 | 久久精品爱爱视频 | 蜜臀aⅴ国产精品久久久国产 | 久久久久综合 | 欧美成亚洲| 天天操操操操操操 | 91黄色在线看 | 超碰97成人| 成人黄色在线看 | 免费热情视频 | 亚洲午夜精品一区二区三区电影院 | 国产99久久九九精品免费 | 四虎影视4hu4虎成人 | 国产伦理久久精品久久久久_ | 亚洲高清91 | 成人国产综合 | www.狠狠| 久久国产精品99精国产 | 日本婷婷色| 97香蕉视频| 91在线观看欧美日韩 | 三级在线国产 | 91精品视频免费观看 | 99热官网| 973理论片235影院9 | 日本精品视频一区二区 | 亚洲资源视频 | 日韩r级电影在线观看 | 日本视频精品 | 色噜噜日韩精品欧美一区二区 | 国产在线国偷精品产拍免费yy | 欧美热久久| 色婷婷色 | 欧美久久久久久久 | 97精品一区二区三区 | 免费国产在线视频 | 黄色a在线观看 | 午夜av免费 | www.天天综合 | 国产亚洲欧美日韩高清 | 色哟哟国产精品 | 国产一区播放 | 免费看特级毛片 | 国产香蕉视频在线观看 | a午夜电影 | 亚洲欧美在线视频免费 | 午夜av免费观看 | 日韩最新中文字幕 | av中文字幕日韩 | 97av精品| 在线观看视频一区二区三区 | 中文在线最新版天堂 | av福利在线导航 | 日韩精品一区二区三区三炮视频 | 日韩中字在线 | 国内精品国产三级国产aⅴ久 | 粉嫩av一区二区三区免费 | 99re久久精品国产 | 久久久久久久久久久综合 | 色九九在线 | 精品国偷自产国产一区 | 免费视频黄 | 国产不卡视频在线播放 | 九九久久免费 | 欧美午夜性生活 | 婷婷丁香狠狠爱 | 亚洲精品视频免费在线 | 日韩免费福利 | 韩日精品在线观看 | 一级黄视频| 欧美精品在线观看免费 | 狠狠狠色丁香综合久久天下网 | 国产999 | 国产黄网在线 | 青青网视频 | 久久久久久久久久伊人 | 91视频免费 | 国产 欧美 日产久久 | 五月婷婷视频在线 | 嫩草91影院| 国外av在线 | 波多野结衣电影久久 | 欧美成人按摩 | 天堂av在线免费观看 | 国产精品v欧美精品 | 欧美一级片在线观看视频 | 四虎影视成人精品国库在线观看 | 久久久久人人 | 99精品免费久久久久久久久 | 国产精品毛片一区视频播 | 久久精品欧美一区 | 亚洲永久精品一区 | 最近2019年日本中文免费字幕 | 男女拍拍免费视频 | 国产精品手机看片 | 亚洲视频电影在线 | 免费高清在线视频一区· | av中文字幕在线看 | av在线影片| 999电影免费在线观看2020 | 9797在线看片亚洲精品 | 国产三级视频在线 | 国产黄色精品视频 | 久久伦理影院 | 九九九热 | 日韩区欧美久久久无人区 | 日韩最新在线视频 | 五月婷婷综合在线 | 少妇高潮流白浆在线观看 | 四虎5151久久欧美毛片 | 精品1区二区 | 婷婷丁香狠狠爱 | 欧美激情视频一区 | 成片免费观看视频大全 | 亚洲精品高清视频 | 日韩欧美xxx | 久久久久精 | 久久国产精品精品国产色婷婷 | 成人小视频免费在线观看 | 不卡av电影在线观看 | 国偷自产视频一区二区久 | 99精品在线免费视频 | 在线国产99 | 一本一本久久a久久精品综合 | 欧美性春潮 | 日韩精品视频一二三 | 成片免费观看视频999 | 欧美视频网址 | 天天操天天是 | 久久久久国产免费免费 | 91av大全 | 亚洲精品资源 | 精品在线二区 | 免费在线观看成人小视频 | 精品人人人人 | 欧美黄色特级片 | 天天干天天天天 | 亚洲码国产日韩欧美高潮在线播放 | 亚洲精品视频免费观看 | 超碰人人做 | 99视频国产精品免费观看 | 日韩一级网站 | 伊人成人久久 | 天天玩天天操天天射 | 99re视频在线观看 | 国产黑丝一区二区 | 91资源在线播放 | 欧美做受高潮电影o | 国内精品久久久久久久久久久久 | 日本在线成人 | av在线影视| 精品国产三级a∨在线欧美 免费一级片在线观看 | 国产伦精品一区二区三区… | av片免费播放 | 精品久久99 | 国产乱码精品一区二区三区介绍 | 九九九九九九精品任你躁 | 五月天电影免费在线观看一区 | 亚洲精品88欧美一区二区 | 亚洲精品无| 91久久国产精品 | 国产原创在线观看 | 成人av教育 | 人人讲 | 国产精品一区二区三区99 | 亚州av免费| 久久视频99 | 国产精品一区二区久久精品 | 992tv又爽又黄的免费视频 | 亚洲高清视频在线观看 | 一本一道久久a久久精品 | 最近中文字幕mv | 一区二区三区动漫 | 337p欧美| 91最新地址永久入口 | 国产精品亚洲片在线播放 | 天天干人人 | 一区在线免费观看 | 欧美福利视频一区 | 日韩精品久久久久 | 欧美精品一区在线 | avove黑丝| 亚洲va天堂va欧美ⅴa在线 | av免费看av | 国产一区二区三区免费视频 | 奇米四色影狠狠爱7777 | 欧美激情精品久久久 | av色综合网 | 亚洲91在线 | 久久久www成人免费精品张筱雨 | 日韩欧美国产激情在线播放 | 81国产精品久久久久久久久久 | 天天射狠狠干 | 午夜精品成人一区二区三区 | 久久精品网站免费观看 | 精品色999| 欧美日比视频 | 最新色站 | 国产一级在线免费观看 | 久久精品99视频 | 一区二区三区在线视频观看58 | 日日夜夜精品免费观看 | 91视频啪| 在线看v片成人 | 91精品视频一区二区三区 | 日韩成人精品 | 一区二区三区不卡在线 | 青青射| 午夜精品区 | 一级性视频 | 91亚洲精品久久久中文字幕 | 天天综合天天综合 | 国产欧美最新羞羞视频在线观看 | 97在线观看 | 中文字幕在线看视频国产中文版 | 深夜免费网站 | 亚洲a免费| 免费a级大片 | 人人揉人人揉人人揉人人揉97 | 久久精品久久久精品美女 | 色综合国产 | 国产精品一区二区av日韩在线 | 黄色软件大全网站 | 亚洲成a人片在线观看中文 中文字幕在线视频第一页 狠狠色丁香婷婷综合 | 97超碰人人澡人人爱 | 日韩欧美高清 | 99精品99| 丁香六月天婷婷 | 色天天综合网 | 久久国产精品一二三区 | 欧洲色综合 | av免费看网站| 日韩两性视频 | 国产一区在线看 | 4438全国亚洲精品观看视频 | 特级a老妇做爰全过程 | 成年人国产精品 | 国产美女黄网站免费 | 一级片在线| 日韩最新av在线 | a视频免费在线观看 | 国产91探花| 波多野结衣视频一区二区三区 | 免费高清在线观看成人 | 五月天高清欧美mv | 日韩毛片久久久 | 瑞典xxxx性hd极品 | 日日骑 | 久久成人一区二区 | a午夜电影| 亚洲高清视频在线观看 | 亚洲精品一区二区三区在线观看 | 亚洲视频综合在线 | 2019中文最近的2019中文在线 | 久久精品三 | 成人精品久久 | 国产精品自拍在线 | 精品国产精品久久 | 91最新视频在线观看 | 久久成年人视频 | 日韩精品一区二区三区第95 | 国产一级片一区二区三区 | 色婷婷色 | 日日夜夜噜 | 亚洲精品国产自产拍在线观看 | 日韩在线免费播放 | 欧美精品国产综合久久 | va视频在线观看 | 91亚洲激情 | av888av.com | 欧美另类sm图片 | 国精产品永久999 | 免费看片在线观看 | 九九热只有这里有精品 | 国产精品美女网站 | av中文字幕网站 | 亚洲精品www | 久久99精品视频 | 久久成人精品电影 | 玖玖爱免费视频 | 最近中文字幕mv免费高清在线 | 免费亚洲一区二区 | 99精品视频在线播放免费 | 久草视频免费看 | 日韩精品久久久久久 | 精品国内自产拍在线观看视频 | 亚洲视频 一区 | 波多野结衣在线视频免费观看 | 伊人导航 | 在线免费观看视频 | 91av电影网| 狠狠艹夜夜干 | 日韩欧美黄色网址 | 日韩v欧美v日本v亚洲v国产v | 亚洲一区视频在线播放 | 日本狠狠色 | 欧美精品一区二区三区一线天视频 | 日韩三级视频在线观看 | 国产日韩在线一区 | 91日韩在线播放 | 91精品国产乱码 | 高清不卡毛片 | 天天操综合 | 91久久国产精品 | 一区二区三区在线观看中文字幕 | 亚洲精品玖玖玖av在线看 | 欧美另类tv| 国产在线看一区 | 久久综合九色综合久久久精品综合 | 亚洲美女免费精品视频在线观看 | 99久久综合国产精品二区 | 国际精品久久久 | 亚洲片在线 | 中文字幕在线观看你懂的 | www日韩高清| 日韩精品偷拍 | 久久国产精品99久久久久 | 久久久久亚洲精品中文字幕 | 久久精品3 | 久久乱码卡一卡2卡三卡四 五月婷婷久 | 久久免费视频在线观看 | 在线观看 国产 | 最新精品国产 | 国产精品久久久久aaaa九色 | 91九色视频网站 | 97超碰精品 | 草久久久久 | 日韩av手机在线观看 | 黄色软件网站在线观看 | 日韩在线观看你懂得 | 国产中文欧美日韩在线 | 久久婷婷视频 | 国产日产av| 在线观看日韩专区 | 尤物九九久久国产精品的分类 | 国产人在线成免费视频 | 911免费视频 | 国产91勾搭技师精品 | 国产 在线 高清 精品 | 国产91精品看黄网站在线观看动漫 | 国产精品国产三级国产不产一地 | 精品国产伦一区二区三区观看方式 | 超碰公开97| 久久综合操| 99999精品视频| 日本黄色一级电影 | 国产在线91精品 | 亚洲成人国产精品 | 久久婷五月 | 久久久久亚洲精品中文字幕 | 精品一区 精品二区 | 韩国视频一区二区三区 | 天堂av最新网址 | 中文字幕第一 | 黄色.com| 欧美精品久久久久久久久久丰满 | 99久久精品免费看 | 国产精品一区二区 91 | 亚洲成人国产精品 | 久久一区国产 | 在线激情影院一区 | 精品国产欧美一区二区 | 亚洲视频资源在线 | 国内久久精品 | 日本护士三级少妇三级999 | 久热久草 | 一区二区三区在线观看免费 | 国产精品国产三级国产不产一地 | 人人玩人人添人人澡超碰 | 免费在线观看不卡av | 四虎影视久久久 | 91av视频导航 | av黄色在线播放 | 天天操天天色天天射 | 日韩免费在线观看网站 | 日韩视频一区二区在线观看 | 国产精品video爽爽爽爽 | 在线观看亚洲成人 | 免费在线观看av电影 | 91在线精品播放 | avv天堂| 日韩网站在线观看 | 手机av电影在线观看 | 99re6热在线精品视频 | 国产欧美高清 | 麻豆影视网站 | 久久婷婷色综合 | 色综合天天狠天天透天天伊人 | 一本一本久久a久久精品牛牛影视 | 一区二区三区av在线 | 成人精品影视 | 中文字幕av免费观看 | 激情欧美一区二区三区免费看 | 免费开视频 | 四虎影视成人永久免费观看亚洲欧美 | 成人av电影在线播放 | 韩国av免费观看 | 丁香视频| 狠狠色丁香婷综合久久 | 最近免费在线观看 | 97福利视频 | 精品日韩中文字幕 | 麻豆精品国产传媒 | 亚洲国产成人高清精品 | 免费在线观看不卡av | 亚洲一区二区三区91 | 在线观看黄色免费视频 | 亚洲欧洲中文日韩久久av乱码 | 色婷婷成人网 | 天天鲁天天干天天射 | 精品美女在线视频 | 96香蕉视频 | 久久女教师 | 久久综合精品国产一区二区三区 | 久草热久草视频 | 91最新网址在线观看 | 成人一区二区三区中文字幕 | 丁香六月五月婷婷 | 亚洲专区在线播放 | 久久精品99久久久久久 | 黄色免费网站 | 夜夜爽夜夜操 | 草久在线观看视频 | 亚洲一级电影 | 日韩动态视频 | 日日天天狠狠 | 日韩成人免费在线观看 | 日韩三级av | 亚洲国内精品在线 | 欧美日韩亚洲国产一区 | 国产又粗又硬又长又爽的视频 | 中文字幕久久亚洲 | 亚洲精品合集 | 精品亚洲国产视频 | 日韩免费成人av | 久久国产精品电影 | 黄色软件在线观看免费 | 国产午夜在线观看视频 | 国产网红在线观看 | 国产精品区在线观看 | 伊人五月天综合 | 国产精品不卡在线观看 | 国产一区二区在线免费播放 | 国产又粗又硬又长又爽的视频 | 精品久久久久久久久久久久久 | 欧美一级艳片视频免费观看 | 精品国产成人在线影院 | 日韩精品一区二区三区在线播放 | 色网站免费在线观看 | 色久五月| 精品久久久久一区二区国产 | 婷婷久久国产 | 色综合久久综合中文综合网 | 精品美女久久久久久免费 | 国产护士av | 免费在线h| 亚洲成人第一区 | 久青草影院 | 国产日韩欧美视频在线观看 | 中文字幕日韩一区二区三区不卡 | 亚洲精品高清在线观看 | 天天爱综合 | 中文理论片 | 久草视频在线播放 | 国产人成在线观看 | 国产精品久久久久久久av大片 | 狠狠综合久久 | 欧美国产日韩在线观看 | 婷婷精品在线视频 | 国产精品久久久久久久久久免费 | 国产精品 日韩 | 天天狠狠 | 98超碰人人 | 奇米四色影狠狠爱7777 | 久久久久国产精品视频 | 中文字幕久久精品 | 免费黄色在线网站 | 久久精品韩国 | 亚洲精品在线观看不卡 | 成人免费在线观看入口 | 麻豆一区在线观看 | 在线观看激情av | 国产69久久精品成人看 | 国产一级h | 日韩av中文字幕在线 | 欧美久久99| 狠狠干网址 | 黄色视屏在线免费观看 | 最新日韩电影 | 丁香五月网久久综合 | 99国产一区 | 二区三区毛片 | 狠狠黄| 456免费视频 | 麻豆首页 | 美腿丝袜av | 午夜婷婷综合 | 久久久在线 | 免费福利视频网站 | 欧美日韩大片在线观看 | 成年人免费av网站 | 探花视频在线观看+在线播放 | 中文字幕中文字幕在线中文字幕三区 | 中文字幕av在线 | 成片人卡1卡2卡3手机免费看 | 亚洲精品久久久久999中文字幕 | 欧美精品v国产精品v日韩精品 | 日韩在线网址 | 日韩精品一区二区久久 | 久久亚洲专区 | 久久久久久久久久久久国产精品 | 久久丝袜视频 | 国产成人久久精品亚洲 | 国产精品96久久久久久吹潮 | 国产无套精品久久久久久 | 999抗病毒口服液 | 91在线看片| 欧洲视频一区 | 亚洲www天堂com | 在线观看日本高清mv视频 | 国产又黄又猛又粗 | 天堂av在线网| 日韩av不卡播放 | 欧美一级黄大片 | 黄色大全免费观看 | 久久久国产精品一区二区中文 | 久久久久久久久久影视 | 92国产精品久久久久首页 | 91九色porny蝌蚪主页 | 国产美女视频网站 | 亚洲一区二区精品在线 | 久久免费av | 亚洲免费av片 | 久久一区二区三区国产精品 | 久久九九影视 | 精品久久久久久久久久 | 午夜国产一区二区三区四区 | 超碰在线9 | 免费国产在线精品 | 亚洲视频观看 | 亚洲成人999 | 国产福利免费看 | 丁香婷婷久久久综合精品国产 | 91国内在线 | 日韩特黄av| 日日干av | 欧洲一区二区三区精品 | 国产一级a毛片视频爆浆 | 免费av片在线 | 国产精品美女久久久久久久久 | 亚洲成人资源 | av在线精品 | 久久精品爱爱视频 | 久久97超碰 | 国产二级视频 | 成人av一区二区兰花在线播放 | 蜜臀91丨九色丨蝌蚪老版 | 精品国产乱码久久久久久1区二区 | 欧美xxxx性xxxxx高清 | 国产v在线观看 | 日韩色高清 | 日本久久综合网 | 成人小视频在线 | 国产999精品久久久久久麻豆 | 婷婷视频在线观看 | 国内精品免费久久影院 | 日本黄色黄网站 | 国产精品毛片一区视频 | 一区二区三区国产欧美 | 综合久久五月天 | 久草在线99 | 日韩久久精品一区二区三区下载 | 精品一区精品二区高清 | 亚洲综合色播 | 日本精品视频在线观看 | 91视频麻豆视频 | 青青草国产免费 | 密桃av在线 | 最近字幕在线观看第一季 | 久久精品视频18 | 波多野结衣精品视频 | 国产二区视频在线观看 | www.黄色片网站 | 久久毛片视频 | 久草在线91 | 国产精品久久久久久久久久久久午夜 | 成人免费观看视频网站 | 国产精品尤物视频 | 久久99精品一区二区三区三区 | 欧洲视频一区 | 成人av电影免费在线播放 | 国产成人久久精品一区二区三区 | 国产91影视 | 亚洲精品网址在线观看 | 国语久久 | 美女黄视频免费 | 国产视频手机在线 | av中文字幕电影 | 久久综合九色综合97婷婷女人 | 美女久久久久久久久久 | 久久毛片高清国产 | 在线精品观看国产 | 久久久久久99精品 | 日韩在线观看三区 | 亚洲无在线 | 久久大片 | 在线导航av | 国产精品一区二区三区在线看 | 国产精品久久久久久久久搜平片 | 综合国产视频 | 操操操人人人 | 狠狠躁日日躁狂躁夜夜躁av | 国产精品欧美一区二区 | 高潮毛片无遮挡高清免费 | 日本精品视频在线观看 | 成人免费在线视频 | 国产亚洲视频在线观看 | 97人人超碰在线 | 一级成人免费视频 | 婷婷综合在线 | 91麻豆精品国产91久久久久久 | 亚洲欧美日韩国产 | 99视频偷窥在线精品国自产拍 | 日韩理论电影网 | 91chinesexxx| 福利电影一区二区 | 91av综合 | 91九色视频观看 | 2018亚洲男人天堂 | 黄色电影网站在线观看 | 97高清免费视频 | 午夜视频福利 | 欧美日韩二区三区 | 日韩一级片大全 | 久草精品视频 | 天天操婷婷 | 国产福利在线免费观看 | 欧美日韩综合在线观看 | 中文字幕在线观看av | 最近字幕在线观看第一季 | 欧美日韩午夜在线 | 毛片视频网址 | 色的网站在线观看 | 欧美视频日韩 | 综合天天网 | 欧美黄色高清 | 久久九九国产精品 | 国产另类av| 亚洲福利精品 | 国产999在线 | 狠狠插狠狠操 | 亚洲高清不卡av | 精品日韩在线一区 | 狠狠的干狠狠的操 | 91麻豆网站| 国内少妇自拍视频一区 | 久久久久久综合网天天 | 91av视频| 韩日电影在线观看 | 黄色软件视频网站 | 亚洲成人第一区 | 天天摸日日摸人人看 | 精品国产欧美一区二区三区不卡 | 一区二区精品视频 | 国产丝袜制服在线 | 久久噜噜少妇网站 | 久久久免费看视频 | 深爱婷婷激情 | av手机在线播放 | 午夜精品久久久99热福利 | 五月婷网站 | 黄色免费国产 | 不卡的av片 | 五月婷婷色综合 | 亚洲成人资源网 | 久久激情五月丁香伊人 | 精品视频| 欧美日韩高清一区二区 国产亚洲免费看 | 国产精品 日韩 欧美 | 91看片在线观看 | 国内久久精品 | 91看片在线免费观看 | 91亚·色| 国产视频久久 | 成人午夜久久 | 色综合色综合久久综合频道88 | 999久久久免费视频 午夜国产在线观看 | 国产视频精品在线 | 人人看人人草 | 久久久网 | 国产一二三在线视频 | av午夜电影 | 久久久久久久久久久网 | 五月综合色婷婷 | 亚洲狠狠丁香婷婷综合久久久 | 九色一区二区 | www.com黄| 美女视频黄网站 | 亚洲人成精品久久久久 | 日韩成人免费在线电影 | 国产三级视频 | 精品国产成人av | 91视频久久久久 | 亚洲成人午夜av | 天天色天天综合 | 日韩成人精品在线观看 | 中文字幕美女免费在线 | 成年人免费看片网站 | 久久久久北条麻妃免费看 | 在线视频日韩精品 | 久久国产精品免费看 | 永久av免费在线观看 | 国产黄色精品视频 | 香蕉在线观看 | 成人91在线 | 久久草草热国产精品直播 | 婷婷视频在线观看 | 久久久久久久久久久久久久电影 | 岛国精品一区二区 | 天天骚夜夜操 | 黄色成人免费电影 | 久久久三级视频 | 精品人人爽 | 中文字幕在线播放日韩 | 午夜电影一区 | 日本韩国精品一区二区在线观看 | 成人精品电影 | 少妇bbw撒尿 | 成人av电影网址 | 亚洲精品网址在线观看 | 亚洲少妇影院 | 久久不卡av| 亚洲人久久久 | 在线国产不卡 | 国产精品视频在线观看 | 日韩欧美在线视频一区二区三区 | 最新午夜 | 狠狠色伊人亚洲综合网站色 | 亚洲视频精品在线 | 国产视频黄 | 成人免费一区二区三区在线观看 | 欧美日韩精品在线一区二区 | 亚洲国内精品在线 | 久草在线视频资源 | 五月天六月色 | 欧美在线aa | 日韩精品视频在线观看网址 | www91在线观看 | 视频一区二区三区视频 | 国产成免费视频 | 狠狠干2018| 久久精品视频网站 | 国产一区在线免费观看 | 手机av电影在线观看 | 男女啪啪免费网站 | 精品一区二区三区电影 | 天天色成人 | 精品一区二区影视 | 免费看搞黄视频网站 | 91精品免费在线 | 成人h在线观看 | 九九免费观看全部免费视频 | 成年人免费电影在线观看 | 92av视频 | 亚洲婷婷网 | 天天躁日日躁狠狠 | 欧美91成人网 | 精品美女久久久久 | 国产成人免费观看 | 日日操操操 | 色婷婷啪啪免费在线电影观看 | 婷婷婷国产在线视频 | 美女一二三区 | 久亚洲精品 | 亚洲综合色视频 | 色婷婷狠狠干 | 成人日韩av| 日韩在线播放av | 黄色免费高清视频 | 91自拍成人| 99精品国产免费久久久久久下载 | 99精品久久久久久久 | 国产精品久久久久久妇 | 国产在线欧美日韩 | 成人免费 在线播放 | 人人干人人艹 | 国产精品一区二区三区四 | 亚a在线 | 欧美性生活一级片 | 在线成人看片 | 天天天操天天天干 | 欧美日韩国产区 | 日p视频 | 有没有在线观看av | 国产精品久久久久久电影 | 午夜123| 一区二区三区中文字幕在线 | 成人电影毛片 | 国产免费精彩视频 | 国内一区二区视频 | 天天操夜夜爱 | av成人黄色| 夜色资源站国产www在线视频 | 手机在线视频福利 | 97香蕉久久超级碰碰高清版 | 成人国产精品免费观看 | 91av社区 | 国产精品视频地址 | 精品国产一区二区久久 | 欧美另类交在线观看 | 久久精品视频在线 | 欧美国产在线看 | 999成人网| 日本激情视频中文字幕 | 久久蜜臀av | 27xxoo无遮挡动态视频 | 久久久私人影院 | 黄污视频大全 | 99精品热| 中文字幕乱码在线播放 | 国产三级精品三级在线观看 | 国产成人久久久久 | 日韩精品视频免费在线观看 | 91九色porny蝌蚪视频 | 欧美精品成人在线 | 中文字幕在线观看免费高清电影 | 久久综合狠狠综合久久狠狠色综合 | 五月婷婷丁香 | 99视频精品免费观看, | 91热在线| 色婷婷骚婷婷 | 中文字幕有码在线播放 | 美女视频黄的免费的 | 亚洲高清视频在线 | 91视频一8mav| 日韩va在线观看 | 亚洲激情精品 | 五月婷香蕉久色在线看 | 在线天堂日本 | 超碰在线天天 | 日韩精品在线观看视频 | 草久热 | www.天天操.com| 精品一区二区视频 | 成年人视频在线 | 人人爽人人爽人人爽人人爽 | 新av在线 | 国产三级视频在线 | 91成人区 | 国产蜜臀av| 四虎影视成人精品 | 久久伊人精品天天 | 国产啊v在线 |