分享

Kubernetes进阶(一)

 塞北de雪 2023-07-26 发布于江苏
  • 文章目录

  • 一、Kubernetes实现蓝绿部署

  • 1.1 什么是蓝绿部署

  • 1.2 滚动更新

  • 1.3 回滚

  • 二、使用yaml(yml)文件创建、删除容器

  • 三、自动创建 YAML文件

  • 四、名称空间创建

  • 4.1生命创造者

  • 4.2 用get命令导出

  • 五、健康检查

  • 六、探针类型

  • 七、应用自修复

一、 库伯内特斯 实现蓝绿部署

1.1 什么是蓝绿部署

蓝绿部署,英文名Blue Green Deployment,是一种可以保证系统在不间断提供服务的情况下上线的部署方式。

蓝绿部署的模型中包含两个集群,就好比海豚的左脑和右脑。

在没有上线的正常情况下,集群A和集群B的代码版本是一致的,并且同时对外提供服务。
在系统升级的时候下,我们首先把一个集群(比如集群A)从负载列表中摘除,进行新版本的部署。集群B仍然继续提供服务。

当集群A升级完毕,我们把负载均衡重新指向集群A,再把集群B从负载列表中摘除,进行新版本的部署。集群A重新提供服务。

1.2 滚动更新

// 创建模块
[根@主人~]#麦克迪尔阿帕奇

// 编写 dockerfile文件
[根@主人~]#猫阿帕奇/码头文件 
来自电话亭

运行mkDH/数据和回声"你好,我是测试1"&tg;/数据/索引。HTMLml

ENTRYPOINT ["/bin/httpd","-f","-h","/data"]

#v1版本
// 创建两个不同版本的镜像
[根@主人~]#码头建设-T-高芬达1225/httPD:V1阿帕奇/
将构建上下文发送到码头守护程序2.048kb
步骤1/3:来自电话亭
最新资料:图书馆/电话亭
3cb635b06a2:拉完 
Digest: sha256:b5cfd4befc119a590ca1a81d6bb0fa1fb19f1fbebd0397f25fae164abe1e8a6a
最新图片:最新图片
 ---> ffe9d497c324
步骤2/3:运行mkDH/数据和回声"你好,这是测试1"&tg;/数据/索引。html
 ---> Running in 2400a9edc3b7
拆除中间容器
 ---> b596ff036149
Step 3/3 : ENTRYPOINT ["/bin/httpd","-f","-h","/data"]
 ---> Running in 9bad15d04393
移动中间容器
 ---> 21d6bd11fd0d
成功建成21D6BD11FD0D
成功标记高峰1225/HTPD:V1

#v2版本
//"创世之父"一行:回声"你好啊,这是实验2";数据/索引。
[根@主人~]#猫阿帕奇/码头文件 
来自电话亭

"你好,我是测试2"/"数据"/"索引2"/"数据"/"学习2"

ENTRYPOINT ["/bin/httpd","-f","-h","/data"]

[根@主人~]#码头建设-T-高芬达1225/httPD:V2阿帕奇/ 
将构建上下文发送到码头守护程序2.048kb
步骤1/3:来自电话亭
 ---> ffe9d497c324
步骤2/3:运行mkDH/数据和回声"你好,这是测试2"&tg;/数据/索引。HTMLml
 ---> Using cache
 ---> b596ff036149
Step 3/3 : ENTRYPOINT ["/bin/httpd","-f","-h","/data"]
 ---> Using cache
 ---> 21d6bd11fd0d
成功建成21D6BD11FD0D
成功标记高峰1225/HTPD:V2

// 登录 docker.hub仓库
[根@主人~]#码头工人登录
登录您的码头工人标识,以推动和拉图像从码头工人集散。如果你没有码头工人的身份证,直接去https://Hub.dker.com创建一个。
用户名:高峰1225
密码: 
警告!您的密码将在/根/中未加密地存储。码头工人/警察。
配置一个凭证助手来删除此警告。看
门户网站:/博士网站/引擎/参考资料/指令线/登录/#证书商店

登录成功

// 上传镜像当 docker.hub仓库 
[根@主人~]#码头推推高夫1225/httPD:V1
推指存储库[码头.io/gaofan1225/httPD]
88be387e4d70: Pushed 
64CAC/Eaf0da:安装在图书馆/电话亭 
v1: digest: sha256:074bdf0f11e9ee6f4efb2c12f67fdfab4eae8472fae1a75eb5004f3e5884ad3e size: 734

