精品欧美一区二区三区在线观看 _久久久久国色av免费观看性色_国产精品久久在线观看_亚洲第一综合网站_91精品又粗又猛又爽_小泽玛利亚一区二区免费_91亚洲精品国偷拍自产在线观看 _久久精品视频在线播放_美女精品久久久_欧美日韩国产成人在线

Google和Facebook為什么不用Docker?

人工智能 機器學習
寫作本文的起因是我想讓修改后的分布式 PyTorch 程序能更快的在 Facebook 的集群上啟動。探索過程很有趣,也展示了工業機器學習需要的知識體系。

 [[397388]]

圖片來自 Pexels

2007 年我剛畢業后在 Google 工作過三年。當時覺得分布式操作系統 Borg 真好用。

從 2010 年離開 Google 之后就一直盼著它開源,直到 Kubernetes 的出現。

Kubernetes 調度的計算單元是 containers(準確的翻譯是“集裝箱”,而不是意思泛泛的“容器”,看看 Docker 公司的 Logo 上畫的是啥就知道作者的心意了)。

而一個 container 執行一個 image,就像一個 process 執行一個 program。

無論 Googlers 還是 ex-Googlers,恐怕在用 Borg 的時候都未曾接觸過 container 和 image 這兩個概念。為啥 Borg 里沒有,而 Kubernetes 卻要引入了這樣兩個概念呢?

這個曾經問題在我腦海中一閃而過就被忽略了。畢竟后來我負責開源項目比較多,比如百度 Paddle 以及螞蟻的 SQLFlow 和 ElasticDL,Docker 用起來很順手。于是也就沒有多想。

今年(2021 年)初,我加入 Facebook。恰逢 Facebook 發論文[1]介紹了其分布式集群管理系統 Tupperware。

不過 Tupperware 是一個注冊于 1946 年的品牌 https://en.wikipedia.org/wiki/Tupperware_Brands,所以在論文里只好起了另一個名字 Twine。

因為行業里知道 Tupperware 這個名字的朋友很多,本文就不說 Twine 了。

總之,這篇論文的發表又引發了我對于之前問題的回顧——Facebook 里也沒有 Docker!

和 Facebook Tuppware 團隊以及 Google Borg 幾位新老同事仔細聊了聊之后,方才恍然。因為行業里沒有看到相關梳理,本文是為記錄。

一言蔽之

簡單的說,如果用 monolithic repository 來管理代碼,則不需要 Docker image(或者 ZIP、tarball、RPM、deb)之類的“包”。

所謂 monolithic repo 就是一家公司的所有項目的所有代碼都集中放在一個(或者極少數)repo 里。

因為 monolithic repository 得有配套的統一構建系統(build system)否則編譯不動那么老大一坨代碼。

而既然有統一的 build system,一旦發現某個集群節點需要執行的程序依賴的某個模塊變化了,同步這個模塊到此節點既可。完全不需要打包再同步。

反之,如果每個項目在一個獨立的 git/svn repo 里,各自用不同的 build system,比如各個開源項目在不同的 GitHub repo 里,則需要把每個項目 build 的結果打包。

而 Docker image 這樣支持分層的包格式讓我們只需要傳輸那些容納被修改的項目的最上面幾層,而盡量復用被節點 cache 了的下面的幾層。

Google 和 Facebook 都使用 monolithic repository,也都有自己的 build systems(我這篇老文尋找 Google Blaze[2] 解釋過 Google 的 build system)所以不需要“包”,當然也就不需要 Docker images。

不過 Borg 和 Tupperware 都是有 container 的(使用 Linux kernel 提供的一些 system calls,比如 Google Borg 團隊十多年前貢獻給 Linux kernel 的 cgroup)來實現 jobs 之間的隔離。

只是因為如果不需要大家 build Docker image 了,那么 container 的存在就不容易被關注到了。

如果不想被上述蔽之,而要細究這個問題,那就待我一層一層剝開 Google 和 Facebook 的研發技術體系和計算技術體系。

Packaging

當我們提交一個分布式作業(job)到集群上去執行,我們得把要執行的程序(包括一個可執行文件以及相關的文件,比如 *.so,*.py)傳送到調度系統分配給這個 job 的一些機器(節點、nodes)上去。

這些待打包的文件是怎么來的呢?當時是 build 出來的。在 Google 里有 Blaze,在 Facebook 里有 Buck。

感興趣的朋友們可以看看 Google Blaze 的“開源版本”Bazel[3],以及 Facebook Buck 的開源版本[4]。

