centos7.2上安装CDH5.16.2及Spark2【原创】

背景:我自己的电脑配置太低,想在centos操作系统上安装CDH5.1.2并配置集群,我去阿里云上买了3台按流量计费的阿里云服务器。

大家一定要注意,配置,购买的阿里云服务器不要太低了。建议:3台2核8G内存的阿里云服务器。测试完毕后,请及时释放掉这三台服务器,否则阿里云会继续计费,很快消耗掉账户里面的钱。我花了不到10元,就完成了测试。

当前环境

操作系统:CentOS7.2

CDH版本:5.16.2

CM版本:5.16.2

Spark2版本:

3台2核8G的阿里云ECS服务器[测试完,已释放了这三台linux服务器]:

3台服务器的账户及密码

账户:root
密码:Root123
==================
aliyun_hadoop001
172.17.238.7

aliyun_hadoop002
172.17.238.8

aliyun_hadoop001
172.17.238.9


阿里云重新发明了“按量付费“这个词,不是按照正常人的思维定义的,而是按照他们自己的规则定义的。除非你彻底删除这个实例包括所有数据,否则计费是不会停止的。所有其他公有云包括AWS,Azure,GCE等都不是这样,都是停机就停止计费,再开机继续运行,所有数据都存在;当然,这个计费针对的是计算能力也就是CPU和内存。网络流量,公网IP,磁盘等有其他的计费规则;
阿里云的“按量计费”翻译成大白话就是:假设你买了包月的ECS,那么哪怕你1小时后后悔了不使用这个ECS了一整个月的钱照收不误,一分钱也不会退还。而“按量计费”的话,你付出比包月贵几倍的单价为代价,你可以1小时后后悔的时候将其彻底删除,计费也就停止了。然而,和包月包年一样的是,不管你使用还是停机,计费都不会停止的,而“按量计费”你可以提前用彻底终止实例并删除所有数据的方法终止计费,这就是阿里云理解的“按量计费”。。


CDH搭建Hadoop集群(Centos7) https://www.cnblogs.com/frankdeng/articles/10136230.html

特别注意,请安装如下依赖
#为了安装mysql服务
yum install libaio
#为了hue服务,需要提前安装环境 httpd, mod_ssl
yum install mod_ssl
yum install httpd
yum -y install libxml2-python #不确定是否是这个原因,但是安装上也不会有什么坏处
yum -y install libxml2-devel libxslt-devel


配置ip和hostname的映射

vi /etc/hosts
文件中追加如下内容:

172.17.238.7 hadoop001
172.17.238.8 hadoop002
172.17.238.9 hadoop003


======================
ntp服务
======================
关闭防火墙

#查看防火墙状态
service firewalld status
或者
systemctl status firewalld

#临时关闭防火墙
service firewalld stop
或者
systemctl stop firewalld

# 永久关闭防火墙
chkconfig firewalld off


======================
关闭SELINUX

vi /etc/selinux/config

#修改SELINUX的值:

#修改前:
SELINUX=endorcing
#修改后:
SELINUX=disabled

======================
免密配置

核心命令:
ssh-keygen
ssh-copy-id
scp

命令scp教程: https://www.runoob.com/linux/linux-comm-scp.html


具体操作:
#在本机生成对密钥

# -t rsa,表示使用rsa的密钥使用rsa算法;
# -P '',表示密码为空;
# -f ~/.ssh/id_rsa,表示生成的密钥保存在当前用户的家目录的.ssh目录下,文件名为:id_rsa
# 前置:当前目录可以是任何目录,下面这句话明确表示密钥对生成后保存到:~/.ssh/,私钥文件名:id_

ssh-keygen -t rsa -P '' -f ~/.ssh/id_rsa


#将本机的当前用户的密钥,添加到另外一台用户的authorized_keys
ssh-copy-id tjnode02


#将本机的文件拷贝到node01的相同的目录下,注意:`pwd`标识当前路径,不是单引号,是数字1前面的反引号。
#前置条件:cd ~/.ssh
scp authorized_keys tjnode01:`pwd`

#测试免密
#前置:当前在node02,免密登录到tjnode01,tjnode03
ssh tjnode01
ssh tjnode03

