主頁 > 軟體設計 > ??蘇州程式大白決議Linux 中的虛擬網路介面??《??記得收藏??》

??蘇州程式大白決議Linux 中的虛擬網路介面??《??記得收藏??》

2021-10-17 09:44:11 軟體設計

??蘇州程式大白決議Linux 中的虛擬網路介面??《??記得收藏??》

  • 目錄
  • 🏳??🌈開講啦!!!!🏳??🌈蘇州程式大白🏳??🌈
  • 🌟博主介紹
  • 前言
  • tun/tap 虛擬網路介面
    • C 語言編程測驗 TUN 設備
    • TUN 與 TAP 的區別
  • veth
  • bridge
    • 虛擬機場景(橋接模式)
    • 跨 namespace 通信場景(容器網路,NAT 模式)
  • macvlan
  • ipvlan
  • vlan
  • vxlan/geneve
    • 比組播更高效的 vxlan 實作
  • 虛擬網路介面的速率
    • 網路性能實測
  • 🌟作者相關的文章、資源分享🌟

目錄

🏳??🌈開講啦!!!!🏳??🌈蘇州程式大白🏳??🌈

在這里插入圖片描述

🌟博主介紹

💂 個人主頁:蘇州程式大白

🤟作者介紹:中國DBA聯盟(ACDU)成員,CSDN全國各地程式猿(媛)聚集地管理員,目前從事工業自動化軟體開發作業,擅長C#、Java、機器視覺、底層演算法等語言,2019年成立柒月軟體作業室,

💬如果文章對你有幫助,歡迎關注、點贊、收藏(一鍵三連)和C#、Halcon、python+opencv、VUE、各大公司面試等一些訂閱專欄哦

🎗? 承接各種軟體開發專案

💅 有任何問題歡迎私信,看到會及時回復

👤 微信號:stbsl6,微信公眾號:蘇州程式大白

🎯 想加入技術交流群的可以加我好友,群里會分享學習資料

前言

在這里插入圖片描述
注意: 本文中使用 ip 命令創建或修改的任何網路配置,都是未持久化的,主機重啟即消失, ?

Linux 具有強大的虛擬網路能力,這也是 openstack 網路、docker 容器網路以及 kubernetes 網路等虛擬網路的基礎,

這里介紹 Linux 常用的虛擬網路介面型別:TUN/TAP、bridge、veth、ipvlan/macvlan、vlan 以及 vxlan/geneve,

tun/tap 虛擬網路介面

tun/tap 是作業系統內核中的虛擬網路設備,他們為用戶層程式提供資料的接收與傳輸,

普通的物理網路介面如 eth0,它的兩端分別是內核協議堆疊和外面的物理網路,

而對于 TUN/TAP 虛擬介面如 tun0,它的一端一定是連接的用戶層程式,另一端則視配置方式的不同而變化,可以直連內核協議堆疊,也可以是某個 bridge(后面會介紹), Linux 通過內核模塊 TUN 提供 tun/tap 功能,該模塊提供了一個設備介面 /dev/net/tun 供用戶層程式讀寫,用戶層程式通過 /dev/net/tun 讀寫主機內核協議堆疊的資料,

> modinfo tun
filename:       /lib/modules/5.13.6-1-default/kernel/drivers/net/tun.ko.xz
alias:          devname:net/tun
alias:          char-major-10-200
license:        GPL
author:         (C) 1999-2004 Max Krasnyansky <maxk@qualcomm.com>
description:    Universal TUN/TAP device driver
...

> ls /dev/net/tun
/dev/net/tun

一個 TUN 設備的示例圖如下: ?

             
+----------------------------------------------------------------------+
|                                                                      |
|  +--------------------+      +--------------------+                  |
|  | User Application A |      | User Application B +<-----+           |
|  +------------+-------+      +-------+------------+      |           |
|               | 1                    | 5                 |           |
|...............+......................+...................|...........|
|               ↓                      ↓                   |           |
|         +----------+           +----------+              |           |
|         | socket A |           | socket B |              |           |
|         +-------+--+           +--+-------+              |           |
|                 | 2               | 6                    |           |
|.................+.................+......................|...........|
|                 ↓                 ↓                      |           |
|             +------------------------+          +--------+-------+   |
|             | Network Protocol Stack |          |  /dev/net/tun  |   |
|             +--+-------------------+-+          +--------+-------+   |
|                | 7                 | 3                   ^           |
|................+...................+.....................|...........|
|                ↓                   ↓                     |           |
|        +----------------+    +----------------+        4 |           |
|        |      eth0      |    |      tun0      |          |           |
|        +-------+--------+    +-----+----------+          |           |
|    10.32.0.11  |                   |   192.168.3.11      |           |
|                | 8                 +---------------------+           |
|                |                                                     |
+----------------+-----------------------------------------------------+
                 ↓
         Physical Network

因為 TUN/TAP 設備的一端是內核協議堆疊,顯然流入 tun0 的資料包是先經過本地的路由規則匹配的,

路由匹配成功,資料包被發送到 tun0 后,tun0 發現另一端是通過 /dev/net/tun 連接到應用程式 B,就會將資料丟給應用程式 B,

應用程式對資料包進行處理后,可能會構造新的資料包,通過物理網卡發送出去,比如常見的 VPN 程式就是把原來的資料包封裝/加密一遍,再發送給 VPN 服務器,

C 語言編程測驗 TUN 設備

為了使用 tun/tap 設備,用戶層程式需要通過系統呼叫打開 /dev/net/tun 獲得一個讀寫該設備的檔案描述符(FD),并且呼叫 ioctl() 向內核注冊一個 TUN 或 TAP 型別的虛擬網卡(實體化一個 tun/tap 設備),其名稱可能是 tun0/tap0 等,

此后,用戶程式可以通過該 TUN/TAP 虛擬網卡與主機內核協議堆疊(或者其他網路設備)互動,當用戶層程式關閉后,其注冊的 TUN/TAP 虛擬網卡以及自動生成的路由表相關條目都會被內核釋放,

可以把用戶層程式看做是網路上另一臺主機,他們通過 tun/tap 虛擬網卡相連,

一個簡單的 C 程式示例如下,它每次收到資料后,都只單純地列印一下收到的位元組數:

#include <linux/if.h>
#include <linux/if_tun.h>

#include <sys/ioctl.h>

#include <fcntl.h>
#include <string.h>

#include <unistd.h>
#include<stdlib.h>
#include<stdio.h>

int tun_alloc(int flags)
{

    struct ifreq ifr;
    int fd, err;
    char *clonedev = "/dev/net/tun";

    // 打開 tun 檔案,獲得 fd
    if ((fd = open(clonedev, O_RDWR)) < 0) {
        return fd;
    }

    memset(&ifr, 0, sizeof(ifr));
    ifr.ifr_flags = flags;

    // 向內核注冊一個 TUN 網卡,并與前面拿到的 fd 關聯起來
    // 程式關閉時,注冊的 tun 網卡及自動生成的相關路由策略,會被自動釋放
    if ((err = ioctl(fd, TUNSETIFF, (void *) &ifr)) < 0) {
        close(fd);
        return err;
    }

    printf("Open tun/tap device: %s for reading...\n", ifr.ifr_name);

    return fd;
}

int main()
{

    int tun_fd, nread;
    char buffer[1500];

    /* Flags: IFF_TUN   - TUN device (no Ethernet headers)
     *        IFF_TAP   - TAP device
     *        IFF_NO_PI - Do not provide packet information
     */
    tun_fd = tun_alloc(IFF_TUN | IFF_NO_PI);

    if (tun_fd < 0) {
        perror("Allocating interface");
        exit(1);
    }

    while (1) {
        nread = read(tun_fd, buffer, sizeof(buffer));
        if (nread < 0) {
            perror("Reading from interface");
            close(tun_fd);
            exit(1);
        }

        printf("Read %d bytes from tun/tap device\n", nread);
    }
    return 0;
}

