首页 > 其他 > 详细

Deployment-k8s

时间:2020-04-21 16:45:54      阅读:72      评论:0      收藏:0      [点我收藏+]

Deployment

Deployment 为 Pod 和 ReplicaSet 提供了?个声明式定义(declarative)?法,?来替代以前的ReplicationController 来?便的管理应?

典型的应?场景包括:

  • 定义Deployment来创建Pod和ReplicaSet
  • 滚动升级和回滚应?
  • 扩容和缩容
  • 暂停和继续Deployment
一个简单的nginx应?可以定义为
apiVersion: extensions/v1beta1
kind: Deployment
metadata:
  name: nginx-deployment
spec:
  replicas: 3
  template:
    metadata:
      labels:
        app: nginx
    spec:
      containers:
      - name: nginx
        image: nginx:1.7.9
        ports:
        - containerPort: 80

扩容
kubectl scale deployment nginx-deployment --replicas 10

如果集群?持 horizontal pod autoscaling 的话,还可以为Deployment设置?动扩展:
kubectl autoscale deployment nginx-deployment --min=10 --max=15 --cpu-percent=80

更新镜像也?较简单:
kubectl set image deployment/nginx-deployment nginx=nginx:1.9.1

回滚:
kubectl rollout undo deployment/nginx-deployment

Deployment 是什么?

Deployment为Pod和Replica Set(下?代Replication Controller)提供声明式更新

您只需要在 Deployment 中描述您想要的?标状态是什么,Deployment controller 就会帮您将 Pod 和ReplicaSet 的实际状态改变到您的?标状态。您可以定义?个全新的 Deployment 来创建 ReplicaSet 或者删除已有的 Deployment 并创建?个新的来替换

典型的?例如下:

  • 使?Deployment来创建ReplicaSet。ReplicaSet在后台创建pod。检查启动状态,看它是成功还是失败。
    然后,通过更新Deployment的PodTemplateSpec字段来声明Pod的新状态。这会创建?个新的ReplicaSet,
  • Deployment会按照控制的速率将pod从旧的ReplicaSet移动到新的ReplicaSet中。
  • 如果当前状态不稳定,回滚到之前的Deployment revision。每次回滚都会更新Deployment的revision。
  • 扩容Deployment以满?更?的负载。
  • 暂停Deployment来应?PodTemplateSpec的多个修复,然后恢复上线。
  • 根据Deployment 的状态判断上线是否hang住了。
  • 清除旧的不必要的 ReplicaSet。

Replication ControllerReplica Set两种资源对象:

RCRS的功能相似,RS支持集合的selector 。

RC是k8s的核心概念,其功能:

1,确保Pod数量:它会确保Kubernetes中有指定数量的Pod在运行,如果少于指定数量的Pod,RC就会创建新的,反之这会删除多余的,保证Pod的副本数量不变。
2,确保Pod健康:当Pod不健康,比如运行出错了,总之无法提供正常服务时,RC也会杀死不健康的Pod,重新创建新的。
3,弹性伸缩:在业务高峰或者低峰的时候,可以用过RC来动态的调整Pod数量来提供资源的利用率,当然我们也提到过如果使用HPA这种资源对象的话可以做到自动伸缩
4,滚动升级:滚动升级是一种平滑的升级方式,通过逐步替换的策略,保证整体系统的稳定性

Deployment功能:管理pod

1,RC的全部功能:Deployment具备上面描述的RC的全部功能
2,事件和状态查看:可以查看Deployment的升级详细进度和状态
3,回滚:当升级Pod的时候如果出现问题,可以使用回滚操作回滚到之前的任一版本
4,版本记录:每一次对Deployment的操作,都能够保存下来,这也是保证可以回滚到任一版本的基础 
5,暂停和启动:对于每一次升级都能够随时暂停和启动

技术分享图片

一个Deployment拥有多个Replica Set,而一个Replica Set拥有一个或多个Pod。一个Deployment控制多个rs主要是为了支持回滚机制,每当Deployment操作时,Kubernetes会重新生成一个Replica Set并保留,以后有需要的话就可以回滚至之前的状态

创建 Deployment

$ kubectl create -f https://kubernetes.io/docs/user-guide/nginx-deployment.yaml --record

