docker06(docker的网络模式及构建)

docker06(docker的网络模式及其构建)

一.引子

docker的使用是非常便捷的,但是其网络一直是弱势。本章,笔者将带大家一起去了解并学习docker的网络模式和docker向外通信的实验搭建。

二.docker网络模式基本概念

(一).namespace

容器之间网络环境和系统网络环境相互交错,导致隔离性极差,而namespace可以将容器的网络环境隔离开来,这样隔离性的问题解决了,稳定性和安全性也就极大地提升了。
namespace 的概念。其目的是将某个特定的全局系统资源(global system resource)通过抽象方法使得namespace 中的进程看起来拥有它们自己的隔离的全局系统资源实例,而namespace不仅仅只是隔离网络环境那么简单。以后有时间我们会详细介绍namespace的功能。

(二).docker网络模式

1.birdge:bridge模式下容器没有一个公有ip,只有宿主机可以直接访问,外部主机是不可见的,但容器通过宿主机的NAT规则后可以访问外网。
2.host:host模式可以让容器共享宿主机网络栈,这样的好处是外部主机与容器直接通信,但是容器的网络缺少隔离性
3.none:网络环境为 none,即不为 Docker Container 任何的网络环境。一旦 Docker Container 采用了none网络模式,那么容器内部就只能使用 loopback 网络设备,不会再有其他的网络资源。
4.container:处于这个模式下的 Docker 容器会共享一个网络栈,这样两个容器之间可以使用localhost高效快速通信。

(三)docker 容器修改常用命令

–dns 用于指定启动的容器的 DNS
–net 用于指定容器的网络通讯方式,有以下四个值
bridge:Docker 默认方式,网桥模式
none:容器没有网络栈
container:使用其它容器的网络栈,Docker容器会加入其它容器的 network namespace --network container:(ContainerName)
host:表示容器使用 Host 的网络,没有自己独立的网络栈。容器可以完全访问 Host 的网络,不安全 --network host
-b, --bridge=”” 指定 Docker 使用的网桥设备,默认情况下 Docker 会自动创建和使用 docker0 网桥设备,通过此参数可以使用已经存在的设备
–bip 指定 Docker0 的 IP 和掩码,使用标准的 CIDR 形式,如 10.10.10.10/24

-p / P 选项的使用格式
> -p :将制定的容器端口映射至主机所有地址的一个动态端口
> -p ::映射至指定的主机端口
> -p :::映射至指定的主机的 IP 的动态端口
> -p :::映射至指定的主机 IP 的主机端口
> -P(大):暴露所需要的所有端口

docker port ContainerName 可以查看容器当前的映射关系

三.docker网络模式实验详解

(一).查看容器网络模式

[root@localhost ~]# docker network ls

NETWORK ID          NAME                DRIVER              SCOPE
41fa5f4f66ca        bridge              bridge              local
ab49d5db7bb1        host                host                local
2df9c496f37d        none                null                local

[root@localhost ~]# ip addr

4: docker0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default 
    link/ether 02:42:fb:83:53:51 brd ff:ff:ff:ff:ff:ff
    inet 172.17.0.1/16 brd 172.17.255.255 scope global docker0
       valid_lft forever preferred_lft forever
    inet6 fe80::42:fbff:fe83:5351/64 scope link 
       valid_lft forever preferred_lft forever

(二)docker的四种网络模式

1.bridge:bridge模式下容器没有一个公有ip,只有宿主机可以直接访问,外部主机是不可见的,但容器通过宿主机的NAT规则后可以访问外网。
在这里插入图片描述

Bridge 桥接模式的实现步骤主要如下:

  • Docker Daemon 利用 veth pair 技术,在宿主机上创建两个虚拟网络接口设备,假设为veth0 和veth1。而veth pair 技术的特性可以保证无论哪一个 veth 接收到网络报文,都会将报文传输给另一方。
  • Docker Daemon 将 veth0 附加到 Docker Daemon 创建的 docker0
    网桥上。保证宿主机的网络报文可以发往 veth0;
  • Docker Daemon 将 veth1 添加到 Docker Container 所属的 namespace 下,并被改名为eth0。如此一来,保证宿主机的网络报文若发往 veth0,则立即会被 eth0 接收,实现宿主机到Docker Container网络的联通性;同时,也保证 Docker Container 单独使用 eth0,实现容器网络环境的隔离性

