從網際網路骨幹 BGP 路由協定出發,逐步理解封包如何在自治系統間傳輸,並探討本地路由表與封包轉發機制。接著,介紹 ICMP 與 ping 的運作原理,以及連結層的乙太網路框架結構。同時,也說明 ARP 協定的地址解析流程,並提供 tcpdump 指令範例。此外,文章還涵蓋 VLAN 與 VXLAN 技術,以及它們在 Kubernetes 網路中的應用。最後,深入探討 Kubernetes 網路模型、CNI 外掛選擇、網路策略設定,並以 Go 語言 TCP 伺服器範例說明網路程式設計的實務應用,最後比較 TCP/IP 與 OSI 模型,解析 Kubernetes 網路抽象層級。

網際網路的骨幹:BGP 路由協定

BGP(Border Gateway Protocol,邊界閘道器協定)是網際網路的路由協定,讓不同的自治系統(AS)之間可以交換路由資訊。每個 AS 都有自己的一組 IP 位址,並透過 BGP 與其他 AS 連線。

  graph LR
    A[AS 100] -- BGP --> B[AS 200]
    B -- BGP --> C[AS 300]
    C -- BGP --> A

圖表翻譯:

此圖示展示了三個自治系統之間的 BGP 連線。AS 之間透過 BGP 交換路由資訊,確保封包可以在網際網路上正確傳輸。這種機制讓網際網路能夠高效運作,並支援複雜的網路拓撲結構。

假設一個封包從 IP 位址 130.10.1.200 傳送到 150.10.2.300130.10.1.200 位於 AS 100,而 150.10.2.300 位於 AS 300。封包如何跨越這些 AS 到達目的地?

  graph LR
    A[130.10.1.200] --> B(AS 100 的路由器)
    B --> C(AS 200 的路由器)
    C --> D(AS 300 的路由器)
    D --> E[150.10.2.300]

AS 100 的路由器根據路由表判斷封包屬於 AS 300,並選擇最佳路徑透過特定介面送出。這個過程會在 AS 200 上重複進行,直到 AS 300 上的本地路由器收到封包。這就像寄送包裹,每個中轉站都會根據地址資訊決定下一個目的地。

本地路由表與封包轉發

本地路由表決定了封包將透過哪個介面送出。目標 IP 為 192.168.1.153 的封包,由於在本地網路內,將透過指定的閘道器送出,不需要路由。而如果目標網路未知,封包將透過預設路由送出。

  graph LR
    A[本地主機] --> B{目標 IP}
    B -- 192.168.1.153 --> C[指定閘道器]
    B -- 其他 --> D[預設路由]

圖表翻譯:

此圖示展示了本地路由表的運作原理。當封包的目的 IP 是 192.168.1.153 時,系統會將其傳送到指定的閘道器。若目的 IP 不在本地網路內,則會透過預設路由轉發。

網路連線的偵察兵:ICMP 與 ping

ICMP(Internet Control Message Protocol,網際網路控制訊息協定)是一種用於錯誤報告和診斷的協定。ping 命令列工具使用 ICMP 來測試主機和路由器之間的連線。

ICMP 封包結構

ICMP 封包包含標頭、資料和選項。標頭包含型別、程式碼、校驗和以及其他欄位。型別欄位識別控制訊息,而程式碼欄位提供訊息的額外上下文資訊。

  graph LR
    A[ICMP 標頭] --> B(型別)
    A --> C(程式碼)
    A --> D(校驗和)
    A --> E(其他欄位)
    A --> F[資料]

圖表翻譯:

此圖示展示了 ICMP 封包的結構。ICMP 標頭包含了多個重要欄位,如型別、程式碼和校驗和,用於 ICMP 的錯誤報告和診斷功能。

資料傳輸的最後一哩路:連結層與乙太網路

HTTP 請求被分解成區段,並透過網際網路進行路由,最後一步是透過實體線路傳送資料。TCP/IP 堆積疊的連結層包含兩個子層:媒體存取控制 (MAC) 子層和邏輯鏈路控制 (LLC) 子層。它們共同執行 OSI 模型的第 1 層和第 2 層,即資料鏈路層和實體層。

