51、Kubernetes 日志收集与监控实战

Kubernetes 日志收集与监控实战

在 Kubernetes 环境中,日志收集和监控是确保系统稳定性和性能的关键环节。本文将详细介绍如何在 Kubernetes 中进行应用程序日志收集、Kubernetes 日志处理、etcd 日志收集以及主节点和工作节点的监控。

1. 应用程序日志收集

在管理应用程序时,日志收集和分析对于跟踪应用程序状态至关重要。但在 Docker/Kubernetes 环境中,由于日志文件位于容器内部,从容器外部访问它们并不容易。为了解决这个问题,可以使用集中式日志收集平台,如 ELK(Elasticsearch、Logstash、Kibana)。

1.1 准备 Elasticsearch 服务器

首先,需要准备 Elasticsearch 服务器。可以通过以下步骤下载并设置 Elasticsearch:

# 下载 Kubernetes 压缩包
curl -L -O https://github.com/kubernetes/kubernetes/releases/download/v1.1.4/kubernetes.tar.gz
# 解压文件
tar zxf kubernetes.tar.gz 
# 进入 Elasticsearch 示例目录
cd kubernetes/examples/elasticsearch/
# 创建 ServiceAccount
kubectl create -f service-account.yaml 
# 创建 Elasticsearch 复制控制器
kubectl create -f es-rc.yaml --validate=false
# 创建 Elasticsearch 服务
kubectl create -f es-svc.yaml 

创建完成后,可以通过 Kubernetes 服务访问 Elasticsearch 接口:

# 获取服务信息
kubectl get service
# 访问 Elasticsearch
curl http://192.168.45.152:9200/
1.2 准备示例应用程序

使用一个 Python Flask 程序作为示例应用程序:

# cat entry.py
from flask import Flask, request 
app = Flask(__name__) 
@app.route("/") 
def hello(): 
    return "Hello World!" 
@app.route("/addition/<int:x>/<int:y>") 
def add(x, y): 
    return "%d" % (x+y) 
if __name__ == "__main__": 
    app.run(host='0.0.0.0') 
1.3 使用 Logstash 发送日志

Logstash 可以将应用程序日志从纯文本格式转换为 Elasticsearch 所需的 JSON 格式。首先,需要创建一个 Logstash 配置文件:

# cat logstash.conf.temp 
input { 
    stdin {}
}
filter {
  grok {
    match => {
        "message" => "%{IPORHOST:clientip} %{HTTPDUSER:ident} %{USER:auth} \[%{DATA:timestamp}\] \"(?:%{WORD:verb} %{NOTSPACE:request}(?: HTTP/%{NUMBER:httpversion})?|%{DATA:rawrequest})\" %{NUMBER:response} (?:%{NUMBER:bytes}|-)"
    }
  }
}
output {
  elasticsearch {
    hosts => ["_ES_IP_:_ES_PORT_"]
    index => "mycalc-access"
}
stdout { codec => rubydebug }
}

然后,创建一个启动脚本,用于替换配置文件中的占位符:

#!/bin/sh
TEMPLATE="logstash.conf.temp"
LOGSTASH="logstash-2.2.2/bin/logstash"
cat $TEMPLATE | sed "s/_ES_IP_/$ELASTICSEARCH_SERVICE_HOST/g" | sed "s/_ES_PORT_/$ELASTICSEARCH_SERVICE_PORT/g" > logstash.conf
python entry.py 2>&1 | $LOGSTASH -f logstash.conf
1.4 构建 Docker 镜像

使用 Dockerfile 构建示例应用程序的 Docker 镜像:

FROM ubuntu:14.04
# 更新软件包
RUN apt-get update -y
# 安装 Python Setuptools
RUN apt-get install -y python-setuptools git telnet curl openjdk-7-jre
# 安装 pip
RUN easy_install pip
# 复制应用程序代码
ADD . /src
WORKDIR /src
# 下载 LogStash
RUN curl -L -O https://download.elastic.co/logstash/logstash/logstash-2.2.2.tar.gz
RUN tar -zxf logstash-2.2.2.tar.gz
# 安装 Python 模块
RUN pip install Flask
# 暴露端口
EXPOSE  5000
# 运行启动脚本
CMD ["./startup.sh"]

构建并上传镜像到 Docker Hub:

# 构建镜像
docker build -t hidetosaito/my-calc-elk .
# 登录 Docker Hub
docker login
# 推送镜像
docker push hidetosaito/my-calc-elk
1.5 创建 Kubernetes 复制控制器和服务

使用 YAML 文件创建 Kubernetes 复制控制器和服务:

# cat my-calc-elk.yaml 
apiVersion: v1
kind: ReplicationController
metadata:
  name: my-calc-elk-rc
spec:
  replicas: 2
  selector:
        app: my-calc-elk
  template:
    metadata:
      labels:
        app: my-calc-elk
    spec:
      containers:
      - name: my-calc-elk
        image: hidetosaito/my-calc-elk
---
apiVersion: v1
kind: Service
metadata:
  name: my-calc-elk-service
spec:
  ports:
    - protocol: TCP
      port: 5000
  type: ClusterIP
  selector:
     app: my-calc-elk

创建复制控制器和服务:

# 创建复制控制器和服务
kubectl create -f my-calc-elk.yaml 
# 获取服务信息
kubectl get service
# 访问应用程序
curl http://192.168.121.63:5000/
curl http://192.168.121.63:5000/addition/3/5
1.6 使用 Kibana 可视化日志

Kibana 是一个用于 Elasticsearch 的可视化工具。下载并启动 Kibana:

# 下载 Kibana
curl -O https://download.elastic.co/kibana/kibana/kibana-4.1.6-linux-x64.tar.gz
# 解压文件
tar -zxf kibana-4.1.6-linux-x64.tar.gz
# 查找 Elasticsearch IP 地址
kubectl get services
# 指定 Elasticsearch IP 地址
sed -i -e "s/localhost/192.168.101.143/g" kibana-4.1.6-linux-x64/config/kibana.yml
# 启动 Kibana
kibana-4.1.6-linux-x64/bin/kibana 

启动后,在浏览器中访问 Kibana 界面,即可查看应用程序日志。

2. 处理 Kubernetes 日志

Kubernetes 主节点上有三个守护进程:API 服务器、调度器和控制器管理器,它们的日志文件分别记录在 /var/log 文件夹下:
| 主节点守护进程 | 日志文件 | 描述 |
| — | — | — |
| API 服务器 | apiserver.log | API 调用日志 |
| 调度器 | k8s-scheduler.log | 容器调度事件的调度器数据日志 |
| 控制器管理器 | controller-manager.log | 与控制器管理器相关的事件或问题日志 |

节点上有一个 kubelet 进程,用于处理容器操作并向主节点报告,其日志文件为 kubelet.log 。此外,主节点和节点上还有一个 kube-proxy.log 文件,用于记录网络连接问题。

2.1 准备工作

使用 ELK 作为集中式日志平台收集 Kubernetes 日志。在收集日志之前,需要了解日志的数据结构,其格式如下:

<log level><date> <timestamp> <indicator> <source file>:<line number>] <logs>

例如:

E0328 00:46:50.870875    3189 reflector.go:227] pkg/proxy/config/api.go:60: Failed to watch *api.Endpoints: too old resource version: 45128 (45135)

通过日志文件中每行的首字符可以判断日志的严重程度:
- D: DEBUG
- I: INFO
- W: WARN
- E: ERROR
- F: FATAL

2.2 收集 Kubernetes 日志

使用 Logstash 的 grok 过滤器处理日志。首先,创建一个自定义模式文件:

# cat ./patterns/k8s
LOGLEVEL    [DEFIW]
DATE        [0-9]{4}
K8SLOGLEVEL %{LOGLEVEL:level}%{DATE}

然后,创建一个 Logstash 配置文件,用于收集 k8s-apiserver.log 日志:

# cat apiserver.conf
input {
  file {
    path => "/var/log/k8s-apiserver.log"
  }
}
filter {
  grok {
    patterns_dir => ["./patterns"]
    match => { "message" => "%{K8SLOGLEVEL} %{TIME}    %{NUMBER} %{PROG:program}:%{POSINT:line}] %{GREEDYDATA:message}" }
  }
}
output {
  elasticsearch {
    hosts => ["_ES_IP_:_ES_PORT_"]
    index => "k8s-apiserver"
  }
  stdout { codec => rubydebug }
}

启动 Logstash 处理日志:

# 启动 Logstash
bin/logstash -f apiserver.conf
3. 处理 etcd 日志

etcd 是 Kubernetes 的数据存储,用于保存 Kubernetes 资源的信息。在 etcd 服务器上,日志文件记录在 /var/log/etcd.log 中,其格式如下:

<date> <time> <subpackage>: <logs>

例如:

2016/04/4 08:43:51 etcdserver: starting server... [version: 2.1.1, cluster version: to_be_decided]
3.1 准备工作

在收集 etcd 日志之前,需要准备好 ELK 服务器。如果 etcd 服务器是 Kubernetes 集群之外的独立机器,需要将 Elasticsearch 服务暴露出来:

# cat es-svc.yaml
apiVersion: v1
kind: Service
metadata:
  name: elasticsearch
  labels:
    component: elasticsearch
spec:
  type: LoadBalancer
  selector:
    component: elasticsearch
  ports:
  - name: http
    port: 9200
    nodePort: 30000
    protocol: TCP
  - name: transport
    port: 9300
    protocol: TCP
3.2 收集 etcd 日志

创建一个 Logstash 配置文件,用于收集 etcd 日志:

# cat etcd.conf
input {
  file {
    path => "/var/log/etcd.log"
  }
}
filter {
  grok {
    match => {
        "message" => "%{DATA:date} %{TIME:time} %{PROG:subpackage}: %{GREEDYDATA:message}"
    }
  }
}
output {
  elasticsearch {
    hosts => ["<ELASTIC_SERVICE_IP>:<EXPOSE_PORT>"]
    index => "etcd-log"
  }
  stdout { codec => rubydebug }
}

启动 Logstash 处理日志:

# 启动 Logstash
./bin/logstash -f etcd.conf
4. 监控主节点和工作节点

监控主节点和工作节点可以帮助我们了解资源消耗情况,提高资源利用率。在设置监控集群之前,需要完成以下两个先决条件:
- 更新 Kubernetes 到最新版本(1.2.1)
- 设置 DNS 服务器

4.1 更新 Kubernetes 到最新版本

更新运行中的 Kubernetes 系统版本的步骤如下:
1. 停止所有 Kubernetes 服务:

service <KUBERNETES_DAEMON> stop
  1. 下载最新的 tarball 文件:
cd /tmp && wget https://storage.googleapis.com/kubernetes-release/release/v1.2.1/kubernetes.tar.gz
  1. 解压文件:
tar -xvf /tmp/kubernetes.tar.gz -C /opt/
cd /opt && tar -xvf /opt/kubernetes/server/kubernetes-server-linux-amd64.tar.gz
  1. 复制新文件并覆盖旧文件:
cd /opt/kubernetes/server/bin/
# 主节点
cp kubectl hypercube kube-apiserver kube-controller-manager kube-scheduler kube-proxy /usr/local/bin
# 节点
cp kubelet kube-proxy /usr/local/bin
  1. 启动系统服务并验证版本:
kubectl version
4.2 设置 DNS 服务器

使用官方模板在 Kubernetes 系统中设置 DNS 服务器,步骤如下:
1. 复制模板文件并修改:

cp skydns-rc.yaml.in skydns-rc.yaml
cp skydns-svc.yaml.in skydns-svc.yaml

替换模板文件中的变量:
| 输入变量 | 替换值 | 示例 |
| — | — | — |
| {{ pillar[‘dns_domain’] }} | 集群的域名 | k8s.local |
| {{ pillar[‘dns_replicas’] }} | 复制控制器的副本数 | 1 |
| {{ pillar[‘dns_server’] }} | DNS 服务器的私有 IP | 192.168.0.2 |
2. 创建资源:

kubectl create -f skydns-svc.yaml
kubectl create -f skydns-rc.yaml
  1. 在 kubelet 中启用 Kubernetes DNS:
# 对于 init 服务
# cat /etc/init.d/kubernetes-node
# 添加 DNS 信息
daemon $kubelet_prog \
        --api_servers=<MASTER_ENDPOINT_URL>:<EXPOSED_PORT> \
        --v=2 \
        --cluster-dns=192.168.0.2 \
        --cluster-domain=k8s.local \
        --address=0.0.0.0 \
        --enable_server \
        --hostname_override=${hostname} \
        > ${logfile}-kubelet.log 2>&1 &