接下來開啟三個終端視窗來測驗上述程式,分別運行上面的 tun 程式、tcpdump 和 iproute2 指令,

首先通過編譯運行上述 c 程式,程式會阻塞住,等待資料到達:

# 編譯,請忽略部分 warning
> gcc mytun.c -o mytun

# 創建并監聽 tun 設備需要 root 權限
> sudo mytun 
Open tun/tap device: tun0 for reading...

現在使用 iproute2 查看下鏈路層設備:

# 能發現最后面有列出名為 tun0 的介面,但是狀態為 down
? ip addr ls
......
3: wlp4s0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default qlen 1000
    link/ether c0:3c:59:36:a4:16 brd ff:ff:ff:ff:ff:ff
    inet 192.168.31.228/24 brd 192.168.31.255 scope global dynamic noprefixroute wlp4s0
       valid_lft 41010sec preferred_lft 41010sec
    inet6 fe80::4ab0:130f:423b:5d37/64 scope link noprefixroute 
       valid_lft forever preferred_lft forever
7: tun0: <POINTOPOINT,MULTICAST,NOARP> mtu 1500 qdisc noop state DOWN group default qlen 500
    link/none 

# 為 tun0 設定 ip 地址,注意不要和其他介面在同一網段,會導致路由沖突
> sudo ip addr add 172.21.22.23/24 dev tun0
# 啟動 tun0 這個介面,這一步會自動向路由表中添加將 172.21.22.23/24 路由到 tun0 的策略
> sudo ip link set tun0 up
#確認上一步添加的路由策略是否存在
? ip route ls
default via 192.168.31.1 dev wlp4s0 proto dhcp metric 600 
172.17.0.0/16 dev docker0 proto kernel scope link src 172.17.0.1 linkdown 
172.21.22.0/24 dev tun0 proto kernel scope link src 172.21.22.23 
192.168.31.0/24 dev wlp4s0 proto kernel scope link src 192.168.31.228 metric 600 

# 此時再查看介面,發現 tun0 狀態為 unknown
> ip addr ls
......
8: tun0: <POINTOPOINT,MULTICAST,NOARP,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UNKNOWN group default qlen 500
    link/none 
    inet 172.21.22.23/24 scope global tun0
       valid_lft forever preferred_lft forever
    inet6 fe80::3d52:49b5:1cf3:38fd/64 scope link stable-privacy 
       valid_lft forever preferred_lft forever

# 使用 tcpdump 嘗試抓下 tun0 的資料,會阻塞在這里,等待資料到達
> tcpdump -i tun0

現在再啟動第三個視窗發點資料給 tun0,持續觀察前面 tcpdumpmytun 的日志:

# 直接 ping tun0 的地址,貌似有問題,資料沒進 mytun 程式,而且還有回應
? ping -c 4 172.21.22.23
PING 172.21.22.23 (172.21.22.23) 56(84) bytes of data.
64 bytes from 172.21.22.23: icmp_seq=1 ttl=64 time=0.167 ms
64 bytes from 172.21.22.23: icmp_seq=2 ttl=64 time=0.180 ms
64 bytes from 172.21.22.23: icmp_seq=3 ttl=64 time=0.126 ms
64 bytes from 172.21.22.23: icmp_seq=4 ttl=64 time=0.141 ms

--- 172.21.22.23 ping statistics ---
4 packets transmitted, 4 received, 0% packet loss, time 3060ms
rtt min/avg/max/mdev = 0.126/0.153/0.180/0.021 ms

# 但是 ping 該網段下的其他地址,流量就會被轉發給 mytun 程式,因為 mytun 啥資料也沒回,自然丟包率 100%
# tcpdump 和 mytun 都會列印出相關日志
? ping -c 4 172.21.22.26
PING 172.21.22.26 (172.21.22.26) 56(84) bytes of data.

--- 172.21.22.26 ping statistics ---
4 packets transmitted, 0 received, 100% packet loss, time 3055ms

下面給出 mytun 的輸出:

Read 84 bytes from tun/tap device
Read 84 bytes from tun/tap device
Read 84 bytes from tun/tap device
Read 84 bytes from tun/tap device

以及 tcpdump 的輸出:

00:22:03.622684 IP (tos 0x0, ttl 64, id 37341, offset 0, flags [DF], proto ICMP (1), length 84)
    172.21.22.23 > 172.21.22.26: ICMP echo request, id 11, seq 1, length 64
00:22:04.633394 IP (tos 0x0, ttl 64, id 37522, offset 0, flags [DF], proto ICMP (1), length 84)
    172.21.22.23 > 172.21.22.26: ICMP echo request, id 11, seq 2, length 64
00:22:05.653356 IP (tos 0x0, ttl 64, id 37637, offset 0, flags [DF], proto ICMP (1), length 84)
    172.21.22.23 > 172.21.22.26: ICMP echo request, id 11, seq 3, length 64
00:22:06.677341 IP (tos 0x0, ttl 64, id 37667, offset 0, flags [DF], proto ICMP (1), length 84)
    172.21.22.23 > 172.21.22.26: ICMP echo request, id 11, seq 4, length 64

TUN 與 TAP 的區別

TUN 和 TAP 的區別在于作業的網路層次不同,用戶程式通過 TUN 設備只能讀寫網路層的 IP 資料包,而 TAP 設備則支持讀寫鏈路層的資料包(通常是以太網資料包,帶有 Ethernet headers),

TUN 與 TAP 的關系,就類似于 socket 和 raw socket,

TUN/TAP 應用最多的場景是 VPN 代理,比如:

1、clash: 一個支持各種規則的隧道,也支持 TUN 模式,

2、tun2socks: 一個全域透明代理,和 VPN 的作業模式一樣,它通過創建虛擬網卡+修改路由表,在第三層網路層代理系統流量,

veth

veth 介面總是成對出現,一對 veth 介面就類似一根網線,從一端進來的資料會從另一端出去,

同時 veth 又是一個虛擬網路介面,因此它和 TUN/TAP 或者其他物理網路介面一樣,也都能配置 mac/ip 地址(但是并不是一定得配 mac/ip 地址),

其主要作用就是連接不同的網路,比如在容器網路中,用于將容器的 namespace 與 root namespace 的網橋 br0 相連, 容器網路中,容器側的 veth 自身設定了 ip/mac 地址并被重命名為 eth0,作為容器的網路介面使用,而主機側的 veth 則直接連接在 docker0/br0 上面,

使用 veth 實作容器網路,需要結合下一小節介紹的 bridge,在下一小節將給出容器網路結構圖,

bridge

Linux Bridge 是作業在鏈路層的網路交換機,由 Linux 內核模塊 brige 提供,它負責在所有連接到它的介面之間轉發鏈路層資料包,

添加到 Bridge 上的設備被設定為只接受二層資料幀并且轉發所有收到的資料包到 Bridge 中, 在 Bridge 中會進行一個類似物理交換機的查MAC埠映射表、轉發、更新MAC埠映射表這樣的處理邏輯,從而資料包可以被轉發到另一個介面/丟棄/廣播/發往上層協議堆疊,由此 Bridge 實作了資料轉發的功能,

如果使用 tcpdump 在 Bridge 介面上抓包,可以抓到網橋上所有介面進出的包,因為這些資料包都要通過網橋進行轉發,