不過提醒在先:Blaze 和 Facebook Buck 的內部版都是用于 monolithic repo 的,而開源版本都是方便大家使用非 mono repos 的,所以理念和實現上有不同,不過基本使用方法還是可以感受一下的。

假設我們有如下模塊依賴(module dependencies),用 Buck 或者 Bazel 語法描述(兩者語法幾乎一樣):

  1. python_binary(name="A", srcs=["A.py"], deps=["B""C"], ...) 
  2. python_library(name="B", srcs=["B.py"], deps=["D"], ...) 
  3. python_library(name="C", srcs=["C.py"], deps=["E"], ...) 
  4. cxx_library(name="D", srcs=["D.cxx""D.hpp"], deps="F", ...) 
  5. cxx_library(name="E", srcs=["E.cxx""E.hpp"], deps="F", ...) 

那么模塊(build 結果)依賴關系如下:

  1. A.py --> B.py --> D.so -\ 
  2.      \-> C.py --> E.so --> F.so 

如果是開源項目,請自行腦補,把上述模塊(modules)替換成 GPT-3,PyTorch,cuDNN,libc++ 等項目(projects)。

當然,每個 projects 里包含多個 modules 也依賴其他 projects,就像每個 module 有多個子 modules 一樣。

Tarball

最簡單的打包方式就是把上述文件 {A,B,C}.py, {D,E,F}.so 打包成一個文件 A.zip,或者 A.tar.gz。

更嚴謹的說,文件名里應該包括版本號。比如 A-953bc.zip,其中版本號 953bc 是 git/Mercurial commit ID。

引入版本號,可以幫助在節點本地 cache,下次運行同一個 tarball 的時候,就不需要下載這個文件了。

請注意這里我引入了 package caching 的概念。為下文解釋 Docker 預備。

XAR

ZIP 或者 tarball 文件拷貝到集群節點上之后,需要解壓縮到本地文件系統的某個地方,比如:/var/packages/A-953bc/{A,B,C}.py,{D,E,F}.so。

一個稍顯酷炫的方式是不用 Tarball,而是把上述文件放在一個 overlay filesystem 的 loopback device image 里。這樣“解壓”就變成了“mount”。

請注意這里我引入了 loopback device image 的概念。為下文解釋 Docker 預備。

什么叫 loopback device image 呢?在 Unix 里,一個目錄樹的文件們被稱為一個文件系統(filesystem)。

通常一個 filesystem 存儲在一個 block device 上。什么是 block device 呢?

簡單的說,但凡一個存儲空間可以被看作一個 byte array 的,就是一個 block device。

比如一塊硬盤就是一個 block device。在一個新買的硬盤里創建一個空的目錄樹結構的過程,就叫做格式化(format)。

既然 block device 只是一個 byte array,那么一個文件不也是一個 byte array 嗎?

是的!在 Unix 的世界里,我們完全可以創建一個固定大小的空文件(用 truncate 命令),然后“格式化”這個文件,在里面創建一個空的文件系統。然后把上述文件 {A,B,C}.py,{D,E,F}.so 放進去。

比如 Facebook 開源的 XAR 文件[5]格式。這是和 Buck 一起使用的。

如果我們運行 buck build A 就會得到 A.xar . 這個文件包括一個 header,以及一個 squashfs loopback device image,簡稱 squanshfs image。

這里 squashfs 是一個開源文件系統。感興趣的朋友們可以參考這個教程[6],創建一個空文件,把它格式化成 squashfs,然后 mount 到本地文件系統的某個目錄(mount point)里。

待到我們 umount 的時候,曾經加入到 mount point 里的文件,就留在這個“空文件”里了。

我們可以把它拷貝分發給其他人,大家都可以 mount 之,看到我們加入其中的文件。

因為 XAR 是在 squashfs image 前面加上了一個 header,所以沒法用 mount -t squashf 命令來 mount,得用 mount -t xar 或者 xarexec -m 命令。

比如,一個節點上如果有了 /packages/A-953bc.xar,我們可以用如下命令看到它的內容,而不需要耗費 CPU 資源來解壓縮:

  1. xarexec -m A-953bc.xar 

這個命令會打印出一個臨時目錄,是 XAR 文件的 mount point。

分層

如果我們現在修改了 A.py,那么不管是 build 成 tarball 還是 XAR,整個包都需要重新更新。

當然,只要 build system 支持 cache,我們是不需要重新生成各個 *.so 文件的。

但是這個不解決我們需要重新分發 .tar.gz 和 .xar 文件到集群的各個節點的麻煩。

