Wednesday, 1 June 2016

The definitive guide for Elasticsearch on Windows Azure

Running Elasticsearch in the cloud with Azure is fairly easy. There are several guides out there talking about how to do this, but my way of doing this is a bit different so I thought it'd be worth blogging about. I've also included discussions on some important related topics in the end.
To highlight the main differences from other guides out there, with my approach:
  1. I prefer running Elasticsearch on Linux VMs as opposed to Windows machines. This is simply because once you have an Elasticsearch data node, it's going to be it's sole purpose (at least, that's what I'd recommend), and Linux is so much easier to setup and maintain as a remote box. Even if you're new to this, learning the ropes is not that hard, and most of what you'll need is detailed below.
  2. Once running on a Linux VM, I will never run Elasticsearch on top of OpenJDK - that has too many known problems.
  3. Since this is Azure, you'll most likely be doing this from a Windows machine, so I'll be using tools that are available for Windows users.
  4. I will not setup a load balancher in front of the Elasticsearch cluster, because it's mostly redundant if you are using an official Elasticsearch client which will do sniffing and round robin, so no need to introduce unnecessary friction.
With that in mind, let's start rolling. Log-in to your Windows Azure account, and head to the Management Portal.

Creating the infrastructure

Let's start by creating the infrastructure. You may need to wait after some steps for the resource you just created to be provisioned and started.
  • You start by creating a new Virtual Network. This will create a subnet where our Elasticsearch nodes can properly communicate with each other. As with all things in Azure, you click on the big "+ NEW" button at the bottom, and make sure to specify a proper Location:
Creating new Virtual Network
  • Now create a new Cloud Service for the Elasticsearch cluster to run on. This will be the "host" for all our VMs, which we will create shortly - again make sure the Region is appropriate and is on the same location as the Virtual Network you created:
Creating new Cloud Service
  • We can now start creating Virtual Machines to work with. Go to New -> Compute -> Virtual Machine, and opt for creating new VMs from Gallery. In the Window that opens select the latest Ubuntu version (14.04 LTS at the time of this writing), and click next.
  • There are now 2 screens which will need your attention. In the second screen, "Virtual machine configuration", make sure to specify a good name to the VM, and set a proper size. If this is for production environment, I'd strongly suggest at least 28GB memory, unless you are certain you can work with smaller sizes. Then, on Authentication, uncheck "Upload ssh key" and check "Provide a password instead". This will allow you to SSH into the machine with a username/password key. More on uploading certificates later:
Creating new VM
  • In the next screen you will be asked to attach the VM to a Cloud Service and a Virtual Network. Select the ones we have created ("my-elasticsearch" Cloud Service and "my-elasticsearch-app" Virtual Network in this case), and accept the rest of the defaults:
Creating new VM
  • Click next and finish, and then repeat the process (starting at #3) to create as many VMs as you need. A recommended setup for a basic installation would be 3 nodes (meaning, 3 servers running Elasticsearch) of the same size, to allow for replication factor of two.

Preparing the Linux VMs

After the VMs were created and initialized, you can click on it in the portal to get to the Dashboard and get it's "SSH details". This will be a domain and a port.
Download PuTTY.exe and for each VM you've created, follow the steps below. This is where we prepare the machine to have OracleJVM and Elasticsearch, before we bring up the cluster.
  • With PuTTY, login to the machine and type the username and password you setup for the machine when creating it.
  • Once logged in, execute the following commands:
This one-liner will install Oracle JDK (mostly) silently, and set JAVA_HOME accordingly. For more details on what it's doing, see http://www.webupd8.org/2012/01/install-oracle-java-jdk-7-in-ubuntu-via.html:
echo debconf shared/accepted-oracle-license-v1-1 select true | \
sudo debconf-set-selections && echo debconf shared/accepted-oracle-license-v1-1 seen true | \
sudo debconf-set-selections && sudo add-apt-repository ppa:webupd8team/java && sudo apt-get update && sudo apt-get install oracle-java7-installer && sudo apt-get install oracle-java7-set-default
If you wish to verify the JVM version, you can now run java -version.
Next, download and install latest Elasticsearch (1.2.1 at the time of writing this) using the official Debian package, and also setting it up to run on boot up:
curl -s https://download.elasticsearch.org/elasticsearch/elasticsearch/elasticsearch-1.2.1.deb -o elasticsearch-1.2.1.deb
&& sudo dpkg -i elasticsearch-1.2.1.deb && sudo update-rc.d elasticsearch defaults 95 10

Configuring Elasticsearch

We now have multiple VMs properly installed with Elasticsearch ready to run on them. Before actually running the cluster, there's a few configurations we need to do.
First, we need to tell Elasticsearch how much memory it can consume. The highly-recommended default is 50% of the available memory. Meaning if we have a 28GB instance, we will give Elasticsearch 14GB. We do this by running:
sudo nano /etc/init.d/elasticsearch
And then uncomment ES_HEAP_SIZE=2g (by removing the #) and changing it to be 50% of available memory (e.g.ES_HEAP_SIZE=14g). To quit and save click Ctrl-X, y, and then Enter.
Last remaining bit is the Elasticsearch configurations file. It has a lot of details in it, with a lot of explanations (that you should read!), but on our VM we don't really care about all that, we just need to have the settings relevant to us there. So let's clean the file and get into editing a clean one:
sudo rm /etc/elasticsearch/elasticsearch.yml && sudo nano /etc/elasticsearch/elasticsearch.yml
Paste the following into the file, changing the defaults as per comments below:
cluster.name: my-cluster
node.name: "my-node"
index.number_of_shards: 1
index.number_of_replicas: 2
bootstrap.mlockall: true
gateway.expected_nodes: 3
discovery.zen.minimum_master_nodes: 2
discovery.zen.ping.multicast.enabled: false
discovery.zen.ping.unicast.hosts: ["10.0.0.4", 10.0.0.5", "10.0.0.6"]
To elaborate on what we have done here:
  1. cluster.name is the name of the cluster. It has to be unique per cluster, and all nodes within the same cluster have to share the exact same name.
  2. node.name is just a convenience option, I usually set it to the VM name.
  3. number_of_shards and number_of_replicas is just a default configuration you can override anytime with the index settings API. These defaults are good for a 3-node cluster
  4. bootstrap.mlockall: true ensures Elasticsearch gets all the memory it needs properly. This must be there.
  5. Set gateway.expected_nodes to the number of nodes in your cluster, set discovery.zen.minimum_master_nodes to ceiling(number of nodes / 2), and disable multicast.
  6. discovery.zen.ping.unicast.hosts should contain the IPs of the VMs that you want to participate in the cluster. This needs to be the internal IP on the subnet, and you can get it from the VM dashboard, just by the SSH Details.
Once done, hit Ctrl-X, y, Enter again to quit and save. You can now run Elasticsearch on this VM, you do that by typing:
sudo /etc/init.d/elasticsearch start
And after a few seconds it takes it to initialize, you can verify it is running by pinging it over HTTP:
curl http://localhost:9200
You should get Elasticsearch's Hello World, spoken in JSON.

Managing the node

Elasticsearch now runs as a service, and writes logs to /var/log/elasticsearch. You should consult with them to check for errors and such on a regular basis (or if something went wrong).
To check the status of a node, simply type:
sudo /etc/init.d/elasticsearch status
And to stop a node:
sudo /etc/init.d/elasticsearch stop
To verify our cluster is all up and running, log in to one of the machines and executecurl http://localhost:9200/_cluster/state?pretty. You should see a response similar to this:
{
  "cluster_name" : "my-cluster",
  "version" : 5,
  "master_node" : "Ufyhfc5-RyiK16EJie9lUg",
  "blocks" : { },
  "nodes" : {
    "Ufyhfc5-RyiK16EJie9lUg" : {
      "name" : "es-vm-ub2",
      "transport_address" : "inet[/10.0.0.6:9300]",
      "attributes" : { }
    },
    "uPXj-Gz1RpeEQkCNy7qiYg" : {
      "name" : "es-vbm-ub1",
      "transport_address" : "inet[/10.0.0.4:9300]",
      "attributes" : { }
    },
    "oEpz-mFNSiSr9K_T8PdCFg" : {
      "name" : "es-vm-ub3",
      "transport_address" : "inet[/10.0.0.5:9300]",
      "attributes" : { }
    }
  },
  "metadata" : {
    "templates" : { },
    "indices" : { }
  },
  "routing_table" : {
    "indices" : { }
  },
  "routing_nodes" : {
    "unassigned" : [ ],
    "nodes" : {
      "Ufyhfc5-RyiK16EJie9lUg" : [ ],
      "oEpz-mFNSiSr9K_T8PdCFg" : [ ],
      "uPXj-Gz1RpeEQkCNy7qiYg" : [ ]
    }
  },
  "allocations" : [ ]
}
This will show you the cluster state, and you should be able to tell if you are missing nodes. More on this here:http://www.elasticsearch.org/guide/en/elasticsearch/reference/current/cluster-state.html.

Some advice

Congratulations, you now have your Elasticsearch cluster running on Azure. Here are a few more points for your consideration.

Use separate disks

In this guide we opted to using the VM storage space for logs and data.
You should mount drives to be used for logging and data files. Meaning, attach one new disk for every VM and have it use it as a data storage. This way, you can easily upgrade your Elasticsearch VMs on the go by just destroying machines without copying files. This is also a good practice for data redundancy. I will consider having one shared disk (with separate folders, one for each VM) for logs a good practice as well, then you can have on logstash instance running on top of one disk.
Changing the data and log paths is fairly simple and can be done by changing path.logs and path.data in elasticsearch.yml, more details here.

Log manangement

Speaking of Elasticsearch logs, you should track them. If anything goes south, you should know where to look and that place should be nearby.

Network access

Our Elasticsearch cluster is inaccessible from the outside, and that's good. We don't want people to have access to our data, even if it's read-only. But how to access it from your applications? you have two options:
  1. Deploy your application to Azure. You can create a new Cloud Service and have it run on the same Virtual Network, so the 9200 HTTP port (as well as the 9300 port if your app is in Java) are both open and accessible to you. That is the best approach. Unfrotunately, Azure Websites do not currently support running on a Virtual Network, meaning you can only deploy websites as a Cloud Service if you want them to access the cluster this way.
  2. Alternatively, if you need to access the cluster from elsewhere (or you have to use Azure Websites and cannot convert them to a Cloud Service), you can open the 9200 port but you should protect it with authentication (Seehttps://github.com/Asquera/elasticsearch-http-basic and https://github.com/sonian/elasticsearch-jetty).

Use a good monitoring tool

See BigDeskElasticHQ and Marvel (first 2 are free, latter needs to be purchased). Either way, unless you use HTTP authentication you will not be able to install them as a site-plugin, but will have to deploy them via a secure host deployed to Azure as a Cloud Service.

Use certificates for logging in to the VMs

Instead of typing a username / password combination to log into your VMs, you can upload a certificate and authenticate using a private key. This tends to be more trouble to do on Windows, but it is indeed possible to do. You can also generate a certificate from your OpenSSH keypair (which is what you probably use for git anyway). See here for more details:http://azure.microsoft.com/en-us/documentation/articles/linux-use-ssh-key/.

Using the Azure plugin

Instead of specifying the IPs of the nodes yourself in the elasticsearch.yml config file (aka using Unicast), you can use the official Elasticsearch Azure plugin to figure out what nodes are available for you. I preferred not using it because for small and solid-state clusters this adds friction I'd rather not have, but for large, vibrant clusters this will probably help a lot.
Another benefit of the plugin (which you can leverage separately, even if you don't enable Azure Multicast) is enablingsnapshot/restore for Azure Storage.

Don't use a load balancer

It's tempting to put a load balancer in front of your cluster, but it really doesn't make a lot of sense in the case of Elasticsearch. Most clients (especially the official ones) will do round-robin and fail-over on their own and in addition implement sniffing functionality, to detect new nodes when they join the cluster. Your load balancer (or Azure's) can only be so smart. Elasticsearch clients will be smarter, as long as you make sure to use an official and recent version of a client (or one that was implemented with this in mind).

Automatic provisioning

The manual provisioning steps outlined above can be automated pretty easily, I just hadn't had the opportunity of trying that out. I believe using a Puppet Master or similar, or automatically running a custom provisioning script downloaded from storage. Either way, treat this guide as a boilerplate really, and just use whatever works for you.

Archive Elasticsearch Indices to Azure Blob Storage using the Azure Cloud Plugin

The Azure Cloud plugin for Elasticsearch adds some great capabilities to integrate your Elasticsearch environment with Azure. One of the capabilities it provides is the snapshot and restoration of indices to and from Azure Blob Storage, giving you a cost effective and highly available option for recovery of your indices. This can also provide a method for archiving indices that are no longer in use, but that you would like to be able to access in the future. In this document, we will walk through the deployment of an Elasticsearch cluster on Azure VMs with the newly integrated Azure Cloud plugin and detail the steps to snapshot and restore an index for archival purposes.

Setup

Create a storage account

One of the first things you will need is a storage account to use as a target for your snapshots. In the Azure Portal, select New, Data + Storage, Storage account and create a new storage account using the redundancy option that best suits your requirements (LRS, ZRS, GRS or RA-GRS).
image
Once created, copy the storage account name and one of the access keys, as we will need this when we deploy our Elasticsearch cluster. To get this information, open your storage account, expand All settings and select Access keys. You'll find the name of the storage account as well as the access key, click the copy button to copy to your clipboard and paste them into a Notepad document for easy availability later on.
image

Build an Elasticsearch cluster with the Azure Cloud plugin installed

The Azure Quickstart Template for Elasticsearch has recently been updated to include the capability to install and configure the Azure Cloud plugin. To deploy a cluster, go to the GitHub template link and click the Deploy to Azure button. This will bring you back to the Azure Portal where you can deploy a cluster into your Azure subscription. You can customize the other parameters that pertain to your environment or take the defaults.
It is recommended to select the latest version of Elasticsearch to be installed (2.3.1 at the time of this writing). There are some additional input parameters pertaining to the plugin that have been added (CLOUDAZURE, CLOUDAZURESTORAGEACCOUNT and CLOUDAZURESTORAGEKEY) allowing you to install and configure the plugin automatically. Ensure you select yes to install the plugin (it is set to no by default) and enter the name of the storage account and your storage account key that you created earlier.
image
This plugin implementation will add a couple additional lines of configuration to your elasticsearch.yml file on each node in the cluster specifying the storage account and key. Full information on the allowed parameters can be found on the Elasticsearch Azure Repository documentation page.
image
Once you have deployed your cluster, you are ready to create an index and go through the snapshot process.

Create and populate your index

For purposes of demonstration we are going to create a basic index of data to walk through the steps required to snapshot and restore. You will use the Sense UI deployed with your cluster to do this, but you can also use curl or any other utility that is capable of sending standard HTTP requests. Sense is deployed on the Kibana server; to get the URL open the parent resource group that contains your cluster and click on the Last deployment link.
image
Select Kibana and you will find the KIBANA-URL output from the deployment; click the copy button to copy the URL to your clipboard.
image
The URL for Sense will be http://X.X.X.X:5601/app/sense, substituting your IP address. In Sense, update the server URL to one of the internal addresses of the Elasticsearch nodes.
image
Now we can create an index called myindex with a few documents. Copy/paste the following HTTP requests into Sense and run each command by clicking the green arrow (the cursor will need to be in each command for the arrow to show up).
PUT myindex
{
  "number_of_shards" : 1,
  "number_of_replicas" : 0
}
POST /myindex/documents
{
  "name" : "document1",
  "content" : "Some example content for document1"
}
POST /myindex/documents
{
  "name" : "document2",
  "content" : "Some example content for document2"
}
POST /myindex/documents
{
  "name" : "document3",
  "content" : "Some example content for document3"
}
Now, run the following commands and you will be able to see the newly created index and search against it to see the entries we just added:
GET _cat/indices?v
GET myindex/_search
Now that we have an index, we will go through the process to archive with a snapshot.

Snapshot and archive an index

Create a snapshot repository

The first thing we need to do is create a repository. A repository is a logical container that points to the location where snapshots should be stored and in this case we are going to store our snapshots in Azure. Set up a new repository by running the following in Sense:
PUT _snapshot/myrepository
{
  "type" : "azure"
}
This creates a new repository called myrepository using the parameters for your storage account that are specified in the elasticsearch.yml file.

Take a snapshot

Now take a snapshot of the index:
PUT /_snapshot/myrepository/myindexsnapshot
{
  "indices" : "myindex",
  "include_global_state" : false
}
We have specified a couple options here. The first is indices which allows us to specify the index (or indices separated by commas) that we want to include in this snapshot. The second option is include_global_state which we set to false so that the global state of the cluster is not included in the snapshot, just the index that we want to archive. You can monitor the status of the snapshot progress with the following request:
GET _snapshot/myrepository/myindexsnapshot/_status
When the snapshot has completed, its state should be SUCCESS.
image
If you take a look in your storage account you will see the files associated with your index in a blob container, which by default is called elasticsearch-snapshots. This is configurable by adding thecloud.azure.storage.default.container parameter to your elasticsearch.ymlconfig file with the name of the container you'd like to store the snapshots in, or by passing the container option on the HTTP request.

Delete the index

Now that you have a snapshot of your index we can close it to ensure nothing is being written to the index and then remove it from the cluster.
POST myindex/_close
DELETE myindex
At this point the index is no longer on the cluster and is not consuming any resources other than the Azure Blob storage that the snapshot is using.

Restore an index

Restoring an index to the same cluster is a straightforward process. Since the repository is already registered (assuming that it has not been unregistered) simply POST the repository and snapshot you want to restore to the cluster as follows:
POST _snapshot/myrepository/myindexsnapshot/_restore
You can also restore the snapshot to a different cluster. Supposing we had a second cluster that was configured to use the same Azure Cloud plugin settings, we would need to register the repository with the cluster:
PUT _snapshot/myarchiverepository
{
  "type":"azure"
}
Note that the name of the repository is different. This is simply to demonstrate that the name of the repository does not need to match the name on the cluster where the snapshot was taken, but the name of the snapshot itself will need to match. Now that the repository is registered, we can restore the index:
POST _snapshot/myarchiverepository/myindexsnapshot/_restore
You can monitor recovery by running the following command, which will show details of the recovery activities on the cluster. Additional options are detailed in the Elasticsearch Indices Recovery documentation.
GET _cat/recovery?v
Run a search against the index, and you should see the entries that were added when we initially created the index:
GET myindex/_search

Learn more

The Azure Cloud plugin for Elasticsearch provides a great option for archiving your Elasticsearch indices to low-cost Azure Blob storage, giving you the ability to reduce resources and expenses associated with maintaining indices that may be stale or no longer needed in an immediately online state. For more information on running Elasticsearch in Azure IaaS or on the Elasticsearch Azure Cloud plugin please visit the following links.

Special thanks to Hans Krijger and Harold Perry for their assistance with this post!

Tuesday, 24 May 2016

How to Install LAMP ( Linux - Apache - MySQL - PHP ) on Ubuntu 13.04/13.10/14.04


Launch Your Existing Website Into the Cloud with Azure

0

Web applications have traditionally been deployed to data center hosted servers (e.g. IIS, Apache, etc.) and published either publicly, internally, or a combination of both.
The process of web deployment has consisted of packing up of web content files, copying them to a web server or servers, and configuring settings on the web host to publish the site properly. There have been improvements over the past several years to make publishing web content easier such as the case with Visual Studio.
Moving applications and services to the cloud has also been a point of discussion over the past couple years. In the beginning, the moving of web content, sites, applications, etc. to the cloud often required a rewrite or it just made sense to rewrite the application because of legacy code. However deployment was never straight forward or required complicated tools/scripts. However, there is a simple method to deploy web applications to the cloud. Using Visual Studio I’ll show you how to deploy a web application to Windows Azure.

Dependencies
PUBLISHING A WEB APPLICATION TO WINDOWS AZURE WITH VISUAL STUDIO

Creating a Windows Azure Web Site
Navigate to http://manage.windowsazure.com/ and either log into your account or sign up for a trial account.

Once you’ve logged into Windows Azure, you’ll see a variety of options on the left hand navigation. Select WEB SITES from the list:
clip_image001

Select +NEW at the bottom left hand corner:
clip_image002
Select COMPUTE -> WEB SITE -> QUICK CREATE, add a name under URL and finally check CREATE WEB SITE: 
clip_image004

Verify the site is created and running and flip over to your Visual Studio development environment:
clip_image006
Create a web application or open an existing web application using Visual Studio. When you’re ready to publish the web application follow the steps below: 
PUBLISHING PROCESS
Remember that web site you created at the beginning? On the Profile Page you’ll want to utilize a publishing profile from your Windows Azure account. I’ll describe how to do that next.

DOWNLOAD PUBLISHING FILE 
Let’s take a moment to download the publishing file…
Navigate to http://manage.windowsazure.com/ and either log into your account or sign up for a trial account.
Once you’ve logged into Windows Azure, you’ll see a variety of options on the left hand navigation. Select WEB SITES from the list:
clip_image001[1]

Select the web site you created in the previous steps:
clip_image008

Select DASHBOARD and then select “Download the publish profile”:
clip_image010

Save the publish profile to the machine Visual Studio is installed on.

OK, back to the Publish Web process in Visual Studio
Open up Visual Studio, load your completed web application, and select BUILD from the menu and then “Publish Selection”:
clip_image012

Select “Import…” and navigate to the publish file you saved and select “Next >
clip_image014

The Connection page will pull information from the publish file and populate the fields for you. Verify the details and select “Next >
clip_image016

The Settings page provides you an option to deploy as a Release or Debug as well as a place to define a database. Configure to suit your needs and select “Next >
clip_image018

Finally the Preview page provides a view of all the files to be uploaded to your Windows Azure Web Site:
clip_image020

Visual Studio will give you a log of information as it deploys to Windows Azure:
clip_image022

Once the web application is deployed, navigate to the site URL (in my case I used a self-signed certificate for SSO):
clip_image024

Here is my site:
clip_image026

Congratulations, you’ve deployed a web application to Windows Azure!


How to build a M.E.A.N web application

Video explain the following steps:



The best ways to connect to the server using Angular CLI

Everybody who has used  Angular CLI  knows that it is a powerful tool which can take a front-end development job to a completely dif...