0
点赞
收藏
分享

微信扫一扫

kubernetes之Pod

Yaphets_巍 2022-04-14 阅读 25

kubernetes

Pod

Pod概述

Pod资源配置项

查看某种资源可以配置的一级属性:kubectl explain 资源类型

[k8s@administrator ~]$  kubectl explain pod
KIND:     Pod
VERSION:  v1

DESCRIPTION:
     Pod is a collection of containers that can run on a host. This resource is
     created by clients and scheduled onto hosts.

FIELDS:
   apiVersion   <string>
     APIVersion defines the versioned schema of this representation of an
     object. Servers should convert recognized schemas to the latest internal
     value, and may reject unrecognized values. More info:
     https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources

   kind <string>
     Kind is a string value representing the REST resource this object
     represents. Servers may infer this from the endpoint the client submits
     requests to. Cannot be updated. In CamelCase. More info:
     https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds

   metadata     <Object>
     Standard object's metadata. More info:
     https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#metadata

   spec <Object>
     Specification of the desired behavior of the pod. More info:
     https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#spec-and-status

   status       <Object>
     Most recently observed status of the pod. This data may not be up to date.
     Populated by the system. Read-only. More info:
     https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#spec-and-status

查看属性的子属性:kubectl explain 资源类型.属性

[k8s@administrator ~]$ kubectl explain pod.metadata
KIND:     Pod
VERSION:  v1

RESOURCE: metadata <Object>

DESCRIPTION:
     Standard object's metadata. More info:
     https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#metadata

     ObjectMeta is metadata that all persisted resources must have, which
     includes all objects users must create.

FIELDS:
   clusterName  <string>

   labels       <map[string]string>

   name <string>
  
   namespace    <string>

在kubernetes中所有资源的一级属性基本都是一样的,主要包含5部分

一级属性概述
apiVersion 版本,由kubernetes定义,使用kubectl api-versions查询
kind 类型,由kubernetes定义,使用kubectl api-resources查询
metadata 元数据,用于资源标识和说明,常用:name、namespace、labels等
spec 描述,配置中最重要的一部分,是对各种资源配置的详细描述
status 状态信息,内容不需要定义,由kubernetes自动生成

核心子属性spec的常用属性

子属性概述
containers <[]Object>容器列表,用于定义容器的详细信息
nodeName 根据nodeName的值将pod调度到指定的Node节点上
nodeSelector <map[]>根据NodeSelector中定义的信息选择将该Pod调度到包含这些label的Node 上
hostNetwork 是否使用主机网络模式,默认为false,如果设置为true,表示使用宿主机网络
volumes <[]Object>存储卷,用于定义Pod上面挂在的存储信息
restartPolicy 重启策略,表示Pod在遇到故障的时候的处理策略

Pod的配置

pod.spec.containers属性的配置

apiVersion: v1
kind: Pod
metadata:
  name: pod-name
  namespace: default
  labels:
    app: pod-label
spec:
  containers:
  - name: nginx-name
    image: nginx
  - name: tomcat-name
    image: tomcat

镜像拉取策略

Always:总是从远程仓库拉取镜像

IfNotPresent:本地有则使用本地镜像,本地没有则从远程仓库拉取镜像

Never:只使用本地镜像,从不去远程仓库拉取,本地没有就报错

默认策略:

镜像tag为具体版本号,默认策略是:IfNotPresent

镜像tag为:latest(最终版本) ,默认策略是always

示例:

apiVersion: v1
kind: Pod
metadata:
  name: pod-name
  namespace: default
  labels:
    app: pod-label
spec:
  containers:
  - name: nginx-name
    image: nginx
    imagePullPolicy: Always

启动命令

command命令用于在pod中的容器初始化完毕之后运行一个命令、脚本。

注意:若脚本执行结束,则容器内部没有常驻进程,将导致容器启退出,然后进行持续的重启。

apiVersion: v1
kind: Pod
metadata:
  name: pod-name
  namespace: default
  labels:
    app: pod-label
spec:
  containers:
  - name: nginx-name
    image: nginx
    command: ["/bin/sh","-c","touch /logs.log;while true;do /bin/echo $(date +%T) >> /logs.log; sleep 5; done;"]

进入Pod中的容器语法:

kubectl exec  pod名称 -n 命名空间 -it -c 容器名称 /bin/sh

进入pod中的nginx-name容器

kubectl exec  pod-name -it -c nginx-name /bin/bash

环境变量

创建vim pod-env.yaml

apiVersion: v1
kind: Pod
metadata:
  name: pod-name
  namespace: default
spec:
  containers:
  - name: nginx-name
    image: nginx
    env: 
    - name: "envName"
      value: "evnValue"

创建pod并进入容器查看

[k8s@administrator ~]$ kubectl apply -f pod-env.yaml 
pod/pod-name created

[k8s@administrator ~]$ kubectl exec  pod-name -it -c nginx-name /bin/bash
kubectl exec [POD] [COMMAND] is DEPRECATED and will be removed in a future version. Use kubectl exec [POD] -- [COMMAND] instead.
root@pod-name:/# echo $envName
evnValue
root@pod-name:/# exit
exit

[k8s@administrator ~]$ kubectl delete -f pod-env.yaml 
pod "pod-name" deleted

端口设置

端口设置:containers.ports属性用于设置容器暴露的端口列表

[k8s@administrator ~]$ kubectl explain pod.spec.containers.ports
KIND:     Pod
VERSION:  v1
RESOURCE: ports <[]Object>
FIELDS:
   containerPort<integer> # 容器监听端口(0<x<65536)
   hostPort     <integer> # 容器在主机上公开的端口,如果设置,主机上只能运行容器的一个副本 
   hostIP       <string>  # 将外部端口绑定到主机IP
   name         <string>  # 端口名称,如果指定,必须保证name在pod中是唯一的		
   protocol     <string>  # 端口协议。必须是UDP、TCP或SCTP。默认为“TCP”

创建vim pod-ports.yaml

kubectl apply-f pod-ports.yaml

查看Pod信息

kubectl get pod pod-name -o yaml

资源配额限制

通过resources项实现,有两个子选项:

limits:用于限制运行时容器的最大占用资源,当容器占用资源超过limits时会被终止,并进行重启

requests :用于设置容器需要的最小资源,如果环境资源不够,容器将无法启动
[k8s@administrator root]$  kubectl explain pod.spec.containers.resources
KIND:     Pod
VERSION:  v1
RESOURCE: resources <Object>
FIELDS:
   limits       <map[string]string>
   requests     <map[string]string>
apiVersion: v1
kind: Pod
metadata:
  name: pod-name
  namespace: default
spec:
  containers:
  - name: nginx-name
    image: nginx
    resources
      limits:  # 限制资源上限
        cpu: "2" # CPU限制
        memory: "1Gi" # 内存限制
      requests: # 请求资源下限
        cpu: "1" 
        memory: "10Mi" 

Pod的生命周期

生命周期的过程

1.pod创建

2.运行初始化容器(init container)

3.运行主容器(main container)

4.pod终止

主容器又包含如下几个过程:

容器启动后钩子(post start)

容器的存活性探测(liveness probe)

就绪性探测(readiness probe)

容器终止前钩子(pre stop)

运行状态

挂起(Pending):apiserver已经创建了pod资源对象,但它尚未被调度完成或者仍处于下载镜像的过程中

运行中(Running):pod已经被调度至某节点,并且所有容器都已经被kubelet创建完成

成功(Succeeded):pod中的所有容器都已经成功终止并且不会被重启

失败(Failed):所有容器都已经终止,但至少有一个容器终止失败,即容器返回了非0值的退出状态

未知(Unknown):apiserver无法正常获取到pod对象的状态信息,通常由网络通信失败所导致

创建与终止过程

创建过程

用户通过kubectl或其他api客户端提交需要创建的pod信息给apiServer

apiServer开始生成pod对象的信息,并将信息存入etcd,然后返回确认信息至客户端

apiServer开始反映etcd中的pod对象的变化,其它组件使用watch机制来跟踪检查apiServer上的变动

scheduler发现有新的pod对象要创建,开始为Pod分配主机并将结果信息更新至apiServer

node节点上的kubelet发现有pod调度过来,尝试调用docker启动容器,并将结果回送至apiServer

apiServer将接收到的pod状态信息存入etcd中

终止过程