與物理交換機不同的是,Bridge 本身可以設定 IP 地址,可以認為當使用 brctl addbr br0 新建一個 br0 網橋時,系統自動創建了一個同名的隱藏 br0 網路介面,br0 一旦設定 IP 地址,就意味著這個隱藏的 br0 介面可以作為路由介面設備,參與 IP 層的路由選擇(可以使用 route -n 查看最后一列 Iface),因此只有當 br0 設定 IP 地址時,Bridge 才有可能將資料包發往上層協議堆疊,

但被添加到 Bridge 上的網卡是不能配置 IP 地址的,他們作業在資料鏈路層,對路由系統不可見,

它常被用于在虛擬機、主機上不同的 namepsaces 之間轉發資料,

虛擬機場景(橋接模式)

以 qemu-kvm 為例,在虛擬機的橋接模式下,qemu-kvm 會為每個虛擬機創建一個 tun/tap 虛擬網卡并連接到 br0 網橋, 虛擬機內部的網路介面 eth0 是 qemu-kvm 軟體模擬的,實際上虛擬機內網路資料的收發都會被 qemu-kvm 轉換成對 /dev/net/tun 的讀寫,

以發送資料為例,整個流程如下:

  • 虛擬機發出去的資料包先到達 qemu-kvm 程式,

  • 資料被用戶層程式 qemu-kvm 寫入到 /dev/net/tun,到達 tap 設備,

  • tap 設備把資料傳送到 br0 網橋,

  • br0 把資料交給 eth0 發送出去,

整個流程跑完,資料包都不需要經過宿主機的協議堆疊,效率高,

+------------------------------------------------+-----------------------------------+-----------------------------------+
|                       Host                     |           VirtualMachine1         |           VirtualMachine2         |
|                                                |                                   |                                   |
|    +--------------------------------------+    |    +-------------------------+    |    +-------------------------+    |
|    |         Network Protocol Stack       |    |    |  Network Protocol Stack |    |    |  Network Protocol Stack |    |
|    +--------------------------------------+    |    +-------------------------+    |    +-------------------------+    |
||||
|.......................|........................|................|..................|.................|.................|
||||
|                  +--------+                    |            +-------+              |             +-------+             |
|                  | .3.101 |                    |            | .3.102|              |             | .3.103|             |
|     +------+     +--------+     +-------+      |            +-------+              |             +-------+             |
|     | eth0 |<--->|   br0  |<--->|tun/tap|      |            | eth0  |              |             | eth0  |             |
|     +------+     +--------+     +-------+      |            +-------+              |             +-------+             |
|         ↑             ↑             ↑      +--------+||
|         |             |             +------|qemu-kvm|-----------+                  |                 |                 |
|         |+--------+                              |                 |                 |
|         |         +-------+                    |                                   |                 |                 |
|         |         |tun/tap|                    |                                   |                 |                 |
|         |         +-------+                    |                                   |                 |                 |
|         ||            +--------+             |                 |                 |
|         |             +-------------------------------------|qemu-kvm|-------------|-----------------+                 |
|         |                                      |            +--------+             |                                   |
|         |                                      |                                   |                                   |
+---------|--------------------------------------+-----------------------------------+-----------------------------------+Physical Network  (192.168.3.0/24)

跨 namespace 通信場景(容器網路,NAT 模式)

由于容器運行在自己單獨的 network namespace 里面,所以和虛擬機一樣,它們也都有自己單獨的協議堆疊,

容器網路的結構和虛擬機差不多,但是它改用了 NAT 網路,并把 tun/tap 換成了 veth,導致 docker0 過來的資料,要先經過宿主機協議堆疊,然后才進入 veth 介面,

多了一層 NAT,以及多走了一層宿主機協議堆疊,都會導致性能下降,

示意圖如下:

+-----------------------------------------------+-----------------------------------+-----------------------------------+
|                      Host                     |           Container 1             |           Container 2             |
|                                               |                                   |                                   |
|   +---------------------------------------+   |    +-------------------------+    |    +-------------------------+    |
|   |       Network Protocol Stack          |   |    |  Network Protocol Stack |    |    |  Network Protocol Stack |    |
|   +----+-------------+--------------------+   |    +-----------+-------------+    |    +------------+------------+    |
|        ^             ^                        |                ^                  |                 ^                 |
|........|.............|........................|................|..................|.................|.................|
|        v             v  ↓                     |                v                  |                 v                 |
|   +----+----+  +-----+------+                 |          +-----+-------+          |           +-----+-------+         |
|   | .31.101 |  | 172.17.0.1 |      +------+   |          | 172.17.0.2  |          |           |  172.17.0.3 |         |
|   +---------+  +-------------<---->+ veth |   |          +-------------+          |           +-------------+         |
|   |  eth0   |  |   docker0  |      +--+---+   |          | eth0(veth)  |          |           | eth0(veth)  |         |
|   +----+----+  +-----+------+         ^       |          +-----+-------+          |           +-----+-------+         |
|        ^             ^                |       |                ^                  |                 ^                 |
|        |             |                +------------------------+                  |                 |                 |
|        |             v                        |                                   |                 |                 |
|        |          +--+---+                    |                                   |                 |                 |
|        |          | veth |                    |                                   |                 |                 |
|        |          +--+---+                    |                                   |                 |                 |
|        |             ^                        |                                   |                 |                 |
|        |             +------------------------------------------------------------------------------+                 |
|        |                                      |                                   |                                   |
|        |                                      |                                   |                                   |
+-----------------------------------------------+-----------------------------------+-----------------------------------+
         v
    Physical Network  (192.168.31.0/24)

每創建一個新容器,都會在容器的 namespace 里新建一個 veth 介面并命令為 eth0,同時在主 namespace 創建一個 veth,將容器的 eth0 與 docker0 連接,

可以在容器中通過 iproute2 查看到, eth0 的介面型別為 veth

? docker run -it --rm debian:buster bash
root@5facbe4ddc1e:/# ip --details addr ls
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 promiscuity 0 minmtu 0 maxmtu 0 numtxqueues 1 numrxqueues 1 gso_max_size 65536 gso_max_segs 65535 
    inet 127.0.0.1/8 scope host lo
       valid_lft forever preferred_lft forever
20: eth0@if21: <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 promiscuity 0 minmtu 68 maxmtu 65535 
    veth numtxqueues 1 numrxqueues 1 gso_max_size 65536 gso_max_segs 65535 
    inet 172.17.0.2/16 brd 172.17.255.255 scope global eth0
       valid_lft forever preferred_lft forever

同時在宿主機中能看到對應的 veth 設備是系結到了 docker0 網橋的:

? sudo brctl show
bridge name     bridge id               STP enabled     interfaces
docker0         8000.0242fce99ef5       no              vethea4171a

macvlan

目前 docker/podman 都支持創建基于 macvlan 的 Linux 容器網路,

注意 macvlan 和 WiFi 存在兼容問題,如果使用筆記本測驗,可能會遇到麻煩,
?
macvlan 是比較新的 Linux 特性,需要內核版本 >= 3.9,它被用于在主機的網路介面(父介面)上配置多個虛擬子介面,這些子介面都擁有各自獨立的 mac 地址,也可以配上 ip 地址進行通訊,

macvlan 下的虛擬機或者容器網路和主機在同一個網段中,共享同一個廣播域,macvlan 和 bridge 比較相似,但因為它省去了 bridge 的存在,所以配置和除錯起來比較簡單,而且效率也相對高,除此之外,macvlan 自身也完美支持 VLAN,

如果希望容器或者虛擬機放在主機相同的網路中,享受已經存在網路堆疊的各種優勢,可以考慮 macvlan,

ipvlan

linux 網路虛擬化: ipvlan

