文章讲什么
本文主要讲,我是如何循序渐进地搭建一个远程开发环境,最后实现的效果是:在公司使用mac进行办公,然后通过frp转发家里台式机的端口,RDP到家里的台式windows,并且SSH直连到windows中使用vagrant管理的一套虚拟机环境,其使用体验就像是拥有了超高配置的云服务器一样。使用mac安装的 vs code 进行开发的时候,使用remote develop扩展包,直连windows开的高配ubuntu虚拟机,从此再也不用担心环境和性能的问题了。(remote develop扩展包,可以让你使用远程主机或者docker中的环境进行开发,本机的vs code此时就像是个浏览器一样,十分的方便)
备注
本文不会贴具体的代码,只是讲一下我整个的过程和思路,因为我觉得这才是最重要的东西。
背景
最近新入职了一家公司,名字就不说了。公司对保密的要求十分严格,对内外网进行了分离,并且只配发了台式机,8g、i5、机械硬盘的配置。用内网就不能访问外网,也就是一些涉及到在线安装的东西全都死翘翘了(比如咱们各种IDE在线安装插件,或者其他开发工具涉及到联网的部分)。用外网的话,文件就无法保存,相当于是开了一个还原卡系统一样的东西,所以想安装软件的唯一途径就是U盘拷贝,或者使用外网后将文件手动导出,然后在内网模式进行安装(说实话作为一个喜欢折腾的程序员,我吐了)。
于是我一直都是使用的我的mac进行工作,但是性能实在有些顶不住(内存定制的是16G),工作内容经常需要集群环境,而且编译工作很重,我只能在mac上开一堆虚拟机进行模拟,经常就风扇狂响,键盘烫手。于是我就想用远程控制我家里的台式机(i7 9700k,1T的三星Nvme固态、40G内存),将台式当作额外的云服务器来用。诞生了这个想法后,我就开始了折腾之旅。。。
如何快速搭建开发环境(windows + mac)
其实吧,由于工作内容的关系,我需要一套很重的开发环境(经常启停一套集群进行测试,各种中间件和工具一大堆),所以在使用mac的时候就折腾了很久的开发环境的搭建的问题。虽然mac号称能跑linux上的很多东西,但是实际上使用的时候,是有很多不兼容的地方的,最后依然需要真正的linux系统来进行开发,不然解决兼容性的问题就把自己烦死了(还是工作内容的原因,我没办法只用docker就组一套环境)。下面就是我折腾开发环境的过程
阶段1:mac开虚拟机
这个阶段就是很朴实的想法,哈哈。在mac装了vmware fusion,然后就是一顿熟悉的操作,安装虚拟机balabala的,这个事儿估计大家都干过,详细过程就不用多说了。
这种方式问题就很大,首先就是安装的过程,我需要手动一步一步的点击下一步,然后改虚拟机的硬件配置啥的,总之是一个经常重复而且效率低下的过程。用了几天之后我就摒弃这种方案了。
阶段2:mac使用vagrant
在阶段一之后,我找了一些资料,然后找到了vagrant。使用过这个工具之后就感觉,这才是程序员使用虚拟机的时候应该有的方式。vagrant可以使用现在主流的VM软件,比如vmware、virtualBox等,对虚拟机进行管理,也就是说,使用vagrant在命令行中开启、关闭、配置虚拟机,并且他还有一个云端的仓库,就像是dockerhub一样的东西,专门用来下载系统镜像。使用vagrant之后,你就可以通过类似于写一个DockerFile的方式,写一个VagrantFile来定义一组虚拟机(一个VagrantFile可以定义无数个虚拟机),然后根据需要,随时开启或者销毁不同的虚拟机实例,一下子就把你从手工方式启停虚拟机里解放了出来。
于是我就折腾了两天,写了一个自己满意的VagrantFile,定义了一套虚拟机环境,达到的效果就是:免密SSH、创建时自动安装了我需要的环境、hosts文件共享,静态IP,自动加入docker swarm集群。到了这个阶段之后,其实环境的问题已经基本上解决了,但是性能问题依然还在,我mac上本身也已经有一堆东西了,内存和CPU余量其实并不多,基本上开的虚拟机性能都比较垃圾,而且散热会比较吃力,所以实际使用起来体验并不好。
阶段3:windows使用vagrant + teamviewer 远程控制
mac使用vagrant已经很明显已经是个比较有效的方案了,唯一的问题就是性能不足。所以我就想到了家里的顶配台式机。于是用台式机也安装了vagrant,但是此时遇到了一个问题。
vagrant实际上是要依赖具体的虚拟机软件的,它本身其实只是一个命令行工具,负责管理而不是负责创建虚拟机。可以这么想:各个虚拟机软件其实都有命令行接口可以进行虚拟机的管理,但是各种虚拟机软件的接口使用方式都不同,而且十分复杂,所以vagrant就在各个虚拟机软件的接口上做了一层封装,我们使用vagrant进行虚拟机的管理,而vagrant则在底层去调用具体的虚拟机软件进行虚拟机的创建和管理等工作。
遇到的问题
我遇到的问题就是:win10里安装docker的时候,必须要打开hyper-v,实际上win10里的docker是运行在hyper-v模拟出来的一个linux虚拟机中的。所以要使用docker就必须打开hyper-v,但是hyper-v有一个致命的缺点,就是不与其他虚拟机软件兼容,也就是说开了hyper-v就没法使用virtualBox和VMware。而且开了hyper-v之后,win10本身其实也是运行在hyper-v里的(可以理解为:其实只有一个hyper-v,而win10是hyper-v自动开启的一个虚拟机),所以win10对网卡的控制权可能有点问题,导致使用hyper-v作为底层的vagrant,无法对虚拟机进行静态IP的设置,每次开启关闭都会变动IP,这对我们的开发环境来说实在是太麻烦了。但是我又不想放弃docker的使用,于是我又查了一些资料,加深了对docker的理解。
解决方案
解决方案:其实docker是一个C/S结构的软件,我们日常使用的是docker的cli,而真正进行容器调度的,都是docker的守护进程。显然,2个进程是需要进行通信的,或者说,只要解决了通信的问题,我们就可以使用本地的docker-cli,去链接远程的docker守护进程。在折腾之前其实我也看到过这个知识,但是并没有放心里,所以折腾了一两天竟没有想到这里。
查阅了一些资料后,我测试了2种方案
- 1种是使用docker-machine,这是docker自带的一种虚拟机方案,用docker-machine也可以创建虚拟机,然后将本地docker-cli连接到docker-machine启动的虚拟机中。但是它的功能主要是围绕docker的,所以虚拟机的管理功能比vagrant弱很多。
- 第2种则是利用docker的remote API接口,使用vagrant,修改了VagrantFile,将开启的虚拟机里安装的docker的remote API接口打开,让它能够接收外部的请求,然后将本地docker的环境变量DOCKER_HOST指向虚拟机里的docker守护进程的端口,实现了从本地对虚拟机docker进行调用的功能。
毫无疑问,我最后选了第二种方案,因为论配置虚拟机本身的话,还是vagrant比较专业。最后的效果就是windows使用vagrant开启了一系列虚拟机,然后windows本地只安装了docker-cli,windows在命令行使用docker命令的时候,自动连接虚拟机docker环境进行调用。
远程控制
完成了windows对虚拟机的管理后,剩下的就是mac怎么连的问题了,这里又一次发挥了自己朴实的思维(汗- -),开了个teamviewer远程控制,然后远程连接windows,对家里的台式机进行操作。
emm。。。其实这样也不是不可以啦,但是着实有点笨拙了。因为其实我更需要的是windows开启的虚拟机,而不是windows本身。而且teamviewer搞不好哪天就检测说商业用途了,不够稳,而且远程控制毕竟还是体验不够好。于是接着折腾,就折腾到了下面的终极方案了。
终极方案:frp转发 + vscode remote develop
这个时候面临的问题就是:我怎么不用teamviewer之类的远程桌面工具,就连接到家里的机器了。又折腾了一两天,找到了神器frp。它的作用是,使用一个具有公网IP的机器,反向代理你内网的机器,进行端口映射,最后的效果就是,访问公网的IP和端口,自动转发到内网的IP和端口,从而实现了连接内网机器的目的。
于是我就开了一个google cloud的机器,开启了frps(frp的服务端),而在家里windows上开启了frpc(frp的客户端),使用google cloud对家里的机器进行端口转发,最后再在mac上连接到google cloud的一些转发的端口上,进而连接到了家里的windows和windows里虚拟机中。windows上使用winsw工具将frpc注册为了一个服务,开机自启动,并且买了一个开机棒。可以随时在远程将机器开机和关机。
于是我现在的开发模式就是:每天上班之后将家里电脑开机,然后使用mac上的vscode直接连接家里windows开的虚拟机进行开发工作,几乎感觉不到什么延迟,因为只是命令行的传输,数据量很小,而且google cloud的延迟只有20多ms。
遇到一些偶尔可能需要GUI操作的东西,就使用frp转发的微软远程桌面端口3389,远程桌面到windows进行一些简单的操作(此类操作其实很少,所以稍微有点延迟不怎么影响体验)。
使用了这套方案之后,就再也不担心开发环境的问题,和机器性能的问题了(反正顶配台式顶得住,hh),工作起来都感觉更有趣了~~😄