用户向apiServer发送删除pod对象的命令

apiServcer中的pod对象信息会随着时间的推移而更新,在宽限期内(默认30s),pod被视为dead

将pod标记为terminating状态

kubelet在监控到pod对象转为terminating状态的同时启动pod关闭过程

端点控制器监控到pod对象的关闭行为时将其从所有匹配到此端点的service资源的端点列表中移除

如果当前pod对象定义了preStop钩子处理器,则在其标记为terminating后即会以同步的方式启动执行

pod对象中的容器进程收到停止信号

宽限期结束后,若pod中还存在仍在运行的进程,那么pod对象会收到立即终止的信号

kubelet请求apiServer将此pod资源的宽限期设置为0从而完成删除操作,此时pod对于用户已不可见

初始化容器

vim pod-init.yaml

apiVersion: v1
kind: Pod
metadata:
  name: pod-name
  namespace: dev
spec:
  containers:
  - name: nginx-name
    image: nginx
    ports: 
    - name: nginx-port
      containerPort: 80
  initContainers:
  - name: nginx-name-1
    image: nginx
    command: ['sh', '-c', 'sleep 5']
  - name: nginx-name-2
    image: nginx
    command: ['sh', '-c', 'sleep 5']  

kubectl apply -f pod-init.yaml

[k8s@administrator ~]$ kubectl get pods -n dev
NAME       READY   STATUS     RESTARTS   AGE
pod-name   0/1     Init:0/2   0          2s
[k8s@administrator ~]$ kubectl get pods -n dev
NAME       READY   STATUS     RESTARTS   AGE
pod-name   0/1     Init:1/2   0          18s
[k8s@administrator ~]$ kubectl get pods -n dev
NAME       READY   STATUS            RESTARTS   AGE
pod-name   0/1     PodInitializing   0          22s
[k8s@administrator ~]$ kubectl get pods -n dev
NAME       READY   STATUS    RESTARTS   AGE
pod-name   1/1     Running   0          24s

钩子函数

K8S在主容器的启动之后和停止之前提供了两个钩子函数:

post start:容器创建之后执行,如果失败了会重启容器

pre stop  :容器终止之前执行,执行完成之后容器将成功终止,在其完成之前会阻塞删除容器的操作

钩子处理器支持三种方式:

Exec命令:在容器内执行一次命令

TCPSocket:在当前容器尝试访问指定的socket

HTTPGet:在当前容器中向某url发起http请求
lifecycle:
    postStart: 
      exec:
        command:
        - cat
        - /tmp/logs.log
      tcpSocket:
        port: 8080
      httpGet:
        path: / #URI地址
        port: 80 #端口号
        host: 127.0.0.1  #主机地址
        scheme: HTTP #支持的协议,http或者https

exec是常用方式。

apiVersion: v1
kind: Pod
metadata:
  name: pod-name
  namespace: default
spec:
  containers:
  - name: nginx-name
    image: nginx
    ports: 
    - name: nginx-port
      containerPort: 80
  lifecycle:
      postStart: 
        exec: # 容器启动时执行命令,修改nginx默认首页内容
          command: ["/bin/sh", "-c", "echo postStart... > /usr/share/nginx/html/index.html"]
      preStop:
        exec: # 容器停止之前停止nginx服务
          command: ["/usr/sbin/nginx","-s","quit"]  

容器探测

K8S供两种探针来实现容器探测

liveness probes:存活性探针,用于检测应用实例当前是否处于正常运行状态,如果不是,k8s会重启容器

readiness probes:就绪性探针,用于检测应用实例当前是否可以接收请求,如果不能,k8s不会转发流量

探针的区别:

[k8s@administrator root]$ kubectl explain pod.spec.containers.livenessProbe
KIND:     Pod
VERSION:  v1
RESOURCE: livenessProbe <Object>
FIELDS:
   exec <Object>
   failureThreshold     <integer> # 连续探测失败多少次才被认定为失败。默认是3。最小值是1
   grpc <Object>
   httpGet      <Object>
   initialDelaySeconds  <integer>  # 容器启动后等待多少秒执行第一次探测
   periodSeconds        <integer>  # 执行探测的频率。默认是10秒,最小1秒
   successThreshold     <integer>  # 连续探测成功多少次才被认定为成功。默认是1
   tcpSocket    <Object>
   terminationGracePeriodSeconds        <integer>
   timeoutSeconds       <integer> # 探测超时时间。默认1秒,最小1秒

