50、Kubernetes高级集群管理指南

Kubernetes高级集群管理指南

1. 清理kubeconfig

kubeconfig文件存储在 $HOME/.kube/config 。若删除该文件,配置将消失;若将文件恢复到该目录,配置也会恢复。

# 清理kubeconfig文件
# rm -f ~/.kube/config
# 查看当前配置
# kubectl config view
apiVersion: v1
clusters: []
contexts: []
current-context: ""
kind: Config
preferences: {}
users: []

kubeconfig用于管理集群、凭证和命名空间的设置。

2. 设置节点资源

2.1 准备工作

在管理计算资源前,需了解应用所需的最大资源。使用以下命令检查当前节点容量:

# 检查当前节点容量
# kubectl get nodes -o json | jq '.items[] | {name: .metadata.name, capacity: .status.capacity}'
{
  "name": "kube-node1",
  "capacity": {
    "cpu": "1",
    "memory": "1019428Ki",
    "pods": "40"
  }
}
{
  "name": "kube-node2",
  "capacity": {
    "cpu": "1",
    "memory": "1019428Ki",
    "pods": "40"
  }
}

当前有两个节点,每个节点有1个CPU、1019428字节内存,每个节点的Pod容量为40。

2.2 操作步骤

Kubernetes调度器调度Pod到节点上运行时,会确保容器的总限制小于节点容量。若节点资源耗尽,Kubernetes不会在其上调度新容器。若启动Pod时无可用节点,Pod将处于待处理状态。

2.2.1 管理节点容量

有时需为节点上的其他进程或未来使用保留一些资源。例如,要在所有节点上保留200MB资源:
1. 创建一个配置文件 /etc/kubernetes/reserve.yaml

apiVersion: v1
kind: Pod
metadata:
  name: resource-reserver
spec:
  containers:
  - name: resource-reserver
    image: gcr.io/google_containers/pause:0.8.0
    resources:
      limits:
        memory: 200Mi
  1. 找到kubelet配置文件,并在启动kubelet时添加参数 --config=/etc/kubernetes/reserve.yaml ,然后重启kubelet。
  2. 检查Pod列表:
# kubectl get pods
NAME                             READY     STATUS    RESTARTS   AGE
resource-reserver-kube-node1   1/1       Running   0          3m
  1. 查看Pod详细信息:
# kubectl describe pods resource-reserver-kube-node1
Name:        resource-reserver-kube-node1
Namespace:      default
Image(s):      gcr.io/google_containers/pause:0.8.0
Node:        kube-node1/10.0.0.224
Start Time:      Fri, 25 Mar 2016 20:44:24 +0000
Labels:        <none>
Status:        Running
IP:        192.168.99.3
Replication Controllers:  <none>
Containers:
  resource-reserver:
    ...
    QoS Tier:
      memory:  Guaranteed
    Limits:
      memory:  200Mi
    Requests:
      memory:    200Mi
    State:    Running
      Started:    Fri, 25 Mar 2016 20:44:24 +0000
    Ready:    True

该容器已保留了最小200MB和最大200MB的内存。在其他节点重复上述步骤,并使用 kubectl get pods 检查状态。

2.2.2 限制与请求

Kubernetes调度器通过检查剩余计算资源来调度Pod。可以为每个启动的Pod指定限制或请求。限制指Pod可占用的最大资源,请求指Pod所需的最小资源。它们的关系可用不等式表示: 0 <= 请求 <= Pod占用的资源 <= 限制 <= 节点容量

2.3 管理Pod中的计算资源

管理Pod或节点容量的概念类似,都在容器资源规范下指定请求或限制。
创建一个带有特定请求和限制的nginx Pod:

# cat nginx-resources.yaml
apiVersion: v1
kind: Pod
metadata:
  name: nginx
  labels:
    name: nginx
spec:
  containers:
  - name: nginx
    image: nginx
    ports:
    - containerPort: 80
    resources:
      requests:
        cpu: 250m
        memory: 32Mi
      limits:
        cpu: 500m
        memory: 64Mi
# 创建Pod
# kubectl create -f nginx-resources.yaml 
pod "nginx" created

该Pod的可用资源如下:
- CPU:250毫核 ~ 500毫核
- 内存:32MB ~ 64MB

