04-K8S Basic-Pod资源清单配置基础(基础命令、Pod网络)

一、Pod资源清单介绍

1.1、资源对象的配置格式

  • 资源对象的配置格式
    • API Server接受和返回的所有JSON对象都遵循同一个模式,它们都具有“Kind" 和 “api version” 字段,用于标识对象所属的资源类型、API群组及相关的版本
    • 大多数的对象或列表类型的资源还具有三个嵌套型的字典 metadata、apec和status
      • metadata : 字段为资源提供的元数据信息,例如:名称、隶属的名称空间和标签等
      • apec:用于定义用户期望的状态,不同的资源类型,其状态的意义各有不同,例如pod资源最为核心的功能在于运行容器
      • stats :则记录着活动对象当前的状态,它由kubernetes系统自行维护,对于用户来说为只读字段
    • kubectl api-resources 命令可以获取集群支持使用的所有资源类型

1.2、和解循环(Reconciliation Loop)

  • 和解循环(Reconciliation Loop)
    • 客户端向API Server提交POST请求以创建对象
      • 通过JSON格式的body提交
      • YAML格式需要事先完成向JSON的转换
      • 对象配置信息保存于etcd中,其定义出的状态也成为“期望的状态(Spec)”
    • 控制器负责将其创建为Kubernetes集群上的具体对象(活动对象),并确保其当前状态(status)与用户定义的期望状态相同;
      • stats由控制器通过各界循环(loop)不间断地监控着相关地对象地状态,在对象地当前状态发生改变时运行合适地操作当前状态无限接近期望地状态

image

04-Pod资源清单配置基础(基础命令、Pod网络)
E编辑 F收藏 W关注中 S分享
页面… 马哥-Kubernetes
跳到banner的尾部
回到标题开始
转至元数据结尾
由 zhe.dai创建, 最后修改于十一月 05, 2020转至元数据起始
一、Pod资源清单介绍
1.1、资源对象的配置格式
1.2、和解循环(Reconciliation Loop)
1.3、管理资源对象
1.4、K8s资源对象管理形式
二、资源配置对象
2.1、kubernetes资源配置对象官方手册
2.2、NameSpace资源YAML格式资源配置清单创建
2.3、Pod资源YAML格式资源配置清单创建(无控制器控制-自主式Pod)
2.3.1、使用模板导出方式定义Pod
2.3.2、手动定义一个Pod(一个pod运行多个容器)
2.4、kubectl exec 连接
2.4.1、kubectl exec 连接进行pod的容器的交互式接口
2.5、kubectl logs 查看pod日志
2.5.1、kubectl logs 查看pod中容器的日志信息
2.6、Pod网络
2.6.1、运行一个pod使用共享宿主机的网络(pods.spec.hostNetwork)
2.6.2、pods.spec.containers.ports指定容器端口暴漏(仅绑定容器运行的一个宿主机的地址即单一端口映射)
一、Pod资源清单介绍
1.1、资源对象的配置格式
资源对象的配置格式

API Server接受和返回的所有JSON对象都遵循同一个模式,它们都具有“Kind" 和 “api version” 字段,用于标识对象所属的资源类型、API群组及相关的版本
大多数的对象或列表类型的资源还具有三个嵌套型的字典 metadata、apec和status
metadata : 字段为资源提供的元数据信息,例如:名称、隶属的名称空间和标签等
apec:用于定义用户期望的状态,不同的资源类型,其状态的意义各有不同,例如pod资源最为核心的功能在于运行容器
stats :则记录着活动对象当前的状态,它由kubernetes系统自行维护,对于用户来说为只读字段
kubectl api-resources 命令可以获取集群支持使用的所有资源类型
1.2、和解循环(Reconciliation Loop)
和解循环(Reconciliation Loop)

客户端向API Server提交POST请求以创建对象
通过JSON格式的body提交
YAML格式需要事先完成向JSON的转换
对象配置信息保存于etcd中,其定义出的状态也成为“期望的状态(Spec)”
控制器负责将其创建为Kubernetes集群上的具体对象(活动对象),并确保其当前状态(status)与用户定义的期望状态相同;
stats由控制器通过各界循环(loop)不间断地监控着相关地对象地状态,在对象地当前状态发生改变时运行合适地操作当前状态无限接近期望地状态

