计算机中所有程序都要寄托一个环境运行,环境可以理解为一个程序运行所需要的条件的集合;如果只是为了写一个Java程序,它是单进程的,那么我们配置jdk、jre就可以了;如果写一个网站,有前后端、数据库服务、缓存服务等各种服务,它们都要跑在不同的端口乃至不同的服务器上,配置环境让他们可以协同运作就会变得稍微复杂一些了,所以有时候配环境真的是比较麻烦的过程;本篇文章将会介绍一个分布式环境配置 —— Spark + Hadoop。
由于 Spark和Hadoop通常都运行于分布式环境,有主从节点,因此一般在Linux服务器集群进行分布式生产环境部署,但很多人在学习时可能是没有多台服务器可以练手的,这时通常会选择用虚拟化的技术实现分布式,这里的选择就包括了虚拟机和Docker。
Docker vs 虚拟机
虚拟机就是用系统镜像去创建,虚拟出硬件资源直接跑一个完整的操作系统,虚拟机运行时你的电脑硬件资源被拆分后跑两个操作系统,配置分布式多节点就要跑多个完整的操作系统,想必性能受限;
Docker是一个沙箱环境, 它在宿主机内核的基础上虚拟出了一个操作系统,更适合对不同应用的隔离,隔离程度没有虚拟机高,不用内核,没那么占据存储空间。
再看看我们的需求,只需要虚拟出多个节点进行Hadoop和Spark的实验,不需要考虑真实的集群生产环境,没必要虚拟完整的操作系统,因此选择用Docker来部署本地的分布式环境。当然,更直观的一个原因是,Docker在内存和存储的消耗比虚拟机小得多,本地实验更友好。
Docker 镜像
首先拉一个docker的centos7镜像(确保已经装了docker),发现只有200M,和虚拟机上运行的5G镜像差了20多倍,原因前面提及过,操作系统是内核加文件系统,而Docker容器运行使用的是宿主机的内核,因此Docker镜像仅包含了挂载在宿主机内核上的根文件系统,叫做Union FS,它是适配了Docker分层结构的一个文件系统。Linux中的根文件系统是文件系统特殊的一种,通常在操作系统启动阶段加载到内存中,挂载了根文件系统才能逻辑性的去访问磁盘,才能去使用基本的shell命令,才能去加载一些系统的配置文件。文件系统就是为了硬件能与用户交互产生的,因此我们在开启一个有根文件系统的容器时,也觉得像在使用一个完整的操作系统。
镜像是只读的,容器相当于“实例化”镜像,它记录了对镜像的修改,可以在当前镜像的基础上叠加修改内容构建出一个新的镜像,由于是分层模式,一个镜像应该尽量简洁仅包含当前环境,删除掉一些无关数据;构建一个新镜像常用的两种方法是commit和Dockerfile,commit是基于当前容器构建镜像,构建出来的镜像像一个黑箱,Dockerfile是从头开始根据一行行指令去构建新镜像,逻辑更加清晰。
启动容器
$ docker # 确认Docker可以正常运行
$ docker pull centos:centos7 # 拉镜像
$ docker image ls