EventStore on Azure and Ubuntu - it's a piece of cake! #4

Finally - the last but not least post about setting your own EventStore instance using Ubuntu on Azure. We've already prepared the majority of work needed here, so it shouldn't be difficult to adjust is just a bit to use DNS instead of hardcoded IPs.

Configuration

Currently our configuration looks like this:

/
---
RunProjections: None
ClusterSize: 3
GossipSeed: 10.0.3.6:2112,10.0.3.5:2112
DiscoverViaDns: False
ExtIp: 10.0.3.4
IntIp: 10.0.3.4

Clearly the first change is to get rid of the DiscoverViaDns property. The reason why we're going to remove it is the fact, that it's set to true by default. However, it appears that we need two more properties: ClusterDns and ClusterGossipPort. Additionally we'll remove the GossipSeed property as it also won't work here anymore. Let's get to work!

Network, DNS and Azure

When we created Ubuntu VMs in Azure we're given a single instance of a virtual network. You can think about it as a logical representation of your network in Azure - you manage IPs, DNS and other settings without installing physical devices. It gives you isolation and security - if you want to, you can forbid both inbound and outbound traffic. What we're interested in right now is its DNS capability. Currently you have two options:

  • use a DNS provided by Azure
  • use your own DNS 

Unfortunately using the former won't work here - we have to add records manually, what is not allowed when using Azure DNS. Obtaining and configuring a DNS server is beyond the scope of this post - if you're interested take a look here. The good thing is that it's still possible within Azure and additional tools are required. Once you have your DNS, the configuration should look similar to:

/
---
RunProjections: None
ClusterSize: 3
ExtIp: 10.0.3.4
IntIp: 10.0.3.4
IntTcpPort: 1111
ExtTcpPort: 1112
IntHttpPort: 2113
ExtHttpPort: 2114
ClusterDns: domain.com
ClusterGossipPort: 2113

DNS entries

The tricky thing here is to set correct entries in your DNS server. What you have to do here is to add an A entry pointing to your private IPs inside a network. Note that there's no concerns in doing this - it's a common practice. The one issue here is that it describes a little how your local network looks like - while accessing domain from an Azure network will point to the correct machine, when one tries to access it from an external network, he will be redirected to the private IP being the same as the one used in an entry.

Summary

This is it - we've went through installing, configuring and managing EventStore using Ubuntu and Azure. I strongly encourage you to discover other OSS solution, which could be run using such configuration and play with them, it becomes more and more fun.

Serverless framework with Azure Functions

Recently an update to Azure Functions has been published containing proxies and integration with Serverless framework. In a nutshell it's a tool for building serverless architectures. Don't get the name fool you - in fact there's a server behind the whole functionality and still all principals regarding web development are true. What in reality it gives you is focusing only on the very functionality of your application. There're no pipelines, layers or areas - you're going to ensure that each component follows the single responsibility pattern and can be deployed separately. 

We're going to build a very simple application using Azure Functions and Serverless to present the current capabilities of the integration.

Provisioning you environment

I decided, that the easiest solution here is to obtain a pre-configured Ubuntu VM with installed NodeJS - you can easiliy get it from the marketplace in the portal. Once you have it, connect to it(as usual in my case, from Windows PuTTY seems like the best idea) and we can start. Type in following commands:

sudo npm install -g serverless
serverless install --url https://github.com/azure/boilerplate-azurefunctions --name ServerlessExample

Those two will:

  • install Serverless globally
  • install a new service locally using name ServerlessExample

Once it's finished, you can go to the ServerlessExample directory - you'll see some files which are the core of our application. In fact, this boilerplate gives us all we need to get started as the example is fully functional.

Deploying a function

Before you're able to deploy your function to Azure you have to provide a credentials for deployment. The whole process is pretty well described here, however I attaching it here with my comments because in my case it didn't go as flawlessly as I thought:

\
bitnami@nodejsblog:~$ sudo npm i -g azure-cli
bitnami@nodejsblog:~$ azure login
bitnami@nodejsblog:~$ azure account show
bitnami@nodejsblog:~$ azure login
bitnami@nodejsblog:~$ azure ad app create -n service_name --home-page http://www.my-app.org --identifier-uris https://www.my-app.org/example -p pass
bitnami@nodejsblog:~$ azure ad sp create -a application_id
bitnami@nodejsblog:~$ azure role assignment create --objectId object_id  -o Contributor
bitnami@nodejsblog:~$ export azureSubId='<subscriptionId>'
bitnami@nodejsblog:~$ export azureServicePrincipalTenantId='<tenantId>'
bitnami@nodejsblog:~$ export azureServicePrincipalClientId='<servicePrincipalName>'
bitnami@nodejsblog:~$ export azureServicePrincipalPassword='<password>'

Note that I used azure ad app create command additionally - in my case it was not possible to simply create a service principal using only a name and a password.

You can ensure that you've added environment variables using printenv command. Once you configured your credentials, go to the directory of your service and just run:

/
serverless deploy

You should see following output:

/
Serverless: Packaging service...
Serverless: Logging in to Azure
Serverless: Creating resource group: ServerlessExampleKamz-rg
Serverless: Creating function app: ServerlessExampleKamz
Serverless: Waiting for Kudu endpoint...
Serverless: Parsing Azure Functions Bindings.json...
Serverless: Building binding for function: httpjs event: httpTrigger
Serverless: Packaging function: httpjs
Serverless: Building binding for function: queuejs event: queueTrigger
Serverless: Building binding for function: queuejs event: blob
Serverless: Packaging function: queuejs
Serverless: Syncing Triggers....Response statuscode: 200
Serverless: Running Kudu command del package.json...
Serverless: Running Kudu command npm install --production...
Serverless: Successfully created Function App

Now when you go to the portal, you'll see a new resource group created and function deployed.

In the next post we'll try to do more advanced configuration and consider involving VSTS and incorporating the framework into our build/release pipeline.