DUICUO

EnspはCalicoクロスセグメントBGPネットワークをシミュレートします

[[437697]]

以前、CalicoのIPIP、VXLAN、BGPモードについて詳しく説明しました。ただし、すべてのKubernetesノードは同じネットワークセグメント上にあります。この記事では、ENSPとWorkstationを使用して、自宅のクロスネットワークセグメントKubernetesクラスター向けにCalicoソリューションのピュアBGPモードをシミュレートおよびテストします。

アーキテクチャのセットアップ

このテストでは、「ラックごとの独立した自律システム」アーキテクチャを使用します。これは、「ラックごとのAS」モデル[1]で参照されています。

クロスネットワークセグメントKubernetesクラスタアーキテクチャ

アーキテクチャ全体は、ESP(エンジニアリングサービスプロバイダー)コンポーネントとワークステーションコンポーネントに分かれています。ESPコンポーネントは主に、R1とR2間のEGP関係を確立し、それぞれのネットワークセグメント内のKubernetesノードのBGPピアをR1とR2に追加します。ワークステーションコンポーネントは、ネットワーク間をまたぐKubernetesクラスターを構築します。192.168.219.0/24ネットワークセグメントからクラスターへのホストの追加はESPのルーティングに依存するため、操作手順は、まずESPのネットワーク部分を確立し、次にKubernetesに新しいノードを追加し、最後にBGPを構成するという流れになります。既存のKubernetesクラスターには、ブリッジ経由で接続された3台のサーバー(マスターノード1台と通常ノード2台)があり、その構成は以下のとおりです。

  • k8sマスター: 10.30.81.127
  • k8s-node1: 10.30.81.128
  • k8s-node2: 10.30.81.130

ESP構成

ENP部分のネットワークデバイス接続トポロジは上図のとおりです。次に、R1、R2、そして2つのクラウドをそれぞれ設定します。R1とR2の設定は以下のとおりです。

  1. :'
  2. R1上の構成
  3. '
  4. # インターフェースIP設定
  5. 整数g0/0/0
  6. IP a 20.20.20.10 24
  7. 整数g0/0/1
  8. IPアドレス 10.30.81.118 24
  9. 整数g0/0/2
  10. IP 30.30.30.10 24
  11.  
  12. # 次のネットワークセグメントにジャンプするための静的ルートを設定します
  13. IPルート -静的192.168.219.0 24 20.20.20.20
  14. IPルート -静的192.168.219.0 24 30.30.30.20
  15.  
  16. # BGP 設定では、同じAS内の BGP ピアも設定します
  17. bgp 64512
  18. ピア 10.30.81.127 を-number 64512として
  19. ピア 10.30.81.128 を-number 64512として
  20. ピア 10.30.81.130 を-number 64512として
  21. ピア 192.168.219.10 を-number 64513として
  22. ピア 192.168.219.10 ebgp-最大ホップ 5
  23. ピア 192.168.219.10接続-インターフェース g0/0/1
  24. ピア 10.30.81.127 リフレクトクライアント
  25. ピア 10.30.81.128 リフレクトクライアント
  26. ピア 10.30.81.130 リフレクトクライアント
  27.  
  28. BGPピアを表示
  29. BGP IPルーティングを表示
  30. IPインターフェースBRを表示
  31. IPルーティングテーブルを表示する 
  32.  
  33. :'
  34. R2上の構成
  35. '
  36. # インターフェースIP設定
  37. 整数g0/0/0
  38. IPアドレス 192.168.219.10 24
  39. 整数g0/0/1
  40. ip a 20.20.20.20 24
  41. 整数g0/0/2
  42. IP 30.30.30.20 24
  43.  
  44. # 次のネットワークセグメントにジャンプするための静的ルートを設定します
  45. IPルート -静的10.30.81.0 24 20.20.20.10
  46. IPルート -静的10.30.81.0 24 30.30.30.10
  47.  
  48.  
  49. # BGP 設定では、同じAS内の BGP ピアも設定します
  50. bgp 64513
  51. ピア 10.30.81.118 を-number 64512として
  52. ピア 10.30.81.118 ebgp-最大ホップ 5
  53. ピア 10.30.81.118接続-インターフェース g0/0/0
  54. ピア 192.168.219.20 を-number 64513として
  55. ピア 192.168.219.40 を-number 64513として
  56. ピア 192.168.219.20 リフレクトクライアント
  57. ピア 192.168.219.40 リフレクトクライアント
  58.  
  59. BGPピアを表示
  60. BGP IPルーティングを表示
  61. IPインターフェースBRを表示
  62. IPルーティングテーブルを表示する 