# 对于 systemd 服务
# cat /etc/kubernetes/kubelet
# 添加 DNS 信息
KUBELET_ARGS="--cluster-dns=192.168.0.2 --cluster-domain=k8s.local"

重启 kubelet 服务。

4.3 安装监控集群

使用 Heapster、influxDB 和 Grafana 构建监控系统。步骤如下:
1. 检查监控集群的目录:

cd /opt/kubernetes/cluster/addons/cluster-monitoring/influxdb && ls
  1. 保留大部分服务模板的默认设置,但暴露 Grafana 服务:
# cat heapster-service.yaml
apiVersion: v1
kind: Service
metadata:
  name: monitoring-grafana
  namespace: kube-system
  labels:
    kubernetes.io/cluster-service: "true"
    kubernetes.io/name: "Grafana"
spec:
  type: NodePort
  ports:
    - port: 80
      nodePort: 30000
      targetPort: 3000
  selector:
    k8s-app: influxGrafana
  1. 修改 Heapster 和 influxDB-Grafana 复制控制器的模板:
# cat influxdb-grafana-controller.yaml
# 修改 Grafana 容器的环境变量
- image: gcr.io/google_containers/heapster_grafana:v2.6.0-2
          name: grafana
          env:
          resources:
            limits:
              cpu: 100m
              memory: 100Mi
            requests:
              cpu: 100m
              memory: 100Mi
          env:
            - name: INFLUXDB_SERVICE_URL
              value: http://monitoring-influxdb.kube-system:8086
            - name: GF_AUTH_BASIC_ENABLED
              value: "false"
            - name: GF_AUTH_ANONYMOUS_ENABLED
              value: "true"
            - name: GF_AUTH_ANONYMOUS_ORG_ROLE
              value: Admin
            - name: GF_SERVER_ROOT_URL
              value: /
# cat heapster-controller.yaml
# 修改 Heapster 容器的参数
      containers:
        - image: gcr.io/google_containers/heapster:v1.0.2
          name: heapster
          resources:
            limits:
              cpu: 100m
              memory: 200Mi
            requests:
              cpu: 100m
              memory: 200Mi
          command:
            - /heapster
            - --source=kubernetes:<MASTER_ENDPOINT_URL>:<EXPOSED_PORT>?inClusterConfig=false
            - --sink=influxdb:http://monitoring-influxdb.kube-system:8086
            - --metric_resolution=60s
  1. 创建资源:
kubectl create -f influxdb-service.yaml
kubectl create -f grafana-service.yaml
kubectl create -f heapster-service.yaml
kubectl create -f influxdb-grafana-controller.yaml
kubectl create -f heapster-controller.yaml
  1. 检查 Kubernetes 资源:
kubectl get svc --namespace=kube-system
kubectl get pod --namespace=kube-system
4.4 介绍 Grafana 仪表盘

在浏览器中访问 Grafana 仪表盘: <NODE_ENDPOINT>:30000 。默认情况下,有两个仪表盘:Cluster 和 Pods。Cluster 仪表盘显示节点的资源利用率,Pods 仪表盘显示每个 Pod 的资源使用情况。

4.5 创建自定义监控指标

创建自定义监控指标的步骤如下:
1. 进入 Pods 仪表盘,点击 ADD ROW,选择添加图形面板。
2. 给面板命名,例如 CPU Rate。
3. 设置查询参数:
- FROM: cpu/usage_rate
- WHERE: type = pod_container
- AND: namespace_name=$namespace, pod_name= $podname
- GROUP BY: tag(container_name)
- ALIAS BY: $tag_container_name
4. 保存面板。

通过以上步骤,我们可以在 Kubernetes 环境中实现应用程序日志收集、Kubernetes 日志处理、etcd 日志收集以及主节点和工作节点的监控。这些操作可以帮助我们更好地了解系统的运行状态,及时发现和解决问题。

Kubernetes 日志收集与监控实战