Bridge桥接模式的缺陷:

  • 最明显的是,该模式下 Docker Container 不具有一个公有 IP,即和宿主机的 eth0
    不处于同一个网段。导致的结果是宿主机以外的世界不能直接和容器进行通信。
  • 虽然 NAT 模式经过中间处理实现了这一点,但是 NAT
    模式仍然存在问题与不便,如:容器均需要在宿主机上竞争端口,容器内部服务的访问者需要使用服务发现获知服务的外部端口等。
  • 另外 NAT 模式由于是在三层网络上的实现手段,故肯定会影响网络的传输效率。

实验:
(1).创建并进入vm2容器内部,发现eth0网卡

[root@localhost ~]# docker exec -it vm2 /bin/bash
[root@f7dfee9bee4a /]# ip addr
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default 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
7: eth0@if8: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default 
    link/ether 02:42:ac:11:00:02 brd ff:ff:ff:ff:ff:ff link-netnsid 0
    inet 172.17.0.2/16 brd 172.17.255.255 scope global eth0
       valid_lft forever preferred_lft forever

(2).docker0上连接了veth网卡,并且真实机多了一张网卡

[root@localhost ~]# brctl show
bridge name     bridge id               STP enabled     interfaces
docker0         8000.0242fb835351       no              veth6f30ba5
[root@localhost ~]# ip addr
8: veth6f30ba5@if7: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue master docker0 state UP group default 
    link/ether 72:60:78:b6:bf:b2 brd ff:ff:ff:ff:ff:ff link-netnsid 0
    inet6 fe80::7060:78ff:feb6:bfb2/64 scope link 
       valid_lft forever preferred_lft forever

#veth设备是成双成对出现的,一端是容器内部命名为eth0,一端是加入到网桥并命名的veth(通常命名为veth),它们组成了一个数据传输通道,一端进一端出,veth设备连接了两个网络设备并实现了数据通信**

2.host:

  • host网络模式需要在容器创建时指定–network=host
  • host 模式是 bridge 桥接模式很好的补充。采用 host 模式的 Docker Container,可以直接使用宿主机的 IP
  • 地址与外界进行通信,若宿主机的 eth0 是一个公有 IP,那么容器也拥有这个公有IP。同时容器内服务的端口也可以使用宿主机的端口,无需额外进行 NAT 转换。host模式可以让容器共享宿主机网络栈,这样的好处是外部主机与容器直接通信,但是容器的网络缺少隔离性。
    在这里插入图片描述
    Host 网络模式的缺陷:
  • 最明显的是 Docker Container 网络环境隔离性的弱化。即容器不再拥有隔离、独立的网络栈。
  • 另外,使用 host 模式的 Docker Container
    虽然可以让容器内部的服务和传统情况无差别、无改造的使用,但是由于网络隔离性的弱化,该容器会与宿主机共享竞争网络栈的使用;
    另外,容器内部将不再拥有所有的端口资源,原因是部分端口资源已经被宿主机本身的服务占用,还有部分端口已经用以 bridge
    网络模式容器的端口映射。

实验:容器vm4中的ip和宿主机(docker0)中的ip一样

[root@localhost ~]# docker run -d -it --name  vm4 --network=host centos
884e7e5de2e705de5ea035f713c6bcc5f2baf459890dd7d2226b7e310d8bd6fc
[root@localhost ~]# docker exec -it vm4 /bin/bash
[root@localhost /]# ip addr     

4: docker0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default 
    link/ether 02:42:fb:83:53:51 brd ff:ff:ff:ff:ff:ff
    inet 172.17.0.1/16 brd 172.17.255.255 scope global docker0
       valid_lft forever preferred_lft forever
    inet6 fe80::42:fbff:fe83:5351/64 scope link 
       valid_lft forever preferred_lft forever