上記のようにR1とR2を設定し、2つのクラウドを設定した後、R2から10.30.81.118へのpingは成功し、R1とR2がEBGP関係を確立していることも確認できます。しかし、R2からKubernetesクラスター内のどのホストへのpingも失敗し、「ホスト到達不能」エラーが発生します。これは、Kubernetesノードにリターンルートがなく、ICMPリプレイパケットをR1に送信する方法がわからないためです。そのため、3つのホストにルートを追加する必要があります。

  1. この時点で次のルートを追加しても効果はありません。R2 から発信された ping パケットの送信元 IP が 192.1168.219.0/24 ネットワーク セグメント内にないためです。
  2. ルート追加-n 192.168.219.0/24 gw 1​​0.30.81.118 dev ens33
  3. echo route add -n 192.168.219.0/24 gw 1​​0.30.81.118 dev ens33 >> /etc/rc.local  
  4. IPルート追加192.168.219.0/24 経由 10.30.81.118 dev ens33
  5.  
  6. 以下のルートを追加すると、R2 が既存の Kubernetes クラスタノードに ping を送信できるようになります。R2 は中間ノードに過ぎないため、ping が成功したら削除できます。
  7. ルート追加-n 20.20.20.0/24 gw 1​​0.30.81.118 dev ens33
  8. ルート追加-n 30.30.30.0/24 gw 1​​0.30.81.118 dev ens33

上記のルートをすべての Kubernetes ノードに追加すると、R2 からすべての Kubernetes ノードに ping を実行できるようになります。

Kubernetes クラスターに新しいマシンが追加されました

仮想マシンを作成し、ネットワークをNATモードに設定します。ネットワークアダプタとルートを設定し、10.30.81.0/24ネットワークセグメントからのルートがvmnet8を指していないことを確認します。ネットワークアダプタの設定は次のとおりです。

  1. # ネットワークカードの構成は次のとおりです
  2. [root@k8s-node4 ~]# cat ifcfg-ens33
  3. タイプ=イーサネット
  4. DNS1=8.8.8.8
  5. IPアドレス=192.168.219.40
  6. ネットマスク=255.255.255.0
  7. ゲートウェイ=192.168.219.10
  8. BOOTPROTO =静的 
  9. DEFROUTE=はい
  10. IPV4_FAILURE_FATAL=いいえ 
  11. 名前=ens33
  12. UUID=6ef9b5bf-31c1-43b9-89d6-b8e89ab3c9c3
  13. デバイス=ens33
  14. ONBOOT=はい
  15.  
  16. # 以下のルートは省略可能です。
  17. ルート追加-net 10.30.81.0/24 gw 1​​92.168.219.10 dev ens33

次はノードをKubernetesに参加させるための準備です。

システム構成は次のとおりです。

  1. echo "ファイアウォールを停止"  
  2. systemctl 停止 firewalld
  3. systemctl で firewalld を無効にする
  4. sed -ie 's/SELINUX=enforcing/SELINUX=disabled/g' /etc/selinux/config
  5. 強制0を設定する
  6.  
  7. echo "net.ipv4.ip_forward = 1" >> /etc/sysctl.conf
  8. echo "net.bridge.bridge-nf-call-ip6tables = 1" >>/etc/sysctl.conf
  9. echo "net.bridge.bridge-nf-call-iptables = 1" >>/etc/sysctl.conf
  10. echo "net.bridge.bridge-nf-call-arptables = 1" >>/etc/sysctl.conf
  11. スワップオフ -a
  12. echo swapoff -a >> /etc/rc.local  
  13. sysctl -p

