当前位置:   article > 正文

kubernetes之Pod控制器_k8s通过生成pod控制器

k8s通过生成pod控制器


在kubernetes中,按照pod的创建方式可以将其分为两类:
         自主式pod:kubernetes直接创建出来的Pod,这种pod删除后就没有了,也不会重建
         控制器创建的pod:kubernetes通过控制器创建的pod,这种pod删除了之后还会自动重建
kubernetes一般都是通过pod控制器对pod进行管理,确保pod资源符合预期的状态。当pod的资源出现故障时,会尝试进行重启和重建pod。

在kubernetes中,有很多类型的pod控制器,每种都有自己的适合的场景,常见的有下面这些:

ReplicationController:比较原始的pod控制器,已经被废弃,由ReplicaSet替代
ReplicaSet:保证副本数量一直维持在期望值,并支持pod数量扩缩容,镜像版本升级
Deployment:通过控制ReplicaSet来控制Pod,并支持滚动升级、回退版本
Horizontal Pod Autoscaler:可以根据集群负载自动水平调整Pod的数量,实现削峰填谷
DaemonSet:在集群中的指定Node上运行且仅运行一个副本,一般用于守护进程类的任务
Job:它创建出来的pod只要完成任务就立即退出,不需要重启或重建,用于执行一次性任务
Cronjob:它创建的Pod负责周期性任务控制,不需要持续后台运行
StatefulSet:管理有状态应用
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8

一、ReplicaSet

        这种控制器保证一定数量的pod能够正常运行,一旦运行中的pod发生故障,就会重启或重建,同时也可以对pod的数量进行扩容,对版本镜像进行升级。

ReplicaSet的资源清单:

apiVersion: apps/v1 # 版本号
kind: ReplicaSet # 类型       
metadata: # 元数据
  name: # rs名称 
  namespace: # 所属命名空间 
  labels: #标签
    controller: rs
spec: # 详情描述
  replicas: 3 # 副本数量
  selector: # 选择器,通过它指定该控制器管理哪些pod
    matchLabels:      # Labels匹配规则
      app: nginx-pod
    matchExpressions: # Expressions匹配规则
      - {key: app, operator: In, values: [nginx-pod]}
  template: # 模板,当副本数量不足时,会根据下面的模板创建pod副本
    metadata:
      labels:
        app: nginx-pod
    spec:
      containers:
      - name: nginx
        image: nginx
        ports:
        - containerPort: 80
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24

1、创建

vim pod-replicaset.yaml
  • 1
apiVersion: apps/v1
kind: ReplicaSet
metadata:
  name: replicaset-pod
  namespace: dev
  labels:
    dep: repli
spec:
  replicas: 3
  selector:
    matchLabels:
      dep: nginx-rep-pod
  template:
    metadata:
      labels:
        dep: nginx-rep-pod
    spec:
      containers:
      - name: nginx-rep
        image: nginx:1.17.1
        ports:
        - containerPort: 80

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
kubectl create -f pod-replicaset.yaml
  • 1

在这里插入图片描述

2、扩缩容

(1)方法一

kubectl edit rs "名称" -n dev
  • 1

该方式直接可以进行修改:
在这里插入图片描述

修改后查看:
在这里插入图片描述

(2)方法二

kubectl scale rs "名称" --replicas=2 -n dev
注:
--replicas=n直接指定目标数量即可
  • 1
  • 2
  • 3

在这里插入图片描述

3、镜像升级

方法一:同上(扩缩容)

方法二:

kubectl set image rs rs名称 容器=镜像版本 -n namespace
  • 1

在这里插入图片描述

4、删除

kubectl delete-f pod-replicaset.yaml
  • 1

二、Deployment

        k8s从V1.2版本开始引入Deployment控制器,这种控制器是通过管理ReplicaSet来间接管理pod,所以Deployment比RealicaSet功能更强大。

典型的应用场景包括:

  • 定义Deployment来创建Pod和ReplicaSet
  • 滚动升级和回滚应用
  • 扩容和缩容
  • 支持发布的暂停、继续

Deployment的资源清单如下:

apiVersion: apps/v1 # 版本号
kind: Deployment # 类型       
metadata: # 元数据
  name: # rs名称 
  namespace: # 所属命名空间 
  labels: #标签
    controller: deploy
spec: # 详情描述
  replicas: 3 # 副本数量
  revisionHistoryLimit: 3 # 保留历史版本,默认:10
  paused: false # 暂停部署,默认是false
  progressDeadlineSeconds: 600 # 部署超时时间(s),默认是600
  strategy: # 策略
    type: RollingUpdate # 滚动更新策略
    rollingUpdate: # 滚动更新
      maxSurge: 30% # 最大额外可以存在的副本数,可以为百分比,也可以为整数
      maxUnavailable: 30% # 最大不可用状态的 Pod 的最大值,可以为百分比,也可以为整数
  selector: # 选择器,通过它指定该控制器管理哪些pod
    matchLabels:      # Labels匹配规则
      app: nginx-pod
    matchExpressions: # Expressions匹配规则
      - {key: app, operator: In, values: [nginx-pod]}
  template: # 模板,当副本数量不足时,会根据下面的模板创建pod副本
    metadata:
      labels:
        app: nginx-pod
    spec:
      containers:
      - name: nginx
        image: nginx
        ports:
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31

1、创建与扩容

(1)命令形式
创建:

kubectl create deploy nginx --image=nginx:1.17.1  -n dev
  • 1

扩容:

kubectl scale deployment nginx --replicas 3 -n dev
  • 1

在这里插入图片描述

说明:与ReplicaSet一样,也可以通过kubectl edit deploy “名称” -n dev来修改扩容

删除时直接删除对应的deployment即可:

kubectl delete deploy nginx -n dev
  • 1

在这里插入图片描述

(2)使用yaml文件

vim deployment-dev.yaml
  • 1
apiVersion: apps/v1
kind: Deployment
metadata:
  name: button-nginx
  namespace: dev
spec:
  replicas: 3
  selector:
    matchLabels:
      test: nginx-test
  template:
    metadata:
      labels:
        test: nginx-test
    spec:
      containers:
      - image: nginx:1.17.1
        name: nginx4
        ports:
        - containerPort: 85
          protocol: TCP
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21

在这里插入图片描述

kubectl create -f deployment-dev.yaml
  • 1

在这里插入图片描述

删除:

kubectl delete -f deployment-dev.yaml
  • 1

更新:

kubectl apply -f deployment-dev.yaml
  • 1

2、镜像升级

deployment支持两种更新策略:重建更新和滚动更新,可以通过strategy指定策略类型,支持属性有两个:

strategy:指定新的Pod替换旧的Pod的策略, 支持两个属性:
  type:指定策略类型,支持两种策略
    Recreate:在创建出新的Pod之前会先杀掉所有已存在的Pod
    RollingUpdate:滚动更新,就是杀死一部分,就启动一部分,在更新过程中,存在两个版本Pod
  rollingUpdate:当type为RollingUpdate时生效,用于为RollingUpdate设置参数,支持两个属性:
    maxUnavailable:用来指定在升级过程中不可用Pod的最大数量,默认为25%。
    maxSurge: 用来指定在升级过程中可以超过期望的Pod的最大数量,默认为25%。
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
vim deployment-dev-new.yaml
  • 1

这里使用rollingUpdate类型:

apiVersion: apps/v1
kind: Deployment
metadata:
  name: button-nginx
  namespace: dev
spec:
  strategy:
    type: RollingUpdate
    rollingUpdate:
      maxUnavailable: 30%
      maxSurge: 20%
  replicas: 3
  selector:
    matchLabels:
      test: nginx-test
  template:
    metadata:
      labels:
        test: nginx-test
    spec:
      containers:
      - image: nginx:1.17.2
        name: nginx4
        ports:
        - containerPort: 80
          protocol: TCP

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27

在这里插入图片描述

在这里插入图片描述

注:查看delpoyment,发现原来的依旧存在,只是pod数量变为了0,而后又新产生了一个delpoyment,pod数量为3,其实这就是deployment能够进行版本回退的原因
在这里插入图片描述

3、版本回退