使用以下命令查看Pod详细信息:

# kubectl describe pod nginx
Name:        nginx
Namespace:      default
Image(s):      nginx
Node:        kube-node1/10.0.0.224
Start Time:      Fri, 25 Mar 2016 21:12:43 +0000
Labels:        name=nginx
Status:        Running
Reason:
Message:
IP:        192.168.99.4
Replication Controllers:  <none>
Containers:
  nginx:
    ...
    QoS Tier:
      cpu:  Burstable
      memory:  Burstable
    Limits:
      memory:  64Mi
      cpu:  500m
    Requests:
      cpu:    250m
      memory:    32Mi
    State:    Running
      Started:    Fri, 25 Mar 2016 21:12:44 +0000
    Ready:    True
    Restart Count:  0

QoS层级为Burstable,与Guaranteed相比,Burstable有一定的缓冲空间可达到限制,但Guaranteed会始终为Pod保留一定资源。若指定过多Guaranteed的Pod,集群利用率会降低。

3. 使用WebUI

3.1 准备工作

Kubernetes WebUI地址为 http://<kubernetes master>/ui ,但默认未启动,发布二进制文件中有YAML文件。Kubernetes 1.2引入了仪表盘,更多信息可参考 http://kubernetes.io/docs/user-guide/ui/

3.2 操作步骤

下载发布二进制文件并启动WebUI:

# 下载发布二进制文件
$ curl -L -O https://github.com/kubernetes/kubernetes/releases/download/v1.1.4/kubernetes.tar.gz
# 解压二进制文件
$ tar zxf kubernetes.tar.gz
# WebUI YAML文件位于cluster/addons/kube-ui目录
$ cd kubernetes/cluster/addons/kube-ui/
$ ls
kube-ui-rc.yaml    kube-ui-svc.yaml

启动kube-ui复制控制器和服务:

# kubectl create -f kube-ui-rc.yaml 
replicationcontroller "kube-ui-v2" created
# kubectl create -f kube-ui-svc.yaml 
service "kube-ui" created

kube-ui-svc 是一种ClusterIP服务,可从外部通过 http://<kubernetes master>/ui 访问Kubernetes网络。

3.3 工作原理

kube-ui复制控制器通过API服务器获取Kubernetes集群信息,与 kubectl 命令类似,但为只读。它有助于查看Kubernetes状态,比 kubectl 命令更易于探索。

4. 使用RESTful API

4.1 准备工作

启动API服务器时,RESTful API默认开放,可使用 curl 命令访问:

# 假设API服务器在本地端口8080运行
# curl http://localhost:8080/api
{
  "kind": "APIVersions",
  "versions": [
    "v1"
  ]
}

4.2 操作步骤

使用JSON格式创建一个复制控制器:

# cat nginx-rc.json 
{
    "apiVersion": "v1",
    "kind": "ReplicationController",
    "metadata": {
        "name": "my-first-rc"
    },
    "spec": {
        "replicas": 2,
        "template": {
            "spec": {
                "containers": [
                    {
                        "image": "nginx",
                        "name": "my-nginx"
                    }
                ]
            },
            "metadata": {
                "labels": {
                    "app": "nginx"
                }
            }
        },
        "selector": {
            "app": "nginx"
        }
    }
}

提交请求创建复制控制器:

# curl -XPOST -H "Content-type: application/json" -d @nginx-rc.json http://localhost:8080/api/v1/namespaces/default/replicationcontrollers

使用 kubectl get rc 查看复制控制器:

# kubectl get rc
CONTROLLER    CONTAINER(S)   IMAGE(S)   SELECTOR    REPLICAS   AGE
my-first-rc   my-nginx       nginx      app=nginx   2          10s

使用 curl 命令通过RESTful API检查:

# curl -XGET http://localhost:8080/api/v1/namespaces/default/replicationcontrollers

使用RESTful API删除复制控制器:

# curl -XDELETE http://localhost:8080/api/v1/namespaces/default/replicationcontrollers/my-first-rc

使用Python 2.7代码创建相同的复制控制器:

# cat nginx-rc.py
import httplib
import json
k8s_master_url = "localhost"
k8s_master_port = 8080
namespace="default"
headers = {"Content-type": "applicaiton/json"}

