AWS チームによる
序文
企業規模が拡大し、ビジネス データが増加するにつれて、Hadoop/Spark フレームワークを使用して大量のデータの ETL/集計分析ジョブを処理することになります。これらのジョブは、統合されたジョブ スケジューリング プラットフォームによって定期的にスケジュールされる必要があります。
Amazon EMR では、AWS を使用して Step Function、ホスト AirFlow、およびジョブ呼び出し用の Apache Oozie または Azkaban を提供できます。しかし、Apache Dolphinscheduler 製品の改良により、コミュニティの人気が高まり、そのシンプルさ、使いやすさ、高い信頼性、高い拡張性、豊富な使用シナリオのサポート、マルチテナント モードなどの機能を選択する企業が増えています。タスクのスケジュール設定のためのサービスとしての製品。
DolphinScheduler は Amazon EMR クラスターにインストールしてデプロイできますが、Amazon EMR 自体の特性と使用上のベストプラクティスに基づいて、ビッグデータ全体を提供するために大規模で包括的で永続的に実行される EMR クラスターを使用することは推奨されません。関連サービス: クラスターは、研究開発段階 (開発、テスト、運用)、ワークロード (アドホック クエリ、バッチ処理)、時間の重要性、ジョブ期間の要件、組織の種類などのさまざまな次元に基づいて分割されます。 DolphinScheduler は、統合スケジューリング プラットフォームとして機能し、固定 EMR クラスターにインストールする必要はなく、独立してデプロイし、ジョブを異なる EMR クラスターに分割し、DAG (有向非巡回グラフ、DAG) ストリーミング モードで組み立てることを選択します。統一されたスケジュールと管理を実現します。
この記事では、DolphinScheduler のインストールとデプロイメント、および DolphinScheduler でのジョブ オーケストレーションを紹介し、Python スクリプトを使用して、クラスターの作成、クラスター ステータスのチェック、EMR ステップ ジョブの送信、EMR ステップ ジョブのステータス チェックなどの EMR タスクのスケジュール設定を実行します。ジョブ 終了したらクラスターを終了します。
アマゾンEMR
Amazon EMR は、AWS 上での Apache Hadoop や Apache Spark などのビッグデータ フレームワークの実行を簡素化し、大量のデータを処理および分析するマネージド クラスター プラットフォームです。ユーザーは、手動による複雑な構成を必要とせず、ワンクリックで多くの Hadoop エコロジカル データ処理および分析関連サービスを含むクラスターを開始できます。
Apache DolphinScheduler
Apache DolphinScheduler は、分散型で簡単にスケーラブルなビジュアル DAG ワークフロー タスク スケジューリングのオープン ソース システムです。エンタープライズレベルのシナリオに適しており、運用タスク、ワークフロー、ライフサイクル全体のデータ処理プロセスを視覚化するためのソリューションを提供します。
特性
使いやすい
- Visual DAG: ユーザーフレンドリーなドラッグアンドドロップワークフロー定義、モジュール式ランタイム制御ツール
- 操作: カスタマイズとメンテナンスが容易なモジュール式
豊富な利用シーン
- 複数のタスク タイプをサポート: シェル、MR、Spark、SQL などの 10 を超えるタスク タイプをサポートし、クロスランゲージをサポートします。
- 簡単に拡張可能で豊富なワークフロー操作: ワークフローはスケジュール、一時停止、再開、停止できるため、グローバル パラメータとローカル パラメータの維持と制御が容易になります。
高信頼性
高い信頼性: 安定性を確保するための分散型設計。ネイティブ HA タスク キューのサポートにより、過負荷フォールト トレランスが提供されます。DolphinScheduler は非常に堅牢な環境を提供します。
- 高い拡張性
高い拡張性: マルチテナンシーとオンライン リソース管理をサポートします。1日あたり10万件のデータタスクの安定した運用をサポートします。
アーキテクチャ図:
主に達成されたこと:
- タスクはタスクの依存関係に従って DAG ダイアグラムの形式で関連付けられ、タスクの実行状況をリアルタイムで視覚的に監視できます。
- さまざまなタスク タイプをサポート: シェル、MR、Spark、SQL (mysql、oceanbase、postgresql、hive、sparksql)、Python、サブプロセス、プロシージャなど。
- ワークフローのスケジュールされたスケジューリング、依存スケジューリング、手動スケジューリング、手動の一時停止/停止/再開をサポートし、失敗した再試行/アラーム、失敗した指定ノードからの回復、キルタスクなどの操作もサポートします。
- ワークフロー優先度、タスク優先度、タスクフェイルオーバー、タスクタイムアウトアラーム/失敗をサポート
- ワークフローのグローバルパラメータとノードのカスタムパラメータ設定をサポート
- リソースファイルのオンラインアップロード/ダウンロード、管理などをサポート、オンラインでのファイル作成と編集をサポート
- タスクログのオンライン表示とスクロール、ログのオンラインダウンロードなどをサポートします。
- クラスター HA を実装し、Zookeeper を通じてマスター クラスターとワーカー クラスターの分散化を実現します。
- マスター/ワーカーの CPU 負荷、メモリ、CPU のオンライン表示をサポート
- ワークフロー実行履歴ツリー/ガントチャート表示、タスクステータス統計、プロセスステータス統計をサポートします。
- 補体をサポート
- マルチテナンシーのサポート
DolphinSchedulerをインストールする
DolphinScheduler は複数のデプロイメント方法をサポートします
- スタンドアロン展開: スタンドアロンは、DolphinScheduler の迅速なエクスペリエンスにのみ適しています
- 擬似クラスター デプロイ: 擬似クラスター デプロイの目的は、DolphinScheduler サービスを単一のマシンにデプロイすることです。このモードでは、マスター、ワーカー、および API サーバーがすべて同じマシン上にあります。
- クラスター展開: クラスター展開の目的は、DolphinScheduler サービスを複数のマシンに展開して、多数のタスクを実行することです。
初心者でDolphinSchedulerの機能を体験したい場合はスタンドアロン、より充実した機能や大きなワークロードを体験したい場合は擬似クラスタ導入、企業内で使用している場合は擬似クラスタ導入を推奨します。運用環境では、クラスター展開または kubernetes を使用することをお勧めします。
この実験では、AWS 上の疑似クラスター モードでの DolphinScheduler のデプロイを紹介します。
- EC2を開始する
AWS パブリック サブネットで EC2 を起動し、Amazon-linux2 を選択し、m5.xlarge セキュリティ グループで TCP 12345 ポートを開きます。
- JDKのインストールとJAVA_HOME環境の設定
java -version
openjdk version "1.8.0_362"
OpenJDK Runtime Environment (build 1.8.0_362-b08) OpenJDK 64-Bit Server VM (build 25.362-b08, mixed mode)
- Zookeeper をインストールして起動する
bin/zkServer.sh status
/usr/bin/java
ZooKeeper JMX enabled by default
Using config: /usr/local/src/apache-zookeeper-3.8.1-bin/bin/../conf/zoo.cfg Client port found: 2181. Client address: localhost. Client SSL: false.
Mode: standalone
- mysql を起動し、ここで Aurora Serverless を選択します
- AWS CLI2をインストールする
aws --version
aws-cli/2.11.4 Python/3.11.2 Linux/5.10.167-147.601.amzn2.x86_64 exe/x86_64.amzn.2 prompt/off
- Pythonのバージョンを3.9にアップデートする
python --version
Python 3.9.1
- ダウンロードDolphinScheduler
cd /usr/local/src
wget https://dlcdn.apache.org/dolphinscheduler/3.1.4/apache-dolphinscheduler-3.1.4-bin.tar.gz
- ユーザーパスワードの免除と権限を構成する
# 创建用户需使用 root 登录
useradd dolphinscheduler
# 添加密码
echo "dolphinscheduler" | passwd --stdin dolphinscheduler
# 配置 sudo 免密
sed -i '$adolphinscheduler ALL=(ALL) NOPASSWD: NOPASSWD: ALL' /etc/sudoers
sed -i 's/Defaults requirett/#Defaults requirett/g' /etc/sudoers
# 修改目录权限,使得部署用户对二进制包解压后的 apache-dolphinscheduler-*-bin 目录有操作权限
cd /usr/local/src
chown -R dolphinscheduler:dolphinscheduler apache-dolphinscheduler-*-bin
- マシンの SSH パスワード不要ログインを構成する
# 切换 dolphinscheduler 用户
su dolphinscheduler
ssh-keygen -t rsa -P '' -f ~/.ssh/id_rsa
cat ~/.ssh/id_rsa.pub >> ~/.ssh/authorized_keys
chmod 600 ~/.ssh/authorized_keys
# 注意:配置完成后,可以通过运行命令 ssh localhost 判断是否成功,如果不需要输⼊密码就能 ssh 登陆则证明成功
- データの初期化
cd /usr/local/src
# 下载 mysql-connector
wget https://downloads.mysql.com/archives/get/p/3/file/mysql-connector-j-8.0.31.tar.gz
tar -zxvf mysql-connector-j-8.0.31.tar.gz
# 驱动拷贝
cp mysql-connector-j-8.0.31/mysql-connector-j-8.0.31.jar ./apache-dolphinscheduler-3.1.4-bin/api-server/libs/
cp mysql-connector-j-8.0.31/mysql-connector-j-8.0.31.jar ./apache-dolphinscheduler-3.1.4-bin/alert-server/libs/
cp mysql-connector-j-8.0.31/mysql-connector-j-8.0.31.jar ./apache-dolphinscheduler-3.1.4-bin/master-server/libs/
cp mysql-connector-j-8.0.31/mysql-connector-j-8.0.31.jar ./apache-dolphinscheduler-3.1.4-bin/worker-server/libs/
cp mysql-connector-j-8.0.31/mysql-connector-j-8.0.31.jar ./apache-dolphinscheduler-3.1.4-bin/tools/libs/
# 安装 mysql 客户端
# 修改 {mysql-endpoint} 为你 mysql 连接地址
# 修改 {user} 和 {password} 为你 mysql ⽤户名和密码
mysql -h {mysql-endpoint} -u{user} -p{password}
mysql> CREATE DATABASE dolphinscheduler DEFAULT CHARACTER SET utf8 DEFAULT COLLATE utf8_general_ci;
# 修改 {user} 和 {password} 为你希望的用户名和密码
mysql> CREATE USER '{user}'@'%' IDENTIFIED BY '{password}';
mysql> GRANT ALL PRIVILEGES ON dolphinscheduler.* TO '{user}'@'%';
mysql> CREATE USER '{user}'@'localhost' IDENTIFIED BY '{password}';
mysql> GRANT ALL PRIVILEGES ON dolphinscheduler.* TO '{user}'@'localhost';
mysql> FLUSH PRIVILEGES;
修改数据库配置
vi bin/env/dolphinscheduler_env.sh
# Database related configuration, set database type, username and password # 修改 {mysql-endpoint} 为你 mysql 连接地址
# 修改 {user} 和 {password} 为你 mysql ⽤户名和密码,{rds-endpoint}为数据库连接地址
export DATABASE=${DATABASE:-mysql}
export SPRING_PROFILES_ACTIVE=${DATABASE}
export SPRING_DATASOURCE_URL="jdbc:mysql://{rds-endpoint}/dolphinscheduler?useUnicode=true&characterEncoding=UTF-8&useSSL=false"
export SPRING_DATASOURCE_USERNAME={user}
export SPRING_DATASOURCE_PASSWORD={password}
# 执行数据初始化
bash apache-dolphinscheduler/tools/bin/upgrade-schema.sh
- install_env.shを変更する
cd /usr/local/src/apache-dolphinscheduler
vi bin/env/install_env.sh
# 替换 IP 为 DolphinScheduler 所部署 EC2 私有 IP 地址
ips=${ips:-"10.100.1.220"}
masters=${masters:-"10.100.1.220"}
workers=${workers:-"10.100.1.220:default"}
alertServer=${alertServer:-"10.100.1.220"}
apiServers=${apiServers:-"10.100.1.220"}
installPath=${installPath:-"~/dolphinscheduler"}
- DolphinScheduler_env.shを変更する
cd /usr/local/src/
mv apache-dolphinscheduler-3.1.4-bin apache-dolphinscheduler
cd ./apache-dolphinscheduler
# 修改 DolphinScheduler 环境变量
vi bin/env/dolphinscheduler_env.sh
export JAVA_HOME=${JAVA_HOME:-/usr/lib/jvm/jre-1.8.0-openjdk-1.8.0.362.b08-1.amzn2.0.1.x86_64}
export PYTHON_HOME=${PYTHON_HOME:-/bin/python}
- DolphinSchedulerを起動する
cd /usr/local/src/apache-dolphinscheduler
su dolphinscheduler
bash ./bin/install.sh
- DolphinScheduler にアクセス
URL アクセスでは、DolphinScheduler にデプロイされた IP EC2 パブリック IP アドレスhttp://ec2-endpoint:12345/dolphinscheduler/ui/login を使用します。
初期ユーザー名/パスワードadmin/dolphinscheduler123 05
DolphinScheduler を構成する
- テナントを作成する
2. ユーザーをテナントにバインドする
- AWS IAM ポリシーの作成
{
"Version":"2012-10-17",
"Statement":[
{
"Sid":"ElasticMapReduceActions",
"Effect":"Allow",
"Action":[
"elasticmapreduce:RunJobFlow",
"elasticmapreduce:DescribeCluster",
"elasticmapreduce:AddJobFlowSteps",
"elasticmapreduce:DescribeStep",
"elasticmapreduce:TerminateJobFlows",
"elasticmapreduce:SetTerminationProtection"
],
"Resource":"*"
},
{
"Effect":"Allow",
"Action":[
"iam:GetRole",
"iam:PassRole"
],
"Resource":[
"arn:aws:iam::accountid:role/EMR_DefaultRole",
"arn:aws:iam::accountid:role:role/EMR_EC2_DefaultRole"
]
}
]
}
- IAM ロールを作成する
AWS IAM を入力し、ロールを作成し、前のステップで作成したポリシーを割り当てます。
- DolphinScheduler は EC2 バインディング ロールをデプロイします
DolphinScheduler によってデプロイされた EC2 が EMR を呼び出す権限を持つように、EC2 を前のステップで作成したロールにバインドします。
- Python は boto3 とその他の必要なコンポーネントをインストールします
sudu pip install boto3
sudu pip install redis
ジョブのスケジュール設定に DolphinScheduler を使用する
Pythonで実行されます。
ジョブ実行シーケンス図:
- EMR クラスター作成タスクの作成
3 つの MASTER と 3 つの CORE を持つ EMR クラスターを作成し、サブネットと権限を指定し、10 分間アイドル状態になった後にクラスターを自動的に終了します。特定のパラメータはリンクにあります。
import boto3
from datetime import date
import redis
def run_job_flow():
response = client.run_job_flow(
Name='create-emrcluster-'+ d1,
LogUri='s3://s3bucket/elasticmapreduce/',
ReleaseLabel='emr-6.8.0',
Instances={
'KeepJobFlowAliveWhenNoSteps': False,
'TerminationProtected': False,
# 替换{Sunbet-id}为你需要部署的子网 id
'Ec2SubnetId': '{Sunbet-id}',
# 替换{Keypairs-name}为你 ec2 使用密钥对名称
'Ec2KeyName': '{Keypairs-name}',
'InstanceGroups': [
{
'Name': 'Master',
'Market': 'ON_DEMAND',
'InstanceRole': 'MASTER',
'InstanceType': 'm5.xlarge',
'InstanceCount': 3,
'EbsConfiguration': {
'EbsBlockDeviceConfigs': [
{
'VolumeSpecification': {
'VolumeType': 'gp3',
'SizeInGB': 500
},
'VolumesPerInstance': 1
},
],
'EbsOptimized': True
},
},
{
'Name': 'Core',
'Market': 'ON_DEMAND',
'InstanceRole': 'CORE',
'InstanceType': 'm5.xlarge',
'InstanceCount': 3,
'EbsConfiguration': {
'EbsBlockDeviceConfigs': [
{
'VolumeSpecification': {
'VolumeType': 'gp3',
'SizeInGB': 500
},
'VolumesPerInstance': 1
},
],
'EbsOptimized': True
},
}
],
},
Applications=[{'Name': 'Spark'},{'Name': 'Hive'},{'Name': 'Pig'},{'Name': 'Presto'}],
Configurations=[
{ 'Classification': 'spark-hive-site',
'Properties': {
'hive.metastore.client.factory.class': 'com.amazonaws.glue.catalog.metastore.AWSGlueDataCatalogHiveClientFactory'}
},
{ 'Classification': 'hive-site',
'Properties': {
'hive.metastore.client.factory.class': 'com.amazonaws.glue.catalog.metastore.AWSGlueDataCatalogHiveClientFactory'}
},
{ 'Classification': 'presto-connector-hive',
'Properties': {
'hive.metastore.glue.datacatalog.enabled': 'true'}
}
],
JobFlowRole='EMR_EC2_DefaultRole',
ServiceRole='EMR_DefaultRole',
EbsRootVolumeSize=100,
# 集群空闲十分钟自动终止
AutoTerminationPolicy={
'IdleTimeout': 600
}
)
return response
if __name__ == "__main__":
today = date.today()
d1 = today.strftime("%Y%m%d")
# {region}替换为你需要创建 EMR 的 Region
client = boto3.client('emr',region_name='{region}')
# 创建 EMR 集群
clusterCreate = run_job_flow()
job_id = clusterCreate['JobFlowId']
# 使用 redis 来保存信息,作为 DolphinScheduler job step 的参数传递,也可以使用 DolphinScheduler 所使用的 mysql 或者其他方式存储
# 替换{redis-endpoint}为你 redis 连接地址
pool = redis.ConnectionPool(host='{redis-endpoint}', port=6379, decode_responses=True)
r = redis.Redis(connection_pool=pool)
r.set('cluster_id_'+d1, job_id)
- EMRクラスターステータスチェックタスクの作成
EMRクラスターが作成されているか確認する
import boto3
import redis
import time
from datetime import date
if __name__ == "__main__":
today = date.today()
d1 = today.strftime("%Y%m%d")
# {region}替换为你需要创建 EMR 的 Region
client = boto3.client('emr',region_name='{region}')
# 替换{redis-endpoint}为你 redis 连接地址
pool = redis.ConnectionPool(host='{redis-endpoint}', port=6379, decode_responses=True)
r = redis.Redis(connection_pool=pool)
# 获取创建的 EMR 集群 id
job_id = r.get('cluster_id_' + d1)
print(job_id)
while True:
result = client.describe_cluster(ClusterId=job_id)
emr_state = result['Cluster']['Status']['State']
print(emr_state)
if emr_state == 'WAITING':
# EMR 集群创建成功
break
elif emr_state == 'FAILED':
# 集群创建失败
# do something...
break
else:
time.sleep(10)
- 作成したEMRクラスターを使用してSparkジョブを開始します。
import time
import re
import boto3
from datetime import date
import redis
def generate_step(step_name, step_command):
cmds = re.split('\\s+', step_command)
print(cmds)
if not cmds:
raise ValueError
return {
'Name': step_name,
'ActionOnFailure': 'CANCEL_AND_WAIT',
'HadoopJarStep': {
'Jar': 'command-runner.jar',
'Args': cmds
}
}
if __name__ == "__main__":
today = date.today()
d1 = today.strftime("%Y%m%d")
# {region}替换为你需要创建 EMR 的 Region
client = boto3.client('emr',region_name='{region}')
# 获取 emr 集群 id
# 替换{redis-endpoint}为你 redis 连接地址
pool = redis.ConnectionPool(host='{redis-endpoint}', port=6379, decode_responses=True)
r = redis.Redis(connection_pool=pool)
job_id = r.get('cluster_id_' + d1)
# job 启动命令
spark_submit_cmd = """spark-submit
s3://s3bucket/file/spark/spark-etl.py
s3://s3bucket/input/
s3://s3bucket/output/spark/"""+d1+'/'
steps = []
steps.append(generate_step("SparkExample_"+d1 , spark_submit_cmd),)
# 提交 EMR Step 作业
response = client.add_job_flow_steps(JobFlowId=job_id, Steps=steps)
step_id = response['StepIds'][0]
# 将作业 id 保存,以便于做任务检查
r.set('SparkExample_'+d1, step_id)
- JOB作成実行状況確認
import boto3
import redis
import time
from datetime import date
if __name__ == "__main__":
today = date.today()
d1 = today.strftime("%Y%m%d")
# {region}替换为你需要创建 EMR 的 Region
client = boto3.client('emr',region_name='{region}')
# 替换{redis-endpoint}为你 redis 连接地址
pool = redis.ConnectionPool(host='{redis-endpoint}', port=6379, decode_responses=True)
r = redis.Redis(connection_pool=pool)
job_id = r.get('cluster_id_' + d1)
step_id = r.get('SparkExample_' + d1)
print(job_id)
print(step_id)
while True:
# 查询作业执行结果
result = client describe_step(ClusterId=job_id,StepId=step_id)
emr_state = result['Step']['Status']['State']
print(emr_state)
if emr_state == 'COMPLETED':
# 作业执行完成
break
elif emr_state == 'FAILED'
# 作业执行失败
# do somethine
# ......
break
else:
time.sleep(10)
- 実行順序を設定する
DolphinScheduler - プロジェクト管理 - ワークフロー - ワークフロー定義でワークフローを作成し、Pythonタスクを作成し、上記のPythonスクリプトをタスクとして連結します
- 保存してオンラインに接続する
タスクを保存し、「オンラインにする」をクリックします
- 埋め込む
クリックしてすぐに実行することも、スケジュールされたタスクを指定して時間通りに実行することもできます。
EMR で実行ステータスを表示する
EMR作成ステータス - 開始中
EMR ステップの実行ステータス - 現在実行中
- 実行結果と実行ログを確認する
DolphinScheduler - プロジェクト管理 - ワークフロー - ワークフローインスタンスで実行状況と実行ログを確認EMRで実行状況を確認
EMR作成ステータス - 待機中
ステップの実行ステータス - 完了
- クラスターを終了する
一時的な実行ジョブまたは毎日実行するようにスケジュールされたバッチ ジョブの場合、コストを節約するためにジョブの終了後に EMR クラスターを終了できます (EMR はベスト プラクティスを使用します)。EMR クラスターの終了は、EMR ネイティブ機能を使用してアイドル状態になった後に自動的に終了するか、手動で中止を呼び出すことができます。
EMR クラスターを自動的に終了し、クラスターの作成時に構成します。
AutoTerminationPolicy={
'IdleTimeout': 600
}
このクラスターは、ジョブが 10 分間アイドル状態になると自動的に終了します。EMR クラスターを手動で終了します。
import boto3
from datetime import date
import redis
if __name__ == "__main__":
today = date.today()
d1 = today.strftime("%Y%m%d")
# 获取集群 id
# {region}替换为你需要创建 EMR 的 Region
client = boto3.client('emr',region_name='{region}')
# 替换{redis-endpoint}为你 redis 连接地址
pool = redis.ConnectionPool(host='{redis-endpoint}', port=6379, decode_responses=True)
r = redis.Redis(connection_pool=pool)
job_id = r.get('cluster_id_' + d1)
# 关闭集群终止保护
client.set_termination_protection(JobFlowIds=[job_id],TerminationProtected=False)
# 终止集群
client.terminate_job_flows(JobFlowIds=[job_id])
このスクリプトを DolphinScheduler ジョブ フローに追加すると、ジョブ フローはすべてのタスクが完了した後にスクリプトを実行して EMR クラスターを終了します。
要約する
エンタープライズビッグデータ分析プラットフォームの適用により、ますます多くのデータ処理プロセス/処理タスクが、シンプルで使いやすいスケジューリングシステムを使用して複雑な依存関係を整理し、実行計画に従って配置およびスケジュールする必要があります。同時に、使いやすく拡張しやすいビジュアル DAG 機能を提供する必要があり、Apache DolphinScheduler は上記のニーズをまさに満たします。
この記事では、AWS 上での DolphinScheduler の独立したデプロイメントを紹介し、ベスト プラクティスと組み合わせた EMR の特性を使用して、EMR クラスターの作成から ETL ジョブの送信、そして最終的にすべてのジョブの実行が完了してクラスターを終了するまでのプロセスを示します。完全なジョブ処理プロセス。ユーザーはこのドキュメントを参照して、独自のビッグ データ スケジューリング システムを迅速に展開および構築できます。
著者
AWS ソリューション アーキテクトの Wang Xiao は、AWS クラウド コンピューティング ソリューション アーキテクチャのコンサルティングと設計を担当し、中国で AWS クラウド プラットフォーム テクノロジーとさまざまなソリューションを推進しています。エンタープライズ IT アーキテクチャで豊富な経験を持ち、現在はビッグデータの分野に注力しています。 . 研究。
この記事はBeluga Open Source Technologyによって公開されています。