3.docker的none模式

  • none模式是指禁用网络功能,只有lo接口,在容器创建时使用–network=none指定。
  • 网络环境为 none,即不为 Docker Container 任何的网络环境。一旦 Docker Container采用了none网络模式,那么容器内部就只能使用 loopback 网络设备,不会再有其他的网络资源。可以说 none 模式为 DockeContainer 做了极少的网络设定,但是俗话说得好“少即是多”,在没有网络配置的情况下,作为 Docker开发者,才能在这基础做其他无限多可能的网络定制开发。这也恰巧体现了 Docker 设计理念的开放。

实验:创建一个none模式容器,发现只有一个lo接口

[root@localhost ~]# docker run  -it --name  vm5 --network=none centosr
[root@f44790b17e90 /]# ip addr 
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default 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

4.container模式:

  • Container 网络模式是 Docker
    中一种较为特别的网络的模式。在容器创建时使用–network=container:vm1指定。(vm1指定的是运行的容器名)
  • 处于这个模式下的 Docker 容器会共享一个网络栈,这样两个容器之间可以使用localhost高效快速通信。
    在这里插入图片描述
    缺陷:它并没有改善容器与宿主机以外世界通信的情况(和桥接模式一样,不能连接宿主机以外的其他设备)。

实验:创建一个container网络模式的容器vm6并查看ip,由于vm4使用的是vm7的网络,所以其查看的网络结果和vm4的相同

4: docker0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default 
    link/ether 02:42:fb:83:53:51 brd ff:ff:ff:ff:ff:ff
    inet 172.17.0.1/16 brd 172.17.255.255 scope global docker0
       valid_lft forever preferred_lft forever
    inet6 fe80::42:fbff:fe83:5351/64 scope link 
       valid_lft forever preferred_lft forever
8: veth6f30ba5@if7: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue master docker0 state UP group default 
    link/ether 72:60:78:b6:bf:b2 brd ff:ff:ff:ff:ff:ff link-netnsid 0
    inet6 fe80::7060:78ff:feb6:bfb2/64 scope link 
       valid_lft forever preferred_lft forever

(三)docker的网络连接

1 .–link :容器与容器之间的网络连接
docker run --link可以用来链接2个容器,使得源容器(被链接的容器)和接收容器(主动去链接的容器)之间可以互相通信,并且接收容器可以获取源容器的一些数据,如源容器的环境变量。
实验:

#创建容器vm8连接vm1并设置vm1别名为db1
[root@localhost bin]# docker run -it --name vm8 --link vm1:db1 centos
#vm8可以连接vm1及db1
[root@275c9f579235 /]# ping vm1
PING db1 (172.17.0.2) 56(84) bytes of data.
64 bytes from db1 (172.17.0.2): icmp_seq=1 ttl=64 time=0.602 ms
64 bytes from db1 (172.17.0.2): icmp_seq=2 ttl=64 time=0.134 ms
64 bytes from db1 (172.17.0.2): icmp_seq=3 ttl=64 time=0.126 ms
[root@275c9f579235 /]# ping db1
PING db1 (172.17.0.2) 56(84) bytes of data.
64 bytes from db1 (172.17.0.2): icmp_seq=1 ttl=64 time=0.132 ms
64 bytes from db1 (172.17.0.2): icmp_seq=2 ttl=64 time=0.111 ms
64 bytes from db1 (172.17.0.2): icmp_seq=3 ttl=64 time=0.117 ms
#vm8与vm1有不同的IP
[root@localhost ~]# docker exec -it vm1 /bin/bash
[root@ebb56b583bc9 /]# ip a
5: eth0@if6: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default 
    link/ether 02:42:ac:11:00:02 brd ff:ff:ff:ff:ff:ff link-netnsid 0
    inet 172.17.0.2/16 brd 172.17.255.255 scope global eth0
       valid_lft forever preferred_lft forever