cilium 1.9 已經提供了基于 ipvlan 的網路(beta 特性),用于替換傳統的 veth+bridge 容器網路,詳見 IPVLAN based Networking (beta) - Cilium 1.9 Docs

ipvlan 和 macvlan 的功能很類似,也是用于在主機的網路介面(父介面)上配置出多個虛擬的子介面,但不同的是,ipvlan 的各子介面沒有獨立的 mac 地址,它們和主機的父介面共享 mac 地址,

因為 mac 地址共享,所以如果使用 DHCP,就要注意不能使用 mac 地址做 DHCP,需要額外配置唯一的 clientID,

如果你遇到以下的情況,請考慮使用 ipvlan:

  • 父介面對 mac 地址數目有限制,或者在 mac 地址過多的情況下會造成嚴重的性能損失,

  • 作業在 802.11(wireless)無線網路中(macvlan 無法和無線網路共同作業),

  • 希望搭建比較復雜的網路拓撲(不是簡單的二層網路和 VLAN),比如要和 BGP 網路一起作業,

  • 基于 ipvlan/macvlan 的容器網路,比 veth+bridge+iptables 的性能要更高,

vlan

vlan 即虛擬局域網,是一個鏈路層的廣播域隔離技術,可以用于切分局域網,解決廣播泛濫和安全性問題,被隔離的廣播域之間需要上升到第三層才能完成通訊,

常用的企業路由器如 ER-X 基本都可以設定 vlan,Linux 也直接支持了 vlan.

以太網資料包有一個專門的欄位提供給 vlan 使用,vlan 資料包會在該位置記錄它的 VLAN ID,交換機通過該 ID 來區分不同的 VLAN,只將該以太網報文廣播到該 ID 對應的 VLAN 中,

vxlan/geneve

rfc8926 - Geneve: Generic Network Virtualization Encapsulation rfc7348 - Virtual eXtensible Local Area Network (VXLAN)

Linux 上實作 vxlan 網路 ?

在介紹 vxlan 前,先說明下兩個名詞的含義: ?

  • underlay 網路:即物理網路,

  • overlay 網路:指在現有的物理網路之上構建的虛擬網路,其實就是一種隧道技術,將原生態的二層資料幀報文進行封裝后通過隧道進行傳輸,

vxlangeneve 都是 overlay 網路協議,它倆都是使用 UDP 包來封裝鏈路層的以太網幀,

vxlan 在 2014 年標準化,而 geneve 在 2020 年底才通過草案階段,目前尚未形成最終標準,但是目前 linux/cilium 都已經支持了 geneve,

geneve 相對 vxlan 最大的變化,是它更靈活——它的 header 長度是可變的,

目前所有 overlay 的跨主機容器網路方案,幾乎都是基于 vxlan 實作的(例外:cilium 也支持 geneve),

單機的容器網路時,不需要接觸到 vxlan,但是在學習跨主機容器網路方案如 flannel/calico/cilium 時,那 vxlan(overlay) 及 BGP(underlay) 就不可避免地要接觸了,

介紹下 vxlan 的資料包結構:
在這里插入圖片描述
? 在創建 vxlan 的 vtep 虛擬設備時,我們需要手動設定圖中的如下屬性:

  • VXLAN 目標埠:即接收方 vtep 使用的埠,這里 IANA 定義的埠是 4789,但是只有 calico 的vxlan 模式默認使用該埠 calico,而 cilium/flannel 的默認埠都是 Linux 默認的 8472,

  • VNID: 每個 VXLAN 網路介面都會被分配一個獨立的 VNID,

一個點對點的 vxlan 網路架構圖如下: ?

在這里插入圖片描述
可以看到每臺虛擬機 VM 都會被分配一個唯一的 VNID,然后兩臺物理機之間通過 VTEP 虛擬網路設備建立了 VXLAN 隧道,所有 VXLAN 網路中的虛擬機,都通過 VTEP 來互相通信,

有了上面這些知識,我們就可以通過如下命令在兩臺 Linux 機器間建立一個點對點的 VXLAN 隧道:

# 在主機 A 上創建 VTEP 設備 vxlan0
# 與另一個 vtep 介面 B(192.168.8.101)建立隧道
# 將 vxlan0 自身的 IP 地址設為 192.168.8.100
# 使用的 VXLAN 目標埠為 4789(IANA 標準)
ip link add vxlan0 type vxlan \
    id 42 \
    dstport 4789 \
    remote 192.168.8.101 \
    local 192.168.8.100 \
    dev enp0s8
# 為我們的 VXLAN 網路設定虛擬網段,vxlan0 就是默認網關
ip addr add 10.20.1.2/24 dev vxlan0
# 啟用我們的 vxlan0 設備,這會自動生成路由規則
ip link set vxlan0 up

# 現在在主機 B 上運行如下命令,同樣創建一個 VTEP 設備 vxlan0,remote 和 local 的 ip 與前面用的命令剛好相反,
# 注意 VNID 和 dstport 必須和前面完全一致
ip link add vxlan0 type vxlan \
    id 42 \
    dstport 4789 \
    remote 192.168.8.100 \
    local 192.168.8.101 \
    dev enp0s8
# 為我們的 VXLAN 網路設定虛擬網段,vxlan0 就是默認網關
ip addr add 10.20.1.3/24 dev vxlan0
ip link set vxlan0 up

# 到這里,兩臺機器就完成連接,可以通信了,可以在主機 B 上 ping 10.20.1.2 試試,應該能收到主機 A 的回應,
ping 10.20.1.2

點對點的 vxlan 隧道實際用處不大,如果集群中的每個節點都互相建 vxlan 隧道,代價太高了,

一種更好的方式,是使用 「組播模式」的 vxlan 隧道,這種模式下一個 vtep 可以一次與組內的所有 vtep 建立隧道, 示例命令如下(這里略過了如何設定組播地址 239.1.1.1 的資訊):

ip link add vxlan0 type vxlan \
    id 42 \
    dstport 4789 \
    group 239.1.1.1 \
    dev enp0s8 
ip addr add 10.20.1.2/24 dev vxlan0
ip link set vxlan0 up

可以看到,只需要簡單地把 local_ip/remote_ip 替換成一個組播地址就行,組播功能會將收到的資料包發送給組里的所有 vtep 介面,但是只有 VNID 能對上的 vtep 會處理該報文,其他 vtep 會直接丟棄資料,

接下來,為了能讓所有的虛擬機/容器,都通過 vtep 通信,我們再添加一個 bridge 網路,充當 vtep 與容器間的交換機,架構如下:
在這里插入圖片描述
使用 ip 命令創建網橋、網路名字空間、veth pairs 組成上圖中的容器網路:

# 創建 br0 并將 vxlan0 系結上去
ip link add br0 type bridge
ip link set vxlan0 master bridge
ip link set vxlan0 up
ip link set br0 up

# 模擬將容器加入到網橋中的操作
ip netns add container1

## 創建 veth pair,并把一端加到網橋上
ip link add veth0 type veth peer name veth1
ip link set dev veth0 master br0
ip link set dev veth0 up

## 配置容器內部的網路和 IP
ip link set dev veth1 netns container1
ip netns exec container1 ip link set lo up

ip netns exec container1 ip link set veth1 name eth0
ip netns exec container1 ip addr add 10.20.1.11/24 dev eth0
ip netns exec container1 ip link set eth0 up

然后在另一臺機器上做同樣的操作,并創建新容器,兩個容器就能通過 vxlan 通信啦~

比組播更高效的 vxlan 實作

組播最大的問題在于,因為它不知道資料的目的地,所以每個 vtep 都發了一份,如果每次發資料時,如果能夠精確到對應的 vtep,就能節約大量資源,

