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

開發 Operator 調度 GPU 實例資源池

云計算 云原生
本文通過結合 Kubernetes、AI 和云平臺,深入探討了如何利用 K8s Operator 實現對 GPU 資源池的自動化管理。我們從 Operator 的核心概念出發,介紹了 CRD(自定義資源定義)和控制器的設計原理,并基于 kubebuilder 開發了一個名為 Spotpool 的 Operator,用于在騰訊云上維護競價實例的穩定運行。

本章節將引入一個新的概念——K8s Operator,它是 K8s 的一種擴展形式,可以幫助用戶以 K8s 聲明式 API 的方式管理應用及服務,Operator 定義了一組在 Kubernetes 集群中打包和部署復雜業務應用的方法,主要是為解決特定應用或服務關于如何運行、部署及出現問題時如何處理提供的一種特定的自定義方式。比如:

  • 按需部署應用服務
  • 實現應用狀態的備份和還原,完成版本升級
  • 數據庫 schema 或額外的配置設置的改動

在 K8s 中我們使用的 Deployment、Daemonset、Statefulset 等這些都是 K8s 的資源,這些資源的創建、刪除、更新等動作都會被稱為事件,K8s 的 Controller Manager 負責事件的監聽,并觸發對應的動作來滿足期望,這種方式就是聲明式,即用戶只需要關心應用程序的最終狀態。當我們在使用中發現有些資源并不能滿足日常的需求,對于這類需求可以使用 K8s 的自定義資源和 Operator 為應用程序提供基于 K8s 的擴展。

在這其中,CRD 就是對自定義資源的描述,如果要自定義資源,就需要先定義好 CRD,也就是介紹這個資源有什么屬性,這些屬性的類型、結構是怎樣的。

比如 PG 的 Operator 如下:

apiVersion: apiextensions.k8s.io/v1beta1
kind: CustomResourceDefinition
metadata:
  name: postgresqls.acid.zalan.do
  labels:
    app.kubernetes.io/name: postgres-operator
  annotations:
    "helm.sh/hook": crd-install
spec:
  group: acid.zalan.do
  names:
    kind: postgresql
    listKind: postgresqlList
    plural: postgresqls
    singular: postgresql
    shortNames:
    - pg  additionalPrinterColumns:
  - name: Team
    type: string
    description: Team responsible for Postgres CLuster
    JSONPath: .spec.teamId
  - name: Version
    type: string
    description: PostgreSQL version
    JSONPath: .spec.postgresql.version
  - name: Pods
    type: integer
    description: Number of Pods per Postgres cluster
    JSONPath: .spec.numberOfInstances
  - name: Volume
    type: string
    description: Size of the bound volume
    JSONPath: .spec.volume.size

CRD 主要包括 apiVersion、kind、metadata 和 spec 四個部分。其中最關鍵的是 apiVersion 和 kind,apiVersion 表示資源所屬組織和版本,apiVersion 一般由 APIGourp 和 Version 組成,這里的 APIGourp 是http://apiextensions.k8s.io,Version 是 v1beta1,相關信息可以通過kubectl api-resoures查看。kind 表示資源類型,這里是CustomResourceDefinition,表示是一個自定義的資源描述。

本文我們將自己開發一個 Operator 來維護 GPU 資源池的穩定,解決 AI 模型訓練的基礎平臺的穩定性。其架構如下:

ee11ee9bb3ba2f232c0f78573956823f MD5

其中:

  • GPU 資源池采用的是騰訊云的競價 GPU 實例
  • Operator 運行在 K8s 中,通過 SpootPool 控制 GPU 資源池的數量
  • 若云平臺釋放了某臺 GPU 實例,當 Operator 監聽到資源池數量和期望的不匹配,會自動補充到期望數量

Operator 的開發有多種腳手架,常用的有 operator-sdk、kubebuilder 等,這里我們將使用 kubebuilder 來完成 Operator 的開發。

前置條件

  • 準備一個可用的 K8s 集群,可以使用 kind、kubeadm、二進制等各種形式安裝,如果使用 kubeadm 安裝集群,可以參考 Kubernetes集群管理。
  • 安裝好 kubebuilder,可以參考 kubebuild快速安裝。
  • 準備好云平臺的 AK,這里是采用騰訊云,其他云類似。

快速開始

1.設計 CRD

在開發之前需要先設計好 CRD(就像業務開發前先設計好表結構一樣),本文的 CRD 主要包含云平臺虛擬機的開通,包括最小和最大實例數,以及騰訊云 SDK 所需要的各種參數,比如地域、可用區、VPC、子網、安全組、鏡像等。