1.3、管理资源对象

image

1.4、K8s资源对象管理形式

  • kubectl的命令可分为三类:
    • 陈述式命令(Imperative Commands)
      • 即此前用到的run、expose、delete和get等命令,它们直接多用于Kubernetes系统上的活动给对象,简单易用,但是不支持代码复用、修改复审即审计日志等功能,这些功能的实现通常要依赖于资源配置文件中,这些问问你进也被称为资源清单
    • 陈述式对象配置 (Imperative Object Configuration)
    • 声明式对象配置 (Declarative Object Configuration)
  • 配置对象指的是:要使用json或者使用YAML格式配置文件具体而清晰的定义出一个资源所期望的状态,也可以使用两种方式进行资源创建,使用create命令称为陈述式对象配置,使用apply命令称为声明式对象配置
  • 参考博客地址:https://blog.csdn.net/dkfajsldfsdfsd/article/details/80916543

二、资源配置对象

2.1、kubernetes资源配置对象官方手册

2.2、NameSpace资源YAML格式资源配置清单创建

###############查看陈述式创建的名称空间###############
basic]# kubectl get ns default -o yaml
apiVersion: v1
kind: Namespace
metadata:
  creationTimestamp: "2020-04-24T16:49:33Z"
  managedFields:
  - apiVersion: v1
    fieldsType: FieldsV1
    fieldsV1:
      f:status:
        f:phase: {}
    manager: kube-apiserver
    operation: Update
    time: "2020-04-24T16:49:33Z"
  name: default
  resourceVersion: "153"
  selfLink: /api/v1/namespaces/default
  uid: d8651cc1-a2fb-4e2b-81cc-727f18c7080f
spec:
  finalizers:
  - kubernetes
status:
  phase: Active     # 相位即状态,如果不指定默认也会存在
#####################################################
 
 
 
 
1、创建配置清单目录
    ~]# mkdir mainfests
    ~]# cd mainfests/
 
    mainfests]# mkdir basic
    mainfests]# cd basic/
    basic]# pwd
        /root/mainfests/basic
 
#创建YAML格式的资源配置清单文件
2、创建简单一个YAML格式的资源类型为名称空间
    basic]# cat develop-ns.yaml
    #使用kubectl get ns default -o yaml --export命令导出一份配置清单加以修改
    #namespace所属的群组
    apiVersion: v1
    #名称空间类型,首字母大写
    kind: Namespace
    #元数据定义
    metadata:
      name: develop
    #所期望的状态,但是对于名称空间来讲没有什么可期望的状态,所以spec字段其实可以不写
    spec:
    #表示由k8s来回收
      finalizers:
      - kubernetes
 
3、确保k8s集群上没有将要创建的develop名称空间
    basic]# kubectl get ns
 
#陈述式对象配置
4、(陈述式对象配置 )使用编写好的YAML清单创建名称空间   
    basic]# kubectl create -f develop-ns.yaml
        namespace/develop created
 
    basic]# kubectl get ns
        NAME              STATUS   AGE
        default           Active   24h
        develop           Active   15s
 
#声明式对象配置
5、(声明式对象配置)创建一个名称为生产环境的名称空间
    basic]# cat pord-ns.yaml
    #使用kubectl get ns default -o yaml --export命令导出一份配置清单加以修改
    #namespace所属的群组
    apiVersion: v1
    #名称空间类型,首字母大写
    kind: Namespace
    #元数据定义
    metadata:
      name: prod
    #所期望的状态,但是对于名称空间来讲没有什么可期望的状态
    spec:
    #表示由k8s来回收
      finalizers:
      - kubernetes
 
     basic]# kubectl apply -f pord-ns.yaml
        namespace/prod created
    basic]# kubectl get ns
        NAME              STATUS   AGE
        default           Active   24h
        develop           Active   4m6s
        prod              Active   3s
 
