From Docker to Kubernetes(二)- Docker Network

2022-08-19 16:32:29 浏览数 (1)

Section 01 - Vagrant

Vagrant is a tool for building and managing virtual machine environments in a single workflow. With an easy-to-use workflow and focus on automation, Vagrant lowers development environment setup time, increases production parity, and makes the "works on my machine" excuse a relic of the past.

Vagrant是一个构建和管理虚拟机的工具,使用Vagrant可以非常方便的构建、启动、关闭或者复制多个相同的虚拟机环境

使用Vagrant VirtualBox可以非常快速的搭建两台或者多台虚拟机集群

参考Vagrant Getting Started

Vagrant常用命令

代码语言:javascript复制
vagrant up # 启动当前目录下Vagrantfile中设置的虚拟机
vagrant halt # 关闭虚拟机
vagrant reload # 重启虚拟机
vagrant ssh # 连接虚拟机
vagrant status # 查看虚拟机启动状态
vagrant suspend # 挂起虚拟机
vagrang destroy # 销毁当前虚拟机

vagrant reload --provision # 按照Vagrantfile配置重新启动虚拟机
vagrant up --provision # 按照其他配置启动虚拟机

vagrant init # 初始化
vagrant box list # 查看本地box列表
vagrant box add # 添加到box列表
vagrant box remove # 从boxe列表中移除
代码语言:javascript复制
# 创建两台机器 docker-node1 docker-node2
vagrant up
vagrant status
vagrant ssh docker-node1
# 修改Linux主机名
sudo hostnamectl set-hostname docker-node1
exit
vagrant ssh docker-node1
docker version
exit
vagrant ssh docker-node2
docker veresion
sudo hostnamectl set-hostname docker-node2
exit
vagrant ssh docker-node2
# 互相 ping,查看是否能够ping通

Section 02 - Docker网络

相关网络概念

  • Public IP:互联网上的唯一标识,可以访问Internet
  • Private IP:不可以在互联网上使用,仅限内部网络访问

相关网络命令

  • ping:用于验证IP的可达性
  • telnet:验证服务的可用性

Linux的网络命名空间

代码语言:javascript复制
docker run -d --name test1 busybox /bin/sh -c "while true; do sleep 3600; done"
# 进入到容器中,fb是Container ID的简写
docker exec -it fb /bin/sh
# 获取网络命名空间
ip a
# 退出容器
exit
# 创建第二个容器
docker run -d --name test2 busybox /bin/sh -c "while true; do sleep 3600; done"
# 交互式执行命令,查看网路Namespace, 25ea是Container ID的简写
docker exec -it 25ea ip a

创建容器时就会创建一个Namespace,这个Namespace跟主机的Namespace是隔离的

这是第一个网络的Namespace

第二个容器的网络命名空间

创建和管理Linux 网络的Namespace,并使两个network namespace相通 Docker Network Namespace实践

代码语言:javascript复制
vagrant up docker-node1
vagratn up docker-node2
vagrant status
vagrant ssh docker-node1
# 查看本机有的network namespace, netns是network namespace的简写
sudo ip netns list
# 删除network namespace
sudo ip netns delete test1
# 添加network namespace
sudo ip netns add test1
sudo ip netns add test2
# 查看network namespace的IP地址
sudo ip netns exec test1 ip a
# 让lo端口up
sudo ip netns exec test1 ip link set dev lo up
sudo ip link add veth-test1 type veth peer name veth-test2
ip link
# 将veth-test1添加到test1
sudo ip link set veth-test1 netns test1
sudo ip netns exec test1 ip link
# 将veth-test2添加到test2
sudo ip link set veth-test2 netns test2
sudo ip netns exec test2 ip link
# 分配 IP 地址
sudo ip netns exec test1 ip addr add 192.168.1.1/24 dev veth-test1
sudo ip netns exec test2 ip addr add 192.168.1.2/24 dev veth-test2
# 查看是否有IP地址
sudo ip netns exec test1 ip link
sudo ip netns exec test2 ip link
# 启动veth
sudo ip netns exec test1 ip link set dev veth-test1 up
sudo ip netns exec test2 ip link set dev veth-test2 up
# 查看是否有IP地址
sudo ip netns exec test1 ip a
sudo ip netns exec test2 ip a
# 执行ping,查看是否有数据传输
sudo ip netns exec test1 ping 192.168.1.2
sudo ip netns exec test2 ping 192.168.1.1
代码语言:javascript复制
sudo ip netns exec test1 ip a

  Linux container 中用到一个叫做veth的东西,这是一种新的设备,专门为 container 所建。veth 从名字上来看是 Virtual ETHernet 的缩写,它的作用很简单,就是要把从一个 network namespace 发出的数据包转发到另一个 namespace。veth 设备是成对的,一个是 container 之中,另一个在 container 之外,即在真实机器上能看到的。

  VETH设备总是成对出现,送到一端请求发送的数据总是从另一端以请求接受的形式出现。创建并配置正确后,向其一端输入数据,VETH会改变数据的方向并将其送入内核网络子系统,完成数据的注入,而在另一端则能读到此数据。(Namespace,其中往veth设备上任意一端上RX到的数据,都会在另一端上以TX的方式发送出去)veth工作在L2数据链路层,veth-pair设备在转发数据包过程中并不串改数据包内容。

