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常用命令
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列表中移除
# 创建两台机器 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通
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实践
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
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 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链接两个容器
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之后,可以直接通过容器名字访问该容器
# 首先删除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
# -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为例
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
没有独立的network namespace,与主机共享network namespace,可能会出现端口冲突
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 访问容器,用来存储密码等敏感信息
# 创建一个容器,使用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