本文主要介绍在不改变 Ambari 现有整体框架逻辑的情况下,管理 Docker 镜像的方法,可以像普通服务一样进行安装、启停、状态监控等功能。
测试环境
- Centos 7.4
- Ambari 2.7.1
- HDP 3.0.1.0
准备环境
安装 Docker
| 1
 | yum remove docker  docker-common docker-selinux docker-engine
 | 
| 12
 
 | systemctl start dockersystemctl enable docker
 
 | 
配置仓库
- 修改配置文件| 1
 | vim /etc/docker/daemon.json
 |  
 
| 12
 3
 4
 
 | {"registry-mirrors": ["http://10.180.XXX.XXX:9090"],
 "insecure-registries": ["10.180.XXX.XXX:9090"]
 }
 
 | 
| 1
 | systemctl restart docker
 | 
| 1
 | docker login 10.180.XXX.XXX:9090
 | 
保证输入账号密码后能正常登录。
制作镜像
这里以 ZooKeeper server 为例制作 Docker 镜像。
解压 rpm 包
| 1
 | rpm2cpio zookeeper_3_0_1_0_187-3.4.6.3.0.1.0-187.noarch.rpm |cpio -idv
 | 

编写 Dockerfile
Dockerfile 内容如下,这里使用 openjdk 8 作为基础镜像,这里的镜像源为:insight/openjdk:8-jre。
| 12
 3
 4
 5
 
 | FROM insight/openjdk:8-jre
 COPY usr /usr
 
 ENTRYPOINT ["/usr/hdp/3.0.1.0-187/zookeeper/bin/zkServer.sh","start-foreground"]
 
 | 
拉取 openjdk 镜像
| 1
 | docker pull insight/openjdk:8-jre
 | 
查看镜像

构建镜像
| 1
 | docker build -t insight/zookeeper:3.4.6 .
 | 

查看镜像

上传镜像
通过 docker tag 重命名镜像,使之与 registry 匹配
| 1
 | docker tag insight/zookeeper:3.4.6 10.180.210.148:9090/insight/zookeeper:3.4.6
 | 
登录(只需一次)
| 1
 | docker login 10.180.xxx.xxx:9090
 | 
push镜像
| 1
 | docker push 10.180.xxx.xxx:9090/insight/zookeeper:3.4.6
 | 
修改 Stacks 文件
Ambari 管理 Docker 的关键在于 Stacks 文件,通过修改服务响应安装、启动、停止等脚本达到管理效果。
这里修改ambari-server\src\main\resources\stacks\HDP\3.0\services\ZOOKEEPER\package\scripts\params_linux.py 和  ambari-server\src\main\resources\stacks\HDP\3.0\services\ZOOKEEPER\package\scripts\zookeeper_server.py 中两个文件。
配置文件
params_linux.py 中添加 docker 相关配置
| 12
 3
 4
 5
 6
 7
 8
 9
 
 | # docker parameterszk_server_docker_name = "zkName"
 zk_server_host_port = "2181"
 zk_server_container_port = "2181"
 zk_server_host_conf_dir = "/usr/hdp/3.0.1.0-187/zookeeper/conf"
 zk_server_docker_conf_dir = "/usr/hdp/3.0.1.0-187/zookeeper/conf"
 zk_server_image_name = "insight/zookeeper"
 zk_server_image_version = "3.4.6"
 root_user = "root"
 
 | 
安装
在 zookeeper_server.py 中修改 install 方法。
| 12
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 
 | def install(self, env):# self.install_packages(env)
 self.configure(env)
 
 Logger.info("Starting pull ZooKeeper image ...")
 
 import params
 
 image_name = params.zk_server_image_name
 image_version = params.zk_server_image_version
 install_cmd = format("docker pull {image_name}:{image_version}")
 Execute(install_cmd, user=params.root_user)
 Logger.info("Pull ZooKeeper image success !")
 
 | 
