【EFK】基于K8S构建EFK+logstash+kafka日志平台(1),一份非常适合收藏的大数据开发进阶面试题

2.1、Elasticsearch组件

Elasticsearch 是一个分布式的免费开源搜索和分析引擎,适用于包括文本、数字、地理空间、结构化和非结构化数据等在内的所有类型的数据。

Elasticsearch 在 Apache Lucene 的基础上开发而成,由 Elasticsearch N.V.(即现在的 Elastic)于 2010 年首次发布。Elasticsearch 以其简单的 REST 风格 API、分布式特性、速度和可扩展性而闻名,是 Elastic Stack 的核心组件;
Elastic Stack 是一套适用于数据采集、扩充、存储、分析和可视化的免费开源工具。

人们通常将 Elastic Stack 称为 ELK Stack(代指 Elasticsearch、Logstash 和 Kibana)。
目前 Elastic Stack 包括一系列丰富的轻量型数据采集代理,这些代理统称为 Beats,可用来向 Elasticsearch 发送数据。

2.2、Filebeat组件

【1】 Filebeat和beat关系

filebeat是Beats中的一员。
  Beats是一个轻量级日志采集器,Beats家族有6个成员,早期的ELK架构中使用Logstash收集、解析日志,但是Logstash对内存、cpu、io等资源消耗比较高。相比Logstash,Beats所占系统的CPU和内存几乎可以忽略不计。

目前Beats包含六种工具:
1、Packetbeat:网络数据(收集网络流量数据)
2、Metricbeat:指标(收集系统、进程和文件系统级别的CPU和内存使用情况等数据)
3、Filebeat:日志文件(收集文件数据)
4、Winlogbeat:windows事件日志(收集Windows事件日志数据)
5、Auditbeat:审计数据(收集审计日志)
6、Heartbeat:运行时间监控(收集系统运行时的数据)

【2】Filebeat是什么

Filebeat是用于转发和收集日志数据的轻量级传送工具。Filebeat监视你指定的日志文件或位置,收集日志事件,并将它们转发到Elasticsearch或 Logstash中。
Filebeat的工作方式如下:启动Filebeat时,它将启动一个或多个输入,这些输入将在为日志数据指定的位置中查找。对于Filebeat所找到的每个日志,Filebeat都会启动收集器。每个收集器都读取单个日志以获取新内容,并将新日志数据发送到libbeat,libbeat将聚集事件,并将聚集的数据发送到为Filebeat配置的输出。

工作的流程图如下:
在这里插入图片描述
Filebeat 有两个主要组件:
harvester:一个harvester负责读取一个单个文件的内容。harvester逐行读取每个文件,并把这些内容发送到输出。每个文件启动一个harvester。
Input:一个input负责管理harvesters,并找到所有要读取的源。如果input类型是log,则input查找驱动器上与已定义的log日志路径匹配的所有文件,并为每个文件启动一个harvester。

【3】Filebeat工作原理

在任何环境下,应用程序都有停机的可能性。 Filebeat 读取并转发日志行,如果中断,则会记住所有事件恢复联机状态时所在位置。
Filebeat带有内部模块(auditd,Apache,Nginx,System和MySQL),可通过一个指定命令来简化通用日志格式的收集,解析和可视化。
FileBeat 不会让你的管道超负荷。FileBeat 如果是向 Logstash 传输数据,当 Logstash 忙于处理数据,会通知 FileBeat 放慢读取速度。一旦拥塞得到解决,FileBeat将恢复到原来的速度并继续传播。
Filebeat保持每个文件的状态,并经常刷新注册表文件中的磁盘状态。状态用于记住harvester正在读取的最后偏移量,并确保发送所有日志行。Filebeat将每个事件的传递状态存储在注册表文件中。所以它能保证事件至少传递一次到配置的输出,没有数据丢失。

【4】传输方案