既存のKubernetesクラスタノードからkubeadm、kubelet、kubectlのバイナリを/usr/binディレクトリにコピーします。kubeletが起動時に自動的に起動するように設定します。kubeletの設定は次のとおりです。

  1. [ユニット]
  2. 説明=kubelet: Kubernetes ノードエージェント
  3. ドキュメント=https://kubernetes.io/docs/
  4. 欲しいもの=ネットワークオンライン.ターゲット
  5. = network-online.target
  6.  
  7. [サービス]
  8. ExecStart=/usr/bin/kubelet --bootstrap-kubeconfig=/etc/kubernetes/bootstrap-kubelet.conf --kubeconfig=/etc/kubernetes/kubelet.conf --config=/var/lib/kubelet/config.yaml --network-plugin=cni --pod-infra-container-image=k8s.gcr.io/pause:3.2 --fail-swap-on=false  
  9. 再起動=常に
  10. 開始制限間隔=0
  11. 再起動秒数=10
  12.  
  13. [インストール]
  14. WantedBy =マルチユーザー.ターゲット

Dockerをインストールする

Calico関連のコンテナイメージとkube-proxyイメージを既存のKubernetesクラスターノードからエクスポートし、新しいノードにインポートします。クラスターは既に存在するため、Kubernetesコントロールプレーンイメージ(apiserver、etcd、controller-manager、scheduler)を新しいノードにコピーする必要はありません。

kubeadm を使用して、新しいノードを Kubernetes クラスターに追加します。

検証の結果、ネットワークセグメント間の通信はENPネットワークを使用していることが示されました。k8s-masterからk8s-node3へのルーティングパスをトレースしたところ、ネクストホップはR2のインターフェースである20.20.20.20であることが判明しました。

  1. [root@k8s-master ~]# トレースルート 192.168.219.20
  2. 192.168.219.20 (192.168.219.20)へのtraceroute、最大30ホップ、60バイトパケット
  3. 1 10.30.81.118 (10.30.81.118) 18.396ミリ秒 79.412ミリ秒 79.396ミリ秒
  4. 2 20.20.20.20 (20.20.20.20) 79.387 ミリ秒 79.380 ミリ秒 83.814 ミリ秒
  5. 3 k8s-node3 (192.168.219.20) 108.104 ミリ秒 112.777 ミリ秒 117.847 ミリ秒

上記のように、5 ノードのクロスネットワーク セグメント Kubernetes クラスターが次のように構築されました。

  1. [root@k8s-node4 ~]# kubectl get node -o ワイド
  2. 名前ステータス 役割 年齢 バージョン 内部IP
  3. k8s-master コントロールプレーン準備完了、マスター 45d v1.20.0 10.30.81.127
  4. k8s-node1 準備完了 <なし> 45d v1.20.0 10.30.81.128
  5. k8s-node2 準備完了 <なし> 9d v1.20.0 10.30.81.130
  6. k8s-node3 準備完了 <なし> 20h v1.20.0 192.168.219.20
  7. k8s-node4 準備完了 <なし> 20h v1.20.0 192.168.219.40

カリコ設定BGP

BGPの設定にはcalicoctlツールが必要です。これはご自身で用意する必要があります。BGPの設定は主に以下の手順で行います。

  1. Calico 展開が純粋な BGP モードであることを確認しました。
  2. BGP のデフォルトのフルメッシュ モードを無効にします。
  3. 指定されたホスト k8s-node3 および k8s-node4 の BGP AS 番号値を 64513 に変更します。
  4. BGP ピアが特定のピアを選択できるように、すべてのホストに BGP AS グループ化のタグを付けます。
  5. BGP ピアを作成し、手順 4 のタグ付けを使用して、RR クライアントと RR の間に IBGP 関係を確立します。

calico-node の次の 2 つの構成が Never に設定されていることを確認します。

  1. -名前: CALICO_IPV4POOL_IPIP
  2. 値: "しない"  
  3. -名前: CALICO_IPV4POOL_VXLAN
  4. 値: "しない"  