[根@主人~]#码头推推高夫1225/httPD:V2
推指存储库[码头.io/gaofan1225/httPD]
88be387e4d70: Pushed 
64Cac9Eaf0da:图层已经存在 
v2: digest: sha256:074bdf0f11e9ee6f4efb2c12f67fdfab4eae8472fae1a75eb5004f3e5884ad3e size: 734

// 创建一个httpd容器,使用v1版本的,并复制成三个
#库贝特尔创建部署httPD----------------------------------------------------------------------------
部署

[根@主人~]#库贝特尔得到豆荚
姓名准备状态重新启动年龄
httpd-8556845dfd-gct9q   1/1     Running   0          58s
httpd-8556845dfd-hcqrk   1/1     Running   0          58s
httpd-8556845dfd-zv9qz   1/1     Running   0          58s

// 暴露端口
#库贝特尔公开部署httPD--端口80--目标端口80
暴露的服务/httPD
[根@主人~]#库贝特尔得到SVC
名称集群----IP外部端口----IP端口
第80条/贸易协定6
kubernetes   ClusterIP   10.96.0.1      <none>        443/TCP   3m35s

// 访问测试
[root@master ~]# curl 10.96.192.41
你好,阿蒙,我是测试者1


// 做一个死循环
[根@主人~]#当:;卷成10.96.192.41;做完
你好,阿蒙,我是测试者1
你好,阿蒙,我是测试者1
你好,阿蒙,我是测试者1
你好,阿蒙,我是测试者1
你好,阿蒙,我是测试者1
你好,阿蒙,我是测试者1
你好,阿蒙,我是测试者1
你好,阿蒙,我是实验室1/V1。
......以下省略

// 升级版本
[根@主~]#库贝特尔设置图像部署/httPDhttPD=gaofan1225/httPD:V2
更新的部署情况

// 正在升级中
[根@主人~]#库贝特尔得到豆荚
姓名准备状态重新启动年龄
httpd-59b875c9dc-kkbdh   1/1     Running       0          4s
httpd-59b875c9dc-lhpjz   1/1     Running       0          6s
httpd-59b875c9dc-s7gmz   1/1     Running       0          8s
httpd-8556845dfd-fb887   1/1     Terminating   0          5m9s
httpd-8556845dfd-fhvlx   1/1     Terminating   0          5m6s
httpd-8556845dfd-l4rww   1/1     Terminating   0          5m7s


[根@主人~]#当:;卷成10.96.192.41;做完
你好,阿蒙,我是测试者1
你好,阿蒙,我是测试员2
你好,阿蒙,我是测试者1
你好,阿蒙,我是测试员2
你好,阿蒙,我是测试者1
你好,阿蒙,我是测试员2
你好,阿蒙,我是测试者1
你好,阿蒙,我是测试员2
......以下省略				// 升级过程中,两个版本的服务会同时滚动

// 升级结束
[根@主人~]#库贝特尔得到豆荚
姓名准备状态重新启动年龄
httpd-59b875c9dc-kkbdh   1/1     Running   0          71s
httpd-59b875c9dc-lhpjz   1/1     Running   0          73s
httpd-59b875c9dc-s7gmz   1/1     Running   0          75s


// 升级完成再去看死循环
[根@主人~]#当:;卷成10.96.192.41;做完
你好,阿蒙,我是测试员2
你好,阿蒙,我是测试员2
你好,阿蒙,我是测试员2
你好,阿蒙,我是测试员2
你好,阿蒙,我是测试员2
你好,阿蒙,我是测试员2
你好,阿蒙,我是测试员2
你好,阿蒙,我是测试员2
......以下省略			// 升级完成,v2版本一直滚动

1.2 回滚

// 回滚,返回上个版本
#库贝特尔推出撤销部署/httPD
部署.应用程序/NGINX后滚

// 开始回滚
[根@主人~]#库贝特尔得到豆荚
姓名准备状态重新启动年龄
httpd-59b875c9dc-kkbdh   1/1     Terminating         0          3m
httpd-59b875c9dc-lhpjz   1/1     Terminating         0          3m2s
httpd-59b875c9dc-s7gmz   1/1     Running             0          3m4s
httpd-8556845dfd-nzkvg   1/1     Running             0          1s
httpd-8556845dfd-zqqz4   1/1     Running             0          3s
httpd-8556845dfd-zt4b2   0/1     ContainerCreating   0          0s

