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

一篇帶你kubebuilder 實戰: CRUD

開發 項目管理
這篇文章我們實現了一個 NodePool 的 Operator 用來控制節點以及對應的 RuntimeClass,除了基本的 CURD 之外我們還學習了預刪除和 OwnerReference 的使用方式。

[[398943]]

在前兩天的文章當中我們搭建好了本地的 K8s 開發環境,并且了解了 kubebuilder 的基本使用方法,今天就從我之前遇到的一個真實需求出發完整的寫一個 Operator

需求分析

背景

在 K8s 運行的過程當中我們發現總是存在一些業務由于安全,可用性等各種各樣的原因需要跑在一些獨立的節點池上,這些節點池里面可能再劃分一些小的節點池。

雖然我們可以使用 Taint,Label對節點進行劃分,使用 nodeSelector 和 tolerations讓 Pod 跑在指定的節點上,但是這樣主要會有兩個問題:

  • 一個是管理上不方便,在實際的使用過程中我們會發現存在錯配漏配的情況 雖然在 v1.16 之后也可以使用 RuntimeClass來簡化 pod 的配置,但是 RuntimClass 并不和節點進行關聯[^1]
  • 另一個就是拓展需求不好實現,例如我們想要的某個節點屬于網段或者當節點加入這個節點池自動開墻等

需求

1.對應用來說我們可以在創建或者更新應用時便捷的選擇的對應的節點池,默認情況下不需要進行選擇

2.對于節點池來說

  • 一個節點池可能有多個節點,并且一個節點也可能同時屬于多個節點池
  • 不同節點池的標簽、污點信息可能不同
  • 后續可以支持不同節點池的機型、安全組或者防火墻策略不同等
  • MVP 版本支持標簽、污點即可

方案設計

節點池資源如下

  1. apiVersion: nodes.lailin.xyz/v1 
  2. kind: NodePool 
  3. metadata: 
  4.   name: test 
  5. spec: 
  6.   taints: 
  7.    - key: node-pool.lailin.xyz 
  8.      value: test 
  9.      effect: NoSchedule 
  10.   labels: 
  11.    node-pool.lailin.xyz/test: "" 

節點和節點池之間的映射如何建立?

  • 我們可以利用 node-role.kubernetes.io/xxx=""標簽和節點池建立映射
  • xxx 和節點池的name相對應
  • 使用這個標簽的好處是,使用 kubectl get no可以很方便的看到節點屬于哪個節點池
  1. NAME                 STATUS                     ROLES                  AGE    VERSION 
  2. kind-control-plane   Ready,SchedulingDisabled   control-plane,master   2d2h   v1.20.2 

Pod 和節點池之間的映射如何建立?

  • 我們可以復用 RuntimeClass對象,當創建一個 NodePool 對象的時候我們就創建一個對應的 RuntimeClass 對象,然后在 Pod 中只需要加上 runtimeClassName: myclass 就可以了

注: 對于 MVP 版本來說其實我們不需要使用自定義資源,只需要通過標簽和 RuntimeClass 結合就能滿足需求,但是這里為了展示一個完整的流程,我們使用了自定義資源

開發

創建項目

  1. # 初始化項目 
  2. kubebuilder init --repo github.com/mohuishou/blog-code/k8s-operator/03-node-pool-operator --domain lailin.xyz --skip-go-version-check 
  3.  
  4. # 創建 api 
  5. kubebuilder create api --group nodes --version v1 --kind NodePool 

