CDH+airflow
简介
本文档将展示如何部署数据仓库以及简单展示其使用场景和方式。
环境
软件 | 版本 |
---|---|
Centos | 7.2 |
CDH | 5.15.0 |
Hadoop | 2.6.0 |
Airflow | 1.10.9 |
Python | 2.7.5 (系统自带)3.7.0 (需要安装) |
MySQL | 5.7.28 |
Redis | 4.0.14 |
Sqoop | 1.4.6 |
模块安装
Airflow
Airflow是一个编排、调度和监控workflow的平台,由Airbnb开源,现在在Apache Software Foundation 孵化。airflow 将workflow编排为tasks组成的DAGs,调度器在一组workers上按照指定的依赖关系执行tasks。同时,airflow 提供了丰富的命令行工具和简单易用的用户界面以便用户查看和操作,并且airflow提供了监控和报警系统。
在生产中,airflow的集群并没有必要性,且airflow集群需要保持全部配置一致,增加了额外的操作和学习成本,因此本文只在CDH集群的主机上部署了airflow。
升级Python
编译环境
yum install gcc-c++ gcc make cmake zlib-devel bzip2-devel openssl-devel ncurse-devel libffi-devel -y复制代码
编译安装Python3
准备好Python-3.7.0.tar.xz
# 确认版本
python -V
# 解压
tar Jxvf Python-3.7.0.tar.xz
# 进入python3.7.0目录
cd Python-3.7.0
# 创建目录
mkdir -p /usr/local/python3
# 配置(指定安装目录)
./configure --prefix=/usr/local/python3 --enable-optimizations
make && make install复制代码
修改系统路径
#备份原有默认Python路径
mv /usr/bin/python /usr/bin/python.bak
#将 python 链接至 python3
ln -s /usr/local/python3/bin/python3.7 /usr/bin/python
ln -s /usr/local/python3/bin/pip3 /usr/bin/pip
# 升级pip
pip install --upgrade pip
#python如果链接的命令失败,可尝试使用下面这条命令
ln -sf /usr/local/python3/bin/python3.7 /usr/bin/python
# 确认版本
python -V
pip -V复制代码
修改yum路径
修改以下两个文件
vi /usr/bin/yum
vi /usr/libexec/urlgrabber-ext-down复制代码
将第一行的 “#! /usr/bin/python” 改为
#! /usr/bin/python2.7复制代码
Redis安装
安装
cd /tmp
tar zxvf redis-4.0.14.tar.gz
cd redis-4.0.14
make
make install PREFIX=/usr/local/redis
cd /usr/local/redis
mkdir /usr/local/redis/etc
cp /tmp/redis-4.0.14/redis.conf /usr/local/redis/etc/复制代码
配置
编辑配置文件/usr/local/redis/etc/redis.conf修改以下设置
bind 0.0.0.0
daemonize yes
protected-mode no
appendonly yes # 将持久化方案从rdb改为aof
# 如果下面的 'appendfilename "appendonly.aof"' 被注释了,那么就去掉注
# 以下按需修改-----
requirepass foobared
# 紧接着下面写一行
requirepass your-password
# 如有需求也可以在此修改端口复制代码
启动
# 将redis加入到开机启动
vi /etc/rc.local
#添加内容
/usr/local/redis/bin/redis-server /usr/local/redis/etc/redis.conf
# 启动redis
/usr/local/redis/bin/redis-server /usr/local/redis/etc/redis.conf复制代码
检查
#端口和进程查找
netstat -tunpl | grep 6379
ps -aux | grep redis
#测试
redis-cli复制代码
Airflow安装
新建Linux用户
# 按需修改
adduser airflow
passwd airflow
#输入自定义密码
#修改该用户权限,使该用户在使用sudo时不需要密码
vi /etc/sudoers
root ALL=(ALL) ALL
airflow ALL=(ALL) NOPASSWD:ALL 复制代码
修改配置
vi /etc/profile
export AIRFLOW_HOME=/home/airflow #根据需要修改
export PYTHON_HOME=/usr/local/python3 #根据实际情况修改
export SLUGIFY_USES_TEXT_UNIDECODE=yes #临时设定
export PATH=$PATH:$PYTHON_HOME/bin
source /etc/profile复制代码
安装
pip install --upgrade setuptools -i http://pypi.douban.com/simple/ --trusted-host=pypi.douban.com
cd /tmp
wget http://repo.mysql.com/mysql57-community-release-el7-8.noarch.rpm
rpm -ivh mysql57-community-release-el7-8.noarch.rpm
yum install mysql-deve
pip install apache-airflow -i http://pypi.douban.com/simple/ --trusted-host=pypi.douban.co复制代码
此时airflow会被安装到Python下的第三方包中,路径为${PYTHON_HOME}/lib/python3.7/site-packages/airflow
pip show apache-airflow复制代码
继续安装
pip install apache-airflow[mysql] -i http://pypi.douban.com/simple/ --trusted-host=pypi.douban.com
pip install apache-airflow[celery] -i http://pypi.douban.com/simple/ --trusted-host=pypi.douban.com
pip install apache-airflow[redis] -i http://pypi.douban.com/simple/ --trusted-host=pypi.douban.com
# 测试
airflow version复制代码
MySQL
默认在部署CDH时已经完成MySQL初期设置。
mysql -u root -p
# 针对airflow使用创建数据库,添加用户并授权
CREATE DATABASE airflow CHARACTER SET utf8 COLLATE utf8_unicode_ci;
# 修改密码强度
set global validate_password_policy=0;
set global validate_password_length=4;
CREATE USER af@localhost IDENTIFIED BY 'xxxxx';
grant all privileges on airflow.* to 'af'@'%' identified by 'xxxxx' with grant option;
flush privileges;
# 开启timestamp ,数据更新时添加上当前时间(airflow推荐)
set @@global.explicit_defaults_for_timestamp=on;
exit
#重启服务器
service mysqld restart
# 账户测试
mysql -u af -p
show databas复制代码
Airflow配置
核心配置
# 编辑/home/airflow/airflow.cfg文件,修改以下内容,根据实际情况填写[ip和端口]:
sql_alchemy_conn = mysql://af:af123@10.0.10.xx:3306/airflow
# 格式mysql://帐号:密码@ip:port/db
executor = CeleryExecutor
#web_server_host = 10.0.10.xx
base_url = http://10.0.10.xx:8080
[celery]
broker_url = redis://10.0.10.xx:6379/0
result_backend = db+mysql://af:xxxxx@10.0.10.xx:3306/airflow
# 进入 dag 详细页面时直接渲染依赖图
dag_default_view = graph
# 修改时区
default_timezone = Asia/Shangh复制代码
修改webUI的时间
修改以下文件,注意
${PYTHON_HOME}/lib/python3.7/site-packages/airflow复制代码
是airflow的安装路径。
/home/airflow/.local/lib/python3.7/site-packages/airflow/utils/timezone.py
/home/airflow/.local/lib/python3.7/site-packages/airflow/utils/sqlalchemy.py
/home/airflow/.local/lib/python3.7/site-packages/airflow/www/templates/admin/master.html
其他配置
# 不加载示例 dag
load_examples = False
# 以 airflow 用户运行 task
default_impersonation = airflow
# 对每个 dag,只运行最新达到周期条件的实例
catchup_by_default = False
# scheduler 的最大线程数
max_threads =复制代码
启动
初次使用或需要初始化数据库时
airflow initdb复制代码
使用操作系统的airflow用户登录,并运行
airflow webserver -D
airflow scheduler -D
airflow flower -D
airflow worker -D 复制代码
webUI
airflow | host:8080 |
---|---|
flower | host:5555 |
测试
DAG脚本,如是集群,则需要在所有节点下配置DAG
mkdir /home/airflow/dags复制代码
在这个文件夹里存放这个hello_world.py文件。
# -*- coding: utf-8 -*-
import airflow
from airflow import DAG
from airflow.operators.bash_operator import BashOperator
from airflow.operators.python_operator import PythonOperator
from datetime import timedelta
#-------------------------------------------------------------------------------
# these args will get passed on to each operator
# you can override them on a per-task basis during operator initialization
default_args = {
'owner': 'airflow',
'depends_on_past': False,
'start_date': airflow.utils.dates.days_ago(2),
'email': ['langai818@qq.com'],
'email_on_failure': False,
'email_on_retry': False,
'retries': 1,
'retry_delay': timedelta(minutes=5),
}
#---------------------------------------------------------------------
# dag
dag = DAG(
'hello_world_dag',
default_args=default_args,
description='test DAG',
schedule_interval=timedelta(days=1))
def print_hello():
return 'Hello world!'
#---------------------------------------------------------------------
# first operator
date_operator = BashOperator(
task_id='date_task',
bash_command='date',
dag=dag)
#---------------------------------------------------------------------
# second operator
sleep_operator = BashOperator(
task_id='sleep_task',
depends_on_past=False,
bash_command='sleep 5',
dag=dag)
#---------------------------------------------------------------------
# third operator
hello_operator = PythonOperator(
task_id='hello_task',
python_callable=print_hello,
dag=dag)
#---------------------------------------------------------------------
# dependencies
sleep_operator.set_upstream(date_operator)
hello_operator.set_upstream(da复制代码
Python代码验证
python hello_world.py复制代码
Airflow编译运行
airflow list_dags
airflow list_tasks dag_name
airflow test dag_name task_name date
#清空任务实例
airflow clear dag_id 复制代码
Sqoop
测试环境配置
静态网关
为了方便测试,将本机(Windows)的网关设为静态。
关闭防火墙
MySQL设置
# 以下改动针对MySQL数据库,操作系统为Windows10
# 针对sqoop添加用户并授权
[mysql]
CREATE USER sqoop@localhost IDENTIFIED BY 'xxxxxx';
grant all privileges on *.* to 'sqoop'@'%' identified by 'xxxxxx' with grant option;
flush privileges;
# 重启服务器
exit
[bash]
service mysqld restart
# 账户测试
mysql -u af -p
show databases复制代码
测试
连接测试
sqoop list-databases --connect jdbc:mysql://10.0.11.99/ --username sqoop -P
sqoop list-tables --connect jdbc:mysql://10.0.11.xx/database_name--username sqoop -P
sqoop import --connect jdbc:mysql://10.0.11.xx/database_name --username sqoop -password xxxxxx-table table_name复制代码
MySQL等数据库,提供自己的传输方式,可以大大加速抽取的速度。
sqoop import --connect jdbc:mysql://10.0.11.xx/database_name-- username sqoop -password xxxxxx-table table_name --direct复制代码
脚本导入
create database if not exists shell_db comment "data import with script" location '/user/hive/warehouse/shell_db';复制代码
编写全量抽取覆盖脚本,hive和sqoop不区分表名和字段的大小写。
#!/bin/bash
local_db_address='10.0.11.xx'
db_name='shell_db'
tables=(cjd jgtzd rkd scjh scjld zcjh)
for table_name in ${tables[@]};
do
sqoop import \
--connect jdbc:mysql://$local_db_address/gnbz \
--direct \
--username sqoop \
--password xxxxxx \
--table $table_name \
--m 2 \
--hive-import \
--hive-overwrite \
--delete-target-dir \
--hive-database $db_name;
don复制代码
定时任务
Note that if you run a DAG on a schedule_interval of one day, the run stamped 2016-01-01 will be trigger soon after 2016-01-01T23:59. In other words, the job instance is started once the period it covers has ended.
Airflow什么时候开始执行任务?实际上是从dag的start_date + schedule_interval开始的,如果schedule_interval设成@daily,那么会从start_date之后的一天开始。
整合
使用airflow完成每日对两个表的定时全量更新,然后将他们的部分字段组合成一个表。
用到的脚本一共有三个,使用一个Python文件作文DAG调度他们。
脚本
qw_import.sh
#!/bin/bash
db_address='192.168.200.xx'
db_name='dw1'
tables=(BIStoreFGReceive)
for table_name in ${tables[@]};
do
sqoop import \
--connect jdbc:mysql://$db_address/db_qw \
--direct \
--username ljw1 \
--password xxx \
--table $table_name \
--m 1 \
--hive-import \
--hive-overwrite \
--delete-target-dir \
--hive-table $table_name \
--hive-database $db_name;
don复制代码
kfq_import.sh
#!/bin/bash
db_address='192.168.200.xx4'
db_name='dw1'
tables=(RKD)
for table_name in ${tables[@]};
do
sqoop import \
--connect jdbc:mysql://$db_address/db_kaifaqu \
--direct \
--username ljw1 \
--password xxxxxx \
--table $table_name \
--m 1 \
--hive-import \
--hive-overwrite \
--delete-target-dir \
--hive-table $table_name \
--hive-database $db_name;
don复制代码
hive_comb.sql
-- 如果不存在则新建表
CREATE TABLE IF NOT EXISTS dw1.d_output(
storage_date timestamp,
unit_area DOUBLE,
storage_qty DOUBLE,
base_no INT)
ROW FORMAT DELIMITED FIELDS TERMINATED BY '\t';
-- 清空现有表中数据
truncate table dw1.d_output;
-- 插入老ERP数据
insert into dw1.d_output
select
cast(date_format(substr(ReceiveDate,1,10),'yyyy-MM-dd') as timestamp) as storage_date,
UnitArea as unit_area,
ReceiveQty as storage_qty,
6 as base_no
from dw1.bistorefgreceive;
-- 插入企望数据
insert into dw1.d_output
select
cast(date_format(substr(rkrq,1,10),'yyyy-MM-dd') as timestamp) as storage_date,
cpmj as unit_area,
rksl as storage_qty,
8 as base_no
from dw1.rk复制代码
DAG
# -*- coding: utf-8 -*-
import airflow
from airflow import DAG
from airflow.operators.bash_operator import BashOperator
from airflow.operators.python_operator import PythonOperator
from airflow.operators.email_operator import EmailOperator
from datetime import timedelta, datetime
from airflow.utils.trigger_rule import TriggerRule
default_args = {
'owner': 'jin',
'depends_on_past': False,
'start_date': datetime(2020, 4, 12, 18),
'email': ['jwli@aiit.org.cn'],
'email_on_failure': False,
'email_on_retry': False,
'retries': 1,
'retry_delay': timedelta(minutes=5),
}
dag_sqool_import = DAG(
dag_id="daily_task",
default_args=default_args,
description='import and combine tasks',
schedule_interval=timedelta(days=1))
# --------------------------------------------------------------------
kfq_script = "/home/script/kfq_import_all.sh"
qw_script = "/home/script/qw_import_all.sh"
#jd_script = "/home/script/jindie_import.sh"
hive_script = "/home/script/hive_comb.sql"
task_import_kfq = BashOperator(
task_id='import_kfq',
bash_command=". %s " % kfq_script,
dag=dag_sqool_import)
task_import_qw = BashOperator(
task_id='import_qw',
bash_command=". %s " % qw_script,
dag=dag_sqool_import)
task_combine = BashOperator(
task_id='hive_combine',
bash_command= "hive -f %s " % hive_script,
dag=dag_sqool_import
)
[task_import_kfq, task_import_qw] >> task_co复制代码
运维
CDH
#主节点
/opt/cm-5.15.0/etc/init.d/cloudera-scm-server start
#所有节点
/opt/cm-5.15.0/etc/init.d/cloudera-scm-agent start
# 查询状态
/opt/cm-5.15.0/etc/init.d/cloudera-scm-agent status
/opt/cm-5.15.0/etc/init.d/cloudera-scm-server status
# 查询日志
tail -f /opt/cm-5.15.0/log/cloudera-scm-agent/cloudera-scm-agent.log
tail -f /opt/cm-5.15.0/log/cloudera-scm-agent/cloudera-scm-server.log
# 关闭
/opt/cm-5.15.0/etc/init.d/cloudera-scm-agent stop
/opt/cm-5.15.0/etc/init.d/cloudera-scm-server stop
# 退出安全模式
sudo -uhdfs hdfs dfsadmin -safemode leave
# Datanode健康状况
hdfs datanode
#清空回收站
hdfs dfs -expunge复制代码
airflow
cd /home/airflow/
rm -rf *.pid
# 删除所有pid,然后
airflow webserver -D
airflow scheduler -D
airflow worker -D
airflow flower -D复制代码
Linux
查找文件
find / -name file_name复制代码
Hive
查询表的最后修改时间
先找出表对应的transient_lastDdlTime
SHOW CREATE TABLE table_name;复制代码
或者
show TBLPROPERTIES table_name ('transient_lastDdlTime');复制代码
然后将该值代入以下query
SELECT CAST(from_unixtime(your_transient_lastDdlTime_value) AS timestamp);复制代码
或使用网页工具时间转换
错误排查
环境/配置
bash: airflow: command not found
需要添加airflow的系统路径
vi /etc/profile
# 末尾追加以下
export PATH=$PATH:$PYTHON_HOME/bin复制代码
mysql_config: command not found
在安装apache-airflow[mysql]时报错,是因为在安装MySQL时使用了编译安装,缺少了部分repo文件。
wget http://repo.mysql.com/mysql57-community-release-el7-8.noarch.rpm
rpm -ivh mysql57-community-release-el7-8.noarch.rpm
yum install mysql-devel复制代码
Global variable explicit_defaults_for_timestamp needs to be on (1) for mysql
vi /etc/my.cnf
# 在末尾追加
explicit_defaults_for_timestamp=1
# 重启MySQL
systemctl restart mysqld.service复制代码
或者
set @@global.explicit_defaults_for_timestamp=on;
# 重启MySQL
service mysqld restart复制代码
bash: netstat: command not found
yum install net-tools复制代码
登录用户出现‘-bash-4.2$’
原因:是在用useradd添加普通用户时,有时会丢失家目录下的环境变量文件,丢失文件如下:
- .bash_profile
- .bashrc
以上这些文件是每个用户都必备的文件。
方案:使用以下命令从主默认文件/etc/skel/下重新拷贝一份配置信息到此用户的家目录下。
cp /etc/skel/.bashrc /home/airflow
cp /etc/skel/.bash_profile /home/airflow复制代码
ssh: connect to host localhost port 22: Connection refused
yum install openssh-server复制代码
Airflow
Internal Server Error 500
原因:服务器没有正常启动。
方案:清空AIRFLOW_HOME下的所有out,err,log和pid文件,杀掉所有airflow相关的进程,然后重新启动airflow服务。
lockfile.AlreadyLocked: /home/airflow/airflow-webserver-monitor.pid is already locked 等类似问题
原因:进程ID被占用。
方案:清空AIRFLOW_HOME下的所有err和log文件,杀掉所有airflow相关的进程。
Sqoop
Hive
Job Submission failed with exception 'org.apache.hadoop.security.AccessControlException(Permission denied: user=root, access=WRITE, inode="/user":hdfs:supergroup:drwxr-xr-x
方案:创建root路径
# su - hdfs
$ hdfs dfs -mkdir /user/root
$ hdfs dfs -chown root:root /user/root复制代码
如果已经有了/user/root ,查看下文件的权限
[root@dn001 ~]# hdfs dfs -ls /user复制代码
改为root所有:
# hdfs dfs -chown root:root /user/root
hdfs dfs -chmod 777 /user/root复制代码
或:
然后重启HDFS服务器。
日志空间不足
修改配置
- CM管理控制台查看告警内容,很多都是日志空间不足。进入每个服务的配置页面,点击筛选“日志”,将每一个的最大日志文件备份从10改为2
- 在CM管理控制台,点击进去HDFS的配置页面,输入:dfs.replication,查看为3,改为2
- 登录集群的机器,输入命令hadoop fs -setrep -R 2 /,重启
- 重启完毕,查看主机存储,发现有些不平衡。故登录CM管理控制台的HDFS界面,点击操作,选择重新平衡。平衡完毕,各个主机的存储基本平衡。
修改的组件:
HDFS、YARN
查询HDFS存储情况
hadoop dfsadmin -report复制代码
清除tmp中的monitor文件
清理回收站
hadoop fs -expunge复制代码
参考资料
[Airflowv1.10]任务调度平台的安装教程
Command Line Interface Reference