// 回滚成功
[根@主人~]#库贝特尔得到豆荚
姓名准备状态重新启动年龄
httpd-8556845dfd-nzkvg   1/1     Running   0          44s
httpd-8556845dfd-zqqz4   1/1     Running   0          46s
httpd-8556845dfd-zt4b2   1/1     Running   0          43s

// 回滚完成再去看死循环
[根@主人~]#当:;卷成10.96.192.41;做完
你好,阿蒙,我是测试者1
你好,阿蒙,我是测试者1
你好,阿蒙,我是测试者1
你好,阿蒙,我是测试者1
你好,阿蒙,我是测试者1
你好,阿蒙,我是测试者1
你好,阿蒙,我是测试者1
hello amu,This is test1·		//  回滚成功,这里 v1 版本会一直滚动
......以下省略

二、使用 亚姆 (yml)文件创建、删除容器

k8s是一个容器编排引擎,使用YAML文件编排要部署应用,因此在学习之前,应先了解YAML语法格式:

  • 缩进表示层级关系

  • 不支持制表符 ”tab“ 缩进,使用空格缩进

  • 通常开头缩进 2 个空格

  • 字符后缩进 1 个空格,如冒号、逗号等

  • “—” 表示YAML格式,一个文件的开始

  • “#” 注释

必写参数:

参数名字意思
苦行阿片剂版本
仁慈的资源类型
元数据资源元数据
说明书资源规格
复制品副本数量
选择者标签选择器
模板脚板
元数据Pod元数据
说明书标准规格
集装箱容器配置

圣公会(圣公会)
在网上查看

Pod容器的字段拼写

kubectl + explain + 类型 + 对象命令
kubectl + explain + 类型 + 对象命令 + 对象命令分类

// 查看 metadata使用方式
#库贝克解释部署。元数据

// 查看 metadata对象的namespace的使用方式
[根@主人~]#库贝克解释部署。

// 列表对象开头必须添加 "-" 
<[]Object>

可参考的一个yaml文件图:
在这里插入图片描述

实例中

[root@master ~]# cd /opt/

// 创建目录
[根@主选]#米克迪尔曼菲
[根@主选机]#CD清单/


// 编写 dockerfile
# v1.1
[根@主清单]#CAT/根/阿帕奇/码头文件
来自电话亭

"嗨,我是V1"/"数据/索引"。  

ENTRYPOINT ["/bin/httpd","-f","-h","/data"]

[根@主舱单]#码头工建造-T-高芬克1225/httPD:V1.1/根/阿帕奇/


# v1.2
[根@主清单]#CAT/根/阿帕奇/码头文件
来自电话亭

"嗨,我是V2"/"数据/索引"。

ENTRYPOINT ["/bin/httpd","-f","-h","/data"]
[根@主舱单]#码头工建造-T-高芬克1225/httPD:V1.2/根/阿帕奇/

// 查看镜像
ENTRYPOINT ["/bin/httpd","-f","-h","/data"]
[根@主清单]#码头图片
创建的大小
4小时前的1.24mb
4小时前1.24mb


//编写部署文件。
[根@主舱单]#六部署。
---
应用程序/V1
类型:部署
元数据:
  姓名:网站
  名称空间:默认
职务:
  replicas: 3
  selector:			#选择
    matchLabels:	#匹配标签
      app: amu
  template:			#模板
    metadata:		#元数据
      labels:		#标签
        app: amu
    职务:
      集装箱:
      - image: gaofan1225/httpd:v1.1		#容器对象
        设想性政策:如果不存在#的话
        姓名:httPD

同位于:库贝特尔创建部署网络--图像=gaofan1225/httPD:V1.1--副本=3-n默认值


[根@主舱单]#6安全阀部署。
apiversion: v1
实物:服务
元数据: 
  姓名:网站
  名称空间:默认
职务:
  港口: 
  - port: 8001
    protocol: TCP							#协议
    targetPort: 80
  选择者:
    app: amu
  类型:无标记#

等同于:kubectl expose deployment web --port=8001 --target-port=80
 