rc = {}
rc["apiVersion"] = "v1"
rc["kind"] = "ReplicationController"
rc["metadata"] = {"name" : "my-second-rc"}
rc["spec"] = {
    "replicas": 2,
    "selector": {"app": "nginx"},
    "template": {
        "metadata": {"labels": {"app": "nginx"}},
        "spec": {
            "containers" :[
                {"name": "my-nginx", "image": "nginx"}
            ]
        }
    }
}
h1 = httplib.HTTPConnection(k8s_master_url, k8s_master_port)
h1.request("POST", "/api/v1/namespaces/%s/replicationcontrollers" % namespace, json.dumps(rc), headers)
res = h1.getresponse()
print "return code = %d" % res.status

运行代码:

# python nginx-rc.py 
return code = 201

HTTP返回码201表示“已创建”。

4.3 工作原理

RESTful API支持CRUD(创建、读取、更新和删除)操作,与现代Web应用的概念相同。Kubernetes RESTful API示例及相关HTTP方法如下表所示:
| 操作 | HTTP方法 | 示例 |
| ---- | ---- | ---- |
| 创建 | POST | POST /api/v1/namespaces/default/services |
| 读取 | GET | GET /api/v1/componentstatuses |
| 更新 | PUT | PUT /api/v1/namespaces/default/replicationcontrollers/my-first-rc |
| 删除 | DELETE | DELETE /api/v1/namespaces/default/pods/my-nginx |

整个Kubernetes RESTful API由Swagger定义,可通过 http://<API Server IP Address>:<API Server port>/swagger-ui 查看详细描述。

5. 认证与授权

5.1 准备工作

在为集群配置权限前,需先安装集群,并停止系统中的所有服务,后续将在启用认证的情况下启动它们。

5.2 操作步骤

5.2.1 启用API调用的认证
5.2.1.1 etcd的基本认证

默认情况下,任何人都可访问etcd数据:

# 在etcd中创建键值对
# curl -X PUT -d value="Happy coding" http://localhost:4001/v2/keys/message
{"action":"set","node":{"key":"/message","value":"Happy coding","modifiedIndex":4,"createdIndex":4}}
# 检查刚写入的值
# curl http://localhost:4001/v2/keys/message
{"action":"get","node":{"key":"/message","value":"Happy coding","modifiedIndex":4,"createdIndex":4}}
# 删除值
# curl -X DELETE http://localhost:4001/v2/keys/message
{"action":"delete","node":{"key":"/message","modifiedIndex":5,"createdIndex":4},"prevNode":{"key":"/message","value":"Happy coding","modifiedIndex":4,"createdIndex":4}}

启用etcd基本认证的步骤如下:
1. 为root管理员账户添加密码。
2. 启用基本认证。
3. 停止访客账户的读写权限。

# 发送API请求设置root账户
# curl -X PUT -d "{\"user\":\"root\",\"password\":\"<YOUR_ETCD_PASSWD>\",\"roles\":[\"root\"]}" http://localhost:4001/v2/auth/users/root
{"user":"root","roles":["root"]}
# 启用认证
# curl -X PUT http://localhost:4001/v2/auth/enable
# 将“USERACCOUNT:PASSWORD”字符串进行Base64编码并记录值
# AUTHSTR=$(echo -n "root:<YOUR_ETCD_PASSWD>" | base64)
# 移除访客账户的所有权限
# curl -H "Authorization: Basic $AUTHSTR" -X PUT -d "{\"role\":\"guest\",\"revoke\":{\"kv\":{\"read\":[\"*\"],\"write\":[\"*\"]}}}" http://localhost:4001/v2/auth/roles/guest
{"role":"guest","permissions":{"kv":{"read":[],"write":[]}}}

验证:

# curl http://localhost:4001/v2/keys
{"message":"Insufficient credentials"}

将etcd用户配置添加到Kubernetes主节点的配置中,修改Kubernetes API服务器的配置文件,添加账户和密码信息。

5.2.1.2 Kubernetes主节点的基本认证

检查主节点的端点:

# curl https://K8S_MASTER_HOST_IP:SECURED_PORT --insecure
或
# curl http://K8S_MASTER_ELB_URL:80
{
  "paths": [
    "/api",
    "/api/v1",
    "/apis",
    "/apis/extensions",
    "/apis/extensions/v1beta1",
    "/healthz",
    "/healthz/ping",
    "/logs/",
    "/metrics",
    "/resetMetrics",
    "/swagger-ui/",
    "/swaggerapi/",
    "/ui/",
    "/version"
  ]
}

创建基本认证文件:

# cat /root/k8s-bafile
<APISERVER_BA_PASSWORD>,<APISERVER_BA_USERACCOUNT>,1

在配置文件中指定该文件:
- 对于 kubernetes-master 文件,在 kube-apiserver hyperkube apiserver 命令后追加 --basic-auth-file=/root/k8s-bafile
- 对于 apiserver 文件,将 --basic-auth-file=/root/k8s-bafile 添加到 KUBE_API_ARGS 变量中。

确保启动Kubernetes服务的用户有权限访问该文件,添加新标签后重启服务。节点通过不安全端口8080与API服务器通信,需配置主节点防火墙,只允许节点通过该端口。

5.2.2 使用用户授权

为Kubernetes主节点的API服务器守护进程添加不同用户权限,需设置三个标志:
- --authorization-mode=ABAC :ABAC是基于属性的访问控制,启用此模式可设置自定义用户权限。
- --token-auth-file=<FULL_PATH_OF_YOUR_TOKEN_FILE> :用于指定允许访问API的合格用户的文件。
- --authorization-policy-file=<FULL_PATH_OF_YOUR_POLICY_FILE> :用于为不同用户生成单独规则的策略文件。

示例配置如下:

# cat /etc/init.d/kubernetes-master
(above lines are ignored)
:
# Start daemon.
    echo $"Starting apiserver: "
    daemon $apiserver_prog \
    --service-cluster-ip-range=${CLUSTER_IP_RANGE} \
    --insecure-port=8080 \
    --secure-port=6443 \
    --authorization-mode=ABAC \
    --token-auth-file=/root/k8s-tokenfile \
    --authorization-policy-file=/root/k8s-policyfile \
    --address=0.0.0.0 \
    --etcd-servers=${ETCD_SERVERS} \
    --cluster-name=${CLUSTER_NAME} \
    > ${logfile}-apiserver.log 2>&1 &
:
(below lines are ignored)

# cat /etc/kubernetes/apiserver
(above lines are ignored)
:
KUBE_API_ARGS="--authorization-mode=ABAC --token-auth-file=/root/k8s-tokenfile --authorization-policy-file=/root/k8s-policyfile"

配置账户文件和策略文件:

# cat /root/k8s-tokenfile
k8s2016,admin,1
happy123,amy,2
# cat /root/k8s-policyfile
{"apiVersion": "abac.authorization.kubernetes.io/v1beta1", "kind": "Policy", "spec": {"user": "admin", "namespace": "*", "resource": "*", "apiGroup": "*"}}
{"apiVersion": "abac.authorization.kubernetes.io/v1beta1", "kind": "Policy", "spec": {"user": "amy", "namespace": "*", "resource": "*", "readonly": true}}

配置完成后,重启Kubernetes主节点的所有守护进程:

# 对于init.d服务管理
# service kubernetes-master restart
# 或单独重启并处理依赖关系
# systemctl stop kube-scheduler
# systemctl stop kube-controller-manager
# systemctl stop kube-apiserver
# systemctl start kube-apiserver
# systemctl start kube-controller-manager
# systemctl start kube-scheduler

通过以上步骤,可实现Kubernetes集群的高级管理,包括资源管理、WebUI使用、RESTful API调用以及认证与授权等功能。

6. 总结与关键要点回顾

6.1 资源管理总结

在Kubernetes集群中,资源管理至关重要。从节点容量管理来看,我们可以通过创建资源预留Pod的方式,为节点上的其他进程或未来使用保留资源。例如,通过创建 resource-reserver Pod并设置内存限制为200Mi,确保了节点有一定的资源余量。

在Pod层面,我们可以为每个容器指定资源的请求和限制。请求表示Pod运行所需的最小资源,而限制则是Pod可占用的最大资源。合理设置请求和限制,能够有效避免资源过度使用或不足的问题。例如,创建的nginx Pod,设置了CPU请求为250m、限制为500m,内存请求为32Mi、限制为64Mi,保证了Pod的稳定运行。