最后 CRD 設計如下:

apiVersion: devops.jokerbai.com/v1
kind: Spotpool
metadata:
  labels:
    app.kubernetes.io/name: spotpool
    app.kubernetes.io/managed-by: kustomize
  name: spotpool-sample
spec:
  secretId: 密鑰ID
  secretKey: 密鑰Key
  region: 區域
  availabilityZone: 可用區
  instanceType: 實例類型
  minimum: 最小實例數
  maximum: 最大實例數
  subnetId: 子網ID
  vpcId: VPC ID
  securityGroupIds:
    - 安全組
  imageId: 鏡像ID
  instanceChargeType: 實例付費類型

2.初始化項目

定義好 CRD 字段之后,我們先使用 kubebuilder 初始化一個 Operator 項目,命令如下:

(1)初始化項目

mkdir spotpool && cd spotpool
kubebuilder init \
  --domain jokerbai.com \
  --repo github.com/joker-bai/spotpool \
  --project-name spotpool \
  --plugins go/v4 \
  --owner "Joker Bai"

(2)創建 API

kubebuilder create api --group devops.jokerbai.com --version v1 --kind Spotpool

(3)生成后的目錄結構大致如下:

.
├── api
│   └── v1
│       ├── groupversion_info.go
│       ├── spotpool_types.go
│       └── zz_generated.deepcopy.go
├── bin
│   ├── controller-gen -> /root/workspace/godev/src/github.com/joker-bai/spotpool/bin/controller-gen-v0.18.0
│   └── controller-gen-v0.18.0
├── cmd
│   └── main.go
├── config
│   ├── crd
│   │   ├── kustomization.yaml
│   │   └── kustomizeconfig.yaml
│   ├── default
│   │   ├── cert_metrics_manager_patch.yaml
│   │   ├── kustomization.yaml
│   │   ├── manager_metrics_patch.yaml
│   │   └── metrics_service.yaml
│   ├── manager
│   │   ├── kustomization.yaml
│   │   └── manager.yaml
│   ├── network-policy
│   │   ├── allow-metrics-traffic.yaml
│   │   └── kustomization.yaml
│   ├── prometheus
│   │   ├── kustomization.yaml
│   │   ├── monitor_tls_patch.yaml
│   │   └── monitor.yaml
│   ├── rbac
│   │   ├── kustomization.yaml
│   │   ├── leader_election_role_binding.yaml
│   │   ├── leader_election_role.yaml
│   │   ├── metrics_auth_role_binding.yaml
│   │   ├── metrics_auth_role.yaml
│   │   ├── metrics_reader_role.yaml
│   │   ├── role_binding.yaml
│   │   ├── role.yaml
│   │   ├── service_account.yaml
│   │   ├── spotpool_admin_role.yaml
│   │   ├── spotpool_editor_role.yaml
│   │   └── spotpool_viewer_role.yaml
│   └── samples
│       ├── devops.jokerbai.com_v1_spotpool.yaml
│       └── kustomization.yaml
├── Dockerfile
├── go.mod
├── go.sum
├── hack
│   └── boilerplate.go.txt
├── internal
│   └── controller
│       ├── spotpool_controller.go
│       ├── spotpool_controller_test.go
│       └── suite_test.go
├── Makefile
├── PROJECT
├── README.md
└── test
    ├── e2e
    │   ├── e2e_suite_test.go
    │   └── e2e_test.go
    └── utils
        └── utils.go

3.CRD 開發

(1)定義 API

api/v1alpha1/spotpool_types.go中定義 CRD 的結構體,如下:

package v1

import (
 metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
)

// EDIT THIS FILE!  THIS IS SCAFFOLDING FOR YOU TO OWN!
// NOTE: json tags are required.  Any new fields you add must have json tags for the fields to be serialized.

// SpotpoolSpec defines the desired state of Spotpool
type SpotpoolSpec struct {
 // INSERT ADDITIONAL SPEC FIELDS - desired state of cluster
 // Important: Run "make" to regenerate code after modifying this file
 SecretId           string   `json:"secretId,omitempty"`
 SecretKey          string   `json:"secretKey,omitempty"`
 Region             string   `json:"region,omitempty"`
 AvaliableZone      string   `json:"availabilityZone,omitempty"`
 InstanceType       string   `json:"instanceType,omitempty"`
 SubnetId           string   `json:"subnetId,omitempty"`
 VpcId              string   `json:"vpcId,omitempty"`
 SecurityGroupId    []string `json:"securityGroupIds,omitempty"`
 ImageId            string   `json:"imageId,omitempty"`
 InstanceChargeType string   `json:"instanceChargeType,omitempty"`
 Minimum            int32    `json:"minimum,omitempty"`
 Maximum            int32    `json:"maximum,omitempty"`
}