5. 总结与最佳实践
5.1 日志收集总结
  • 应用程序日志 :通过 ELK 堆栈(Elasticsearch、Logstash、Kibana)可以有效地收集和可视化应用程序日志。将 Logstash 与应用程序容器捆绑在一起,即使复制控制器增加副本数量,也能无配置更改地捕获所有应用程序日志。
  • Kubernetes 日志 :利用 Logstash 的 grok 过滤器可以解析 Kubernetes 主节点和节点上各种守护进程的日志,将其发送到 Elasticsearch 进行集中存储和分析。
  • etcd 日志 :同样使用 Logstash 收集 etcd 日志,通过自定义的 grok 模式解析日志格式,方便后续的查询和分析。
5.2 监控总结
  • 前置条件 :更新 Kubernetes 到最新版本并设置 DNS 服务器是搭建监控系统的重要前提。DNS 服务器可以简化服务连接,减少配置依赖。
  • 监控系统 :基于 Heapster、influxDB 和 Grafana 构建的监控系统,可以实时监控节点和 Pod 的资源使用情况。Grafana 提供了直观的可视化界面,方便用户查看和分析数据。
5.3 最佳实践
  • 日志管理
    • 定期清理 Elasticsearch 中的过期日志,避免占用过多磁盘空间。
    • 为不同类型的日志设置不同的索引,便于管理和查询。
    • 对日志进行备份,以防数据丢失。
  • 监控管理
    • 定期检查监控系统的运行状态,确保数据收集和可视化的正常进行。
    • 根据实际需求调整监控指标和阈值,及时发现潜在的问题。
    • 对监控数据进行长期存储和分析,以便进行容量规划和性能优化。
6. 未来展望

随着 Kubernetes 的不断发展,日志收集和监控领域也会有更多的创新和改进。以下是一些可能的发展方向:

6.1 自动化日志分析

未来可能会出现更多的自动化日志分析工具,能够自动识别和分类日志中的异常信息,提供更智能的问题诊断和解决方案。

6.2 集成更多监控数据源

除了现有的资源使用监控,可能会集成更多的数据源,如网络流量、存储 I/O 等,提供更全面的系统监控。

6.3 云原生监控解决方案

随着云原生技术的普及,可能会出现更多专门为 Kubernetes 设计的云原生监控解决方案,提供更高效、更便捷的监控服务。

7. 流程图回顾

以下是整个日志收集和监控流程的 mermaid 流程图:

graph LR
    classDef startend fill:#F5EBFF,stroke:#BE8FED,stroke-width:2px
    classDef process fill:#E5F6FF,stroke:#73A6FF,stroke-width:2px
    classDef decision fill:#FFF6CC,stroke:#FFBC52,stroke-width:2px

    A([开始]):::startend --> B(应用程序日志收集):::process
    B --> B1(准备 Elasticsearch):::process
    B --> B2(准备示例应用):::process
    B --> B3(使用 Logstash 发送日志):::process
    B --> B4(构建 Docker 镜像):::process
    B --> B5(创建 Kubernetes 资源):::process
    B --> B6(使用 Kibana 可视化):::process

    A --> C(Kubernetes 日志处理):::process
    C --> C1(了解日志结构):::process
    C --> C2(创建自定义模式):::process
    C --> C3(创建 Logstash 配置):::process
    C --> C4(启动 Logstash 收集):::process

    A --> D(etcd 日志收集):::process
    D --> D1(准备 ELK 服务器):::process
    D --> D2(暴露 Elasticsearch 服务):::process
    D --> D3(创建 Logstash 配置):::process
    D --> D4(启动 Logstash 收集):::process

    A --> E(监控主节点和工作节点):::process
    E --> E1(更新 Kubernetes 版本):::process
    E --> E2(设置 DNS 服务器):::process
    E --> E3(安装监控集群):::process
    E --> E4(使用 Grafana 仪表盘):::process
    E --> E5(创建自定义指标):::process

    B6 & C4 & D4 & E5 --> F([结束]):::startend

这个流程图展示了从开始到结束的整个日志收集和监控过程,包括应用程序日志、Kubernetes 日志、etcd 日志的收集,以及主节点和工作节点的监控。每个步骤都有明确的操作和依赖关系,帮助读者更好地理解整个流程。

8. 常见问题解答
8.1 日志收集问题
  • 问题 :Logstash 无法连接到 Elasticsearch。
    • 解决方案 :检查 Elasticsearch 的 IP 地址和端口是否正确,确保 Logstash 配置文件中的占位符已正确替换为实际值。同时,检查网络连接是否正常。
  • 问题 :日志解析错误。
    • 解决方案 :检查 grok 模式是否正确,确保模式能够匹配日志的实际格式。可以使用 Logstash 的调试模式进行验证。
