<?xml version="1.0" encoding="utf-8"?>
<rss xmlns:atom="https://www.w3.org/2005/Atom" xmlns:sy="https://purl.org/rss/1.0/modules/syndication/" xmlns:dc="https://purl.org/dc/elements/1.1/" xmlns:content="https://purl.org/rss/1.0/modules/content/" xmlns:wfw="https://wellformedweb.org/CommentAPI/" xmlns:slash="https://purl.org/rss/1.0/modules/slash/"
  version="2.0">
  <channel>
    <title>Paige's blog</title>
    <atom:link
      href="https://docs.microsoft.com/archive/blogs/pliu/feed.xml"
      rel="self"
      type="application/rss+xml" />
    <link>https://docs.microsoft.com/archive/blogs/pliu/feed.xml</link>
    <description />
    <lastBuildDate>Wed, 17 Apr 2019 04:06:52 GMT</lastBuildDate>
    <language>en-US</language>
    <sy:updatePeriod>hourly</sy:updatePeriod>
    <sy:updateFrequency>1</sy:updateFrequency>
    <item>
      <title>SSH tunnel to endpoints in Azure VNet from Windows</title>
      <link>https://docs.microsoft.com/archive/blogs/pliu/ssh-tunnel-to-endpoints-in-azure-vnet-from-windows</link>
      <pubDate>Tue, 17 Jan 2017 00:04:46 GMT</pubDate>
      <dc:creator><![CDATA[Paige Liu]]></dc:creator>
      <guid
        isPermaLink="false">https://blogs.msdn.microsoft.com/pliu/?p=155</guid>
      <description><![CDATA[When you deploy virtual machines on Azure, a good practice is to set up Azure Network Security...]]></description>
      <content:encoded><![CDATA[When you deploy virtual machines on Azure, a good practice is to set up Azure <a target="_blank" href="https://docs.microsoft.com/en-us/azure/virtual-network/virtual-networks-nsg">Network Security Groups</a> (NSG) to minimize the exposure of endpoints and limit access to those endpoints to only known IPs from the Internet.  In order to access the rest of the endpoints in your Virtual Network (VNet) on Azure, you can set up a SSH tunnel.  SSH tunnel is a familiar concept for Linux users.  If you are working on Windows, you can follow these steps to access the endpoints in Azure VNet from your laptop or desktop.

<strong>Step 1:</strong> In Azure portal, navigate to <span>the VM that you want to tunnel into and copy its public IP or DNS from the </span><strong>Overview</strong><span> blade. </span>

<a href="https://msdnshared.blob.core.windows.net/media/2017/01/AzureVMDNS.png"><img src="https://msdnshared.blob.core.windows.net/media/2017/01/AzureVMDNS-1024x603.png" alt="azurevmdns" width="1024" height="603" class="alignnone wp-image-165 size-large" /></a>

<strong>Step 2:</strong> Find the SSH port for the VM.  This is typically port 22.  But you can verify it by opening <strong>Network interfaces</strong> blade of the VM, click on the network interface, then <strong>Network security group</strong>.  Click on the network security group in the blade, and find the inbound security rule of the network security group:

<a href="https://msdnshared.blob.core.windows.net/media/2017/01/AzureVMNSG.png"><img src="https://msdnshared.blob.core.windows.net/media/2017/01/AzureVMNSG-1024x325.png" alt="azurevmnsg" width="1024" height="325" class="alignnone wp-image-175 size-large" /></a>

<strong>Step 3:</strong> Set up a SSH tunnel to Azure
<ul>
 	<li>Download <a target="_blank" href="https://www.putty.org/">Putty</a> if you haven't already</li>
 	<li>Open Putty, enter userName@VMpublicIPorDNS and the SSH port for the VM that you identified in Step 1 and 2:</li>
</ul>
<a href="https://msdnshared.blob.core.windows.net/media/2017/01/AzureVMPutty1.png"><img src="https://msdnshared.blob.core.windows.net/media/2017/01/AzureVMPutty1.png" alt="azurevmputty1" width="597" height="532" class="alignnone wp-image-185 size-full" /></a>
<ul>
 	<li>In the left navigation panel of Putty, go to <strong>Connections</strong>, <strong>SSH</strong>, then <strong>Tunnels</strong>, enter the tunneling port in Putty, click <strong>Add</strong>, and then click <strong>Open</strong> to connect to the VM:</li>
</ul>
<a href="https://msdnshared.blob.core.windows.net/media/2017/01/AzureVMPutty2.png"><img src="https://msdnshared.blob.core.windows.net/media/2017/01/AzureVMPutty2.png" alt="azurevmputty2" width="592" height="526" class="alignnone wp-image-186 size-full" /></a>

<strong>Step 4:</strong> Configure the browser to access endpoints in Azure VNet through a SSH tunnel

Configure one instance of your Chrome browser to proxy through the tunnel.  The default settings for other Chrome instances won't be affected.
<pre class="brush: jscript; title: ; notranslate" title="">&gt;"C:\Program Files (x86)\Google\Chrome\Application\chrome.exe" --user-data-dir="%USERPROFILE%\chrome-via-socks" --proxy-server="socks5://localhost:1080"
</pre>
You can now access the private endpoints on Azure VNet from your Chrome browser.  For example,
<ul>
 	<li><em>https://www.whatismyipaddress.com</em> will display that you are using an IP owned by Microsoft</li>
 	<li><em>https://localhost</em> will connect to port 80 of the Azure VM that you are tunneling into</li>
 	<li><em>https://&lt;Azure VNet private IP or host name&gt;:&lt;port&gt;</em> will connect to the specified port of an Azure VM on the same VNet as the VM that you are tunneling into</li>
</ul>]]></content:encoded>
    </item>
    <item>
      <title>Backup and Restore Cassandra on Azure</title>
      <link>https://docs.microsoft.com/archive/blogs/pliu/backup-and-restore-cassandra-on-azure</link>
      <pubDate>Fri, 07 Oct 2016 01:51:31 GMT</pubDate>
      <dc:creator><![CDATA[Paige Liu]]></dc:creator>
      <guid
        isPermaLink="false">https://blogs.msdn.microsoft.com/pliu/?p=105</guid>
      <description><![CDATA[When you run Cassandra on virtual machines on Azure, one way to back up and restore data is to rsync...]]></description>
      <content:encoded><![CDATA[When you run Cassandra on virtual machines on Azure, one way to back up and restore data is to rsync Cassandra snapshots to data disks attached to each VM.  The data disks in Azure are backed by Azure blob storage and automatically benefit from the durability that Azure storage brings.  You can also copy the backup disks to a new Cassandra cluster and restore data there.  In this example we will outline the steps to back up a single keyspace with a single table, make some changes to the table, then restore the backup to the original cluster, and also restore to a new cluster.  You can automate the steps in scripts and also extend the same method to back up and restore multiple tables or keyspaces.

These steps are verified on a default deployment of <a href="https://azure.microsoft.com/en-us/marketplace/partners/datastax/datastax-enterprisesingledc/">DataStax Enterprise cluster on Azure Marketplace</a>, but it doesn't use any DataStax Enterprise specific capabilities, and should work on Apache Cassandra.

Let's assume we are backing up "demo_keyspace", which has a "users" table, and our snapshot name is "test_snapshot".
<h3>Back up</h3>
To back up demo_keyspace, go to each Cassandra node and perform the following steps:
<p class="indent">1. If you don't already have a data disk dedicated for backups on the VM, attach a data disk, format and mount it.  You can use Azure command line tool or PowerShell to attach a disk to a VM, but for simplicity, we will use Azure portal here.  Navigate to the VM in Azure portal, click on <strong>Disks</strong>, and <strong>Attach new</strong>:</p>
<p class="indent"><a href="https://msdnshared.blob.core.windows.net/media/2016/10/backuprestore1.png"><img src="https://msdnshared.blob.core.windows.net/media/2016/10/backuprestore1-1024x435.png" alt="backuprestore1" width="1024" height="435" class="alignnone wp-image-115 size-large" /></a></p>
<p class="indent">You can format and mount the disks however the way you want, below commands are just an example, you need sudo or root to run these commands:</p>

<pre class="brush: jscript; title: ; notranslate" title="">$ fdisk -l (find the newly attached disk, it's likely /dev/sdc if it's the first disk, we assume it's /dev/sdc below)
$ fdisk /dev/sdc (type 'n' at the first prompt, use default for the rest of the prompts, and finally type 'w' to save the changes)
$ mkfs -t ext4 /dev/sdc1
$ mkdir /backupdrive
$ mount /dev/sdc1 /backupdrive
$ blkid (note down the uuid for /dev/sdc1)
$ vi /etc/fstab (add a line like this 'UUID=(uuid from above) /backupdrive ext4 defaults,nofail,noatime, 0 2')
</pre>
<p class="indent">2. If you haven't already backed up the schema for demo_keyspace, back up the schema and save the output file. You only need to run this on one node:</p>

<pre class="brush: jscript; title: ; notranslate" title="">$ cqlsh -e "desc keyspace demo_keyspace" &gt; demo_keyspace_schema.cql
</pre>
<p class="indent">3. Flush data from memory to disk.  On the default deployment of DataStax on Azure, data is stored on the ephemeral disk on each VM in the folder /mnt/data</p>

<pre class="brush: jscript; title: ; notranslate" title="">$ nodetool flush
</pre>
<p class="indent">4. If we have an old test_snapshot, remove it, and list the snapshots folder to make sure it's gone:</p>

<pre class="brush: jscript; title: ; notranslate" title="">$ nodetool clearsnapshot -t test_snapshot
$ ls /mnt/data/demo_keyspace/users-(uuid)/snapshots
</pre>
<p class="indent">5. Take a snapshot and rsync it to the backup disk:</p>

<pre class="brush: jscript; title: ; notranslate" title="">$ nodetool snapshot -t test_snapshot demo_keyspace
$ mkdir /backupdrive/cassandra_snapshots (need sudo or root privilege)
$ rsync -azP --delete /mnt/data/demo_keyspace --include '*/' --include 'snapshots/***' --exclude '*' /backupdrive/cassandra_snapshots
</pre>
<h3>Restore to the existing cluster</h3>
To verify back up and restore works, select some data from users table, then make some changes.  Remember what you changed, so that after we restore, we can verify the changes are gone.  Take the following steps on each node to restore to an existing cluster where the snapshot was taken, you will need to run most of these commands with sudo or root:
<p class="indent">1. Stop Cassandra, on our DataStax deployment, run this command:</p>

<pre class="brush: jscript; title: ; notranslate" title="">$ service dse stop
</pre>
<p class="indent">2. Clear commit log and saved cache:</p>

<pre class="brush: jscript; title: ; notranslate" title="">$ rm -f /mnt/commitlog/*
$ rm -f /mnt/saved_caches/*
</pre>
<p class="indent">3. Remove database files for demo_keyspace:</p>

<pre class="brush: jscript; title: ; notranslate" title="">$ rm -f /mnt/data/demo_keyspace/users-(uuid)/*.db
</pre>
<p class="indent">4. Rsync backups to demo_keyspace and move the snapshots two levels up to the directory for the db files:</p>

<pre class="brush: jscript; title: ; notranslate" title="">$ rsync -azP /backupdrive/cassandra_snapshots/ --include '*/' --include 'demo_keyspace/***' --exclude '*' /mnt/data/
$ mv /mnt/data/demo_keyspace/users-(uuid)/snapshots/test_snapshot/* /mnt/data/demo_keyspace/users-(uuid)
$ chown -R cassandra:cassandra /mnt/data/demo_keyspace
</pre>
<p class="indent">5. Start Cassandra:</p>

<pre class="brush: jscript; title: ; notranslate" title="">$ service dse start
</pre>
select some data from users table again, and make sure the table is restored to its original state prior to your changes made after the snapshot.
<h3>Restore to a new cluster</h3>
<p class="indent">1. Find the tokens of each node on the existing cluster. Go to the Azure portal, and find the public IP of each node:</p>
<a href="https://msdnshared.blob.core.windows.net/media/2016/10/backuprestore2.png"><img src="https://msdnshared.blob.core.windows.net/media/2016/10/backuprestore2.png" alt="backuprestore2" width="768" height="279" class="alignnone wp-image-125 size-full" /></a>
<p class="indent">Note down the tokens for each node by running the following command with that nodes's IP:</p>

<pre class="brush: jscript; title: ; notranslate" title="">$ nodetool ring | grep ip_address_of_node | awk '{print $NF ","}' | xargs</pre>
<p class="indent">2. Deploy a new cluster with the same number of nodes as the old cluster where the snapshot was taken.  On Azure, you can easily do this by deploying <a href="https://azure.microsoft.com/en-us/marketplace/partners/datastax/datastax-enterprisesingledc/">DataStax from Azure Marketplace</a></p>
<p class="indent">3. Copy the backup disks from the old cluster to a storage account in the new cluster.
Find the backup disks from the old cluster:</p>
<a href="https://msdnshared.blob.core.windows.net/media/2016/10/backuprestore3.png"><img src="https://msdnshared.blob.core.windows.net/media/2016/10/backuprestore3-1024x381.png" alt="backuprestore3" width="1024" height="381" class="alignnone wp-image-135 size-large" /></a>
<p class="indent">For testing, we can copy to the storage account and container used by the OS disks. We can use Azure command line tool as shown below, or download <a>Azure Storage Explorer</a>, then copy and paste blobs in the UI.</p>

<pre class="brush: jscript; title: ; notranslate" title=""># use "export" on Linux and "set" on Windows to set the environment variables
&gt; export AZURE_STORAGE_ACCOUNT=(destination storage account name) 
&gt; export AZURE_STORAGE_ACCESS_KEY=(destination storage account key)
# create a sas url for the source storage account
&gt; azure storage account sas create --account-name (source storage account name) --account-key (source storage account key) b o r (expiration date, ex: 2016-12-31)
&gt; azure storage blob copy start "https://(source vhd url shown in the above screenshot)?(output from above sas command)" vhds 
# run this to check if copy succeeded
&gt; azure storage blob copy show vhds (vhd blob name)  
</pre>
Go to each node of the new cluster and take the following steps:
<p class="indent">4. Attach a copied disk and mount it:</p>
<p class="indent"><a href="https://msdnshared.blob.core.windows.net/media/2016/10/backuprestore4.png"><img src="https://msdnshared.blob.core.windows.net/media/2016/10/backuprestore4-1024x311.png" alt="backuprestore4" width="1024" height="311" class="alignnone wp-image-145 size-large" /></a></p>

<pre class="brush: jscript; title: ; notranslate" title="">$ fdisk -l (find the newly attached disk, it's likely /dev/sdc if it's the first disk, we assume it's /dev/sdc below)
$ mkdir /backupdrive
$ mount /dev/sdc1 /backupdrive
$ blkid (note down the uuid for /dev/sdc1)
$ vi /etc/fstab (add a line like this 'UUID=(uuid from above) /backupdrive ext4 defaults,nofail,noatime, 0 2')</pre>
<p class="indent">5. Update cassandra.yaml with the tokens for this node:</p>

<pre class="brush: jscript; title: ; notranslate" title="">$ vi /etc/dse/cassandra/cassandra.yaml 
# uncomment initial_token, and set the value of initial_token to the tokens you noted in step 1
</pre>
<p class="indent">6. Create the schema.  This only needs to run on one node:</p>

<pre class="brush: jscript; title: ; notranslate" title="">$ cqlsh
&gt; source 'demo_keyspace_schema.sql'</pre>
<p class="indent">7. Restore the snapshots:</p>

<pre class="brush: jscript; title: ; notranslate" title=""># Stop Cassandra:
service dse stop

# Clear systems table
rm -rf /mnt/data/system/*

# Clear commit log and saved caches
rm -rf /mnt/commitlog/*
rm -rf /mnt/saved_caches/*

# Rename the snapshot file from the table name in the old cluster to the table name in the new cluster
ls /mnt/data/demo_keyspace  (copy the new table name)
cd /backupdrive/cassandra_snapshots/demo_keyspace/
mv (old table name) (new table name)

# rsync the snapshot to the data disk and move two levels up to the data folder
rsync -azP /backupdrive/cassandra_snapshots/ --include '*/' --include 'demo_keyspace/***' --exclude '*' /mnt/data/
mv /mnt/data/demo_keyspace/users-(uuid)/snapshots/test_snapshot/* /mnt/data/demo_keyspace/users-(uuid)
chown -R cassandra:cassandra /mnt/data 
# Start Cassandra 
service dse start
</pre>
Select data from the users table, and make sure it's the same as the old cluster when the snapshot was taken.]]></content:encoded>
    </item>
    <item>
      <title>Backup Cloudera data to Azure Storage</title>
      <link>https://docs.microsoft.com/archive/blogs/pliu/backup-cloudera-data-to-azure-storage</link>
      <pubDate>Sun, 19 Jun 2016 22:22:00 GMT</pubDate>
      <dc:creator><![CDATA[Paige Liu]]></dc:creator>
      <guid
        isPermaLink="false">https://blogs.msdn.microsoft.com/pliu/2016/06/19/backup-cloudera-data-to-azure-storage/</guid>
      <description><![CDATA[Azure Blob Storage supports an HDFS interface which can be accessed by HDFS clients using the syntax...]]></description>
      <content:encoded><![CDATA[Azure Blob Storage supports an HDFS interface which can be accessed by HDFS clients using the syntax <em>wasb://</em>.  The <a title="hadoop-azure module" href="https://hadoop.apache.org/docs/stable2/hadoop-azure/index.html" target="_blank">hadoop-azure module</a> which implements this interface is distributed with Apache Hadoop, but is not configured out of the box in Cloudera.  In this blog, we will provide instructions on how to backup Cloudera data to Azure storage.

The steps here have been verified on a default deployment of Cloudera CDH cluster on Azure.
<p style="padding-left: 30px">1. Go to Cloudera Manager, select <strong>HDFS</strong>, then <strong>Configuration</strong>, Search for "core-site", and add the following configuration to <strong>Cluster-wide Advanced Configuration Snippet (Safety Valve) for core-site.xml</strong>, replace with your storage account name and key:</p>

<pre class="scroll" style="padding-left: 30px"><code class="js">Name: fs.azure.account.key.&lt;your_storage_account&gt;.blob.core.windows.net
Value: &lt;your_storage_access_key&gt;</code></pre>
<p style="padding-left: 30px"><a href="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/01/71/47/1385.wasb1.png" original-url="https://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-01-71-47/1385.wasb1.png"><img src="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/01/71/47/1385.wasb1.png" original-url="https://blogs.msdn.com/resized-image.ashx/__size/550x0/__key/communityserver-blogs-components-weblogfiles/00-00-01-71-47/1385.wasb1.png" alt="" border="0" /></a></p>
<p style="padding-left: 30px">2. Redeploy stale client configurations, then restart all Cloudera services from Cloudera Manager.</p>
<p style="padding-left: 30px">3. To test that Cloudera can access files in Azure storage, put some files in Azure storage.  You can do so by using command line tools like <a title="AzCopy" href="https://azure.microsoft.com/en-us/documentation/articles/storage-use-azcopy/" target="_blank">AzCopy</a>, or UI tools such as <a title="Visual Studio Server Explorer" href="https://azure.microsoft.com/en-us/documentation/articles/vs-azure-tools-storage-resources-server-explorer-browse-manage/" target="_blank">Visual Studio Server Explorer</a> or <a title="Azure Storage Explorer" href="https://azurestorageexplorer.codeplex.com/" target="_blank">Azure Storage Explorer</a>.</p>
<p style="padding-left: 30px"><a href="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/01/71/47/8372.wasb2.png" original-url="https://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-01-71-47/8372.wasb2.png"><img src="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/01/71/47/8372.wasb2.png" original-url="https://blogs.msdn.com/resized-image.ashx/__size/550x0/__key/communityserver-blogs-components-weblogfiles/00-00-01-71-47/8372.wasb2.png" alt="" border="0" /></a></p>
<p style="padding-left: 30px">4. SSH into any Cloudera node, run the following command.  You may see some warnings, but make sure your can see the files in your Azure storage account.  Note that if you don't specify a destination folder name, you must have the trailing slash in the wasb URL, as shown in the following example:</p>

<pre class="scroll" style="padding-left: 30px"><code class="js">hdfs dfs -ls wasb://&lt;your_container&gt;@&lt;your_account&gt;.blob.core.windows.net/
 </code></pre>
<p style="padding-left: 30px"><a href="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/01/71/47/1537.wasb3.png" original-url="https://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-01-71-47/1537.wasb3.png"><img src="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/01/71/47/1537.wasb3.png" original-url="https://blogs.msdn.com/resized-image.ashx/__size/550x0/__key/communityserver-blogs-components-weblogfiles/00-00-01-71-47/1537.wasb3.png" alt="" border="0" /></a></p>
<p style="padding-left: 30px">5. Run distcp on any Cloudera node to copy data from HDFS to Azure Storage.</p>

<pre class="scroll" style="padding-left: 30px"><code class="js"># Run this command under a user who has access to the source HDFS files, 
# for example, the HDFS superuser hdfs
hadoop distcp /&lt;hdfs_src&gt; wasb://&lt;your_container&gt;@&lt;your_account&gt;.blob.core.windows.net/</code></pre>
<p style="padding-left: 30px"><a href="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/01/71/47/7245.wasb4.png" original-url="https://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-01-71-47/7245.wasb4.png"><img src="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/01/71/47/7245.wasb4.png" original-url="https://blogs.msdn.com/resized-image.ashx/__size/550x0/__key/communityserver-blogs-components-weblogfiles/00-00-01-71-47/7245.wasb4.png" alt="" border="0" /></a></p>
<p style="padding-left: 30px">Now you should be able to see the source HDFS content showing up in Azure storage:</p>
<p style="padding-left: 30px"><a href="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/01/71/47/7802.wasb5.png" original-url="https://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-01-71-47/7802.wasb5.png"><img src="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/01/71/47/7802.wasb5.png" original-url="https://blogs.msdn.com/resized-image.ashx/__size/550x0/__key/communityserver-blogs-components-weblogfiles/00-00-01-71-47/7802.wasb5.png" alt="" border="0" /></a></p>
For more information about Hadoop support for Azure storage, please see <a title="this documentation" href="https://hadoop.apache.org/docs/stable2/hadoop-azure/index.html" target="_blank">this documentation</a>.]]></content:encoded>
    </item>
    <item>
      <title>Run Jupyter Notebook on Cloudera</title>
      <link>https://docs.microsoft.com/archive/blogs/pliu/run-jupyter-notebook-on-cloudera</link>
      <pubDate>Sun, 19 Jun 2016 18:31:00 GMT</pubDate>
      <dc:creator><![CDATA[Paige Liu]]></dc:creator>
      <guid
        isPermaLink="false">https://blogs.msdn.microsoft.com/pliu/2016/06/19/run-jupyter-notebook-on-cloudera/</guid>
      <description><![CDATA[In a previous blog, we demonstrated how to enable Hue Spark notebook with Livy on CDH. &nbsp;Here we...]]></description>
      <content:encoded><![CDATA[<p>In <a title="a previous blog" href="https://blogs.msdn.com/b/pliu/archive/2016/06/18/run-spark-notebooks-on-cloudera.aspx" target="_blank">a previous blog</a>, we demonstrated how to enable Hue Spark notebook with Livy on CDH. &nbsp;Here we will provide instructions on how to run a Jupyter notebook on a CDH cluster. &nbsp;<p>These steps have been verified on a default deployment of Cloudera CDH cluster on Azure. &nbsp;At the time of this writing, the deployed CDH is at version 5.7 and Jupyter notebook server 4.1.0 running on Python 2.7 and Anaconda 4.0.0. &nbsp;The steps should be similar for any CDH cluster deployed with Cloudera Manager.&nbsp;</p><p style="padding-left: 30px">1. Go to Cloudera Manager, click the <strong>Parcels</strong> icon on the top navigation bar, then <strong>Configurations</strong>, <strong>Remote Parcel Repository URLs</strong>, add the Anaconda parcel URL "https://repo.continuum.io/pkgs/misc/parcels/"&nbsp;and <strong>Save Changes</strong>. &nbsp;</p><p style="padding-left: 30px"><a href="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/01/71/47/8625.jupyter1.png" original-url="https://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-01-71-47/8625.jupyter1.png"><img src="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/01/71/47/8625.jupyter1.png" original-url="https://blogs.msdn.com/resized-image.ashx/__size/550x0/__key/communityserver-blogs-components-weblogfiles/00-00-01-71-47/8625.jupyter1.png" alt="" border="0"></a></p><p style="padding-left: 30px">Follow the Cloudera Manager's <strong>Parcels</strong> wizard to <strong>Download, Distribute,</strong> and <strong>Activate</strong> the Anaconda parcel.&nbsp;</p><p style="padding-left: 30px">2. SSH into the Spark driver. &nbsp;If you deployed the CDH cluster on Azure, this is typically the first master node with a host name ending with "-mn0". &nbsp;For simplicity, we will run the following commands with sudo or as root user.</p><pre class="scroll" style="padding-left: 30px"><code class="js"># install the packages<br>pip install Jinja2<br>yum install gcc-c++<br>yum install python-devel<br>pip install pyzmq<br>pip install tornado<br>pip install jupyter<br> <br># set environment variables for pyspark<br>export PYSPARK_DRIVER_PYTHON=/opt/cloudera/parcels/Anaconda/bin/jupyter<br>export PYSPARK_DRIVER_PYTHON_OPTS="notebook --NotebookApp.open_browser=False --NotebookApp.ip='*' --NotebookApp.port=8880"<br>export PYSPARK_PYTHON=/opt/cloudera/parcels/Anaconda/bin/python<br>export PATH=/opt/cloudera/parcels/Anaconda/bin:$PATH<br> <br># create a notebook directory, make sure it's accessible by a hadoop user with sufficient priviledge to hdfs, for example, the hadoop superuser hdfs. <br>mkdir /&lt;your_notebook_dir&gt;<br>chown hdfs:hdfs /&lt;your_notebook_dir&gt;<br> <br># run pyspark as a hadoop user with sufficient privilege, such as the superuser hdfs.<br>su hdfs<br>pyspark<br><br></code></pre><p style="padding-left: 30px">3. SSH into the Spark executors. &nbsp;These are typically the data nodes in your cluster. &nbsp;Set the following environment variable on each executor. &nbsp;Instead of setting it in the console, you want to permanently set it by, for example, adding your custom file under /etc/profile.d.&nbsp;</p><pre class="scroll" style="padding-left: 30px"><code class="js">export PYSPARK_PYTHON=/opt/cloudera/parcels/Anaconda/bin/python</code></pre><p style="padding-left: 30px">4. Now go to the Jupyter notebook URL: https://&lt;your_spark_driver&gt;:8880/notebooks, and <strong>New</strong> a <strong>Python2</strong> notebook.&nbsp;</p><p style="padding-left: 30px">(If your cluster is deployed with the default configuration in Azure, then port 8880 may be blocked, and you won't be able to access the notebook URL from the Internet. &nbsp;You can open this port by going to the Azure portal, find the Network Security Groups for the VNet and the master nodes of the CDH cluster, and open this port in their inbound security rules. )</p><p style="padding-left: 30px"><a href="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/01/71/47/2806.jupyter3.png" original-url="https://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-01-71-47/2806.jupyter3.png"><img src="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/01/71/47/2806.jupyter3.png" original-url="https://blogs.msdn.com/resized-image.ashx/__size/550x0/__key/communityserver-blogs-components-weblogfiles/00-00-01-71-47/2806.jupyter3.png" alt="" border="0"></a></p><p style="padding-left: 30px">For more information about running Jupyter notebook on Cloudera, please see <a title="this documentation" href="https://www.cloudera.com/documentation/enterprise/5-5-x/topics/spark_ipython.html" target="_blank">this documentation</a>.&nbsp;</p><p style="padding-left: 30px">&nbsp;</p></p>
]]></content:encoded>
    </item>
    <item>
      <title>Enable Kerberos on Cloudera with Azure AD Domain Service</title>
      <link>https://docs.microsoft.com/archive/blogs/pliu/enable-kerberos-on-cloudera-with-azure-ad-domain-service</link>
      <pubDate>Sat, 18 Jun 2016 19:59:00 GMT</pubDate>
      <dc:creator><![CDATA[Paige Liu]]></dc:creator>
      <guid
        isPermaLink="false">https://blogs.msdn.microsoft.com/pliu/2016/06/18/enable-kerberos-on-cloudera-with-azure-ad-domain-service/</guid>
      <description><![CDATA[In this previous blog series we documented how to integrate Active Directory deployed in virtual...]]></description>
      <content:encoded><![CDATA[In this <a target="_blank" href="https://blogs.msdn.com/b/pliu/archive/2016/01/02/integrating-cloudera-cluster-with-active-directory-part-1-3.aspx" rel="noopener noreferrer" title="previous blog series">previous blog series</a> we documented how to integrate Active Directory deployed in virtual machines on Azure with Cloudera. In that scenario, we need to deploy and maintain the domain controller VMs ourselves. In this article, we will use <a target="_blank" href="https://azure.microsoft.com/en-us/services/active-directory-ds/" rel="noopener noreferrer" title="Azure Active Directory Domain Service (AADDS)">Azure Active Directory Domain Service (AADDS)</a> to integrate Kerberos and single-sign-on with Cloudera.  AADDS is a managed service that lets you join Azure VMs to a domain without the need to deploy your own domain controllers.

Here are the main tasks to complete:
<ol>
 	<li>Enable Azure AD Domain Service. <em>By the end of this step, we will have a classic VNet managed by AADDS.  We will have a Windows VM joined to the domain with Active Directory tools to view and manage the domain services.</em></li>
 	<li>Connect the Azure classic VNet used with AADDS with an <a target="_blank" href="https://azure.microsoft.com/en-us/documentation/articles/resource-group-overview/" rel="noopener noreferrer" title="Azure Resource Manager (ARM)">Azure Resource Manager (ARM)</a> VNet in which the VMs will be deployed. <em>By the end of this step, we will have an ARM VNet connected to the classic VNet via VPN and managed by AADDS. AADDS currently only works with Azure classic VNet. Hopefully ARM VNet support will come in the near future, in which case this step will become unnecessary. [Update 8/2017: Azure now supports <a href="https://docs.microsoft.com/en-us/azure/virtual-network/create-peering-different-deployment-models">VNet peering between classic and ARM VNet</a> as long as the two VNets are in the same region. This step can now be greatly simplified with VNet peering if the VNets are in the same region.]</em></li>
 	<li>Deploy and configure the VMs. <em>By the end of this step, we will have Linux VMs joined to the domain, with Kerberos enabled. We will be able to ssh into the Linux VMs with users defined in AADDS. </em></li>
 	<li>Enable Kerberos on Cloudera.</li>
</ol>
<strong>Step 1: Enable Azure AD Domain Service</strong>
<ol>
 	<li>Follow <a target="_blank" href="https://azure.microsoft.com/en-us/documentation/articles/active-directory-ds-getting-started/" rel="noopener noreferrer" title="this AADDS documentation">this AADDS documentation</a> to enable Domain Service.  Although we will connect the classic VNet used with AADDS with the ARM VNet for the VMs later in Step 2, here are a few things to plan head because they can't be changed after AADDS is enabled -</li>
</ol>
<p style="padding-left: 60px">a. Make sure the classic VNet to be used with AADDS is deployed in a region where your VMs will be deployed to.
b. Make sure the address space of the classic VNet to be used with AADDS don't overlap with the address space for the ARM VNet.  For example, use 10.1.0.0/16 for the classic VNet, and 10.2.0.0/16 for the ARM VNet.
c. When you enable AADDS, you can choose the dns name for your domain. It doesn't have to be the default "onmicrosoft.com" dns name, you can use, for example, "bigdata.local".</p>
<p style="padding-left: 60px"><a href="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/01/71/47/4431.DNSName.png"><img src="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/01/71/47/4431.DNSName.png" alt="" border="0" /></a></p>
<p style="padding-left: 30px">2. Once AADDS is enabled, deploy a Windows VM to the subnet of the classic VNet managed by AADDS.</p>
<p style="padding-left: 60px">a. Add AD and DNS tools using "Add roles and features" wizard.</p>
<p style="padding-left: 60px"><a href="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/01/71/47/0333.ADTools.png"><img src="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/01/71/47/0333.ADTools.png" alt="" border="0" /></a></p>
<p style="padding-left: 60px">b. Join the VM to the AADDS domain, for example "bigdata.local", using a user that belongs to the "AAD DC Administrators" group created in the previous step.  After rebooting the VM, log in as a domain admin, we can now use the AD and DNS tools to manage the domain.</p>
&nbsp;

<strong>Step 2: Connect the "classic" VNet used with AADDS with an Azure Resource Manager (ARM) VNet in which the VMs will be deployed</strong>

<em>[Update 8/2017: Azure now supports<span> </span><a href="https://docs.microsoft.com/en-us/azure/virtual-network/create-peering-different-deployment-models">VNet peering between classic and ARM VNet</a><span> </span>as long as the two VNets are in the same region. This step<span> </span>can now be greatly simplified with VNet peering if the VNets are in the same region.]</em>
<ol>
 	<li>Create an ARM VNet in which we will deploy the VMs, make sure it's in the same region as the classic VNet and that its address space doesn't overlap with that of the classic VNet.</li>
 	<li>Follow <a target="_blank" href="https://azure.microsoft.com/en-us/documentation/articles/virtual-networks-arm-asm-s2s/" rel="noopener noreferrer" title="these steps">these steps</a> to create a gateway in the classic VNet and ARM VNet respectively, then connect the two VNets.  Note that you don't have to use the scripts in the documentation, you can create both gateways and the connection from the Azure portal.  The "shared key" used to make the connection between the two gateways can be accessed from the portal of the classic VNet:</li>
</ol>
<p style="padding-left: 30px"><a href="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/01/71/47/6036.ARMVNet.png"><img src="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/01/71/47/6036.ARMVNet.png" alt="" border="0" /></a></p>
<p style="padding-left: 30px"><a href="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/01/71/47/4162.classicVNet.png"><img src="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/01/71/47/4162.classicVNet.png" alt="" border="0" /></a></p>
<p style="padding-left: 30px">3. The classic VNet should already be configured to use AADDS for DNS in Step 1. Now configure DNS for the ARM VNet to use AADDS as well:</p>
<p style="padding-left: 30px"><a href="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/01/71/47/2352.ARMVNetDNS.png"><img src="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/01/71/47/2352.ARMVNetDNS.png" alt="" border="0" /></a></p>
<p style="padding-left: 30px">4. Plan for the IP addresses you will assign to the VMs. If you deploy the VMs using <a target="_blank" href="https://github.com/liupeirong/Azure/tree/master/ClouderaAD" rel="noopener noreferrer" title="this ARM template">this Cloudera ARM template</a> in Step 3 and the address prefix for the VM subnet is, for example, 10.7.0, then the Cloudera master nodes start with 10.7.0.10, and the data nodes start with 10.7.0.20.  Add a Reverse Lookup Zone for the domain controllers and another for the VMs. Make sure to update the PTR records for the domain controllers so that they show up in their reverse lookup zone.</p>
<p style="padding-left: 30px"><a href="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/01/71/47/1072.reverseZones.png"><img src="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/01/71/47/1072.reverseZones.png" alt="" border="0" /></a></p>
<p style="padding-left: 30px">5. Add the DNS records for the VMs</p>
<p style="padding-left: 30px"><a href="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/01/71/47/5430.LinuxDNS.png"><img src="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/01/71/47/5430.LinuxDNS.png" alt="" border="0" /></a></p>
&nbsp;

<strong>Step 3: Deploy and configure the VMs</strong>
<ol>
 	<li>For Kerberos to work, we need the FQDN of the domain controllers. The host name generated by AADDS can be found in the DNS tool:</li>
</ol>
<p style="padding-left: 30px"><a href="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/01/71/47/2161.DCName.png"><img src="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/01/71/47/2161.DCName.png" alt="" border="0" /></a></p>
<p style="padding-left: 30px">2. In this example, we will use <a target="_blank" href="https://github.com/liupeirong/Azure/tree/master/ClouderaAD" rel="noopener noreferrer" title="an ARM template">an ARM template</a> originally created for a Cloudera cluster to deploy Cent OS VMs, however, Cloudera specific code is only used in Step 4. You can deploy Cloudera in another way, or you can customize the template to deploy any Linux VMs. In any case, note the following configurations that made the integration between the VMs and AADDS possible:</p>
<p style="padding-left: 60px">a. ntp, sssd, samba, and kerberos are installed and configured on each VM (see<a target="_blank" href="https://github.com/liupeirong/Azure/blob/master/ClouderaAD/scripts/initialize-node.sh" rel="noopener noreferrer" title="initialize-node.sh"> initialize-node.sh</a> and the configuration templates in the <a target="_blank" href="https://github.com/liupeirong/Azure/tree/master/ClouderaAD/config" rel="noopener noreferrer" title="config folder">config folder</a>)
b. AADDS domain controller names and IPs are passed to the ARM template in the following parameters so they can be automatically set in the configuration files, for example, the following values match the screenshots above. It's also important to set <em>useLdapIDMapping</em> to <em>True </em>when we use sssd rather than NIS (NIS is not supported on AADDS):</p>

<pre style="padding-left: 120px"><em>"adDomainName": {"value": "bigdata.local"},</em>
<em>"PDC": {"value": "ad-k1kxmrudcuxv"},</em>
<em>"BDC": {"value": "LQ75SYGTK0EFQAA"},</em>
<em>"PDCIP": {"value": "10.1.1.4"},</em>
<em>"BDCIP": {"value": "10.1.1.5"},</em>
<em>"useLdapIDMapping": {"Value": "<strong>True</strong>"}</em></pre>
<p style="padding-left: 30px">Deploy <a target="_blank" href="https://github.com/liupeirong/Azure/blob/master/ClouderaAD/azuredeploy.json" rel="noopener noreferrer" title="azuredeploy.json">azuredeploy.json</a>. Once done, from the Windows VM on the classic VNet, we should be able to ping the linux VMs using their FQDN, for example contoso-mn0.bigdata.local, and vice versa. We should also be able to ping Linux VMs from each other using their FQDN. To verify reverse DNS works, run "host &lt;linux vm ip&gt;" on a Linux VM, and it should return the FQDN for that IP.</p>
<p style="padding-left: 30px">3. Join the Linux VMs to the domain by ssh into each VM and run the following commands with root privilege:</p>

<pre class="scroll"><code class="cplusplus">#join the domain with a domain admin credential
#this should be a user in the "AAD DC Administrators" group created in Step 1
<em>&gt; net ads join -Uadadmin@BIGDATA.LOCAL</em>
<em>&gt; authconfig --enablesssd --enablemkhomedir --enablesssdauth --update</em>
<em>&gt; service sssd start</em>
<em>&gt; kinit adadmin@BIGDATA.LOCAL</em>
#if you see an output from the following command, then everything is set up correctly
<em>&gt; getent passwd adadmin@BIGDATA.LOCAL</em>
 </code></pre>
<p style="padding-left: 30px">Now we should be able to ssh into each VM using a user defined in AADDS. Up till this point, other than we leveraged the ARM template originally created for Cloudera to deploy the VMs, there's nothing specific we did for Cloudera. In fact, Cloudera bits are not yet installed on the VMs.</p>
<strong>Step 4: Enable Kerberos on Cloudera.</strong>
<ol>
 	<li>Install Cloudera on the VMs by deploying <a target="_blank" href="https://github.com/liupeirong/Azure/blob/master/ClouderaAD/azuredeploy_postad.json" rel="noopener noreferrer" title="azuredeploy_postad.json">azuredeploy_postad.json</a>. The following parameters must match what was specified when deploying <a target="_blank" href="https://github.com/liupeirong/Azure/blob/master/ClouderaAD/azuredeploy.json" rel="noopener noreferrer" title="azuredeploy.json">azuredeploy.json</a> in the previous step. (This is not necessary if you deployed Cloudera using a different method than our sample ARM template.)</li>
</ol>
<p style="padding-left: 60px"><em>adminUserName</em>
<em>adminPassword</em>
<em>dnsNamePrefix</em>
<em>adDomainName</em>
<em>nodeAddressPrefix</em>
<em>numberOfDataNodes</em>
<em>region</em>
<em>tshirtSize</em></p>
<p style="padding-left: 30px">2. Verify Cloudera is installed correctly by RDP into a VM (could be the Windows VM created in the AADDS classic VNet), open a browser, and access https://&lt;dnsNamePrefix&gt;-mn0.&lt;adDomainName&gt;:7180. Use the Cloudera Manager admin credential specified when deploying the template in the previous step.</p>
<p style="padding-left: 30px">3. Follow <a target="_blank" href="https://azure.microsoft.com/en-us/documentation/articles/active-directory-ds-admin-guide-configure-secure-ldap/" rel="noopener noreferrer" title="this documentation">this documentation</a> to enable secure LDAP on AADDS. This is required by Cloudera Manager when issuing LDAPS requests to import KDC account manager credentials.</p>
<p style="padding-left: 30px">4. If you haven't already, create an Organization Unit in AADDS. This is required because users in AADDS are created in Azure AD and synced to AADDS, only users under an Organization Unit can be created inside AADDS.</p>
<p style="padding-left: 30px">5. Follow <a target="_blank" href="https://www.cloudera.com/documentation/enterprise/latest/topics/cm_sg_intro_kerb.html" rel="noopener noreferrer" title="this Cloudera documentation">this Cloudera documentation</a> to enable Kerberos using the wizard in Cloudera Manager</p>
<p style="padding-left: 60px">a. Make sure to install JCE Policy file
b. We already installed OpenLdap client library on all VMs using our template.</p>
<p style="padding-left: 60px"><a href="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/01/67/51/8688.Step7-1-ldaplib.png"><img style="max-width: 550px" src="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/01/67/51/8688.Step7-1-ldaplib.png" alt="" border="0" /></a></p>
<p style="padding-left: 60px">c. Specify domain info, note that here we specify encryption type rc4-hmac (aes256 doesn't seem to work with AADDS, however, JCE policy file is still needed for hadoop commands to work):</p>
<p style="padding-left: 60px"> <a href="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/01/71/47/3681.ClouderaKerberos.png"><img src="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/01/71/47/3681.ClouderaKerberos.png" alt="" border="0" /></a></p>
<p style="padding-left: 30px">6. Verify Kerberos is set up correctly by running "hdfs dfs -ls /" as the built-in hdfs user on a Cloudera VM, it should render a security error.  Create a hdfs@&lt;domain name&gt; in the Organization Unit created earlier, ssh in as this domain user and run the command again, it should succeed.</p>
<em>(Many thanks to my colleague Bruce Nelson who enabled Kerberos on Cloudera with AADDS first and made me aware of this solution.)</em>]]></content:encoded>
    </item>
    <item>
      <title>Run Hue Spark Notebook on Cloudera</title>
      <link>https://docs.microsoft.com/archive/blogs/pliu/run-hue-spark-notebook-on-cloudera</link>
      <pubDate>Sat, 18 Jun 2016 19:57:00 GMT</pubDate>
      <dc:creator><![CDATA[Paige Liu]]></dc:creator>
      <guid
        isPermaLink="false">https://blogs.msdn.microsoft.com/pliu/2016/06/18/run-hue-spark-notebook-on-cloudera/</guid>
      <description><![CDATA[When you deploy a CDH cluster using Cloudera Manager, you can use Hue web UI to run, for example,...]]></description>
      <content:encoded><![CDATA[<p>When you deploy a CDH cluster using Cloudera Manager, you can use Hue web UI to run, for example, Hive and Impala queries. &nbsp;But Spark notebook is not configured out of the box. &nbsp;Turns out installing and configuring Spark notebooks on CDH isn't as straightforward as is described in their existing documentation. &nbsp;In this blog, we will provide step by step instructions on how to enable Hue Spark notebook with Livy on CDH. &nbsp;<p>These steps have been verified in a default deployment of Cloudera CDH cluster on Azure. &nbsp;At the time of this writing, the deployed CDH is at version 5.7, HUE 3.9, and Livy 0.2. &nbsp;The steps should be similar for any CDH cluster deployed with Cloudera Manager. &nbsp;Note that Livy is not yet supported by Cloudera. &nbsp;&nbsp;</p><div style="padding-left: 30px">1. Go to Cloudera Manager, go to <strong>Hue</strong> and find the host name of the Hue Server.</div><p style="padding-left: 30px"><a href="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/01/71/47/4657.hue_server.png" original-url="https://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-01-71-47/4657.hue_5F00_server.png"><img src="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/01/71/47/4657.hue_server.png" original-url="https://blogs.msdn.com/resized-image.ashx/__size/550x0/__key/communityserver-blogs-components-weblogfiles/00-00-01-71-47/4657.hue_5F00_server.png" alt="" border="0"></a></p><p style="padding-left: 30px">&nbsp;</p><p style="padding-left: 30px">2. In Cloudera Manager, go to <strong>Hue</strong>-&gt;<strong>Configurations</strong>, search for "safety", in <strong>Hue Service Advanced Configuration Snippet (Safety Valve) for hue_safety_valve.ini</strong>,&nbsp;add the following configuration, save the changes, and restart Hue:</p><pre class="scroll" style="padding-left: 30px"><code class="js">[desktop]<br>app_blacklist=<br><br>[spark]<br>server_url=https://&lt;your_hue_server&gt;:8998/<br><br>languages='[{"name": "Scala", "type": "scala"},{"name": "Python", "type": "python"},{"name": "Impala SQL", "type": "impala"},{"name": "Hive SQL", "type": "hive"},{"name": "Text", "type": "text"}]'<br> </code></pre><p style="padding-left: 30px"><a href="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/01/71/47/8738.hue_config.png" original-url="https://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-01-71-47/8738.hue_5F00_config.png"><img src="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/01/71/47/8738.hue_config.png" original-url="https://blogs.msdn.com/resized-image.ashx/__size/550x0/__key/communityserver-blogs-components-weblogfiles/00-00-01-71-47/8738.hue_5F00_config.png" alt="" border="0"></a></p><p style="padding-left: 30px">&nbsp;</p><p style="padding-left: 30px">Now if you go to the Hue Web UI, you should be able to see the Spark notebook. &nbsp;The Spark notebook uses Livy to submit Spark jobs, so without Livy, it's not functioning yet.&nbsp;</p><p style="padding-left: 30px"><a href="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/01/71/47/0167.hue_spark1.png" original-url="https://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-01-71-47/0167.hue_5F00_spark1.png"><img src="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/01/71/47/0167.hue_spark1.png" original-url="https://blogs.msdn.com/resized-image.ashx/__size/550x0/__key/communityserver-blogs-components-weblogfiles/00-00-01-71-47/0167.hue_5F00_spark1.png" alt="" border="0"></a></p><p style="padding-left: 30px">&nbsp;</p><p style="padding-left: 30px">3. In the Hue Web UI, go to <strong>Configuration</strong>, find <strong>hadoop_conf_dir </strong>and note it down:</p><p style="padding-left: 30px">&nbsp;<a href="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/01/71/47/6064.hue_hadoopconf.png" original-url="https://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-01-71-47/6064.hue_5F00_hadoopconf.png"><img src="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/01/71/47/6064.hue_hadoopconf.png" original-url="https://blogs.msdn.com/resized-image.ashx/__size/550x0/__key/communityserver-blogs-components-weblogfiles/00-00-01-71-47/6064.hue_5F00_hadoopconf.png" alt="" border="0"></a></p><p style="padding-left: 30px">&nbsp;</p><p style="padding-left: 30px">4. SSH to your Hue server, for simplicity, unless specified we'll run the following commands in sudo or as root user:</p><pre class="scroll" style="padding-left: 30px"><code class="js">#download Livy<br>wget https://archive.cloudera.com/beta/livy/livy-server-0.2.0.zip<br>unzip livy-server-0.2.0.zip -d /&lt;your_livy_dir&gt;<br> <br>#set environment variables for Livy<br>export SPARK_HOME=/opt/cloudera/parcels/CDH/lib/spark<br>export JAVA_HOME=/usr/java/jdk1.7.0_67-cloudera<br>export HADOOP_CONF_DIR=&lt;your hadoop_conf_dir found in the previous step in Hue configuration&gt;<br>export HUE_SECRET_KEY=&lt;your Hue superuser password, this is usually the user you use when you log in to Hue Web UI the first time&gt;<br> <br>#run Livy. You must run Livy as a user who has access to hdfs, for example, the superuser hdfs.<br>su hdfs<br>/&lt;your_livy_dir&gt;/livy-server-0.2.0/bin/livy-server</code></pre><p style="padding-left: 30px">&nbsp;</p><p style="padding-left: 30px">5. Now if you go to Hue Web UI again, the warning about Spark in Step 2 should be gone. Go to the root of your Hue Web UI URL, then add "/notebook" in the URL. You should be able to add a notebook to run code:</p><p class="scroll" style="padding-left: 30px"><a href="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/01/71/47/6661.hue_spark2.png" original-url="https://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-01-71-47/6661.hue_5F00_spark2.png"><img src="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/01/71/47/6661.hue_spark2.png" original-url="https://blogs.msdn.com/resized-image.ashx/__size/550x0/__key/communityserver-blogs-components-weblogfiles/00-00-01-71-47/6661.hue_5F00_spark2.png" alt="" border="0"></a></p><p style="padding-left: 30px">&nbsp;</p><p style="padding-left: 30px">In the following example, we added a Scala snippet and ran it in the notebook:</p><p style="padding-left: 30px"><a href="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/01/71/47/5460.hue_spark3.png" original-url="https://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-01-71-47/5460.hue_5F00_spark3.png"><img src="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/01/71/47/5460.hue_spark3.png" original-url="https://blogs.msdn.com/resized-image.ashx/__size/550x0/__key/communityserver-blogs-components-weblogfiles/00-00-01-71-47/5460.hue_5F00_spark3.png" alt="" border="0"></a></p><p style="padding-left: 30px">&nbsp;</p><p style="padding-left: 30px">If you keep your ssh console with Livy running open, you will see when you start to run your code in a notebook, a Spark job is being submitted. If there's any error, you will also see it in the console.</p><p style="padding-left: 30px">You can also add Impala snippet, and use the various graphing tools:</p><p style="padding-left: 30px"><a href="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/01/71/47/1070.hue_impala.png" original-url="https://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-01-71-47/1070.hue_5F00_impala.png"><img src="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/01/71/47/1070.hue_impala.png" original-url="https://blogs.msdn.com/resized-image.ashx/__size/550x0/__key/communityserver-blogs-components-weblogfiles/00-00-01-71-47/1070.hue_5F00_impala.png" alt="" border="0"></a></p><p style="padding-left: 30px">For more information about Hue Spark notebook, please see <a title="gethue.com/spark" href="https://gethue.com/spark/" target="_blank">gethue.com/spark</a>.</p><p>&nbsp;</p></p>
]]></content:encoded>
    </item>
    <item>
      <title>Integrating Cloudera cluster with Active Directory (Part 3/3)</title>
      <link>https://docs.microsoft.com/archive/blogs/pliu/integrating-cloudera-cluster-with-active-directory-part-33</link>
      <pubDate>Sat, 02 Jan 2016 19:36:00 GMT</pubDate>
      <dc:creator><![CDATA[Paige Liu]]></dc:creator>
      <guid
        isPermaLink="false">https://blogs.msdn.microsoft.com/pliu/2016/01/02/integrating-cloudera-cluster-with-active-directory-part-33/</guid>
      <description><![CDATA[In Part 1 and Part 2 of this blog, we covered the first 5 steps, here we will describe the remaining...]]></description>
      <content:encoded><![CDATA[In <a target="_blank" href="https://blogs.msdn.com/b/pliu/archive/2016/01/02/integrating-cloudera-cluster-with-active-directory-part-1-3.aspx" rel="noopener noreferrer">Part 1</a> and <a target="_blank" href="https://blogs.msdn.com/b/pliu/archive/2016/01/02/integrating-cloudera-cluster-with-active-directory-part-2-3.aspx" rel="noopener noreferrer">Part 2</a> of this blog, we covered the first 5 steps, here we will describe the remaining Cloudera specific steps to enable Kerberos and Single-Sign-On for web consoles.
<ol>
 	<li>Deploy Active Directory with HA in Azure</li>
 	<li>Deploy Linux VMs for the Cloudera cluster</li>
 	<li>Enable Active Directory DNS on the Linux VMs</li>
 	<li>Sync Linux VMs to Active Directory time service</li>
 	<li>Join the Linux VMs to Active Directory and enable Single-Sign-On</li>
 	<li><strong>Install Cloudera</strong></li>
 	<li><strong>Enable Kerberos on Cloudera</strong></li>
 	<li><strong>Enable Single-Sign-On for Cloudera web consoles</strong></li>
</ol>
<h3>Step 6: Install Cloudera</h3>
<div>By the end of this step, we should have Cloudera bits installed on the Linux VMs.  We should be able to access Cloudera Manager console using the Cloudera Manager admin specified during installation.</div>
<div></div>
<div style="padding-left: 30px">1. Install Cloudera using the template azuredeploy_postad.json in this <a target="_blank" href="https://github.com/liupeirong/Azure/tree/master/ClouderaAD" rel="noopener noreferrer">GitHub repo</a>.  The following parameters must match what was created or modified in previous steps.</div>
<div>
<ul>
 	<li style="list-style-type: none">
<ul>
 	<li>adminUserName: this could be the AD sudo user if the default user created with the VM has been disabled</li>
 	<li>adminPassword</li>
 	<li>dnsNamePrefix</li>
 	<li>adDomainName</li>
 	<li>nodeAddressPrefix</li>
 	<li>numberOfDataNodes</li>
 	<li>region</li>
 	<li>tshirtSize</li>
</ul>
</li>
</ul>
</div>
<div style="padding-left: 30px">2. Verify Cloudera is installed correctly by RDP into a VM within the same VNet, open a browser, and access https://&lt;<em>dnsNamePrefix</em>&gt;-mn0.&lt;<em>adDomainName</em>&gt;:7180.  Use the Cloudera Manager admin credential specified in the template parameters.</div>
<h3>Step 7: Enable Kerberos on Cloudera</h3>
<div>Follow the steps outlined in <a target="_blank" href="https://www.cloudera.com/content/www/en-us/documentation/enterprise/5-4-x/topics/cm_sg_intro_kerb.html" rel="noopener noreferrer">this Cloudera documentation</a> to enable Kerberos on Cloudera with AD.  Most of the steps are fairly clear in the documentation, however, the following steps may need more details:</div>
<div style="padding-left: 30px">1. Since we deployed Cent OS VMs, the default Kerberos encryption type is AES, so JCE policy file is required.  The simplest way to install this file is to go to Cloudera Manager -&gt; Hosts -&gt; Re-run Upgrade Wizard -&gt; check Install JDK and JCE policy file.  Note that this will revert some configuration values to default.  Note down these values, and after the installation, revert them back.</div>
<div style="padding-left: 30px">
<div>2. We already installed OpenLdap client library on all Linux VMs.</div>
<div style="padding-left: 30px"><a href="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/01/67/51/8688.Step7-1-ldaplib.png"><img src="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/01/67/51/8688.Step7-1-ldaplib.png" alt="" border="0" /></a></div>
</div>
<div style="padding-left: 30px">3. Specify Kerberos encryption the same as the output of "klist -e" on a Linux VM:</div>
<div style="padding-left: 60px"><a href="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/01/67/51/4505.Step7-1-CMencrypt.png"><img src="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/01/67/51/4505.Step7-1-CMencrypt.png" alt="" border="0" /></a></div>
<div style="padding-left: 30px">4. When importing KDC account manager credentials, Cloudera Manager issues LDAP requests over SSL.  We need to enable LDAP over SSL on AD.</div>
<div style="padding-left: 30px">
<ul>
 	<li>Add server role "Certificate Authority" to the PDC.  After installation, complete configuration with default options.</li>
 	<li>Run mmc on PDC, add "Certificates" snapin, Computer Account -&gt; Local Computer -&gt; Personal -&gt; Certificates -&gt; All Tasks -&gt; Request New Certificate to request a certificate for Kerberos authentication.  You may need to restart both PDC and BDC after this change.</li>
</ul>
</div>
<div style="padding-left: 90px"><a href="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/01/67/51/2642.Step7-4-cert.png"><img src="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/01/67/51/2642.Step7-4-cert.png" alt="" border="0" /></a></div>
<div style="padding-left: 90px"></div>
<div style="padding-left: 30px">5. If we created an Organizational Unit (OU) in AD, the credential used to generate other credentials must be granted delegation rights to administer user accounts in that OU:</div>
<div style="padding-left: 90px"><a href="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/01/67/51/8105.Step7-5-delegate.png"><img src="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/01/67/51/8105.Step7-5-delegate.png" alt="" border="0" /></a></div>
<div style="padding-left: 30px">6. Complete the wizard.  Now that we enabled Kerberos, if we run the following commands on a Cloudera VM, we should get a security error:</div>
<pre class="scroll" style="padding-left: 60px"><code class="cplusplus">sudo su hdfs
hdfs dfs -ls / 
//should display security error</code></pre>
<p style="padding-left: 30px">7. Create the hadoop superuser hdfs in AD in the same NIS domain.  ssh in as hdfs@&lt;domain name&gt;, run the above command again, it should succeed.
8. Create hadoop users in AD in the same NIS domain, create their home directory with hdfs, then log in as a hadoop user, and run mapreduce job.</p>

<pre class="scroll" style="padding-left: 60px"><code class="cplusplus">//log in as hdfs, create home directory for each hadoop user
hdfs dfs -mkdir /user/alice
hdfs dfs -chown alice /user/alice
 
//log in as a hadoop user, for example, then run mapreduce
hadoop jar /opt/cloudera/parcels/CDH/lib/hadoop-mapreduce/hadoop-mapreduce-examples.jar pi 10 10000 </code></pre>
<h3>Step 8: Enable Single-Sign-On for Cloudera web consoles</h3>
<ol>
 	<li>Follow the <a target="_blank" href="https://www.cloudera.com/content/www/en-us/documentation/enterprise/5-4-x/topics/cm_sg_web_auth.html" rel="noopener noreferrer">Cloudera documentation</a> to enable Single-Sign-On using AD credentials. Once enabled, it will prompt for user credential when we open, for example, Yarn ResourceManager Web UI.  We need to provide the fully qualified user name, for example, someone@bigdata.com.</li>
 	<li>To enable AD authentication for Cloudera Manager console, configure External Authentication:</li>
</ol>
<p style="padding-left: 60px"><a href="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/01/67/51/1882.Step7-8-CMauth.png"><img src="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/01/67/51/1882.Step7-8-CMauth.png" alt="" border="0" /></a></p>
<p style="padding-left: 30px">Note that users must be explicitly added to the AD groups specified here, for example,</p>
<p style="padding-left: 60px"><a href="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/01/67/51/4062.Step7-8-Group.png"><img src="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/01/67/51/4062.Step7-8-Group.png" alt="" border="0" /></a></p>
<p style="padding-left: 30px">Restart Cloudera Manager server:</p>

<pre class="scroll" style="padding-left: 60px"><code class="cplusplus">service cloudera-scm-server restart</code></pre>
All done. In summary, we started from scratch, created an AD forest, deployed a Cloudera cluster, enabled DNS and joined the Cloudera cluster VMs to the AD.  Finally we enabled authentication on Cloudera and web consoles using the credentials managed by AD.]]></content:encoded>
    </item>
    <item>
      <title>Integrating Cloudera cluster with Active Directory (Part 2/3)</title>
      <link>https://docs.microsoft.com/archive/blogs/pliu/integrating-cloudera-cluster-with-active-directory-part-23</link>
      <pubDate>Sat, 02 Jan 2016 19:34:00 GMT</pubDate>
      <dc:creator><![CDATA[Paige Liu]]></dc:creator>
      <guid
        isPermaLink="false">https://blogs.msdn.microsoft.com/pliu/2016/01/02/integrating-cloudera-cluster-with-active-directory-part-23/</guid>
      <description><![CDATA[In Part 1 of this blog, we covered the first 4 steps, here we will describe how to join the LInux...]]></description>
      <content:encoded><![CDATA[<p>In <a href="https://blogs.msdn.com/b/pliu/archive/2016/01/02/integrating-cloudera-cluster-with-active-directory-part-1-3.aspx" target="_blank">Part 1</a> of this blog, we covered the first 4 steps, here we will describe how to join the LInux VMs to AD.<ol>
<li>Deploy Active Directory with HA in Azure</li>
<li>Deploy Linux VMs for the Cloudera cluster</li>
<li>Enable Active Directory DNS on the Linux VMs</li>
<li>Sync Linux VMs to Active Directory time service</li>
<li><strong>Join the Linux VMs to Active Directory and enable Single-Sign-On</strong></li>
<li>Install Cloudera</li>
<li>Enable Kerberos on Cloudera</li>
<li>Enable Single-Sign-On for Cloudera web consoles</li>
</ol><h3>Step 5: Join the Linux VMs to Active Directory and enable Single-Sign-On</h3><div>By the end of this step, we will be able to ssh into Linux VMs using the users created in Active Directory.</div><div style="padding-left: 30px">&nbsp;&nbsp;</div><div style="padding-left: 30px">1. Login to each Linux VM, and run the following commands to join the Linux VMs to AD</div><div>
<pre class="scroll" style="padding-left: 60px"><code class="cplusplus">net ads join -U&lt;a domain admin user name&gt;<br>net ads testjoin -P //verify the VM has joined the domain</code></pre>
</div><div style="padding-left: 30px">2. Run the following commands to update sssd</div><pre class="scroll" style="padding-left: 60px"><code class="cplusplus">authconfig --enablesssd --enablemkhomedir --enablesssdauth --update<br>service sssd start</code>&nbsp;</pre><div style="padding-left: 30px">3. RDP into the PDC and BDC, open cmd console as Administrator, and enable Linux identity management in AD by running the following commands, restart the Windows VMs after the commands finish.</div><pre class="scroll" style="padding-left: 60px"><code class="cplusplus">//install the administration tools for Identity Management for UNIX<br>dism.exe /online /enable-feature /featurename:adminui /all<br>//install Server for Network Information Server (NIS)<br>dism.exe /online /enable-feature /featurename:nis /all <br>//install Password Synchronization<br>dism.exe /online /enable-feature /featurename:psync /all </code></pre><div style="padding-left: 30px">4. In PDC, open Active Directory Users and Computers, if it's not installed, go to Add Roles and Features -&gt; Remote Server Administration Tools -&gt; Role Administration Tools -&gt; AD DS and AD LDS Tools -&gt; AD DS Tools. &nbsp;Optionally create an organizational unit for the Cloudera environment, add groups, for example, hadoopadmin and hadoopuser, then set their NIS domain the the AD domain:</div><div style="padding-left: 60px"><a href="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/01/67/51/6607.Step5-1-NISdomain.png" original-url="https://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-01-67-51/6607.Step5_2D00_1_2D00_NISdomain.png"><img src="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/01/67/51/6607.Step5-1-NISdomain.png" original-url="https://blogs.msdn.com/resized-image.ashx/__size/550x0/__key/communityserver-blogs-components-weblogfiles/00-00-01-67-51/6607.Step5_2D00_1_2D00_NISdomain.png" alt="" border="0"></a></div><div style="padding-left: 30px">5. Add users to the organizational unit in the same NIS domain, and assign them to the groups created in the previous step. &nbsp;If a user has a different primary group, make sure to explicitly add the user to the target group in the "Members" tab (not the UNIX tab) of the group.&nbsp;</div><div style="padding-left: 60px"><a href="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/01/67/51/7610.Step5-2-NISuser.png" original-url="https://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-01-67-51/7610.Step5_2D00_2_2D00_NISuser.png"><img src="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/01/67/51/7610.Step5-2-NISuser.png" original-url="https://blogs.msdn.com/resized-image.ashx/__size/550x0/__key/communityserver-blogs-components-weblogfiles/00-00-01-67-51/7610.Step5_2D00_2_2D00_NISuser.png" alt="" border="0"></a></div><div style="padding-left: 30px">6. Move the Linux VMs which joined the AD in #1 to the Cloudera organization unit, and set them to same NIS domain&nbsp;</div><div style="padding-left: 60px"><a href="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/01/67/51/6305.Step5-3-NISvm.png" original-url="https://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-01-67-51/6305.Step5_2D00_3_2D00_NISvm.png"><img src="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/01/67/51/6305.Step5-3-NISvm.png" original-url="https://blogs.msdn.com/resized-image.ashx/__size/550x0/__key/communityserver-blogs-components-weblogfiles/00-00-01-67-51/6305.Step5_2D00_3_2D00_NISvm.png" alt="" border="0"></a></div><div style="padding-left: 30px">7. Verify we can now ssh into Linux VMs using the AD users</div><div style="padding-left: 30px">8. Optionally we can add AD groups as sudoers as shown in the following example. &nbsp;We can also disable the initial Linux user that was created with the VM, and from now on only allow AD users to login.</div><div>
<pre class="scroll" style="padding-left: 60px"><code class="cplusplus">%hadoopadmin ALL=(ALL) NOPASSWD: ALL</code></pre>
</div><p>Although we have deployed Linux VMs that have disk configuration and host name conventions configured for Cloudera, the rest of the configuration for joining AD and Single-Sign-On up until this point is not Cloudera specific. &nbsp;You can join any Linux VMs to AD using the steps above. &nbsp;The key here is the configuration files we deployed on the Linux VMs. &nbsp;</p><ul>
<li>/etc/resolv.conf</li>
<li>/etc/ntp.conf</li>
<li>/etc/krb5.conf</li>
<li>/etc/samba/smb.conf</li>
<li>/etc/sssd/sssd.conf</li>
</ul><div>In <a href="https://blogs.msdn.com/b/pliu/archive/2016/01/02/integrating-cloudera-cluster-with-active-directory-part-3-3.aspx" target="_blank">Part 3</a> of this blog, we will cover the remaining Cloudera specific steps to enable Kerberos and Single-Sign-On for web consoles.&nbsp;</div></p>
]]></content:encoded>
    </item>
    <item>
      <title>Integrating Cloudera cluster with Active Directory (Part 1/3)</title>
      <link>https://docs.microsoft.com/archive/blogs/pliu/integrating-cloudera-cluster-with-active-directory-part-13</link>
      <pubDate>Sat, 02 Jan 2016 19:30:00 GMT</pubDate>
      <dc:creator><![CDATA[Paige Liu]]></dc:creator>
      <guid
        isPermaLink="false">https://blogs.msdn.microsoft.com/pliu/2016/01/02/integrating-cloudera-cluster-with-active-directory-part-13/</guid>
      <description><![CDATA[[Update 8/2017: With Cloudera Director support on Azure, you can now automate this whole process of...]]></description>
      <content:encoded><![CDATA[<em>[Update 8/2017: With Cloudera Director support on Azure, you can now automate this whole process of enabling Kerberos on a Cloudera cluster.  See this <a href="https://github.com/liupeirong/Azure/tree/master/DomainJoinedLinuxVMOnAzure/clouderadirector">Github repo</a> for instructions and scripts.]</em>

In this blog post, we will show you step by step how to secure a Cloudera cluster by enabling DNS, Single-Sign-On (SSO) and Kerberos with Active Directory.  While we will deploy Active Directory and Cloudera VMs in Azure, because Azure makes deployment much easier, it doesn't have to be Azure to integrate AD with Cloudera.  Many of the steps should apply to AD and Cloudera in general.  Here's what this system topology looks like.

<a href="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/01/67/51/2148.ADArchitecture.png"><img src="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/01/67/51/2148.ADArchitecture.png" alt="" border="0" /></a>

The following steps are described in details.
<ol>
 	<li><strong>Deploy Active Directory with HA in Azure</strong></li>
 	<li><strong>Deploy Linux VMs for the Cloudera cluster</strong></li>
 	<li><strong>Enable Active Directory DNS on the Linux VMs</strong></li>
 	<li><strong>Sync Linux VMs with Active Directory time service</strong></li>
 	<li>Join the Linux VMs to Active Directory and enable Single-Sign-On</li>
 	<li>Install Cloudera</li>
 	<li>Enable Kerberos on Cloudera</li>
 	<li>Enable Single-Sign-On for Cloudera web consoles</li>
</ol>
<div>Part 1 of this blog will cover the first 4 steps, <a target="_blank" href="https://blogs.msdn.com/b/pliu/archive/2016/01/02/integrating-cloudera-cluster-with-active-directory-part-2-3.aspx" rel="noopener noreferrer">Part 2</a> will explain how to join Linux VMs to AD and enable Single-Sign-On, and <a target="_blank" href="https://blogs.msdn.com/b/pliu/archive/2016/01/02/integrating-cloudera-cluster-with-active-directory-part-3-3.aspx" rel="noopener noreferrer">Part 3</a> will cover the remaining Cloudera specific steps.</div>
<h3><strong>Step 1: Deploy Active Directory with HA in Azure</strong></h3>
By the end of this step, we will have an AD forest with a primary domain controller (PDC) and a backup domain controller (BDC).  We can create this AD forest by simply deploying<a target="_blank" href="https://github.com/Azure/azure-quickstart-templates/tree/master/active-directory-new-domain-ha-2-dc" rel="noopener noreferrer"> this template</a> on Azure Quick Start Templates repo on GitHub.  Among the parameters to the template, the following two impact the rest of the components in this system:
<div>
<ul>
 	<li>Virtual Network (VNet):  the AD VMs and the Cloudera VMs must be in the same virtual network (which also implies the same region).  The AD VMs and the Cloudera VMs can be in different subnets of this VNet.</li>
 	<li>Domain name: this is the domain that will be used by all the VMs in this system.  In this example, we specify <em>mydomain.com</em> as our domain name.</li>
</ul>
</div>
<h3><strong>Step 2: Deploy the Linux VMs for Cloudera cluster</strong></h3>
By the end of this step, we will have 4 identical Cent OS VMs in Azure, with necessary SSO and Kerberos packages installed and /etc/krb5.conf, /etc/samba/smb.conf, /etc/sssd/sssd.conf, and /etc/ntp.conf configured.
<ol>
 	<li>If we want a different subnet for Cloudera than AD, we can go to the Azure portal and create a subnet for Cloudera.  Make sure to use the name and IP address of the VNet created in Step 1 and the subnet created here as the network parameters for the template below.</li>
 	<li>Normally we can deploy a Cloudera cluster in Azure using <a target="_blank" href="https://github.com/Azure/azure-quickstart-templates/tree/master/cloudera-on-centos" rel="noopener noreferrer">this template</a>.  However, it uses public DNS and hosts files for domain resolution.  To integrate with AD instead, we need to refactor this template by splitting it into two parts: the deployment of the VMs, and the installation of Cloudera.  The refactored template can be found <a target="_blank" href="https://github.com/liupeirong/Azure/tree/master/ClouderaAD" rel="noopener noreferrer">here</a>.  Deploy azuredeploy.json in this step.  The following parameters must match what we have created in #1.</li>
</ol>
<ul>
 	<li style="list-style-type: none">
<ul>
 	<li><em>adDomainName</em>, for example, bigdata.com</li>
 	<li><em>PDC</em>, the host name of the PDC, for example, adpdc</li>
 	<li><em>BDC</em>, the host name of the BDC, for example, adbdc</li>
 	<li><em>PDCIP</em>, the static private IP of the PDC, for example, 10.0.0.4</li>
 	<li><em>BDCIP</em>, the static private IP of the BDC, for example, 10.0.0.5</li>
 	<li><em>region</em>, the same region as the AD forest</li>
 	<li><em>virtualNetworkName</em>, the same virtual network as the AD</li>
 	<li><em>vnetResourceGroup</em>, the resource group where the virtual network is located, not necessarily same as the resource group the Cloudera VMs will live in</li>
 	<li><em>subnetName</em>, the subnet for Cloudera VM, must be created in #1 if not already exists</li>
 	<li><em>subnetPrefix</em>, the IP CIDR for the Cloudera subnet</li>
 	<li><em>nodeAddressPrefix</em>, the first 3 octets of the subnetPrefix</li>
</ul>
</li>
</ul>
We can deploy either a production or an evaluation type of cluster with any number of data nodes, for simplicity, here we will deploy an evaluation cluster with 1 master node and 3 data nodes.  If we specify <em>cloudera</em> in the <em>dnsNamePrefix</em>, and <em>bigdata.com</em> in <em>adDomainName</em>, the 4 VMs will have these FQDNs:
<ul>
 	<li style="list-style-type: none">
<ul>
 	<li><em>cloudera-mn0.bigdata.com</em></li>
 	<li><em>cloudera-dn0.<em>bigdata</em>.com</em></li>
 	<li><em>cloudera-dn1.<em>bigdata</em>.com</em></li>
 	<li><em>cloudera-dn2.<em>bigdata</em>.com</em></li>
</ul>
</li>
</ul>
<div>However, the VMs are not addressable with these domain names until we integrate the VMs with Active Directory DNS.  All the VMs have static IP addresses within the VNet.  The deployment also populates the following files in each VM with the specified AD info:</div>
<div>
<ul>
 	<li style="list-style-type: none">
<ul>
 	<li>/etc/resolv.conf</li>
 	<li>/etc/ntp.conf</li>
 	<li>/etc/krb5.conf</li>
 	<li>/etc/samba/smb.conf</li>
 	<li>/etc/sssd/sssd.conf</li>
</ul>
</li>
</ul>
</div>
<h3><em>S</em>tep 3: Enable Active Directory DNS on Linux VMs</h3>
By the end of this step, we should be able to ping the Linux VMs with their FQDN from within the VNet.  Note that registering a domain name on the Internet is out of the scope of this blog, so here we will use the AD domain, for example, <em>bigdata.com</em> within the VNet.
<p style="padding-left: 30px">1.  RDP into the PDC, and open the DNS Manager.  Note that if DNS Manager is not installed, install it by "Add Roles and Features" -&gt; Features -&gt; Role Administration Tools -&gt; DNS Server Tools
2.  Add a new reverse lookup zone if there's none that corresponds to the subnet address range where the Linux VMs are located</p>
<p style="padding-left: 60px"><a href="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/01/67/51/1057.Step3-1-reverseAD.png"><img src="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/01/67/51/1057.Step3-1-reverseAD.png" alt="" border="0" /></a></p>
<p style="padding-left: 30px">
3.  Add the Linux VMs to the forward lookup zone with their static IPs, check "create/update associated PTR record"</p>
<p style="padding-left: 60px"><a href="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/01/67/51/3644.Step3-2-forwardAD.png"><img src="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/01/67/51/3644.Step3-2-forwardAD.png" alt="" border="0" /></a></p>
<p style="padding-left: 30px">4.  On the Linux VMs, verify VMs are reachable by their DNS names:</p>

<pre class="scroll" style="padding-left: 60px"><code class="cplusplus">hostname -i //should display the static IP of the VM
host &lt;VM static IP&gt; //should perform DNS reverse lookup and display FQDN of the VM
ping &lt;VM name.mydomain.com&gt; //should successfully reach any of the 4 Cloudera VMs within the VNet</code></pre>
<h3>Step 4: Sync Linux VMs with Active Directory time service</h3>
By default, the AD domain controllers deployed in this example are already running time service for its clients to sync.  The Linux VMs also have their /etc/ntp.conf configured to sync with AD.  If your AD doesn't have time service running, you can use the steps below to configure it.
<p style="padding-left: 30px">1.  On the PDC, configure the Windows Time service by running this command, time.windows.com is a valid time server, or you can use another time server of your choice, restart the time service</p>

<pre class="scroll" style="padding-left: 60px"><code class="cplusplus">w32tm /config /manualpeerlist:"time.windows.com" /syncfromflags:manual /reliable:yes /update
net restart w32time</code></pre>
<p style="padding-left: 30px">2.  On the BDC, restart the time service by running the following command:</p>

<pre class="scroll" style="padding-left: 60px"><code class="cplusplus">w32tm /config /syncfromflags:domhier /update</code></pre>
<p style="padding-left: 30px">3.  On the Linux VMs, verify time syncing with the following command, the "system peer" in the output should point to the PDC:</p>

<pre class="scroll" style="padding-left: 60px"><code class="cplusplus">ntpdc -c sysinfo</code></pre>
Now we have an AD forest with a PDC and a BDC.  We have Linux VMs addressable by AD DNS and syncing to the AD time service.  In <a target="_blank" href="https://blogs.msdn.com/b/pliu/archive/2016/01/02/integrating-cloudera-cluster-with-active-directory-part-2-3.aspx" rel="noopener noreferrer">Part 2</a> of this blog, we will join the Linux VMs to AD and enable ssh with AD users.]]></content:encoded>
    </item>
    <item>
      <title>Real Time Analytics with Azure Event Hubs, Cloudera, and Azure SQL</title>
      <link>https://docs.microsoft.com/archive/blogs/pliu/real-time-analytics-with-azure-event-hubs-cloudera-and-azure-sql</link>
      <pubDate>Wed, 18 Nov 2015 17:42:00 GMT</pubDate>
      <dc:creator><![CDATA[Paige Liu]]></dc:creator>
      <guid
        isPermaLink="false">https://blogs.msdn.microsoft.com/pliu/2015/11/18/real-time-analytics-with-azure-event-hubs-cloudera-and-azure-sql/</guid>
      <description><![CDATA[In this blog post, I will demonstrate how to ingest data from Azure Event Hubs to...]]></description>
      <content:encoded><![CDATA[<p>In this blog post, I will demonstrate how to ingest data from Azure Event Hubs to Spark&nbsp;Streaming&nbsp;running on Cloudera EDH, process the data in real time using Spark SQL, and write the results to Azure SQL database.&nbsp; Alternatively, data&nbsp;processing can also be done using Impala.&nbsp; This example uses the same data generator as described in<a href="https://azure.microsoft.com/en-us/documentation/articles/stream-analytics-get-started/" target="_blank"> this article about Azure Stream Analytics</a>.<h1><span style="font-size: small"><span style="font-size: large">Scenario:</span>&nbsp;</span></h1><p>A telecommunications company has a large volume of data for incoming calls.&nbsp; The company needs to -</p><ol>
<li>Obtain insights about customer usage aggregated across geographical regions in real time</li>
<li>Detect SIM fraud (multiple calls coming from the same identity around the same time but in geographically different locations) in real time</li>
</ol><h1><span style="font-size: large">Ingesting data:</span></h1><p>Data ingestion is the same&nbsp;as described in the aforementioned article about Stream Analytics.&nbsp;&nbsp;Follow these&nbsp;main steps:</p><h4><span style="font-size: small">Step 1: Create an Event Hubs Input</span>&nbsp;</h4><ol>
<li>Go to the <a href="https://manage.windowsazure.com" target="_blank">Azure portal</a>, click <strong>New </strong>-&gt; <strong>App Services </strong>-&gt; <strong>Service Bus </strong>-&gt; <strong>Event Hub </strong>-&gt; <strong>Quick Create</strong> to create a new Event Hub</li>
<li>Go to the newly created Event Hub, on the <strong>Consumer Groups</strong> tab, click <strong>Create</strong> at the bottom of the page to create a new consumer group</li>
<li>On the <strong>Configure</strong> tab of the Event Hub, under <strong>Shared Access Policies</strong>, create a new policy with <strong>Manage</strong> permissions</li>
<li>Save the changes, and navigate to the <strong>Dashboard</strong>, click <strong>Connection Information</strong> at the bottom of the page, and copy down the connection information</li>
</ol><h4><span style="font-size: small">Step 2: Download and configure the sample app&nbsp;that can generate sample&nbsp;call records and push them to Event Hubs</span></h4><ol>
<li>Download the event generator sample app from <a href="https://github.com/Azure/azure-stream-analytics/tree/master/DataGenerators/TelcoGenerator" target="_blank">GitHub</a>&nbsp;</li>
<li>Replace the Microsoft.ServiceBus.ConnectionString and EvenHubName values in App.Config with your Event Hub connection string and name</li>
<li>Run the solution</li>
</ol><p style="padding-left: 60px"><span style="color: #993366"><em>telcodatagen [#NumCDRsPerHour] [SIM Card Fraud Probability] [#DurationHours]</em></span></p><p style="padding-left: 30px">The following example will generate 1000 events with a 20% probability of fraud over the course of 2 hours</p><p style="padding-left: 60px"><span style="color: #993366"><em>telcodatagen 1000 .2 2</em></span></p><h4><span style="font-size: small">Step 3: Optionally you can verify that you are able to receive data from Event Hubs using the <a href="https://github.com/hdinsight/eventhubs-client" target="_blank">Java client for Event Hubs</a>.</span> &nbsp;</h4><p>There are two reasons you may want to do this:</p><ol>
<li>Become familiar with how Java client for Event Hubs works, what packages are needed, and how to build it etc, which can be helpful when we run Spark Streaming in Scala below</li>
<li>Make sure the ingestion pipeline works</li>
</ol><h1><span style="font-size: large">Processing data&nbsp;with Spark Streaming and Spark SQL on Cloudera:</span></h1><p>If you don't already have a Cloudera cluster, you can <a href="https://azure.microsoft.com/en-us/marketplace/partners/cloudera/clouderaedhcloudera/" target="_blank">install it from a simple UI wizard on Azure Marketplace</a>, which is also used in this example.&nbsp; But the cluster doesn't have to be in any specific environment, as long as you have Spark on YARN installed on the cluster. &nbsp;Please note that different versions of Spark do require some changes in the code. &nbsp;Here, we are using Spark 1.3.0 installed with Cloudera 5.4.</p><p>You can find the source code for this Spark job on <a href="https://github.com/liupeirong/Azure/tree/master/EventHubStream" target="_blank">GitHub</a>. &nbsp; Below are the key steps:</p><h2><span style="font-size: medium">Running the Spark job in Spark-Shell</span></h2><p>Before submitting a Spark job in cluster mode, it's a good idea to run Spark interactively with spark-shell for easy troubleshooting. &nbsp;In the YARN client mode, the Spark driver runs on the local machine, so any additional jars must be available on the local machine. &nbsp;Any additional jars required by the Spark executors must be available on the Spark executor nodes as well. &nbsp;For simplicity, we copied all the necessary jars to the /libs folder on both the Spark driver and the executors.</p><p style="padding-left: 30px"><span style="color: #993366"><em>spark-shell --master yarn --deploy-mode client --executor-cores 4 -usejavacp --jars /libs/spark-streaming-eventhubs_2.10-0.1.0.jar,/libs/eventhubs-client-0.9.1.jar,/libs/qpid-amqp-1-0-client-0.32.jar,/libs/qpid-amqp-1-0-client-jms-0.32.jar,/libs/qpid-amqp-1-0-common-0.32.jar,/libs/qpid-client-0.32.jar,/libs/qpid-common-0.32.jar --driver-class-path /libs/sqljdbc4.jar --conf spark.executor.extraClassPath=/libs/sqljdbc4.jar</em></span></p><ul>
<li>You can build spark-streaming-eventhubs jar from the&nbsp;<a href="https://github.com/hdinsight/spark-eventhubs" target="_blank">source code of the Event Hubs receiver for Spark Streaming</a>, or you can download it from <a href="https://github.com/hdinsight/hdinsight-spark-examples/tree/master/sparkstreaming/lib" target="_blank">this Even Hubs Spark Streaming example</a>.&nbsp;</li>
<li>You can build eventhubs-client jar from the source code of the <a href="https://github.com/hdinsight/eventhubs-client" target="_blank">Java client for Event Hubs</a>.</li>
<li>You can <a href="https://www.microsoft.com/en-us/download/details.aspx?id=19847" target="_blank">download</a> sqljdbc jar. &nbsp;</li>
<li>One important thing to note is that the number of executor cores must double the number of Event Hubs partitions so that the executor can receive data from Event Hubs and also process the data at the same time. &nbsp;If this is not set correctly, you will not see any error, but there will be no output data either. &nbsp;It will appear that the job is not doing anything.&nbsp;</li>
</ul><h4><span style="font-size: small"><strong>Step 1</strong>: Receive data in Spark Streaming from Event Hubs</span></h4><p>In the interactive command prompt of spark-shell, you can paste the following Scala code to run the Spark Streaming job, replacing the parameters with your own. &nbsp;&nbsp;</p><pre class="scroll"><em><code class="java">import org.apache.spark.SparkConf<br>import org.apache.spark.SparkContext<br>import org.apache.spark.streaming.eventhubs.EventHubsUtils<br>import org.apache.spark.streaming.{Seconds, StreamingContext}<br> <br>val streamBatchIntervalInSeconds = 60<br>val ehParams = Map[String, String](<br> "eventhubs.policyname" -&gt; "your event hubs rule name",<br> "eventhubs.policykey" -&gt; "your event hubs policy key",<br> "eventhubs.namespace" -&gt; "your event hubs namespace",<br> "eventhubs.name" -&gt; "your event hubs name",<br> "eventhubs.partition.count" -&gt; "2", //executor core count must be twice that of partition count<br> "eventhubs.consumergroup" -&gt; "your event hubs consumer group name",<br> "eventhubs.checkpoint.dir" -&gt; "your spark checkpoint dir in hdfs", //for simplicity we are not using reliable receiver with checkpoint in this example<br> "eventhubs.checkpoint.interval" -&gt; "600")<br>val ssc = new StreamingContext(sc, Seconds(streamBatchIntervalInSeconds))<br>val stream = EventHubsUtils.createUnionStream(ssc, ehParams)<br>val lines = stream.map(msg =&gt; new String(msg))<br>lines.print()<br>ssc.start()</code></em></pre><p>Start the telcodatagen mentioned earlier to generate some data for input. &nbsp;If you can see each line received from Event Hubs printed out in the spark-shell, congratulations, you have everything wired up correctly. &nbsp;</p><h4><span style="font-size: small"><strong>Step 2</strong>: Run real time queries in Spark SQL</span>&nbsp;&nbsp;</h4><p>Replace "<span style="color: #993366"><em>lines.print()</em></span>" in the above Scala code with the following code.</p><pre class="scroll"><em><code class="java"> //convert international datetime string to unix time<br> val isoformat = new java.text.SimpleDateFormat("yyyy-MM-dd'T'hh:mm:ss'Z'")<br> def date2long: (String =&gt; Long) = (s: String) =&gt; try { isoformat.parse(s).getTime() } catch { case _: Throwable =&gt; 0 }<br> val sqlfunc = udf(date2long)<br> <br> //define sqlContext<br> val sqlContext = new org.apache.spark.sql.SQLContext(sc)<br> import sqlContext.implicits._<br> import org.apache.spark.sql.functions._<br> <br> //process the data using Spark SQL<br> lines.foreachRDD { rdd =&gt; if (rdd.count() &gt; 0) {<br> val rawdf = sqlContext.jsonRDD(rdd);<br> // convert international time string to unix time for easy calculation<br> val df = rawdf.withColumn("callTime", sqlfunc(rawdf("callrecTime")));<br> // use the min time of this mini batch as the timestamp for the aggregated entry<br> val minTime = df.filter(df("callTime") &gt; 0).select("callTime").first().getLong(0);<br> // real time aggregation by region<br> val callsByRegion = df.groupBy("SwitchNum").count().withColumnRenamed("count", "callCount").withColumn("callTimeStamp", lit(minTime));<br> callsByRegion.show();<br> }<br> }</code></em></pre><p>Now you should be able to see aggregated results in the spark-shell console output. &nbsp;Note that the aggregation is applied directly on the Spark SQL DataFrame without having to run a SQL query. &nbsp;For more complex data analysis, such as detecting fraud in this example, we can run a query like the following:</p><pre class="scroll"><em><code class="java">df.registerTempTable("calls");<br>val fraudCalls = sqlContext.sql("SELECT CS1.CallingIMSI, CS1.callrecTime as calltime1, CS2.callrecTime as calltime2, CS1.CallingNum as CallingNum1, CS2.CallingNum as CallingNum2, CS1.SwitchNum as Switch1, CS2.SwitchNum as Switch2 FROM calls CS1 inner JOIN calls CS2 ON CS1.CallingIMSI = CS2.CallingIMSI AND (CS1.callTime - CS2.callTime) between 1000 AND 5000 WHERE CS1.SwitchNum != CS2.SwitchNum order by CS1.CallingIMSI, CS1.callrecTime");</code></em></pre><p>Note that this query will fail in Spark 1.3.0, probably related to a <a href="https://issues.apache.org/jira/browse/SPARK-6247" target="_blank">bug</a>&nbsp;with self joins in Spark SQL. &nbsp;We will demonstrate how to run this query in Impala instead later in this article.</p><h4><span style="font-size: small"><strong>Step 3</strong>: Store results in Azure SQL Server</span></h4><p>Create a table in Azure SQL Server:</p><pre style="padding-left: 30px"><span style="color: #993366"><em>CREATE TABLE callsByRegion (</em></span><br><span style="color: #993366"><em> SwitchNum NVARCHAR (20) NOT NULL,</em></span><br><span style="color: #993366"><em> callCount INT NOT NULL,</em></span><br><span style="color: #993366"><em> callTimeStamp BIGINT NOT NULL</em></span><br><span style="color: #993366"><em>);</em></span><br><span style="color: #993366"><em>CREATE CLUSTERED INDEX IX_callsByRegion</em></span><span style="color: #993366"><em> ON callsByRegion(callTimeStamp ASC);</em></span></pre><p>Add a jdbc connection string variable anywhere before "<span style="color: #993366"><em>lines.foreachRDD...</em></span>" in the above Scala code, replacing parameters with your own:</p><pre class="scroll"><em><code class="java">val jdbccxn = "jdbc:sqlserver://&lt;your azure db server&gt;.database.windows.net:1433;database=&lt;your db name&gt;;user=&lt;your db username&gt;;password=&lt;your password&gt;;encrypt=false;loginTimeout=30;"</code></em></pre><p>Replace "<span style="color: #993366"><em>callsByRegion.show()</em></span>" in the above Scala code with the following code:</p><pre class="scroll"><em><code class="java">//save real time aggregation to sql azure<br>callsByRegion.insertIntoJDBC(jdbccxn, "callsByRegion", false);</code></em></pre><p>Run the Spark job again and check your Azure SQL Server. &nbsp;You should see aggregated data in the callsByRegion table in your database.</p><h2><span style="font-size: medium">Running the Spark job with Spark-Submit</span></h2><p>Once everything runs fine in spark-shell, for production workload, you would want to submit the job to the Spark cluster. &nbsp;Using spark-submit, you can run the job either in client mode or cluster mode. &nbsp;You can build the Scala application into a jar and apply dependencies at run time, or you can build a uber jar that has all the dependencies in it. &nbsp;Check out this example on <a href="https://github.com/liupeirong/Azure/tree/master/EventHubStream" target="_blank">GitHub</a>&nbsp;to see how to build the jars in maven.</p><h4><span style="font-size: small">Running the job in YARN <strong>client mode</strong></span></h4><p>Note that the order of the parameters in the following commands is important. &nbsp;--class and app jar must be at the end of each command.&nbsp;</p><p>Using a jar without dependencies:</p><p style="padding-left: 30px"><em><span style="color: #993366">spark-submit --master yarn --deploy-mode client --executor-cores 4 --jars /libs/spark-streaming-eventhubs_2.10-0.1.0.jar,/libs/eventhubs-client-0.9.1.jar,/libs/qpid-amqp-1-0-client-0.32.jar,/libs/qpid-amqp-1-0-client-jms-0.32.jar,/libs/qpid-amqp-1-0-common-0.32.jar,/libs/qpid-client-0.32.jar,/libs/qpid-common-0.32.jar --driver-class-path /libs/sqljdbc4.jar --conf spark.executor.extraClassPath=/libs/sqljdbc4.jar --class com.sparkeventhub.sample.SparkEventHubSample ./app.jar</span></em></p><p>Using a uber jar with dependencies:</p><p style="padding-left: 30px"><span style="color: #993366"><em>spark-submit --master yarn --deploy-mode client --executor-cores 4 --driver-class-path /libs/sqljdbc4.jar --conf spark.executor.extraClassPath=/libs/sqljdbc4.jar --class com.sparkeventhub.sample.SparkEventHubSample ./app-jar-with-dependencies.jar</em></span></p><h4><span style="font-size: small">Running the job in YARN <strong>cluster mode</strong></span></h4><p>Using a jar without dependencies:</p><p style="padding-left: 30px"><span style="color: #993366"><em>spark-submit --master yarn --deploy-mode cluster&nbsp; --executor-cores 4 --driver-cores 2 --jars /libs/spark-streaming-eventhubs_2.10-0.1.0.jar,/libs/eventhubs-client-0.9.1.jar,/libs/qpid-amqp-1-0-client-0.32.jar,/libs/qpid-amqp-1-0-client-jms-0.32.jar,/libs/qpid-amqp-1-0-common-0.32.jar,/libs/qpid-client-0.32.jar,/libs/qpid-common-0.32.jar --driver-class-path /libs/sqljdbc4.jar --conf spark.executor.extraClassPath=/libs/sqljdbc4.jar --class com.sparkeventhub.sample.SparkEventHubSample ./app.jar</em></span></p><p>Using a uber jar with dependencies:</p><p style="padding-left: 30px"><em><span style="color: #993366">spark-submit --master yarn --deploy-mode cluster --executor-cores 4 --driver-cores 2 --driver-class-path /libs/sqljdbc4.jar --conf spark.executor.extraClassPath=/libs/sqljdbc4.jar --class com.sparkeventhub.sample.SparkEventHubSample ./app-jar-with-dependencies.jar</span></em></p><h1><span style="font-size: large">Processing data&nbsp;with Impala</span></h1><p>Instead of running queries in Spark SQL, we can alternatively store the data in hdfs, and run queries in real time with Impala. &nbsp;To store data in HDFS, add a variable to the output file path in HDFS anyhere before "<span style="color: #993366"><em>lines.foreachRDD...</em></span>" in the above Scala code, replacing the path with your own:</p><pre class="scroll"><em><code class="java">import org.apache.spark.sql.SaveMode<br>val outputDir = "sparkoutput/calls"</code></em></pre><p>Store the data in HDFS by adding the following code at the end of the "<span style="color: #993366"><em>lines.foreachRDD...</em></span>" block:</p><pre class="scroll"><em><code class="java">df.registerTempTable("rawcalls");<br>val calls=sqlContext.sql("SELECT callrecTime, SwitchNum, CallingIMSI, CallingNum, CalledNum, callTime from rawcalls");<br>calls.save(outputDir, SaveMode.Append);<br></code></em></pre><p>Run the job again, and you should be able to see parquet files being stored in the specified HDFS folder. &nbsp;The folder may be relative to the current HDFS user home directory, for example "/user/hdfs/sparkoutput/calls". &nbsp;Create an external table in Impala:</p><p style="padding-left: 30px"><em><span style="color: #993366">create external table calls (callrecTime string, SwitchNum string, CallingIMSI string, CallingNum string, CalledNum string, callTime bigint) stored as parquet location '/user/hdfs/sparkoutput/calls'</span></em></p><p>Query the data in Impala:</p><p style="padding-left: 30px"><span style="color: #993366"><em>SELECT CS1.CallingIMSI, CS1.callrecTime as calltime1, CS2.callrecTime as calltime2, CS1.CallingNum as CallingNum1, CS2.CallingNum as CallingNum2, CS1.SwitchNum as Switch1, CS2.SwitchNum as Switch2 FROM calls CS1 inner JOIN calls CS2 ON CS1.CallingIMSI = CS2.CallingIMSI AND (CS1.callTime - CS2.callTime) between 1000 AND 5000 WHERE CS1.SwitchNum != CS2.SwitchNum order by CS1.CallingIMSI, CS1.callrecTime</em></span></p><p>There you have it. &nbsp;I'm new to Spark Streaming, Spark SQL, and Impala. &nbsp;Would love to learn if there are better ways to do this.&nbsp;</p></p>
]]></content:encoded>
    </item>
  </channel>
</rss>