启动
在 zookeeper_server.py 中修改 start 方法。
| 12
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 
 | def start(self, env, upgrade_type=None):import params
 env.set_params(params)
 self.configure(env, upgrade_type=upgrade_type)
 # zookeeper_service(action='start', upgrade_type=upgrade_type)
 
 Logger.info("Starting ZooKeeper ...")
 zkName = params.zk_server_docker_name
 hport = params.zk_server_host_port
 cport = params.zk_server_container_port
 image_name = params.zk_server_image_name
 image_version = params.zk_server_image_version
 hconf = params.zk_server_host_conf_dir
 cconf = params.zk_server_docker_conf_dir
 hdata = params.zk_data_dir
 cpu = params.zk_server_cpu_value
 memory = params.zk_server_heapsize_value
 
 try:
 stop_cmd = format("docker stop {zkName} && docker rm {zkName}")
 Execute(stop_cmd, user=params.root_user)
 except:
 Logger.info("ZooKeeper is not running .")
 
 start_cmd = format("docker run -d --name {zkName} "
 "--network host "
 "-v {hconf}:{cconf} "
 "-v {hdata}:{hdata} "
 "--cpus {cpu} -m {memory} "
 "{image_name}:{image_version}")
 
 if params.kerberos_security_enabled:
 start_cmd = format("docker run -d --name {zkName} "
 "--network host "
 "-p {hport}:{cport} "
 "-v {hconf}:{cconf} "
 "-v {hdata}:{hdata} "
 "-v {keytabs_dir}:{keytabs_dir} "
 "-v {krb5_conf_dir}:{krb5_conf_dir} "
 "--cpus {cpu} -m {memory} "
 "{image_name}:{image_version}")
 
 Execute(start_cmd, user=params.root_user)
 Logger.info("Started ZooKeeper success !")
 
 Logger.info("Starting write pid ...")
 pid_file = params.zk_pid_file
 get_pid = "docker top " + zkName + " | awk '{print $2}' | sed -n '2p' > " + pid_file
 Execute(get_pid, user=params.root_user)
 Logger.info("Write pid success !")
 
 | 
这里主要涉及获取参数,拼接启动命令(包括 kerberos 环境),写入 pid 文件等步骤。
停止
在 zookeeper_server.py 中修改 stop 方法。
| 12
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 
 | def stop(self, env, upgrade_type=None):import params
 env.set_params(params)
 # zookeeper_service(action='stop', upgrade_type=upgrade_type)
 
 Logger.info("Start stop ZooKeeper ...")
 zkName = params.zk_server_docker_name
 
 status = 1
 try:
 status_cmd = format("docker ps -a | grep {zkName}")
 Execute(status_cmd, user=params.root_user)
 except:
 status = 0
 
 if status:
 stop_cmd = format("docker stop {zkName} && docker rm {zkName}")
 Execute(stop_cmd, user=params.root_user)
 Logger.info("Stopped ZooKeeper ...")
 
 # delete pid file
 Logger.info("Start delete pid file ...")
 File(params.zk_pid_file, action="delete")
 Logger.info("Delete pid file success ...")
 
 | 
主要包括检测 docker 镜像是否存在,如果存在就停掉并删除,并且删除 pid 文件。
状态
这里的状态检测可完全使用之前的方法,不必修改。
| 12
 3
 4
 
 | def status(self, env):import status_params
 env.set_params(status_params)
 check_process_status(status_params.zk_pid_file)
 
 | 
安装测试
替换脚本
| 12
 3
 4
 5
 6
 7
 8
 9
 10
 
 | cd /var/lib/ambari-server/resources/stacks/HDP/3.0/services/ZOOKEEPERcd package/scripts/
 
 rm -rf params_linux.py*
 rm -rf zookeeper_server.py*
 
 # 上传修改后的脚本
 
 chmod 755 params_linux.py
 chmod 755 zookeeper_server.py
 
 | 
重启 ambari
全部节点
| 12
 3
 
 | ## 清除缓存rm -rf /var/lib/ambari-agent/cache/*
 rm -rf /var/lib/ambari-agent/tmp/*
 
 | 
重启 Ambari server
Server 节点:
重启 Ambari agent
全部节点:
安装
安装步骤与普通版本一样,然后可以进行相应的测试使用。
参考资料