8.2 监控问题
  • 问题 :Grafana 仪表盘无法显示数据。
    • 解决方案 :检查 Heapster 是否正常工作,确保它能够正确收集资源使用数据。同时,检查 influxDB 是否正常存储数据,以及 Grafana 配置中数据源的设置是否正确。
  • 问题 :监控系统性能下降。
    • 解决方案 :检查 influxDB 的磁盘使用情况,确保有足够的空间存储数据。同时,调整 Heapster 的数据收集频率,避免过度收集数据导致性能问题。

通过以上的总结、展望、流程图和常见问题解答,希望读者能够更好地掌握 Kubernetes 日志收集和监控的相关知识,在实际应用中更加得心应手。不断学习和实践,将有助于我们更好地管理和优化 Kubernetes 集群。

基于径向基函数神经网络RBFNN的自适应滑模控制学习(Matlab代码实现)内容概要:本文介绍了基于径向基函数神经网络(RBFNN)的自适应滑模控制方法,并提供了相应的Matlab代码实现。该方法结合了RBF神经网络的非线性逼近能力和滑模控制的强鲁棒性,用于解决复杂系统的控制问题,尤其适用于存在不确定性和外部干扰的动态系统。文中详细阐述了控制算法的设计思路、RBFNN的结构权重更新机制、滑模面的构建以及自适应律的推导过程,并通过Matlab仿真验证了所提方法的有效性和稳定性。此外,文档还列举了大量相关的科研方向和技术应用,涵盖智能优化算法、机器学习、电力系统、路径规划等多个领域,展示了该技术的广泛应用前景。; 适合人群:具备一定自动控制理论基础和Matlab编程能力的研究生、科研人员及工程技术人员,特别是从事智能控制、非线性系统控制及相关领域的研究人员; 使用场景及目标:①学习和掌握RBF神经网络滑模控制相结合的自适应控制策略设计方法;②应用于电机控制、机器人轨迹跟踪、电力电子系统等存在模型不确定性或外界扰动的实际控制系统中,提升控制精度鲁棒性; 阅读建议:建议读者结合提供的Matlab代码进行仿真实践,深入理解算法实现细节,同时可参考文中提及的相关技术方向拓展研究思路,注重理论分析仿真验证相结合。
先展示下效果 https://pan.quark.cn/s/a4b39357ea24 本项目是本人参加BAT等其他公司电话、现场面试之后总结出来的针对Java面试的知识点或真题,每个点或题目都是在面试中被问过的。 除开知识点,一定要准备好以下套路: 个人介绍,需要准备一个1分钟的介绍,包括学习经历、工作经历、项目经历、个人优势、一句话总结。 一定要自己背得滚瓜烂熟,张口就来 抽象概念,当面试官问你是如何理解多线程的时候,你要知道从定义、来源、实现、问题、优化、应用方面系统性地回答 项目强化,至少知识点的比例是五五开,所以必须针对简历中的两个以上的项目,形成包括【架构和实现细节】,【正常流程和异常流程的处理】,【难点+坑+复盘优化】三位一体的组合拳 压力练习,面试的时候难免紧张,可能会严重影响发挥,通过平时多找机会参交流分享,或找人做压力面试来改善 表达练习,表达能力非常影响在面试中的表现,能否简练地将答案告诉面试官,可以通过给自己讲解的方式刻意练习 重点针对,面试官会针对简历提问,所以请针对简历上写的所有技术点进行重点准备 Java基础 JVM原理 集合 多线程 IO 问题排查 Web框架、数据库 Spring MySQL Redis 通用基础 操作系统 网络通信协议 排序算法 常用设计模式 从URL到看到网页的过程 分布式 CAP理论 锁 事务 消息队列 协调器 ID生成方式 一致性hash 限流 微服务 微服务介绍 服务发现 API网关 服务容错保护 服务配置中心 算法 数组-快速排序-第k大个数 数组-对撞指针-最大蓄水 数组-滑动窗口-最小连续子数组 数组-归并排序-合并有序数组 数组-顺时针打印矩形 数组-24点游戏 链表-链表反转-链表相加 链表-...
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符  | 博主筛选后可见
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值