Antrea CNIのFlow ExporterでPod間のフロー情報を可視化する
vExperts Advent Calendar 2020の12月18日分の投稿です。
はじめに
Antrea CNIのFlow Exporter機能を利用して、Elastic Stackで構成されるFlowコレクターでPod間のフロー情報を可視化してみます。
- Ubuntu 20.04.1 LTS
- Kubernetes v1.19.4
- Antrea v0.11.1
- Elastic Stack
- elasticsearch 7.8.0
- kibana 7.8.0
- logstash 7.8.0
AntreaとFlow Exporter
AntreaはオープンソースのCNI Pluginで、KubernetesでPod間通信を可能にし、Network Policyによる通信制御を可能にします。AntreaはOpen vSwitch(OVS)を利用しています。
Antrea v0.9.0で実装されたFlow Exporter機能はNodeのconntrackを監視し、conntrackが持つフロー情報をIPFIXフローレコードに変換して指定したフローコレクターに送信することが可能です。(IPFIXへの変換はgo-ipfixライブラリを利用しています。)Flow Exporterの機能はAntrea Agentに実装されており、定期的にconntrackモジュールの状態をポーリングしてIPFIX(Netflow v10)フォーマットでFlowレコードを作成します。
参考 Network Flow Visibility in Antrea
Antreaのデプロイ
最新のTanzu Kubernetes GridはCNIとしてAntreaに対応していますが、作成されるKubernetesクラスターはClsuter APIによってAntreaの設定(Configmap)が制御されてしまうため、今回はkubeadmで作成したクラスターを利用しています。
$ kubectl get node -o wide
NAME STATUS ROLES AGE VERSION INTERNAL-IP EXTERNAL-IP OS-IMAGE KERNEL-VERSION CONTAINER-RUNTIME
master NotReady master 2m v1.19.4 10.44.185.125 <none> Ubuntu 20.04.1 LTS 5.4.0-56-generic docker://19.3.14
node1 NotReady <none> 82s v1.19.4 10.44.185.126 <none> Ubuntu 20.04.1 LTS 5.4.0-56-generic docker://19.3.14
node2 NotReady <none> 67s v1.19.4 10.44.185.127 <none> Ubuntu 20.04.1 LTS 5.4.0-56-generic docker://19.3.14
antrea v0.11.1をデプロイします。
$ kubectl apply -f https://github.com/vmware-tanzu/antrea/releases/download/v0.11.1/antrea.yml
kube-systemネームスペースでantrea-controller/antrea-agentが起動します。
$ kubectl get pod -n kube-system
NAME READY STATUS RESTARTS AGE
antrea-agent-2vs6n 2/2 Running 0 81s
antrea-agent-dkf75 2/2 Running 0 81s
antrea-agent-lfctk 2/2 Running 0 81s
antrea-controller-db5b84647-vzvm4 1/1 Running 0 81s
coredns-f9fd979d6-7vzgh 1/1 Running 0 13m
coredns-f9fd979d6-dwhdq 1/1 Running 0 13m
etcd-master 1/1 Running 0 13m
kube-apiserver-master 1/1 Running 0 13m
kube-controller-manager-master 1/1 Running 0 13m
kube-proxy-df8d8 1/1 Running 0 12m
kube-proxy-kwcfg 1/1 Running 0 13m
kube-proxy-x7rmx 1/1 Running 0 13m
kube-scheduler-master 1/1 Running 0 13m
CNIが有効になることで、corednsがREADYになりNodeもReady状態になります。
$ kubectl get node -o wide
NAME STATUS ROLES AGE VERSION INTERNAL-IP EXTERNAL-IP OS-IMAGE KERNEL-VERSION CONTAINER-RUNTIME
master Ready master 14m v1.19.4 10.44.185.125 <none> Ubuntu 20.04.1 LTS 5.4.0-56-generic docker://19.3.14
node1 Ready <none> 14m v1.19.4 10.44.185.126 <none> Ubuntu 20.04.1 LTS 5.4.0-56-generic docker://19.3.14
node2 Ready <none> 13m v1.19.4 10.44.185.127 <none> Ubuntu 20.04.1 LTS 5.4.0-56-generic docker://19.3.14
antrea-controller/antrea-agentの設定はConfigMap(antrea-config-9c7h568bgf)が利用されます。
$ kubectl get configmap -n kube-system
NAME DATA AGE
antrea-ca 1 17m
antrea-config-9c7h568bgf 3 17m
coredns 1 29m
extension-apiserver-authentication 6 29m
kube-proxy 2 29m
kubeadm-config 2 29m
kubelet-config-1.19 1 29m
Flowコレクターの作成
AntreaのリポジトリにFlowコレクターを構成するためのelk-flow-collector
が提供されています。このマニフェストを利用してelasticsearch/kibana/logstashを作成します。
logstash向けのinput/filter/outputの設定、codecに利用するIPFIXの定義ファイルなどが提供されており、これらのファイルをConfigMaptとしてlogstashコンテナから利用します。
$ git clone https://github.com/vmware-tanzu/antrea
$ cd antrea/build/yamls
$ kubectl create namespace elk-flow-collector
$ kubectl create configmap logstash-configmap -n elk-flow-collector --from-file=./elk-flow-collector/logstash/
$ kubectl apply -f ./elk-flow-collector/elk-flow-collector.yml -n elk-flow-collector
しばらくするとPodがReadyになります。
$ kubectl get pod -n elk-flow-collector
NAME READY STATUS RESTARTS AGE
elasticsearch-0 1/1 Running 0 2m49s
kibana-7ddf7f7c78-vqgxl 1/1 Running 0 2m49s
logstash-6f55bf94f6-kswct 1/1 Running 0 2m49s
kibanaはNodePort
として公開されます。必要に応じてLoadBalancer
に変更します。
$ kubectl get svc -n elk-flow-collector
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
elasticsearch ClusterIP 10.102.54.73 <none> 9200/TCP 3m21s
kibana NodePort 10.107.159.250 <none> 5601:30007/TCP 3m21s
logstash ClusterIP 10.104.53.86 <none> 4739/UDP 3m21s
elk-flow-collectorで構成されるlogstashは以下のようにInputを設定しおり、上記の通りClusterIP 10.104.53.86:4739:udp
としてantrea agentからFlowレコードを受信します。
input {
udp {
host => "0.0.0.0"
port => "4739"
workers => "4"
queue_size => "2048"
receive_buffer_bytes => "16777216"
codec => netflow {
versions => [10]
target => "ipfix"
include_flowset_id => "true"
cache_ttl => 86400
ipfix_definitions => "/usr/share/logstash/definitions/ipfix.yml"
}
type => "ipfix"
}
}
Antreaの設定変更
ConfigMapとして構成されている、antrea-agentが起動時に参照する設定ファイル(antrea-agent.conf)を以下のように修正します。
-
featureGates.FlowExporter
をtrue
としてFlowExporter有効化します。 - flowPollIntervalをコメントアウトします。
flowPollInterval: "5s"
- flowPollIntervalはFlowExporterがconntrackモジュールからConnection情報を取得する間隔を指定します。
- flowExportFrequencyをコメントアウトします。
flowExportFrequency: 12
- FlowレコードをFlow Collectorにエクスポートする頻度としてポーリングサイクルを指定します。
-
flowCollectorAddr
としてlogstash ServiceがListenしている10.104.53.86:4739:udp
を指定します。
実際に修正したConfigMapのサンプル : antrea-configmap.yaml。
各Node上で起動しているantrea-agentを削除して新しいコンフィグで再起動します。
$ kubectl delete pod -n kube-system `kubectl get pod -n kube-system -l component=antrea-agent -o=jsonpath='{.items[*].metadata.name}'`
antrea-agentが再起動してRunningになります。
$ kubectl get pods -n kube-system -l component=antrea-agent
NAME READY STATUS RESTARTS AGE
antrea-agent-fnjbx 2/2 Running 0 41s
antrea-agent-lfhft 2/2 Running 0 35s
antrea-agent-pv2t6 2/2 Running 0 36s
Flowコレクターの確認
antrea-agentがFlowレコードの送信を開始すると、Flowコレクターであるlogstashのログにjson形式のデータが記録され始めます。
$ kubectl logs -n elk-flow-collector -f logstash-6f55bf94f6-kswct
...
{
"type" => "ipfix",
"ipfix" => {
"sourcePodName" => "logstash-6f55bf94f6-kswct",
"egressNetworkPolicyNamespace" => "N/A",
"destinationNodeName" => "",
"destinationPodName" => "",
"octetTotalCount" => 0,
"flowset_id" => 256,
"destinationIPv4Address" => "10.244.2.3",
"sourceNodeName" => "node1",
"ingressNetworkPolicyName" => "N/A",
"packets" => 0,
"flowStartSeconds" => "2042-07-14T01:04:00.000Z",
"packetDeltaCount" => 0,
"flowEndSeconds" => "2042-07-14T01:04:00.000Z",
"reverseOctetDeltaCount" => 0,
"protocolIdentifier" => 6,
"ingressNetworkPolicyNamespace" => "N/A",
"packetTotalCount" => 0,
"bytes" => 0,
"sourceIPv4Address" => "10.244.1.3",
"destinationTransportPort" => 9200,
"octetDeltaCount" => 0,
"destinationPodNamespace" => "",
"egressNetworkPolicyName" => "N/A",
"sourceTransportPort" => 37872,
"reversePacketDeltaCount" => 0,
"destinationClusterIPv4" => "10.102.54.73",
"version" => 10,
"reverseOctetTotalCount" => 0,
"destinationServicePortName" => "elk-flow-collector/elasticsearch:",
"sourcePodNamespace" => "elk-flow-collector",
"reversePacketTotalCount" => 0
},
"@timestamp" => 2020-12-09T09:10:26.000Z,
"@version" => "1",
"host" => "10.244.1.1"
}
ダッシュボードの作成
デプロイされたkibanaにアクセスします。elasticsearchがデータを受信できていると以下のようにflow-yyyy-mm-dd
というインデックスが作成され、インデックスパターンを作成することができます。Antreaのリポジトリにあるbuild/yamls/elk-flow-collector/kibana.ndjsonはIndex Pattern、Visualize、Dashboardが定義されているため、Management > Stack Management > Saved Objects画面でImportを選択してファイルをインポートします。
上記をインポートすることによりIndex Patternが定義され、以下のダッシュボードが作成されます。
- Antrea: Overview Dashboard
- Antrea: Flow Dashboard
- Antrea: Flow Record Dashboard
- Antrea: Node Thorughput Dashboard
- Antrea: Network Policy Dashboard
まとめ
Antrea CNIのFlowエクスポート機能により生成されるフローレコードをELKスタックを利用して可視化することができました。将来的にはVMwareのvRealize Network Insightを利用してNSX-Tや物理デバイスと同じ画面で一元的にフロー情報を確認できるようになるのでしょう。