#声明式对象配置优点:如果使用同一YAML配置文件创建多次则会自动检测是否存在此资源并告知已经存在而且还支持再次目录下的YAML进行资源创建或修改,但是陈述式对象配置则会报错
6、声明式对象及陈述性对象对比
    #陈述式 --> 陈述式则报错为资源已经存在
    basic]# kubectl create -f develop-ns.yaml
        Error from server (AlreadyExists): error when creating "develop-ns.yaml": namespaces "develop" already exists
 
    #声明式 --> 声明式则显示资源并未进行改变
    basic]# kubectl apply -f pord-ns.yaml
        namespace/prod unchanged

2.3、Pod资源YAML格式资源配置清单创建(无控制器控制-自主式Pod)

2.3.1、使用模板导出方式定义Pod

1、使用之前手动创建pod资源导出一个YAML格式的清单文件
    basic]# kubectl get pods myapp-5c6976696c-8kpqh -o yaml --export > pod-demo-yaml
 
2、编辑导出的YAML
basic]# cat pod-demo-yaml
#pod所属的群组
apiVersion: v1
#资源的类型为pod
kind: Pod
#元数据
metadata:
  creationTimestamp: null   # 创建启动时间会自动修改
  #generateName名称为手动创建自动生成的,手动定义使用name
  #generateName: myapp-5c6976696c-
  #pod名称
  name: pod-demo
  #pod使用的名称空间
  namespace: develop
#定义pod的属性
spec:
  #容器
  containers:
  #这个容器使用的镜像文件
  - image: ikubernetes/myapp:v1
    #imagePullPolicy如果调度的node集群上没有则使用imagePullPolicy定义有三个值
    #   Always:总是拉取 pul
    #   IfNotPresent:默认值,本地有则使用本地镜像,不拉取
    #   Never:只使用本地镜像,从不拉取)
    imagePullPolicy: IfNotPresent
    #容器的名称
    name: myapp
    #定义这个容器期望和拥有所使用的资源
    resources: {}
  #dnsPolicy使用什么样的dns策略
     #  ClusterFirst:表示优先使用k8s集群中的dns服务
     #  None:无任何策略
     #  Default:默认
     #  ClusterFirstWithHostNet 集群 DNS 优先,并伴随着使用宿主机网络)
  dnsPolicy: ClusterFirst
  #是否允许service引用此pod
  enableServiceLinks: true
  #(节点绑定)此pod运行所调度运行的node节点,如果声明则此pod只能运行在此node上,如果不声明则可以由scheduler调度器随机调度
  #nodeName: 192.168.1.141
  #pod优先级
  priority: 0
  #restartPolicy定义Pod时,可以指定restartPolicy字段,表明此Pod中的容器在何种条件下会重启。restartPolicy拥有三个候选值
    #   Always:只要退出就重启
    #   OnFailure:失败退出时(exit code不为0)才重启
    #   Never:永远不重启
  restartPolicy: Always
  #使用哪个调度器进行调度此pod
  schedulerName: default-scheduler
  #定义安全上下文
  securityContext: {}
 
3、使用声明式对象配置指向YAML资源配置文件创建Pod
    basic]# kubectl apply -f pod-demo-yaml
        pod/pod-demo created
 
4、指定查看develop名称空间下的pod
    basic]# kubectl get pods -n develop
        NAME       READY   STATUS    RESTARTS   AGE
        pod-demo   1/1     Running   0          36s
 
 
5、使用kubectl explain 资源    可以查看此资源的创建讲解
    basic]# kubectl explain pods
    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
 
    #以上显示写为 <Object>都可以使用字段名称显示的更详细
    basic]# kubectl explain pods.apiVersion
    basic]# kubectl explain pods.metadata

2.3.2、手动定义一个Pod(一个pod运行多个容器)

1、手动写一个pod资源配置文件
basic]# cat pod-demo-2.yaml
#pod所属的群组
apiVersion: v1
#资源类型为pod
kind: Pod
#元数据
metadata:
  #pod名称
  name: pod-demo
  #pod所属的名称空间,如果不指定可在apply时使用-n选项
  namespace: prod