乙太網路框架結構

乙太網路框架具有標頭和頁尾。標頭包含前導碼、目標 MAC 位址、來源 MAC 位址、VLAN 標籤和乙太網路型別。頁尾包含框架檢查序列 (FCS) 或迴圈冗餘校驗 (CRC)。

  graph LR
    A[乙太網路框架] --> B(標頭)
    B --> C(前導碼)
    B --> D(目標 MAC 位址)
    B --> E(來源 MAC 位址)
    B --> F(VLAN 標籤)
    B --> G(乙太網路型別)
    A --> H(頁尾)
    H --> I(FCS/CRC)
    A --> J[資料]

圖表翻譯:

此圖示展示了乙太網路框架的結構。乙太網路框架由標頭、資料和頁尾組成。標頭包含了多個重要資訊,如來源和目標 MAC 位址,而頁尾則用於資料完整性檢查。

ARP 協定與區域網路通訊

ARP(Address Resolution Protocol,地址解析協定)用於將 IP 位址解析為 MAC 位址。在區域網路中,當一個 IP 封包到達目的地網路時,目的 IP 位址需要透過 ARP 解析成目的主機的 MAC 位址。

ARP 請求流程

  graph LR
    A[請求主機] --> B{ARP 快取}
    B -- 快取命中 --> C[傳送乙太網路框架]
    B -- 快取未命中 --> D[廣播 ARP 請求]
    D --> E[目標伺服器]
    E --> F[ARP 回應]
    F --> A
    F --> C

圖表翻譯:

此圖示説明瞭 ARP 請求的流程。當請求主機需要傳送資料給目標主機時,會先查詢 ARP 快取。若快取中有對應的 MAC 位址,則直接傳送乙太網路框架。若無,則會廣播 ARP 請求,目標主機回應後,請求主機即可傳送資料。

使用 tcpdump 分析 ARP 請求

可以使用 tcpdump 命令來檢視本地網路上的 ARP 請求:

sudo tcpdump -i en0 arp -vvv

這個指令會監聽介面 en0 上的所有 ARP 流量,並以詳細模式輸出。輸出資訊包含乙太網路型別、協定、請求主機和目標 IP 位址等。在 Kubernetes 環境中,可以使用 tcpdump 分析 Pod 之間的網路通訊,進而排查網路問題。

VLAN 與 VXLAN

VLAN(虛擬區域網路)用於進一步分割 Layer 2 網路。在乙太網路框架標頭中有一個可選的 VLAN 標記,用於區分割域網路上的流量。VLAN 有助於劃分割域網路,並管理網路校園中相同或不同交換器上的網路。

VXLAN(虛擬可延伸區域網路)是 VLAN 的延伸,允許將 Layer 2 框架封裝到 Layer 4 UDP 封包中。VXLAN 將可擴充功能性提高到 1600 萬個邏輯網路,並允許跨 IP 網路的 Layer 2 鄰接。這項技術用於 Kubernetes 網路中以產生覆寫網路。

  graph LR
    A[Layer 2 框架] --> B[VXLAN 封裝]
    B --> C[UDP 封包]
    C --> D[IP 網路]

圖表翻譯:

此圖示展示了 VXLAN 的運作原理。VXLAN 將 Layer 2 框架封裝到 UDP 封包中,使其能夠在 IP 網路上傳輸,從而實作跨網路的 Layer 2 連線。這在 Kubernetes 網路中至關重要,因為它允許 Pod 在不同的節點上進行通訊,即使它們不在同一個 Layer 2 網路中。

Kubernetes 網路模型與實務應用

Kubernetes 的網路模型根據每個 Pod 有一個唯一的 IP 位址,並且 Pod 之間可以直接通訊,無需 NAT。這種設計簡化了應用程式的佈署和管理。

CNI(Container Network Interface)

CNI 是 Kubernetes 網路模型的核心元件。它定義了一套標準介面,用於連線容器網路。不同的 CNI 外掛提供了不同的網路實作,如 Calico、Flannel 和 Cilium 等。

