精品欧美一区二区三区在线观看 _久久久久国色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技術棧公眾號

韩国女主播一区二区三区| 91在线中字| 日韩av中文在线观看| 色婷婷综合成人av| 国产人成视频在线观看| 欧美成人资源| 亚洲美女屁股眼交3| 国产精品av一区| 最近中文字幕在线观看视频| 欧美在线黄色| 国产视频久久久久| 国内av免费观看| 成人爱爱网址| 亚洲最新视频在线播放| 青青草久久网络| www.精品视频| 欧美aa在线视频| 97国产成人精品视频| 99热在线观看精品| 亚洲电影一级片| 欧美一区二区播放| 欧美日韩在线观看不卡| av在线最新| 中文字幕亚洲成人| 欧洲精品一区色| 亚洲精品一区二区三区新线路| 西野翔中文久久精品国产| 欧洲亚洲精品在线| 18禁免费观看网站| 日本在线观看高清完整版| 国产日韩欧美电影| 国产精品三区在线| 国产日韩欧美一区二区东京热| 日韩精品一区二区三区免费观影 | 亚洲高清在线| 最新中文字幕亚洲| 国产夫妻性爱视频| 91精品国产乱码久久久竹菊| 欧美日韩成人综合| 五月婷婷深爱五月| 色戒汤唯在线观看| 亚洲一二三区在线观看| 国产免费色视频| www.视频在线.com| 久久综合丝袜日本网| 国产欧美在线一区二区| 亚洲va欧美va| 国产成人一区二区精品非洲| 成人做爰www免费看视频网站| 亚洲欧美一区二区三区四区五区| 麻豆国产一区| 51精品秘密在线观看| 波多野结衣作品集| 亚洲成人不卡| 一本色道a无线码一区v| 啊啊啊一区二区| 成人观看网址| 午夜电影一区二区三区| 777av视频| 国产网站在线| 欧美日韩亚洲视频| 久久久久久久久久久久久久国产| 巨大荫蒂视频欧美另类大| 国产视频一区在线播放| 欧美一级二级三级| 高清av电影在线观看| 中文字幕国产一区| 亚洲欧美日本国产有色| 免费a级毛片在线播放| 综合精品久久久| 在线精品亚洲一区二区| 黄色片免费在线观看| 亚洲美女视频一区| 97超碰人人澡| 亚洲精品一区| 欧美亚洲国产一卡| 一级黄色片国产| 136福利精品导航| 亚洲缚视频在线观看| 免费在线观看成年人视频| 你懂的一区二区三区| 中文字幕精品—区二区| 四虎884aa成人精品| 欧美天堂亚洲电影院在线观看| 夜夜嗨av一区二区三区免费区 | 日韩免费小视频| 在线中文字幕不卡| 高清av免费看| 99亚洲乱人伦aⅴ精品| 亚洲精品之草原avav久久| 538精品视频| 韩日精品在线| 国产大片精品免费永久看nba| 91精品国产高潮对白| 久久高清一区| 亚洲在线免费观看| 色视频在线观看福利| 国产精品美女一区二区在线观看| 麻豆av一区二区三区| 日韩成人影视| 午夜电影网一区| 天堂在线中文在线| 亚洲欧美日本伦理| 欧美成人中文字幕| 不卡av电影在线| 国产九九视频一区二区三区| 麻豆精品视频| gogogogo高清视频在线| 欧美色视频日本版| 国产农村妇女精品久久| 九色精品国产蝌蚪| 久久久伊人日本| 中文字幕第99页| 成人av电影免费在线播放| 亚洲五月六月| 色偷偷偷在线视频播放| 日韩午夜电影在线观看| 国产熟女一区二区| 99国产精品99久久久久久粉嫩| 97国产精品人人爽人人做| 国产一区二区在线播放视频| 91视频免费播放| www.欧美黄色| 国产激情欧美| 日韩美女av在线| 久久艹精品视频| 老汉av免费一区二区三区| 久久国产欧美精品| 欧美14一18处毛片| 欧美一区午夜精品| 亚洲欧美综合7777色婷婷| 久久亚洲综合| 久久国产精品-国产精品| 美女91在线| 日韩欧美色综合网站| 一区二区三区在线播放视频| 日韩精品视频网站| 欧美精品一区二区视频| √最新版天堂资源网在线| 欧美大胆人体bbbb| 全程偷拍露脸中年夫妇| 韩国午夜理伦三级不卡影院| 亚洲欧美成人一区| 主播大秀视频在线观看一区二区| 欧美一区二区免费视频| 毛片久久久久久| 青青草国产精品97视觉盛宴| 清纯唯美一区二区三区| 国产不卡网站| 亚洲色图激情小说| 中文字幕在线欧美| 国产日韩精品一区二区三区| 日本在线观看a| 欧美日韩播放| 国产成人avxxxxx在线看| 美女做暖暖视频免费在线观看全部网址91| 国产精品成人一区二区三区夜夜夜| 国产精品久久成人免费观看| 日韩午夜电影免费看| 日韩视频免费大全中文字幕| 亚洲天堂手机在线| 亚洲欧洲精品一区二区三区不卡 | 中文字幕伦理免费在线视频| 欧美剧在线免费观看网站| 日韩一区二区三区四区视频| 久久综合综合久久综合| 只有这里有精品| 97一区二区国产好的精华液| 91国语精品自产拍在线观看性色| 91资源在线视频| 自拍偷拍国产亚洲| 佐佐木明希电影| 亚洲第一精品影视| 久久久久久国产精品一区| 欧美动物xxx| 色偷偷偷亚洲综合网另类 | 在线观看美女网站大全免费| 欧美日韩卡一卡二| 欧美人与禽zozzo禽性配| 国产 日韩 欧美大片| 亚洲欧洲日产国码无码久久99| 日韩一区二区三区精品| 欧美精品videosex牲欧美| 午夜av免费在线观看| 色婷婷综合久久久中文一区二区 | 亚洲 欧美 日韩 国产综合 在线| 久久国际精品| 91av国产在线| 秋霞午夜在线观看| 精品国产91洋老外米糕| 欧美成人一区二区三区四区| 中文字幕在线不卡| 超碰男人的天堂| 美女一区二区久久| 欧美视频在线观看视频| 精品国产aⅴ| 国产成人亚洲欧美| 99欧美精品| 高清欧美一区二区三区| 91sp网站在线观看入口| 精品久久久三级丝袜| 啪啪小视频网站| 亚洲国产一区视频| 99久久99久久精品免费看小说. | 日韩综合精品| 国产精品一区二区三区免费| 少妇一区视频| 久久久在线视频| 浪潮av一区| 一个色综合导航| 日韩一级片免费在线观看| 欧美精品xxxxbbbb| 久久久精品视频网站| 洋洋成人永久网站入口| 欧美肥妇bbwbbw| 国产亚洲精品aa午夜观看| 在线观看亚洲免费视频| 精品一区二区三区香蕉蜜桃| 国产乱子夫妻xx黑人xyx真爽| 九九久久精品| 国产欧美日韩综合一区在线观看 | 亚洲中国最大av网站| 精品无码在线观看| 91污在线观看| 动漫av在线免费观看| 精彩视频一区二区三区| 大肉大捧一进一出好爽视频| 亚洲午夜一区| 免费的av在线| 水蜜桃久久夜色精品一区| 清纯唯美一区二区三区| 西瓜成人精品人成网站| 久久99国产精品99久久| 动漫视频在线一区| av在线亚洲男人的天堂| 日韩免费一级| 91麻豆精品秘密入口| 永久免费观看精品视频| 国产区精品视频| 日韩色性视频| 国产主播欧美精品| 国产原创一区| 国产在线视频2019最新视频| 免费成人高清在线视频| 国产精品久久久久久久久粉嫩av| 女囚岛在线观看| 九九精品在线观看| 国产欧美久久久久久久久| 日韩在线视频导航| 麻豆网站在线| 不卡毛片在线看| 性网站在线观看| 欧美激情日韩图片| h片在线观看视频免费| 久久久久久伊人| 理论不卡电影大全神| 青青草成人在线| av亚洲一区二区三区| 国产精品视频色| 日韩精品一页| 亚洲最大福利视频网| 日韩中文一区二区| 国产精品一国产精品最新章节| 99蜜月精品久久91| 91久久久久久| 成人av综合网| 久精品国产欧美| 欧美日韩一二| 一区二区三区|亚洲午夜| 91成人国产| 久久成人福利视频| 国产欧美日本| 激情 小说 亚洲 图片: 伦| 精品一二线国产| 人妻 日韩 欧美 综合 制服| 久久久久久一级片| 精品国产视频在线观看| 亚洲一卡二卡三卡四卡五卡| 亚洲永久精品在线观看| 欧美日韩一区二区三区视频| a毛片在线免费观看| 亚洲激情视频在线播放| 成年午夜在线| 色综合男人天堂| 日韩激情电影免费看| 国产一区二区在线播放| xxxx日韩| 亚洲欧洲一区二区在线观看| 欧美精品二区| 日韩av一二三四| 国产一区二区三区在线看麻豆| 亚洲36d大奶网| 国产成人午夜视频| 中文字幕被公侵犯的漂亮人妻| 99久久婷婷国产综合精品| 免费观看av网站| 亚洲精品免费播放| 4438国产精品一区二区| 日韩一区二区三区精品视频| 三级无遮挡在线观看| 免费91在线视频| 韩国久久久久久| 91视频网页| 欧美亚洲国产精品久久| 2018日日夜夜| 国产在线国偷精品免费看| av无码av天天av天天爽| 尤物av一区二区| 亚洲精品国产精品乱码视色| 亚洲黄页网在线观看| 超碰在线无需免费| 国产精品久久二区| 亚洲影院天堂中文av色| 日韩精品在线视频免费观看| 久久99蜜桃精品| 国产精品一二三区在线观看| 亚洲成人在线免费| 成人h动漫精品一区二区无码| 亚洲精品999| 91黄色在线| 国产欧美日韩精品在线观看| 网友自拍一区| 狠狠干 狠狠操| 国产成人精品1024| 欧洲美女女同性互添| 欧美午夜精品久久久久久孕妇| 亚洲天堂网视频| 亚洲欧美福利视频| 少妇在线看www| 国产视频不卡| 亚洲激情不卡| 中文字幕在线播放一区二区| 成人欧美一区二区三区视频网页| 国产无码精品在线观看| 日韩一区二区电影在线| 黄色的网站在线观看| 成人妇女免费播放久久久| 欧洲福利电影| 校园春色 亚洲色图| 久久综合久久久久88| 久草手机在线观看| 日韩精品免费观看| 亚洲妇女成熟| 国产综合色一区二区三区| 亚洲区一区二| 亚洲熟女一区二区| 无码av免费一区二区三区试看| 伊人成人在线观看| 国产亚洲a∨片在线观看| 欧美va在线观看| 色姑娘综合av| 蜜桃视频在线观看一区| 国产在线免费av| 欧美男女性生活在线直播观看 | 亚洲午夜av电影| 成人线上视频| 五月天婷亚洲天综合网鲁鲁鲁| 综合亚洲视频| 91精品人妻一区二区三区蜜桃2| 国产视频一区不卡| 在线观看免费高清视频| 久久久精品国产| 视频欧美一区| 国产免费观看高清视频| 2022国产精品视频| 亚洲无码精品一区二区三区| 一本一本久久a久久精品综合小说| 成人ssswww在线播放| 欧美一区二区三区在线免费观看| 欧美成熟视频| 人妻 日韩 欧美 综合 制服| 欧美网站在线观看| 午夜激情视频在线观看| 亚洲xxx视频| 亚洲欧美久久| 国产7777777| 日韩一级免费一区| 日本蜜桃在线观看视频| 亚洲人成77777| 国产成人精品影视| 天堂а√在线中文在线新版| 一区二区三欧美| 欧美电影在线观看一区| 免费看的黄色大片| 最新日韩av在线| 黄色三级网站在线观看| 国产精品18久久久久久麻辣| 91精品国产成人观看| 黄色av网址在线观看| 欧美色网一区二区| 麻豆av在线免费观看| 日韩精品国内| 国产99精品在线观看| 波多野结衣视频网址| 欧美丰满少妇xxxxx| 国产尤物久久久| 激情av中文字幕| 欧美欧美欧美欧美| www.精品| www婷婷av久久久影片|