将kubectl的 --record 的 flag 设置为 true 可以在 annotation 中记录当前命令创建或者升级了该资源。这在未来会很有?,例如,查看在每个 Deployment revision 中执?了哪些命令

立即执行:

$ kubectl get deployments
NAME            DESIRED    CURRENT     UP-TO-DATE    AVAILABLE      AGE
nginx-deployment 3         0            0            0              1s

输出结果表明我们希望的repalica数是3(根据deployment中的 .spec.replicas 配置)当前replica数(
.status.replicas )是0, 最新的replica数( .status.updatedReplicas )是0,可?的replica数
( .status.availableReplicas )是0。

过?秒后再执? get 命令,

$ kubectl get deployments
NAME            DESIRED      CURRENT    UP-TO-DATE    AVAILABLE     AGE
nginx-deployment 3           3           3             3            18s

看到Deployment已经创建了3个 replica,所有的 replica 都已经是最新的了(包含最新的pod template),可
?的(根据Deployment中的 .spec.minReadySeconds 声明,处于已就绪状态的pod的最少个数)。执? kubectl get
rs 和 kubectl get pods 会显示Replica Set(RS)和Pod已创建

$ kubectl get rs
NAME                        DESIRED     CURRENT     READY        AGE
nginx-deployment-2035384211 3            3          0            18s

 ReplicaSet 的名字总是 <Deployment的名字>-<pod template的hash值> 
 
$ kubectl get pods --show-labels
NAME                              READY STATUS RESTARTS AGE LABELS
nginx-deployment-2035384211-7ci7o 1/1 Running 0 18s app=nginx,pod-template-hash=2035384211
nginx-deployment-2035384211-kzszj 1/1 Running 0 18s app=nginx,pod-template-hash=2035384211
nginx-deployment-2035384211-qqcnn 1/1 Running 0 18s app=nginx,pod-template-hash=2035384211

刚创建的Replica Set将保证总是有3个 nginx 的 pod 存在。
注意: 您必须在 Deployment 中的 selector 指定正确的 pod template label(在该示例中是 app = nginx ),不要跟其他的 controller 的 selector 中指定的 pod template label 搞混了(包括 Deployment、Replica Set、Replication
Controller 等)。Kubernetes 本身并不会阻?您任意指定 pod template label ,但是如果您真的这么做了,这些
controller 之间会相互打架,并可能导致不正确的?为

更新Deployment

注意: Deployment 的 rollout 当且仅当 Deployment 的 pod template(例如 .spec.template )中的label更新或者镜像更改时被触发。其他更新,例如扩容Deployment不会触发 rollout。

假如我们现在想要让 nginx pod 使? nginx:1.9.1 的镜像来代替原来的 nginx:1.7.9 的镜像。
$ kubectl set image deployment/nginx-deployment nginx=nginx:1.9.1
deployment "nginx-deployment" image updated

我们可以使? edit 命令来编辑 Deployment,修改 .spec.template.spec.containers[0].image ,将 nginx:1.7.9 改写成nginx:1.9.1 。
$ kubectl edit deployment/nginx-deployment
deployment "nginx-deployment" edited


查看 rollout 的状态,只要执?:
$ kubectl rollout status deployment/nginx-deployment
Waiting for rollout to finish: 2 out of 3 new replicas have been updated...
deployment "nginx-deployment" successfully rolled out


Rollout 成功后, get Deployment:
$ kubectl get deployments
NAME                DESIRED   CURRENT   UP-TO-DATE   AVAILABLE    AGE
nginx-deployment     3          3         3           3           36s

UP-TO-DATE 的 replica 的数?已经达到了配置中要求的数?
CURRENT 的 replica 数表示 Deployment 管理的 replica 数量,AVAILABLE 的 replica 数是当前可?的replica数量。

我们通过执? kubectl get rs 可以看到 Deployment 更新了Pod,通过创建?个新的 ReplicaSet 并扩容了3个 replica,同时将原来的 ReplicaSet 缩容到了0个 replica。
$ kubectl get rs
NAME                         DESIRED CURRENT READY AGE
nginx-deployment-1564180365  3       3       0     6s
nginx-deployment-2035384211  0       0       0     36s

执? get pods 只会看到当前的新的 pod:
$ kubectl get pods
NAME                              READY STATUS    RESTARTS   AGE
nginx-deployment-1564180365-khku8 1/1   Running   0          14s
nginx-deployment-1564180365-nacti 1/1   Running   0          14s
nginx-deployment-1564180365-z9gth 1/1   Running   0          14s