網路策略與安全

Kubernetes 提供了豐富的網路策略功能,允許使用者控制 Pod 之間的流量。這有助於提高叢集的安全性,防止未經授權的存取。

apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: allow-from-same-namespace
spec:
  podSelector: {}
  ingress:
  - from:
    - podSelector: {}

這個範例定義了一個簡單的網路策略,允許來自相同名稱空間的流量進入被選中的 Pod。

程式碼範例:簡單的 TCP 伺服器

以下是一個簡單的 TCP 伺服器範例,使用 Go 語言編寫:

package main

import (
	"fmt"
	"log"
	"net"
)

func handleConnection(conn net.Conn) {
	defer conn.Close()
	buffer := make([]byte, 1024)
	n, err := conn.Read(buffer)
	if err != nil {
		log.Println("Error reading from connection:", err)
		return
	}
	clientAddr := conn.RemoteAddr().String()
	fmt.Printf("Received %d bytes from %s: %s\n", n, clientAddr, string(buffer[:n]))

	response := []byte("Hello from the server!\n")
	_, err = conn.Write(response)
	if err != nil {
		log.Println("Error writing to connection:", err)
	}
}

func main() {
	listener, err := net.Listen("tcp", ":8080")
	if err != nil {
		log.Fatal("Error starting server:", err)
	}
	defer listener.Close()

	fmt.Println("Server listening on port 8080")

	for {
		conn, err := listener.Accept()
		if err != nil {
			log.Println("Error accepting connection:", err)
			continue
		}
		go handleConnection(conn)
	}
}

程式碼解說:

此範例程式碼實作了一個簡單的 TCP 回顯伺服器。它監聽在 8080 連線埠上,當接收到客戶端的連線請求時,會啟動一個新的 goroutine 處理該連線。伺服器讀取客戶端傳送的資料,並將其回傳給客戶端。在 Kubernetes 環境中,這種服務可以用於建立 Pod 之間的通訊。

網路模型的比較

以下圖表比較了 TCP/IP 模型和 OSI 模型:

  graph LR
    subgraph "OSI 模型"
        A[應用程式層] --> B(表格示層)
        B --> C(工作階段層)
        C --> D(傳輸層)
        D --> E(網路層)
        E --> F(資料鏈結層)
        F --> G(實體層)
    end
    subgraph "TCP/IP 模型"
        A1[應用程式層] ==> D1(傳輸層)
        D1 ==> E1(網路層)
        E1 ==> H(鏈路層)
    end
    A --- A1
    D --- D1
    E --- E1
    F --- H
    G --- H

圖表翻譯:

此圖表比較了 TCP/IP 和 OSI 網路模型。它們在結構上有所不同,但都描述了網路通訊的不同層面。理解這兩種模型有助於深入理解電腦網路的工作原理。

網路基礎與 Kubernetes 網路架構解析

網路模型是理解現代網路架構的基礎。TCP/IP 模型和 OSI 模型是兩種常見的網路模型,它們在層級數量上有所不同。TCP/IP 模型採用四層結構,而 OSI 模型則包含七層。TCP/IP 模型的簡潔性使其更具實用性,而 OSI 模型的複雜性則使其更適合理論研究。

TCP/IP 與 OSI 模型的比較

TCP/IP 模型和 OSI 模型在網路通訊中扮演著重要角色。TCP/IP 模型的四層結構包括:應用層、傳輸層、網路層和鏈結層。OSI 模型的七層結構則包括:應用層、表示層、會話層、傳輸層、網路層、資料鏈結層和實體層。兩種模型的差異反映了它們在設計上的不同取向。

Go 語言網路伺服器實作

為了更好地理解網路程式設計,我們可以參考一個簡單的 Go 語言網路伺服器範例。以下是一個基本的 TCP 伺服器實作:

package main

import (
	"fmt"
	"net"
)