之前節點上可能有老版本的 A-953bc87fe.{tar.gz,xar} 了,但是不能復用。為了復用 ,需要分層。

對于上面情況,我們可以根據模塊依賴關系圖,構造多個 XAR 文件。

  1. A-953bc.xar --> B-953bc.xar --> D-953bc.xar -\ 
  2.             \-> C-953bc.xar --> E-953bc.xar --> F-953bc.xar 

其中每個 XAR 文件里只有對應的 build rule 產生的文件。比如,F-953bc.xar 里只有 F.so。

這樣,如果我們只修改了 A.py,則只有 A.xar 需要重新 build 和傳送到集群節點上。這個節點可以復用之前已經 cache 了的 {B,C,D,E,F}-953bc.xar 文件。

假設一個節點上已經有 /packages/{A,B,C,D,E,F}-953bc.xar,我們是不是可以按照模塊依賴順序,運行 xarexec -m 命令,依次 mount 這些 XAR 文件到同一個 mount point 目錄,既可得到其中所有的內容了呢?

很遺憾,不行。因為后一個 xarexec/mount 命令會報錯 —— 因為這個 mount point 已經被前一個 xarexec/mount 命令占據了。

下面解釋為什么文件系統 image 優于 tarball。

那退一步,不用 XAR 了,用 ZIP 或者 tar.gz 不行嗎?可以,但是慢。我們可以把所有 .tar.gz 都解壓縮到同一個目錄里。

但是如果 A.py 更新了,我們沒法識別老的 A.py 并且替換為新的,而是得重新解壓所有 .tar.gz 文件,得到一個新的文件夾。而重新解壓所有的 {B,C,D,E,F}.tar.gz 很慢。

Overlay Filesystem

有一個申請的開源工具 fuse-overlayfs。它可以把幾個目錄“疊加”(overlay)起來。

比如下面命令把 /tmp/{A,B,C,D,E,F}-953bc 這幾個目錄里的內容都“疊加”到 /pacakges/A-953bc 這個目錄里。

  1. fuse-overlayfs -o \ 
  2.   lowerdir="/tmp/A-953bc:/tmp/B-953bc:..." \ 
  3.   /packages/A-953bc 

而 /tmp/{A,B,C,D,E,F}-953bc 這幾個目錄來自 xarcexec -m /packages/{A,B,C,D,E,F}-953bc.xar。

請注意這里我引入了 overlay filesystem 的概念。為下文解釋 Docker 預備。fuse-overlayfs 是怎么做到這一點的呢?

當我們訪問任何一個文件系統目錄,比如 /packages/A 的時候,我們使用的命令行工具(比如 ls )調用 system calls(比如 open/close/read/write) 來訪問其中的文件。

這些 system calls 和文件系統的 driver 打交道 —— 它們會問 driver:/packages/A 這個目錄里有沒有一個叫 A.py 的文件呀?

如果我們使用 Linux,一般來說,硬盤上的文件系統是 ext4 或者 btrfs。也就是說,Linux universal filesystem driver 會看看每個分區的文件系統是啥,然后把 system call 轉發給對應的 ext4/btrfs driver 去處理。

一般的 filesystem drivers 和其他設備的 drivers 一樣運行在 kernel mode 里。

這是為什么一般我們運行 mount 和 umount 這類操作 filesystems 的命令的時候,都需要 sudo。而 FUSE 是一個在 userland 開發 filesystem driver 的庫。

fuse-overlayfs 這命令利用 FUSE 這個庫,開發了一個運行在 userland 的 fuse-overlayfs driver。

當 ls 命令詢問這個 overlayfs driver /packages/A-953bc 目錄里有啥的時候,這個 fuse-overlayfs driver 記得之前用戶運行過 fuse-overlayfs 命令把 /tmp/{A,B,C,D,E}-953bc 這幾個目錄給疊加上去過,所以它返回這幾個目錄里的文件。

此時,因為 /tmp/{A,B,C,D,E}-953bc 這幾個目錄其實是 /packages/{A,B,C,D,E,F}-953bc.xar 的 mount points,所以每個 XAR 就相當于一個 layer。

像 fuse-overlayfs driver 這樣實現把多個目錄“疊加”起來的 filesystem driver 被稱為 overlay filesystem driver,有時簡稱為 overlay filesystems。

Docker Image and Layer

上面說到用 overlay filesystem 實現分層。用過 Docker 的人都會熟悉一個 Docker image 由多層構成。

當我們運行 docker pull <image-name> 命令的時候,如果本機已經 cache 了這個 image 的一部分 layers,則省略下載這些 layers。這其實就是用 overlay filesystem 實現的。