6.2 WebUI与RESTful API使用要点

WebUI为我们提供了直观的方式来查看Kubernetes集群的状态。通过下载发布二进制文件并启动相关的复制控制器和服务,我们可以轻松访问WebUI界面,了解Pod、复制控制器和服务等实例的信息。

RESTful API则为自动化管理提供了便利。我们可以使用 curl 命令或编写Python代码来进行CRUD操作。例如,使用JSON格式创建复制控制器,并通过POST请求提交到API服务器;使用GET请求查看资源信息;使用DELETE请求删除资源等。整个Kubernetes RESTful API由Swagger定义,方便我们查看详细描述。

6.3 认证与授权要点

认证和授权是保障Kubernetes集群安全的重要手段。在etcd和Kubernetes主节点上,我们可以通过基本认证机制来限制未授权的访问。例如,为etcd的root账户设置密码,启用认证并移除访客账户的权限;为Kubernetes主节点创建基本认证文件,并在配置文件中指定该文件。

用户授权方面,通过设置 --authorization-mode=ABAC --token-auth-file --authorization-policy-file 三个标志,我们可以为不同用户设置不同的权限。例如,创建了具有完全访问权限的admin用户和只读权限的amy用户,确保了不同用户对资源的合理访问。

7. 实际应用中的注意事项

7.1 资源管理注意事项

  • 资源评估 :在进行资源管理前,务必对应用的资源需求进行充分评估。不准确的资源评估可能导致资源浪费或应用运行不稳定。例如,如果对nginx Pod的资源需求评估过低,可能会导致Pod因资源不足而频繁重启。
  • QoS层级选择 :根据应用的特性选择合适的QoS层级。Guaranteed层级会始终为Pod保留资源,但可能会降低集群利用率;Burstable层级有一定的缓冲空间,但在资源紧张时可能会受到影响。例如,对于对资源稳定性要求较高的关键业务应用,可选择Guaranteed层级;对于一些非关键的测试应用,可选择Burstable层级。

7.2 WebUI与RESTful API使用注意事项

  • WebUI安全 :虽然WebUI提供了方便的查看功能,但要注意其安全性。确保Kubernetes主节点的防火墙配置正确,只允许授权的用户访问WebUI界面。
  • RESTful API安全 :在使用RESTful API时,要注意保护API服务器的安全。例如,使用HTTPS协议进行通信,避免明文传输敏感信息;对API的访问进行身份验证和授权,防止未授权的访问。

7.3 认证与授权注意事项

  • 文件权限 :在设置认证和授权时,要确保相关文件(如基本认证文件、令牌文件、策略文件等)的权限设置正确。只有授权的用户才能访问这些文件,否则可能会导致安全漏洞。
  • 配置更新 :在修改认证和授权配置后,要及时重启相关的守护进程,确保配置生效。同时,要注意重启过程中可能出现的依赖关系问题,避免服务中断。

8. 未来发展趋势与展望

8.1 资源管理的发展趋势

随着Kubernetes的不断发展,资源管理将更加智能化和自动化。未来可能会出现更高级的资源调度算法,能够根据应用的实时资源需求动态调整资源分配。例如,基于机器学习的资源预测模型,能够提前预测应用的资源需求,从而实现更精准的资源调度。

8.2 WebUI与RESTful API的发展趋势

WebUI界面将更加丰富和直观,提供更多的可视化功能和交互方式。同时,RESTful API将更加完善,支持更多的操作和功能。例如,未来可能会提供更细粒度的资源管理API,方便用户进行更精确的资源控制。

8.3 认证与授权的发展趋势

认证和授权机制将更加灵活和多样化。未来可能会支持更多的认证方式,如OAuth、OpenID Connect等。同时,授权策略将更加复杂和精细,能够根据用户的角色、行为等多维度信息进行授权。例如,根据用户的地理位置、访问时间等因素来动态调整授权权限。

9. 案例分析:某企业Kubernetes集群的高级管理实践

9.1 案例背景

某企业采用Kubernetes集群来管理其微服务架构的应用。随着业务的发展,集群规模不断扩大,资源管理、安全认证等问题日益突出。为了提高集群的性能和安全性,企业决定实施高级管理策略。