下次更新这些 pod 的时候,只需要更新 Deployment 中的 pod 的 template 即可。
Deployment 可以保证在升级时只有?定数量的 Pod 是 down 的。默认的,它会确保?少有?期望的Pod数量少?个是
up状态(最多?个不可?)。
Deployment 同时也可以确保只创建出超过期望数量的?定数量的 Pod。默认的,它会确保最多?期望的Pod数量多?
个的 Pod 是 up 的(最多1个 surge )

$ kubectl describe deployments

Label selector 更新

不?励更新 label selector,我们建议事先规划好您的 selector。

任何情况下,只要您想要执? label selector 的更新,请?定要谨慎并确认您已经预料到所有可能因此导致的后果。
增添 selector 需要同时在 Deployment 的 spec 中更新新的 label,否则将返回校验错误。此更改是不可覆盖的,这
意味着新的 selector 不会选择使?旧 selector 创建的 ReplicaSet 和 Pod,从?导致所有旧版本的 ReplicaSet 都被
丢弃,并创建新的 ReplicaSet。
更新 selector,即更改 selector key 的当前值,将导致跟增添 selector 同样的后果。
删除 selector,即删除 Deployment selector 中的已有的 key,不需要对 Pod template label 做任何更改,现有的
ReplicaSet 也不会成为孤?,但是请注意,删除的 label 仍然存在于现有的 Pod 和 ReplicaSet 中。

回退Deployment

默认情况下,kubernetes 会在系统中保存前两次的 Deployment 的 rollout 历史记录,以便您可以随时回退(您可以修改 revision history limit 来更改保存的revision数)

注意: 只要 Deployment 的 rollout 被触发就会创建?个 revision。也就是说当且仅当 Deployment 的 Pod
template(如 .spec.template )被更改,例如更新template 中的 label 和容器镜像时,就会创建出?个新的 revision

其他的更新,?如扩容 Deployment 不会创建 revision——因此我们可以很?便的?动或者?动扩容。这意味着当您回退到历史 revision 时,只有 Deployment 中的 Pod template 部分才会回退

假设我们在更新 Deployment 的时候犯了?个拼写错误,将镜像的名字写成了 nginx:1.91 ,?正确的名字应该
是 nginx:1.9.1 :
kubectl set image deployment/nginx-deployment nginx=nginx:1.91
Rollout 将会卡住
kubectl rollout status deployments nginx-deployment
按住 Ctrl-C 停?上?的 rollout 状态监控。

kubectl get rs
您会看到旧的 replica(nginx-deployment-1564180365 和 nginx-deployment-2035384211)和新的 replica (nginxdeployment-3066724191)数?都是2个
看下创建 Pod,您会看到有两个新的 ReplicaSet 创建的 Pod 处于 ImagePullBackOff 状态,循环拉取镜像
$ kubectl get pods

注意,Deployment controller会?动停?坏的 rollout,并停?扩容新的 ReplicaSet。
$ kubectl describe deployment

##修复错误:回滚
检查 Deployment 升级的历史记录
检查下 Deployment 的 revision:
$ kubectl rollout history deployment/nginx-deployment

创建 Deployment 的时候使?了 --record 参数可以记录命令,我们可以很?便的查看每次 revision 的变化
查看单个revision 的详细信息:
$ kubectl rollout history deployment/nginx-deployment --revision=2
回退到历史版本
kubectl rollout undo deployment/nginx-deployment
也可以使? --revision 参数指定某个历史版本
$ kubectl rollout undo deployment/nginx-deployment --to-revision=2

该 Deployment 现在已经回退到了先前的稳定版本。如您所?,Deployment controller产?了?个回退到revison 2
的 DeploymentRollback 的 event
$ kubectl get deployment

清理 Policy

您可以通过设置 .spec.revisonHistoryLimit 项来指定 deployment 最多保留多少 revision 历史记录。默认的会保留所有的revision;如果将该项设置为0,Deployment就不允许回退了。
Deployment 扩容

$ kubectl scale deployment nginx-deployment --replicas 10

