Move Nic to Container

Move Nic to Container

Move Nic to Container
Page content

将网卡通过网络名称空间分配给容器

将网卡通过网络名称空间分配给容器后,该网卡在主机不可见,容器使用none网络 分配后需要在容器中配置默认路由。

#!/usr/bin/env bash
#
# 1. get eth0 device
# 2. get eth0/eth1 ips
# 3. link ns
# 4. set ip and route
#
CONTAINER_NAME=containerName
CONTAINER_IP=
HOST_IP=

CONTAINER_NIC=
HOST_NIC=

getDeviceNameAndIndex() {
  while read name; do
    readlink /sys/class/net/$name | grep -wv 'virtual' > /dev/null
    [[ $? -eq 0 ]] && dev=`echo ${name}` && idx=`cat /sys/class/net/$name/ifindex`
    [[ $? -eq 0 ]] && echo -n "$dev $idx "
  done < <(ls -1 /sys/class/net/)
  echo
}

# getDeviceNameAndIndex

dev1=`getDeviceNameAndIndex | awk '{print $1,$2,$3,$4}' | awk '{print $1}'`
idx1=`getDeviceNameAndIndex | awk '{print $1,$2,$3,$4}' | awk '{print $2}'`
dev2=`getDeviceNameAndIndex | awk '{print $1,$2,$3,$4}' | awk '{print $3}'`
idx2=`getDeviceNameAndIndex | awk '{print $1,$2,$3,$4}' | awk '{print $4}'`

if [[ ! -z $dev1 ]] && [[ ! -z $dev2 ]]
then
  if [[ $idx1 -lt $idx2 ]]; then
    echo "Primary nic is: $dev1"
    echo "Secondary nic is: $dev2"
    CONTAINER_IP=`ifconfig $dev1 | grep -w 'inet' | awk '{print $2}'`
    HOST_IP=`ifconfig $dev2 | grep -w 'inet' | awk '{print $2}'`
    CONTAINER_NIC=$dev1
    HOST_NIC=$dev2
    echo "containerNIC: $CONTAINER_NIC containerIP: $CONTAINER_IP hostNIC: $HOST_NIC hostIP: $HOST_IP"
  else
    echo "Primary nic is: $dev2"
    echo "Secondary nic is: $dev1"
    CONTAINER_IP=`ifconfig $dev2 | grep -w 'inet' | awk '{print $2}'`
    HOST_IP=`ifconfig $dev1 | grep -w 'inet' | awk '{print $2}'` CONTAINER_NIC=$dev2
    HOST_NIC=$dev1
    echo "containerNIC: $CONTAINER_NIC containerIP: $CONTAINER_IP hostNIC: $HOST_NIC hostIP: $HOST_IP"
  fi
else
  echo "There are not two NICs."
  exit 1
fi

if [ -z $CONTAINER_NIC ] || [ -z $HOST_NIC ]
then
  exit 1
fi

# Get container PID
CONTAINER_PID=`docker inspect -f '{{.State.Pid}}' $CONTAINER_NAME` || exit $?

# Purge the ip address in host primary nic which will be moved into container
ifconfig $CONTAINER_NIC 0

# Create net namespace root dir
mkdir -p /var/run/netns || exit $?

# Associate net namespace
[ -f /var/run/netns/${CONTAINER_PID} ] \
  || ln -s /proc/${CONTAINER_PID}/ns/net /var/run/netns/${CONTAINER_PID} \
  || exit $?

echo containerNIC=$CONTAINER_NIC hostNIC=$HOST_NIC

# Delete the default bridge NIC created by docker
ip netns exec $CONTAINER_PID ip link delete dev eth0

# Move primary NIC into container.
ip link set dev $CONTAINER_NIC name $CONTAINER_NIC netns $CONTAINER_PID || exit $?

sleep 5

MOVED_NIC=`ip netns exec $CONTAINER_PID ls -1 /sys/class/net/ | grep -vw lo`
echo "MOVED_NIC=$MOVED_NIC"

# make sure the NIC name in container is eth0
if [ "${MOVED_NIC}" != "${CONTAINER_NIC}" ]
then
  ip netns exec $CONTAINER_PID ip link set dev $MOVED_NIC name $CONTAINER_NIC
  #ip netns exec 1776 ip link set dev ens5 name eth0
else
 echo "NIC in container is: $MOVED_NIC"
fi

# Assign eth0's ip in host to container
ip netns exec $CONTAINER_PID ip addr add ${CONTAINER_IP}/26 dev $CONTAINER_NIC || exit $?
# Bring up moved interface
ip netns exec $CONTAINER_PID ip link set $CONTAINER_NIC up || exit $?

GATEWAY=172.20.2.2
BROADCAST=172.20.2.192

# Add default route
ip netns exec $CONTAINER_PID ip route add default via $GATEWAY dev $CONTAINER_NIC || exit $?
ip netns exec $CONTAINER_PID ip route add ${BROADCAST}/26 dev $CONTAINER_NIC proto kernel scope link src $CONTAINER_IP \
  || exit $?