Docker 團隊開發了一個 filesystem(driver)叫做 overlayfs —— 這是一個特定的 filesystem 的名字。

顧名思義,Docker overlayfs 也實現了“疊加”(overlay)的能力,這就是我們看到每個 Docker image 可以有多個 layers 的原因。

Docker 的 overlayfs 以及它的后續版本 overlayfs2 都是運行在 kernel mode 里的。

這也是 Docker 需要機器的 root 權限的原因之一,而這又是 Docker 被詬病容易導致安全漏斗的原因。

有一個叫 btrfs 的 filesystem,是 Linux 世界里最近幾年發展很迅速的,用于管理硬盤效果很好。

這個 filesystem 的 driver 也支持 overlay。所以 Docker 也可以被配置為使用這個 filesystem 而不是 overlayfs。

不過只有 Docker 用戶的電腦的 local filesystem 是 btrfs 的時候,Docker 才能用 btrfs 在上面疊加 layers。

所以說,如果你用的是 macOS 或者 Windows,那肯定沒法讓 Docker 使用 btrfs 了。

不過如果你用的是 fuse-overlayfs,那就是用了一副萬靈藥了。只是通過 FUSE 在 userland 運行的 filesystem 的性能很一般,不過本文討論的情形對性能也沒啥需求。

其實 Docker 也可以被配置使用 fuse-overlayfs。Docker 支持的分層 filesystem 列表在這里 Docker storage drivers[7]。

為什么需要 Docker Image

總結上文所述,從編程到可以在集群上跑起來,我們要做幾個步驟:

  • 編譯:把源碼編譯成可執行的形式。
  • 打包:把編譯結果納入一個“包”里,以便部署和分發
  • 傳輸:通常是集群管理系統(Borg、Kubernetes、Tupperware 來做)。如果要在某個集群節點上啟動 container,則需要把“包”傳輸到此節點上,除非這個節點曾經運行過這個程序,已經有包的 cache。
  • 解包:如果“包”是 tarball 或者 zip,到了集群節點上之后需要解壓縮;如果“包”是一個 filesystem image,則需要 mount。

把源碼分成模塊,可以讓編譯這步充分利用每次修改只改動一小部分代碼的特點,只重新編譯被修改的模塊,從而節省時間。

為了節省 2,3 和 4 的時間,我們希望“包”是分層的。每一層最好只包含一個或者幾個代碼模塊。這樣,可以利用模塊之間的依賴關系,盡量復用容納底層模塊的“層”。

在開源的世界里,我們用 Docker image 支持分層的特點,一個基礎層可能只包括某個 Linux distribution(比如 CentOS)的 userland programs,如 ls、cat、grep 等。

在其上,可以有一個層包括 CUDA。再其上安裝 Python 和 PyTorch。再再之上的一層里是 GPT-3 模型的訓練程序。

這樣,如果我們只是修改了 GPT-3 訓練程序,則不需要重新打包和傳輸下面三層。

這里的邏輯核心是:存在“項目”(project)的概念。每個項目可以有自己的 repo,自己的 building system(GNU make、CMake、Buck、Bazel 等),自己的發行版本(release)。

所以每個項目的 release 裝進 Docker image 的一層 layer。與其前置多層合稱為一個 image。

為什么 Google 和 Facebook 不需要 Docker

經過上述這么多知識準備,請我們終于可以點題了。

因為 Google 和 Facebook 使用 monolithic repository,使用統一的 build system(Google Blaze 或者 Facebook Buck)。

雖然也可以利用“項目”的概念,把每個項目的 build result 裝入 Docker image 的一層。但是實際上并不需要。

利用 Blaze 和 Buck 的 build rules 定義的模塊,以及模塊之間依賴關系,我們可以完全去打包和解包的概念。

沒有了包,當然就不需要 zip、tarball、以及 Docker image 和 layers 了。

直接把每個模塊當做一個 layer 既可。如果 D.so 因為我們修改了 D.cpp 被重新編譯,那么只重新傳輸 D.so 既可,而不需要去傳輸一個 layer 其中包括 D.so。

于是,在 Google 和 Facebook 里,受益于 monolithic repository 和統一的 build 工具。

我們把上述四個步驟省略成了兩個:

  • 編譯:把源碼編譯成可執行的形式。
  • 傳輸:如果某個模塊被重新編譯,則傳輸這個模塊。

Google 和 Facebook 沒在用 Docker