另一個問題是 ARP 查詢也會被組播,要知道 vxlan 本身就是個 overlay 網路,ARP 的成本也很高,

上述問題都可以通過一個中心化的注冊中心(如 etcd)來解決,所有容器、網路的注冊與變更,都寫入到這個注冊中心,然后由程式自動維護 vtep 之間的隧道、fdb 表及 ARP 表,

虛擬網路介面的速率

Loopback 和本章講到的其他虛擬網路介面一樣,都是一種軟體模擬的網路設備, 他們的速率是不是也像物理鏈路一樣,存在鏈路層(比如以太網)的帶寬限制呢?

比如目前很多老舊的網路設備,都是只支持到百兆以太網,這就決定了它的帶寬上限, 即使是較新的設備,目前基本也都只支持到千兆,也就是 1GbE 以太網標準,那本文提到的虛擬網路介面單純在本機內部通信,是否也存在這樣的制約呢?是否也只能跑到 1GbE?

使用 ethtool 檢查:

# docker 容器的 veth 介面速率
> ethtool vethe899841 | grep Speed
        Speed: 10000Mb/s

# 網橋看起來沒有固定的速率
> ethtool docker0 | grep Speed
        Speed: Unknown!

# tun0 設備的默認速率貌似是 10Mb/s ?
> ethtool tun0 | grep Speed
        Speed: 10Mb/s

# 此外 ethtool 無法檢查 lo 以及 wifi 的速率

網路性能實測

接下來實際測驗一下,先給出機器引數:

? cat /etc/os-release 
NAME="openSUSE Tumbleweed"
# VERSION="20210810"
...

? uname -a
Linux legion-book 5.13.8-1-default #1 SMP Thu Aug 5 08:56:22 UTC 2021 (967c6a8) x86_64 x86_64 x86_64 GNU/Linux


? lscpu
Architecture:                    x86_64
CPU(s):                          16
Model name:                      AMD Ryzen 7 5800H with Radeon Graphics
...

# 記憶體,單位 MB
? free -m
               total        used        free      shared  buff/cache   available
Mem:           27929        4482       17324         249        6122       22797
Swap:           2048           0        2048

使用 iperf3 測驗: ?

# 啟動服務端
iperf3 -s

-------------
# 新視窗啟動客戶端,通過 loopback 介面訪問 iperf3-server,大概 49Gb/s
? iperf3 -c 127.0.0.1
Connecting to host 127.0.0.1, port 5201
[  5] local 127.0.0.1 port 48656 connected to 127.0.0.1 port 5201
[ ID] Interval           Transfer     Bitrate         Retr  Cwnd
[  5]   0.00-1.00   sec  4.46 GBytes  38.3 Gbits/sec    0   1.62 MBytes       
[  5]   1.00-2.00   sec  4.61 GBytes  39.6 Gbits/sec    0   1.62 MBytes       
[  5]   2.00-3.00   sec  5.69 GBytes  48.9 Gbits/sec    0   1.62 MBytes       
[  5]   3.00-4.00   sec  6.11 GBytes  52.5 Gbits/sec    0   1.62 MBytes       
[  5]   4.00-5.00   sec  6.04 GBytes  51.9 Gbits/sec    0   1.62 MBytes       
[  5]   5.00-6.00   sec  6.05 GBytes  52.0 Gbits/sec    0   1.62 MBytes       
[  5]   6.00-7.00   sec  6.01 GBytes  51.6 Gbits/sec    0   1.62 MBytes       
[  5]   7.00-8.00   sec  6.05 GBytes  52.0 Gbits/sec    0   1.62 MBytes       
[  5]   8.00-9.00   sec  6.34 GBytes  54.5 Gbits/sec    0   1.62 MBytes       
[  5]   9.00-10.00  sec  5.91 GBytes  50.8 Gbits/sec    0   1.62 MBytes       
- - - - - - - - - - - - - - - - - - - - - - - - -
[ ID] Interval           Transfer     Bitrate         Retr
[  5]   0.00-10.00  sec  57.3 GBytes  49.2 Gbits/sec    0             sender
[  5]   0.00-10.00  sec  57.3 GBytes  49.2 Gbits/sec                  receiver

# 客戶端通過 wlp4s0 wifi 網卡(192.168.31.228)訪問 iperf3-server,實際還是走的本機,但是速度要比 loopback 快一點,可能是默認設定的問題
? iperf3 -c 192.168.31.228
Connecting to host 192.168.31.228, port 5201
[  5] local 192.168.31.228 port 43430 connected to 192.168.31.228 port 5201
[ ID] Interval           Transfer     Bitrate         Retr  Cwnd
[  5]   0.00-1.00   sec  5.12 GBytes  43.9 Gbits/sec    0   1.25 MBytes       
[  5]   1.00-2.00   sec  5.29 GBytes  45.5 Gbits/sec    0   1.25 MBytes       
[  5]   2.00-3.00   sec  5.92 GBytes  50.9 Gbits/sec    0   1.25 MBytes       
[  5]   3.00-4.00   sec  6.00 GBytes  51.5 Gbits/sec    0   1.25 MBytes       
[  5]   4.00-5.00   sec  5.98 GBytes  51.4 Gbits/sec    0   1.25 MBytes       
[  5]   5.00-6.00   sec  6.05 GBytes  52.0 Gbits/sec    0   1.25 MBytes       
[  5]   6.00-7.00   sec  6.16 GBytes  52.9 Gbits/sec    0   1.25 MBytes       
[  5]   7.00-8.00   sec  6.08 GBytes  52.2 Gbits/sec    0   1.25 MBytes       
[  5]   8.00-9.00   sec  6.00 GBytes  51.6 Gbits/sec    0   1.25 MBytes       
[  5]   9.00-10.00  sec  6.01 GBytes  51.6 Gbits/sec    0   1.25 MBytes       
- - - - - - - - - - - - - - - - - - - - - - - - -
[ ID] Interval           Transfer     Bitrate         Retr
[  5]   0.00-10.00  sec  58.6 GBytes  50.3 Gbits/sec    0             sender
[  5]   0.00-10.00  sec  58.6 GBytes  50.3 Gbits/sec                  receiver

# 從容器中訪問宿主機的 iperf3-server,速度幾乎沒區別
? docker run  -it --rm --name=iperf3-server networkstatic/iperf3 -c 192.168.31.228
Connecting to host 192.168.31.228, port 5201
[  5] local 172.17.0.2 port 43436 connected to 192.168.31.228 port 5201
[ ID] Interval           Transfer     Bitrate         Retr  Cwnd
[  5]   0.00-1.00   sec  4.49 GBytes  38.5 Gbits/sec    0    403 KBytes       
[  5]   1.00-2.00   sec  5.31 GBytes  45.6 Gbits/sec    0    544 KBytes       
[  5]   2.00-3.00   sec  6.14 GBytes  52.8 Gbits/sec    0    544 KBytes       
[  5]   3.00-4.00   sec  5.85 GBytes  50.3 Gbits/sec    0    544 KBytes       
[  5]   4.00-5.00   sec  6.14 GBytes  52.7 Gbits/sec    0    544 KBytes       
[  5]   5.00-6.00   sec  5.99 GBytes  51.5 Gbits/sec    0    544 KBytes       
[  5]   6.00-7.00   sec  5.86 GBytes  50.4 Gbits/sec    0    544 KBytes       
[  5]   7.00-8.00   sec  6.05 GBytes  52.0 Gbits/sec    0    544 KBytes       
[  5]   8.00-9.00   sec  5.99 GBytes  51.5 Gbits/sec    0    544 KBytes       
[  5]   9.00-10.00  sec  6.12 GBytes  52.5 Gbits/sec    0    544 KBytes       
- - - - - - - - - - - - - - - - - - - - - - - - -
[ ID] Interval           Transfer     Bitrate         Retr
[  5]   0.00-10.00  sec  58.0 GBytes  49.8 Gbits/sec    0             sender
[  5]   0.00-10.00  sec  58.0 GBytes  49.8 Gbits/sec                  receiver

