This page shows how to use a pre-built Docker image available at DockerHub in order to operate Hive on MR3 with Minikube. All components (Metastore, HiveServer2, MR3 DAGAppMaster) will be running inside Minikube. For Metastore, we will run a MySQL database as a Docker container, although an existing MySQL database is also okay to use. By following the instruction, the user will learn:

  1. how to start Metastore
  2. how to run Hive on MR3
  3. how to create Beeline connections and send queries to HiveServer2 running inside Minikube

This scenario has the following prerequisites:

  • A running Minikube cluster should be available.
  • The user should be able to execute: 1) command docker if no MySQL database is available; 2) command kubectl.
  • A MySQL connector should be available.

This scenario should take less than 30 minutes to complete, not including the time for downloading a pre-built Docker image. This page has been tested with MR3 release 1.0 on CentOS 7.5 running Minikube v1.2.0 using user gla.

Installation

Download an MR3 release containing the executable scripts.

$ wget https://github.com/mr3project/mr3-release/releases/download/v1.0/mr3-1.0-run.tar.gz
$ gunzip -c mr3-1.0-run.tar.gz | tar xvf -;
$ cd mr3-1.0-run/kubernetes

Starting a MySQL database

For simplicity, we will run a MySQL database for Metastore as a Docker container.

$ docker run -d --name mysql-server -p 3306:3306 -e MYSQL_ROOT_PASSWORD=passwd mysql:5.6
$ mysql --user=root --password=passwd --host=127.0.0.1 -e 'show databases;'
+--------------------+
| Database           |
+--------------------+
| information_schema |
| mysql              |
| performance_schema |
+--------------------+

Creating local directories

In our scenario, Hive on MR3 uses four kinds of Pods: Metastore Pod, HiveServer2 Pod, DAGAppMaster Pod, and ContainerWorker Pod. A Metastore Pod runs a Metastore container, and the user creates a Metastore Pod by executing the script run-metastore.sh. A HiveServer2 Pod runs a HiveServer2 container, and the user creates a HiveServer2 Pod by executing the script run-hive.sh. A DAGAppMaster Pod is created by HiveServer2, and a ContainerWorker Pod runs a ContainerWorker container and is created by DAGAppMaster at runtime.

We need to create two new local directories:

  1. for a PersistentVolume to be shared by all Pods;
  2. for a hostPath volume where ContainerWorker Pods write intermediate data.

Create a local directory for the PersistentVolume.

$ mkdir /data1/gla/workdir
$ chmod 777 /data1/gla/workdir 

Create a local directory for the hostPath volume for ContainerWorker Pods.

$ mkdir -p /data1/gla/k8s
$ chmod 777 /data1/gla/k8s

Preparing a MySQL connector

The user should have a MySQL connector compatible with the MySQL database for Metastore. One can download the official JDBC driver for MySQL at https://dev.mysql.com/downloads/connector/j/.

Copy the MySQL connector to the directory /lib under the local directory for the PersistentVolume.

$ mkdir -p /data1/gla/workdir/lib
$ cp mysql-connector-java-8.0.17.jar /data1/gla/workdir/lib/
$ chmod 777 /data1/gla/workdir/lib/mysql-connector-java-8.0.17.jar

Configuring Pods

Open yaml/workdir-pv.yaml and create a hostPath PersistentVolume using the directory created in the previous step.

$ vi yaml/workdir-pv.yaml

  hostPath:
     path: "/data1/gla/workdir"

Open yaml/hiveserver2-service.yaml and use the IP address of the local machine.

$ vi yaml/hiveserver2-service.yaml

  externalIPs:
  - 111.111.111.11        # use your IP address

Open env.sh and set the following environment variables.

$ vi env.sh

DOCKER_HIVE_IMG=mr3project/hive3:1.0
DOCKER_HIVE_WORKER_IMG=mr3project/hive3:1.0

CREATE_KEYTAB_SECRET=false            # do not create a Secret from key/*

HIVE_DATABASE_HOST=111.111.111.11     # use your IP address (where the MySQL database is running)
HIVE_WAREHOUSE_DIR=/opt/mr3-run/work-dir/warehouse

METASTORE_SECURE_MODE=false           # disable Kerberos authentication

HIVE_SERVER2_HEAPSIZE=8192
HIVE_SERVER2_AUTHENTICATION=NONE

TOKEN_RENEWAL_HDFS_ENABLED=false

HIVE_METASTORE_HEAPSIZE=8192
HIVE_CLIENT_HEAPSIZE=2048             # heap size for Beeline

Open yaml/metastore.yaml and yaml/hive.yaml, and update the following fields.

  • image is set to a pre-built Docker image mr3project/hive3:1.0 available at DockerHub.
  • imagePullPolicy is set to IfNotPresent because we download the Docker image from DockerHub.
  • args includes "--init-schema" because it is the first time to run Metastore.
  • We mount work-dir-volume because we mount a MySQL connector inside the Metastore Pod.
  • Change the resources if necessary.