定義對象

  1. // NodePoolSpec 節點池 
  2. type NodePoolSpec struct { 
  3.  // Taints 污點 
  4.  Taints []v1.Taint `json:"taints,omitempty"
  5.  
  6.  // Labels 標簽 
  7.  Labels map[string]string `json:"labels,omitempty"

創建

我們實現 Reconcile 函數,req會返回當前變更的對象的 Namespace和Name信息,有這兩個信息,我們就可以獲取到這個對象了,所以我們的操作就是

1.獲取 NodePool 對象

2.通過 NodePool 對象生成對應的 Label 查找是否已經存在對應的 Label 的 Node

  • 如果存在,就給對應的 Node 加上對應的 Taint 和 Label
  • 如果不存在就跳過

3.通過 NodePool 生成對應的 RuntimeClass ,查找是否已經存在對應的 RuntimeClass

  • 如果不存在就新建
  • 存在就跳過
  1. func (r *NodePoolReconciler) Reconcile(ctx context.Context, req ctrl.Request) (ctrl.Result, error) { 
  2.  _ = r.Log.WithValues("nodepool", req.NamespacedName) 
  3.  // 獲取對象 
  4.  pool := &nodesv1.NodePool{} 
  5.  if err := r.Get(ctx, req.NamespacedName, pool); err != nil { 
  6.   return ctrl.Result{}, err 
  7.  } 
  8.  
  9.  var nodes corev1.NodeList 
  10.  
  11.  // 查看是否存在對應的節點,如果存在那么就給這些節點加上數據 
  12.  err := r.List(ctx, &nodes, &client.ListOptions{LabelSelector: pool.NodeLabelSelector()}) 
  13.  if client.IgnoreNotFound(err) != nil { 
  14.   return ctrl.Result{}, err 
  15.  } 
  16.  
  17.  if len(nodes.Items) > 0 { 
  18.   r.Log.Info("find nodes, will merge data""nodes", len(nodes.Items)) 
  19.   for _, n := range nodes.Items { 
  20.    n := n 
  21.    err := r.Patch(ctx, pool.Spec.ApplyNode(n), client.Merge) 
  22.    if err != nil { 
  23.     return ctrl.Result{}, err 
  24.    } 
  25.   } 
  26.  } 
  27.  
  28.  var runtimeClass v1beta1.RuntimeClass 
  29.  err = r.Get(ctx, client.ObjectKeyFromObject(pool.RuntimeClass()), &runtimeClass) 
  30.  if client.IgnoreNotFound(err) != nil { 
  31.   return ctrl.Result{}, err 
  32.  } 
  33.  
  34.  // 如果不存在創建一個新的 
  35.  if runtimeClass.Name == "" { 
  36.   err = r.Create(ctx, pool.RuntimeClass()) 
  37.   if err != nil { 
  38.    return ctrl.Result{}, err 
  39.   } 
  40.  } 
  41.  
  42.  return ctrl.Result{}, nil 

更新

相信聰明的你已經發現上面的創建邏輯存在很多的問題

1.如果 NodePool 對象更新,Node 是否更新對應的 Taint 和Label

  • 如果 NodePool 刪除了一個 Label 或Taint對應 Node 的Label或Taint 是否需要刪除,怎么刪除?

2.如果 NodePool 對象更新,RuntimeClass是否更新,如何更新

我們 MVP 版本實現可以簡單一些,我們約定,所有屬于 NodePool 的節點 Tanit 和Label信息都應該由 NodePool管理,key 包含 kubernetes 標簽污點除外

  1. func (r *NodePoolReconciler) Reconcile(ctx context.Context, req ctrl.Request) (ctrl.Result, error) { 
  2.   // .... 
  3.    
  4.  if len(nodes.Items) > 0 { 
  5.   r.Log.Info("find nodes, will merge data""nodes", len(nodes.Items)) 
  6.   for _, n := range nodes.Items { 
  7.    n := n 
  8.  
  9.    // 更新節點的標簽和污點信息 
  10. +   err := r.Update(ctx, pool.Spec.ApplyNode(n)) 
  11. -   err := r.Patch(ctx, pool.Spec.ApplyNode(n), client.Merge) 
  12.    if err != nil { 
  13.     return ctrl.Result{}, err 
  14.    } 
  15.   } 
  16.  } 
  17.  
  18.  //... 
  19.  
  20.  // 如果存在則更新 
  21. + err = r.Client.Patch(ctx, pool.RuntimeClass(), client.Merge) 
  22. + if err != nil { 
  23. +  return ctrl.Result{}, err 
  24. + } 
  25.  
  26.  return ctrl.Result{}, err 

ApplyNode 方法如下所示,主要是修改節點的標簽和污點信息

  1. // ApplyNode 生成 Node 結構,可以用于 Patch 數據 
  2. func (s *NodePoolSpec) ApplyNode(node corev1.Node) *corev1.Node { 
  3.  // 除了節點池的標簽之外,我們只保留 k8s 的相關標簽 
  4.  // 注意:這里的邏輯如果一個節點只能屬于一個節點池 
  5.  nodeLabels := map[string]string{} 
  6.  for k, v := range node.Labels { 
  7.   if strings.Contains(k, "kubernetes") { 
  8.    nodeLabels[k] = v 
  9.   } 
  10.  } 
  11.  
  12.  for k, v := range s.Labels { 
  13.   nodeLabels[k] = v 
  14.  } 
  15.  node.Labels = nodeLabels 
  16.  
  17.  // 污點同理 
  18.  var taints []corev1.Taint 
  19.  for _, taint := range node.Spec.Taints { 
  20.   if strings.Contains(taint.Key"kubernetes") { 
  21.    taints = append(taints, taint) 
  22.   } 
  23.  } 
  24.  
  25.  node.Spec.Taints = append(taints, s.Taints...) 
  26.  return &node 
  27. }  

我們使用 make run將服務跑起來測試一下

首先我們準備一份 NodePool 的 CRD,使用 kubectl apply -f config/samples/ 部署一下

  1. apiVersion: nodes.lailin.xyz/v1 
  2. kind: NodePool 
  3. metadata: 
  4.   name: master 
  5. spec: 
  6.   taints: 
  7.     - key: node-pool.lailin.xyz 
  8.       value: master 
  9.       effect: NoSchedule 
  10.   labels: 
  11.     "node-pool.lailin.xyz/master""8" 
  12.     "node-pool.lailin.xyz/test""2" 
  13.   handler: runc 

部署之后可以獲取到節點的標簽

  1. labels: 
  2.     beta.kubernetes.io/arch: amd64 
  3.     beta.kubernetes.io/os: linux 
  4.     kubernetes.io/arch: amd64 
  5.     kubernetes.io/hostname: kind-control-plane 
  6.     kubernetes.io/os: linux 
  7.     node-pool.lailin.xyz/master: "8" 
  8.     node-pool.lailin.xyz/test: "2" 
  9.     node-role.kubernetes.io/control-plane: "" 
  10.     node-role.kubernetes.io/master: "" 

以及 RuntimeClass

  1. apiVersion: node.k8s.io/v1 
  2.   handler: runc 
  3.   kind: RuntimeClass 
  4.   scheduling: 
  5.     nodeSelector: 
  6.       node-pool.lailin.xyz/master: "8" 
  7.       node-pool.lailin.xyz/test: "2" 
  8.     tolerations: 
  9.     - effect: NoSchedule 
  10.       key: node-pool.lailin.xyz 
  11.       operator: Equal 
  12.       value: master 

我們更新一下 NodePool

  1. apiVersion: nodes.lailin.xyz/v1 
  2. kind: NodePool 
  3. metadata: 
  4.   name: master 
  5. spec: 
  6.   taints: 
  7.     - key: node-pool.lailin.xyz 
  8.       value: master 
  9.       effect: NoSchedule 
  10.   labels: 
  11. +    "node-pool.lailin.xyz/master""10" 
  12. -    "node-pool.lailin.xyz/master""8" 
  13. -    "node-pool.lailin.xyz/test""2" 
  14.   handler: runc 

可以看到 RuntimeClass

  1. scheduling: 
  2.   nodeSelector: 
  3.     node-pool.lailin.xyz/master: "10" 
  4.   tolerations: 
  5.   - effect: NoSchedule 
  6.     key: node-pool.lailin.xyz 
  7.     operator: Equal 
  8.     value: master 

和節點對應的標簽信息都有了相應的變化

  1. labels: 
  2.    beta.kubernetes.io/arch: amd64 
  3.    beta.kubernetes.io/os: linux 
  4.    kubernetes.io/arch: amd64 
  5.    kubernetes.io/hostname: kind-control-plane 
  6.    kubernetes.io/os: linux 
  7.    node-pool.lailin.xyz/master: "10" 
  8.    node-role.kubernetes.io/control-plane: "" 
  9.    node-role.kubernetes.io/master: "" 

預刪除: Finalizers

我們可以直接使用 kubectl delete NodePool name刪除對應的對象,但是這樣可以發現一個問題,就是 NodePool 創建的 RuntimeClass 以及其維護的 Node Taint Labels 等信息都沒有被清理。

當我們想要再刪除一個對象的時候,清理一寫想要清理的信息時,我們就可以使用 Finalizers 特性,執行預刪除的操作。

k8s 的資源對象當中存在一個 Finalizers字段,這個字段是一個字符串列表,當執行刪除資源對象操作的時候,k8s 會先更新 DeletionTimestamp 時間戳,然后會去檢查 Finalizers是否為空,如果為空才會執行刪除邏輯。所以我們就可以利用這個特性執行一些預刪除的操作。注意:預刪除必須是冪等的

  1. func (r *NodePoolReconciler) Reconcile(ctx context.Context, req ctrl.Request) (ctrl.Result, error) { 
  2.  _ = r.Log.WithValues("nodepool", req.NamespacedName) 
  3.  // ...... 
  4.  
  5. + // 進入預刪除流程 
  6. + if !pool.DeletionTimestamp.IsZero() { 
  7. +  return ctrl.Result{}, r.nodeFinalizer(ctx, pool, nodes.Items) 
  8. + } 
  9.  
  10. + // 如果刪除時間戳為空說明現在不需要刪除該數據,我們將 nodeFinalizer 加入到資源中 
  11. + if !containsString(pool.Finalizers, nodeFinalizer) { 
  12. +  pool.Finalizers = append(pool.Finalizers, nodeFinalizer) 
  13. +  if err := r.Client.Update(ctx, pool); err != nil { 
  14. +   return ctrl.Result{}, err 
  15. +  } 
  16. + } 
  17.  
  18.  // ...... 

預刪除的邏輯如下

  1. // 節點預刪除邏輯 
  2. func (r *NodePoolReconciler) nodeFinalizer(ctx context.Context, pool *nodesv1.NodePool, nodes []corev1.Node) error { 
  3.  // 不為空就說明進入到預刪除流程 
  4.  for _, n := range nodes { 
  5.   n := n 
  6.  
  7.   // 更新節點的標簽和污點信息 
  8.   err := r.Update(ctx, pool.Spec.CleanNode(n)) 
  9.   if err != nil { 
  10.    return err 
  11.   } 
  12.  } 
  13.  
  14.  // 預刪除執行完畢,移除 nodeFinalizer 
  15.  pool.Finalizers = removeString(pool.Finalizers, nodeFinalizer) 
  16.  return r.Client.Update(ctx, pool) 

我們執行 kubectl delete NodePool master 然后再獲取節點信息可以發現,除了 kubernetes 的標簽其他 NodePool 附加的標簽都已經被刪除掉了

  1. labels: 
  2.      beta.kubernetes.io/arch: amd64 
  3.      beta.kubernetes.io/os: linux 
  4.      kubernetes.io/arch: amd64 
  5.      kubernetes.io/hostname: kind-control-plane 
  6.      kubernetes.io/os: linux 
  7.      node-role.kubernetes.io/control-plane: "" 
  8.      node-role.kubernetes.io/master: "" 

OwnerReference

我們上面使用 Finalizer 的時候只處理了 Node 的相關數據,沒有處理 RuntimeClass,能不能用相同的方式進行處理呢?當然是可以的,但是不夠優雅。

對于這種一一映射或者是附帶創建出來的資源,更好的方式是在子資源的 OwnerReference 上加上對應的 id,這樣我們刪除對應的 NodePool 的時候所有 OwnerReference 是這個對象的對象都會被刪除掉,就不用我們自己對這些邏輯進行處理了。

  1. func (r *NodePoolReconciler) Reconcile(ctx context.Context, req ctrl.Request) (ctrl.Result, error) { 
  2.  //... 
  3.  
  4.  // 如果不存在創建一個新的 
  5.  if runtimeClass.Name == "" { 
  6. +  runtimeClass = pool.RuntimeClass() 
  7. +  err = ctrl.SetControllerReference(pool, runtimeClass, r.Scheme) 
  8. +  if err != nil { 
  9. +   return ctrl.Result{}, err 
  10. +  } 
  11. +  err = r.Create(ctx, runtimeClass) 
  12. -  err = r.Create(ctx, pool.RuntimeClass()) 
  13.   return ctrl.Result{}, err 
  14.  } 
  15.  
  16.  // ... 

在創建的時候使用 controllerutil.SetOwnerReference 設置一下 OwnerReference 即可,然后我們再試試刪除就可以發現 RuntimeClass 也一并被刪除了。

注意,RuntimeClass 是一個集群級別的資源,我們最開始創建的 NodePool 是 Namespace 級別的,直接運行會報錯,因為 Cluster 級別的 OwnerReference 不允許是 Namespace 的資源。

這個需要在 api/v1/nodepool_types.go 添加一行注釋,指定為 Cluster 級別

  1. //+kubebuilder:object:root=true 
  2. +//+kubebuilder:resource:scope=Cluster 
  3. //+kubebuilder:subresource:status 
  4.  
  5. // NodePool is the Schema for the nodepools API 
  6. type NodePool struct { 

修改之后我們需要先執行 make uninstall 然后再執行 make install

總結

回顧一下,這篇文章我們實現了一個 NodePool 的 Operator 用來控制節點以及對應的 RuntimeClass,除了基本的 CURD 之外我們還學習了預刪除和 OwnerReference 的使用方式。之前在 kubectl delete 某個資源的時候有時候會卡住,這個其實是因為在執行預刪除的操作,可能本來也比較慢,也有可能是預刪除的時候返回了錯誤導致的。

下一篇我們一起來為我們的 Operator 加上 Event 和 Status。

參考文獻

[^1]: 容器運行時類(Runtime Class):

https://kubernetes.io/zh/docs/concepts/containers/runtime-class/

[^2]: kubebuilder 進階使用:

https://zhuanlan.zhihu.com/p/144978395

[^3]: kubebuilder2.0學習筆記——搭建和使用

https://segmentfault.com/a/1190000020338350

[^4]: KiND - How I Wasted a Day Loading Local Docker Images:

https://iximiuz.com/en/posts/kubernetes-kind-load-docker-image/

 

責任編輯:姜華 來源: mohuishou
相關推薦

2021-05-16 10:52:58

kubebuilderstatus event

2021-05-18 05:40:27

kubebuilderwebhook進階

2021-05-17 05:51:31

KubeBuilderOperator測試

2021-05-08 09:02:48

KubeBuilderOperatork8s

2021-05-20 06:57:16

RabbitMQ開源消息

2023-04-20 08:00:00

ES搜索引擎MySQL

2021-06-16 08:28:25

unary 方法函數技術

2022-02-24 07:56:42

開發Viteesbuild

2022-03-10 08:31:51

REST接口規范設計Restful架構

2025-01-17 07:00:00

2022-02-21 09:44:45

Git開源分布式

2021-06-30 00:20:12

Hangfire.NET平臺

2022-04-08 08:32:40

mobx狀態管理庫redux

2021-07-14 08:24:23

TCPIP 通信協議

2021-07-28 10:02:54

建造者模式代碼

2021-08-11 07:02:21

npm包管理器工具

2023-05-12 08:19:12

Netty程序框架

2021-11-24 08:51:32

Node.js監聽函數

2023-02-28 23:04:15

2023-04-21 08:11:54

KubernetesPod
點贊
收藏

51CTO技術棧公眾號

农村老熟妇乱子伦视频| 黄色激情在线视频| 中文字幕av影视| 日本久久黄色| 91.麻豆视频| 亚洲爆乳无码精品aaa片蜜桃| 亚洲xxx在线| 国产日韩欧美高清免费| 亚洲欧洲成视频免费观看| 女人另类性混交zo| 尤物在线视频| 国产精品中文字幕日韩精品| 欧美激情精品久久久| 色婷婷.com| 久久一卡二卡| 国产日韩视频一区二区三区| 国产91精品在线播放| 日本不卡一区视频| 国内精品视频| 五月天激情小说综合| 免费一区二区三区| ,一级淫片a看免费| 亚洲日韩成人| 色av吧综合网| 成年人的黄色片| yy6080久久伦理一区二区| 亚洲最大成人综合| 日韩偷拍一区二区| 国产 欧美 精品| 日本va欧美va欧美va精品| 欧美丰满片xxx777| 色www亚洲国产阿娇yao| 精品精品国产毛片在线看| 欧美日韩在线播放一区| 国产精品久久久久7777| 色综合久久影院| 97久久超碰国产精品电影| 国产免费一区二区三区在线观看| 国产免费无码一区二区视频| 国产精品一区二区av日韩在线| 91精品在线麻豆| www.中文字幕在线| √天堂8在线网| 欧美韩日一区二区三区| 精品国产乱码久久久久久郑州公司 | 日韩不卡在线视频| 欧美在线观看视频在线| 免费观看国产精品视频| aa在线视频| 91在线视频在线| 亚洲va久久久噜噜噜久久天堂| 日韩欧美亚洲国产| 影音先锋成人在线电影| 在线观看日韩视频| 亚洲码无人客一区二区三区| 国产美女撒尿一区二区| 日韩三级精品电影久久久| 欧美精品性生活| 国产高清不卡| 天天色综合天天| youjizz.com在线观看| 黄色网址在线免费观看| 国产情人综合久久777777| 精品一区在线播放| 亚洲国产综合网| 国产一区二区三区蝌蚪| 91精品啪在线观看麻豆免费| 最近国语视频在线观看免费播放| 免费日韩av片| 26uuu国产精品视频| 日本污视频在线观看| 欧美三级不卡| 欧美激情2020午夜免费观看| 免费中文字幕日韩| 亚洲一区欧美| 欧美成人午夜免费视在线看片| 网爆门在线观看| 成人一区二区| 日韩中文字幕在线观看| 久久精品国产亚洲AV成人婷婷| 日本高清免费电影一区| 中文字幕国产精品久久| 亚洲天堂最新地址| 亚洲午夜久久| 亚洲毛片在线观看.| 成人免费网站黄| 国产一区二区三区天码| 一个人看的www久久| 黄色三级生活片| 成人羞羞视频播放网站| 精品国产一区二区三区久久狼5月 精品国产一区二区三区久久久狼 精品国产一区二区三区久久久 | 杨幂毛片午夜性生毛片| 黄色欧美视频| 日韩一区二区视频在线观看| 9191在线视频| 日韩欧美四区| 综合av色偷偷网| 国产这里有精品| 99热这里只有精品8| 国产mv免费观看入口亚洲| 欧美性受xxx黑人xyx性爽| 九一九一国产精品| 999视频在线观看| 亚洲 精品 综合 精品 自拍| 久久先锋资源网| 亚洲一区精品视频| xxx.xxx欧美| 91久久精品一区二区| 天天干天天色天天干| 九七影院97影院理论片久久| 91精品国产91久久综合桃花| 娇妻高潮浓精白浆xxⅹ| 婷婷精品在线观看| 日韩在线欧美在线| 日韩免费一二三区| 日韩专区欧美专区| 91久久极品少妇xxxxⅹ软件| 天天干在线观看| 国产精品视频观看| 日本a在线免费观看| 456成人影院在线观看| 日韩精品一区二区三区视频播放| 97人妻精品一区二区三区免| 水蜜桃久久夜色精品一区| 国内免费精品永久在线视频| 成人黄色免费网| 99国产精品99久久久久久| 天天爽天天狠久久久| 女同一区二区免费aⅴ| 在线这里只有精品| yjizz视频| 天天综合网网欲色| 国产成人一区三区| 欧美熟妇另类久久久久久不卡 | 国产aⅴ夜夜欢一区二区三区| av小说天堂网| 国产欧美日韩激情| 3d动漫一区二区三区| 精品176极品一区| 精品五月天久久| 黄网站免费在线| 国产一区二区h| 午夜精品福利一区二区| av影院在线免费观看| 在线不卡中文字幕播放| 亚洲精品久久一区二区三区777| 欧美三级情趣内衣| 国语自产精品视频在免费| 亚洲天堂手机在线| 久久久亚洲高清| 激情深爱综合网| 超碰97久久| 久久久91精品国产| 波多野结衣黄色网址| 91在线小视频| 免费不卡av在线| 精品欧美午夜寂寞影院| 欧美国产第一页| a级片免费视频| 亚洲欧美区自拍先锋| 日韩爱爱小视频| 竹菊久久久久久久| 欧美一区二区三区图| 五月激情丁香婷婷| 黑人精品xxx一区一二区| 在线播放第一页| 国自产拍偷拍福利精品免费一 | 一级久久久久久久| 国产精品久久久久久久久免费相片 | 800av在线播放| 香蕉av一区二区| 国产精品吹潮在线观看| 亚洲第一页综合| 亚洲综合免费观看高清完整版 | 九九视频免费看| 国产精品白丝av| 日本一二三区视频在线| 色播一区二区| 久久夜色精品国产| 国产精品国产精品国产专区| 国产精品久久福利| 中文字幕55页| 激情综合在线| 久久久久久99| av在线一区不卡| 日韩性生活视频| 国产绳艺sm调教室论坛| 亚洲综合在线观看视频| 中文字幕在线国产| 国产精品久久777777毛茸茸 | 99视频精品免费| 成人久久综合| 亚洲r级在线观看| 欧美1234区| 国产视频精品久久久| 无码人妻丰满熟妇区五十路| 国产精品视频观看| 三大队在线观看| 中文高清一区| 日韩免费毛片| 日韩中文一区二区| 午夜欧美不卡精品aaaaa| 深夜福利免费在线观看| 欧美专区日韩专区| 超碰在线国产97| 99这里只有精品| 三上悠亚av一区二区三区| 中文字幕一区二区三区久久网站| dy888夜精品国产专区| 中老年在线免费视频| 视频直播国产精品| 亚洲国产av一区二区| 色老汉一区二区三区| 91九色丨porny丨极品女神| zzijzzij亚洲日本少妇熟睡| 人妻丰满熟妇av无码区app| 久久成人综合| 激情视频在线观看一区二区三区| 九九热这里有精品| 欧美中文在线免费| av网址在线播放| 亚洲欧美精品中文字幕在线| 国产视频www| 欧美性大战久久久久久久蜜臀| 国产大学生自拍| 国产香蕉久久精品综合网| 97中文字幕在线观看| 日本亚洲免费观看| 亚洲国产精品成人天堂| 久久在线播放| 欧美高清视频一区| 国产精品99久久久久久董美香| 久久久久国产精品免费网站| 成人免费在线电影| 国产婷婷色综合av蜜臀av| 99免费在线视频| 欧美日韩国产免费一区二区 | 99久久99久久精品国产片果冰| 国内外成人免费视频| 欧美.com| 91精品视频专区| 亚洲成人av观看| 91精品国产成人www| 亚洲欧美成人影院| 久久精品成人动漫| av一本在线| 亚洲欧洲中文天堂| 完全免费av在线播放| 一级成人国产| 欧美又粗又长又爽做受| 亚洲精品午夜av福利久久蜜桃| 日本在线观看不卡| 一区二区三区日本久久久| 国产亚洲第一区| 成人h动漫免费观看网站| 国产精品视频永久免费播放 | 免费观看性欧美大片无片| 国产裸体写真av一区二区| 日韩大片欧美大片| 日本视频久久久| 成人私拍视频| 欧洲精品久久久| 樱花草涩涩www在线播放| 午夜精品福利在线观看| av免费不卡国产观看| 91精品国产自产91精品| 国产传媒av在线| 7777kkkk成人观看| 91美女精品| 亲爱的老师9免费观看全集电视剧| 91豆花视频在线播放| 欧美成人自拍视频| 日韩另类在线| 国内免费久久久久久久久久久| www.51av欧美视频| 欧美精品18videosex性欧美| a'aaa级片在线观看| 久久久久亚洲精品| 在线视频cao| 国产精品入口日韩视频大尺度| 激情久久一区二区| 91网站免费看| youjizzjizz亚洲| 精品欧美国产| 国产一区二区三区日韩精品| 亚洲精品欧美精品| 亚洲国产精品日韩专区av有中文| 日韩视频在线观看视频| 亚洲精品午夜av福利久久蜜桃| 公共露出暴露狂另类av| 欧美精品三区| 午夜肉伦伦影院| 欧美a一区二区| aaaaaaaa毛片| 95精品视频在线| 91精品国自产在线| 怡红院av一区二区三区| 日韩欧美亚洲一区二区三区| 午夜视频在线观看一区二区| 69视频免费看| 欧美变态tickling挠脚心| 天堂成人在线观看| 这里只有精品在线观看| 在线观看黄av| 久久久久久久久91| 无人区在线高清完整免费版 一区二 | 国产精品一区二区欧美| 奇米亚洲欧美| 杨幂一区欧美专区| 在线精品福利| 91视频这里只有精品| 成人精品免费视频| 天天舔天天操天天干| 亚洲尤物在线视频观看| 日本久久综合网| 欧美大片在线观看一区| 国产一级网站视频在线| 久久999免费视频| 天堂8中文在线最新版在线| 国产在线播放不卡| 欧美精品密入口播放| 中国黄色录像片| 老妇喷水一区二区三区| 国产又粗又长又爽又黄的视频| 91免费看视频| 欧美成人一区二区三区高清| 欧美日韩国产中文字幕| 97国产精品久久久| 亚洲天堂网站在线观看视频| 丝袜在线观看| 国产精品中文字幕久久久| 日韩av三区| 亚洲精品国产suv一区88| 日韩一区精品视频| 亚洲v在线观看| 福利在线观看| 色妞久久福利网| 欧美123区| 日韩精品国内| 免费不卡在线视频| 久操视频在线观看免费| 色欧美88888久久久久久影院| 三级视频在线| 欧美一级电影久久| 亚洲第一福利专区| 女人和拘做爰正片视频| av高清久久久| 波多野结衣国产| 精品亚洲一区二区三区在线观看| 黄色在线网站噜噜噜| 麻豆成人在线播放| 久久国产欧美| 欧美大波大乳巨大乳| 91官网在线免费观看| 福利视频在线导航| 国产日韩欧美在线视频观看| 国产精品久久久久9999赢消| 在线观看国产福利| 亚洲色图欧美在线| 亚洲男人第一天堂| 911国产网站尤物在线观看| 日韩美女国产精品| 亚欧在线免费观看| 国产精品久久久久9999吃药| 国产孕妇孕交大片孕| 九九精品视频在线观看| 国产精品男女| 久久精品视频91| 亚洲人成7777| 色网站免费观看| 国产成人一区二区三区小说 | 99麻豆久久久国产精品免费优播| 国产精品xxxx喷水欧美| 亚洲人成网站免费播放| 福利一区和二区| 乱熟女高潮一区二区在线| 99国产精品国产精品久久| 中文字幕av第一页| 久久视频在线视频| 免费看久久久| 亚洲综合色在线观看| 玉米视频成人免费看| 欧洲免费在线视频| 亚洲综合中文字幕68页| 亚洲自啪免费| 欧美日韩色视频| 亚洲精品mp4| 福利精品在线| 成年女人18级毛片毛片免费| 久久精品视频在线免费观看| 国产av无码专区亚洲av麻豆| 欧美夜福利tv在线| 亚洲精品va| 日本成人午夜影院| 精品国产乱码久久久久久1区2区 | 欧美三级韩国三级日本一级| 性国产高清在线观看| 日本亚洲导航| 丁香六月综合激情| 一级黄在线观看|