繼我們被apache linkis社群翻牌子以後,收錄了幾篇文章,今天被小海豚社群官方翻牌子了哈,當然我們也有flink社群的大佬,貢獻flink社群文章若幹,那就今天繼續更新一篇小海豚的文章哈,本文章來自滌生大資料老師,阿裡巴巴技術大佬貢獻
Ambari內建大資料元件系列
1.背景
DolphinScheduler本來提供了Ambari的安裝程式,可以直接內建的。但是呢,Amabri停止維護了,DS對應的安裝代碼也就沒再更新了。DS最新版本已經到3.x了,但是安裝部署腳本依舊停留在DS1.3.8,這太Low了,一點都不适用。對此,咱們就來改改,來實作DS3.x在Ambari下的內建實作。
部署環境:Aliyun Linux 2.x(Centos7.x)
2.RPM制作
安裝的方式有很多,但是個人還是比較喜歡AMbari的安裝風格rpm,對此,依舊沿用此方法,先把我們的安裝包封裝成RPM。
2.1軟體包準備
官網下載下傳對應的軟體包資訊,切記!!不要選最新版本的,選次新版本。别問,問就是血的教訓。
#下載下傳位址
https://dolphinscheduler.apache.org/zh-cn/download
截止2023年4月,最新版本為3.1.5,咨詢了社群那些,相對比較穩定的版本是3.1.2,對此,我們選擇3.1.2來進行實際環境的安裝。此處,我們需要進行rpmrebuild的環境的制作,可參考百度rpmbuild的使用。然後,将我們的DS軟體,解壓并拷貝到對應的編譯目錄,待用。特殊說明:
1.安裝目錄軟體
後續的安裝目錄,沿用HDP的路徑:/usr/hdp/3.3.1.0-001/dolphinscheduler;
2.編譯目錄
rpmbulid打包成rpm時候用到的目錄,主目錄在
/root/rpmbuild/BUILDROOT/;
3.軟體包目錄
apache-dolphinscheduler-3.1.2-1.x86_64;
4.軟體包内的安裝目錄
/usr/hdp/3.3.1.0-001/dolphinscheduler;
是以,整體的DS的解壓完整的路徑是:
/root/rpmbuild/BUILDROOT/apache-dolphinscheduler-3.1.2-1.x86_64/usr/hdp/3.3.1.0-001/dolphinscheduler
2.2SPEC檔案編輯
SPEC檔案,是RPM制作的說明檔案,我們可以完全自己寫,也可以抄一個現有的。對于看這個文檔的小夥伴,直接抄我的即可。完整的内容如下:
# rpmrebuild autogenerated specfile
BuildRoot: /root/.tmp/rpmrebuild.15841/work/root
AutoProv: no
%undefine __find_provides
AutoReq: no
%undefine __find_requires
# Do not try autogenerate prereq/conflicts/obsoletes and check files
%undefine __check_files
%undefine __find_prereq
%undefine __find_conflicts
%undefine __find_obsoletes
# Be sure buildpolicy set to do nothing
%define __spec_install_post %{nil}
# Something that need for rpm-4.1
%define _missing_doc_files_terminate_build 0
#dummy
#dummy
#BUILDHOST: ambaritest-vbj01c-2
#BUILDTIME: Tue Mar 15 15:06:49 2022
#SOURCERPM: apache-dolphinscheduler-2.0.1-2.src.rpm
#RPMVERSION: 4.11.3
#OS: linux
#SIZE: 245615802
#ARCHIVESIZE: 245813056
#ARCH: noarch
BuildArch: x86_64
Name: apache-dolphinscheduler
Version: 3.1.2
Release: 2
License: (c) The Apache Software Foundation
Group: apache
Summary: dolphinscheduler-dist
Distribution: apache dolphinscheduler rpm
URL: https://www.apache.org/
Vendor: The Apache Software Foundation
Packager: dolphinscheduler
Provides: apache-dolphinscheduler = 3.1.2
Requires: /bin/sh
Requires: /bin/sh
Requires: /bin/sh
Requires: /bin/sh
#suggest
#enhance
%description
Dolphin Scheduler is a distributed and easy-to-expand visual DAG workflow scheduling system, dedicated
to solving the complex dependencies in data processing, making the scheduling system out of the box for data
processing.
%files
/usr/hdp/3.3.1.0-001/dolphinscheduler
/var/run/dolphinscheduler
/var/log/dolphinscheduler
%pre -p /bin/sh
mkdir -p /usr/hdp/3.3.1.0-001/dolphinscheduler
mkdir -p /var/run/dolphinscheduler
mkdir -p /var/log/dolphinscheduler
%post -p /bin/sh
%postun -p /bin/sh
rm -rf /usr/hdp/3.3.1.0-001/dolphinscheduler
rm -rf /var/run/dolphinscheduler
%changelog
裡面的具體内容與細節,參考《RPMSEPC檔案解讀》,此處不在複述,能用就行了,要啥自行車。說明下,這個rpm的SPEC内容,是用DS官網的1.3.8版本RPM包改的。
2.3rpm制作
有了rpm包資訊,有了SPEC說明檔案,剩下的就簡單了,直接使用rpmbulid-bb進行編輯即可。
[root@bigdata ~]# rpmbuild -bb /root/rpmbuild/SPECS/dolphinscheduler_1.spec
剩下的交給時間即可。
我們的rpm資訊就制作完成了,在HDP的repo目錄,建立一個dolphinscheduler的目錄,拷貝進去
[root@bigdata ~]# cp /root/rpmbuild/RPMS/x86_64/apache-dolphinscheduler-3.1.2-3.x86_64.rpm /var/www/html/ambari/HDP/centos7/3.3.1.0-001/dolphinscheduler/
[root@bigdata ~]# cd /var/www/html/ambari/HDP/centos7/3.3.1.0-001/
[root@bigdata ~]# creatrepo ./
最後用yum驗證下,是否能夠正确識别到。
[root@bigdata ~]# yum list |grep apache-dolphinscheduler
apache-dolphinscheduler.x86_64 3.1.2-3 HDP-3.3-repo-1
2.4長久之計
問題來了,如果下次DS更新版本,或者添加什麼内容的。那麼就需要重新制作RPM,以上操作再來一次。很明顯,這種B格一看就不是大佬的作風。要玩,就長久點,代碼能搞的,咱們就不動手。(有同樣功能的,參考bigtop)我們的目的,是在DS有更新後,能夠自動建立更新,建立rpm資訊。自動檢測一看就比較難,而且價值不大,咱們就不做了。我們把2.1-2.3的步驟全部自動化,還是有十分可觀的價值的。
首先,需要解決如下幾個問題:
· 編譯目錄:/root/rpmbulid/BULIDROOT/.. ,這個目錄下的檔案回自動删除,我們每次建構都需要建立一次。
· 多版本支援,能不能每次自動更新release資訊,自動儲存曆史記錄。
帶着疑惑,咋們就開始出發。
· 首先第一點,解決緩存檔案被删除,無長久儲存的問題。關于這個問題,從兩方面進行考慮:1. 建立一個長久位址,每次封裝的時候,拷貝次檔案夾的内容來生成臨時目錄;2. 修改spec内容中的file部分,不寫詳細的檔案清單,隻寫目錄即可(2.2 已經修改)。
· 再然後就是release的更新了。這個就簡單了,分為現有版本的擷取與SPEC的更新。擷取可以通過掃描repo中的檔案清單,提取固定字段來擷取。比如:apache-dolphinscheduler-3.1.2-3.x86_64.rpm中的3就是Relase的版本,查詢 + 排序即可搞定。Relase的替換,也簡單,拿到這個數字後,加1後,使用sed指令來進行替換即可。
最後,再來自己加點難度。比如,最好适用hdp的其他程式,和變量相關的,丢前面。盡量使用函數進行封裝等。
接下來,上完整代碼
#!/bin/bash
# 用于ambari管理平台自動打包dolphinscheduler程式。
#===============
#定義運作環境位址
#----------------
rpm_file_path="/var/www/html/ambari/HDP/centos7/3.3.1.0-001/dolphinscheduler"
buildroot_dir="/root/rpmbuild/BUILDROOT"
src_path="/var/www/html/ambarisrc/rpm/dolphinscheduler"
version="3.1.2"
spec_dir="/root/rpmbuild/SPECS/dolphinscheduler"
#===============
# 擷取各種運作變量資訊
#----------------
# 擷取版本資訊
old_release_num=$(ls ${rpm_file_path} |grep dolphinscheduler |grep ${version} |awk -F '-' '{print $NF}'|awk -F '.' '{print $1}' |sort |tail -n 1)
release_num=$((old_release_num+1))
os_type=$(uname -a |awk '{print $12}')
function spec_config() {
#通過變量擷取rpm名
rpm_file_name=$1
spec_file_name=${rpm_file_name}_${release_num}".spec"
#擷取spec資訊
if [ ${spec_dir}/${spec_file_name} ];then
rm -rf ${spec_dir}/${spec_file_name}
fi
cp ${spec_dir}/${rpm_file_name}.spec ${spec_dir}/${spec_file_name}
#更新release版本資訊
sed -i "s/^Release:.*/Release: ${release_num}/g" ${spec_dir}/${spec_file_name}
}
function buildroot_init() {
#初始化最初的代碼目錄,隻運作一次
#源代碼目錄位址:/var/www/html/ambarisrc/rpm/dolphinscheduler
cd ${src_path}
for rpm_file_list in $(ls ${rpm_file_path}|grep ${version})
do
#擷取release 版本資訊
rpm_file_name=$(echo ${rpm_file_list} |awk -F "-${version}" '{print $1}')
echo ${rpm_file_name}
mkdir -p ${src_path}/${rpm_file_name};cd ${src_path}/${rpm_file_name}
rpm2cpio ${rpm_file_path}/${rpm_file_name}-${version}-${old_release_num}.${os_type}.rpm |cpio -idv
done
}
function buildroot_create() {
#生成對應的編輯目錄
echo "擷取軟體包名為: ${rpm_file_name}"
rpm_file_name=$1
rpm_buildroot_dir=${rpm_file_name}-${version}-${release_num}.${os_type}
echo "軟體包編譯安裝名:$buildroot_dir/$rpm_buildroot_dir"
if [ ! -z ${buildroot_dir}/${rpm_buildroot_dir} ];then
mkdir ${buildroot_dir}/${rpm_buildroot_dir}
#使用現有rpm包資訊,直接覆寫
fi
cd ${buildroot_dir}/${rpm_buildroot_dir}
echo "使用更新代碼替換原有包資訊:${src_path}/${rpm_file_name} ${buildroot_dir}/${rpm_buildroot_dir}"
cp -raf ${src_path}/${rpm_file_name}/* ${buildroot_dir}/${rpm_buildroot_dir}
echo "執行編譯指令:rpmbuild -bb ${spec_dir}/${rpm_file_name}_${release_num}.spec"
rpmbuild -bb ${spec_dir}/${rpm_file_name}_${release_num}".spec"
echo "拷貝編譯包更新到yum源:${rpm_file_path}"
cp /root/rpmbuild/RPMS/${os_type}/${rpm_file_name}-${version}-${release_num}.${os_type}.rpm ${rpm_file_path}
}
for rpm_file_name in $(ls ${rpm_file_path} |grep ${version} |awk -F "-${version}" '{print $1}' |uniq)
do
#spec配置生成
spec_config ${rpm_file_name}
buildroot_create ${rpm_file_name}
done
cd ${rpm_file_path}/../
createrepo ./
代碼解讀:第一段:各種變量的定義,如果其他程式,改路徑和版本即可。比如ambari的打包,修改配置如下
rpm_file_path="/var/www/html/ambari/ambari/centos7/2.7.6.3-0/ambari"
buildroot_dir="/root/rpmbuild/BUILDROOT"
src_path="/var/www/html/ambarisrc/rpm/ambari"
version="2.7.6.0"
spec_dir="/root/rpmbuild/SPECS/ambari"
第二段:擷取版本資訊。擷取現在的最新版本資訊;函數:spec_config。此函數,先拷貝一個模闆spec檔案,步驟2.2做好的東西,然後使用sed進行版本的替換
sed -i "s/^Release:.*/Release: ${release_num}/g" ${spec_dir}/${spec_file_name}
函數:buildroot_initx0;這個是為了友善建立永久儲存的目錄:${src_path}。就第一次運作的時候運作;
函數:buildroot_createx0;,進行rpm的封裝。從${src_path}路徑拷貝最新的檔案到緩存目錄,然後運作rpmbuild-bb進行實際rpm的制作;
整體函數使用for循環,進行檔案清單循環,以适應多個包的更新;
最後的最後:更新rpm資訊:createrepo./示範示例:
有了此代碼後,更新就簡單多了。比如我們想修改DS的存儲為Mysql,需要添加mysql-connection-java.jar到DS各個程式的lib中。
首先第一步,下載下傳jar包:mysql-connector-java-8.0.26.jar
第二步:拷貝此jar包到alert-server/libs,api-server/libs,master-server/libs,worker-server/libs
第三步:運作程式。就會自動封裝:apache-dolphinscheduler-3.1.2-4.x86_64.rpm
3.Dolphin內建
為了調試DS的安裝,本人按照官網的安裝教程,使用自帶的安裝程式install.shN次後得出的結論。有興趣的小夥伴,可以自己折騰下。
3.1DS服務架構
盜的一個架構圖,一看就比較複雜。
不過從圖中可以看出,有ZK,有API、UI、DB、Alert、Master、Worker。這些,其實就是我們安裝部署過程中需要運作的程式。安裝DS前,需要有ZK叢集以及一個Mysql。UI頁面是封裝到API中的,後面的Alert,Master,Worker每個作為單獨的程式來運作。那麼對于我們自動化部署,就是要實作DS的四個程式的啟動。
3.2代碼結構
有了架構圖,大概對這個軟體有了大概的意思,但是這東西來得不實際,很飄。涉及到具體部署的時候,拿來沒啥用。最有用的,還是看安裝的壓縮包。第一層目錄,直接拆分了角色了,一下就清爽多了,一看就懂了,每個角色程式,一個檔案夾。
[root@bigdata-pricloud-mirrors dolphinscheduler]# ll
總用量 184
drwxr-xr-x. 5 root root 4096 4月 12 16:12 alert-server
drwxr-xr-x. 6 root root 4096 4月 12 16:12 api-server
drwxr-xr-x. 3 root root 4096 4月 7 16:05 bin
-rw-r--r--. 1 root root 53845 4月 7 16:05 LICENSE
drwxr-xr-x. 4 root root 20480 4月 7 16:05 licenses
drwxr-xr-x. 5 root root 4096 4月 12 16:12 master-server
-rw-r--r--. 1 root root 77523 4月 7 16:05 NOTICE
drwxr-xr-x. 5 root root 4096 4月 21 11:56 standalone-server
drwxr-xr-x. 6 root root 4096 4月 7 16:05 tools
drwxr-xr-x. 4 root root 4096 4月 7 16:05 ui
drwxr-xr-x. 5 root root 4096 4月 12 16:12 worker-server
随便進一個角色的目錄:api-server
[root@bigdata-pricloud-mirrors api-server]# ll
總用量 36
drwxr-xr-x. 2 root root 4096 4月 7 16:05 bin
drwxr-xr-x. 2 root root 4096 4月 7 16:05 conf
drwxr-xr-x. 2 root root 24576 4月 7 16:05 libs
lrwxrwxrwx. 1 root root 25 4月 12 16:11 logs -> /var/log/dolphinscheduler
drwxr-xr-x. 4 root root 4096 4月 7 16:05 ui
[root@bigdata-pricloud-mirrors api-server]# ll bin/
總用量 4
-rw-r--r--. 1 root root 1400 4月 7 16:05 start.sh
[root@bigdata-pricloud-mirrors api-server]# ll conf/
總用量 32
-rw-r--r--. 1 root root 6198 4月 7 16:05 application.yaml
-rw-r--r--. 1 root root 987 4月 7 16:05 bootstrap.yaml
-rw-r--r--. 1 root root 5797 4月 7 16:05 common.properties
-rw-r--r--. 1 root root 2879 4月 7 16:05 dolphinscheduler_env.sh
-rw-r--r--. 1 root root 2587 4月 7 16:05 logback-spring.xml
-rw-r--r--. 1 root root 1385 4月 7 16:05 task-type-config.yaml
和這個角色相關的東西,大體有以下目錄:
bin/start.sh
#啟動指令,寫死了,每個下面的,都是單獨起單個程序的。比如,api下的,就是起api-server的
libs
#下面是一堆依賴檔案
conf
#下面是一堆配置檔案,具體的配置資訊,後面實作的時候來分析
logs
#日志目錄,這個不要改,不要改,改了位址後,沒法線上重新整理日志。但是可以用超連結換到其他地方。
ui
#這個隻有api有,其他的沒有。
這樣的目錄結構,conf、bin 目錄下的檔案,在不同的服務目錄下面,都是一樣,一樣的。隻需要根據不同的内容,改配置即可。
除了服務以外,還有一個特殊的目錄bin/env,這個下面有兩個檔案,在安裝的時候需要進行配置的修改,用于安裝,初始化的時候需要,也要做對應的修改。
[root@bigdata ]# ll bin/env/
總用量 8
-rwxr-xr-x. 1 root root 2879 4月 7 16:05 dolphinscheduler_env.sh
-rwxr-xr-x. 1 root root 3816 4月 7 16:05 install_env.sh
3.3安裝實作
目錄結構看完了,部署大體結構也知道了,接下來就要開始進行實際的自動化實作了。
3.3.1服務定義:metainfo.xml
這個是定義服務的程式,定義軟體版本,安裝的包資訊,以及配置依賴資訊。此處隻貼了些案例,沒貼全。子產品一:服務定義
<name>DOLPHIN</name>
<displayName>Dolphin Scheduler</displayName>
<comment>分布式易擴充的可視化DAG工作流任務排程系統</comment>
<version>3.1.2</version>
這個的效果圖,在服務添加頁面展示:
子產品二:程式定義
主要定義包含哪些程式,以及程式的維護程式,定義等等各種東西,一共有四個:DOLPHIN_MASTER,DOLPHIN_WORKERx0;,DOLPHIN_APIx0;,DOLPHIN_ALERTx0;。單個參考如下,具體細節百度知。
<component>
<name>DOLPHIN_MASTER</name>
<displayName>DS Master</displayName>
<category>MASTER</category>
<cardinality>1+</cardinality>
<commandScript>
<script>scripts/dolphin_master_service.py</script>
<scriptType>PYTHON</scriptType>
<timeout>600</timeout>
</commandScript>
</component>
子產品三:安裝rpm定義
這邊定義需要安裝的rpm程式,以及系統。我們這裡能支援的是Centos7.x/8.x,Redha7.x/8.x,KylinV10,Anolis8.x,直接寫個any先用着吧。
<osSpecifics>
<osSpecific>
<osFamily>any</osFamily>
<packages>
<package>
<name>apache-dolphinscheduler*</name>
</package>
</packages>
</osSpecific>
</osSpecifics>
剩下的,還有點内容,後期加吧,這裡貼一個完成的圖。
<?xml version="1.0"?>
<metainfo>
<schemaVersion>2.0</schemaVersion>
<services>
<service>
<name>DOLPHIN</name>
<displayName>Dolphin Scheduler</displayName>
<comment>分布式易擴充的可視化DAG工作流任務排程系統</comment>
<version>3.1.2</version>
<components>
<component>
<name>DOLPHIN_MASTER</name>
<displayName>DS Master</displayName>
<category>MASTER</category>
<cardinality>1+</cardinality>
<commandScript>
<script>scripts/dolphin_master_service.py</script>
<scriptType>PYTHON</scriptType>
<timeout>600</timeout>
</commandScript>
</component>
<component>
<name>DOLPHIN_WORKER</name>
<displayName>DS Worker</displayName>
<category>SLAVE</category>
<cardinality>1+</cardinality>
<commandScript>
<script>scripts/dolphin_worker_service.py</script>
<scriptType>PYTHON</scriptType>
<timeout>600</timeout>
</commandScript>
</component>
<component>
<name>DOLPHIN_ALERT</name>
<displayName>DS Alert</displayName>
<category>SLAVE</category>
<cardinality>1+</cardinality>
<commandScript>
<script>scripts/dolphin_alert_service.py</script>
<scriptType>PYTHON</scriptType>
<timeout>600</timeout>
</commandScript>
</component>
<component>
<name>DOLPHIN_API</name>
<displayName>DS Api</displayName>
<category>SLAVE</category>
<cardinality>1+</cardinality>
<commandScript>
<script>scripts/dolphin_api_service.py</script>
<scriptType>PYTHON</scriptType>
<timeout>600</timeout>
</commandScript>
</component>
</components>
<requiredServices>
<service>ZOOKEEPER</service>
</requiredServices>
<osSpecifics>
<osSpecific>
<osFamily>any</osFamily>
<packages>
<package>
<name>apache-dolphinscheduler*</name>
</package>
</packages>
</osSpecific>
</osSpecifics>
<configuration-dependencies>
<config-type>dolphin_env</config-type>
<config-type>common.properties</config-type>
<config-type>dolphin-jvm</config-type>
</configuration-dependencies>
<themes>
<theme>
<fileName>theme.json</fileName>
<default>true</default>
</theme>
</themes>
<quickLinksConfigurations-dir>quicklinks</quickLinksConfigurations-dir>
<quickLinksConfigurations>
<quickLinksConfiguration>
<fileName>quicklinks.json</fileName>
<default>true</default>
</quickLinksConfiguration>
</quickLinksConfigurations>
</service>
</services>
</metainfo>
3.3.2程式安裝:master_install.py
上面服務定義好了,接下來就進行軟體的安裝流程。就是看服務定義中的“scripts/dolphin_master_service.pyx0;”程式内容。這個裡面呢,就是定義各個軟體的安裝與啟動程式。以下,是經過N多次改版過後的實際安裝代碼。
# -*- coding: utf-8 -*-
import time
from resource_management import *
from dolphin_env import dolphin_env
class DolphinMasterService(Script):
def install(self, env):
import params
env.set_params(params)
self.install_packages(env)
with open("/etc/passwd") as f:
userlist = []
for line in f:
line=line.strip()
vec =line.split(':')
userlist.append(vec[0])
if params.dolphin_user in userlist:
Logger.info("Dolphin Deploy User : " + params.dolphin_user + "already exists ")
else:
Execute(('useradd', params.dolphin_user))
Execute(('sed -i \'/^' + params.dolphin_user + '/d\' /etc/sudoers'))
Execute(('sed -i \'$a' + params.dolphin_user + ' ALL=(ALL) NOPASSWD: NOPASSWD: ALL\' /etc/sudoers'))
Execute(('mkdir -p ' + " " + params.dolphin_home))
Execute(('mkdir -p ' + " " + params.dolphin_log_dir))
Execute(('mkdir -p ' + " " + params.dolphin_pidfile_dir))
Execute(('chown -R ' + params.dolphin_user + ":" + params.dolphin_group + " " + params.dolphin_home))
Execute(('chown -R ' + params.dolphin_user + ":" + params.dolphin_group + " " + params.dolphin_log_dir))
Execute(('chown -R ' + params.dolphin_user + ":" + params.dolphin_group + " " + params.dolphin_pidfile_dir))
Execute(('chown -R ' + params.dolphin_user + ":" + params.dolphin_group + "/var/log/dolphinscheduler"))
Execute(('rm -f ' + " " + params.dolphin_home+"/master-server/conf/core-site.xml"))
Execute(('ln -s /etc/hadoop/conf/core-site.xml' + " " + params.dolphin_home+"/master-server/conf/core-site.xml"))
Execute(('rm -f ' + " " + params.dolphin_home+"/master-server/conf/hdfs-site.xml"))
Execute(('ln -s /etc/hadoop/conf/hdfs-site.xml' + " " + params.dolphin_home+"/master-server/conf/hdfs-site.xml"))
def configure(self, env):
import params
params.pika_slave = True
env.set_params(params)
dolphin_env()
def start(self, env):
import params
env.set_params(params)
self.configure(env)
Execute(('sed -i \'/^' + params.dolphin_user + '/d\' /etc/sudoers'))
Execute(('sed -i \'$a' + params.dolphin_user + ' ALL=(ALL) NOPASSWD: NOPASSWD: ALL\' /etc/sudoers'))
no_op_test = format("ls {dolphin_pidfile_dir}/master-server.pid >/dev/null 2>&1 && ps `cat {dolphin_pidfile_dir}/master-server.pid` | grep `cat {dolphin_pidfile_dir}/master-server.pid` >/dev/null 2>&1")
start_cmd = format("sh " + params.dolphin_bin_dir + "/dolphinscheduler-daemon.sh start master-server")
Execute(start_cmd, user=params.dolphin_user, not_if=no_op_test)
def stop(self, env):
import params
env.set_params(params)
stop_cmd = format("sh " + params.dolphin_bin_dir + "/dolphinscheduler-daemon.sh stop master-server")
Execute(stop_cmd, user=params.dolphin_user)
time.sleep(5)
def status(self, env):
import params
env.set_params(params)
check_process_status(params.dolphin_pidfile_dir + "/master-server/pid")
if __name__ == "__main__":
DolphinMasterService().execute()
具體内容,其中,服務安裝的程式在下面代碼的:install_packages中,會根據3.1.1中,os處定義的内容,來進行rpm包的安裝,此處實際執行指令:yuminstall-yapache-dolphinscheduler*
def install(self, env):
import params
env.set_params(params)
self.install_packages(env)
其他安裝程式,類似,隻是需要修改對應的路徑和檔案名資訊
特殊說明下,最開始的程式,需要做系統的初始化,沿用1.3.8版本的初始化邏輯,把資料庫的初始化放在api的啟動程式中:dolphin_api_service.pyx0;
def start(self, env):
import params
env.set_params(params)
self.configure(env)
Execute(('sed -i \'/^' + params.dolphin_user + '/d\' /etc/sudoers'))
Execute(('sed -i \'$a' + params.dolphin_user + ' ALL=(ALL) NOPASSWD: NOPASSWD: ALL\' /etc/sudoers'))
#init
init_cmd=format("sh " + params.dolphin_home + "/tools/bin/upgrade-schema.sh")
Execute(init_cmd, user=params.dolphin_user)
no_op_test = format("ls {dolphin_pidfile_dir}/api-server.pid >/dev/null 2>&1 && ps `cat {dolphin_pidfile_dir}/api-server.pid` | grep `cat {dolphin_pidfile_dir}/api-server.pid` >/dev/null 2>&1")
start_cmd = format("sh " + params.dolphin_bin_dir + "/dolphinscheduler-daemon.sh start api-server")
Execute(start_cmd, user=params.dolphin_user, not_if=no_op_test)
3.4配置管理
你以為上面寫好就能用了?膚淺了,格局一定要打開。安裝才是第一步,怎麼做配置的更新、管理才是一個好的部署平台。最好自動化安裝,點一下需要安裝的程式,剩下的全部根據叢集,系統來預設最優配置設定,這才是一個大佬應該寫出來的自動化程式。其實,3.3中的程式,已經包含了配置的更新,其中,每個控制子產品前的importparams和set-params即配置的讀取與更新程式。
def install(self, env):
import params
env.set_params(params)
以上代碼,對應的程式
3.4.1配置解讀
在我N多次的安裝、解除安裝,對比配置等各個操作手段後,得出了以下内容。需要修改的配置内容如下,以ds的安裝相對路徑進行檔案的書寫。
#各種允許環境的指定,以及DB的環境資訊,其他環境全部通用。
./bin/env/dolphinscheduler_env.sh
#各種軟體角色位址的部署位址資訊。以及一些hdfs的配置...
./bin/env/install_env.sh
#各個服務相關的配置,定義資料庫資訊,ZK資訊,以及端口資訊。
./api-server/conf/application.yaml
#這個元件裡面的配置不同
./api-server/conf/bootstrap.yaml
#啟動程式名的定義,這個不需要做任何修改。
./api-server/conf/common.properties
#主要的配置資訊,資料庫,存儲位址啊,等等相關的。
./api-server/conf/logback-spring.xml
#日志路徑相關的,不用改内容,嘗試改過,然後功能不正常了。是以還是用超連結來實作log的修改吧。
./api-server/conf/task-type-config.yaml
#支援的排程定義,預設即可。
差不多,這些配置都得改吧。
3.4.2confiuration配置管理
對于配置相關的管理,在Amabri中,是通過一個叫configuration相關的xml進行設定的。這裡以dolphin-env.xml比如配置./bin/env/dolphinscheduler_env.sh中的一個配置
# Database related configuration, set database type, username and password
export DATABASE=${DATABASE:-mysql}
export SPRING_PROFILES_ACTIVE="dolphin"
export SPRING_DATASOURCE_URL="jdbc:mysql://127.0.0.1:3306/pricloud_dolphin?useUnicode=true&characterEncoding=UTF-8&useSSL=false"
export SPRING_DATASOURCE_USERNAME="admin"
export SPRING_DATASOURCE_PASSWORD="password"
其中在configuration中的相關定義如下:
<property>
<name>dolphin.database.type</name>
<value>mysql</value>
<description>選擇海豚排程的資料庫類型:Mysql/PG 2選一,預設Mysql</description>
<display-name>資料庫類型</display-name>
<value-attributes>
<type>value-list</type>
<entries>
<entry>
<value>mysql</value>
<label>Mysql</label>
</entry>
<entry>
<value>postgresql</value>
<label>Postgresql</label>
</entry>
</entries>
<selection-cardinality>1</selection-cardinality>
</value-attributes>
<on-ambari-upgrade add="true"/>
</property>
<property>
<name>dolphin.database.db</name>
<value>dolphin</value>
<display-name>資料庫名</display-name>
<on-ambari-upgrade add="true"/>
</property>
特殊說明,這種類型不太一樣,資料庫類型提供的是一個多選,提供mysql個PG的單選按鈕,資料庫是一個字元串,不用進階設定。成品大概如下:
特殊說明下,我是代碼搞好後再寫的文檔,截圖和xml中的定義,不太一樣。
3.4.2params配已置讀取
接下來,資料的定義有了,那就需要進行資料的讀取了,在web頁面,如果修改了配置,需要将這個配置寫入到具體的配置檔案中。怎麼來讀取這個配置呢?這個寫入在腳本parms.py中,先來一個案例:
#==================================
# dolphin env
#==================================
dolphin_database_type = config['configurations']['dolphin-env']['dolphin.database.type']
dolphin_database_db = config['configurations']['dolphin-env']['dolphin.database.db']
dolphin_database_username = config['configurations']['dolphin-env']['dolphin.database.username']
dolphin_database_password = config['configurations']['dolphin-env']['dolphin.database.password']
if 'mysql' == dolphin_database_config['dolphin_database_type']:
dolphin_database_config['dolphin_database_url'] = 'jdbc:mysql://'...
dolphin_database_driver = 'com.mysql.cj.jdbc.Driver'
driverDelegateClass = 'org.quartz.impl.jdbcjobstore.StdJDBCDelegate'
dolphin_database_url = 'jdbc:mysql://'...
else:
dolphin_database_config['dolphin_database_driver'] = 'org.postgresql.Driver'
dolphin_database_config['driverDelegateClass'] = 'org.quartz.impl.jdbcjobstore.PostgreSQLDelegate'
dolphin_database_config['dolphin_database_url'] = 'jdbc:postgresql://'...
案例解讀,這裡就是定義各種變量資訊的。比如讀取“dolphin-envx0;.xml”中關于mysql類型的定義為:
dolphin_database_type = config['configurations']['dolphin-env']['dolphin.database.type']
玩得再花一點,就再寫點判斷,這樣就可以根據一個選擇來進行不同資料的定義。除了這種定義的以外,還有和叢集相關的配置,比如ZK相關的,可以根據ZK叢集的資訊,自動讀取ZK配置,具體寫法如下:
ZookeeperServerHostInfo = config['clusterHostInfo']['zookeeper_server_hosts']
if len(ZookeeperServerHostInfo) > 0 and "clientPort" in config["configurations"]['zoo.cfg']:
clientPort = config['configurations']['zoo.cfg']['clientPort']
zookeeperPort = ":" + clientPort + ","
dolphin_registry_addr = zookeeperPort.join(ZookeeperServerHostInfo) + ":" + clientPort
Logger.info("dolphin_registry_addr : " + str(dolphin_registry_addr))
剩下的,自己更具配置的内容添加即可。
3.4.3Templates模闆生成
資料配置定義了,資料配置的方法讀取方法擷取了,接下來,問題來了:怎麼把這些資訊寫入到具體配置裡面呢?這裡,使用Templates模闆來進行配置文檔的編輯。此處核心就是配置使用{{變量名}}來進行替換首先用application.yaml來打個樣。
spring:
config:
activate:
on-profile: {{application_jdbc_type}}
datasource:
driver-class-name: {{application_jdbc_driver}}
url: {{application_jdbc_url}}
username: {{application_jdbc_username}}
password: {{application_jdbc_password}}
其中:{{application_jdbc_type}}等,都是parms.py中進行的變量擷取。整體套路就是這樣,剩下的就是對比不同的配置,來制作多個模闆。全部的資訊如下:
這裡隻是完成了一半,另外的一半,需要定義這些模闆檔案,需要寫到哪些配置裡面。這裡的話,寫在了dolphin_env.py中,這裡面主要進行檔案夾的建立,以及配置的更新。
def dolphin_env():
import params
Directory(params.dolphin_pidfile_dir,
mode=0755,
owner=params.dolphin_user,
group=params.dolphin_group,
create_parents=True
)
File(format(params.dolphin_home + '/alert-server/conf/application.yaml'),
mode=0644,
content=Template("application-alter.yaml.j2"),
owner=params.dolphin_user,
group=params.dolphin_group
)
File(format(params.dolphin_home + '/api-server/conf/application.yaml'),
mode=0644,
content=Template("application-api.yaml.j2"),
owner=params.dolphin_user,
group=params.dolphin_group
)
以上為案例,一看就懂,不做解釋。剩下的就是體力勞動。到此,已經可用了,寫到這裡,自動化部署就已經完成了。但是,還是那句話,格局一定要打開,要最求卓越。
3.5themes視覺優化
以下兩個圖,那個好看?很明顯,不做選擇題,咋們全都要。隻是,上圖已經實作了,接下來進行下圖的實作。
其中,下圖的内容需要使用到的是Ambari提供的Themes模闆,類似于一個頁面編輯框的工具,可以将單單選,多選文本的換個花樣來展示。
3.5.1themes解讀
首先來看看themes的寫法,大概長這樣的,主題包含三個目錄。layouts,placement和widgets
{
"name": "default",
"description": "Default theme for Dolphin Scheduler service",
"configuration": {
"layouts": [
{
"name": "default",
"tabs": [
{
"name": "settings",
"display-name": "Settings",
"layout": {
"tab-rows": "4",
"tab-columns": "3",
"sections": [
{
"name": "dolphin-env-config",
"display-name": "海豚環境配置",
"row-index": "0",
"column-index": "0",
"row-span": "1",
"column-span": "2",
"subsections": [
{
"name": "env-row1-col1",
"display-name": "部署使用者資訊",
"row-index": "0",
"column-index": "0",
"row-span": "1",
"column-span": "1"
},...
],
"placement": {
"configuration-layout": "default",
"configs": [
{
"config": "dolphin-env/dolphin.user",
"subsection-name": "env-row1-col1"
}
...
]
},
"widgets": [
{
"config": "dolphin-env/dolphin.user",
"widget": {
"type": "text-field"
}
layouts:是對整體頁面做拆分,做頁面排布。并對每個頁面命名和編号。頁面的布局内容如下:
placement,是對定義在框框中,填入什麼樣的内容。比如JVM處,大題填以下内容:
widgets,則是定義資料的規範,和顯示的格式,這個需要和對應的xml中的配置遙相呼應。比如:text-fieldx0;文本框,就是單純的框框格式,比如環境配置資訊的
togglex0; 二選一的拖拽框,比如,是否開啟kerbers配置的選項
combox0;,下拉框,用于多選一的選擇,比如資料庫類型,檔案存儲類型等。
大體介紹完了,接下來進行實際的實作。
3.5.2目錄配置
我們在最開始的地方<0,0>來進行環境配置的設定。打算提供,使用者賬号、組,以及環境變量的定義。這裡采用的是大框套小框來進行實作的,整體頁面布局就,及其對應的編碼就變成了這樣。
接下來就進行具體的框框的定義。在configurationx0;.layoutsx0;.tabs.x0;sectionsx0;處進行定義,從外部定義到内部,逐級定義。
{
"name": "dolphin-env-config",
"display-name": "海豚環境配置",
"row-index": "0",
"column-index": "0",
"row-span": "1",
"column-span": "2",
"subsections": [
{
"name": "env-row1-col1",
"display-name": "部署使用者資訊",
"row-index": "0",
"column-index": "0",
"row-span": "1",
"column-span": "1"
}
接下來,定義這個框裡面需要輸入的資料:賬号、組,以及環境變量;在配置位置:configurationx0;.placementx0;x0;.configsx0;
"placement": {
"configuration-layout": "default",
"configs": [
{
"config": "dolphin-env/dolphin.user",
"subsection-name": "env-row1-col1"
},
{
"config": "dolphin-env/dolphin.group",
"subsection-name": "env-row1-col1"
},
{
"config": "dolphin-env/dolphinscheduler-env-content",
"subsection-name": "env-row1-col1"
}
最後,定義處這些内容的資料展示格式。在配置configuration.widgetsx0;處
"widgets": [
{
"config": "dolphin-env/dolphin.user",
"widget": {
"type": "text-field"
}
},
{
"config": "dolphin-env/dolphin.group",
"widget": {
"type": "text-field"
}
},
{
"config": "dolphin-env/dolphinscheduler-env-content",
"widget": {
"type": "text-area"
}
},
這裡都是text格式,對應的一個xml案例,dolphin-env.xml關于部署使用者dolphin.user的定義。
<property>
<name>dolphin.user</name>
<value>dolphin</value>
<description>安裝哪個使用者并管理海豚排程器</description>
<display-name>部署使用者</display-name>
<on-ambari-upgrade add="true"/>
</property>
通過以上,操作,最後的效果圖如下。
3.5.2JVM配置
同上,依舊來進行JVM的設定,複制3.5.1開頭的内容,先來進行JVM的位置資訊設定。他的位置是<0,1>;
{
"name": "env-row1-col2",
"display-name": "JVM資訊配置",
"row-index": "0",
"column-index": "1",
"row-span": "1",
"column-span": "1"
}
接下來進行對應資料的填充與設定,同上,這裡隻提供一些參數的設定,其他的,參考排布即可。
{
"config": "dolphin-jvm/alert.jvm.xmx",
"subsection-name": "env-row1-col2"
},
{
"config": "dolphin-jvm/api.jvm.xmx",
"subsection-name": "env-row1-col2"
},
與上圖不同的是,這裡采用拉條的方式來進行資料的資料的設定,左右橫拉,實作JVM的設定。其中,在themes中的資料定義如下:
{
"config": "dolphin-jvm/alert.jvm.xmx",
"widget": {
"type": "slider",
"units": [
{
"unit-name": "GB"
}
]
}
},
對應的xml資訊,在配置dolphin-jvm.xml中,每次可調節1G大小,允許設定的範圍為1-4G,可以根據具體的配置設定。
<property>
<name>alert.jvm.xmx</name>
<value>1</value>
<display-name>Alert JVM大小</display-name>
<description>Alert 預配置設定的JVM使用的最大記憶體量
如果您希望輸入一個高于滑塊上最大值的值,請單擊滑鼠懸停在設定上時出現的鉛筆,并忽略不建議輸入更高的值。
</description>
<value-attributes>
<type>int</type>
<minimum>1</minimum>
<maximum>4</maximum>
<increment-step>1</increment-step>
<unit>GB</unit>
</value-attributes>
</property>
最後效果案例效果。
3.5.3資料庫配置
資料庫的,同上。不整廢話,都一樣的東西。效果圖如下:
3.5.4存儲類型選擇
資料存儲類型的時候,這個有點不同了,因為添加了可選,并且可選進行資料内容的展示。先來看效果圖:
選擇HDFS為存儲後,對應的配置如圖左上;選擇Null的效果如右上;AwsS3及其同類産品的如左下;阿裡雲OSS的如右下。這個是怎麼實作的呢?關于圖表框的定義,同上。不在叙述。接下來就是關于具體内容的選擇,這裡設定不一樣了。首選,下拉框,選擇存儲格式,下面定義資料的輸入
{
"config": "common.properties/resource.storage.type",
"subsection-name": "dynamic-row1-col1"
}
對應的資料格式為:
{
"config": "common.properties/resource.storage.type",
"widget": {
"type": "combo"
}
}
對應的xml定義檔案:common.properties.xml,這是一個多選
<property>
<name>resource.storage.type</name>
<value>HDFS</value>
<description>
資源存儲類型: HDFS , S3 , OSS , NONE
</description>
<display-name>資源存儲類型</display-name>
<value-attributes>
<type>value-list</type>
<entries>
<entry>
<value>HDFS</value>
<label>HDFS</label>
</entry>
<entry>
<value>S3</value>
<label>S3/MinIO/Ozone</label>
</entry>
<entry>
<value>OSS</value>
<label>OSS</label>
</entry>
<entry>
<value>NONE</value>
<label>NONE</label>
</entry>
</entries>
<selection-cardinality>1</selection-cardinality>
</value-attributes>
<on-ambari-upgrade add="true"/>
</property>
這樣,下拉框就完成了。接下來,怎麼根據下拉框的格式來進行相應配置的選擇呢?其實,這個的重點就是判斷+可顯示字段的資訊标記。貼代碼就懂了。在資料展示處:
{
"config": "common.properties/resource.alibaba.cloud.oss.endpoint",
"subsection-name": "dynamic-row1-col1",
"depends-on": [
{
"configs":[
"common.properties/resource.storage.type"
],
"if": "${common.properties/resource.storage.type} === OSS",
"then": {
"property_value_attributes": {
"visible": true
}
},
"else": {
"property_value_attributes": {
"visible": false
}
}
}
]
},
{
"config": "common.properties/resource.hdfs.root.user",
"subsection-name": "dynamic-row1-col1",
"depends-on": [
{
"configs":[
"common.properties/resource.storage.type"
],
"if": "${common.properties/resource.storage.type} === HDFS",
"then": {
"property_value_attributes": {
"visible": true
}
},
"else": {
"property_value_attributes": {
"visible": false
}
}
}
]
},
在每個選項中,添加一個判斷,隻有當type類型相關的時候,顯示标記位再設定是否顯示。這樣就完事兒了。
3.5.5Kerberos&Wechat
這兩個功能還沒設定好,先把功能頁面開啟來先。
資料框,及其框中資料編輯都同上,不在叙述。
不同就是資料的定義:
{
"config": "common.properties/hadoop.security.authentication.startup.state",
"widget": {
"type": "toggle"
}
},
{
"config": "common.properties/enterprise.wechat.enable",
"widget": {
"type": "toggle"
}
}
對應的XML資料定義,剩下的自己複制改。
<property>
<name>hadoop.security.authentication.startup.state</name>
<value>false</value>
<description>功能未開發完畢,别開啟</description>
<display-name>是否開啟Kerberos認證</display-name>
<value-attributes>
<type>value-list</type>
<entries>
<entry>
<value>true</value>
<label>Enabled</label>
</entry>
<entry>
<value>false</value>
<label>Disabled</label>
</entry>
</entries>
<selection-cardinality>1</selection-cardinality>
</value-attributes>
<on-ambari-upgrade add="false"/>
</property>通過以上一波操作,就全部完成了themes的定義,重點配置丢這裡,看起來就舒服了。這樣,重點配置在Setting頁面,詳細配置在advance頁面。
3.6超連結實作
DS給提供了Web頁面,最好的話,再搞個超連結,點選即可通路。說幹就看,先看效果圖
這個功能一共需求兩個東東。
第一個,服務定義metainfo.xml中,需要添加關于超連結的定義。
<quickLinksConfigurations>
<quickLinksConfiguration>
<fileName>quicklinks.json</fileName>
<default>true</default>
</quickLinksConfiguration>
</quickLinksConfigurations>
在建立檔案夾quicklinks,并在下面建立檔案quicklinks.json案例資料如下,具體内容,自己百度。
{
"name": "default",
"description": "default quick links configuration",
"configuration": {
"protocol":
{
"type":"http"
},
"links": [
{
"name": "dolphin-application-ui",
"label": "DolphinApplication UI",
"requires_user_name": "false",
"component_name": "DOLPHIN_API",
"url": "%@://%@:%@/dolphinscheduler/ui/",
"port":{
"http_property": "server.port",
"http_default_port": "12345",
"regex": "^(\\d+)#34;,
"site": "dolphin-application-api"
}
}
]
}
}
這個改起來簡單,效率給力。到此,文檔完畢,還有監控和告警相關的,不想寫了,就是這麼有脾氣。不是代碼不想寫,而且不想寫文檔。因為幹IT最讨厭兩件事:自己寫代碼的時候,寫備注+文檔、看别人代碼的時候,沒備注和文檔;
歡迎在研究大資料叢集二開的朋友們來戰(交流交流哈哈哈),也可以在b站上看我錄制的apache hadoop叢集運維實戰哈