#同时,也测试一下,从tjnode01,免密登录到tjnode02,tjnode03
#同时,也测试一下,从tjnode03,免密登录到tjnode01,tjnode02

======================
安装jdk:


mkdir /usr/java
cd /opt/software
tar -zxvf jdk-8u221-linux-x64.tar.gz -C /usr/java


2.配置环境变量:vi /etc/profile
vi /etc/profile


export JAVA_HOME=/usr/java/jdk1.8.0_221
export PATH=$JAVA_HOME/bin:$PATH
export CLASSPATH=.:$JAVA_HOME/lib/dt.jar:$JAVA_HOME/lib/tools.jar

======================
安装配置MySql

(主节点安装即可--这里将tjnode01作为主节点)

1.卸载mariadb

rpm -qa|grep mariadb

rpm -e --nodeps mariadb的包名


Linux解压rar: https://blog.csdn.net/jacson_bai/article/details/85230060
1.下载rar包

wget https://www.rarlab.com/rar/rarlinux-x64-5.6.1.tar.gz
tar xf rarlinux-x64-5.6.1.tar.gz
cp rar/rar rar/unrar /usr/bin
rm -rf rar rarlinux-x64-5.6.1.tar.gz
至此,rar压缩和解压包安装完成

2.解压命令简析

将*.rar压缩文件解压到当前文件目录
rar e *.rar 

解压带密码的rar压缩文件
rar e -p *.rar
在弹出的交互式里面输入密码即可
————————————————
版权声明:本文为CSDN博主「Python兔子」的原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/jacson_bai/article/details/85230060


[root@hadoop001 mysql-5.7.21-1.el7.x86_64.rpm-bundle]# ll
total 580032
-rw-r--r-- 1 root root 25107316 Dec 28 2017 mysql-community-client-5.7.21-1.el7.x86_64.rpm
-rw-r--r-- 1 root root 278844 Dec 28 2017 mysql-community-common-5.7.21-1.el7.x86_64.rpm
-rw-r--r-- 1 root root 3779988 Dec 28 2017 mysql-community-devel-5.7.21-1.el7.x86_64.rpm
-rw-r--r-- 1 root root 46256768 Dec 28 2017 mysql-community-embedded-5.7.21-1.el7.x86_64.rpm
-rw-r--r-- 1 root root 24078148 Dec 28 2017 mysql-community-embedded-compat-5.7.21-1.el7.x86_64.rpm
-rw-r--r-- 1 root root 128571868 Dec 28 2017 mysql-community-embedded-devel-5.7.21-1.el7.x86_64.rpm
-rw-r--r-- 1 root root 2238596 Dec 28 2017 mysql-community-libs-5.7.21-1.el7.x86_64.rpm
-rw-r--r-- 1 root root 2115904 Dec 28 2017 mysql-community-libs-compat-5.7.21-1.el7.x86_64.rpm
-rw-r--r-- 1 root root 55662616 Dec 28 2017 mysql-community-minimal-debuginfo-5.7.21-1.el7.x86_64.rpm
-rw-r--r-- 1 root root 171890056 Dec 28 2017 mysql-community-server-5.7.21-1.el7.x86_64.rpm
-rw-r--r-- 1 root root 15289580 Dec 28 2017 mysql-community-server-minimal-5.7.21-1.el7.x86_64.rpm
-rw-r--r-- 1 root root 118654584 Dec 28 2017 mysql-community-test-5.7.21-1.el7.x86_64.rpm
[root@hadoop001 mysql-5.7.21-1.el7.x86_64.rpm-bundle]# rpm -ivh mysql-community-common-5.7.21-1.el7.x86_64.rpm
warning: mysql-community-common-5.7.21-1.el7.x86_64.rpm: Header V3 DSA/SHA1 Signature, key ID 5072e1f5: NOKEY
Preparing... ################################# [100%]
Updating / installing...
1:mysql-community-common-5.7.21-1.e################################# [100%]
[root@hadoop001 mysql-5.7.21-1.el7.x86_64.rpm-bundle]# rpm -ivh mysql-community-libs-5.7.21-1.el7.x86_64.rpm
warning: mysql-community-libs-5.7.21-1.el7.x86_64.rpm: Header V3 DSA/SHA1 Signature, key ID 5072e1f5: NOKEY
Preparing... ################################# [100%]
Updating / installing...
1:mysql-community-libs-5.7.21-1.el7################################# [100%]
[root@hadoop001 mysql-5.7.21-1.el7.x86_64.rpm-bundle]# rpm -ivh mysql-community-libs-compat-5.7.21-1.el7.x86_64.rpm
warning: mysql-community-libs-compat-5.7.21-1.el7.x86_64.rpm: Header V3 DSA/SHA1 Signature, key ID 5072e1f5: NOKEY
Preparing... ################################# [100%]
Updating / installing...
1:mysql-community-libs-compat-5.7.2################################# [100%]
[root@hadoop001 mysql-5.7.21-1.el7.x86_64.rpm-bundle]# rpm -ivh mysql-community-client-5.7.21-1.el7.x86_64.rpm
warning: mysql-community-client-5.7.21-1.el7.x86_64.rpm: Header V3 DSA/SHA1 Signature, key ID 5072e1f5: NOKEY
Preparing... ################################# [100%]
Updating / installing...
1:mysql-community-client-5.7.21-1.e################################# [100%]