把 iperf3-server 跑在容器里再測一遍:

# 在容器中啟動 iperf3-server,并映射到宿主機埠 6201
> docker run  -it --rm --name=iperf3-server -p 6201:5201 networkstatic/iperf3 -s
> docker inspect --format "{{ .NetworkSettings.IPAddress }}" iperf3-server
172.17.0.2
-----------------------------
# 測驗容器之間互訪的速度,ip 為 iperf3-server 的容器 ip,速度要慢一些,
# 畢竟過了 veth -> veth -> docker0 -> veth -> veth 五層虛擬網路介面
? docker run  -it --rm networkstatic/iperf3 -c 172.17.0.2
Connecting to host 172.17.0.2, port 5201
[  5] local 172.17.0.3 port 40776 connected to 172.17.0.2 port 5201
[ ID] Interval           Transfer     Bitrate         Retr  Cwnd
[  5]   0.00-1.00   sec  4.74 GBytes  40.7 Gbits/sec    0    600 KBytes       
[  5]   1.00-2.00   sec  4.48 GBytes  38.5 Gbits/sec    0    600 KBytes       
[  5]   2.00-3.00   sec  5.38 GBytes  46.2 Gbits/sec    0    600 KBytes       
[  5]   3.00-4.00   sec  5.39 GBytes  46.3 Gbits/sec    0    600 KBytes       
[  5]   4.00-5.00   sec  5.42 GBytes  46.6 Gbits/sec    0    600 KBytes       
[  5]   5.00-6.00   sec  5.39 GBytes  46.3 Gbits/sec    0    600 KBytes       
[  5]   6.00-7.00   sec  5.38 GBytes  46.2 Gbits/sec    0    635 KBytes       
[  5]   7.00-8.00   sec  5.37 GBytes  46.1 Gbits/sec    0    667 KBytes       
[  5]   8.00-9.00   sec  6.01 GBytes  51.7 Gbits/sec    0    735 KBytes       
[  5]   9.00-10.00  sec  5.74 GBytes  49.3 Gbits/sec    0    735 KBytes       
- - - - - - - - - - - - - - - - - - - - - - - - -
[ ID] Interval           Transfer     Bitrate         Retr
[  5]   0.00-10.00  sec  53.3 GBytes  45.8 Gbits/sec    0             sender
[  5]   0.00-10.00  sec  53.3 GBytes  45.8 Gbits/sec                  receiver

# 本機直接訪問容器 ip,走的是 docker0 網橋,居然還挺快
? iperf3 -c 172.17.0.2
Connecting to host 172.17.0.2, port 5201
[  5] local 172.17.0.1 port 56486 connected to 172.17.0.2 port 5201
[ ID] Interval           Transfer     Bitrate         Retr  Cwnd
[  5]   0.00-1.00   sec  5.01 GBytes  43.0 Gbits/sec    0    632 KBytes       
[  5]   1.00-2.00   sec  5.19 GBytes  44.6 Gbits/sec    0    703 KBytes       
[  5]   2.00-3.00   sec  6.46 GBytes  55.5 Gbits/sec    0    789 KBytes       
[  5]   3.00-4.00   sec  6.80 GBytes  58.4 Gbits/sec    0    789 KBytes       
[  5]   4.00-5.00   sec  6.82 GBytes  58.6 Gbits/sec    0    913 KBytes       
[  5]   5.00-6.00   sec  6.79 GBytes  58.3 Gbits/sec    0   1007 KBytes       
[  5]   6.00-7.00   sec  6.63 GBytes  56.9 Gbits/sec    0   1.04 MBytes       
[  5]   7.00-8.00   sec  6.75 GBytes  58.0 Gbits/sec    0   1.04 MBytes       
[  5]   8.00-9.00   sec  6.19 GBytes  53.2 Gbits/sec    0   1.04 MBytes       
[  5]   9.00-10.00  sec  6.55 GBytes  56.3 Gbits/sec    0   1.04 MBytes       
- - - - - - - - - - - - - - - - - - - - - - - - -
[ ID] Interval           Transfer     Bitrate         Retr
[  5]   0.00-10.00  sec  63.2 GBytes  54.3 Gbits/sec    0             sender
[  5]   0.00-10.00  sec  63.2 GBytes  54.3 Gbits/sec                  receiver

# 如果走本機 loopback 地址 + 容器埠映射,速度就慢了好多
# 或許是因為用 iptables 做埠映射導致的?
? iperf3 -c 127.0.0.1 -p 6201
Connecting to host 127.0.0.1, port 6201
[  5] local 127.0.0.1 port 48862 connected to 127.0.0.1 port 6201
[ ID] Interval           Transfer     Bitrate         Retr  Cwnd
[  5]   0.00-1.00   sec  2.71 GBytes  23.3 Gbits/sec    0   1.37 MBytes       
[  5]   1.00-2.00   sec  3.64 GBytes  31.3 Gbits/sec    0   1.37 MBytes       
[  5]   2.00-3.00   sec  4.08 GBytes  35.0 Gbits/sec    0   1.37 MBytes       
[  5]   3.00-4.00   sec  3.49 GBytes  30.0 Gbits/sec    0   1.37 MBytes       
[  5]   4.00-5.00   sec  5.50 GBytes  47.2 Gbits/sec    2   1.37 MBytes       
[  5]   5.00-6.00   sec  4.06 GBytes  34.9 Gbits/sec    0   1.37 MBytes       
[  5]   6.00-7.00   sec  4.12 GBytes  35.4 Gbits/sec    0   1.37 MBytes       
[  5]   7.00-8.00   sec  3.99 GBytes  34.3 Gbits/sec    0   1.37 MBytes       
[  5]   8.00-9.00   sec  3.49 GBytes  30.0 Gbits/sec    0   1.37 MBytes       
[  5]   9.00-10.00  sec  5.51 GBytes  47.3 Gbits/sec    0   1.37 MBytes       
- - - - - - - - - - - - - - - - - - - - - - - - -
[ ID] Interval           Transfer     Bitrate         Retr
[  5]   0.00-10.00  sec  40.6 GBytes  34.9 Gbits/sec    2             sender
[  5]   0.00-10.00  sec  40.6 GBytes  34.9 Gbits/sec                  receiver

# 可走 wlp4s0 + 容器埠映射,速度也不慢啊
? iperf3 -c 192.168.31.228 -p 6201
Connecting to host 192.168.31.228, port 6201
[  5] local 192.168.31.228 port 54582 connected to 192.168.31.228 port 6201
[ ID] Interval           Transfer     Bitrate         Retr  Cwnd
[  5]   0.00-1.00   sec  4.34 GBytes  37.3 Gbits/sec    0    795 KBytes       
[  5]   1.00-2.00   sec  4.78 GBytes  41.0 Gbits/sec    0    834 KBytes       
[  5]   2.00-3.00   sec  6.26 GBytes  53.7 Gbits/sec    0    834 KBytes       
[  5]   3.00-4.00   sec  6.30 GBytes  54.1 Gbits/sec    0    875 KBytes       
[  5]   4.00-5.00   sec  6.26 GBytes  53.8 Gbits/sec    0    875 KBytes       
[  5]   5.00-6.00   sec  5.75 GBytes  49.4 Gbits/sec    0    875 KBytes       
[  5]   6.00-7.00   sec  5.49 GBytes  47.2 Gbits/sec    0    966 KBytes       
[  5]   7.00-8.00   sec  5.72 GBytes  49.1 Gbits/sec    2    966 KBytes       
[  5]   8.00-9.00   sec  4.81 GBytes  41.3 Gbits/sec    2    966 KBytes       
[  5]   9.00-10.00  sec  5.98 GBytes  51.4 Gbits/sec    0    966 KBytes       
- - - - - - - - - - - - - - - - - - - - - - - - -
[ ID] Interval           Transfer     Bitrate         Retr
[  5]   0.00-10.00  sec  55.7 GBytes  47.8 Gbits/sec    4             sender
[  5]   0.00-10.00  sec  55.7 GBytes  47.8 Gbits/sec                  receiver