deployment支持版本升级过程中的暂停、继续功能以及版本回退等诸多功能。
kubectl rollout: 版本升级相关功能,支持下面的选项:
status 显示当前升级状态
在这里插入图片描述

history 显示升级历史记录
在这里插入图片描述

pause 暂停版本升级过程

kubectl rollout pause deploy "名称" -n dev
  • 1

resume 继续已经暂停的版本升级过程

 kubectl rollout resume deploy "名称" -n dev
  • 1

restart 重启版本升级过程

kubectl rollout restart deploy "名称" -n dev
  • 1

undo 回滚到上一级版本(可以使用–to-revision回滚到指定版本)

kubectl rollout undo deploy "名称" --to-revision=1 -n dev
  • 1

注:nginx版本又回到了1.17.1
在这里插入图片描述

        我们平时更新新版本应用的时候,可以在一部分pod更新完成后执行暂停操作,此时一部分属于新版本,一部分还是属于旧版本,可以筛选一小部分用户请求路由到新版本的pod应用,如果确认升级新版本,则继续完成剩余pod的滚动升级即可,否则立即回退更新操作,这种被成为金丝雀发布

三、Horizontal Pod Autoscaler(HPA)

        Horizontal Pod Autoscaler(HPA)实现通过监测Pod的使用情况,实现pod数量的自动调整。HPA可以获取每个Pod利用率,然后和HPA中定义的指标进行对比,同时计算出需要伸缩的具体值,最后实现Pod的数量的调整。
注:kubernetes 1.8以下需要安装heapster,1.8以上建议使用metrics server,这里只演示metrics server的安装

yum install git -y
# 获取metrics-server
git clone -b v0.3.6 https://github.com/kubernetes-incubator/metrics-server
cd /**/metrics-server/deploy/1.8+/
vim metrics-server-deployment.yaml
具体配置位置见下图:
hostNetwork: true
image: registry.cn-hangzhou.aliyuncs.com/google_containers/metrics-server-amd64:v0.3.6
args:
- --kubelet-insecure-tls
- --kubelet-preferred-address-types=InternalIP,Hostname,InternalDNS,ExternalDNS,ExternalIP
配置完成后保存继续执行如下命令:
kubectl apply -f ./
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13

在这里插入图片描述

安装完成后稍等片刻:

kubectl get pod -n kube-system
  • 1

在这里插入图片描述

kubectl top node
  • 1

在这里插入图片描述

创建:

vim hpa-dev.yaml
  • 1
apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx
  namespace: dev
spec:
  strategy: # 策略
    type: RollingUpdate # 滚动更新策略
  replicas: 1
  selector:
    matchLabels:
      app: nginx-pod
  template:
    metadata:
      labels:
        app: nginx-pod
    spec:
      containers:
      - name: nginx
        image: nginx:1.17.1
        ports:
        - containerPort: 80
          protocol: TCP
        resources: # 资源配额
          limits:  # 限制资源(上限)
            cpu: "1" # CPU限制,单位是core数
          requests: # 请求资源(下限)
            cpu: "100m"  # CPU限制,单位是core数
---
apiVersion: v1
kind: Service
metadata:
  name: svc-nginx
  namespace: dev
spec:
  type: NodePort
  ports:
  - port: 80
    protocol: TCP
    targetPort: 80
    nodePort: 30333
  selector:
    app: nginx-pod
---
apiVersion: autoscaling/v1
kind: HorizontalPodAutoscaler
metadata:
  name: pc-hpa
  namespace: dev
spec:
  minReplicas: 1  #最小pod数量
  maxReplicas: 10 #最大pod数量
  targetCPUUtilizationPercentage: 3 # CPU使用率指标,当CPU平均负载大于30%后,将自动伸缩,最大伸缩Pod数为10个,最小1个。
  scaleTargetRef:   # 指定要控制的nginx信息
    apiVersion: apps/v1
    kind: Deployment
    name: nginx
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
kubectl create -f hpa-dev.yaml
  • 1

在这里插入图片描述

为了测试效果,我们使用Jmeter模拟高并发环境。
这是再查看就会发现又新创建了pod:
在这里插入图片描述

最多创建到10个pod
在这里插入图片描述
当请求量降低之后,创建的pod就会自动删除,直到满足配置的要求。