[root@275c9f579235 /]# ip a
9: eth0@if10: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default 
    link/ether 02:42:ac:11:00:04 brd ff:ff:ff:ff:ff:ff link-netnsid 0
    inet 172.17.0.4/16 brd 172.17.255.255 scope global eth0
       valid_lft forever preferred_lft forever
#查看etc/hosts文件
[root@275c9f579235 /]# cat /etc/hosts
127.0.0.1       localhost
::1     localhost ip6-localhost ip6-loopback
fe00::0 ip6-localnet
ff00::0 ip6-mcastprefix
ff02::1 ip6-allnodes
ff02::2 ip6-allrouters
172.17.0.2      db1 ebb56b583bc9 vm1
172.17.0.4      275c9f579235

2.高级网络配置:网桥
自定义网络模式中,docker提供了三种自定义网络驱动:brdge,overlay,macvlan,bridge驱动类似默认的bridge网络模式,但增加了一些新的功能,overlay和macvlan是用于创建跨主机网络
建议使用自定义的网络来控制哪些容器可以相互通信,还可以自动DNS解析容器名称到IP地址

实验:(将所有容器删除:docker rm -f $(docker pa -a -q))

(1).birdge自定义网络:自定义网桥中会自己分配ip地址和网关地址(可以使用自定义网桥来控制哪些容器可以相互通信)

#创建自定义网桥
[root@localhost ~]# docker network create --driver bridge my_net1
cccd284cdc6b58626e3f4f1f21e351b47b11e8e5e6fb5b99950b39ca94aa73d1
[root@localhost ~]# docker network ls
NETWORK ID          NAME                DRIVER              SCOPE
2fb232dda51e        bridge              bridge              local
ab49d5db7bb1        host                host                local
cccd284cdc6b        my_net1             bridge              local
2df9c496f37d        none                null                local
#查看IP及自定义网桥IP
[root@localhost ~]# ip a
4: docker0: <NO-CARRIER,BROADCAST,MULTICAST,UP> mtu 1500 qdisc noqueue state DOWN group default 
    link/ether 02:42:e4:1e:a2:4b brd ff:ff:ff:ff:ff:ff
    inet 172.17.0.1/16 brd 172.17.255.255 scope global docker0
       valid_lft forever preferred_lft forever
    inet6 fe80::42:e4ff:fe1e:a24b/64 scope link 
       valid_lft forever preferred_lft forever