#### 在安装mysql-community-server-5.7.20-1.el7.x86_64.rpm前需要安装libaio-0.3.107-10.el6.x86_64.rpm
#### 如果有网络:yum install libaio

[root@hadoop001 mysql-5.7.21-1.el7.x86_64.rpm-bundle]# rpm -ivh mysql-community-server-5.7.21-1.el7.x86_64.rpm
warning: mysql-community-server-5.7.21-1.el7.x86_64.rpm: Header V3 DSA/SHA1 Signature, key ID 5072e1f5: NOKEY
Preparing... ################################# [100%]
Updating / installing...
1:mysql-community-server-5.7.21-1.e################################# [100%]

vim /etc/my.cnf

重启mysql服务 systemctl restart mysqld.service

获取初始密码
cat /var/log/mysqld.log | grep password

注意:修改密码的复杂度
/etc/my.cfg,添加如下,降低密码安全要求:

#0(LOW),1(MEDIUM),2(STRONG)
validate_password_policy=0
validate_password_length=3
validate_password_number_count=0
validate_password_mixed_case_count=0
validate_password_special_char_count=0


将初始密码复制下来,输入如下命令登陆mysql :
mysql -uroot -p
将复制的密码粘贴到命令行中,进入了mysql,使用如下命令修改密码:
set password=password('root1234');
flush privileges;
添加远程访问权限:
GRANT ALL PRIVILEGES ON *.* TO 'root'@'%' IDENTIFIED BY 'root1234' WITH GRANT OPTION;
flush privileges;
重启mysql服务即可使用。

安装完后:需要创建以下5个mysql数据库:hive 和oozie作为hadoop的核心功能
CREATE DATABASE hive DEFAULT CHARACTER SET utf8 DEFAULT COLLATE utf8_general_ci;
CREATE DATABASE oozie DEFAULT CHARACTER SET utf8 DEFAULT COLLATE utf8_general_ci;

CREATE DATABASE activity DEFAULT CHARACTER SET utf8 DEFAULT COLLATE utf8_general_ci;
CREATE DATABASE hue DEFAULT CHARACTER SET utf8 DEFAULT COLLATE utf8_general_ci;
CREATE DATABASE reports DEFAULT CHARACTER SET utf8 DEFAULT COLLATE utf8_general_ci;

SHOW VARIABLES LIKE 'validate_password%';
SET GLOBAL validate_password_policy=LOW;

GRANT ALL ON hive.* TO 'root'@'%' IDENTIFIED BY 'root1234';
GRANT ALL ON oozie.* TO 'root'@'%' IDENTIFIED BY 'root1234';
GRANT ALL ON activity.* TO 'root'@'%' IDENTIFIED BY 'root1234';
GRANT ALL ON hue.* TO 'root'@'%' IDENTIFIED BY 'root1234';
GRANT ALL ON reports.* TO 'root'@'%' IDENTIFIED BY 'root1234';

FLUSH PRIVILEGES;

=================
安装cloudera-manager:

* 1、安装Cloudera Manager Server、Agent

- mkdir /opt/cloudera-manager
- tar xvzf cloudera-manager*.tar.gz -C /opt/cloudera-manager