假设您的集群中启?了horizontal pod autoscaling,您可以给 Deployment 设置?个 autoscaler,基于当前 Pod的 CPU利?率选择最少和最多的 Pod 数。
$ kubectl autoscale deployment nginx-deployment --min=10 --max=15 --cpu-percent=80

?例扩容

RollingUpdate Deployment ?持同时运??个应?的多个版本。或者 autoscaler 扩 容 RollingUpdate Deployment 的时候,正在中途的 rollout(进?中或者已经暂停的),为了降低?险,Deployment controller 将会平衡已存在的活动中的ReplicaSet(有 Pod 的 ReplicaSet)和新加?的 replica。这被称为?例扩容。
例如,您正在运?中含有10个 replica 的 Deployment。maxSurge=3,maxUnavailable=2

$ kubectl get deploy

暂停和恢复Deployment

可以在发出?次或多次更新前暂停?个 Deployment,然后再恢复它。这样您就能多次暂停和恢复 Deployment,在此期间进??些修复?作,?不会发出不必要的 rollout。

$ kubectl get deploy
NAME DESIRED CURRENT UP-TO-DATE AVAILABLE AGE
nginx 3 3 3 3 1m
[mkargaki@dhcp129-211 kubernetes]$ kubectl get rs
NAME DESIRED CURRENT READY AGE
nginx-2142116321 3 3 3 1m


暂停 Deployment:
$ kubectl rollout pause deployment/nginx-deployment
deployment "nginx-deployment" paused

然后更新 Deplyment中的镜像:
$ kubectl set image deploy/nginx nginx=nginx:1.9.1
deployment "nginx-deployment" image updated

注意新的 rollout 启动了:
$ kubectl rollout history deploy/nginx
deployments "nginx"
REVISION CHANGE-CAUSE
1 <none>
$ kubectl get rs
NAME DESIRED CURRENT READY AGE
nginx-2142116321 3 3 3 2m
您可以进?任意多次更新,例如更新使?的资源:
$ kubectl set resources deployment nginx -c=nginx --limits=cpu=200m,memory=512Mi
deployment "nginx" resource requirements updated

Deployment 暂停前的初始状态将继续它的功能,?不会对 Deployment 的更新产?任何影响,只要 Deployment是暂停
的。
最后,恢复这个 Deployment,观察完成更新的 ReplicaSet 已经创建出来了

$ kubectl rollout resume deploy nginx
$ KUBECTL get rs -w
$ KUBECTL get rs

Deployment 状态

Deployment 在?命周期中有多种状态。在创建?个新的 ReplicaSet 的时候它可以是 progressing 状态, complete 状态,或者 fail to progress 状态。

进?中的 Deployment
Kubernetes 将执?过下列任务之?的 Deployment 标记为 progressing 状态:
Deployment 正在创建新的ReplicaSet过程中。
Deployment 正在扩容?个已有的 ReplicaSet。
Deployment 正在缩容?个已有的 ReplicaSet。
有新的可?的 pod 出现。

使? kubectl rollout status 命令监控 Deployment 的进度

Kubernetes 将包括以下特性的 Deployment 标记为 complete 状态:

  • Deployment 最?可?。最?可?意味着 Deployment 的可? replica 个数等于或者超过 Deployment 策略中的期望个数。
  • 所有与该 Deployment 相关的replica都被更新到了您指定版本,也就说更新完成。
  • 该 Deployment 中没有旧的 Pod 存在。

您可以? kubectl rollout status 命令查看 Deployment 是否完成。如果 rollout 成功完成, kubectl rollout status 将返回?个0值的 Exit Code

$ kubectl rollout status deploy/nginx

失败的 Deployment

Deployment 在尝试部署新的 ReplicaSet 的时候可能卡住,永远也不会完成。这可能是因为以下?个因素引起
的:

?效的引?
不可读的 probe failure
镜像拉取错误
权限不够
范围限制
程序运?时配置错误

探测这种情况的?种?式是,在您的 Deployment spec 中指定 spec.progressDeadlineSeconds 。 spec.progressDeadlineSeconds 表示 Deployment controller 等待多少秒才能确定(通过Deployment status)Deployment进程是卡住的。

下?的 kubectl 命令设置 progressDeadlineSeconds 使 controller 在 Deployment 在进度卡住10分钟后报告:
$ kubectl patch deployment/nginx-deployment -p ‘{"spec":{"progressDeadlineSeconds":600}}‘