// SpotpoolStatus defines the observed state of Spotpool
type SpotpoolStatus struct {
 // INSERT ADDITIONAL STATUS FIELD - define observed state of cluster
 // Important: Run "make" to regenerate code after modifying this file
 Size       int32              `json:"size,omitempty"`
 Conditions []metav1.Condition `json:"conditions,omitempty" patchStrategy:"merge" patchMergeKey:"type" protobuf:"bytes,rep,name=conditions"`
 Instances  []Instances        `json:"instances,omitempty"`
}

type Instances struct {
 InstanceId string `json:"instanceId,omitempty"`
 PublicIp   string `json:"publicIp,omitempty"`
}

//+kubebuilder:object:root=true
//+kubebuilder:subresource:status

// Spotpool is the Schema for the spotpools API
type Spotpool struct {
 metav1.TypeMeta   `json:",inline"`
 metav1.ObjectMeta `json:"metadata,omitempty"`

 Spec   SpotpoolSpec   `json:"spec,omitempty"`
 Status SpotpoolStatus `json:"status,omitempty"`
}

//+kubebuilder:object:root=true

// SpotpoolList contains a list of Spotpool
type SpotpoolList struct {
 metav1.TypeMeta `json:",inline"`
 metav1.ListMeta `json:"metadata,omitempty"`
 Items           []Spotpool `json:"items"`
}

func init() {
 SchemeBuilder.Register(&Spotpool{}, &SpotpoolList{})
}

在 SpotpoolSpec 中定義設計的 CRD 結構體,這些字段都是創建虛擬機的必要字段。另外,在 SpotpoolStatus 中定義返回狀態里的信息,這里只需要 Instance 相關的信息。

(2)生成代碼

API 相關的代碼開發完后,執行以下命令生成代碼:

make generate
make manifests

4.Controller 開發

(1)開發控制器邏輯

控制器的主邏輯是:

  • 從云平臺獲取運行的實例數
  • 判斷實例數和期望的實例數是否相等
  • 如果小于期望值,則創建實例
  • 如果大于期望值,則刪除實例

所以主邏輯的代碼如下,修改internal/controller/spotpool_controller.go

func (r *SpotpoolReconciler) Reconcile(ctx context.Context, req ctrl.Request) (ctrl.Result, error) {
 log := logf.FromContext(ctx)

 // 獲取用戶期望
 spotpool := &devopsjokerbaicomv1.Spotpool{}
 if err := r.Get(ctx, req.NamespacedName, spotpool); err != nil {
  log.Error(err, "unable to fetch spotspool")
 }

 // 從云平臺獲取獲取運行的實例
 runningVmList, err := r.getRunningInstanceIds(spotpool)
 if err != nil {
  log.Error(err, "get running vm instance failed")
  // 十秒后重試
  return ctrl.Result{RequeueAfter: 10 * time.Second}, nil
 }

 runningCount := len(runningVmList)

 switch {
 case runningCount < int(spotpool.Spec.Minimum):
  // 創建實例擴容
  delta := spotpool.Spec.Minimum - int32(runningCount)
  log.Info("creating instances", "delta", delta)
  err = r.runInstances(spotpool, delta)
  if err != nil {
   log.Error(err, "unable to create instances")
   return ctrl.Result{RequeueAfter: 40 * time.Second}, nil
  }
 case runningCount > int(spotpool.Spec.Maximum):
  // 刪除實例縮容
  delta := int32(runningCount) - spotpool.Spec.Maximum
  log.Info("terminating instances", "delta", delta)
  err = r.terminateInstances(spotpool, delta)
  if err != nil {
   log.Error(err, "unable to terminate instances")
   return ctrl.Result{RequeueAfter: 40 * time.Second}, nil
  }
 }

 return ctrl.Result{RequeueAfter: 40 * time.Second}, nil
}

其中:

  • r.getRunningInstanceIds(spotpool) 用戶獲取云平臺運行的實例數
  • r.runInstances(spotpool, delta) 用于調用云平臺進行擴容
  • r.terminateInstances(spotpool, delta) 用于調用云平臺進行縮容

接下來分別實現上面的三個方法。

(1)首先,實現 getRunningInstanceIds 方法