注意:所有节点都要创建目录:/opt/cloudera-manager 


* 2、配置CM Agent


--- 修改文件 vi /opt/cloudera-manager/cm-5.16.2/etc/cloudera-scm-agent/config.ini中server_host


* 3、创建用户 cloudera-scm

- useradd --system --no-create-home --shell=/bin/false --comment "Cloudera SCM User" cloudera-scm
说明:新创建的用户cloudera-scm,不能远程登录,没有家目录

下面第5步骤中,需要用到该用户。将资源和用户捆绑到这里。
做到: 用户、权限、资源,三位一体 


* 4、创建Parcel目录


- Server节点(仅仅主服务器)
-- mkdir -p /opt/cloudera/parcel-repo
-- chown cloudera-scm:cloudera-scm /opt/cloudera/parcel-repo
- Agent节点(所有的服务器)
-- mkdir -p /opt/cloudera/parcels
-- chown cloudera-scm:cloudera-scm /opt/cloudera/parcels

* 5、配置CM Server数据库


--- 拷贝mysql jar文件到目录 /usr/share/java/,该目录如果不存在,则先创建该目录
--- 注意jar包名称要修改为mysql-connector-java.jar

--- grant all on *.* 'temp'@'%' identified by 'temp' with grant option; 这句话:创建一个msyql的账户temp,当然你可以起一个知名见意的好名字,例如:cmadmin
降低mysql 5.7的密码强度设置:/etc/my.cfg,添加如下,降低密码安全要求,见如下
/etc/my.cfg,添加如下,降低密码安全要求:

#0(LOW),1(MEDIUM),2(STRONG)
validate_password_policy=0
validate_password_length=3
validate_password_number_count=0
validate_password_mixed_case_count=0
validate_password_special_char_count=0

--- ./scm_prepare_database.sh mysql temp -h node01 -utemp -ptemp --scm-host node01 scm scm scm
--- 格式:数据库类型、数据库、数据库服务器、用户名、密码、cm server服务器

### 只在服务器,执行
cd /opt/cloudera-manager/cm-5.16.2/share/cmf/schema

线上:[root@tjnode01 schema]# ./scm_prepare_database.sh mysql cm -hhadoop001 -uroot -proot1234 --scm-host thadoop001 scm scm scm

查找文件scm_prepare_database.sh的路径:
[root@hadoop001 cm-5.16.2]# pwd
/opt/cloudera-manager/cm-5.16.2


[root@hadoop001 cm-5.16.2]# find . -name scm_prepare_database.sh
./share/cmf/schema/scm_prepare_database.sh

说明:
scm_prepare_database.sh文件路径:/opt/cloudera-manager/cm-5.16.2/share/cmf/schema/scm_prepare_database.sh

报错:java.sql.SQLException: Access denied for user 'scm'@'hadoop001' (using password: YES)
解决办法:

GRANT ALL ON cm.* TO 'scm'@'%' IDENTIFIED BY 'scm';

删除数据库:drop database cm;

完美解决问题。

====================================================
启动server
cd /opt/cloudera-manager/cm-5.16.2/etc/init.d/

./cloudera-scm-server start

启动agent:

cd /opt/cloudera-manager/cm-5.16.2/etc/init.d/
./cloudera-scm-agent start

界面安装CDH

http://39.107.100.95:7180/


已启用透明大页面压缩,可能会导致重大性能问题。请运行“echo never > /sys/kernel/mm/transparent_hugepage/defrag”
和“echo never > /sys/kernel/mm/transparent_hugepage/enabled”以禁用此设置,然后将同一命令添加到 /etc/rc.local 等初始化脚本中,以便在系统重启时予以设置。以下主机将受到影响:

echo never > /sys/kernel/mm/transparent_hugepage/defrag
echo never > /sys/kernel/mm/transparent_hugepage/enabled

vi /etc/rc.local

添加:
echo never > /sys/kernel/mm/transparent_hugepage/defrag
echo never > /sys/kernel/mm/transparent_hugepage/enabled

然后在分配角色的时候注意:
zookeeper,请保证奇数台服务器上安装。

Hbase Trift server请安装到和hue server在同一台服务器上。

数据库:
hive
oozie
activity
hue
reports