func handleConnection(conn net.Conn) {
	defer conn.Close()
	buf := make([]byte, 1024)
	n, err := conn.Read(buf)
	if err != nil {
		fmt.Println("讀取錯誤:", err.Error())
		return
	}
	fmt.Println("接收到:", string(buf[:n]))
	conn.Write([]byte("伺服器回應:Hello!\n"))
}

func main() {
	ln, err := net.Listen("tcp", ":8080")
	if err != nil {
		fmt.Println("監聽錯誤:", err.Error())
		return
	}
	defer ln.Close()
	fmt.Println("伺服器監聽在 :8080")
	for {
		conn, err := ln.Accept()
		if err != nil {
			fmt.Println("接受連線錯誤:", err.Error())
			return
		}
		go handleConnection(conn)
	}
}

程式碼解析

此 Go 程式碼建立了一個簡單的 TCP 伺服器,監聽在 8080 埠。handleConnection 函式負責處理每個客戶端的連線請求,讀取客戶端傳送的資料,並回傳一個簡單的訊息。伺服器利用 goroutine 來處理多個客戶端連線,實作了併發處理能力。

Kubernetes 網路模型與 CNI 外掛選擇

Kubernetes 的網路模型根據容器網路介面(CNI),允許使用不同的網路外掛來管理 Pod 網路。選擇適當的 CNI 外掛對於 Kubernetes 叢集的效能和穩定性至關重要。

常見 CNI 外掛比較

CNI 外掛特性描述優點缺點
Calico根據 BGP 的網路解決方案高度可擴充和靈活,支援網路策略設定較為複雜
Weave Net根據 UDP 封裝的網路解決方案易於佈署和管理可能受限於 UDP 的效能
Cilium根據 eBPF 的網路解決方案高效能和安全性,支援 Service Mesh需要較新版本的 Linux 核心支援
Flannel根據 VXLAN 或 UDP 的網路解決方案簡單易用,資源佔用低功能相對較為簡單

在選擇 CNI 外掛時,需要綜合考慮叢集規模、效能需求、安全性和團隊技術堆疊等因素。

Linux 網路基礎與 Pod 網路隔離

Linux 網路名稱空間是 Kubernetes 網路隔離的基礎。每個 Pod 都執行在獨立的網路名稱空間中,擁有自己的網路堆積疊,從而實作了 Pod 之間的隔離。可以使用 ip netns list 命令來檢視系統中的網路名稱空間。

Kubernetes 網路抽象層級解析

Kubernetes 網路模型建立在 Linux 網路基礎之上,CNI 負責將 Pod 連線到網路中。理解這些抽象層之間的關係對於 Kubernetes 網路的管理和除錯非常重要。

  flowchart TD
    A[應用程式] --> B[Pod]
    B --> C[CNI]
    C --> D[Linux 網路名稱空間]
    D --> E[Linux 網路核心]

圖表解析

此圖表展示了 Kubernetes 網路模型的抽象層級結構。應用程式執行在 Pod 中,Pod 的網路由 CNI 管理,CNI 根據 Linux 網路名稱空間實作隔離,最終依賴於 Linux 網路核心進行資料傳輸。

本文全面探討了 Kubernetes 網路架構的核心概念,從 TCP/IP 模型到 CNI 選擇策略,再到 Linux 網路基礎和網路名稱空間,最後闡述了 Kubernetes 網路抽象層之間的關係。透過深入理解這些內容,可以更好地掌握 Kubernetes 網路的管理和除錯技巧,從而確保應用程式的高效能和穩定性。

  flowchart LR
    A[客戶端] -->|請求| B[伺服器]
    B -->|回應| A
    B --> C[日誌記錄]

圖表解析

此圖表展示了一個簡單的客戶端-伺服器互動流程。客戶端向伺服器傳送請求,伺服器處理請求後回傳回應,同時進行日誌記錄。此圖清晰地展示了客戶端與伺服器之間的互動過程,有助於理解網路通訊的基本原理。

最終,這些知識有助於建立更穩定和高效的 Kubernetes 網路環境,為現代應用程式的開發和佈署提供堅實的基礎。