>> In our discussion today, we're going to talk about some of
the options that you have to run Linux on Azure.
We're going to go over the road map of
these talks because this is one of a four-part series.
We'll talk about some best practices
that you can put into place now,
and then we'll demonstrate those in action.
First let's start with your options for running Linux on Azure.
Of course, the number 1 option is
running Linux on a virtual machine.
We can run Linux and Windows virtual machines,
and we have a wide variety of sizes to fit your workload needs.
You can run anywhere from one up to 416 virtual CPUs,
and up to 12 terabytes of RAM.
I would love to have a machine with 12 terabytes of RAM.
You can use these for application servers,
database servers, web servers.
Anything that you would want to run a service on,
these virtual machines can be sized perfectly for those needs.
Another option is App Service.
This is our platform as a service,
this allows you to rapidly scale web and Cloud applications.
It's a managed platform,
so you have access to all of
the different services that Azure provides.
You can deploy anywhere from one to
multiple instances instantly and it will scale to meet your needs.
App Service is perfect when you need to do
rapid deployment that meets critical performance,
security, or compliance requirements,
and high-demand applications.
App Service is the perfect Black Friday application scaler.
Azure Kubernetes Service is
Microsoft's managed Kubernetes instance.
It's highly available and it's a fully managed Kubernetes,
which means that Azure takes care of the control plane
for you and you just bring your compute.
It has end-to-end integration with DevOps and CI/CD,
and it gives you a rapid development cycles
that Kubernetes is known for,
along with the ability to maintain
the enterprise governance you already have.
It allows you to simplify and
standardize your application deployments.
We also have a few other specialized options for running Linux,
including Azure Batch, Azure Container Instances,
Azure VMware Solution, and Azure CycleCloud.
Azure CycleCloud is interesting because it allows you
to create a HPC cluster on Azure's Instance,
who doesn't want their own Beowulf cluster?
I'm ready, sign me up.
Let's talk about the road map of this four-part series.
In session 1 today,
we're going to talk about how to take
virtual machines and run them on Azure with Linux,
we're going to do some setup automation,
and we're going to do some partially automated provisioning,
so we'll get the machines almost ready for production.
We're going to position ourselves for growth,
this is the most important part.
When we start off this project,
we don't want to put ourselves in a place where
we have to throw away the work that we've already done.
In stage 2 we'll be able to scale
up what we've already built with load balancers,
virtual machine scale sets,
and we'll be able to protect
our investment with backups and disaster recovery.
Stage 3 will bring us into containers and will containerize
our applications and orchestrate
their deployments on Azure Kubernetes Service.
Then finally in stage 4,
we'll add security, monitoring, and CI/CD.
In this four-part series we'll grow
from tiny startup all the way up to
a fully grown-up enterprise application
that's ready for anything you throw at it.
Let's talk about the best practices for the stage 1.
I selected a small set of best practices that we can apply
quickly and easily that will
position us for good growth in the future.
The first is using the ephemeral disk for swap storage.
Azure virtual machines come with
an operating system disk and an ephemeral disk.
Ephemeral disk is a temporary disk
that has a small amount of storage on it,
and it's not guaranteed to persist between reboots.
Using that ephemeral disk for your swap space on
Linux allows you to have
better performance because swap is enabled,
and you don't have to use a disk
that you've bought somewhere else.
Ephemeral disk comes automatically and we just need
to set it up to use as our swap partition.
Another best practice is to add
a second data disk for application storage.
The boot disk for operating systems on
Azure VMs is optimized for fast boot times,
but slower storage retrieval.
If we want fast performing storage,
we need to add a data disk that has
better IO throughput and we'll use that for application services.
We also want to add
application security groups and network security groups to
partition our traffic and protect our network
from possible intrusions and keep us secured.
The combination of application security groups with
network security groups allows us to take
like VMs and put them in
groups and then apply security policies to those groups.
We can say that the database application security group
is not allowed to talk to the Internet directly,
and it's only allowed to receive
traffic from the application server.
We also want to be able to restrict
remote access to a limited subset of Internet addresses.
We don't want the whole world to be able to SSH into our servers.
We might want to restrict that to
just your office subnet or even your home IP address.
We're going to use tags so that we tag everything,
and all of our resources will have tags that we
can search and find them easily.
Then finally, we're going to use a declarative tool like
Azure Resource Manager or Terraform to manage our infrastructure.
This will position us for rapid development and
easily changing the scale of our systems in the future.
Let's take a look at a demonstration of these in action.
I've created a Terraform setup here that shows
off some of the recommendations
that you saw in the presentation a moment ago.
I chose Terraform because I hadn't used it previously
and I'm a big fan of declarative infrastructure development.
I wanted to see how Terraform worked with Azure.
I was quite pleased with the results.
We created a Terraform file and a group of additional files
that manifest our infrastructure using this declarative format.
We require the Azure RM Terraform provider.
Then start simply like we would in the portal,
by creating a resource group for everything to live in.
I've put all of the common infrastructure bits
in this main.tf file.
We create a virtual network and then a subnet on
that virtual network and
a common network security group for all of the machines.
Finally, I create a data source that
pulls my own IP address from ipify.org,
and I use that in
the security group so that I restrict SSH access to
these machines to only have
my source IP address from home into these machines.
No other network address can SSH into these machines.
You could of course change this into
a sub-net or do something different.
But this allows me to have
relatively good restrictions on SSH access into these system.
Moving on, we've got three Terraform files,
one for each of the systems that we plan to start.
We've got an app server,
a database server, and a web server.
Then we've got a file called variables.tf.
This stores variables that we're going to use for this run.
Let's look at these individual files.
The app server declares a virtual machine called App VM
in the location that's stored in
our variables inside our resource group.
It then creates a network interface card for it.
We declare the size of Standard DS1 v2,
apply the tags that are in the variables file,
and we apply this custom data section,
which is in a file called app-data.txt.
We'll get back to that in a moment.
For the operating system disk,
we call it app OS disk.
We give it read-write caching and we
set the storage account type to premium LRS.
That gives us much faster read-write access on SSDs.
The source image will be Canonical, Ubuntu Server.
At the latest version,
we'll call it prefix app VM.
We'll get the admin username and password from our settings file.
We'll disable password authentication in
our SSH server so that you have to use an SSH key.
Therefore, we have to define our SSH key in our configuration.
It's going to pull the SSH key from our configuration file.
We add manage disks for storage.
In this case, we're using
100 gigabyte disk at premium LRS storage.
This is because the disks that's attached to
the OS is not optimized for data retrieval and storage.
It's optimized for fast boots.
We want storage on a separate disk from the OS disk.
This also allows us to detach this disk and attach it to
another VM in case there's
a problem with this particular virtual machine.
We attach the disk to the virtual machine using
this Azure VM disk attachment stanza,
and then we create
the network interface that is attached to the virtual machine.
Finally, we create the security group association
from that network to our security group.
Give it a public IP address,
and then attach it to an application security group.
If you remember, I mentioned application security groups
as a way to bring machines together
as a common resource type and
apply network controls to those resources.
If we have an application security group for app servers,
we can apply rules to
that application service without
having any problems when we upgrade,
create more machines, create fewer machines.
That application security group will allow
us to deploy that policy to the set.
Here in this next line,
we use that application security group
and apply it to the network interface,
and finally declare our public IP address.
The database server is roughly the
same with just some different variables.
If you scan through that,
it's almost exactly the same.
We just have different names for the devices.
Then the web server, also similar.
Now I mentioned that we were using this custom data.
This is a way that you can send either a bash script to be
executed or a Cloud-init file
to be executed when the machine is created.
Inside this custom data,
we've base-64 encoding the contents of the file web-data.txt.
Let's take a look at this because this is a Cloud-init file.
This Cloud config has a few stanzas
that tell us that we're going to update the packages.
It's going to run apt update and then apt upgrade.
This is on first boot.
It's going to install Nginx full,
the package Nginx full.
Then here's the interesting part.
This took me a bit to figure out,
but it's really exciting that we can
declare how to set up the disks from this Cloud config.
I've told it to use the temporary disk,
the ephemeral disk that's attached to the virtual machine,
and give it a master boot record partition table
and set 100 percent of it as a Linux swap file.
This 82 is the code for a Linux swap file format.
We're going to set that up as a swap file system.
Then when the machine boots will take
that partition and mount it to swap.
That's really exciting because we don't have to do
manual partitioning after the machine is booted.
The other Cloud configs are
similar except they don't install Nginx.
We've installed Nginx on the web server,
but not on the app server or the database server.
Let's take a look at what this looks like when we run it.
First thing we need to do is type "terraform init".
This initializes Terraform, it creates a.Terraform directory,
downloads the plugins that we've declared in our Terraform app,
and if everything is good,
you see a lot of green.
We'll try Terraform plan.
Now it's asking for our admin password.
If you look at the variables file again,
we have defaults for nearly everything except for the password.
We'll create a password that nobody can break.
It's going to refresh the state.
It's going out and asking Azure,
"Do you have a resource group
with the name that I've specified here?
Do you have a virtual machine
with a name that I've specified here?"
Since Terraform is declarative,
it's asking Azure RM
if we've got these devices already configured.
Since we don't, the output here shows lots of green plus signs
because it's going to add these things to our Azure account.
If we type Terraform apply,
we will enter our password again.
We'll watch as it goes off to Azure and again,
refreshes the state to make sure that these resources
that we've requested don't already exist.
It gives us the final prompt.
Are you sure you want to do this thing?
We say yes, and we watch it take off,
as it goes off and starts to create the bits that we need.
Terraform is smart enough that it knows
the relationships between the stanzas that we declare.
It will create the resource group
before it tries to create a virtual machine,
it will create the disks and the network interfaces first,
and then attach them to the virtual machines.
While all of that runs,
let's go back and look at the variables
file and see what other variables we've declared in here.
We declared a location of eastus2.
I used my initials for the admin username,
and then I created a prefix.
Almost all of the resources in
this Terraform system are going to have a prefix of stage zero.
Then I created a list of tags.
Our tags for this stage are called iteration 1.
Everything in our dashboard
will have a tag of iteration equals 1.
That way we can search for them if we want to delete these later.
Then an sku variable for
the Ubuntu instances that we might want to run.
Then the path to my ssh key.
We're going to take that ssh key
and it automatically gets uploaded to
the servers and allows me to
do passwordless login to those servers.
We can see our virtual machines are still being created.
In previous iterations, it's created the network.
It's created our App Security Group,
our network security group.
All of those pieces are in place,
so the last thing it's going to do is
create these virtual machines,
and then attach the disks to them.
Overall, I really enjoyed the Terraform process.
I'm using Terraform version 0.13.0.
The documentation was really clear on
both Azure documentation website and the Terraform website.
I found lots of good examples on how to
operate with Azure and Terraform.
It seems like a really well-matched group Azure and Terraform.
I haven't used Terraform on any other platform,
but I was really pleased with how well it worked for this demo.
Now our virtual machines are created.
It's taking the last part and
attaching our data disks to the virtual machines.
As they get attached,
those Cloud-init files will be running in the background.
We're all set. We can see that all of our disks had been created,
all of the virtual machines have been created.
The machines have been provisioned with the information
that we requested in our Cloud configs.
We've got quite a bit of automation
taken care of already with very little bit of work.
This sets us up for a really simple modifications in the future,
where we can evolve this into a much more complex platform with
more services and more machines without
having to throw away
the investment we've made in creating this layer.
Now that you've had a chance to see these in action,
my challenge to you is to take
these best practices and apply them to your infrastructure.
If you have more questions,
you can go to Microsoft.com/learn
and see the thousands of tutorials,
documents, and other guides that we have available for you.
[MUSIC].
You can also see the sample GitHub repository
at https://cda.ms/1zB.
My name is Brian Ketelsen,
and I hope that you'll continue this journey with me as we evolve
our architecture into
full automated deployment. Thanks for joining.