#定义pod的属性
spec:
  #容器
  containers:
  #第一个容器的名称
  - name: myapp
  #这个容器使用的镜像文件
    image: ikubernetes/myapp:v1
    imagePullPolicy: IfNotPresent   # 总是去互联网上拖最新的
  #第二个容器的名称
  - name: bbox
    image: busybox:latest
    imagePullPolicy: IfNotPresent
    #定义这个容器启动运行的命令
    command: ["/bin/sh","-c","sleep 86400"]
    # kubectl explain pods.spec.containers.command
 
 
# 也可以换种command写法
    command:
    - /bin/sh
    - -c
    - "sleep 86400"
 
 
 
2、使用aply声明式对象创建pod
    basic]# kubectl apply -f pod-demo-2.yaml
        pod/pod-demo created
 
3、查看指定的名称空间下的pod
    basic]# kubectl get pods -n prod
        NAME       READY   STATUS    RESTARTS   AGE
        pod-demo   2/2     Running   0          72s
 
4、查看运行的pod的详细信息
basic]# kubectl get pods -n prod -o yaml
apiVersion: v1
items:
- apiVersion: v1
  kind: Pod
  metadata:
    annotations:
      kubectl.kubernetes.io/last-applied-configuration: |
        {"apiVersion":"v1","kind":"Pod","metadata":{"annotations":{},"name":"pod-demo","namespace":"prod"},"spec":{"containers":[{"image":"ikubernetes/myapp:v1","imagePullPolicy":"IfNotPresent","name":"myapp"},{"command":["/bin/sh","-c","sleep 86400"],"image":"busybox:latest","imagePullPolicy":"IfNotPresent","name":"bbox"}]}}
    creationTimestamp: "2020-02-18T14:32:32Z"
    name: pod-demo
    namespace: prod
    resourceVersion: "417615"
    selfLink: /api/v1/namespaces/prod/pods/pod-demo
    uid: f453f403-cb5d-4636-bfdb-9711a7120cad
  spec:
    containers:
    - image: ikubernetes/myapp:v1
      imagePullPolicy: IfNotPresent
      name: myapp
      resources: {}
      terminationMessagePath: /dev/termination-log
      terminationMessagePolicy: File
      volumeMounts:
      - mountPath: /var/run/secrets/kubernetes.io/serviceaccount
        name: default-token-hs4w4
        readOnly: true
    - command:
      - /bin/sh
      - -c
      - sleep 86400
      image: busybox:latest
      imagePullPolicy: IfNotPresent
      name: bbox
      resources: {}
      terminationMessagePath: /dev/termination-log
      terminationMessagePolicy: File
      volumeMounts:
      - mountPath: /var/run/secrets/kubernetes.io/serviceaccount
        name: default-token-hs4w4
        readOnly: true
    dnsPolicy: ClusterFirst
    enableServiceLinks: true
    nodeName: 192.168.1.51
    priority: 0
    restartPolicy: Always
    schedulerName: default-scheduler
    securityContext: {}
    serviceAccount: default
    serviceAccountName: default
    terminationGracePeriodSeconds: 30
    tolerations:
    - effect: NoExecute
      key: node.kubernetes.io/not-ready
      operator: Exists
      tolerationSeconds: 300
    - effect: NoExecute
      key: node.kubernetes.io/unreachable
      operator: Exists
      tolerationSeconds: 300
    volumes:
    - name: default-token-hs4w4
      secret:
        defaultMode: 420
        secretName: default-token-hs4w4
  status:
    conditions:
    - lastProbeTime: null
      lastTransitionTime: "2020-02-18T14:32:32Z"
      status: "True"
      type: Initialized
    - lastProbeTime: null
      lastTransitionTime: "2020-02-18T14:32:50Z"
      status: "True"
      type: Ready
    - lastProbeTime: null
      lastTransitionTime: "2020-02-18T14:32:50Z"
      status: "True"
      type: ContainersReady
    - lastProbeTime: null
      lastTransitionTime: "2020-02-18T14:32:32Z"
      status: "True"
      type: PodScheduled
    containerStatuses:
    - containerID: docker://917912c11e895b6d6f21d0d3316e474b6e3789db990f70ae12d45b84744d2a30
      image: busybox:latest
      imageID: docker-pullable://busybox@sha256:6915be4043561d64e0ab0f8f098dc2ac48e077fe23f488ac24b665166898115a
      lastState: {}
      name: bbox
      ready: true
      restartCount: 0
      started: true
      state:
        running:
          startedAt: "2020-02-18T14:32:49Z"
    - containerID: docker://8dccb799765fdf915cb20bc6d92b24f0f200d95587ebd00fc4da3ac1879e8a38
      image: ikubernetes/myapp:v1
      imageID: docker-pullable://ikubernetes/myapp@sha256:9c3dc30b5219788b2b8a4b065f548b922a34479577befb54b03330999d30d513
      lastState: {}
      name: myapp
      ready: true
      restartCount: 0
      started: true
      state:
        running:
          startedAt: "2020-02-18T14:32:33Z"
    hostIP: 192.168.1.51
    phase: Running
    podIP: 192.168.1.81
    podIPs:
    - ip: 192.168.1.81
    qosClass: BestEffort
    startTime: "2020-02-18T14:32:32Z"