上一節說了 monolithic repo 可以讓 Google 和 Facebook 不需要 Docker image。

現實是 Google 和 Facebook 沒有在使用 Docker。這兩個概念有區別。

我們先說“沒在用”。歷史上,Google 和 Facebook 使用超大規模集群先于 Docker 和 Kubernetes 的出現。當時為了打包方便,連 tarball 都沒有。

對于 C/C++ 程序,直接全靜態鏈接,根本沒有 *.so。于是一個 executable binary file 就是“包”了。

直到今天,大家用開源的 Bazel 和 Buck 的時候,仍然可以看到默認鏈接方式就是全靜態鏈接。

Java 語言雖然是一種“全動態鏈接”的語言,不過其誕生和演進扣準了互聯網歷史機遇,其開發者發明 jar 文件格式,從而支持了全靜態鏈接。

Python 語言本身沒有 jar 包,所以 Blaze 和 Bazel 發明了 PAR 文件格式(英語叫 subpar),相當于為 Python 設計了一個 jar。開源實現在這里[8]。

類似的,Buck 發明了 XAR 格式,也就是我上文所說的 squashfs image 前面加了一個 header。其開源實現在這里[9]。

Go 語言默認就是全靜態鏈接的。在 Rob Pike 早期的一些總結里提到,Go 的設計,包括全靜態鏈接,基本就是繞坑而行,繞開 Google C/C++ 實踐中遇到過的各種坑。

熟悉 Google C++ style guide 的朋友們應該感覺到了 Go 語法覆蓋了 guide 說的“應該用的 C++ 語法”,而不支持 guide 說的 “不應該用的 C++ 的部分”。

簡單的說,歷史上 Google 和 Facebook 沒有在用 Docker image,很重要的一個原因是,其 build system 對各種常見語言的程序都可以全靜態鏈接,所以可執行文件就是“包”。

但這并不是最好的解法,畢竟這樣就沒有分層了。哪怕我只是修改了 main 函數里的一行代碼,重新編譯和發布,都需要很長時間,十分鐘甚至數十分鐘,要知道全靜態鏈接得到的可執行文件往往大小以 GB 計。

所以全靜態鏈接雖然是 Google 和 Facebook 沒有在用 Docker 的原因之一,但是并不是一個好選擇。

所以也沒被其他公司效仿。大家還是更愿意用支持分層 cache 的 Docker image。

完美解法的技術挑戰

完美的解法應該支持分層 cache(或者更精確的說是分塊 cache)。所以還是應該用上文介紹的 monolithic repo 和統一 build system 的特點。

但是這里有一個技術挑戰,build system 描述的模塊,而模塊通常比“項目”細粒度太多了。

以 C/C++ 語言為例,如果每個模塊生成一個 .so 文件,當做一個“層”或者“塊”以便作為 cache 的單元,那么一個應用程序可能需要的 .so 數量就太多了。

啟動應用的時候,恐怕要花幾十分鐘來 resolve symbols 并且完成鏈接。

所以呢,雖然 monolithic repo 有很多好處,它也有一個缺點,不像開源世界里,大家人力的把代碼分解成“項目”。

每個項目通常是一個 GitHub repo,其中可以有很多模塊,但是每個項目里所有模塊 build 成一個 *.so 作為一個 cache 的單元。

因為一個應用程序依賴的項目數量總不會太多,從而控制了 layer 的總數。

好在這個問題并非無解。既然一個應用程序對各個模塊的依賴關系是一個 DAG,那么我們總可以想辦法做一個 graph partitioning,把這個 DAG 分解成不那么多的幾個子圖。

仍然以 C/C++ 程序為例,我們可以把每個子圖里的每個模塊編譯成一個 .a,而每個子圖里的所有 .a 鏈接成一個 *.so,作為一個 cache 的單元。

于是,如何設計這個 graph partitioning 算法就成了眼前最重要的問題了。

相關鏈接:

  • https://engineering.fb.com/2019/06/06/data-center-engineering/twine/
  • https://zhuanlan.zhihu.com/p/55452964
  • https://bazel.build/
  • https://buck.build/
  • https://github.com/facebookincubator/xar
  • https://tldp.org/HOWTO/SquashFS-HOWTO/creatingandusing.html
  • https://docs.docker.com/storage/storagedriver/select-storage-driver/
  • https://github.com/google/subpar
  • https://github.com/facebookincubator/xar

作者:王益

編輯:陶家龍

出處:zhuanlan.zhihu.com/p/368676698

責任編輯:武曉燕 來源: 知乎
相關推薦

2010-11-02 14:31:44