// 查看pod、svc、deployment类型容器
[根@主舱单]#库贝特尔得到吊舱
在默认名称空间中找不到资源。 
[根@主清单]#库贝特尔获得SVC
名称集群----IP外部端口----IP端口
kubernetes   ClusterIP   10.96.0.1    <none>        443/TCP   28m

[根@主人~]#库贝特尔得到部署
在默认名称空间中找不到资源。


// 创建容器
[根@主清单]#库贝特尔创建--部署。 
部署/创建网络

[根@主舱单]#库贝特尔得到吊舱
姓名准备状态重新启动年龄
web-685c878c69-jkz62   1/1     Running   0          7s
web-685c878c69-nf968   1/1     Running   0          7s
web-685c878c69-vb7x6   1/1     Running   0          7s


[根@主人~]#库贝特尔得到部署
提供最新资料
web    3/3     3            3           79s

[根@主清单]#库贝特尔获得SVC
名称集群----IP外部端口----IP端口
kubernetes   ClusterIP   10.96.0.1       <none>        443/TCP          6h11m
web          NodePort    10.108.194.44   <none>        8001:30531/TCP   9s


// 访问测试
[root@master manifest]# curl 10.108.194.44:8001
嗨,阿蒙,我是V1

页面访问

访问:本机IP + 30531

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-BpHflaxb-1640080009887)(C:\Users\HP\AppData\Roaming\Typora\typora-user-images\image-20211221160119232.png)]

// 版本升级
[根@主舱单]#六部署。
---
应用程序/V1
类型:部署
元数据:
  姓名:网站
  名称空间:默认
职务:
  replicas: 3
  选择者:
    匹配标签:
      app: amu
  模板:
    元数据:
      标签:
        app: amu
    职务:				
      集装箱:
      - image: gaofan1225/httpd:v1.2	// 修改版本,删除 imagePullPolicy
        姓名:httPD

#库贝克尔申请-部署。 
警告:资源部署/Web缺失了ECTL应用程序所要求的库贝特配置注释,只应用于创建的资源,即创建-保存配置或库贝特应用程序。这个东西会自动修补。
部署.应用程序/网络配置

[根@主清单]#库贝特尔获得SVC
名称集群----IP外部端口----IP端口
kubernetes   ClusterIP   10.96.0.1       <none>        443/TCP          6h46m
web          NodePort    10.108.194.44   <none>        8001:30531/TCP   35m

[root@master manifest]# curl 10.108.194.44:8001
嗨,阿蒙,我是V2

// 删除资源
#库贝特尔删除-f部署。 
删除"网络"

[根@主舱单]#库贝特尔删除-fsvc-部署。 
删除"网络"服务

[root@master manifest]# kubectl get pods
No resources found in default namespace.

// 文件还是存在的
[root@master manifest]# ls
deploy.yaml  svc-deploy.yaml

页面访问

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-73CK1V2b-1640080009888)(C:\Users\HP\AppData\Roaming\Typora\typora-user-images\image-20211221163557398.png)]

注意:版本更新只需要更改文件里面的容器名字版本,升级也是一样,所以使用yaml文件部署容器,非常方便!!!

两个文件也可以合并写

[root@master manifest]# vi deploy.yml
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: web
  namespace: default
spec:
  replicas: 3
  selector:			
    matchLabels:	
      app: amu
  template:			
    metadata:		
      labels:		
        app: amu
    spec:
      containers:
      - image: gaofan1225/httpd:v1.1		
        imagePullPolicy: IfNotPresent		
        name: httpd
        
---						// 中间使用 “---”隔开
apiversion: v1
kind: Service
metadata: 
  name: web
  namespace: default
spec:
  ports: 
  - port: 8001
    protocol: TCP							
    targetPort: 80
  selector:
    app: amu
  type: NodePort

三、自动创建 YAML文件

4.1 用create命令生成

库贝特尔创建部署NGINX--图像==NGINX:1.16-OYMAL--模拟运行=客户机&DH;MY-部署。

示例:

#库贝特尔创建部署NGINX--图像=NGINX--模拟运行=客户端-OYMAL&DH;NGINXY。

[根@主清单]#
部署。部署。部署。

[根@主清单]# 
应用程序/V1
类型:部署
元数据:
  创造时间戳:空
  标签:
    应用程序:
  姓名:
职务:
  replicas: 1
  选择者:
    匹配标签:
      应用程序:
  strategy: {}
  模板:
    元数据:
      创造时间戳:空
      标签:
        应用程序:
    职务:
      集装箱:
      -图像:
        姓名:
        resources: {}
status: {}

4.2 用get命令导出

库贝特尔得到部署,并进行部署。

示例:

[根@主清单]#库贝克尔创建部署NGINX--图像NGINX--副本3
部署.设立了辅助人员/国家专家小组
[根@主舱单]#库贝特尔得到吊舱
姓名准备状态重新启动年龄
nginx-85b98978db-8b9xj   0/1     ContainerCreating   0          11s
nginx-85b98978db-dds2s   0/1     ContainerCreating   0          11s
nginx-85b98978db-sg9qn   0/1     ContainerCreating   0          11s

[根@主清单]#库贝克尔得到部署

# get获取的信息比create获取的信息更详细
[根@主清单]# 
应用程序/V1
类型:部署
元数据:
  说明:
    deployment.kubernetes.io/revision: "1"
  creationTimestamp: "2021-12-21T09:16:57Z"
  generation: 1
  标签:
    应用程序:
  姓名:
  名称空间:默认
  resourceVersion: "85342"
  uid: ea5653ea-9fd2-424e-9267-2b1112771835
职务:
  progressDeadlineSeconds: 600
  replicas: 3
  revisionHistoryLimit: 10
  selector:
    matchLabels:
      app: nginx
  strategy:
    rollingUpdate:
      maxSurge: 25%
      maxUnavailable: 25%
    type: RollingUpdate
  template:
    metadata:
      creationTimestamp: null
      labels:
        app: nginx
    spec:
      containers:
      - image: nginx
        imagePullPolicy: Always
        name: nginx
        resources: {}
        terminationMessagePath: /dev/termination-log
        terminationMessagePolicy: File
      dnsPolicy: ClusterFirst
      restartPolicy: Always
      schedulerName: default-scheduler
      securityContext: {}
      terminationGracePeriodSeconds: 30
status:
  conditions:
  - lastTransitionTime: "2021-12-21T09:16:57Z"
    lastUpdateTime: "2021-12-21T09:16:57Z"
    message: Deployment does not have minimum availability.
    reason: MinimumReplicasUnavailable
    状况:"虚假"
    类型:可用
  - lastTransitionTime: "2021-12-21T09:16:57Z"
    lastUpdateTime: "2021-12-21T09:16:57Z"
    消息:复制品"NGINX-85B98978B"正在进行中。
    理由:复制的
    现状:"真实"
    类型:进展情况
  observedGeneration: 1
  replicas: 3
  unavailableReplicas: 3
  updatedReplicas: 3

注意:不建议使用以上两种方法,还是建议手写,手写使用起来会更方便!

将你需要创建的资源描述到YAML文件中
部署:申请库贝特尔----FXxxYal
卸载:库贝特尔删除-fXxx.Yal

四、名称空间创建

// 没有pod就没有控制器
[根@主舱单]#库贝特尔得到吊舱
在默认名称空间中找不到资源。

// 干跑查看格式
#库贝特尔创建名称空间运行时--模拟运行=客户机
创建名称空间/运行时(模拟运行)
[root@master manifest]# kubectl create namespace runtime --dry-run=client -o yaml
apiVersion: v1
kind: Namespace
metadata:
  creationTimestamp: null
  name: runtime
spec: {}
status: {}

[root@master manifest]# cat test.yaml 
---
apiVersion: v1
kind: Namespace			// 名称空间
metadata:
  name: runtime

---
apiVersion: apps/v1
kind: Deployment
metadata: 
  name: web
  namespace: default
spec:
  replicas: 3
  selector:
    matchLabels:
      app: amu
  template:
    metadata: 
      labels:
        app: amu
    spec: 
      containers: 
      - image: gaofan1225/httpd:v1.1
        imagePullPolicy: IfNotPresent
        name: httpd

---
apiVersion: v1
kind: Service
metadata: 
  name: web
  namespace: default
spec:
  ports: 
  - port: 8001
    protocol: TCP
    targetPort: 80
  selector:
    app: amu
  type: NodePort