kind: List
metadata:
  resourceVersion: ""
  selfLink: ""
 
 
5、删除此前使用YAML资源配置文件删除此pod
    basic]# kubectl delete -f hostname.yaml
        pod "mypod" deleted

2.4、kubectl exec 连接

2.4.1、kubectl exec 连接进行pod的容器的交互式接口

1、查看kubectl exec帮助
    ~]# kubectl exec -h
    Usage:
         kubectl exec (POD | TYPE/NAME) [-c CONTAINER] [flags] -- COMMAND [args...] [options]
 
2、指定连入时指定哪个名称空间下的Pod资源下的容器的名称
    ~]# kubectl exec pod-demo -c bbox -n prod -it -- /bin/sh
    / #
 
3、同一Pod中容器共享同一网络名称空间
    / # netstat -tnl
    Active Internet connections (only servers)
    Proto Recv-Q Send-Q Local Address           Foreign Address         State      
    tcp        0      0 0.0.0.0:80              0.0.0.0:*               LISTEN     
    / # ip a
    1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue qlen 1000
        link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
        inet 127.0.0.1/8 scope host lo
           valid_lft forever preferred_lft forever
    3: eth0@if7: <BROADCAST,MULTICAST,UP,LOWER_UP,M-DOWN> mtu 1454 qdisc noqueue
        link/ether 9a:2a:38:8d:6b:c1 brd ff:ff:ff:ff:ff:ff
        inet 192.168.1.81/32 brd 192.168.1.81 scope global eth0
           valid_lft forever preferred_lft forever
    / # wget -O - -q  192.168.1.81
        Hello MyApp | Version: v1 | <a href="hostname.html">Pod Name</a>

2.5、kubectl logs 查看pod日志

2.5.1、kubectl logs 查看pod中容器的日志信息

1、查看命令的使用帮助
    ~]# kubectl logs -h
    Usage:
        kubectl logs [-f] [-p] (POD | TYPE/NAME) [-c CONTAINER] [options]
 
 
 
2、查看指定哪个名称空间下的Pod资源下的容器的名称的日志
    ~]# kubectl logs pod-demo -n prod -c myapp
        192.168.1.81 - - [18/Feb/2020:14:44:44 +0000] "GET / HTTP/1.1" 200 65 "-" "Wget" "-"
    ~]# kubectl logs pod-demo -n prod -c bbox
 
3、如果pod中仅有一个容器则仅需要指定pod查看日志即可
    ~]# kubectl get pods
        NAME                            READY   STATUS    RESTARTS   AGE
        myapp-5c6976696c-8kpqh          1/1     Running   0          29h
 
    ~]# kubectl logs myapp-5c6976696c-8kpqh
        192.168.1.177 - - [17/Feb/2020:08:58:58 +0000] "GET / HTTP/1.1" 200 65 "-" "curl/7.29.0" "-"
        192.168.1.177 - - [17/Feb/2020:08:59:27 +0000] "GET /hostname.html HTTP/1.1" 200 23 "-" "curl/7.29.0" "-"