[root@localhost ~]# docker network inspect my_net1

            "Options": {},
            "Config": [
                {
                    "Subnet": "172.18.0.0/16",
                    "Gateway": "172.18.0.1"
                }
       
#创建vm1和vm2容器并测试他们之间的相互通信
[root@localhost ~]# docker run --name vm1 -it --network=my_net1 centos
[root@bd0878a73cf8 /]# ping vm1
PING vm1 (172.18.0.2) 56(84) bytes of data.
64 bytes from bd0878a73cf8 (172.18.0.2): icmp_seq=1 ttl=64 time=0.084 ms
64 bytes from bd0878a73cf8 (172.18.0.2): icmp_seq=2 ttl=64 time=0.062 ms
[root@localhost bin]# docker run --name vm2 -it --network=my_net1 centos
[root@de769084f578 /]# ping vm1
PING vm1 (172.18.0.2) 56(84) bytes of data.
64 bytes from vm1.my_net1 (172.18.0.2): icmp_seq=1 ttl=64 time=0.817 ms
64 bytes from vm1.my_net1 (172.18.0.2): icmp_seq=2 ttl=64 time=0.103 ms

注:在创建容器时,如果器在同一网桥内可以相互通信,可以创建私有网桥来进行容器管理

(2).bridge自定义网络–网段
还可以自己定义网段:在创建时指定参数:–subnet 、–gateway
创建两个容器,并桥接到不同的网桥上(vm1连接的网桥是my_net1),彼此是不通信的。
使用–ip参数可以指定容器ip地址,但必须是在自定义网桥上,默认的bridge模式不支持,同一网桥上的容器是可以互通的。
实验

#创建特定网段
[root@localhost ~]# docker network create --subnet=172.21.8.0/24  my_net3
43478a85395392e4903555a08391d0b6d802ff4cb7e99a3014dea2a860bddce2
[root@localhost ~]# docker network ls
NETWORK ID          NAME                DRIVER              SCOPE
2fb232dda51e        bridge              bridge              local
ab49d5db7bb1        host                host                local
cccd284cdc6b        my_net1             bridge              local
43478a853953        my_net3             bridge              local
2df9c496f37d        none                null                local
#创建vm3并查看其IP
[root@localhost ~]# docker run --name vm3 -it --network=my_net3 centos
[root@ba219d81870b /]# ip a
17: eth0@if18: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default 
    link/ether 02:42:ac:15:08:02 brd ff:ff:ff:ff:ff:ff link-netnsid 0
    inet 172.21.8.2/24 brd 172.21.8.255 scope global eth0
       valid_lft forever preferred_lft forever
#检测其网络联通性:无法连接vm1
[root@ba219d81870b /]# ping vm3
PING vm3 (172.21.8.2) 56(84) bytes of data.
64 bytes from ba219d81870b (172.21.8.2): icmp_seq=1 ttl=64 time=0.073 ms
64 bytes from ba219d81870b (172.21.8.2): icmp_seq=2 ttl=64 time=0.076 ms
[root@ba219d81870b /]# ping vm1
ping: vm1: Name or service not known

(3).实现不同网桥之间的通信

docker在设计上就是要隔离不同的network的
dokcer作为一个超级厉害的容器,怎么能容忍不同网桥间无法进行通信,它当然有其自己的方法。
前提:
现在使用的容器vm1使用的网桥时my_net1,容器vm3使用的网桥是my_net3,默认是无法进行通讯的.
实验:
1.使用 docker network connect命令为vm1添加一块my_net3的网卡。

[root@localhost ~]# docker network connect my_net3 vm1
[root@localhost ~]# docker start vm1
[root@localhost ~]# docker attach vm1
[root@bd0878a73cf8 /]# ping vm3
PING vm3 (172.21.8.2) 56(84) bytes of data.
64 bytes from vm3.my_net3 (172.21.8.2): icmp_seq=1 ttl=64 time=0.261 ms
64 bytes from vm3.my_net3 (172.21.8.2): icmp_seq=2 ttl=64 time=0.116 ms
#vm1和vm3之间能够通信
1.docker的bridge自定义网络(自定义网络中的网桥)间可以随便添加对方的网卡
2.docker的bridge自定义网络与系统自带的网桥自己间:只能是系统自带的网桥对应的容器添加给自定义的网桥间,而反过来会报错
3.docker的系统自带的网桥之间时可以互相通信的,因为在同一个网络桥接上

3.docker与外网进行访问和连接

(1).容器如何实现访问外网(容器如通过iptables的SNAT实现的)
在这里插入图片描述

(2).外网如何访问容器
通过端口映射以及选项指定映射端口
外网访问容器用到了docker-proxy和iptables DNAT 宿主机访问本机容器使用的是iptables DNAT外部主机访问容器或容器之间的访问是docker-proxy实现
[root@localhost ~]# iptables -t nat -nL

1.查看防火墙规则
Chain POSTROUTING (policy ACCEPT)
target     prot opt source               destination         
MASQUERADE  all  --  172.21.8.0/24        0.0.0.0/0           
MASQUERADE  all  --  172.18.0.0/16        0.0.0.0/0           
MASQUERADE  all  --  172.17.0.0/16        0.0.0.0/0  
Chain DOCKER (2 references)
target     prot opt source               destination         
RETURN     all  --  0.0.0.0/0            0.0.0.0/0           
RETURN     all  --  0.0.0.0/0            0.0.0.0/0           
RETURN     all  --  0.0.0.0/0            0.0.0.0/0  
2.运行nginx容器并设置映射端口
docker run -d --name nginx -p 80:80 nginx
d49c1d7cb1649f9847908626754a302a173d0389138404e9665438c1315f9b85
3.查看容器端口
[root@localhost ~]# docker port nginx
80/tcp -> 0.0.0.0:80
[root@localhost ~]# netstat -antp |grep 80
tcp6       0      0 :::80                   :::*                    LISTEN      115609/docker-proxy 
4.查看防火墙规则
[root@localhost ~]# iptables -t nat -nL
Chain DOCKER (2 references)
target     prot opt source               destination         
RETURN     all  --  0.0.0.0/0            0.0.0.0/0           
RETURN     all  --  0.0.0.0/0            0.0.0.0/0           
RETURN     all  --  0.0.0.0/0            0.0.0.0/0           
DNAT       tcp  --  0.0.0.0/0            0.0.0.0/0            tcp dpt:80 to:172.17.0.2:80

5.本机访问容器(成功)
curl localhost
curl 172.17.0.2
6.外网访问容器
$ docker run -d -p 80:80 nginx
$ iptables -t nat -A  PREROUTING -m addrtype --dst-type LOCAL -j DOCKER
$ iptables -t nat -A DOCKER ! -i docker0 -p tcp -m tcp --dport 80 -j  DNAT --to-destination 172.17.0.2:80
#可以成功

(3)跨主机之间的docker网络连接
跨主机网络解决方案:docker原生的overlay和macvlan,第三方的flannel,weave,calico

  • 众多网络方案是如何与docker集成在一起的:libnetwork docker容器网络库;CNM(Container NetworkModel)这个模型对容器网络进行了抽象CNM分三类组件
    1.Sandbox:容器网络栈,包含容器接口、dns、路由表。(namespace)
    2.Endpoint:作用是将sandbox接入network (veth pair)
    3.Network:包含一组endpoint,同一network的endpoint可以通信。
    在这里插入图片描述

  • macvlan网络方案实现:
    Linux kernel提供的一种网卡虚拟化技术。
    无需Linux bridge,直接使用物理接口,性能极好。
    macvlan本身是linuxkernel的模块,本质上是一种网卡虚拟化技术。其功能是允许在同一个物理网卡上虚拟出多个网卡,通过不同的MAC地址在数据链路层进行网络数据的转发,一块网卡上配置多个MAC 地址(即多个 interface),每个interface可以配置自己的IP,Docker的macvlan网络实际上就是使用了Linux提供的macvlan驱动。

  • macvlan网络间的隔离和连通
    (1)macvlan网络在二层上是隔离的,所以不同macvlan网络的容器是不能通信的。
    (2)可以在三层上通过网关将macvlan网络连通起来。
    (3)docker本身不做任何限制,像传统vlan网络那样管理即可。

实验:将容器IP绑定到网卡IP上

$ cd /etc/sysconfig/network-scripts/
	
$ cp ifcfg-eth0 ifcfg-br0
	
$ vi ifcfg-eth0
	DEVICE=eth0
	HWADDR=00:0C:29:06:A2:35
 	TYPE=Ethernet
 	UUID=34b706cc-aa46-4be3-91fc-d1f48c301f23
 	ONBOOT=yes
 	BRIDGE=br0 #指定bro文件
 	NM_CONTROLLED=yes
 	BOOTPROTO=static
	
$ vi ifcfg-br0
 	DEVICE=br0
 	TYPE=Bridge
 	ONBOOT=yes
 	BOOTPROTO=static
 	IPADDR=192.168.216.131
 	NETMASK=255.255.255.0
 	GATEWAY=192.168.216.2
 	DN1=8.8.8.8

$ yum install -y git	
$ git clone https://github.com/jpetazzo/pipework	(测试工具)
$ cp pipework/pipework /usr/local/bin/
$ docker run -itd --net=none --name=ff centos-6-x86 bash 
$ pipework br0 ff 192.168.216.135/24  (给容器IP)
$ ping 192.168.216.135

以上便是docker的网络配置的基本介绍了,感谢大家阅读。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值