1、output.elasticsearch
如果你希望使用 filebeat 直接向 elasticsearch 输出数据,需要配置 output.elasticsearch
output.elasticsearch:
hosts: [“192.168.40.180:9200”]
2、output.logstash
如果使用filebeat向 logstash输出数据,然后由 logstash 再向elasticsearch 输出数据,需要配置 output.logstash。 logstash 和 filebeat 一起工作时,如果 logstash 忙于处理数据,会通知FileBeat放慢读取速度。一旦拥塞得到解决,FileBeat 将恢复到原来的速度并继续传播。这样,可以减少管道超负荷的情况。
output.logstash:
hosts: [“192.168.40.180:5044”]

3、output.kafka
如果使用filebeat向kafka输出数据,然后由 logstash 作为消费者拉取kafka中的日志,并再向elasticsearch 输出数据,需要配置 output.logstash
output.kafka:
enabled: true
hosts: [“192.168.40.180:9092”]
topic: elfk8stest

2.3、Logstash组件

2.4、Fluent组件

2.5、fluentd、filebeat、logstash对比分析

三、EFK组件安装

在安装Elasticsearch集群之前,我们先创建一个名称空间,在这个名称空间下安装日志收工具elasticsearch、fluentd、kibana。我们创建一个kube-logging名称空间,将EFK组件安装到该名称空间中。

kubectl create ns kube-logging

3.1、安装elasticsearch

首先,我们需要部署一个有3个节点的Elasticsearch集群。
我们使用3个Elasticsearch Pods可以避免高可用中多节点集群中发生的“脑裂”问题。
脑裂问题参考如下:
https://www.elastic.co/guide/en/elasticsearch/reference/current/modules-node.html#split-brain

【1】创建headless service服务
[root@master 4]# cat elasticsearch\_svc.yaml
apiVersion: v1
kind: Service
metadata:
  name: elasticsearch
  namespace: kube-logging
  labels:
    app: elasticsearch
spec:
  selector:
    app: elasticsearch
  clusterIP: None
  ports:
  - port: 9200
    name: rest
  - port: 9300
    name: inter-node

在kube-logging名称空间定义了一个名为 elasticsearch 的 Service服务,带有app=elasticsearch标签,当我们将 Elasticsearch StatefulSet 与此服务关联时,服务将返回带有标签app=elasticsearch的 Elasticsearch Pods的DNS A记录,然后设置clusterIP=None,将该服务设置成无头服务。最后,我们分别定义端口9200、9300,分别用于与 REST API 交互,以及用于节点间通信。

[root@master 4]# kubectl apply -f elasticsearch\_svc.yaml
service/elasticsearch created
[root@master 4]# kubectl get svc -n kube-logging
NAME            TYPE        CLUSTER-IP   EXTERNAL-IP   PORT(S)             AGE
elasticsearch   ClusterIP   None         <none>        9200/TCP,9300/TCP   20s

现在我们已经为 Pod 设置了无头服务和一个稳定的域名.elasticsearch.kube-logging.svc.cluster.local,接下来我们通过 StatefulSet来创建具体的 Elasticsearch的Pod 应用。

【2】创建Storageclass ,实现存储类动态供给

1、安装nfs

[root@master 4]# yum install nfs-utils -y
[root@node01 ~]# yum install nfs-utils -y
[root@node02 ~]#yum install nfs-utils -y
 
[root@master 4]# systemctl start nfs
[root@node01 ~]# systemctl start nfs
[root@node02 ~]# systemctl start nfs

[root@master 4]# systemctl enable nfs.service
[root@node01 ~]# systemctl enable nfs.service
[root@node02 ~]# systemctl enable nfs.service

2、master创建共享目录

[root@master 4]# mkdir /data/v1 -p
# 编辑/etc/exports文件
[root@master 4]# vim /etc/exports
/data/v1 10.32.1.0/24(rw,no_root_squash)
# 加载配置,使配置生效
[root@master 4]# exportfs -arv
exporting 10.32.1.0/24:/data/v1
[root@master 4]# systemctl restart nfs

3、创建nfs作为存储的供应商

  • 创建sa
    kubectl create sa nfs-provisioner
  • 对sa做rbac授权