func (r *SpotpoolReconciler) getRunningInstanceIds(spotpool *devopsjokerbaicomv1.Spotpool) ([]string, error) {
 client, err := r.createCVMClient(spotpool.Spec)
 if err != nil {
  return nil, err
 }

 request := cvm.NewDescribeInstancesRequest()
 response, err := client.DescribeInstances(request)
 if err != nil {
  return nil, err
 }
 var instances []devopsjokerbaicomv1.Instances
 var runningInstanceIDs []string
 for _, instance := range response.Response.InstanceSet {
  if *instance.InstanceState == "RUNNING" || *instance.InstanceState == "PENDING" || *instance.InstanceState == "STARTING" {
   runningInstanceIDs = append(runningInstanceIDs, *instance.InstanceId)
  }
  // 檢查實例的公網 IP,如果不存在公網 IP,則繼續重試
  if len(instance.PublicIpAddresses) == 0 {
   return nil, fmt.Errorf("instance %s does not have public ip", *instance.InstanceId)
  }
  instances = append(instances, devopsjokerbaicomv1.Instances{
   InstanceId: *instance.InstanceId,
   PublicIp:   *instance.PublicIpAddresses[0],
  })
 }
 // 更新 status
 spotpool.Status.Instances = instances
 err = r.Status().Update(context.Background(), spotpool)
 if err != nil {
  return nil, err
 }
 return runningInstanceIDs, nil
}

// 獲取騰訊云 SDK client
func (r *SpotpoolReconciler) createCVMClient(spec devopsjokerbaicomv1.SpotpoolSpec) (*cvm.Client, error) {
 credential := common.NewCredential(spec.SecretId, spec.SecretKey)
 cpf := profile.NewClientProfile()
 cpf.HttpProfile.ReqMethod = "POST"
 cpf.HttpProfile.ReqTimeout = 30
 cpf.SignMethod = "HmacSHA1"

 client, err := cvm.NewClient(credential, spec.Region, cpf)
 if err != nil {
  return nil, err
 }
 return client, nil
}

其中:

  • 調用 r.createCVMClient(spotpool.Spec) 獲取騰訊云SDK client
  • 然后調用 client.DescribeInstances(request) 獲取實例詳細信息
  • 最后通過判斷 instance.InstanceStat 和 instance.PublicIpAddresses 的狀態信息決定是否是需要的實例
  • 最后返回實例列表信息

(2)實現 r.runInstances(spotpool, delta) 用于調用云平臺進行擴容

func (r *SpotpoolReconciler) runInstances(spotpool *devopsjokerbaicomv1.Spotpool, count int32) error {
 client, err := r.createCVMClient(spotpool.Spec)
 if err != nil {
  return err
 }
 request := cvm.NewRunInstancesRequest()
 request.ImageId = common.StringPtr(spotpool.Spec.ImageId)
 request.Placement = &cvm.Placement{
  Zone: common.StringPtr(spotpool.Spec.AvaliableZone),
 }
 request.InstanceChargeType = common.StringPtr(spotpool.Spec.InstanceChargeType)
 request.InstanceCount = common.Int64Ptr(int64(count))
 request.InstanceName = common.StringPtr("spotpool" + time.Now().Format("20060102150405"))
 request.InstanceType = common.StringPtr(spotpool.Spec.InstanceType)
 request.InternetAccessible = &cvm.InternetAccessible{
  InternetChargeType:      common.StringPtr("BANDWIDTH_POSTPAID_BY_HOUR"),
  InternetMaxBandwidthOut: common.Int64Ptr(1),
  PublicIpAssigned:        common.BoolPtr(true),
 }
 request.LoginSettings = &cvm.LoginSettings{
  Password: common.StringPtr("Password123"),
 }
 request.SecurityGroupIds = common.StringPtrs(spotpool.Spec.SecurityGroupId)
 request.SystemDisk = &cvm.SystemDisk{
  DiskType: common.StringPtr("CLOUD_BSSD"),
  DiskSize: common.Int64Ptr(100),
 }
 request.VirtualPrivateCloud = &cvm.VirtualPrivateCloud{
  SubnetId: common.StringPtr(spotpool.Spec.SubnetId),
  VpcId:    common.StringPtr(spotpool.Spec.VpcId),
 }

 // print request
 fmt.Println(request.ToJsonString())

 // 創建實例
 response, err := client.RunInstances(request)
 if _, ok := err.(*errors.TencentCloudSDKError); ok {
  return err
 }
 // other errors
 if err != nil {
  return err
 }

 // 獲取到返回的 instancesid
 instanceIds := make([]string, 0, len(response.Response.InstanceIdSet))
 for _, instanceId := range response.Response.InstanceIdSet {
  instanceIds = append(instanceIds, *instanceId)
 }

 fmt.Println("run instances success", instanceIds)
 // 更新 status
 _, err = r.getRunningInstanceIds(spotpool)
 if err != nil {
  return err
 }
 return nil
}