Calico の BGP モードはデフォルトでフルメッシュなので、オフにしてください。

  1. calicoctl get bgpconfiguration default -o yaml
  2. apiバージョン: projectcalico.org/v3
  3. アイテム:
  4. - apiバージョン: projectcalico.org/v3
  5. 種類: BGPConfiguration
  6. メタデータ:
  7. 作成タイムスタンプ: "2021-09-05T06:23:50Z"  
  8. 名前:デフォルト 
  9. リソースバージョン: "555583"  
  10. uid: 9438105f-cdd8-4315-8694-6d4885c76c85
  11. 仕様:
  12. logSeverityScreen: 情報
  13. nodeToNodeMeshEnabled: false # これをfalseに変更した後、 calicoctl apply -f bgpconfiguration.yaml
  14. 種類: BGPConfigurationList
  15. メタデータ:
  16. リソースバージョン: "580613"  

calico ノード k8s-node3 と k8s-node4 の BGP AS 番号を 64513 に設定します。

  1. calicoctl get node k8s-node3 -o yaml > node3.yaml
  2. apiバージョン: projectcalico.org/v3
  3. 種類: ノード
  4. メタデータ:
  5. 注釈:
  6. projectcalico.org/kube-labels: '{"beta.kubernetes.io/arch":"amd64","beta.kubernetes.io/os":"linux","kubernetes.io/arch":"amd64","kubernetes.io/hostname":"k8s-node3","kubernetes.io/os":"linux"}'  
  7. 作成タイムスタンプ: "2021-09-04T14:03:35Z"  
  8. ラベル:
  9. beta.kubernetes.io/arch: amd64
  10. beta.kubernetes.io/os: Linux
  11. kubernetes.io/arch:amd64
  12. kubernetes.io/ホスト名: k8s-node3
  13. kubernetes.io/os: Linux
  14. 名前: k8s-node3
  15. リソースバージョン: "580885"  
  16. uid: 64f44ad1-f537-43f3-9f0e-d5d5b80adba2
  17. 仕様:
  18. 住所:
  19. - アドレス: 192.168.219.20/24
  20. タイプ: CalicoNodeIP
  21. - 住所: 192.168.219.20
  22. タイプ: 内部IP
  23. bgp:
  24. asNumber: 64513 # この行を追加
  25. ipv4アドレス: 192.168.219.20/24
  26. orchRefs:
  27. - ノード名: k8s-node3
  28. オーケストレーター: k8s
  29. 状態:
  30. podCIDR:
  31. - 10.244.4.0/24

ノードのタグ付け

  1. :'
  2. as64512のノードにタグを付ける
  3. '
  4. kubectl ラベルノード k8s-master as -グループ=as64512
  5. kubectl ラベルノード k8s-master -id =as64512
  6. kubectl ラベルノード k8s-node1 as -グループ=as64512
  7. kubectl ラベルノード k8s-node1-id=as64512 を付ける
  8. kubectl ラベルノード k8s-node2 as -グループ=as64512
  9. kubectl ラベルノード k8s-node2-id=as64512 を付ける
  10.  
  11. :'
  12. as64513のノードにタグを付ける
  13. '
  14. kubectl ラベルノード k8s-node3 as -グループ=as64513
  15. kubectl ラベルノード k8s-node3 を-id=as64513として
  16. kubectl ラベルノード k8s-node4 as -グループ=as64513
  17. kubectl ラベルノード k8s-node4 を-id=as64513として
  18.  
  19. :'
  20. 次のポッドのデプロイメントでは、ネットワーク間のセグメント ノード通信をテストします。
  21. '
  22. kubectl ラベル ノード k8s-master node=master
  23. kubectl ラベル ノード k8s-node4 node=node4
  24. kubectl ラベル ノード k8s-node3 node=node3
  25. kubectl ラベル ノード k8s-node2 node=node2
  26. kubectl ラベル ノード k8s-node1 node=node1