数据库账户:root
数据库密码:root1234

到这里基本都差不多了,继续下去可能会出现一些问题,可以继续向下看,如果遇到和我一样的问题,如下是我的解决办法,仅供参考学习!!!


下面是安装的错误、排查错误的思路及解决办法,仅供参考:


Hue: 报错误:Unexpected error. Unable to verify database connection.

先查看日志:
[root@hadoop001 init.d]# cat /opt/cloudera-manager/cm-5.16.2/log/cloudera-scm-server/cloudera-scm-server.log

发现日志中报:
ImportError: libxslt.so.1: cannot open shared object file: No such file or directory


原因:OS缺少相关包

解决办法: 安装hue需要的依赖包即可

执行这个一般就可以了:yum -y install libxml2-devel libxslt-devel

如果不行,请执行下面这些:


yum install krb5-devel cyrus-sasl-gssapi cyrus-sasl-deve libxml2-devel libxslt-devel mysql mysql-devel openldap-devel python-devel python-simplejson sqlite-devel -y

————————————————
版权声明:本文为CSDN博主「jimmyxyalj」的原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/xjping0794/article/details/77526760


参见文章:
CDH中安装Hue连接不上数据库 Unexpected error. Unable to verify database connection 完美解决方案
https://blog.csdn.net/xiaobao5214/article/details/83748265


====================================================

CDH安装后,再次安装:spark2

#创建csd目录:
[root@hadoop001 SPARK2-2.1.0.cloudera2-1.cdh5.7.0]# mkdir /opt/cloudera/csd
#下载SPARK2_ON_YARN-2.1.0.cloudera2.jar到路径/opt/cloudera/csd/下
[root@hadoop001 SPARK2-2.1.0.cloudera2-1.cdh5.7.0]# cd /opt/cloudera/csd/
[root@hadoop001 SPARK2-2.1.0.cloudera2-1.cdh5.7.0]# wget http://archive.cloudera.com/spark2/csd/SPARK2_ON_YARN-2.1.0.cloudera2.jar
#修改所有者
[root@hadoop001 csd]# chown cloudera-scm:cloudera-scm SPARK2_ON_YARN-2.1.0.cloudera2.jar
[root@hadoop001 csd]# chmod 644 SPARK2_ON_YARN-2.1.0.cloudera2.jar


#先备份一下 /opt/cloudera/parcel-repo/
注意: 如果有其他的安装包,不用删除 ,但是如果本目录下有其他的重名文件比如manifest.json文件,把它重命名备份一下。然后把那spark2的那3个parcel包的文件放在这里。


# 拷贝spark2的包到 /opt/cloudera/parcel-repo/
[root@hadoop001 SPARK2-2.1.0.cloudera2-1.cdh5.7.0]# cp ./* /opt/cloudera/parcel-repo/
[root@hadoop001 SPARK2-2.1.0.cloudera2-1.cdh5.7.0]# ll /opt/cloudera/parcel-repo/
total 2252428
-rw-r--r-- 1 root root 2132782197 Nov 6 17:52 CDH-5.16.2-1.cdh5.16.2.p0.8-el7.parcel
-rw-r----- 1 root root 1368064 Nov 6 17:55 CDH-5.16.2-1.cdh5.16.2.p0.8-el7.parcel.part
-rw-r--r-- 1 root root 41 Nov 6 17:52 CDH-5.16.2-1.cdh5.16.2.p0.8-el7.parcel.sha
-rw-r----- 1 root root 81526 Nov 6 17:56 CDH-5.16.2-1.cdh5.16.2.p0.8-el7.parcel.torrent
-rw-r--r-- 1 root root 66804 Nov 6 17:52 manifest-cdh.json
-rw-r--r-- 1 root root 4650 Nov 6 19:09 manifest.json
-rw-r--r-- 1 root root 172161150 Nov 6 19:09 SPARK2-2.1.0.cloudera2-1.cdh5.7.0.p0.171658-el7.parcel
-rw-r--r-- 1 root root 41 Nov 6 19:09 SPARK2-2.1.0.cloudera2-1.cdh5.7.0.p0.171658-el7.parcel.sha


