工作站的容器化和虚拟化实践
2018-03-07 22:39
1021 查看
1. 环境说明
对于一个配置略高的工作站如果一个人使用有点浪费了,可以考虑把资源分享给小组成员,大家时分复用或者资源复用可以有效的提高生产力,现在容器化和虚拟技术为我们提供了这样的方式,并且可以很方便的管理和分配。Windows 10 已经可以很好的实现工作站级别的容器和虚拟化,比如 Hyper-V 与 Docker for Windows 的组合,但是从容器的效率来讲,还是采用 Linux 平台比较精彩。下面来记录一下我将自己的工作站容器化(Docker)和虚拟化(KVM)的实践过程。相对于服务器级别的容器化和虚拟化,在工作站上面要轻松许多,因为毕竟工作站的主要用途是开发的调试和测试,对服务的稳定性和安全性都和服务器不再一个等级上,可以大胆的使用社区版的软件,可以大胆的手动解决开源软件中的Bug .
首先需要一个用着顺手的 Linux 发行版,从安装的便捷性和大众性考虑我这里使用 Ubuntu 16.04 作为本次实践的宿主操作系统(host). 使用下面命令检测以下工作站硬件是否支持虚拟化:
egrep '(vmx|svm)' /proc/cpuinfo
然后是网络连接方式,一个人使用的工作站生成的虚拟机或者容器可以采用NAT的方式,这样比较安全,也是很多虚拟化软件的默认网络配置,但如果想把宿主主机生成的容器和虚拟机分享给组织内的其他成员,就需要使用网桥(bridge)的方式来连接host生成的容器和虚拟机,下面是需要实现的工作站网络连接示意图:
安全提示:修改网络操作可能会导致工作站不可远程访问,配置时请尽可能使用本地显示器+本地键盘的方式进行
Ubuntu 16.04默认情况下有线网卡的命名是 enp3sxx 的格式,把它还原成 eth0 的命名方式。在 /etc/default/grub 中,GRUB_CMDLINE_LINUX里添加参数net.ifnames=0 biosdevname=0,sudo方式执行下面命令:
echo "GRUB_CMDLINE_LINUX=\"net.ifnames=0 biosdevname=0\"" >> /etc/default/grub && update-grub
安装 bridge-utils 网桥管理工具
apt-get install bridge-utils
停止使用 NetworkManager 自动化网络配置工具,因为我们要使用纯手动的方式(networking)来管理网络配置:
systemctl stop NetworkManager && systemctl disable NetworkManager
手动修改网络配置文件 /etc/network/interfaces
auto lo iface lo inet loopback auto eth0 iface eth0 inet loopback auto br0 iface br0 inet static address /*YOUR_HOST_IP_ADDRESS*/ netmask /*YOUR_HOST_NET_MASK*/ gateway /*YOUR_HOST_GATEWAY*/ dns-nameservers /*YOUR_HOST_DNS*/ bridge_stp off bridge_fd 0 bridge_ports eth0
保存文件并重启(reboot)后通过 ifconfig 或者 ls /proc/sys/net/ipv4/conf 看到生成的网桥配置
如果出现问题,可以通过 systemctl status networking 或者 journalctl -xe 查看日志排除问题。
2. 容器化
Docker CE 的安装这里就不去赘述了,可以参考这个链接: https://docs.docker.com/install/linux/docker-ce/ubuntu/如果是Nvidia显卡的主机,建议安装 nvidia-docker 插件 https://github.com/NVIDIA/nvidia-docker ,使用 nvidia-container-runtime 可以将硬件GPU映射到容器内,对于视频处理和深度学习的容器非常有用。
Docker CE 默认情况下容器是不能直接暴露到真实网络中的,这时你需要docker工程师自己写的一个脚本 pipework
wget -P /usr/local/bin/ \ https://raw.githubusercontent.com/jpetazzo/pipework/master/pipework
Docker CE 只提供了命令行的访问和控制方式,掌握CLI(command line interface)的方式是必须的,但对于多人协作时,还是WBI(web interface)的方式比较靠谱,综合对比了几种 Docker web UI 的软件( DockerUI, Shipyard, Portainer ),最后还是觉得 Portainer 比较适合工作站上面部署,首先把 portainer 的镜像 pull 到本地:
docker pull portainer/portainer
通过下面命令查看 portainer/portainer 镜像需要映射的 port 和需要挂载的 volume :
image="portainer/portainer" docker inspect ${image} | jq -r '.[0].ContainerConfig.Volumes' docker inspect ${image} | jq -r '.[0].ContainerConfig.ExposedPorts'
下面描述三种部署 Portainer 的方式:
1. 以 Docker container 的方式运行:
docker run -d \ --name portainer \ --privileged=true \ --restart=always \ -p 9000:9000 \ -v /data/volume/portainer-data:/data \ -v /var/run/docker.sock:/var/run/docker.sock \ portainer/portainer
2. 以 Docker service 的方式运行:
docker swarm init docker service create \ --name portainer \ --publish 9000:9000 \ --constraint 'node.role == manager' \ --mount type=bind,src=//var/run/docker.sock,dst=/var/run/docker.sock \ --mount type=bind,src=//data/volume/portainer-data,dst=/data \ portainer/portainer \ -H unix:///var/run/docker.sock
3. 以系统服务的方式运行:
新建并编辑文件 /etc/systemd/system/docker-portainer.service :
[Unit] Description=Docker portainer Server After=docker.service Requires=docker.service [Service] ExecStartPre=/usr/bin/docker kill portainer ExecStartPre=/usr/bin/docker rm portainer ExecStart=/usr/bin/docker run --name portainer --privileged=true -v /data/volume/portainer-data:/data -v /var/run/docker.sock:/var/run/docker.sock portainer/portainer ExecStartPost=/usr/local/bin/pipework br0 portainer YOUR_IP_ADDRESS/YOUR_NET_MASK@YOUR_GATEWAY ExecStop=/usr/bin/docker stop portainer [Install] WantedBy=multi-user.target
然后启动服务:
systemctl start docker-portainer.service systemctl enable docker-portainer.service
第3种方法的优点是:我们可以通过将容器封装成系统服务的同时,在容器启动后自动执行 pipework 将容器的网络映射到真实网络中。
下面是 portainer 容器运行后的截图,管理工作站的 docker 服务非常方便并且一目了然。
在这里填一个小坑,默认情况下使用 ‘docker exec -it xxx bash’ 进入一个容器时,默认打开的terminal大小是 80X24 的分辨率,使用起来非常不方便,与自己的显示器极不协调,尤其是想在容器内使用 tmux 的情况,在 stackoverflow 上找到了一种解决方法,把下面代码加入到 ~/.bashrc 文件中,然后 srouce ~/.bashrc 使其生效:
# docker 容器 tty 默认分辨率修改 docker-inside(){ docker exec -it $1 bash -c "stty cols $COLUMNS rows $LINES && bash"; } export -f docker-inside
使用 stty 将进入的容器的 terminfo 参数修改成当前 shell 相同的行数和列数,使用起来非常方便。
3. 虚拟化
虚拟组件的系统堆栈是这样子的:下面来描述虚拟化的实践过程,Ubuntu 发行版的内核中已经默认挂载了 KVM 模块:
lsmod | grep kvm
所以我们只需要安装 libvirtd 服务,通过 libvirtd 服务与 libvirt API 通信来管理和控制虚拟机的运行。
Libvirtd 是一个 daemon 进程,可以被本地的virsh调用,也可以被远程的virsh调用
Libvirtd 调用 qemu-kvm 操作KVM 虚拟机
安装必要的虚拟化组件:
apt-get install kvm libvirt-bin bridge-utils sasl2-bin
修改 libvirtd 的配置文件,使其可以远程访问:
sed -i 's/#libvirtd_opts=""/libvirtd_opts="-l"/g' /etc/default/libvirt-bin sed -i 's/#listen_tls/listen_tls/g' /etc/libvirt/libvirtd.conf sed -i 's/#listen_tcp/listen_tcp/g' /etc/libvirt/libvirtd.conf sed -i 's/#auth_tcp/auth_tcp/g' /etc/libvirt/libvirtd.conf sed -i 's/#vnc_listen/vnc_listen/g' /etc/libvirt/qemu.conf
重新启动 libvirtd 服务:
systemctl daemon-reload systemctl restart libvirtd
创建一个可以远程访问 libvirtd 的用户:
saslpasswd2 -a libvirt aggresss
查看用户列表:
sasldblistusers2 -f /etc/libvirt/passwd.db
删除一个可以远程访问 libvirtd 的用户:
saslpasswd2 -a libvirt -d aggresss
测试 libvirtd 服务是否可以远程访问:
virsh -c qemu+tcp://localhost/system nodeinfo
创建虚拟机的磁盘空间(参考命令,请根据自己的磁盘结构自行划分):
lvcreate -L 200G -n lv-virt vgpool mkfs.ext4 /dev/vgpool/lv-virt blkid vim /etc/fstab mount -a
理论上现在就可以使用 virsh 来管理虚拟机了,就像CLI模式下的 docker命令,但是 virsh 命令要比 docker 命令复杂很多,而且用它来创建虚拟机的参数文件需要使用 xml 格式,如果没有可视化的管理工具,实施起来将非常耗时,如果不需要远程管理虚拟机,virt-manager 是一个不错的轻量化管理工具,同时还有很多支持 KVM 的管理工具,可以在这个链接里选择: https://www.linux-kvm.org/page/Management_Tools
管理工具的配置可能比较繁琐,而且管理工具可能会更换,所以我的原则是管理工具尽量不运行在宿主主机的环境下,一个更好的方式是将管理工具容器化,达到一个用过即抛的效果,同时也便于迁移和数据管理,经过筛选最后使用 webvirtmgr 来通过WBI的方式管理虚拟服务,并且将 webvirtmgr 容器化到一个镜像里面,可以通过下面的 GitHub repository 构建镜像: https://github.com/aggresss/docker-webvirtmgr ,也可以使用命令直接下载镜像:
docker pull aggresss/docker-webvirtmgr
运行镜像:
docker run -d \ --name webvirtmgr \ --privileged=true \ --restart=always \ -p 8080:8080 \ -p 6080:6080 \ aggresss/webvirtmgr
webvirtmgr 从2016年就没有更新了,GitHub 上的 Issues 和 Pull requests 也没有人处理,所以作为工作站的虚拟机管理还勉强能用,遇到 Bug 需要自行解决了。
webvirtmgr 在创建网络时不能创建本地的网桥网络,会提示 “The pool bridge name must not contain any special characters” 的 Bug,需要手动将本地网桥添加到 libvirtd 服务的配置文件中:
创建一个xml文件,比如 host-bridge.xml ,内容如下:
<network> <name>host-bridge</name> <forward mode="bridge"/> <bridge name="br0"/> </network>
然后执行:
virsh net-define ./host-bridge.xml virsh net-autostart host-bridge virsh net-start host-bridge
webvirtmgr 默认通过 noVNC 的方式远程控制Guest主机,下面是运行截图:
4. 总结
将工作站容器化和虚拟化的过程记录了下来,方便大家填坑,感谢参考文档中各位大神的文章的帮助,在这里表示真诚的感谢。欢迎各位提出指导意见。参考文档
Docker网络详解及pipework源码解读与实践Advanced Docker Networking with Pipework
KVM 介绍(5):libvirt 介绍 [ Libvrit for KVM/QEMU ]
CentOS7.2部署KVM虚拟机
libvirt.org -> Network XML format
通过noVNC和websockify连接到QEMU/KVM
相关文章推荐
- 每周运行30万个容器实例 - Netflix 的容器化实践
- 虚拟化实践之一:基于ISCSI网络共享磁盘测试实验
- 虚拟化项目之运维实践 1
- KVM虚拟化主机HA功能实践 推荐
- Coding-Job:从研发到生产的容器化融合实践
- 虚拟化项目之运维实践2
- 有容云:微服务架构最佳实践课堂PPT- 微服务容器化的挑战和解决之道
- linux系统中轻量级内核虚拟化技术LXC安装部署实践
- 计算机专业找工作面试面经总结(操作系统,数据库,数据结构,算法,虚拟化,编程实践等)
- 图形工作站也虚拟化,立即让你的工作站也可以远程访问
- 将Node.js项目docker容器化并纳入kubernetes调度编排的实践
- 【VMware虚拟化解决方案】vmware P2V迁移同步实践
- 虚拟化项目运维实践
- 苏州工业园区地税局:虚拟化重在实践
- 虚拟化项目之运维实践 3
- Linux 虚拟化实践之KVM
- 虚拟化项目之运维实践 4
- KVM虚拟化技术实践
- 云计算实践之虚拟化技术介绍
- 每周运行30万个容器实例 - Netflix 的容器化实践