每种探针均支持三种探测方式:

Exec命令:在容器内执行一次命令,如果命令执行的退出码为0,则认为程序正常,否则不正常

TCPSocket:将会尝试访问一个用户容器的端口,如果能够建立这条连接,则认为程序正常,否则不正常

HTTPGet:调用容器内Web应用的URL,如果返回的状态码在200和399之间,则认为程序正常,否则不正常

exec方式

 livenessProbe:
    exec:
      command:
      - cat
      - /tmp/healthy
    tcpSocket:
      port: 8080      - 
    httpGet:
      path: 
      port: 80 
      host: 127.0.0.1 
      scheme: HTTP 

apiVersion: v1
kind: Pod
metadata:
  name: pod-name
  namespace: default
spec:
  containers:
  - name: nginx-name
    image: nginx
    ports: 
    - name: nginx-port
      containerPort: 80
    livenessProbe:
      initialDelaySeconds: 5
      timeoutSeconds: 5
      exec:
        command: ["/bin/cat","/tmp/hello.txt"]

tcpSocket方式

apiVersion: v1
kind: Pod
metadata:
  name: pod-name
  namespace: default
spec:
  containers:
  - name: nginx-name
    image: nginx
    ports: 
    - name: nginx-port
      containerPort: 80
    livenessProbe:
      initialDelaySeconds: 10
      timeoutSeconds: 5
      tcpSocket:
        port: 8080 # 尝试访问8080端口

httpGet方式

apiVersion: v1
kind: Pod
metadata:
  name: pod-name
  namespace: default
spec:
  containers:
  - name: nginx-name
    image: nginx
    ports: 
    - name: nginx-port
      containerPort: 80
    livenessProbe:
      initialDelaySeconds: 15
      timeoutSeconds: 5
      httpGet:  # 访问http://127.0.0.1:80/test  
        scheme: HTTP 
        port: 80 
        path: /test  

重启策略

pod的重启策略有 3 种:

Always :容器失效时,自动重启该容器,是默认值

OnFailure : 容器终止运行且退出码不为0时重启

Never : 不论状态为何,都不重启该容器
apiVersion: v1
kind: Pod
metadata:
  name: pod-name
  namespace: default
spec:
  containers:
  - name: nginx-name
    image: nginx
    ports: 
    - name: nginx-port
      containerPort: 80
    livenessProbe:
      exec:
        command: ["/bin/cat","/logs.log"]
  restartPolicy: Never

Pod的调度

在默认情况下,Pod在那个Node节点运行,是由Scheduler组件采用相应的算法计算出来的,整个过程不受人工控制的。

但在实际使用中,是可以控制Pod到在那个节点上运行的,使用K8S提供的调度方式

K8S提供了四大类调度方式:

自动调度:运行在哪个节点上完全由Scheduler经过一系列的算法计算得出

定向调度:NodeName、NodeSelector

亲和性调度:NodeAffinity、PodAffinity、PodAntiAffinity

污点(容忍)调度:Taints、Toleration

定向调度

NodeName

apiVersion: v1
kind: Pod
metadata:
  name: pod-name
  namespace: default
spec:
  containers:
  - name: nginx-name
    image: nginx
  nodeName: node001

NodeSelector

给node节点添加标签

kubectl label nodes node002 nodeRole=dev

kubectl label nodes node003 nodeRole=test
apiVersion: v1
kind: Pod
metadata:
  name: pod-name
  namespace: default
spec:
  containers:
  - name: nginx-name
    image: nginx
  nodeSelector: 
    nodeRole: dev # 指定调度到具有nodeRole=dev标签的节点上

亲和性调度

亲和性调度(Affinity)分为三类:

nodeAffinity(node亲和性): 以node为目标,解决pod可以调度到哪些node的问题

podAffinity(pod亲和性) :  以pod为目标,解决pod可以和哪些已存在的pod部署在同一个拓扑域中的问题

podAntiAffinity(pod反亲和性) :  以pod为目标,解决pod不能和哪些已存在pod部署在同一个拓扑域中的问题