四、DaemonSet(DS)

这种控制器可以保证集群中的每一个节点上只运行一个副本,适用于节点监控、日志收集等场景。
DaemonSet控制器的特点:

  • 集群中添加节点时,指定的 Pod 副本也将添加到该节点上
  • 当节点从集群中移除时,Pod 也就被回收了

DaemonSet的资源清单:

apiVersion: apps/v1 # 版本号
kind: DaemonSet # 类型       
metadata: # 元数据
  name: # rs名称 
  namespace: # 所属命名空间 
  labels: #标签
    controller: daemonset
spec: # 详情描述
  revisionHistoryLimit: 3 # 保留历史版本
  updateStrategy: # 更新策略
    type: RollingUpdate # 滚动更新策略
    rollingUpdate: # 滚动更新
      maxUnavailable: 1 # 最大不可用状态的 Pod 的最大值,可以为百分比,也可以为整数
  selector: # 选择器,通过它指定该控制器管理哪些pod
    matchLabels:      # Labels匹配规则
      app: nginx-pod
    matchExpressions: # Expressions匹配规则
      - {key: app, operator: In, values: [nginx-pod]}
  template: # 模板,当副本数量不足时,会根据下面的模板创建pod副本
    metadata:
      labels:
        app: nginx-pod
    spec:
      containers:
      - name: nginx
        image: nginx:1.17.1
        ports:
        - containerPort: 80
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28

创建:

vim  ds-dev.yaml
  • 1
apiVersion: apps/v1
kind: DaemonSet
metadata:
  name: pc-ds
  namespace: dev
spec:
  selector:
    matchLabels:
      app: nginx-pod
  template:
    metadata:
      labels:
        app: nginx-pod
    spec:
      containers:
      - name: nginx
        image: nginx:1.17.1
        ports:
        - containerPort: 80
          protocol: TCP
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
kubectl create -f ds-dev.yaml
  • 1

在这里插入图片描述

可以发现每个节点上都只运行了一个pod。

五、Job

        Job控制器用于调配pod对象运行一次性任务,容器中的进程在正常运行结束后不会对其进行重启,而是将pod对象置于completed状态。若容器中的进程因错误而终止,则需要依据配置确定重启与否,未运行完成的pod对象因其所在的节点故障而意外终止后会被重新调度。

Job的资源清单:

apiVersion: batch/v1 # 版本号
kind: Job # 类型       
metadata: # 元数据
  name: # rs名称 
  namespace: # 所属命名空间 
  labels: #标签
    controller: job
spec: # 详情描述
  completions: 1 # 指定job需要成功运行Pods的次数。默认值: 1
  parallelism: 1 # 指定job在任一时刻应该并发运行Pods的数量。默认值: 1
  activeDeadlineSeconds: 30 # 指定job可运行的时间期限,超过时间还未结束,系统将会尝试进行终止。
  backoffLimit: 6 # 指定job失败后进行重试的次数。默认是6
  manualSelector: true # 是否可以使用selector选择器选择pod,默认是false
  selector: # 选择器,通过它指定该控制器管理哪些pod
    matchLabels:      # Labels匹配规则
      app: job-pod
    matchExpressions: # Expressions匹配规则
      - {key: app, operator: In, values: [counter-pod]}
  template: # 模板,当副本数量不足时,会根据下面的模板创建pod副本
    metadata:
      labels:
        app: job-pod
    spec:
      restartPolicy: Never # 重启策略只能设置为Never或者OnFailure
      containers:
      - name: bb-job
        image: busybox
        command: ['sh', '-c']
        args: ['echo "start job";sleep 60; echo "job end"']
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29

特别说明:

重启策略设置的说明:
    如果指定为OnFailure,则job会在pod出现故障时重启容器,而不是创建pod,failed次数不变
    如果指定为Never,则job会在pod出现故障时创建新的pod,并且故障pod不会消失,也不会重启,failed次数加1
    如果指定为Always的话,就意味着一直重启,Job控制器不能设置为Always
  • 1
  • 2
  • 3
  • 4

创建:

vim job-dev.yaml
  • 1
apiVersion: batch/v1
kind: Job
metadata:
  name: pc-job
  namespace: dev
