Microservices

on

Azure

The good, the bad and the ugly

Before we start

Survey

Who am I?

Piotr Stapp

  • Unique name - just sing a song: "Don't Stapp me know" ;)
  • CEO @ Dotnetomaniak
  • VP @ devWarsztaty
  • ex-Head architect @FinAi
  • "Top secret" @ Allegro (Pay)
  • M.Sc (distction) Oxford Brooks University in Web Tech
  • M.Sc. Warsaw University of Technology in Computer Science
  • And ......

What about microservices experience?

  • mBank - a lot of (micro)services
  • FinAi - 100% microservices on Azure
  • Allegro - again 100% microservies on Azure

The app

Microservices

  • Shiny UI in Angular/React/Vue
  • REST / gRPC
  • MongoDB/Cassandra/SQL?
  • RabbitMQ/Kafka
  • Kubernetes/Hosting

Microservices

  • Shiny UI in Angular/React/Vue
  • REST / gRPC
  • RabbitMQ/Kafka
  • MongoDB/Cassandra/SQL?
  • Hosting/Kubernetes
  • API Gateway!

Survey result

Database

Options (built-in)

  • SQL
    • Azure SQL
    • Azure Database for PostgreSQL

    • Azure Database for MySQL

    • Azure Database for MariaDB

  • NoSQL
    • Azure Cosmos DB
    • Azure Cache for Redis
    • Table storage (simple key value)
  • Self-hosted :)

 

Where is MongoDB or Cassandra?

Azure Cosmos DB

Using

Azure CLI

- Creating is easy :)

- 5-15 minutes :(

- I will cheat a bit




az cosmosdb create \
   --name $COSMOS_DB_NAME \
   --resource-group $group \
   --kind MongoDB

Making it cheap

  • Use Free Tier when possible :)
  • Use shared throughput on database level
  • Think about indexes:
    • default is the strings with hash,  numbers by value
    • up to the third level
  • Apply dynamic scaling - manual or automatic :)
  • It offers 99.999% SLA for both read and write availability
  • Use calculator to plan proper RU before start   https://cosmos.azure.com/capacitycalculator/

Funny error

var query = _dbClient.Where<UserDocument>( _collectionUri,
 d =>d.User.Email.ToLower() == criteria.SearchString);

SELECT * FROM c
WHERE LOWER(c.User.Email) = "{search}" 

------------------------------

var query = _dbClient.Where<UserDocument>( _collectionUri,
 d => d.User.Email.Equals(originalSearchString,
 		StringComparison.OrdinalIgnoreCase)); 

SELECT * FROM c
WHERE STRINGEQUALS(c.User.Email, "{search}", true)

Build our app

Options

  • CI/CD
    • GitHub
    • Azure DevOps
    • Any other :)
  • Fast and semi-CI/CD
    • Azure Container Instances for Docker
  • Manual
    • Your own machine

Container registry

  • Public
    • docker hub
    • ...
  • Private:
    • any
    • Azure Container Registry
    • ...

Create Azure Container Registry

with Azure CLI



az acr create \
  -n $ACR_NAME \
  -g $group -l westeurope \
  --sku Standard \
  --admin-enabled true

Build an App

with Azure CLI



# build data-api
az acr build \
  --registry $ACR_NAME \
  -g $group \
  --file node/data-api/Dockerfile \
  --image smilr/data-api $GIT_URL

# build frontend
az acr build \
  --registry $ACR_NAME \
  -g $group \
  --file node/frontend/Dockerfile \
  --image smilr/frontend $GIT_URL

# get logs
az acr task logs \
  --registry $ACR_NAME \
  -g $group

Hosting simple

Azure Web App

  • .NET, Java, Node.js, PHP, and Python on Windows 
  • .NET Core, Node.js, PHP or Ruby on Linux
  • Docker on Linux

 

More:

https://docs.microsoft.com/en-us/azure/app-service/

App Plan

Something to host apps :)



az appservice plan create \
   -n appPlan \
   -g $group \
   --sku B1 --is-linux

Prepare deployment

To deploy demo app we need:

- Cosmos (Mongo) connection string

- Azure Container Registry  Credentials

export COSMOS_CONN_STR=$(az cosmosdb keys list \
  -n $COSMOS_DB_NAME -g $group \
  --type connection-strings \
  --query 'connectionStrings[0].connectionString' -o tsv)