[root@master manifest]# kubectl create -f test.yaml 
namespace/runtime created
deployment.apps/web created
service/web created

[root@master manifest]# kubectl get pods
姓名准备状态重新启动年龄
web-6f5fb9dd4d-5bmnl   1/1     Running   0          6s
web-6f5fb9dd4d-5rzg5   1/1     Running   0          6s
网络b-6F5Fb9d4d-Vvcbf/1运行0-6s

// runtime名称空间创建成功
[根@主舱单]#库贝特尔得到
姓名状况年龄
主动违约3D5H
库比诺租赁活动3D5H
科威特公共活动3D5H
库伯系统活动3D5H
运行时主动14

[根@主清单]#库贝特尔得到部署
提供最新资料
web    3/3     3            3           5m55s

[根@主清单]#库贝特尔获得SVC
名称集群----IP外部端口----IP端口
kubernetes   ClusterIP   10.96.0.1     <none>        443/TCP          7h53m
web          NodePort    10.111.5.34   <none>        8001:31860/TCP   9m59s

// 访问测试
[root@master manifest]# curl 10.111.5.34:8001
嗨,阿蒙,我是V1

// 删除名称空间
[根@主舱单]#库贝特尔删除-f测试。 
名称空间"运行时"删除
删除"网络"
删除"网络"服务

[根@主舱单]#库贝特尔得到
姓名状况年龄
主动违约3D5H
库比诺租赁活动3D5H
科威特公共活动3D5H
库伯系统活动3D5H

总结:创建名称空间也可以靠yaml文件实现,不需要的时候直接删除yaml文件资源就可以删除,启用的时候直接指定yaml文件就行,非常方便!

五、健康检查

强大的自愈能力是 Kubernetes 这类容器编排引擎的一个重要特性。自愈的默认实现方式是自动重启发生故障的容器。除此之外,用户还可以利用 Liveness 和 Readiness 探测机制设置更精细的健康检查,进而实现如下需求:

零停机部署。

避免部署无效的镜像。

更加安全的滚动升级。

六、探针类型

生命探测器:

  • Liveness 探测让用户可以自定义判断容器是否健康的条件。如果探测失败,Kubernetes 就会重启容器。

即时探测器:

  • 除了活性探测,库伯内特斯的健康检查包括准备性探测。

  • 用户通过 Liveness 探测可以告诉 Kubernetes 什么时候通过重启容器实现自愈;Readiness 探测则是告诉 Kubernetes 什么时候可以将容器加入到 Service 负载均衡池中,对外提供服务。

活力和阅读能力

  • Liveness 探测和 Readiness 探测是两种 Health Check 机制,如果不特意配置,Kubernetes 将对两种探测采取相同的默认行为,即通过判断容器启动进程的返回值是否为零来判断探测是否成功。

  • 两种探测的配置方法完全一样,支持的配置参数也一样。不同之处在于探测失败后的行为:Liveness 探测是重启容器;Readiness 探测则是将容器设置为不可用,不接收 Service 转发的请求。

  • Liveness 探测和 Readiness 探测是独立执行的,二者之间没有依赖,所以可以单独使用,也可以同时使用。用 Liveness 探测判断容器是否需要重启以实现自愈;用 Readiness 探测判断容器是否已经准备好对外提供服务。

七、应用自修复

重启策略+监控检查

重启策略:

  • Always:当容器终止退出后,总是重启容器,默认策略。

  • OnFailure:当容器异常退出(退出状态码非0)时,才重启容器。

  • Never:当容器终止退出,从不重启容器。

健康检查类型:

  • livenessProbe(存货检查):如果检查失败,将杀死容器,根据Pod的restartPolicy来操作。

  • readinessProbe(就绪检查):如果检查失败,Kubernetes会把Pod从service endpoints中剔除。

支持的检查方法:

  • httpGet:发送HTTP请求,返回200-400范围状态码为成功。

  • exec:执行Shell命令返回状态码是0为成功。

  • 发霉座:发霉座立成功。

    本站是提供个人知识管理的网络存储空间,所有内容均由用户发布,不代表本站观点。请注意甄别内容中的联系方式、诱导购买等信息,谨防诈骗。如发现有害或侵权内容,请点击一键举报。
    转藏 分享 献花(0

    0条评论

    发表

    请遵守用户 评论公约

    类似文章 更多