[root@hadoop001 SPARK2-2.1.0.cloudera2-1.cdh5.7.0]# cd /opt/sofrware/SPARK2-2.1.0.cloudera2-1.cdh5.7.0
[root@hadoop001 SPARK2-2.1.0.cloudera2-1.cdh5.7.0]# ll
total 168140
-rw-r--r-- 1 root root 4650 Nov 6 17:01 manifest.json
-rw-r--r-- 1 root root 172161150 Nov 6 17:01 SPARK2-2.1.0.cloudera2-1.cdh5.7.0.p0.171658-el7.parcel
-rw-r--r-- 1 root root 41 Nov 6 17:01 SPARK2-2.1.0.cloudera2-1.cdh5.7.0.p0.171658-el7.parcel.sha


参考文章链接:
https://www.jianshu.com/p/6acd6419f697?utm_campaign=maleskine&utm_content=note&utm_medium=seo_notes&utm_source=recommendation

然后:
停掉CM和集群,现在将他们停掉。然后运行命令

 service cloudera-scm-agent restart

service cloudera-scm-server restart


把CM和集群启动起来。然后点击主机->Parcel页面,看是否多了个spark2的选项。如下图,你这里此时应该是分配按钮,点击,等待操作完成后,点击激活按钮


激活后,点击你的群集-》添加服务,添加spark2服务。注意,如果你这里看不到spark2服务,就请检查你的CSD包和parcel包是否对应,上面的步骤是否有漏掉。正常情况下,应该是能用了。

*****CDH5.16.2 不需要这些配置,spark2添加到集群后,就能正确显示spark2的状态 开始*****
4、文件配置
 1、前提交代
  - CDH安装目录 /opt/cloudera/parcels/CDH/
  - SPARK2安装目录 /opt/cloudera/parcels/SPARK2
  - 启动spark2用户名为hadoop
  - 所有配置文件目录为 /etc/
 2、将CDH中spark配置文件拷贝到SPARK2的配置文件中,并配置spark-env.sh文件

#拷贝文件
cp /opt/cloudera/parcels/CDH/etc/spark/conf.dist/* /opt/cloudera/parcels/SPARK2/etc/spark2/conf.dist/
#配置spark-env.sh文件
vim /opt/cloudera/parcels/SPARK2/etc/spark2/conf.dist/spark-env.sh
#添加如下内容
export SPARK_DIST_CLASSPATH=$(hadoop classpath) //指定hadoop class文件目录
export HADOOP_CONF_DIR=/etc/hadoop/conf //指定hadoop配置文件目录

 3、配置启动账户hadoop .bashrc文件

#打开文件
vim /home/hadoop/.bashrc
#添加如下内容
export HADOOP_CONF_DIR=/etc/hadoop_conf
export SPARK_HOME=/opt/cloudera/parcels/SPARK2/lib/spark2
export PATH=$SPARK_HOME/bin:$PATH

作者:bigdata_er
链接:https://www.jianshu.com/p/6acd6419f697
来源:简书
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

*****CDH5.16.2 不需要这些配置 结束*****


到命令行下,运行:spark2-shell命令,报错误:
To adjust logging level use sc.setLogLevel(newLevel). For SparkR, use setLogLevel(newLevel).
19/11/06 19:46:35 ERROR spark.SparkContext: Error initializing SparkContext.
java.lang.IllegalArgumentException: Required executor memory (1024+384 MB) is above the max threshold (1024 MB) of this cluster! Please check the values of 'yarn.scheduler.maximum-allocation-mb'
and/or 'yarn.nodemanager.resource.memory-mb'.

解决办法:
YARN--->ResourceManager--->资源管理:
修改:最大容器内存
yarn.scheduler.maximum-allocation-mb :2G

YARN--->NodeManager--->资源管理:
修改:容器内存
yarn.nodemanager.resource.memory-mb :2G

参见下面这篇文章,有图片

CDH5(5.15.0)中修改spark的yarn.nodemanager.resource.memory-mb和yarn.scheduler.maximum-allocation-mb配置:
https://blog.csdn.net/u013429010/article/details/81809522


#请切换到hdfs账户下,执行spark2-shell

[root@hadoop001 init.d]# su hdfs
[hdfs@hadoop001 init.d]$ spark2-shell


==================================

猜你喜欢

转载自www.cnblogs.com/wangqiideal/p/11808818.html