-
Notifications
You must be signed in to change notification settings - Fork 431
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
4 changed files
with
194 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,148 @@ | ||
#!/bin/bash | ||
set -euo pipefail | ||
|
||
KUBE_OVN_NS=kube-ovn | ||
CENTRAL_POD= | ||
|
||
showHelp(){ | ||
echo "kubectl ko {subcommand} [option...]" | ||
echo "Available Subcommands:" | ||
echo " nbctl [ovn-nbctl options ...] invoke ovn-nbctl" | ||
echo " sbctl [ovn-sbctl options ...] invoke ovn-sbctl" | ||
echo " tcpdump {namespace/podname} [tcpdump options ...] capture pod traffic" | ||
echo " trace {namespace/podname} {target ip address} {icmp|tcp|udp} [target tcp or udp port] trace ovn microflow of specific packet" | ||
} | ||
|
||
tcpdump(){ | ||
namespacedPod="$1"; shift | ||
namespace=$(echo "$namespacedPod" | cut -d "/" -f2) | ||
if [ "$podName" = "$namespacedPod" ]; then | ||
nodeName=$(kubectl get pod "$podName" -o jsonpath={.spec.nodeName}) | ||
mac=$(kubectl get pod "$podName" -o jsonpath={.metadata.annotations.ovn\\.kubernetes\\.io/mac_address}) | ||
hostNetwork=$(kubectl get pod "$podName" -o jsonpath={.spec.hostNetwork}) | ||
else | ||
nodeName=$(kubectl get pod "$podName" -n "$namespace" -o jsonpath={.spec.nodeName}) | ||
mac=$(kubectl get pod "$podName" -n "$namespace" -o jsonpath={.metadata.annotations.ovn\\.kubernetes\\.io/mac_address}) | ||
hostNetwork=$(kubectl get pod "$podName" -n "$namespace" -o jsonpath={.spec.hostNetwork}) | ||
fi | ||
|
||
if [ -z "$nodeName" ]; then | ||
echo "Pod $namespacedPod not exists on any node" | ||
exit 1 | ||
fi | ||
|
||
if [ -z "$mac" ] && [ "$hostNetwork" != "true" ]; then | ||
echo "pod mac address not ready" | ||
exit 1 | ||
fi | ||
|
||
ovnCni=$(kubectl get pod -n $KUBE_OVN_NS -o wide| grep kube-ovn-cni| grep "$nodeName" | awk '{print $1}') | ||
if [ -z "$ovnCni" ]; then | ||
echo "kube-ovn-cni not exist on node $nodeName" | ||
exit 1 | ||
fi | ||
|
||
if [ "$hostNetwork" = "true" ]; then | ||
set -x | ||
kubectl exec -it "$ovnCni" -n $KUBE_OVN_NS -- tcpdump -nn "$@" | ||
else | ||
nicName=$(kubectl exec -it "$ovnCni" -n $KUBE_OVN_NS -- ovs-vsctl --data=bare --no-heading --columns=name find interface mac_in_use="${mac//:/\\:}" | tr -d '\r') | ||
if [ -z "$nicName" ]; then | ||
echo "nic doesn't exist on node $nodeName" | ||
exit 1 | ||
fi | ||
set -x | ||
kubectl exec -it "$ovnCni" -n $KUBE_OVN_NS -- tcpdump -nn -i "$nicName" "$@" | ||
fi | ||
} | ||
|
||
trace(){ | ||
namespacedPod="$1" | ||
namespace=$(echo "$1" | cut -d "/" -f1) | ||
podName=$(echo "$1" | cut -d "/" -f2) | ||
if [ "$podName" = "$1" ]; then | ||
echo "namespace is required" | ||
exit 1 | ||
fi | ||
|
||
podIP=$(kubectl get pod "$podName" -n "$namespace" -o jsonpath={.metadata.annotations.ovn\\.kubernetes\\.io/ip_address}) | ||
mac=$(kubectl get pod "$podName" -n "$namespace" -o jsonpath={.metadata.annotations.ovn\\.kubernetes\\.io/mac_address}) | ||
ls=$(kubectl get pod "$podName" -n "$namespace" -o jsonpath={.metadata.annotations.ovn\\.kubernetes\\.io/logical_switch}) | ||
hostNetwork=$(kubectl get pod "$podName" -n "$namespace" -o jsonpath={.spec.hostNetwork}) | ||
|
||
if [ "$hostNetwork" = "true" ]; then | ||
echo "Can not trace host network pod" | ||
exit 1 | ||
fi | ||
|
||
if [ -z "$ls" ]; then | ||
echo "pod address not ready" | ||
exit 1 | ||
fi | ||
|
||
gwMac=$(kubectl exec -it ovn-central-8ddc7dd8-fm2c4 -n $KUBE_OVN_NS -- ovn-nbctl --data=bare --no-heading --columns=mac find logical_router_port name=ovn-cluster-"$ls" | tr -d '\r') | ||
|
||
if [ -z "$gwMac" ]; then | ||
echo "get gw mac failed" | ||
exit 1 | ||
fi | ||
|
||
dst="$2" | ||
if [ -z "$dst" ]; then | ||
echo "need a target ip address" | ||
exit 1 | ||
fi | ||
|
||
type="$3" | ||
|
||
case $type in | ||
icmp) | ||
set -x | ||
kubectl exec "$CENTRAL_POD" -n $KUBE_OVN_NS -- ovn-trace --ct=new "$ls" "inport == \"$podName.$namespace\" && ip.ttl == 64 && icmp && eth.src == $mac && ip4.src == $podIP && eth.dst == $gwMac && ip4.dst == $dst" | ||
;; | ||
tcp|udp) | ||
set -x | ||
kubectl exec "$CENTRAL_POD" -n $KUBE_OVN_NS -- ovn-trace --ct=new "$ls" "inport == \"$podName.$namespace\" && ip.ttl == 64 && eth.src == $mac && ip4.src == $podIP && eth.dst == $gwMac && ip4.dst == $dst && $type.src == 10000 && $type.dst == $4" | ||
;; | ||
*) | ||
echo "type $type not supported" | ||
echo "kubectl ko trace {namespace/podname} {target ip address} {icmp|tcp|udp} [target tcp or udp port]" | ||
;; | ||
esac | ||
} | ||
|
||
getOvnCentralPod(){ | ||
centralPod=$(kubectl get pod -n $KUBE_OVN_NS | grep ovn-central | head -n 1 | awk '{print $1}') | ||
if [ -z "$centralPod" ]; then | ||
echo "ovn-central not exists" | ||
exit 1 | ||
fi | ||
CENTRAL_POD=$centralPod | ||
} | ||
|
||
if [ $# -lt 1 ]; then | ||
showHelp | ||
exit 0 | ||
else | ||
subcommand="$1"; shift | ||
fi | ||
|
||
getOvnCentralPod | ||
|
||
case $subcommand in | ||
nbctl) | ||
kubectl exec "$CENTRAL_POD" -n $KUBE_OVN_NS -- ovn-nbctl "$@" | ||
;; | ||
sbctl) | ||
kubectl exec "$CENTRAL_POD" -n $KUBE_OVN_NS -- ovn-sbctl "$@" | ||
;; | ||
tcpdump) | ||
tcpdump "$@" | ||
;; | ||
trace) | ||
trace "$@" | ||
;; | ||
*) | ||
showHelp | ||
;; | ||
esac |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,41 @@ | ||
Kube-OVN provides a kubectl plugin to help better diagnose container network. You can use this plugin to tcpdump a specific pod, trace a specific packet or query ovn-nb/ovn-sb. | ||
|
||
# Prerequisite | ||
|
||
To enable kubectl plugin, kubectl version of 1.12 or later is recommended. You can use `kubectl version` to check the version. | ||
|
||
# Install | ||
|
||
1. Get the `kubectl-ko` file | ||
```bash | ||
wget https://github.com/alauda/kube-ovn/blob/master/dist/images/kubectl-ko | ||
``` | ||
|
||
2. Move the file to one of $PATH directories | ||
```bash | ||
mv kubectl-ko /usr/local/bin/kubectl-ko | ||
``` | ||
|
||
3. Add executable permission to `kubectl-ko` | ||
```bash | ||
chmod +x /usr/local/bin/kubectl-ko | ||
``` | ||
|
||
4. Check if the plugin is ready | ||
```bash | ||
[root@kube-ovn01 ~]# kubectl plugin list | ||
The following compatible plugins are available: | ||
|
||
/usr/local/bin/kubectl-ko | ||
``` | ||
|
||
# Usage | ||
|
||
```bash | ||
kubectl ko {subcommand} [option...] | ||
Available Subcommands: | ||
nbctl [ovn-nbctl options ...] invoke ovn-nbctl | ||
sbctl [ovn-sbctl options ...] invoke ovn-sbctl | ||
tcpdump {namespace/podname} [tcpdump options ...] capture pod traffic | ||
trace {namespace/podname} {target ip address} {icmp|tcp|udp} [target tcp or udp port] | ||
``` |