[root@master 4]# cat rbac.yaml
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
  name: nfs-provisioner-runner
rules:
  - apiGroups: [""]
    resources: ["persistentvolumes"]
    verbs: ["get","list","watch","create","delete"]
  - apiGroups: [""]
    resources: ["persistentvolumeclaims"]
    verbs: ["get", "list", "watch", "update"]
  - apiGroups: ["storage.k8s.io"]
    resources: ["storageclasses"]
    verbs: ["get", "list", "watch"]
  - apiGroups: [""]
    resources: ["events"]
    verbs: ["create", "update", "patch"]
  - apiGroups: [""]
    resources: ["services", "endpoints"]
    verbs: ["get"]
  - apiGroups: ["extensions"]
    resources: ["podsecuritypolicies"]
    resourceNames: ["nfs-provisioner"]
    verbs: ["use"]
---
kind: ClusterRoleBinding
apiVersion: rbac.authorization.k8s.io/v1
metadata:
  name: run-nfs-provisioner
subjects:
  - kind: ServiceAccount
    name: nfs-provisioner
    namespace: default
roleRef:
  kind: ClusterRole
  name: nfs-provisioner-runner
  apiGroup: rbac.authorization.k8s.io
---
kind: Role
apiVersion: rbac.authorization.k8s.io/v1
metadata:
  name: leader-locking-nfs-provisioner
rules:
  - apiGroups: [""]
    resources: ["endpoints"]
    verbs: ["get", "list", "watch", "create", "update", "patch"]
---
kind: RoleBinding
apiVersion: rbac.authorization.k8s.io/v1
metadata:
  name: leader-locking-nfs-provisioner
subjects:
- kind: ServiceAccount
  name: nfs-provisioner
  namespace: default
roleRef:
  kind: Role
  name: leader-locking-nfs-provisioner
  apiGroup: rbac.authorization.k8s.io

[root@master 4]# kubectl apply -f rbac.yaml
clusterrole.rbac.authorization.k8s.io/nfs-provisioner-runner created
clusterrolebinding.rbac.authorization.k8s.io/run-nfs-provisioner created
role.rbac.authorization.k8s.io/leader-locking-nfs-provisioner created
rolebinding.rbac.authorization.k8s.io/leader-locking-nfs-provisioner created

  • 创建pod
    把nfs-client-provisioner.tar.gz上传到node工作节点上,手动解压。
    ctr -n=k8s.io image import nfs-client-provisioner.tar.gz
    通过deployment创建pod用来运行nfs-provisioner
[root@master 4]# cat deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
 name: nfs-provisioner
spec:
  selector:
    matchLabels:
     app: nfs-provisioner
  replicas: 1
  strategy:
      type: Recreate
  template:
    metadata:
      labels:
        app: nfs-provisioner
    spec:
      serviceAccount: nfs-provisioner
      containers:
      - name: nfs-provisioner
        # 这个供应商镜像如果有问题,就换成其他的,我的最后换成了
        # registry.cn-beijing.aliyuncs.com/mydlq/nfs-subdir-external-provisioner 前提是这个镜像上传到了node节点
        image: registry.cn-hangzhou.aliyuncs.com/open-ali/xianchao/nfs-client-provisioner:v1
        imagePullPolicy: IfNotPresent
        volumeMounts:
        - name: nfs-client-root
          mountPath: /persistentvolumes
        env:
        - name: PROVISIONER_NAME
          value: example.com/nfs
        - name: NFS_SERVER
          value: 10.32.1.147
          #这个需要写nfs服务端所在的ip地址,大家需要写自己安装了nfs服务的机器ip
        - name: NFS_PATH
          value: /data/v1
      volumes:
        # 这个是nfs服务端共享的目录
        - name: nfs-client-root
          nfs:
           server: 10.32.1.147
           path: /data/v1