当超过截?时间后,Deployment controller 会在 Deployment 的 status.conditions 中增加?条DeploymentCondition,
它包括如下属性:
Type=Progressing
Status=False
Reason=ProgressDeadlineExceeded
注意: kubernetes除了报告 Reason=ProgressDeadlineExceeded 状态信息外不会对卡住的 Deployment 做任何操作。更?层次的协调器可以利?它并采取相应?动,例如,回滚 Deployment 到之前的版本。
注意: 如果您暂停了?个 Deployment,在暂停的这段时间内kubernetnes不会检查您指定的 deadline。您可以在
Deployment 的 rollout 途中安全的暂停它,然后再恢复它,这不会触发超过deadline的状态。

kubectl get deployment nginx-deployment -o yaml

?旦超过 Deployment 进程的 deadline,kuberentes 会更新状态和导致 Progressing 状态的原因

Conditions:
Type Status Reason


Available True MinimumReplicasAvailable
Progressing False ProgressDeadlineExceeded
ReplicaFailure True FailedCreate

您可以通过缩容 Deployment的?式解决配额不?的问题,或者增加您的 namespace 的配额。如果您满?了配额条件后,Deployment controller 就会完成您的 Deployment rollout,您将看到 Deployment 的状态更新为成功状态
( Status=True 并且 Reason=NewReplicaSetAvailable )。
Conditions:
Type Status Reason


Available True MinimumReplicasAvailable
Progressing True NewReplicaSetAvailable

Type=Available 、 Status=True 以为这您的Deployment有最?可?性。 最?可?性是在Deployment策略中指定的参
数。 Type=Progressing 、 Status=True 意味着您的Deployment 或者在部署过程中,或者已经成功部署,达到了期望的最少的可?replica数量(查看特定状态的Reason——在我们的例?中 Reason=NewReplicaSetAvailable 意味着Deployment已经完成)

?丝雀 Deployment

如果您想要使? Deployment 对部分?户或服务器发布 release,您可以创建多个 Deployment,每个 Deployment 对应?个 release,参照 managing resources 中对?丝雀模式的描述

Deployment 实操

Deployment,它创建了一个Replica Set来启动3个nginx pod

apiVersion: apps/v1beta1
kind: Deployment
metadata:
  name: nginx-deploy
  labels:
    k8s-app: nginx-demo
spec:
  replicas: 3
  template:
    metadata:
      labels:
        app: nginx
    spec:
      containers:
      - name: nginx
        image: nginx:1.7.9
        ports:
        - containerPort: 80
#执行
$ kubectl create -f nginx-deployment.yaml
#查看
$ kubectl get deployments
NAME           DESIRED   CURRENT   UP-TO-DATE   AVAILABLE   AGE
nginx-deploy   3         0         0            0           1s
稍等几秒再查看
$ kubectl get deployments
NAME           DESIRED   CURRENT   UP-TO-DATE   AVAILABLE   AGE
nginx-deploy   3         3         3            3           4m
#查看Replica Set 执行下面的命令查看rs和pod
$ kubectl get rs
NAME                     DESIRED   CURRENT   READY     AGE
nginx-deploy-431080787   3         3         3         6m

$ kubectl get pod --show-labels
NAME                           READY     STATUS    RESTARTS   AGE       LABELS
nginx-deploy-431080787-53z8q   1/1       Running   0          7m        app=nginx,pod-template-hash=431080787
nginx-deploy-431080787-bhhq0   1/1       Running   0          7m        app=nginx,pod-template-hash=431080787
nginx-deploy-431080787-sr44p   1/1       Running   0          7m        app=nginx,pod-template-hash=431080787

#滚动升级
将刚刚保存的yaml文件中的nginx镜像修改为nginx:1.13.3,然后在spec下面添加滚动升级策略:
minReadySeconds: 5
strategy:
  # indicate which strategy we want for rolling update
  type: RollingUpdate
  rollingUpdate:
    maxSurge: 1
    maxUnavailable: 1
    
minReadySeconds:
    Kubernetes在等待设置的时间后才进行升级
    如果没有设置该值,Kubernetes会假设该容器启动起来后就提供服务了
    如果没有设置该值,在某些极端情况下可能会造成服务不正常运行