Google Maps

2020-09-25 08:10:55

Rust系統編程

2024-04-15 00:00:00

Git管理代碼

2023-06-06 09:03:06

InnodbMySQL

2020-06-19 14:55:11

Kubernetes容器技術

2013-05-17 11:53:44

googleGoogle Glas

2015-08-13 14:10:53

OKRGoogleFacebook

2014-04-09 10:08:06

FacebookHack

2015-04-08 10:46:11

2019-03-11 08:36:11

Python代碼Flask

2015-08-13 13:24:53

Google重組

2010-11-16 11:08:54

2015-09-08 16:22:14

Facebook公有云云市場

2012-07-19 09:31:48

googleGOOGLE CEO雅虎

2011-12-26 09:59:50

GoogleFirefox反壟問題

2021-08-23 08:19:48

辭職Google工程師

2013-08-05 11:15:45

GoogleNexus系列

2013-04-25 10:14:39

Facebook開發者開發

2021-10-22 09:32:55

即時通訊通訊軟件微信

2019-05-15 08:29:56

Web面板運維
點贊
收藏

51CTO技術棧公眾號

欧美在线视屏| 久久精品国产福利| 不卡一区二区三区四区| 欧美精品video| 大地资源二中文在线影视观看| 欧美大片1688| 日韩理论片网站| 国产日韩二区| 91av久久久| 韩日视频一区| 最好看的2019的中文字幕视频| 国产麻豆剧传媒精品国产| 亚洲最大网站| 一区二区三区在线视频免费观看| 麻豆久久久9性大片| 国产美女免费看| 久热国产精品| 久久全球大尺度高清视频| 手机看片福利视频| 日韩精品一区二区三区中文 | 狠狠色伊人亚洲综合成人| 欧美精品xxx| 四虎永久免费地址| 色棕色天天综合网| 亚洲第一天堂av| 老司机午夜性大片| 性感美女一区二区在线观看| 亚洲一区二区三区自拍| 一区二区三区四区免费视频| 免费人成黄页在线观看忧物| 高清在线成人网| 成人黄色生活片| 最好看的日本字幕mv视频大全| 亚洲高清毛片| 欧美大片免费观看在线观看网站推荐| av在线播放中文字幕| 日韩激情啪啪| 亚洲国内精品视频| 91人妻一区二区| 精品久久国产一区| 欧美美女一区二区| www.涩涩涩| 日韩免费小视频| 色综合久久久久久久| 国产欧美日韩网站| 91九色美女在线视频| 亚洲午夜视频在线观看| 今天免费高清在线观看国语| 国产日产一区二区三区| 亚洲欧美综合网| 亚洲午夜精品久久久中文影院av| 国产女人在线观看| 久久麻豆一区二区| 欧洲精品在线一区| 欧美成人综合在线| 久久精品人人做人人爽人人| 久久伊人一区| 国际av在线| 中文字幕不卡三区| 亚洲精品成人a8198a| 成人在线免费视频| 国产精品久久毛片a| 亚洲综合av一区| 久草资源在线观看| 亚洲制服丝袜一区| 国产午夜大地久久| 中文字幕资源网在线观看免费| 精品露脸国产偷人在视频| 18岁网站在线观看| 欧美三区四区| 欧美日韩国产大片| 9191在线视频| 欧美一区 二区| 亚洲天堂一区二区三区| 成人做爰视频网站| 亚洲无线一线二线三线区别av| 国模极品一区二区三区| 在线观看日韩中文字幕| 免费久久精品视频| 97se亚洲综合在线| 性猛交xxxx| 欧美国产欧美综合| 亚洲国产精品影视| 91丝袜在线| 欧美三级中文字| 无码人妻丰满熟妇区毛片蜜桃精品 | 亚洲一区二区三区四区的| 水蜜桃色314在线观看| 周于希免费高清在线观看| 欧美日韩国产精品成人| 精品人妻二区中文字幕| 欧美**vk| 九九热这里只有在线精品视| 久久久久久久久影院| 麻豆成人免费电影| 国产精品一区二区你懂得| 福利在线播放| 亚洲国产综合色| 四季av一区二区| 精品按摩偷拍| 色狠狠久久aa北条麻妃| 日本系列第一页| 理论电影国产精品| 国内精品视频在线播放| 色多多视频在线观看| 午夜精品福利一区二区蜜股av | 国产午夜精品全部视频在线播放 | 爱情岛论坛亚洲入口| 亚洲成人一区二区三区| 久久人人爽人人爽爽久久| 亚洲国产精品va| 日韩免费电影一区| 91黄色在线看| 欧美123区| 欧美大片日本大片免费观看| 久久久久久九九九九九| 欧美精品福利| 日本韩国欧美精品大片卡二| av综合在线观看| 国产日韩精品一区二区三区 | 天堂资源最新在线| 中文字幕在线观看不卡| 人妻精品无码一区二区三区| 欧洲大片精品免费永久看nba| 国产视频综合在线| 国产真人真事毛片| 韩国av一区二区三区在线观看 | 午夜国产精品视频| 国产精品久久久久久久app| 香蕉久久国产av一区二区| 亚洲精品老司机| 污污网站免费观看| 日本免费黄视频| 成人av影院在线观看| 在线播放91灌醉迷j高跟美女| 一级黄色性视频| 亚洲欧美高清| 精品一区二区不卡| 蜜桃麻豆影像在线观看| 欧美大片一区二区| 激情五月婷婷在线| 国产ts人妖一区二区| 日韩中文在线字幕| 国内精品视频| 久久久精品在线观看| 国产精品午夜一区二区| 国产三级精品三级| 日韩欧美在线免费观看视频| 在线亚洲a色| 国产激情久久久| 黄色毛片在线看| 在线精品亚洲一区二区不卡| 熟女高潮一区二区三区| 日韩经典一区二区| 亚洲成人午夜在线| 麻豆久久久久| 久久视频在线看| 国产丝袜视频在线观看| 亚洲精品网站在线观看| 欧美一级大片免费看| 欧美天天视频| 久久精品日产第一区二区三区乱码 | 久久青草精品视频免费观看| www久久久久久| 亚洲一二三四区不卡| 五月天丁香社区| 亚洲美女色禁图| 欧美精品一区二区三区久久| 少妇一区视频| 精品国产自在精品国产浪潮| 精品久久无码中文字幕| 亚洲成人在线观看视频| 瑟瑟视频在线观看| 日韩和欧美的一区| 国产大尺度在线观看| 日韩中文字幕无砖| 97久久久免费福利网址| 韩国中文免费在线视频| 欧美剧情片在线观看| 成人免费毛片东京热| 99久久伊人网影院| 成人亚洲精品777777大片| 亚洲激情中文| 国产手机精品在线| 韩国女主播一区二区| 超碰精品一区二区三区乱码| 日本黄色一区二区三区| 欧美怡红院视频| 91日韩中文字幕| 久久一区二区三区四区| 亚洲一区二区在线视频观看| 精品9999| 亚洲精品欧洲精品| 国产美女撒尿一区二区| 国产精品久久久久久搜索| 中中文字幕av在线| 亚洲人成啪啪网站| 精品久久久久成人码免费动漫| 精品久久在线播放| 久久久久亚洲av片无码| 91免费国产在线观看| 日本精品一区在线| 久久成人免费| av在线观看地址| 日本久久一二三四| 精品视频一区二区三区四区| 黄色一级免费视频| 一本色道精品久久一区二区三区 | 欧美色18zzzzxxxxx| 欧美性色aⅴ视频一区日韩精品| 久草免费在线视频观看| 国产午夜精品久久| 国产伦精品一区二区三区88av| 日韩国产精品91| 欧美亚洲日本一区二区三区| 亚洲一区二区日韩| 视频一区二区三| 日韩精品导航| 国产传媒一区| www.久久久.com| 国产精品久久久久久久久久ktv| av蜜臀在线| 久久亚洲精品一区| www.亚洲.com| 亚洲欧美中文日韩v在线观看| 性生活视频软件| 制服丝袜亚洲精品中文字幕| 探花国产精品一区二区| 岛国精品视频在线播放| 精品在线视频免费观看| 亚洲日本电影在线| 黄色裸体一级片| 中日韩av电影| 成人激情五月天| 久久久av毛片精品| 国产精品无码一区二区三区免费| 国产91在线看| 久久久久国产免费| 国产成人av网站| 白丝校花扒腿让我c| 国产精品一区二区三区99| 亚洲va在线va天堂va偷拍| 久久激情综合网| 亚洲一区日韩精品| 激情五月婷婷综合| 国产永久免费网站| 精品午夜一区二区三区在线观看| 91 在线视频观看| 看国产成人h片视频| 国产精品视频中文字幕| 美美哒免费高清在线观看视频一区二区| 草草草在线视频| 日韩电影免费在线看| 亚洲精品高清无码视频| 蜜臀久久99精品久久久久宅男| 男女爽爽爽视频| 麻豆精品在线视频| 肉色超薄丝袜脚交| 国产精品一区二区在线观看不卡| 中国男女全黄大片| 99久久99久久精品国产片果冻| 黄色网址在线视频| 久久先锋影音av鲁色资源| 精品成人av一区二区三区| 国产农村妇女毛片精品久久麻豆 | www日韩tube| 久久久国产精品免费| 污污的网站在线看| 91极品女神在线| 日韩大片欧美大片| 国产精品中文在线| 视频在线观看免费影院欧美meiju 视频一区中文字幕精品 | 成人免费高清视频在线观看| 这里只有精品在线观看视频| 2017欧美狠狠色| 中国美女黄色一级片| 亚洲激情av在线| 国产精品第9页| 欧美日韩在线播放| 精品人妻无码一区二区| 日韩av在线播放资源| 成年网站在线| 久久99亚洲热视| 黄色综合网址| 97超级碰碰| 国产一区二区电影在线观看| 伊人久久在线观看| 久久综合图片| 少妇丰满尤物大尺度写真| 久久综合九色综合欧美98| 国产人与禽zoz0性伦| 天天综合天天做天天综合| 91福利免费视频| 日韩成人小视频| 成人在线观看免费网站| 秋霞av国产精品一区| 精品国模一区二区三区欧美| 欧美激情国产日韩| 欧美日韩国产欧| 黄色三级视频在线| 成人动漫精品一区二区| 亚洲区一区二区三| 色综合中文字幕| 亚洲精品久久久久久无码色欲四季 | 婷婷成人激情| 国内精品视频久久| 日韩色性视频| 欧美午夜精品久久久久久蜜| 欧美激情综合色综合啪啪| 五月婷婷狠狠操| 99久久国产免费看| 男人与禽猛交狂配| 欧美在线观看视频一区二区三区| 男人天堂综合网| 久久在线免费观看视频| 国产精成人品2018| 就去色蜜桃综合| 亚洲日韩成人| 99热这里只有精品2| 中文成人综合网| 亚洲欧美一二三区| 日韩av在线精品| 97人澡人人添人人爽欧美| 91精品国产91久久久久青草| 日韩激情在线| 免费涩涩18网站入口| 久久精子c满五个校花| 日韩久久精品视频| 精品日韩在线观看| 呦呦在线视频| 91免费电影网站| 99久久综合| 亚洲欧美久久久久| 中文字幕欧美区| 青青国产在线视频| 亚洲女人天堂av| 成人午夜视屏| 欧美成人蜜桃| 久久激情网站| 精品无码人妻一区二区免费蜜桃 | 九九热爱视频精品视频| 成人免费aaa| 91美女蜜桃在线| 狠狠人妻久久久久久综合| 亚洲精品永久免费| 亚洲美女久久精品| 日本精品二区| 日韩经典中文字幕一区| 欧美老女人性生活视频| 欧美天堂一区二区三区| a黄色在线观看| 国产精选久久久久久| 91久久久精品国产| 在线一区二区不卡| 亚洲一区自拍偷拍| 污污视频在线观看网站| 欧美一级电影在线| 加勒比久久综合| 日本中文字幕精品—区二区| 中文字幕制服丝袜一区二区三区| 国产又色又爽又黄又免费| 美日韩在线视频| 国产精伦一区二区三区| 丰满少妇被猛烈进入高清播放| 久久精品欧美一区二区三区麻豆| 中文在线观看免费高清| 精品国产一区av| av成人app永久免费| 国产免费黄色av| 国产精品欧美极品| www.天天干.com| 8050国产精品久久久久久| 国产日产精品一区二区三区四区的观看方式| 精品少妇无遮挡毛片| 国产精品成人一区二区艾草| 亚洲成人久久精品| 欧洲永久精品大片ww免费漫画| 欧美呦呦网站| 能看毛片的网站| 一本久道久久综合中文字幕 | 国产欧美日韩一区二区三区四区| 我要看一级黄色大片| 一区二区三区美女视频| 日韩欧美亚洲系列| 成人免费视频网| 国产精品日韩精品欧美精品| 亚洲精品成人无码| 日韩精品一区二区三区四区视频 | 日本韩国视频一区二区| 国产一二三区在线观看| 国内精品视频在线播放| 精品系列免费在线观看| 日韩中文字幕在线观看视频| 日韩有码在线视频| 网友自拍一区| 久久久久亚洲av无码麻豆| 色8久久人人97超碰香蕉987| av大片在线| 日日骚一区二区网站| 成人精品视频一区二区三区尤物|