總的來看,loopback、bridge、veth 這幾個介面基本上是沒被限速的,veth 有查到上限為 10000Mb/s(10Gb/s) 感覺也是個假數字, 實際上測出來的資料基本在 35Gb/s 到 55Gb/s 之間,視情況浮動,

性能的變化和虛擬網路設備的鏈路和型別有關,或許和默認配置的區別也有關系,

另外 TUN 設備這里沒有測,ethtool tun0 查到的值是比較離譜的 10Mb/s,但是感覺不太可能這么慢,有時間可以再測一波看看,

🌟作者相關的文章、資源分享🌟

🌟讓天下沒有學不會的技術🌟

學習C#不再是難問題

🌳《C#入門到高級教程》🌳

有關C#實戰專案

👉C#RS232C通訊原始碼👈

👉C#委托資料傳輸👈

👉C# Modbus TCP 源代碼👈

👉C# 倉庫管理系統原始碼👈

👉C# 歐姆龍通訊Demo👈

👉C#+WPF+SQL目前在某市上線的車管所攝像系統👈

👉2021C#與Halcon視覺通用的框架👈

👉2021年視覺專案中利用C#完成三菱PLC與上位機的通訊👈

👉VP聯合開源深度學習編程(WPF)👈

?有關C#專案歡迎各位查看個人主頁?

🌟機器視覺、深度學習🌟

學習機器視覺、深度學習不再是難問題

🌌《Halcon入門到精通》🌌

🌌《深度學習資料與教程》🌌

有關機器視覺、深度學習實戰

👉2021年C#+HALCON視覺軟體👈

👉2021年C#+HALCON實作模板匹配👈

👉C#集成Halcon的深度學習軟體👈

👉C#集成Halcon的深度學習軟體,帶[MNIST例子]資料集👈

👉C#支持等比例縮放拖動的halcon WPF開源表單控制元件👈

👉2021年Labview聯合HALCON👈

👉2021年Labview聯合Visionpro👈

👉基于Halcon及VS的動車組制動閘片厚度自動識別模塊👈

?有關機器視覺、深度學習實戰歡迎各位查看個人主頁?

🌟Java、資料庫教程與專案🌟

學習Java、資料庫教程不再是難問題

🍏《JAVA入門到高級教程》🍏

🍏《資料庫入門到高級教程》🍏

有關Java、資料庫專案實戰

👉Java經典懷舊小霸王網頁游戲機原始碼增強版👈

👉js+css類似網頁版網易音樂原始碼👈

👉Java物業管理系統+小程式原始碼👈

👉JavaWeb家居電子商城👈

👉JAVA酒店客房預定管理系統的設計與實作SQLserver👈

👉JAVA圖書管理系統的研究與開發MYSQL👈

?有關Java、資料庫教程與專案實戰歡迎各位查看個人主頁?

🌟分享Python知識講解、分享🌟

學習Python不再是難問題

🥝《Python知識、專案專欄》🥝

🥝《Python 檢測抖音關注賬號是否封號程》🥝

🥝《手把手教你Python+Qt5安裝與使用》🥝

🥝《用一萬字給小白全面講解python編程基礎問答》🥝

🥝《Python 繪制Android CPU和記憶體增長曲線》🥝

有關Python專案實戰

👉Python基于Django圖書管理系統👈

👉Python管理系統👈

👉2021年9個常用的python爬蟲原始碼👈

👉python二維碼生成器👈

?有關Python教程與專案實戰歡迎各位查看個人主頁?

🌟分享各大公司面試題、面試流程🌟

面試成功不是難事

🍏《2021年金九銀十最新的VUE面試題??《??記得收藏??》》🍏

🍏《只要你認真看完一萬字??Linux作業系統基礎知識??分分鐘鐘都吊打面試官《??記得收藏??》》🍏

🍏《??用一萬字給小白全面講解python編程基礎問答??《😀記得收藏不然看著看著就不見了😀》》🍏

?有關各大公司面試題、面試流程歡迎各位查看個人主頁?

在這里插入圖片描述

??關注蘇州程式大白公眾號??


👇 👇👇

轉載請註明出處,本文鏈接:https://www.uj5u.com/ruanti/319873.html

標籤:其他

上一篇:【思維導圖】廠長爆肝計算機網路(第七版)(?建議收藏)

下一篇:僅需6道題輕松掌握Python例外捕獲 | Python技能樹征題

標籤雲
其他(157675) Python(38076) JavaScript(25376) Java(17977) C(15215) 區塊鏈(8255) C#(7972) AI(7469) 爪哇(7425) MySQL(7132) html(6777) 基礎類(6313) sql(6102) 熊猫(6058) PHP(5869) 数组(5741) R(5409) Linux(5327) 反应(5209) 腳本語言(PerlPython)(5129) 非技術區(4971) Android(4554) 数据框(4311) css(4259) 节点.js(4032) C語言(3288) json(3245) 列表(3129) 扑(3119) C++語言(3117) 安卓(2998) 打字稿(2995) VBA(2789) Java相關(2746) 疑難問題(2699) 细绳(2522) 單片機工控(2479) iOS(2429) ASP.NET(2402) MongoDB(2323) 麻木的(2285) 正则表达式(2254) 字典(2211) 循环(2198) 迅速(2185) 擅长(2169) 镖(2155) 功能(1967) .NET技术(1958) Web開發(1951) python-3.x(1918) HtmlCss(1915) 弹簧靴(1913) C++(1909) xml(1889) PostgreSQL(1872) .NETCore(1853) 谷歌表格(1846) Unity3D(1843) for循环(1842)