Calico BGPピアインスタンスを作成します。ESP設定でR1とR2にRRモードが既に設定されているため、すべてのKubernetesノードをRRクライアントとして扱うことを選択します。したがって、同じAS配下のKubernetesノードはIBGPピア関係を確立する必要はありません。残りの手順では、各ASのKubernetesノードがそれぞれR1およびR2とIBGP関係を確立します。

  1. :'
  2. リージョン as64513 の Kubernetes ノードは、R2 と rr 関係を確立します。
  3. '
  4. vim as64513_r2_peer.yaml
  5. apiバージョン: projectcalico.org/v3
  6. 種類: BGPPeer
  7. メタデータ:
  8. name : as64513- to -r2-peer ## BGPPeerに識別しやすい名前を付けます
  9. 仕様:
  10. nodeSelector: rr-id == 'as64513' ##ノードセレクターを使用して、タグrr-id == 'as64513'を持つノードを追加します。
  11. ピアIP: 192.168.219.10
  12. 番号: 64513
  13.  
  14.  
  15. :'
  16. リージョン as64512 の Kubernetes ノードは、R1 と rr 関係を確立します。
  17. '
  18. vim as64512_r1_peer.yaml
  19. apiバージョン: projectcalico.org/v3
  20. 種類: BGPPeer
  21. メタデータ:
  22. name : as64512- to -r1-peer ## BGPPeerに識別しやすい名前を付けます
  23. 仕様:
  24. nodeSelector: rr-id == 'as64512' ##ノードセレクターを使用して、タグrr-id == 'as64512'を持つノードを追加します
  25. ピアIP: 10.30.81.118
  26. 番号: 64512
  27.  
  28. calicoctl apply -f as64512_r1_peer.yaml
  29. calicoctl apply -f as64513_r2_peer.yaml

BGPルートアナウンスメントとポッド間通信を検証する

各ノード行のタグを使用してポッドを作成し、異なるネットワークエンドポイントにまたがる 2 つのホスト上のポッドに ping を送信してパケットキャプチャを取得します。(ポッドの作成)

  1. mkdir test_pod
  2. cd test_pod
  3.  
  4. vim マスター.yaml
  5. apiバージョン: v1
  6. 種類: ポッド
  7. メタデータ:
  8. 名前:マスター
  9. 仕様:
  10. コンテナ:
  11. -名前: マスター
  12. 画像: larioy/nettool:latest
  13. imagePullPolicy: IfNotPresent
  14. ノードセレクター:
  15. ノード: マスター
  16.      
  17. sed s/master/node1/g master.yaml > node1.yaml
  18. sed s/master/node2/g master.yaml > node2.yaml
  19. sed s/master/node3/g master.yaml > node3.yaml
  20. sed s/master/node4/g master.yaml > node4.yaml
  21.  
  22. ls -l | grep -v grep | grep yaml | awk '{print $9}' | xargs -I {} kubectl apply -f {}

作成されたポッドの分布を確認します。

  1. [root@k8s-master ~]# kubectl get pod -o wide
  2. 名前準備完了 ステータス 再起動 年齢 IP ノード
  3. マスター 1/1 実行中 0 4時間17分 10.244.235.192 k8s-master
  4. node1 1/1 実行中 0 4時間17分 10.244.36.64 k8s-node1
  5. node2 1/1 実行中 0 4時間17分 10.244.169.129 k8s-node2
  6. node3 1/1 実行中 0 4時間17分 10.244.107.192 k8s-node3
  7. node4 1/1 実行中 0 4時間17分 10.244.122.64 k8s-node4

Birdクライアントで学習したBGPルートを確認します。Kubernetesマスターノードでは、そのポッドサブネットは10.244.235.192/26です。

RRルートアナウンス

ensp ネットワークの R1 では、すべての Kubernetes ノードのポッド サブネットに対応するサブネット ルートを学習できる必要があります。

R1が学習したBGPルーティング