[root@master 4]# kubectl apply -f deployment.yaml
deployment.apps/nfs-provisioner configured
[root@master 4]# kubectl get pods -owide| grep nfs
nfs-provisioner-5fb64dc877-4pzbk   1/1     Running   0             6m49s   10.244.196.143   node01   <none>           <none>

  • 创建storageclass
[root@master 4]# cat class.yaml
apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
  name: do-block-storage
provisioner: example.com/nfs
[root@master 4]# k apply -f class.yaml
storageclass.storage.k8s.io/do-block-storage created
[root@master 4]# k get sc
NAME               PROVISIONER       RECLAIMPOLICY   VOLUMEBINDINGMODE   ALLOWVOLUMEEXPANSION   AGE
do-block-storage   example.com/nfs   Delete          Immediate           false                  70m

【3】安装Elasticsearch集群

把elasticsearch_7_2_0.tar.gz和busybox.tar.gz
上传到工作节点node01、node02,手动解压:

[root@node01 package]# ctr -n=k8s.io image import elasticsearch\_7\_2\_0.tar.gz
[root@node02 package]# ctr -n=k8s.io image import elasticsearch\_7\_2\_0.tar.gz

更新和应用yaml文件

[root@master 4]# cat elasticsearch-statefulset.yaml
apiVersion: apps/v1
kind: StatefulSet
metadata:
  name: es-cluster
  namespace: kube-logging
spec:
  serviceName: elasticsearch
  replicas: 3
  selector:
    matchLabels:
      app: elasticsearch
  template:
    metadata:
      labels:
        app: elasticsearch
    spec:
      containers:
      - name: elasticsearch
        image: docker.elastic.co/elasticsearch/elasticsearch:7.2.0
        imagePullPolicy: IfNotPresent
        resources:
          limits:
            cpu: 1000m
          requests:
            cpu: 100m
        ports:
          - containerPort: 9200
            name: rest
            protocol: TCP
          - containerPort: 9300
            name: inter-node
            protocol: TCP
        volumeMounts:
        - name: data
          mountPath: /usr/share/elasticsearch/data
        env:
        - name: cluster.name
          value: k8s-logs
        - name: node.name
          valueFrom:
            fieldRef:
              fieldPath: metadata.name
        - name: discovery.seed_hosts
          value: "es-cluster-0.elasticsearch,es-cluster-1.elasticsearch,es-cluster-2.elasticsearch"
        - name: cluster.initial_master_nodes
          value: "es-cluster-0,es-cluster-1,es-cluster-2"
        - name: ES_JAVA_OPTS
          value: "-Xms512m -Xmx512m"
      initContainers:
      - name: fix-permissions
        image: busybox
        imagePullPolicy: IfNotPresent
        command: ["sh", "-c", "chown -R 1000:1000 /usr/share/elasticsearch/data"]
        securityContext:
          privileged: true
        volumeMounts:
        - name: data
          mountPath: /usr/share/elasticsearch/data
      - name: increase-vm-max-map
        image: busybox
        imagePullPolicy: IfNotPresent
        command: ["sysctl", "-w", "vm.max\_map\_count=262144"]
        securityContext:
          privileged: true
      - name: increase-fd-ulimit
        image: busybox
        imagePullPolicy: IfNotPresent
        command: ["sh", "-c", "ulimit -n 65536"]
        securityContext:
          privileged: true
  volumeClaimTemplates:
  - metadata:
      name: data
      labels:
        app: elasticsearch
    spec:
      accessModes: [ "ReadWriteOnce" ]
      storageClassName: do-block-storage
      resources:
        requests:
          storage: 5Gi

上面内容的解释:在kube-logging的名称空间中定义了一个es-cluster的StatefulSet。
然后,我们使用serviceName 字段与我们之前创建的headless ElasticSearch服务相关联。这样可以确保可以使用以下DNS地址访问StatefulSet中的每个Pod:,es-cluster-[0,1,2].elasticsearch.kube-logging.svc.cluster.local,其中[0,1,2]与Pod分配的序号数相对应。
我们指定3个replicas(3个Pod副本),将selector matchLabels 设置为app: elasticseach。该.spec.selector.matchLabels和.spec.template.metadata.labels字段必须匹配。