spec:
  manualSelector: true
  selector:
    matchLabels:
      app: job-pod
  template:
    metadata:
      labels:
        app: job-pod
    spec:
      restartPolicy: Never
      containers:
      - name: bb-job
        image: busybox
        command: ['sh', '-c']
        args: ['echo "start job";sleep 60; echo "job end"']
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
kubectl create -f job-dev.yaml
  • 1

创建完成后可以看到任务正在执行
在这里插入图片描述

任务执行后再次查看,发现状态已经成了Completed
在这里插入图片描述

Job控制器也支持并行任务,接下来在上面的配置中做一些修改:

vim job-dev-new.yaml
  • 1
apiVersion: batch/v1
kind: Job
metadata:
  name: pc-job
  namespace: dev
spec:
  completions: 8 # 指定job需要成功运行Pods的次数。默认值: 1
  parallelism: 4 # 指定job在任一时刻应该并发运行Pods的数量。默认值: 1
  manualSelector: true
  selector:
    matchLabels:
      app: job-pod
  template:
    metadata:
      labels:
        app: job-pod
    spec:
      restartPolicy: Never
      containers:
      - name: bb-job
        image: busybox
        command: ['sh', '-c']
        args: ['echo "start job";sleep 60; echo "job end"']
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
kubectl create -f job-dev-new.yaml
  • 1
kubectl get pods -n dev -w
  • 1

观察如下的创建过程:
在这里插入图片描述

六、CronJob(CJ)

这种控制器简单的理解就是在特定的时间点反复的去运行job任务。这里的反复是通过cron表达式定义的。
CronJob的资源清单:

apiVersion: batch/v1beta1 # 版本号
kind: CronJob # 类型       
metadata: # 元数据
  name: # rs名称 
  namespace: # 所属命名空间 
  labels: #标签
    controller: cronjob
spec: # 详情描述
  schedule: # cron格式的作业调度运行时间点,用于控制任务在什么时间执行
  concurrencyPolicy: # 并发执行策略,用于定义前一次作业运行尚未完成时是否以及如何运行后一次的作业
  failedJobHistoryLimit: # 为失败的任务执行保留的历史记录数,默认为1
  successfulJobHistoryLimit: # 为成功的任务执行保留的历史记录数,默认为3
  startingDeadlineSeconds: # 启动作业错误的超时时长
  jobTemplate: # job控制器模板,用于为cronjob控制器生成job对象;下面其实就是job的定义
    metadata:
    spec:
      completions: 1
      parallelism: 1
      activeDeadlineSeconds: 30
      backoffLimit: 6
      manualSelector: true
      selector:
        matchLabels:
          app: counter-pod
        matchExpressions: 规则
          - {key: app, operator: In, values: [counter-pod]}
      template:
        metadata:
          labels:
            app: counter-pod
        spec:
          restartPolicy: Never 
          containers:
          - name: counter
            image: busybox
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35

说明:

1、cron表达式不过多说明
cron表达式,用于指定任务的执行时间
    */1    *      *    *     *
    <分钟> <小时> <> <月份> <星期>2、并发执行策略
concurrencyPolicy:
    Allow:   允许Jobs并发运行(默认)
    Forbid:  禁止并发运行,如果上一次运行尚未完成,则跳过下一次运行
    Replace: 替换,取消当前正在运行的作业并用新作业替换它
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10

创建:

vim cronjob-dev.yaml
  • 1
apiVersion: batch/v1beta1
kind: CronJob
metadata:
  name: cron-dev
  namespace: dev
  labels:
    test: cronjob-dev
spec:
  schedule: "*/1 * * * *"
  concurrencyPolicy: Forbid
  jobTemplate:
    metadata:
    spec:
      template:
        spec:
          restartPolicy: Never
          containers:
          - name: bb-dev
            image: busybox
            command: ['sh', '-c']
            args: ['echo "start job";sleep 10; echo "job end"']

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
kubectl create -f cronjob-dev.yaml
  • 1

查看可以发现,每分钟会执行一次
在这里插入图片描述

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/Cpp五条/article/detail/162324
推荐阅读
相关标签
  

闽ICP备14008679号