$ vi yaml/metastore.yaml 

      containers:
      - image: mr3project/hive3:1.0
        command: ["/opt/mr3-run/hive/metastore-service.sh"]
        args: ["start", "--kubernetes", "--init-schema"]
        imagePullPolicy: IfNotPresent

        resources:
          requests:
            cpu: 1
            memory: 8Gi
          limits:
            cpu: 1
            memory: 8Gi

        volumeMounts:
        - name: work-dir-volume
          mountPath: /opt/mr3-run/lib
          subPath: lib

Open yaml/hive.yaml and update image and imagePullPolicy so that Minikube reads the pre-built Docker image from DockerHub. Change the resources if necessary.

$ vi yaml/hive.yaml 

      containers:
      - image: mr3project/hive3:1.0
        imagePullPolicy: IfNotPresent

        resources:
          requests:
            cpu: 1
            memory: 8Gi
          limits:
            cpu: 1
            memory: 8Gi

Open conf/mr3-site.xml and set the configuration key mr3.k8s.pod.image.pull.policy to IfNotPresent. Set the configuration key mr3.k8s.pod.worker.hostpaths to the local directory for the hostPath PersistentVolume.

$ vi conf/mr3-site.xml 

<property>
  <name>mr3.k8s.pod.image.pull.policy</name>
  <value>IfNotPresent</value>
</property>

<property>
  <name>mr3.k8s.pod.worker.hostpaths</name>
  <value>/data1/gla/k8s</value>
</property>

Update conf/hive-site.xml.

$ vi conf/hive-site.xml 

<property>
  <name>javax.jdo.option.ConnectionUserName</name>
  <value>root</value>
</property>

<property>
  <name>javax.jdo.option.ConnectionPassword</name>
  <value>passwd</value>
</property>

<property>
  <name>hive.metastore.pre.event.listeners</name>
  <value></value>
</property>
<property>
  <name>metastore.pre.event.listeners</name>
  <value></value>
</property>

<property>
  <name>hive.security.authorization.manager</name>
  <value>org.apache.hadoop.hive.ql.security.authorization.plugin.sqlstd.SQLStdHiveAuthorizerFactory</value> 
</property>
  • javax.jdo.option.ConnectionPassword is set to the password of the MySQL database.
  • hive.metastore.pre.event.listeners and metastore.pre.event.listeners are set to empty because we do not enable security on the Metastore side.

Update conf/core-site.xml.

$ vi conf/core-site.xml 

<property>
  <name>hadoop.security.authentication</name>
  <value>simple</value>
</property>
  • hadoop.security.authentication is set to simple in order to disable Kerberos for authentication.

Starting Hive on MR3

Before running HiveServer2, the user should remove the label node-role.kubernetes.io/master from minikube node. This is because Hive on MR3 does not count the resources of master nodes when estimating the resources for ContainerWorker Pods. Since minikube node, the only node in a Minikube cluster, is a master node, we should demote it to an ordinary node in order to secure resources for ContainerWorker Pods. Thus, in order to be able to create ContainerWorker Pods in minikube node, the user should execute the following command:

$ kubectl label node minikube node-role.kubernetes.io/master-

In order to run Metastore, the user can execute the script run-metastore.sh.

$ ./run-metastore.sh
...
CLIENT_TO_AM_TOKEN_KEY=ad22f422-a6b7-4bcc-a821-48ec101cfb39
MR3_APPLICATION_ID_TIMESTAMP=16119
MR3_SHARED_SESSION_ID=88bcfb02-3a4c-44e2-9864-96b4fceb81cd
ATS_SECRET_KEY=d93733b6-87e1-4c9b-8713-8a73a43aaa9a
configmap/client-am-config created
statefulset.apps/hivemr3-metastore created
service/metastore created

In order to run HiveServer2, the user can execute the script run-hive.sh.

$ ./run-hive.sh 
...
CLIENT_TO_AM_TOKEN_KEY=e36e7145-f90c-4575-b827-d26a998fea1b
MR3_APPLICATION_ID_TIMESTAMP=18581
MR3_SHARED_SESSION_ID=9900a5ec-17c6-4e5a-97f6-9b04de469b09
ATS_SECRET_KEY=08256518-a5e7-4c20-be28-4616ad7c9aa4
Error from server (AlreadyExists): configmaps "client-am-config" already exists
replicationcontroller/hivemr3-hiveserver2 created
service/hiveserver2 created