熱門瀏覽
  • 面試突擊第一季,第二季,第三季

    第一季必考 https://www.bilibili.com/video/BV1FE411y79Y?from=search&seid=15921726601957489746 第二季分布式 https://www.bilibili.com/video/BV13f4y127ee/?spm_id_fro ......

    uj5u.com 2020-09-10 05:35:24 more
  • 第三單元作業總結

    1.前言 這應該是本學期最后一次寫作業總結了吧。總體來說,對作業的節奏也差不多掌握了,作業做起來的效率也更高了。雖然和之前的作業一樣,作業中都要用到新的知識,但是相比之前,更加懂得了如何利用工具以及資料。雖然之間卡過殼,但總體而言,這幾次作業還算完成的比較好。 2.作業程序總結 相比前兩個單元,此單 ......

    uj5u.com 2020-09-10 05:35:41 more
  • 北航OO(2020)第四單元博客作業暨課程總結博客

    北航OO(2020)第四單元博客作業暨課程總結博客 本單元作業的架構設計 在本單元中,由于UML圖具有比較清晰的樹形結構,因此我對其中需要進行查詢操作的元素進行了包裝,在樹的父節點中存盤所有孩子的參考。考慮到性能問題,我采用了快取機制,一次查詢后盡可能快取已經遍歷過的資訊,以減少遍歷次數。 本單元我 ......

    uj5u.com 2020-09-10 05:35:48 more
  • BUAA_OO_第四單元

    一、UML決議器設計 ? 先看下題目:第四單元實作一個基于JDK 8帶有效性檢查的UML(Unified Modeling Language)類圖,順序圖,狀態圖分析器 MyUmlInteraction,實際上我們要建立一個有向圖模型,UML中的物件(元素)可能與同級元素連接,也可與低級元素相連形成 ......

    uj5u.com 2020-09-10 05:35:54 more
  • 6.1邏輯運算子

    邏輯運算子 1. && 短路與 運算式1 && 運算式2 01.運算式1為true并且運算式2也為true 整體回傳為true 02.運算式1為false,將不會執行運算式2 整體回傳為false 03.只要有一個運算式為false 整體回傳為false 2. || 短路或 運算式1 || 運算式2 ......

    uj5u.com 2020-09-10 05:35:56 more
  • BUAAOO 第四單元 & 課程總結

    1. 第四單元:StarUml檔案決議 本單元采用了圖模型決議UML。 UML檔案可以抽象為圖、子圖、邊的邏輯結構。 在實作中,圖的節點包括類、介面、屬性,子圖包括狀態圖、順序圖等。 采用了三次遍歷UML元素的方法建圖,第一遍遍歷建點,第二、三次遍歷設定屬性、連邊,實作圖物件的初始化。這里借鑒了一些 ......

    uj5u.com 2020-09-10 05:36:06 more
  • 談談我對C# 多型的理解

    面向物件三要素:封裝、繼承、多型。 封裝和繼承,這兩個比較好理解,但要理解多型的話,可就稍微有點難度了。今天,我們就來講講多型的理解。 我們應該經常會看到面試題目:請談談對多型的理解。 其實呢,多型非常簡單,就一句話:呼叫同一種方法產生了不同的結果。 具體實作方式有三種。 一、多載 多載很簡單。 p ......

    uj5u.com 2020-09-10 05:36:09 more
  • Python 資料驅動工具:DDT

    背景 python 的unittest 沒有自帶資料驅動功能。 所以如果使用unittest,同時又想使用資料驅動,那么就可以使用DDT來完成。 DDT是 “Data-Driven Tests”的縮寫。 資料:http://ddt.readthedocs.io/en/latest/ 使用方法 dd. ......

    uj5u.com 2020-09-10 05:36:13 more
  • Python里面的xlrd模塊詳解

    那我就一下面積個問題對xlrd模塊進行學習一下: 1.什么是xlrd模塊? 2.為什么使用xlrd模塊? 3.怎樣使用xlrd模塊? 1.什么是xlrd模塊? ?python操作excel主要用到xlrd和xlwt這兩個庫,即xlrd是讀excel,xlwt是寫excel的庫。 今天就先來說一下xl ......

    uj5u.com 2020-09-10 05:36:28 more
  • 當我們創建HashMap時,底層到底做了什么?

    jdk1.7中的底層實作程序(底層基于陣列+鏈表) 在我們new HashMap()時,底層創建了默認長度為16的一維陣列Entry[ ] table。當我們呼叫map.put(key1,value1)方法向HashMap里添加資料的時候: 首先,呼叫key1所在類的hashCode()計算key1 ......

    uj5u.com 2020-09-10 05:36:38 more
最新发布
  • 【中介者設計模式詳解】C/Java/JS/Go/Python/TS不同語言實作

    * 中介者模式是一種行為型設計模式,它可以用來減少類之間的直接依賴關系,
    * 將物件之間的通信封裝到一個中介者物件中,從而使得各個物件之間的關系更加松散。
    * 在中介者模式中,物件之間不再直接相互互動,而是通過中介者來中轉訊息。 ......

    uj5u.com 2023-04-20 08:20:47 more
  • 露天煤礦現場調研和交流案例分享

    他們集團的資訊化公司及研究院在一個礦區正在做智能礦山的統一平臺的 試點,專案投資大概1億,包括了礦山的各方面的內容,顯示得我們這次交流有點多余。他們2年前開始做智能礦山的規劃,有很多煤礦行業專家的加持,他們的描述是非常完美,但是去年底應該上線的平臺,現在還沒有看到影子。他們確實有很多場景需求,但是被... ......

    uj5u.com 2023-04-20 08:20:25 more
  • 《社區人員管理》實戰案例設計&個人案例分享

    設計是一個讓人夢想成真程序,開始編碼、測驗、除錯之前進行需求分析和架構設計,才能保證關鍵方面都做正確 ......

    uj5u.com 2023-04-20 08:20:17 more
  • 軟體架構生態化-多角色交付的探索實踐

    作為一個技術架構師,不僅僅要緊跟行業技術趨勢,還要結合研發團隊現狀及痛點,探索新的交付方案。在日常中,你是否遇到如下問題 “ 業務需求排期長研發是瓶頸;非研發角色感受不到研發技改提效的變化;引入ISV 團隊又擔心質量和安全,培訓周期長“等等,基于此我們探索了一種新的技術體系及交付方案來解決如上問題。 ......

    uj5u.com 2023-04-20 08:20:10 more
  • 【中介者設計模式詳解】C/Java/JS/Go/Python/TS不同語言實作

    * 中介者模式是一種行為型設計模式,它可以用來減少類之間的直接依賴關系,
    * 將物件之間的通信封裝到一個中介者物件中,從而使得各個物件之間的關系更加松散。
    * 在中介者模式中,物件之間不再直接相互互動,而是通過中介者來中轉訊息。 ......

    uj5u.com 2023-04-20 08:19:44 more
  • 露天煤礦現場調研和交流案例分享

    他們集團的資訊化公司及研究院在一個礦區正在做智能礦山的統一平臺的 試點,專案投資大概1億,包括了礦山的各方面的內容,顯示得我們這次交流有點多余。他們2年前開始做智能礦山的規劃,有很多煤礦行業專家的加持,他們的描述是非常完美,但是去年底應該上線的平臺,現在還沒有看到影子。他們確實有很多場景需求,但是被... ......

    uj5u.com 2023-04-20 08:19:07 more
  • 《社區人員管理》實戰案例設計&個人案例分享

    設計是一個讓人夢想成真程序,開始編碼、測驗、除錯之前進行需求分析和架構設計,才能保證關鍵方面都做正確 ......

    uj5u.com 2023-04-20 08:18:57 more
  • 軟體架構生態化-多角色交付的探索實踐

    作為一個技術架構師,不僅僅要緊跟行業技術趨勢,還要結合研發團隊現狀及痛點,探索新的交付方案。在日常中,你是否遇到如下問題 “ 業務需求排期長研發是瓶頸;非研發角色感受不到研發技改提效的變化;引入ISV 團隊又擔心質量和安全,培訓周期長“等等,基于此我們探索了一種新的技術體系及交付方案來解決如上問題。 ......

    uj5u.com 2023-04-20 08:18:49 more
  • 05單件模式

    #經典的單件模式 public class Singleton { private static Singleton uniqueInstance; //一個靜態變數持有Singleton類的唯一實體。 // 其他有用的實體變數寫在這里 //構造器宣告為私有,只有Singleton可以實體化這個類! ......

    uj5u.com 2023-04-19 08:42:51 more
  • 【架構與設計】常見微服務分層架構的區別和落地實踐

    軟體工程的方方面面都遵循一個最基本的道理:沒有銀彈,架構分層模型更是如此,每一種都有各自優缺點,所以請根據不同的業務場景,并遵循簡單、可演進這兩個重要的架構原則選擇合適的架構分層模型即可。 ......

    uj5u.com 2023-04-19 08:42:41 more