maxSurge:
    升级过程中最多可以比原先设置多出的POD数量
    例如:maxSurage=1,replicas=5,则表示Kubernetes会先启动1一个新的Pod后才删掉一个旧的POD,整个升级过程中最多会有5+1个POD。
maxUnavaible:
    升级过程中最多有多少个POD处于无法提供服务的状态
    当maxSurge不为0时,该值也不能为0
    例如:maxUnavaible=1,则表示Kubernetes整个升级过程中最多会有1个POD处于无法服务的状态。
#然后执行命令:
$ kubectl apply -f nginx-deployment.yaml

#使用rollout命令
$ kubectl rollout status deployment/nginx-deploy   查看状态
$ kubectl rollout pause deployment <deployment>    暂停升级
$ kubectl rollout resume deployment <deployment>   继续升级
升级结束,查看状态
$ kubectl get rs

#回滚Deployment
查看Deployment的升级历史
$ kubectl rollout history deployment nginx-deploy  
在执行Deployment升级的时候最好带上record参数,便于我们查看历史版本信息。
默认情况下,所有通过kubectl xxxx --record都会被kubernetes记录到etcd进行持久化,这无疑会占用资源,最重要的是,时间久了,当你kubectl get rs时,会有成百上千的垃圾RS返回给你,那时你可能就眼花缭乱了。

上生产时,我们最好通过设置Deployment的.spec.revisionHistoryLimit来限制最大保留的revision number,比如15个版本,回滚的时候一般只会回滚到最近的几个版本就足够了。其实rollout history中记录的revision都和ReplicaSets一一对应。如果手动delete某个ReplicaSet,对应的rollout history就会被删除,也就是还说你无法回滚到这个revison了。

rollout history和ReplicaSet的对应关系,可以在kubectl describe rs $RSNAME返回的revision字段中得到,这里的revision就对应着rollout history返回的revison。

$ kubectl rollout history deployment nginx-deploy --revision=3  查看单个版本信息
假如现在要直接回退到当前版本的前一个版本
$ kubectl rollout undo deployment nginx-deploy
也可以用revision回退到指定的版本
$ kubectl rollout undo deployment nginx-deploy --to-revision=2

StatefulSet

StatefulSet 作为 Controller 为 Pod 提供唯?的标识。它可以保证部署和 scale 的顺序

StatefulSet是为了解决有状态服务的问题(对应Deployments和ReplicaSets是为?状态服务?设计),其应?场景包
括:

  • 稳定的持久化存储,即Pod重新调度后还是能访问到相同的持久化数据,基于PVC来实现
  • 稳定的?络标志,即Pod重新调度后其PodName和HostName不变,基于Headless Service(即没有Cluster IP的
    Service)来实现
  • 有序部署,有序扩展,即Pod是有顺序的,在部署或者扩展的时候要依据定义的顺序依次依次进?(即从0到N-1,
  • 在下?个Pod运?之前所有之前的Pod必须都是Running和Ready状态),基于init containers来实现有序收缩,有序删除(即从N-1到0)

StatefulSet由以下?个部分组成:

  • ?于定义?络标志(DNS domain)的Headless Service
  • ?于创建PersistentVolumes的volumeClaimTemplates
  • 定义具体应?的StatefulSet

StatefulSet中每个Pod的DNS格式为 statefulSetName-{0..N-1}.serviceName.namespace.svc.cluster.local ,其中

  • serviceName 为Headless Service的名字
  • 0..N-1 为Pod所在的序号,从0开始到N-1
  • statefulSetName 为StatefulSet的名字
  • namespace 为服务所在的namespace,Headless Servic和StatefulSet必须在相同的namespace
  • .cluster.local 为Cluster Domain

StatefulSet 适?于有以下某个或多个需求的应?:

  • 稳定,唯?的?络标志。
  • 稳定,持久化存储。
  • 有序,优雅地部署和 scale。
  • 有序,优雅地删除和终?。
  • 有序,?动的滚动升级。

稳定是 Pod (重新)调度中持久性的代名词。 如果应?程序不需要任何稳定的标识符、有序部署、删除和scale,则应该使?提供?组?状态副本的 controller 来部署应?程序,例如 Deployment 或 ReplicaSet 可能更适合您的?状态需求

Deployment-k8s

原文:https://www.cnblogs.com/g2thend/p/12745066.html

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!