[root@master 4]# kubectl get pods -n kube-logging
NAME           READY   STATUS    RESTARTS   AGE
es-cluster-0   1/1     Running   0          10m
es-cluster-1   1/1     Running   0          10m
es-cluster-2   1/1     Running   0          10m
[root@master 4]# kubectl get svc -n kube-logging
NAME            TYPE        CLUSTER-IP   EXTERNAL-IP   PORT(S)             AGE
elasticsearch   ClusterIP   None         <none>        9200/TCP,9300/TCP   6h15m


pod部署完成之后,可以通过REST API检查elasticsearch集群是否部署成功,使用下面的命令将本地端口9200转发到 Elasticsearch 节点(如es-cluster-0)对应的端口:

kubectl port-forward es-cluster-0 9200:9200 --namespace=kube-logging
然后,在另外的终端窗口中,执行如下请求,新开一个master1终端:

[root@master 4]# curl http://localhost:9200/\_cluster/state?pretty|head -50
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
 10  146k   10 16294    0     0   310k      0 --:--{-- --:--:-- --:--:--     0
  "cluster\_name" : "k8s-logs",
  "cluster\_uuid" : "GCzlBOZnT8abADeTCJyrRg",
  "version" : 17,
  "state\_uuid" : "yIAM6AEzSdOCgK9FHmuriQ",
  "master\_node" : "7UL9lwt2Qa-Rx9S-5hm3tQ",
  "blocks" : { },
  "nodes" : {
    "6FkyqeBnQ9GGJjqxmIK4OA" : {
      "name" : "es-cluster-2",
      "ephemeral\_id" : "T8DdDj6tQSm-mERp4rkrNg",
      "transport\_address" : "10.244.196.142:9300",
      "attributes" : {
        "ml.machine\_memory" : "8201035776",
        "ml.max\_open\_jobs" : "20",
        "xpack.installed" : "true"
      }
    },
    "7UL9lwt2Qa-Rx9S-5hm3tQ" : {
      "name" : "es-cluster-0",
      "ephemeral\_id" : "JFYS2bHqTD-FaxV5IpACWQ",
      "transport\_address" : "10.244.196.135:9300",
      "attributes" : {
        "ml.machine\_memory" : "8201035776",
        "xpack.installed" : "true",
        "ml.max\_open\_jobs" : "20"
      }
    },
    "QRd7XeJ5TtO-bdaru3wAkg" : {
      "name" : "es-cluster-1",
      "ephemeral\_id" : "uG4ZE\_N8QGGNDyXnE4puSQ",
      "transport\_address" : "10.244.140.105:9300",
      "attrib:--utes" : {
         "ml.machine\_memory" : "8201248768",
-        "ml.max\_open\_jobs" : "20",
-        "xpack.installed" : "true"
:      }
-    }
-  },
# 看到上面的信息就表明我们名为 k8s-logs 的 Elasticsearch 集群成功创建了3个节点:
# es-cluster-0,es-cluster-1,和es-cluster-2
# 当前主节点是 es-cluster-0

3.2、安装kibana可视化UI界面

[root@master 4]# cat kibana.yaml
apiVersion: v1
kind: Service
metadata:
  name: kibana
  namespace: kube-logging
  labels:
    app: kibana
spec:
  ports:
  - port: 5601
  selector:
    app: kibana
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: kibana
  namespace: kube-logging
  labels:
    app: kibana
spec:
  replicas: 1
  selector:
    matchLabels:
      app: kibana
  template:
    metadata:
      labels:
        app: kibana
    spec:
      containers:
      - name: kibana
        image: docker.elastic.co/kibana/kibana:7.2.0
        imagePullPolicy: IfNotPresent
        resources:
          limits:
            cpu: 1000m
          requests:
            cpu: 100m
        env:
        - name: ELASTICSEARCH_URL
          value: http://elasticsearch:9200
        ports:
        - containerPort: 5601



**自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。**

**深知大多数大数据工程师,想要提升技能,往往是自己摸索成长或者是报班学习,但对于培训机构动则几千的学费,着实压力不小。自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!**

**因此收集整理了一份《2024年大数据全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友。**
![img](https://img-blog.csdnimg.cn/img_convert/b7d356a01bf4935a27af1bdd164253fe.png)
![img](https://img-blog.csdnimg.cn/img_convert/5268dc90b3011ac4b4076e9869b3841e.png)
![img](https://img-blog.csdnimg.cn/img_convert/8ff1d780d95b4ab3b311e3f170a8a8a6.png)
![img](https://img-blog.csdnimg.cn/img_convert/9bf34dba869dde07e5127e73a881d3e9.png)
![img](https://img-blog.csdnimg.cn/img_convert/808b52a3b5500b9cf4c7590061098b00.png)

**既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上大数据开发知识点,真正体系化!**

**由于文件比较大,这里只是将部分目录大纲截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且后续会持续更新**

**如果你觉得这些内容对你有帮助,可以添加VX:vip204888 (备注大数据获取)**
![img](https://img-blog.csdnimg.cn/img_convert/ca2bac9091857d5b4939463e4c349dd1.png)

**一个人可以走的很快,但一群人才能走的更远。不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎扫码加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!**

收集整理了一份《2024年大数据全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友。**
[外链图片转存中...(img-02YbhAMq-1712995903837)]
[外链图片转存中...(img-E6ZGyybO-1712995903837)]
[外链图片转存中...(img-QnHIAu5L-1712995903838)]
[外链图片转存中...(img-Qek0xGcq-1712995903838)]
[外链图片转存中...(img-EHZRAMme-1712995903838)]

**既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上大数据开发知识点,真正体系化!**

**由于文件比较大,这里只是将部分目录大纲截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且后续会持续更新**

**如果你觉得这些内容对你有帮助,可以添加VX:vip204888 (备注大数据获取)**
[外链图片转存中...(img-HYixFMtP-1712995903838)]

**一个人可以走的很快,但一群人才能走的更远。不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎扫码加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!**

  • 17
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
在运维开发Kubernetes(k8s)面试中,通常会涉及到以下几个方面: 1. Kubernetes基础知识:面试官可能会问你Kubernetes的概念、架构和组件,以及它的工作原理和优势等等。你需要了解Pod、Service、Namespace、Deployment、ReplicaSet等基本概念,并且能够解释它们之间的关系和作用。 2. 应用部署与管理:面试官可能会询问你如何在Kubernetes上行应用的部署和管理。你需要熟悉使用Kubectl命令行工具或Helm行应用的创建、更新和删除,并且了解如何行应用扩缩容、滚动更新和版本回滚等操作。 3. 资源调度与管理:面试官可能会关注你对资源调度和管理的理解。你需要清楚如何为Pod分配CPU和内存资源,以及如何设置资源配额和限制。此外,你还需要了解Kubernetes的调度策略和调度器的工作原理。 4. 监控和日志面试官可能会问你如何在Kubernetes中行应用的监控和日志收集。你需要了解Prometheus、Grafana和EFK等常用的监控和日志工具,并且知道如何在Kubernetes中配置和使用它们。 5. 故障排查与修复:面试官可能会考察你对故障排查和修复的能力。你需要熟悉常见的Kubernetes故障场景,如Pod启动失败、网络故障等,以及相应的排查和修复方法。 6. 安全与权限:面试官可能会询问你如何在Kubernetes中行访问控制和安全设置。你需要了解RBAC的概念和使用方法,并且知道如何创建和管理用户、角色和角色绑定等。 总之,在准备运维开发Kubernetes面试时,你需要深入了解Kubernetes的架构和相关概念,并且熟悉常用的命令和工具。此外,实践经验和项目经历也非常重要,因此建议你在实际项目中多动手操作和实践,从而更好地准备和回答面试

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值