DOCKER_PASS=$(az acr credential show -n $ACR_NAME -g $group \
                     --query 'passwords[0].value' -o tsv)
DOCKER_USER=$(az acr credential show -n $ACR_NAME -g $group \
                     --query 'username' -o tsv)

Deploy

data-api

with CLI



# Create
az webapp create --plan appPlan \
   -n $APP_DATA -g $group \
   --deployment-container-image-name \
     $ACR_NAME.azurecr.io/smilr/data-api \
   --docker-registry-server-user \
     $DOCKER_USER \
   --docker-registry-server-password \
     $DOCKER_PASS


# Database connection
az webapp config appsettings set \
   -g $group -n $APP_DATA \
   --settings \
     MONGO_CONNSTR=$COSMOS_CONN_STR

# curl
curl $APP_DATA.azurewebsites.net

Deploy frontend

# Create     
az webapp create --plan appPlan -n $APP_FRONT -g $group \
   --deployment-container-image-name \
     $ACR_NAME.azurecr.io/smilr/frontend \
   --docker-registry-server-user $DOCKER_USER \
   --docker-registry-server-password $DOCKER_PASS

# App settings
az webapp config appsettings set -g $group -n $APP_FRONT \
   --settings \
   API_ENDPOINT=https://$APP_DATA.azurewebsites.net/api

# browser
open https://$APP_FRONT.azurewebsites.net

Sum up

  • We can host multiple apps on one app plan
  • App plan shares CPU and RAM across all running instances.
  • Putting it in private VLAN is very expensive - it is called Application Service Environment
  • You don't have to think about security updates and patches.
  • Scaling up&down is rather minutes not seconds.
  • It supports Windows hosting without virtual machine.
 

Hosting advanced

Azure Kubernetes Service

Create

with Azure CLI

 

- 10-15 minutes

- machine size is important



az aks create \
  -g $group -n $AKS_NAME \
  --node-vm-size Standard_DS2_v2 \
  --node-count 2 \
  --generate-ssh-keys
  

# Attach ACR
az aks update \
   -n $AKS_NAME \
   -g $group \
   --attach-acr $ACR_NAME

Get kubectl credentials

- use it as any other Kubernetes cluster



# Get kubectl credentials 
az aks get-credentials \
   -n $AKS_NAME \
   -g $group --admin

Demo app

K8s deploy

- envsubst is a nice util to substitute env variables in text files

- rest is normal k8s deployment



# deploy ingress
k apply -f ingress/ingress.yaml
k apply -f ingress/ingress-ip.yaml

# deploy data api
envsubst < data-api.yaml | \
	kubectl apply -f -

# deploy frontend
envsubst < frontend.yaml | \
	kubectl apply -f -
    
# deploy ingress rules
k apply -f ingress-rules.yaml

AKS - sum up

  • Magic of K8s: write one - use everywhere
  • Windows nodes are supported as GA
  • Good (not great just good) integration with other Azure services
  • Pricing similar to GKE or EKS
  • Logs can be rather expensive, so be careful

Making it secure

Normal way

  • Use DNS Zone
  • Use Let's Encrypt
  • Attach public IP to DNS
  • Install cert-manager
  • ...

Let's hack a bit

  • Use Cloudflare
  • Fill only IP address (can be done with code)

Queue

Options

  • Azure Service Bus
  • Azure Event Hub
  • Azure Event Grid
Service Purpose Type When to use
Event Grid Reactive programming Event distribution (discrete) React to status changes
Event Hubs Big data pipeline Event streaming (series) Telemetry and distributed data streaming
Service Bus High-value enterprise messaging Message Order processing and financial transactions

What? When? Why?

What about RabbitMQ?

AMPQ 1.0 protocol is supported by:

  • Azure Service Bus Messaging
  • Azure Event Hubs

What about Kafka?

  • Azure Event Hubs for Apache Kafka
  • Use Kafka Connect or MirrorMaker to talk to Event Hubs without changing a line of code

The end?

Not yet :)

Poznaj Azure

"Poznaj Azure" next project:

  • Design system for motorway toll
  • All cars in Poland
  • No "funny" device in the car
  • HA for data
  • Money & money & money
  • Only in Polish

 

  • + All "emails" from previous project
 

Q&A

MicroservicesOnAzure - v3

By Piotr Stapp

MicroservicesOnAzure - v3

  • 83