亲和性与反亲和性:

如果两个应用频繁交互,则有必要利用亲和性让两个应用尽可能的靠近,减少因网络通信而带来的性能损耗

当应用采用多副本部署时,有必要采用反亲和性让各个应用实例打散分布在各个node上,提高服务的高可用性

常用关系符:In NotIn Exists Gt Lt DoesNotExists

关系符使用说明:

- matchExpressions:
  - key: nodeRole   # 匹配存在标签的key为nodeRole的节点
    operator: Exists
  - key: nodeRole   # 匹配标签的key为nodeRole,且value是"dev"或"test"的节点
    operator: In
    values: ["dev","test"]
  - key: nodeNum   # 匹配标签的key为nodeNum,且value大于"20"的节点
    operator: Gt
    values: "20"

NodeAffinity

[k8s@administrator root]$ kubectl explain  pod.spec.affinity.nodeAffinity
KIND:     Pod
VERSION:  v1
RESOURCE: nodeAffinity <Object>
FIELDS:
   preferredDuringSchedulingIgnoredDuringExecution      <[]Object> # 优先调度到满足指定的规则的Node,相当于软限制 (倾向)
      preference   # 一个节点选择器项,与相应的权重相关联
        matchFields   # 按节点字段列出的节点选择器要求列表
        matchExpressions   # 按节点标签列出的节点选择器要求列表(推荐)
          key    # 键
          values # 值
          operator # 关系符 支持In, NotIn, Exists, DoesNotExist, Gt, Lt
      weight # 倾向权重,在范围1-100。   

   requiredDuringSchedulingIgnoredDuringExecution       <Object> # Node节点必须满足指定的所有规则才可以,相当于硬限制
      nodeSelectorTerms  # 节点选择列表
        matchFields   # 按节点字段列出的节点选择器要求列表
        matchExpressions   # 按节点标签列出的节点选择器要求列表(推荐)
          key    # 键
          values # 值
          operator # 关系符 支持Exists, DoesNotExist, In, NotIn, Gt, Lt

NodeAffinity规则设置的注意事项:

如果同时定义了nodeSelector和nodeAffinity,那么必须两个条件都得到满足,Pod才能运行在指定的Node上

如果nodeAffinity指定了多个nodeSelectorTerms,那么只需要其中一个能够匹配成功即可

如果一个nodeSelectorTerms中有多个matchExpressions ,则一个节点必须满足所有的才能匹配成功

如果一个pod所在的Node在Pod运行期间其标签发生了改变,不再符合该Pod的节点亲和性需求,则系统将忽略此变化

preferredDuringSchedulingIgnoredDuringExecution软亲和性,匹配失败也能运行

apiVersion: v1
kind: Pod
metadata:
  name: pod-name
  namespace: default
spec:
  containers:
  - name: nginx-name
    image: nginx
  affinity: 
    nodeAffinity:
      preferredDuringSchedulingIgnoredDuringExecution: 
      - weight: 1
        preference:
          matchExpressions: 
          - key: nodeRole
            operator: NotIn
            values: ["dev","test"] 

requiredDuringSchedulingIgnoredDuringExecution硬亲和性,匹配失败则运行失败

apiVersion: v1
kind: Pod
metadata:
  name: pod-name
  namespace: default
spec:
  containers:
  - name: nginx-name
    image: nginx
  affinity: 
    nodeAffinity: 
      requiredDuringSchedulingIgnoredDuringExecution:
        nodeSelectorTerms:
        - matchExpressions: 
          - key: nodeRole
            operator: In
            values: ["dev","test"]

PodAffinity

[k8s@administrator root]$ kubectl explain  pod.spec.affinity.podAffinity
KIND:     Pod
VERSION:  v1
RESOURCE: podAffinity <Object>
FIELDS:
  preferredDuringSchedulingIgnoredDuringExecution 
    podAffinityTerm  
      namespaces      
      topologyKey
      labelSelector
        matchExpressions  
          key    
          values 
          operator
        matchLabels 
    weight 倾向权重,在范围1-100
  requiredDuringSchedulingIgnoredDuringExecution  
    namespaces       # 指定参照pod的namespace
    topologyKey      # 指定调度作用域
    labelSelector    # 标签选择器
      matchExpressions  # 按节点标签列出的节点选择器要求列表(推荐)
        key    
        values 
        operator 
      matchLabels    # 指多个matchExpressions映射的内容