9.2 实施步骤

  • 资源管理 :企业对应用的资源需求进行了详细评估,为每个应用设置了合理的资源请求和限制。同时,在节点上创建了资源预留Pod,确保了节点有足够的资源余量。通过这种方式,有效避免了资源过度使用和不足的问题,提高了集群的利用率。
  • WebUI与RESTful API使用 :企业启用了WebUI界面,方便运维人员直观地查看集群状态。同时,开发了自动化脚本,使用RESTful API进行资源的创建、更新和删除操作,提高了管理效率。
  • 认证与授权 :企业为etcd和Kubernetes主节点设置了基本认证机制,限制了未授权的访问。同时,为不同的用户角色设置了不同的权限,确保了数据的安全性和合规性。

9.3 实施效果

通过实施高级管理策略,企业的Kubernetes集群性能得到了显著提升。资源利用率提高了30%,应用的响应时间缩短了20%。同时,安全认证机制的实施有效防止了未授权的访问,保障了企业数据的安全。

10. 总结与建议

10.1 总结

通过本文的介绍,我们了解了Kubernetes高级集群管理的各个方面,包括资源管理、WebUI使用、RESTful API调用以及认证与授权等。这些管理策略能够帮助我们提高集群的性能、安全性和管理效率。

10.2 建议

  • 持续学习 :Kubernetes技术不断发展,建议持续关注官方文档和社区动态,学习最新的管理策略和技术。
  • 实践验证 :在实际应用中,要通过实践来验证所学的知识。可以搭建测试环境,进行各种管理策略的实验,确保在生产环境中能够稳定运行。
  • 团队协作 :Kubernetes集群管理涉及多个方面的知识,建议团队成员之间加强协作,共同解决遇到的问题。

在实际应用中,我们可以根据具体的需求和场景,灵活运用这些管理策略,打造高效、安全的Kubernetes集群。

以下是一个mermaid流程图,展示了Kubernetes集群高级管理的整体流程:

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(节点容量管理):::process
    B --> B2(Pod资源管理):::process
    A --> C(WebUI使用):::process
    C --> C1(启动WebUI):::process
    C --> C2(查看集群状态):::process
    A --> D(RESTful API调用):::process
    D --> D1(创建资源):::process
    D --> D2(查看资源):::process
    D --> D3(更新资源):::process
    D --> D4(删除资源):::process
    A --> E(认证与授权):::process
    E --> E1(etcd认证):::process
    E --> E2(Kubernetes主节点认证):::process
    E --> E3(用户授权):::process
    B --> F([结束]):::startend
    C --> F
    D --> F
    E --> F

通过这个流程图,我们可以清晰地看到Kubernetes集群高级管理的主要流程和各个环节之间的关系。

基于可靠性评估序贯蒙特卡洛模拟法的配电网可靠性评估研究(Matlab代码实现)内容概要:本文围绕“基于可靠性评估序贯蒙特卡洛模拟法的配电网可靠性评估研究”,介绍了利用Matlab代码实现配电网可靠性的仿真分析方法。重点采用序贯蒙特卡洛模拟法对配电网进行长时间段的状态抽样与统计,通过模拟系统元件的故障与修复过程,评估配电网的关键可靠性指标,如系统停电频率、停电持续时间、负荷点可靠性等。该方法能够有效处理复杂网络结构与设备时序特性,提升评估精度,适用于含分布式电源、电动汽车等新型负荷接入的现代配电网。文中提供了完整的Matlab实现代码与案例分析,便于复现和扩展应用。; 适合人群:具备电力系统基础知识和Matlab编程能力的高校研究生、科研人员及电力行业技术人员,尤其适合从事配电网规划、运行与可靠性分析相关工作的人员; 使用场景及目标:①掌握序贯蒙特卡洛模拟法在电力系统可靠性评估中的基本原理与实现流程;②学习如何通过Matlab构建配电网仿真模型并进行状态转移模拟;③应用于含新能源接入的复杂配电网可靠性定量评估与优化设计; 阅读建议:建议结合文中提供的Matlab代码逐段调试运行,理解状态抽样、故障判断、修复逻辑及指标统计的具体实现方式,同时可扩展至不同网络结构或加入更多不确定性因素进行深化研究。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值