這個方法主要是調用 client.RunInstances(request) 進行實例創建,然后調用 r.getRunningInstanceIds(spotpool) 更新 status 的狀態信息。

(3)開發r.terminateInstances(spotpool, delta) 用于調用云平臺進行縮容

func (r *SpotpoolReconciler) terminateInstances(spotpool *devopsjokerbaicomv1.Spotpool, count int32) error {
 client, err := r.createCVMClient(spotpool.Spec)
 if err != nil {
  return err
 }

 runningInstances, err := r.getRunningInstanceIds(spotpool)
 if err != nil {
  return err
 }

 instancesIds := runningInstances[:count]
 request := cvm.NewTerminateInstancesRequest()
 request.InstanceIds = common.StringPtrs(instancesIds)

 // 獲取返回
 response, err := client.TerminateInstances(request)
 if _, ok := err.(*errors.TencentCloudSDKError); ok {
  return err
 }
 // other errors
 if err != nil {
  return err
 }

 fmt.Println("Terminate response: ", response)
 fmt.Println("terminate instances success", instancesIds)

 // 更新 status
 _, err = r.getRunningInstanceIds(spotpool)
 if err != nil {
  return err
 }
 return nil
}

刪除實例和創建實例的實現邏輯類似,先調用 client.TerminateInstances(request) 進行刪除,然后調用 r.getRunningInstanceIds(spotpool) 更新狀態。

上面三個步驟完成了主要邏輯開發,可以初步實現具體的效果,如果希望功能更健全,則需要對其進行開發優化。

部署和測試

1.本地測試

# 安裝 CRD
make install
# 運行 controller
make run

2.創建 Spotpool 實例測試

(1)創建 Spotpool 資源清單,編輯 config/samples/devops.jokerbai.com_v1_spotpool.yaml

apiVersion: devops.jokerbai.com.jokerbai.com/v1
kind: Spotpool
metadata:
  labels:
    app.kubernetes.io/name: spotpool
    app.kubernetes.io/managed-by: kustomize
  name: spotpool-sample
spec:
  secretId: xxx
  secretKey: xxx
  region: ap-singapore
  availabilityZone: ap-singapore-2
  instanceType: "GN7.2XLARGE32"
  minimum: 2
  maximum: 2
  subnetId: DEFAULT
  vpcId: DEFAULT
  securityGroupIds:
    - sg-xxx
  imageId: img-xxx
  instanceChargeType: SPOTPAID

(2)運行資源清單

# 創建實例
kubectl apply -f config/samples/devops.jokerbai.com_v1_spotpool.yaml

# 查看狀態
kubectl get spotpool

(3)構建并部署到集群

# 構建鏡像
make docker-build docker-push IMG=<your-registry>/spotpool:v1

# 部署到集群
make deploy IMG=<your-registry>/spotpool:v1

(4)清理

# 刪除 operator
make undeploy

# 刪除 CRD
make uninstall

最后

本文通過結合 Kubernetes、AI 和云平臺,深入探討了如何利用 K8s Operator 實現對 GPU 資源池的自動化管理。我們從 Operator 的核心概念出發,介紹了 CRD(自定義資源定義)和控制器的設計原理,并基于 kubebuilder 開發了一個名為 Spotpool 的 Operator,用于在騰訊云上維護競價實例的穩定運行。

整個開發過程遵循“聲明式 API”的思想,用戶只需定義期望的狀態(如最小/最大實例數),Operator 便會在后臺持續監控并自動調整實際狀態,確保資源池始終符合預期。這不僅極大地簡化了運維操作,也提升了 AI 模型訓練平臺的穩定性和彈性。

Operator 是云原生時代自動化運維的重要利器。掌握其開發方法,意味著我們不僅能“用好” Kubernetes,更能“擴展” Kubernetes,為復雜業務場景提供定制化的解決方案。

責任編輯:姜華 來源: 運維開發故事
相關推薦

2024-12-16 07:41:35

2025-01-03 17:07:23

2024-12-17 16:20:40

2022-12-16 08:31:37

調度線程池源碼

2015-05-05 09:37:29

OpenStackNova資源統計

2022-06-13 14:31:02

