3.2. 安装 Vagrant 和概念介绍
安装步骤如下
- 下载 VirtualBox, 因为 VMWare 是收费的, Vagrant 不允许我们使用破解版, 有版权问题
- 安装 VirtualBox
- 下载 Vagrant, 地址是
https://releases.hashicorp.com/vagrant/2.2.7/vagrant_2.2.7_x86_64.msi
- 安装 Vagrant
- 考虑到大家网络比较慢, 已经将下载过的 Vagrant 相关的安装包放在了
Files/Setup
中
Vagrant 中的概念
作用: 帮助我们管理虚拟机, 自动化的创建虚拟机, 自动化的初始化虚拟机, 提供了命令帮助我们管理虚拟机
- Vagrantfile, 这个文件是虚拟机的配置文件
vagrant up
, 使用这个命令, 即可创建一个符合 Vagrantfile 配置的虚拟机- Provision, 当 Vagrant 建立虚拟机后, 会执行通过 Provision 配置的自动化脚本, 自动化的安装服务
Vagrant 初体验, 创建一个虚拟机
步骤
- 编写脚本, 配置虚拟机
- 定义 Vagrant 配置
- 新增一台虚拟机的配置
- 配置虚拟机所使用的操作系统
- 配置网络
- 配置虚拟机的硬件配置
- 执行命令创建虚拟机
- 登入虚拟机, 查看同步的目录
- 编写脚本
Vagrant.configure("2") do |config| config.vm.define "edge" do |config| config.vm.box = 'centos/7' config.disksize.size = '50GB' config.vm.network 'private_network', ip: '192.168.56.101' config.vm.hostname = 'edge' config.vm.provider 'virtualbox' do |vb| vb.gui = false vb.name = 'edge' vb.memory = 2048 vb.cpus = 1 vb.customize ["modifyvm", :id, "--cpuexecutioncap", "50"] end end end
在脚本所在目录执行命令
# 因为用到了修改磁盘大小的插件, 需要安装 vagrant plugin install vagrant-disksize # 建立虚拟机 vagrant up
登入虚拟机, 查看同步的目录
# 登录 vagrant ssh edge # 查看同步的目录 cd /vagrant
Vagrant 还有一个很强大的功能, 就是在创建虚拟机完毕时, 执行初始化任务
- 关闭已经创建的虚拟机
vagrant destroy
编写脚本
Vagrant.configure("2") do |config| config.vm.define "edge" do |config| config.vm.box = 'centos/7' config.disksize.size = '50GB' config.vm.network 'private_network', ip: '192.168.56.101' config.vm.hostname = 'edge' config.vm.provider 'virtualbox' do |vb| vb.gui = false vb.name = 'edge' vb.memory = 2048 vb.cpus = 1 vb.customize ["modifyvm", :id, "--cpuexecutioncap", "50"] end config.vm.provision "shell", path: "script.sh" end end
- 编写 Shell 脚本
echo "Hello everyone"
- 运行查看
vagrant up
目前, 除了 Shell 的 Provision, Vagrant 还支持 Ansible, Chef, Docker, Puppet 等
3.3. 使用 Vagrant 构建一个虚拟机集群
接下来, 要使用 Vagrant 构建一个集群了, 在开始之前, 根据我们的情况, 要规划一下集群
主机名 | 角色 | 配置 |
master01 | Master | 1 cores, 16G -> 6G, 32G -> 8G |
workder 01 - 02 | Worker | 1 cores, 16G -> 4G, 32G -> 5G |
- 如果只有 8G 内存, 建议去下载 Cloudera quick start vm
- Cloudera CDH 的每一个服务的内存配置, 是按照比例来的
然后, 进行集群搭建
- 编写脚本
Vagrant.configure("2") do |config| config.vm.define "master01" do |master01| master01.vm.box = 'centos/7' master01.disksize.size = '50GB' master01.vm.network 'private_network', ip: '192.168.56.101' master01.vm.hostname = 'master01' master01.vm.provider 'virtualbox' do |vb| vb.gui = false vb.name = 'master01' vb.memory = 6000 vb.cpus = 1 vb.customize ["modifyvm", :id, "--cpuexecutioncap", "50"] end end config.vm.define "worker01" do |worker01| worker01.vm.box = 'centos/7' worker01.disksize.size = '50GB' worker01.vm.network 'private_network', ip: '192.168.56.102' worker01.vm.hostname = 'worker01' worker01.vm.provider 'virtualbox' do |vb| vb.gui = false vb.name = 'worker01' vb.memory = 2048 vb.cpus = 1 vb.customize ["modifyvm", :id, "--cpuexecutioncap", "50"] end end config.vm.define "worker02" do |worker02| worker02.vm.box = 'centos/7' worker02.disksize.size = '50GB' worker02.vm.network 'private_network', ip: '192.168.56.103' worker02.vm.hostname = 'worker02' worker02.vm.provider 'virtualbox' do |vb| vb.gui = false vb.name = 'worker02' vb.memory = 2048 vb.cpus = 1 vb.customize ["modifyvm", :id, "--cpuexecutioncap", "50"] end end config.vm.define "edge" do |edge| edge.vm.box = 'centos/7' edge.disksize.size = '50GB' edge.vm.network 'private_network', ip: '192.168.56.104' edge.vm.hostname = 'edge' edge.vm.provider 'virtualbox' do |vb| vb.gui = false vb.name = 'edge' vb.memory = 1024 vb.cpus = 1 vb.customize ["modifyvm", :id, "--cpuexecutioncap", "50"] end end end
运行集群
vagrant up
这个时候, 我们已经建立起来了测试集群, 但是有一个问题, 似乎无法在外部登录
- 使用 MobaXterm 使用 SSH 登录虚拟机
- 发现无法登录
原因是, Vagrant 自动创建出来的虚拟机是关闭了 SSH 登录功能的, 只能使用 vagrant ssh 登录, 这是为了保障安全性, 但是测试集群的话, 其实我们还是需要它方便, 解决办法也很简单, 修改 SSH 配置, 再打包一下系统, 让 Vagrant 下次创建的时候使用我们修改过的系统
修改 SSH 登录
# 修改文件 /etc/ssh/sshd_config PasswordAuthentication no
- 打包
vagrant package
- 脚本中使用
Vagrant.configure("2") do |config| config.ssh.password = "vagrant" # 此处使用密码登录 config.vm.define "master01" do |master01| master01.vm.box = './pkgs/package.box' # 此处引用打包好的 box master01.disksize.size = '50GB' master01.vm.network 'private_network', ip: '192.168.56.101' master01.vm.hostname = 'master01' master01.vm.provider 'virtualbox' do |vb| vb.gui = false vb.name = 'master01' vb.memory = 6000 vb.cpus = 1 vb.customize ["modifyvm", :id, "--cpuexecutioncap", "50"] end end config.vm.define "worker01" do |worker01| worker01.vm.box = './pkgs/package.box' worker01.disksize.size = '50GB' worker01.vm.network 'private_network', ip: '192.168.56.102' worker01.vm.hostname = 'worker01' worker01.vm.provider 'virtualbox' do |vb| vb.gui = false vb.name = 'worker01' vb.memory = 2048 vb.cpus = 1 vb.customize ["modifyvm", :id, "--cpuexecutioncap", "50"] end end config.vm.define "worker02" do |worker02| worker02.vm.box = './pkgs/package.box' worker02.disksize.size = '50GB' worker02.vm.network 'private_network', ip: '192.168.56.103' worker02.vm.hostname = 'worker02' worker02.vm.provider 'virtualbox' do |vb| vb.gui = false vb.name = 'worker02' vb.memory = 2048 vb.cpus = 1 vb.customize ["modifyvm", :id, "--cpuexecutioncap", "50"] end end config.vm.define "edge" do |edge| edge.vm.box = './pkgs/package.box' edge.disksize.size = '50GB' edge.vm.network 'private_network', ip: '192.168.56.104' edge.vm.hostname = 'edge' edge.vm.provider 'virtualbox' do |vb| vb.gui = false vb.name = 'edge' vb.memory = 1024 vb.cpus = 1 vb.customize ["modifyvm", :id, "--cpuexecutioncap", "50"] end edge.vm.provision "shell" do |s| s.path = "install_ansible.sh" s.privileged = true end end end
下面再次查看, 即可使用 MobaXterm 登录虚拟机
4. 自动化部署服务 (了解, 运维领域)
- 目标
- 能够通过自动化脚本安装 CM 服务
- 步骤
- 痛点和 Ansible
- 使用 Vagrant 整合 Ansible
- 离线安装 Ansible
4.1. 痛点和 Ansible
好了, 我们现在要开始安装 CM 服务了, 大概有如下步骤
- 配置好每一台机器的系统环境
- 修改主机名
- 关闭防火墙
- 关闭 SELinux
- 安装 JDK
- 安装 MySQL
- … 一上午过去了
- 在每一台机器上安装 SCM Agents
- Master 01 上下载 Agents
- Worker 01上下载 Agents
- Worker 02 上下载 Angents
- 配置 Master 01
- 配置 Worker 01
- 配置 Worker 02
- 启动 Maser 01 的 Agents
- … 一小时又过去了, 逐渐恼怒 😡
- 在 Master 01 上安装 SCM
- 创建 Linux 用户, hadoop, hive, yarn, hdfs, oozie 等所有服务都要有一个系统用户
- 创建 MySQL 用户, 大概六七个
- 安装 SCM
- 启动
- 报错
- … 一下午过去了, 老子不学习! 😡😡
- 安装 CDH …
好了, 这些痛点我们都懂, 于是引入 Ansible, Ansible 非常重要, 几乎是运维领域的银弹, 但是如果大家不打算在运维领域发展, 了解即可, Ansible 可以帮助我们做如下事情
- 上述所有步骤, Ansible 可以帮助我们以配置的形式编写
- Ansible 可以帮助我们在多台机器上执行配置文件表示的过程
Ansible 有如下概念
名称 | 解释 |
Playbook | 剧本, 是 Ansible 中的总控, 根配置文件 比如说这次运行 Ansible 的最终任务是搭建好一个 CM 集群, 那我们应该就有一个 Playbook 叫做 cm_playbook.yml |
Roles | Ansible 任务中的角色 例如为了完成 CM 集群的搭建, 可能要配置操作系统, 那应该就把配置操作系统所需要执行的所有配置都放在一个叫做 system_common 的 Roles 中 |
Inventory | Ansible 中的服务器地址配置 Ansible 需要在多个主机中执行任务, Inventory 的作用就是告诉 Ansible 主机的地址等信息 |
首先来看看 PlayBook
- name: Create hosts file in locally hosts: 192.168.56.101 any_errors_fatal: True become: yes roles: - hosts - name: Set yum locally hosts: cdh_cluster any_errors_fatal: True become: yes roles: - yum_locally
- 在
192.168.56.101
中配置 hosts 文件 - 在
cdh_cluster
所对应的机器中配置本地 Yum 仓库 cdh_cluster
是一个分组, 这个分组在Inventory
中配置
hosts
和yum_locally
就是角色
然后再来看看 Roles yum_locally
- name: Set yum repo locally yum_repository: name: itcast-locally description: Local yum repo baseurl: http://master01/ failovermethod: priority file: itcast priority: 1 gpgcheck: no enabled: yes - name: Clean yum meata command: yum clean all
- 第一个任务是通过 Ansible 提供的 Yum repository 插件, 配置本地 Yum 仓库
- 第二个任务是执行一个命令
yum clean all
清理 Yum 缓存
4.2. 使用 Vagrant 整合 Ansible
Ansible 是一个非常知名的自动化运维工具, 不仅仅只是为了搭建测试环境, 在测试环境和正式环境中, 其应用都很广泛, 先来看看在正式环境中该如何使用 Ansible
- 在 13 台机器中, 选择一台作为主控
- 在主控机器中放入 Ansible 脚本
- 执行命令运行 Ansible, Ansible 会在 Playbook 中标示的机器上运行
ansible-playbook --inventory-file=/vagrant/inventory -v /vagrant/playbooks/cdh_cm.yml
明白了如何在正式环境使用 Ansible 以后, 使用 Vagrant 搭建测试环境的时候也可以使用 Ansible 脚本, Vagrant 提供了对应的 Provision
- 编写 Ansible playbook, 文件名为
testing.yml
- hosts: worker_servers tasks: debug: msg: "Hello from {{ inventory_hostname }}"
编写 Inventory, 文件名为 inventory
[master_servers] master01 ansible_host=192.168.56.101 ansible_user=vagrant ansible_ssh_pass=vagrant [worker_servers] worker01 ansible_host=192.168.56.102 ansible_user=vagrant ansible_ssh_pass=vagrant worker02 ansible_host=192.168.56.103 ansible_user=vagrant ansible_ssh_pass=vagrant
编写 Vagrantfile
Vagrant.configure("2") do |config| config.ssh.password = "vagrant" config.vm.define "master01" do |master01| master01.vm.box = './pkgs/package.box' master01.disksize.size = '50GB' master01.vm.network 'private_network', ip: '192.168.56.101' master01.vm.hostname = 'master01' master01.vm.provider 'virtualbox' do |vb| vb.gui = false vb.name = 'master01' vb.memory = 6000 vb.cpus = 1 vb.customize ["modifyvm", :id, "--cpuexecutioncap", "50"] end end config.vm.define "worker01" do |worker01| worker01.vm.box = './pkgs/package.box' worker01.disksize.size = '50GB' worker01.vm.network 'private_network', ip: '192.168.56.102' worker01.vm.hostname = 'worker01' worker01.vm.provider 'virtualbox' do |vb| vb.gui = false vb.name = 'worker01' vb.memory = 2048 vb.cpus = 1 vb.customize ["modifyvm", :id, "--cpuexecutioncap", "50"] end end config.vm.define "worker02" do |worker02| worker02.vm.box = './pkgs/package.box' worker02.disksize.size = '50GB' worker02.vm.network 'private_network', ip: '192.168.56.103' worker02.vm.hostname = 'worker02' worker02.vm.provider 'virtualbox' do |vb| vb.gui = false vb.name = 'worker02' vb.memory = 2048 vb.cpus = 1 vb.customize ["modifyvm", :id, "--cpuexecutioncap", "50"] end end config.vm.define "edge" do |edge| edge.vm.box = './pkgs/package.box' edge.disksize.size = '50GB' edge.vm.network 'private_network', ip: '192.168.56.104' edge.vm.hostname = 'edge' edge.vm.provider 'virtualbox' do |vb| vb.gui = false vb.name = 'edge' vb.memory = 1024 vb.cpus = 1 vb.customize ["modifyvm", :id, "--cpuexecutioncap", "50"] end machine.vm.provision :ansible_local do |ansible| ansible.playbook = "testing.yml" ansible.verbose = true ansible.install = true ansible.limit = "all" # or only "nodes" group, etc. ansible.inventory_path = "inventory" end end end
- 运行查看结果
当然, 我们也可以使用 Roles 来封装一下这个任务
- 创建
roles/hello/tasks
目录 - 编写 Roles
- name: Hello debug: msg: "Hello from {{ inventory_hostname }}"
修改 Playbook
- hosts: worker_servers roles: - hello
4.3. 使用 Ansible 部署 CM
脚本已经为大家编写好了, 因为大家只需要了解这个东西, 所以, 不再深入去讲, 大家有兴趣可以自行研究
- 离线安装 Ansible
- 配置 Hosts
- 配置离线 Yum
- 离线安装 MySQL
- …
4.4. 已知问题
可以解决的问题
- 如果在部署过程中, 出现 scm 或者 scm agents 开头的错误, 可以用如下的方式解决
注释掉 cdh_cm.yml 中的前半部分代码, 在 Install cloudera agents 之前的代码都注释掉
vagrant ssh master01
密码是 vagrant
PYTHONUNBUFFERED=1 ANSIBLE_FORCE_COLOR=true ansible-playbook --limit="all" --inventory-file=/vagrant/inventory -v /vagrant/playbooks/cdh_cm.yml
成功的表现
Save import command id 开头的命令执行完成, 则意味着整个集群已经部署成功
接下来, 查看进度即可
打开 http://master01:7180
登录, 账号密码都是 admin
点击右上角1的小图标, 查看集群部署情况
- Namenode 可能格式化超时, 这是因为集群资源不够, 需要登录到 Master01 上删除
/dfs/nn
, 然后重试
- Hive 的 Metastore 和 Oozie 的数据库可能连接超时, 也是因为集群资源不够, 重试即可
- Hive 的 Schema 有可能创建失败, 同样因为集群无法并行太多任务的原因, 登入到 master01 中, 执行如下步骤
- 登入 MySQL, 删除 metastore 下所有表,
mysql -uhive -ppassword
DROP TABLE IF EXISTS BUCKETING_COLS; DROP TABLE IF EXISTS CDS; DROP TABLE IF EXISTS COLUMNS_V2; DROP TABLE IF EXISTS DATABASE_PARAMS; DROP TABLE IF EXISTS DBS; DROP TABLE IF EXISTS DB_PRIVS; DROP TABLE IF EXISTS DELEGATION_TOKENS; DROP TABLE IF EXISTS FUNCS; DROP TABLE IF EXISTS GLOBAL_PRIVS; DROP TABLE IF EXISTS IDXS; DROP TABLE IF EXISTS INDEX_PARAMS; DROP TABLE IF EXISTS MASTER_KEYS; DROP TABLE IF EXISTS NUCLEUS_TABLES; DROP TABLE IF EXISTS PARTITIONS; DROP TABLE IF EXISTS PARTITION_EVENTS; DROP TABLE IF EXISTS PARTITION_KEYS; DROP TABLE IF EXISTS PARTITION_KEY_VALS; DROP TABLE IF EXISTS PARTITION_PARAMS; DROP TABLE IF EXISTS PART_COL_PRIVS; DROP TABLE IF EXISTS PART_COL_STATS; DROP TABLE IF EXISTS PART_PRIVS; DROP TABLE IF EXISTS ROLES; DROP TABLE IF EXISTS ROLE_MAP; DROP TABLE IF EXISTS SDS; DROP TABLE IF EXISTS SD_PARAMS; DROP TABLE IF EXISTS SEQUENCE_TABLE; DROP TABLE IF EXISTS SERDES; DROP TABLE IF EXISTS SERDE_PARAMS; DROP TABLE IF EXISTS SKEWED_COL_NAMES; DROP TABLE IF EXISTS SKEWED_COL_VALUE_LOC_MAP; DROP TABLE IF EXISTS SKEWED_STRING_LIST; DROP TABLE IF EXISTS SKEWED_STRING_LIST_VALUES; DROP TABLE IF EXISTS SKEWED_VALUES; DROP TABLE IF EXISTS SORT_COLS; DROP TABLE IF EXISTS TABLE_PARAMS; DROP TABLE IF EXISTS TAB_COL_STATS; DROP TABLE IF EXISTS TBLS; DROP TABLE IF EXISTS TBL_COL_PRIVS; DROP TABLE IF EXISTS TBL_PRIVS; DROP TABLE IF EXISTS TYPES; DROP TABLE IF EXISTS TYPE_FIELDS; DROP TABLE IF EXISTS VERSION;
在 /opt/cloudera/parcels/CDH/lib/hive/conf/hive-site.xml
中加入如下
<property> <name>javax.jdo.option.ConnectionUserName</name> <value>hive</value> </property> <property> <name>javax.jdo.option.ConnectionPassword</name> <value>hive_password</value> </property> <property> <name>javax.jdo.option.ConnectionURL</name> <value>jdbc:mysql://master01:3306/metastore?useUnicode=true&characterEncoding=UTF-8</value> </property> <property> <name>javax.jdo.option.ConnectionDriverName</name> <value>com.mysql.jdbc.Driver</value> </property>
执行任务初始化 Hive metastore
/opt/cloudera/parcels/CDH/lib/hive/bin/schematool -dbType mysql -initSchema
- Ansible 执行可能在最后一步失败, 这是因为导入 CDH 集群是一件耗时的工作, 重试的时间不够, 这个问题无需理会, 登录
master01:7180
查看集群状态即可, 默认账号和密码都是admin
如果实在是机器的资源有限, 运行速度很慢, 或者无法执行 Yarn 任务, 有以下两种做法
- 关闭 SCM 有关服务, 只留下 Hadoop 相关服务
systemctl stop cloudera-scm-agent systemctl stop cloudera-scm-server
关闭 Edge 机
vagrant destroy edge
无法解决的问题
- 因为 Master 的内存配置过低, 所以 Hue 的运行受限, 有可能在上传大文件时, 访问 Oozie 时, 会出现无响应因为集群整体资源受限, 所以执行 Oozie 任务时, 可能会出现无法调度的问题
这些问题其实并不是问题, 当给集群足够资源时, 自然会解决, 如果有 32G 的内存, 建议如下分配
- Master 01 分配 12 G
- Workers 分配 8 G