2.6、Pod网络

2.6.1、运行一个pod使用共享宿主机的网络(pods.spec.hostNetwork)

1、手动写一个pod资源配置文件
basic]# cat hostname.yaml
apiVersion: v1
kind: Pod
metadata:
  name: mypod
  namespace: default
spec:
  containers:
  - name: myapp
    image: ikubernetes/myapp:v1
#开启共享宿主机网络端口
  hostNetwork: true
 
 
2、使用aply声明式对象创建pod
    ~]# kubectl apply -f mainfests/basic/hostname.yaml
        pod/mypod created
 
 
3、验证此pod是否运行宿主机网络 (pod资源的地址就时node节点的地址即监听宿主机的名称空间)
    basic]# kubectl get pods -o wide
        NAME                            READY   STATUS    RESTARTS   AGE   IP              NODE            NOMINATED NODE   READINESS GATES
        mypod                           1/1     Running   0          40s   192.168.1.185   192.168.1.185   <none>           <none>
 
 basic]# curl  192.168.1.185
    Hello MyApp | Version: v1 | <a href="hostname.html">Pod Name</a>
 basic]# curl  192.168.1.185/hostname.html
    k8s.node2    # 这里的主机名为宿主机名名称

2.6.2、pods.spec.containers.ports指定容器端口暴漏(仅绑定容器运行的一个宿主机的地址即单一端口映射)

  • containerPort :容器的端口 (仅表示Node所在的节点上,打开此端口)
  • hostPort : 宿主机端口,可以使得容器的端口和宿主机的端口建立映射关系(DNET)
1、删除此前使用YAML资源配置文件删除此pod
    basic]# kubectl delete -f hostname.yaml
        pod "mypod" deleted
 
2、重新配置YAML资源配置
basic]# cat hostname.yaml
apiVersion: v1
kind: Pod
metadata:
  name: mypod
  namespace: default
spec:
  containers:
  - name: myapp
    image: ikubernetes/myapp:v1
    #定义容器的端口暴漏信息
    ports:
        #协议
    - protocol: TCP
        #容器内部端口
      containerPort: 80
        #可以给此端口设置一个名称,后期可以使用名称引用
      name: httpd
        #映射宿主机的端口
      hostPort: 8080
 
3、使用资源配置文件创建pod
    basic]# kubectl apply -f hostname.yaml
        pod/mypod created
 
4、查看创建的pod信息并访问
    basic]# kubectl get pods -o wide
        mypod                           1/1     Running   0          32s   192.168.1.226   192.168.1.185   <none>           <none>
     
5、访问运行pod的宿主机节点的映射端口就可以访问到容器的80
    basic]# 192.168.1.185:8080
    Hello MyApp | Version: v1 | <a href="hostname.html">Pod Name</a>

问题思考

# 问题思考:运行一个pods,地址在10.244.0.0/16网络中,如何让集群外部进行访问?
    1、Service : NodePort类型的Service, 通过集群中各个主机节点都打开同一个端口,把用户的请求映射给Pods,使其任何节点的这个端口都可以访问到此Pods,端口是随机的一般在30000~32767范围。(kube-proxy生成对应的iptable及Lvs规则实现的)
    2、hostPort : Pods一定是运行在集群中的某一个节点上的,所以,Pods运行在哪个节点上,就使用哪个节点的端口访问,其它未运行Pods的节点不可以访问,即单一端口映射。
    3、hostNetwork : pod资源的地址就时node节点的地址即监听宿主机的名称空间,Pods直接使用节点的网络,仅通过此运行Pods的节点进行访问其Pods监听的端口,其它未运行Pods的节点不可以访问。
posted @ 2021-06-13 19:58  SRE运维充电站  阅读(3)  评论(0编辑  收藏  举报