topologyKey用于指定调度时作用域:

指定为kubernetes.io/hostname,则以Node节点为区分范围

指定为beta.kubernetes.io/os,则以Node节点的操作系统类型区分

创建参照Pod,并将目标pod名确指定到node002上

apiVersion: v1
kind: Pod
metadata:
  name: pod-name
  namespace: default
  labels:
    nodeRole: dev 
spec:
  containers:
  - name: nginx-name
    image: nginx
  nodeName: node002 

创建Pod,指定新Pod必须要与拥有标签nodeRole=dev或者nodeRole=test的pod在同一Node上

apiVersion: v1
kind: Pod
metadata:
  name: pod-name
  namespace: default
spec:
  containers:
  - name: nginx-name
    image: nginx
  affinity: 
    podAffinity: 
      requiredDuringSchedulingIgnoredDuringExecution: 
      - labelSelector:
          matchExpressions: 
          - key: nodeRole
            operator: In
            values: ["dev","test"]
        topologyKey: kubernetes.io/hostname

PodAntiAffinity

创建参照Pod,并将目标pod名确指定到node002上

apiVersion: v1
kind: Pod
metadata:
  name: pod-name
  namespace: default
  labels:
    nodeRole: dev 
spec:
  containers:
  - name: nginx-name
    image: nginx
  nodeName: node002

创建Pod,指定新Pod必须要与拥有标签nodeRole=dev的pod不在同一Node上

apiVersion: v1
kind: Pod
metadata:
  name: pod-name
  namespace: default
spec:
  containers:
  - name: nginx-name
    image: nginx
  affinity:  
    podAntiAffinity:
      requiredDuringSchedulingIgnoredDuringExecution: 
      - labelSelector:
          matchExpressions: 
          - key: nodeRole
            operator: In
            values: ["dev"]
        topologyKey: kubernetes.io/hostname 

污点和容忍

污点

污点格式:key=value:effect

key和value是污点的标签

effect描述污点的作用

effect支持三个选项:

PreferNoSchedule:K8S尽量避免把Pod调度到具有该污点的Node上,除非没有其他节点可调度

NoSchedule:K8S不会把Pod调度到具有该污点的Node上,但不会影响当前Node上已存在的Pod

NoExecute:K8S不会把Pod调度到具有该污点的Node上,同时也会将Node上已存在的Pod驱离

搭建K8S集群,默认就会给master节点添加一个污点标记,所以pod就不会调度到master节点上

污点操作命令:

# 设置污点
kubectl taint nodes node001 key=value:effect

# 去除污点
kubectl taint nodes node001 key:effect-

# 去除所有污点
kubectl taint nodes node001 key-

测试

node002与node003设置污点

kubectl taint nodes node002 tag=val:NoExecute

kubectl taint nodes node003 tag=val:NoExecute

创建Pod01,则失败

kubectl run pod01 --image=nginx

删除node002的污点,重新设置污点

kubectl taint nodes node002  tag:NoExecute-

kubectl taint nodes node002 tag=val:PreferNoSchedule

创建Pod02,成功,运行在node002

kubectl run pod02 --image=nginx

容忍

参数说明

[k8s@administrator root]$ kubectl explain pod.spec.tolerations
KIND:     Pod
VERSION:  v1
RESOURCE: tolerations <[]Object>
FIELDS:
   effect       <string> # 对应污点的effect,空则匹配所有影响
   key  <string>   # 对应要容忍的污点的键,空则匹配所有的键
   operator     <string>  # key-value的运算符,支持Equal和Exists(默认)
   tolerationSeconds    <integer>  # 容忍时间, 当effect为NoExecute时生效,表示pod在Node上的停留时间
   value        <string>  # 对应要容忍的污点的值

示例

apiVersion: v1
kind: Pod
metadata:
  name: pod-name
  namespace: default
spec:
  containers:
  - name: nginx-name
    image: nginx
  tolerations:     
  - key: "tag"    
    operator: "Equal" 
    value: "val"  
    effect: "NoExecute" 
举报

相关推荐

0 条评论