資源調度鴻蒙

2023-04-26 15:36:51

WPA鴻蒙

2022-06-27 10:25:55

Kubernetes調度CPU

2010-08-12 15:38:39

IT運維網管軟件摩卡軟件

2009-06-17 16:22:45

Hibernate連接

2024-10-21 09:18:47

2013-06-08 13:07:23

Java線程池調度器

2025-01-08 08:49:50

2010-03-23 17:18:50

云計算資源調度

2012-01-16 09:00:18

云計算高性能計算

2022-07-27 19:27:47

CPU資源內存

2013-07-30 10:15:37

2020-07-08 08:30:28

Windows操作系統功能

2023-12-29 09:38:00

Java線程池

2015-09-01 10:42:36

Cloudsim云計算資源調度算法
點贊
收藏

51CTO技術棧公眾號

神马电影网我不卡| 精品久久久久一区二区三区| 欧美性色综合| 亚洲男人天堂视频| 91在线第一页| 在线人成日本视频| 国产精品乱码久久久久久| 俄罗斯精品一区二区三区| 国产伦精品一区二区三区视频网站 | 天天综合网91| 欧美一区二区视频在线观看2020 | 亚洲成a人在线观看| 精品国产一区二区三区麻豆免费观看完整版 | 国产三级漂亮女教师| 午夜国产欧美理论在线播放| 亚洲人成在线观| www.com日本| 国产一区二区三区四区五区3d| 久久色中文字幕| 91视频最新| 中文字幕第三页| 国产亚洲精品久久久久婷婷瑜伽| 精品区一区二区| 少妇人妻互换不带套| 高清电影在线免费观看| 国产精品久久毛片av大全日韩| 国产主播在线一区| 中文字幕在线欧美| 亚洲国产精品第一区二区三区| 91精品国产高清一区二区三区蜜臀| 亚洲福利av| 天堂a√中文在线| 国产不卡免费视频| 91精品国产综合久久久久久蜜臀 | 成人福利网站在线观看| 日本一级黄色大片| 欧美网站在线| 欧美精品日韩www.p站| 国产123在线| 国产成人精品三级高清久久91| 欧美专区亚洲专区| 99热亚洲精品| 激情影院在线| 一区二区三区高清| 艳母动漫在线观看| 久久精品视频观看| 亚洲欧洲综合另类在线| 中文字幕欧美人与畜| 在线看的av网站| 国产精品拍天天在线| 日韩欧美三级电影| avav免费在线观看| 国产精品久久网站| 成年人黄色在线观看| 秋霞午夜理伦电影在线观看| 国产精品久久久久aaaa| 伊人久久99| 黄在线免费观看| 亚洲免费av高清| 久久久99精品视频| 91超碰在线| 日韩欧美一区二区三区| 日韩欧美在线免费观看视频| 国产一区二区主播在线| 欧美日韩精品欧美日韩精品一综合 | 天堂资源最新在线| 久久综合999| 日本在线一区| 欧美精品电影| 亚洲主播在线观看| 精品人妻一区二区三区四区在线| 国产大片在线免费观看| 国产精品网曝门| 国产精品久久成人免费观看| 俄罗斯一级**毛片在线播放| 午夜激情久久久| 999香蕉视频| 久久av日韩| 欧美成人综合网站| 亚洲AV无码国产精品| 欧美偷拍综合| 欧美激情精品久久久久久大尺度 | 免费av一区二区三区四区| 欧美中文字幕一区| 99中文字幕在线| 六月丁香久久丫| 在线性视频日韩欧美| 国产免费久久久久| 99精品国产在热久久| 国产精品入口免费视| 国产又黄又粗又长| 成人福利视频网站| 一区视频二区视频| 国产盗摄——sm在线视频| 91国内精品野花午夜精品| 日本一二三四区视频| 日韩高清一级| 久久久精品一区| 国产免费观看av| 国产另类ts人妖一区二区| 久久波多野结衣| 黄色av网站在线播放| 偷拍一区二区三区| 日韩高清第一页| 亚瑟一区二区三区四区| 欧美成人性色生活仑片| 免费看日批视频| 福利电影一区二区三区| 亚洲人体一区| 少妇在线看www| 日韩网站在线看片你懂的| 91在线无精精品白丝| 亚洲午夜电影| 成人亚洲激情网| 免费在线超碰| 亚洲国产成人tv| 久久久久久综合网| 日韩电影免费网站| 欧美一区二区三区免费视| www.日本在线观看| 国产精品卡一卡二| 另类小说第一页| 中文有码一区| 性金发美女69hd大尺寸| 在线视频 91| 日本一区免费视频| 精品一区二区中文字幕| 都市激情亚洲| 欧美激情视频播放| 国产伦一区二区| 中文字幕一区日韩精品欧美| 欧洲熟妇精品视频| 一本久久青青| 欧美在线免费观看| 亚洲欧美色视频| 五月婷婷激情综合网| 日本天堂在线播放| 亚洲无线视频| 国产高清自拍99| 手机av在线播放| 欧美一级淫片007| 无码人妻精品一区二区三区夜夜嗨| 91久久午夜| 国产精品久久久久久久小唯西川| 瑟瑟在线观看| 亚洲成国产人片在线观看| 日韩无码精品一区二区| 亚洲国产高清一区二区三区| 国产精品swag| 136福利第一导航国产在线| 精品国产乱码久久久久久图片 | 色黄视频免费看| 99久久精品费精品国产| 国产精品视频久久久久| 99青草视频在线播放视| 欧美日韩免费在线视频| 最新av电影网站| 国产激情精品久久久第一区二区 | 中文字幕一区二区av| 91久久国产精品91久久性色| 欧美黄色激情| 日韩欧美电影一区| 国产成人精品片| 久久久亚洲精品石原莉奈| 国产精品免费成人| 四虎国产精品免费观看| 亚洲r级在线观看| 综合图区亚洲| 亚洲精品国产拍免费91在线| 中文字幕免费观看| 亚洲色图一区二区| aaa黄色大片| 三级一区在线视频先锋| 一本色道婷婷久久欧美| 亚洲精品不卡在线观看 | √天堂8资源中文在线| 日韩久久精品成人| 在线观看免费高清视频| 一区二区视频免费在线观看| 中文字幕在线观看91| 亚洲欧美高清| 亚洲一一在线| 国产精品18hdxxxⅹ在线| 日韩免费不卡av| 国产一区久久精品| 日韩成人av网| 国产女18毛片多18精品| 精品久久久久久电影| 东京热无码av男人的天堂| 国产高清精品网站| 日日碰狠狠丁香久燥| 亚洲美女视频| 日本a级片久久久| 精品视频一区二区三区| 热re91久久精品国99热蜜臀| 成年人黄视频在线观看| 精品无码久久久久久国产| 国产精品嫩草影院桃色| 一本一本大道香蕉久在线精品 | 污污网站在线免费观看| 精品婷婷伊人一区三区三| 中文字幕第28页| 中文字幕一区二区三区在线不卡| 超碰在线97免费| 黑丝一区二区三区| 一区二区在线观| 亚洲v天堂v手机在线| 999国产在线| 麻豆久久久久| 日本视频久久久| heyzo中文字幕在线| 久久精品精品电影网| 黄色美女网站在线观看| 亚洲精品国产综合久久| www.国产欧美| 欧美一级黄色大片| 中文无码av一区二区三区| 精品久久久久久久久久久| 欧美人禽zoz0强交| 国产精品区一区二区三| 色无极影院亚洲| 成人国产精品免费观看动漫 | 中文av在线全新| 欧美另类高清videos| 成人全视频高清免费观看| 亚洲国产精品yw在线观看| 精品人妻一区二区三区蜜桃| 欧美另类z0zxhd电影| 中文字幕第三页| 一本大道久久精品懂色aⅴ| 日韩av一二三区| 亚洲成人av电影在线| 国产精品成人国产乱| 亚洲精品日韩综合观看成人91| 白嫩情侣偷拍呻吟刺激| 极品尤物av久久免费看| av网站在线不卡| 天堂成人国产精品一区| 四虎永久在线精品无码视频| 国产美女一区| 免费高清在线观看免费| 亚洲欧美日韩国产一区| 久久久久免费看黄a片app| 亚洲小说欧美另类社区| 国产美女作爱全过程免费视频| 久久综合五月婷婷| 国产在线一区二区三区欧美| 91免费精品国偷自产在线在线| 韩国三级日本三级少妇99| 菠萝蜜视频国产在线播放| 久久精品一本久久99精品| 欧美日本一道| 久久99国产综合精品女同| 在线中文字幕视频观看| 色综合导航网站| 秋霞在线午夜| 91精品国产高清久久久久久| av福利导福航大全在线| 欧美在线视频在线播放完整版免费观看 | 国产又粗又爽视频| 欧美性猛交xxxx免费看| 五月天综合激情网| 在线观看一区日韩| 国产精品久久久久久久久毛片| 五月天丁香久久| 六月丁香婷婷综合| 欧美亚洲高清一区二区三区不卡| 久久久久无码精品国产| 亚洲va国产va欧美va观看| 亚洲日本韩国在线| 欧美伊人久久久久久久久影院 | 日韩av电影免费观看| 青草国产精品| 超碰97在线看| 亚洲一区久久| 一区二区三区四区毛片| 丰满岳乱妇一区二区三区| 爱爱免费小视频| 国产精品久久网站| 欧美一级高潮片| 欧美三级三级三级爽爽爽| 精品人妻伦一二三区久久 | 忘忧草精品久久久久久久高清| 欧美视频一区二区三区…| 日本黄色免费观看| 99久久精品费精品国产| 女人帮男人橹视频播放| 老牛国产精品一区的观看方式| 超碰超碰超碰超碰超碰| 国产精品入口| 亚洲日本黄色片| 96av麻豆蜜桃一区二区| 一区二区三区影视| 色综合久久综合| 精品人妻无码一区二区色欲产成人 | 日韩中文在线中文网三级| 欧美1234区| 欧美亚洲在线播放| 麻豆精品久久| 丝袜美腿玉足3d专区一区| 欧美日韩伊人| 最新天堂在线视频| 26uuu亚洲婷婷狠狠天堂| 极品久久久久久| 在线观看日韩精品| 噜噜噜久久,亚洲精品国产品| 欧美不卡激情三级在线观看| 超碰免费97在线观看| 81精品国产乱码久久久久久| 国产精品久久久久久久久久辛辛 | 亚洲精品久久久久久| 国产亚洲欧美日韩在线一区| 强乱中文字幕av一区乱码| 欧美三级电影在线观看| 全部免费毛片在线播放网站| 欧美日本黄视频| 国产日韩在线观看视频| 亚洲人成网站在线观看播放| 噜噜噜躁狠狠躁狠狠精品视频| 成年人视频在线免费| 高清国产一区二区三区| 动漫性做爰视频| 欧美精品日韩一本| a天堂在线资源| 国产97在线视频| 你懂的视频欧美| 99热在线这里只有精品| 成人福利视频在线| 国产午夜精品一区二区理论影院 | 国产又爽又黄免费软件| 精品视频一区在线视频| 国产蜜臀在线| 国产精品免费一区二区三区观看| 妖精视频一区二区三区| 青青艹视频在线| www.66久久| 亚洲国产成人精品激情在线| 精品国产91亚洲一区二区三区婷婷 | 亚洲视频导航| 蜜桃精品视频在线| 四虎影视一区二区| 777午夜精品免费视频| 欧美精品videos另类| 91精品国产综合久久香蕉的用户体验 | 欧美欧美一区二区| 视频在线在亚洲| 最近中文字幕免费| 欧美在线看片a免费观看| 99re热久久这里只有精品34| 国产欧美精品日韩| 亚洲成人三区| 色哟哟网站在线观看| 亚洲成a人片在线不卡一二三区| 国产精品第6页| 最新69国产成人精品视频免费| a天堂中文在线官网在线| 91成人在线播放| 欧美日韩一区二区三区四区不卡| 中文字幕剧情在线观看一区| 久久99精品久久久久久久久久久久| 日本三级日本三级日本三级极| 国产精品毛片久久久久久久| 亚洲天堂网视频| 欧美精品在线免费播放| 高潮按摩久久久久久av免费| 国产a级一级片| 久久精品视频免费观看| 在线免费av网| 欧美激情一区二区三区久久久| 日韩精品第二页| 看一级黄色录像| 99在线视频精品| 精品黑人一区二区三区| 久热精品视频在线免费观看 | 久久国产精品亚洲77777| 久久午夜精品视频| 欧美不卡一区二区三区| 男人久久天堂| 亚洲一区二区三区午夜| 丁香五精品蜜臀久久久久99网站| www深夜成人a√在线| 日韩精品中文字幕一区二区三区| 色综合久久久久综合一本到桃花网| 欧美一级淫片videoshd| 国产在视频线精品视频www666| 欧美女人性生活视频| 国产精品乱码久久久久久| www.com欧美| 国产精品精品视频一区二区三区| 免费一区二区三区视频导航| 久国产精品视频| 动漫精品一区二区| а√天堂资源地址在线下载| 精品无码久久久久久久动漫| 六月丁香婷婷色狠狠久久| 日本少妇裸体做爰| 久久精品视频va| 伊人久久大香线蕉| 91人妻一区二区三区| 在线观看一区不卡|