These scripts mount the following files inside the Metastore and HiveServer2 Pods:

  • env.sh
  • conf/*

In this way, the user can completely specify the behavior of Metastore and HiveServer2 as well as DAGAppMaster and ContainerWorkers.

Executing the script run-hive.sh starts a HiveServer2 Pod and a DAGAppMaster Pod in a moment.

$ kubectl get pods -n hivemr3
NAME                        READY   STATUS    RESTARTS   AGE
hivemr3-hiveserver2-9frvz   1/1     Running   0          54s
hivemr3-metastore-0         1/1     Running   0          3m43s
mr3master-6119-0            1/1     Running   0          36s

Running Beeline

Download a sample dataset and copy it to the directory for the PersistentVolume.

$ wget https://github.com/mr3project/mr3-release/releases/download/v1.0/pokemon.csv
$ cp pokemon.csv /data1/gla/workdir
$ chmod 777 /data1/gla/workdir/pokemon.csv 

The user can verify that the sample dataset is accessible inside the HiveServer2 Pod.

$ kubectl exec -n hivemr3 -it hivemr3-hiveserver2-9frvz -- /bin/bash
bash-4.2$ ls /opt/mr3-run/work-dir/pokemon.csv 
/opt/mr3-run/work-dir/pokemon.csv
bash-4.2$ exit

The user may use any client program to connect to HiveServer2. In our example, we run Beeline inside the Hiveserver2 Pod.

$ kubectl exec -n hivemr3 -it hivemr3-hiveserver2-9frvz -- /bin/bash 
bash-4.2$ export USER=hive
bash-4.2$ /opt/mr3-run/hive/run-beeline.sh
...
Connecting to jdbc:hive2://hivemr3-hiveserver2-9frvz:9852/;;;
Connected to: Apache Hive (version 3.1.2)
Driver: Hive JDBC (version 3.1.2)
Transaction isolation: TRANSACTION_REPEATABLE_READ
Beeline version 3.1.2 by Apache Hive
0: jdbc:hive2://hivemr3-hiveserver2-9frvz:985> 

Use the default database.

0: jdbc:hive2://hivemr3-hiveserver2-9frvz:985> show databases;
+----------------+
| database_name  |
+----------------+
| default        |
+----------------+
1 row selected (2.187 seconds)
0: jdbc:hive2://hivemr3-hiveserver2-9frvz:985> use default;

Create a table called pokemon.

0: jdbc:hive2://hivemr3-hiveserver2-9frvz:985> CREATE TABLE pokemon (Number Int,Name String,Type1 String,Type2 String,Total Int,HP Int,Attack Int,Defense Int,Sp_Atk Int,Sp_Def Int,Speed Int) row format delimited fields terminated BY ',' lines terminated BY '\n' tblproperties("skip.header.line.count"="1");

Import the sample dataset.

0: jdbc:hive2://hivemr3-hiveserver2-9frvz:985> load data local inpath '/opt/mr3-run/work-dir/pokemon.csv' INTO table pokemon;

Execute queries.

0: jdbc:hive2://hivemr3-hiveserver2-9frvz:985> select avg(HP) from pokemon;
...
0: jdbc:hive2://hivemr3-hiveserver2-9frvz:985> create table pokemon1 as select *, IF(HP>160.0,'strong',IF(HP>140.0,'moderate','weak')) AS power_rate from pokemon;
...
0: jdbc:hive2://hivemr3-hiveserver2-9frvz:985> select COUNT(name), power_rate from pokemon1 group by power_rate;
...
+------+-------------+
| _c0  | power_rate  |
+------+-------------+
| 363  | strong      |
| 336  | weak        |
| 108  | moderate    |
+------+-------------+
3 rows selected (1.874 seconds)

Now we see that new ContainerWorker Pods have been created.

$ kubectl get pods -n hivemr3                                        
NAME                        READY   STATUS    RESTARTS   AGE
hivemr3-hiveserver2-9frvz   1/1     Running   0          6m22s
hivemr3-metastore-0         1/1     Running   0          9m11s
mr3master-6119-0            1/1     Running   0          6m4s
mr3worker-fe82-1            1/1     Running   0          72s
mr3worker-fe82-2            1/1     Running   0          40s

The user can find the warehouse directory /data1/gla/workdir/warehouse/.

$ ls /data1/gla/workdir/warehouse
pokemon  pokemon1

Stopping Hive on MR3

Delete ReplicationController for HiveServer2.

$ kubectl -n hivemr3 delete replicationcontroller hivemr3-hiveserver2
replicationcontroller "hivemr3-hiveserver2" deleted

Deleting ReplicationController for HiveServer2 does not automatically terminate the DAGAppMaster Pod. This is a feature, not a bug, which is due to the support of high availability in Hive on MR3. (After setting environment variable MR3_APPLICATION_ID_TIMESTAMP properly, running run-hive.sh attaches the existing DAGAppMaster Pod to the new HiveServer2 Pod.)

Delete DAGAppMaster Pod.

$ kubectl delete pod -n hivemr3 mr3master-6119-0

Deleting DAGAppMaster Pod automatically deletes all ContainerWorker Pods as well.

Delete StatefulSet for MetaStore.

$ kubectl -n hivemr3 delete statefulset hivemr3-metastore

Now no Pods should be running in the namespace hivemr3. To delete all remaining resources, execute the following command:

$ kubectl -n hivemr3 delete configmap --all; kubectl -n hivemr3 delete svc --all; kubectl -n hivemr3 delete secret --all; kubectl -n hivemr3 delete serviceaccount hive-service-account; kubectl -n hivemr3 delete role --all; kubectl -n hivemr3 delete rolebinding --all; kubectl delete clusterrole node-reader; kubectl delete clusterrolebinding hive-clusterrole-binding; kubectl -n hivemr3 delete persistentvolumeclaims workdir-pvc; kubectl delete persistentvolumes workdir-pv