次に、パケットキャプチャを使用して、ネットワークセグメントをまたがるポッド間の通信を検証しました。R2でパケットキャプチャを実行し、as64512のk8s-masterノード上のポッドマスターとas64513のk8s-node3ノード上のポッドノード3間の通信を検証しました。

  1. [root@k8s-master ~]# kubectl get pod -o wide | grep -E "node3|master"   
  2. マスター 1/1 実行中 0 29分 10.244.235.192 k8s-master
  3. node3 1/1 実行中 0 29m 10.244.107.192 k8s-node3
  4.  
  5. [root@k8s-master ~]# kubectl exec -it マスター-- ping 10.244.107.192  
  6. PING 10.244.107.192 (10.244.107.192): 56データバイト
  7. 10.244.107.192からの64 バイト: seq=0 ttl=60 time =49.314 ms
  8. 10.244.107.192からの64 バイト: seq=1 ttl=60 time =28.744 ms
  9. 10.244.107.192からの64 バイト: seq=2 ttl=60 time =48.422 ms
  10. 10.244.107.192からの64 バイト: seq=3 ttl=60 time =39.144 ms
  11. 10.244.107.192からの64 バイト: seq=4 ttl=60 time =32.472 ms

R2 パケットキャプチャ

上記のクロスノード Kubernetes クラスターは、BGP に基づいてポッド間通信を実装します。

BGPの手動メンテナンス

実験中、ENSPセクションのR1/R2のBGP設定はすべて手動で管理されていました。ラックごとに1つのASを配置する構成において、AS内のホストのオンライン/オフライン状態を監視し、RR上のクライアント情報を自動更新する方法を説明します。

BGPアーキテクチャに関する考察

このテストでは、「各ラックを独立したASとして」というアーキテクチャのみを確立しました。このアーキテクチャでは、最上位層は接続にスイッチを使用します。したがって、異なるネットワークセグメント内のすべてのルートレシーバー(RR)はEBGP関係を確立する必要があります。完全な相互接続は必須ではありませんが、各RRは少なくとも1つのRRから、他のRRによってアドバタイズされたBGPルートを学習できる必要があります。「各ラックを独立したASとして」という別のアーキテクチャでは、最上位層にルーターを使用し、すべてのRRとEBGP関係を確立します。これにより、RR間のBGP関係は不要になります。ルートエントリ数が多い異なるアーキテクチャの適合性については、まだ検討されていません。

問題ログ

  • ESP でクラウド使用時に vmnet8 ネットワークアダプタが見つからないという問題が発生しています。WinPcap と ESP を再インストールした後、同じネットワークセグメント上のルーターとホストに突然アクセスできなくなりました。おそらくネットワークアダプタが見つからないことが原因です。
  • ESPルーティングデバイスの無効化に関する問題については、ESPインターフェースの右上メニューにあるヘルプマニュアルをご覧ください。ページ上のすべてのデバイスを削除し、再登録してください。それでも問題が解決しない場合は、ESPの再インストールをご検討ください。
  • Workstation が NAT モードで仮想マシンに接続できない: まず、ホスト上の vmnet8 ネットワークアダプタの IP アドレスを確認してください。仮想ネットワークエディタで NAT を設定する際は、NAT 範囲が vmnet8 の IP アドレスと同じネットワークセグメント内にある必要があり、ゲートウェイが vmnet8 の IP アドレスに設定されている必要があります。
  • 新しい Kubernetes ノードを追加して必要なツールをインストールするときは、最初にブリッジ ネットワークに切り替え、次に NAT に切り替えて、Kubernetes クラスターに参加することができます。
  • ENP ネットワーク構成が失敗した場合、ルータ R1 と R2 のインターフェイスの両端でパケットを直接キャプチャして、どのセグメントに障害が発生しているか、どのセグメントが要求を受信して​​いるが応答していないかを分析できます。

これはオリジナルの投稿です。元の記事はこちらです:https://larioy.gst.monster/2021/09/05/k8s-ji-chong-cni-fang-an-jie-xi/calico/ensp-mo-ni-calico-kua-wang-duan-bgp-wang-luo/

参考文献

[1]AS Per Rackモデル: https://docs.projectcalico.org/reference/architecture/design/l3-interconnect-fabric