两个namespace之间互相通信

Docker Bridge

代码语言:javascript复制
docker start test1
docker start test2
docker exec -it test1 ip a
docker exec -it test2 ip a
# 进入test1
docker exec -it test1 /bin/sh
# ping另外一个容器的ip
ping 172.17.0.2

Docker中是通过bridge0代替veth链接两个容器

代码语言:javascript复制
docker stop test2
docker rm test2
# 列举当前机器上的网络,test1正在运行中
docker network ls
# 查看网络详情
docker network inspect 28af3c328fe0
ip a
# 查看test1容器的网络
docker exec -it test1 ip a


# 验证veth是连到docker0上的
brctl show


# 在创建一个容器test2
docker run -d --name test2 busybox /bin/sh -c "while true; do sleep 3600; done"


docker network ls
docker network inspect bridge
# 多出了一个veth,用来与test2
brctl show
# docker0 连了两个接口
bridge name	bridge id		STP enabled	interfaces
docker0		8000.0242f0fecf55	no		vethb22ca59
                                        vethd2fffa8

下图说明test1容器连到birdge上

ip a命令展示

vethd2fffa8@if7 和 eth0@if8是一对

container 通过这一对端口可以连接到主机的网络上面及连接到了docker0上

验证veth是连接在docker0上的

docker network inspect bridge有两个容器连到了bridge网络

两个容器之间的连接方式

容器与外网通信

容器之间的Link

建立link之后,可以直接通过容器名字访问该容器

代码语言:javascript复制
# 首先删除test2
docker stop test2
doker rm test2
# 再次创建test2,通过添加--link参数, --link test1 
docker run -d --name test2 --link test1 busybox /bin/sh -c "while true; do sleep 3600; done"
# 进入容器中
docker exec -it test2 /bin/sh
# 可以用容器名字代替ip
ping test1

新建容器的网络使用自定义的网络,不使用bridge

代码语言:javascript复制
# -d bridge表示使用bridge为驱动,my-bridge为创建的网络的名字
docker network create -d bridge my-bridge
docker network ls
brctl show
# 新建一个容器,并指定使用新创建的网络
docker run -d --name test3 --network my-bridge busybox /bin/sh -c "while true; do sleep 3600; done"
# 查看容器网络
docker inpect test3
brctl show
# 已运行的容器连到具体网络
docker network connect my-bridge test2
docker inpect my-bridge

容器之间的端口映射

如果两个容器连接到同一个网络(自定义的网路,系统默认网络不可以)上面,可以通过容器名字ping通,除了通过命令行访问docker部署的应用,还有其他方式,通过暴露端口给外界(不仅仅是在docker宿主机上)提供服务,将端口映射到宿主机的端口上面。

实践,以Nginx为例

代码语言:javascript复制
docker run -d --name web nginx
docker exec -it web /bin/bash
# 容器默认连接到bridge上,通过查看bridge,确定容器的IP
docker network inspect bridge
# 确定容器的80端口是否可以访问
telnet 172.17.0.4 80
curl http://172.17.0.4
# 删除web容器,重新创建一个 容器 -p 80:80, 第一个80是容器的端口,第二个是宿主机的端口
docker run -d --name web -p 80:80 nginx
# 访问本机的80端口,显示nginx信息
curl 127.0.0.1:80

容器网络之host和none

没有独立的network namespace,与主机共享network namespace,可能会出现端口冲突

代码语言:javascript复制
docker run -d --name test2 --network host busybox /bin/sh -c "while true; do sleep 3600; done"
docker network inspect host
docker exec -it test2 /bin/bash
ip a

none网络是一个孤立的网络,只能通过docker exec -it 访问容器,用来存储密码等敏感信息

代码语言:javascript复制
# 创建一个容器,使用none网络
docker run -d --name test1 --network none busybox /bin/sh -c "while true; do sleep 3600; done"
docker network inspect none
docker exec -it test1 /bin/bash
ip a

0 人点赞