Deploy Dockerized .NET 6 on AWS with EC2

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
in this episode we're going to look at deploying a.net 6 web api to a load balance cluster of ec2 instances in aws [Music] hey everyone wes here with productivedev i hope you're doing well i'm super excited about this episode because we're going to do a deep dive into some aws infrastructure we're going to look at how to take a dot net six web api that was built using test driven development and containerized and look at how we can deploy that to a load balance cluster of ec2 instances in the cloud we should be able to watch logs basically alternate left and right here confirming that our load balancer is working so we'll refresh we see the right side the left side and we can see this load balancing round robin style between the two ec2 instances in our target group so in episodes 1 and 2 we built this.net 6 web api using test driven development in episode 2 we dockerized this image and we looked at how we can run our web api using docker and now we're going to look at how we can deploy this image to a number of different virtual machines in aws so conceptually we're going to start with the creation of a vpc so we'll look at how you would create a vpc in aws from there we're going to look at how we can set up subnets in our vpc in different availability zones which is going to increase the availability of our web infrastructure with two availability zones in place we're going to create an application load balancer this application load balancer is going to be very simply configured to deliver traffic in a round-robin fashion to two instances of our containers running.net each in a different availability zone so as we dive in and build this project out we're also going to cover a lot of really interesting topics related to developing for aws and developing for web workloads in the cloud so for instance we're going to talk about some security considerations when we look at creating and configuring various security groups we'll also talk about things like the like a nat gateway which is going to be used to allow services in our private subnets to access the internet while not allowing traffic from the internet to actually reach any of the resources in our private subnet we'll talk about routing tables and how to make sure that our public and private subnets are set up properly either with a nat gateway or an internet gateway we'll also talk about configuring iam roles so that we can basically set permissions properly on the services that need to say pull docker images from ecr so we'll talk about ecr which is the elastic container registry finally at the end of the video i want to make sure that you can tear down any of the resources that you create so i'll show you how to basically tear down everything that we work on in this video just to make sure that you're not leaving any resources provisioned and that you may be paying for beyond the scope of what you'd like to learn in this video so i'm super excited about this video i hope you learned something if you run into any issues be sure to leave comments or questions below also if you'd like to see how we actually built this.net web api from scratch then i'd recommend checking out episode one if you need to know how to dockerize it check out episode two and otherwise if you'd just like access to all the source code patrons of the channel via patreon get access to all of the source code that's created on productive dev if you do decide to support the channel via patreon i'm incredibly grateful for your support and in any case whether or not you're a patreon or not i do really appreciate your viewership and i hope that you're able to learn something from this and other videos so thanks for watching let's get started creating our new vpc on aws okay so let's get started setting up a vpc to host our web infrastructure so before we do that something that i'd like to do is to set up an elastic ip address we're going to use this elastic ip address to associate it with a nat gateway and so we'll talk about the nat gateway in a little bit here but one thing to note is that the nat gateway is going to require inelastic ip so we can set that up by visiting ec2 and if you don't see that on your dashboard you can search for ec2 in the search bar and we can visit the dashboard now we can head over to elastic ips here if you see it in resources otherwise if you scroll down on the left side under network and security you can also see elastic ips here so we're going to allocate an elastic ip address one thing to note here is that ip addresses are a scarce resource so be sure to release this address if you're not using it for anything for one thing you'll be charged for not using it and for another thing it's it's a good habit just to go ahead and release that back into the pool of available addresses so that you're not sort of hanging on to ip addresses that you're not using okay so we're going to leave everything the same here you can see this is going to pull from amazon's pool of ipv4 addresses and we're just going to click allocate so within a few seconds aws is going to allocate a public ip address for us so this elastic ip address is static meaning that it's not going to change and so this is going to be really useful for us when we're setting up any number of different resources we might put in a public subnet so something that's going to be accessible from the public internet in our case that's going to be a nat gateway and so we'll look at that shortly i'm going to go ahead and name this net gateway demo and we'll save this and now we're ready to head over to the vpc dashboard so for that you can type vpc and we'll head here and what you'll see here is a number of different resources that we can manage related to vpcs for now we just need to focus on creating a new vpc for our web infrastructure and a really convenient tool that aws has for us to create a new vpc is this vpc wizard so we'll select launch vpc wizard and now we're going to select vpc with public and private subnets so you can see from the diagram here basically the idea is that we're going to create a vpc which you can think of as a sort of virtual data center it's a virtual private cloud so it's sort of a small section of amazon's cloud that you're going to use to provision your own resources and to network them and so in terms of networking it's going to create a public subnet for us which will contain a small number of resources that we need to have public facing to the internet and so this includes things like our load balancers and a nat gateway in this case and then the private subnet contains usually the bulk of our infrastructure things like our web servers our application servers and things like database servers so all of these are basically shielded from the public internet they're not publicly addressable and they won't have public ip addresses associated with them they will however be addressable within the vpc via private ip addresses which is what we'll set up shortly here when we look at subnets so the purpose of a nat gateway is to provide outbound traffic from our from resources in our private subnet to the internet but it prevents us from being able to have those resources connect back directly to anything in our private subnet so when we have services like web applications and database applications and things like this in the private subnet those resources will be able to reach out and access resources on the internet using the nat gateway so those http requests will be routed through the net gateway out to the world but it's sort of one-way traffic we have no way to for the broader internet rather to make a connection back to resources in the private subnet so i hope that makes sense we're going to click select now and now we're brought to a screen where we're going to set up our public and private subnets first of all we'll give our vpc a name here we'll call this dotnet apps demo and now we're going to set up the range of ip addresses for our private and public subnet so you can think of a subnet as being defined by a range of ip addresses and when we're talking about ranges of ip addresses one way to represent those ranges is using is using a cider block notation so cider block notation basically consists of two parts we have a prefix which is an ip address here so you can see ipv4 address in this case and then a forward slash and then a number and this number is called the prefix length and so basically the way you can think of it is the higher the number here at a very high level the higher the number the smaller the range of ip addresses starting at the prefix address and the lower the number the greater the number of addresses basically this just helps define a a mask over which there's a range of matching numbers so for instance ip address 10.0.0 gives us technically 256 ip addresses now you'll see 251 ip addresses here to make this a little bit confusing aws actually reserves five addresses from any subnet for its own purposes and this includes for things like reserving the network broadcast address which is at in this case 10.0.0.255. the network address which is 10.0.0.0 and a few other addresses that it uses for its own internal purposes so 256 minus those five addresses leaves us with 251 available iep addresses defined by this cider block and if you're interested in seeing what that range is i won't get deep into the way that the prefix length is calculated but we can see if we have 10.0.0.0 forward slash 24 rather prefix length of 24 here we can see this gives us the 256 addresses between 1000 and 100 255. if we were to make this number higher say 32 this basically means that we have to match exactly the prefix all bits of the prefix and so we have a start and end address of exactly the same number and so this is defined as one ip address if we were to go lower say 16 we get a much broader range of ip addresses starting at 10 000 and ending at 10 0 255 255 so that's the basic concept so we're going to get 256 minus 5 so 251 ip addresses for our public subnet and we're going to set this in availability zone u.s east 1a in my case i'm going to call this public subnet 1 and for the private subnet we now need to define a range of ip addresses that doesn't overlap with our public subnet and so we'll just go to 10.0.1.0 forward slash 24 and you'll see that that effectively takes us from 10.0.1.0 to 10.0.1.250 so we'll use this for our private subnet and again us east 1a we'll call this private subnet one and now we need to tell aws when it creates our vpc for us here what elastic ip address it would like to or we would like to use rather for our nat gateway so we're going to select the ip address that we just allocated again the nat gateway allows resources in our private subnet to make contact to make requests to the public internet and it allows that one-way outbound traffic okay we're going to go ahead and create the vpc now this should take about three minutes and so i'm going to pause the video here and once it's done we'll pick things back up okay so you can see our vpc was successfully created and we can take a look at it if we just visit the your vpcs link we can see we have in my case i have two vpcs this is the default vpc created with this particular aws account and then we have a net apps demo which was the vpc that we just created and we can select the vpc id to get more details about this particular vpc now when the vpc wizard ran we created several new subnets we created a private subnet in a public subnet and we're going to set up a load balancer and in order to basically increase the availability and resiliency of our infrastructure we'd like that load balancer to use at least two different availability zones and so our private and public subnet here are in the us east 1a a z and so we'd like to set up a new private and a new public subnet so that we have a pair of public and private subnets each in a different availability zone and this is actually pretty simple to do so we can do that by selecting subnets from the left menu here and then we're going to select create subnet so here we need to make sure that we select our new vpc which in my case is this.net apps demo and let's call our first one private subnet two we're going to choose a different availability zone than the one we choose chose for our first subnets when we ran the wizard so i'm going to select use 1b here and now we need to select yet another range of ip addresses using cider block notation that don't overlap with either of our other subnets so here i'm going to do 10.0.2.0 forward slash 24. so this is a new range previously we've used 10.0.0 and 10.0.1 and now we're using 10.0.2.0 forward slash 24. and we'll now add a subnet again this time for our second public subnet so we're going to call this public and again i'm going to use use 1b here and we're going to put this in a new range 10.0.3.0 and we'll go ahead and create these two subnets now by default these are going to be private subnets associated with that nat gateway in terms of reaching the internet so we need to update our routing table for our public subnet and so if we click the subnet id for our new public subnet and we scroll down to the route table we'll see the destination route the destination for the route zero zero zero forward slash zero which represents all ipv4 addresses the target is the nat gateway we need to change this to be our internet gateway which was created for us when we created our vpc and this is going to allow communication with the greater internet so let's go ahead and change the route table well we're in a we're visiting the nat gateway now so we'll go back let's go ahead and once again go to the route table and we'll edit the route table association here we're going to select the route table that contains our internet gateway target where the destination route is all ipv4 addresses so we're doing this for our public subnet our second public subnet almost fave okay and so now if we head back to our subnets and i'm going to order this by vpc we can see the four subnets that we've created the first two were created with the wizard so public and private subnet one and public and private subnet 2 were created just now when we ran create subnet and we can check to make sure that the routing looks correct what we'll do is for public subnet 1 we'll click the subnet id and scroll down look at the route table and we should see our internet gateways we should see igw as the target for the destination zero zero zero forward slash zero which is all ipv4 addresses we'll go back we'll take a look at public subnet 2. in the route table this is the one that we just updated also pointed to the internet gateway and then our private subnet should both be using the nat gateway so we'll come down to the route table for this one you can see the nat as the target and now we'll go to private subnet to scroll down the route table again we see the nat so again this is allowing outbound traffic from our private subnets here so basically resources in those private subnets should be able to reach out to the internet by route by having those requests routed through the net okay so with that we've now set up basically two pairs of public and private subnets and we can go ahead and create a load balancer that we'll use to balance traffic across application instances that we'll be running so for this let's head over to ec2 and we'll scroll down to load balancers and we're going to create an application load balancer so we'll select create load balancer and we're going to select application load balancer this is a really fantastic very advanced load balancing resource this lets us basically route http and https traffic and as you'll see here in a moment we can actually have it route to ip addresses or specific ec2 instances or even lambda functions let's call this the net apps alb demo it'll be internet facing ipv4 and we need to select our new vpc and now that we have mappings in two availability zones we should see those here and you can see that aws does recommend selecting at least two azs this is for increased availability of our application and resiliency so we'll select us east 1a and if private subnet is selected you'll see we get a warning that we need to have a route to an internet gateway because our load balancer is of course going to be internet facing so we'll select our public subnet so that looks good and us east 1b our public subnet which should now also have a route to our internet gateway we're going to leave the default security group we'll talk about security groups more in a moment and for now we're going to listen on port 80. so it is best practice here to set up an ssl cert that we would put on our load balancer for handling https traffic on port 443 but for now we'll stick with port 80 to get started and basically what's going to happen is we are going to listen on port 80 and that traffic is going to basically be balanced against the target group and so we don't have any target groups created yet but if we select the create target group link here this will open up a new tab for us and as you can see we can create a target group for instances of ec2 instances ip addresses or even lambda functions or other application load balancers but we'll call our target group here dot net apps tg for netapp's target group and we'll call this demo again and we're going to set this to http port 5000 where our net apps will be listening and again the net apps demo is selected we'll use protocol http one and for health checks if you saw episode two of productive dev when we were dockerizing our net apps we added a health check at forward slash health for any of our net services and so we're going to use that health check here as well we can see advanced health check settings here as well we're not going to worry about that for now but we do have a simple health check exposed at forward slash health so we'll use that and i'll select next oops and for target group name here we need this to actually not have spaces in it so we fix that and next we don't have any instances available to register yet but we can register them later we'll just go ahead and create our target group and you can see i have an old demo here we're going to delete the old target group just to avoid any confusion you likely won't have one in yours if you haven't set one up yet you can see we don't have a load balancer associated with this new target group so let's go ahead and associate one now we'll head back into the load balancers tab if we don't see it here just hit the refresh button and now we see our new target group and we should be good to go so basically the load balancer is going to be listening on port 80 and it's going to be forwarding that to traffic in it's going to be forwarding that traffic rather to our applications that are running in this target group and listening themselves on port 5000 okay we won't worry about add-on services for now and you can take a look at the summary we'll go ahead and create our load balancer and our load balancer name also should not have spaces in it so apologies for that okay let's go ahead and see if this works now we'll create the load balancer okay so this is now getting created note that it will take a few minutes here for it to be fully set up and routing traffic we can go ahead and view it and you can see that it's in a provisioning state so now what we should do is basically provision some ec2 instances that we can add to the target group we're also going to set up a small jump server that will allow us to essentially ssh into our vpc and then we're going to forward our ssh connection into the private subnet where our application servers are running so this way we can actually get a shell on our private servers which don't have public ip addresses via this drum server so i'll show you how to do that now we'll head back into the ec2 dashboard and so now we're going to head over into instances and we're going to launch an instance for our jump server now for this i'm just going to use amazon linux so we're going to select this and i'm going to use the free tier eligible t2 micro instance and we can configure details here we need to make sure that we put this in the correct vpc so i'm going to put this in our new vpc and for this jump server i'm going to put this in our public subnet and we're going to auto assign a public ip for our jump server our jump server's sole purpose is just to enable a developer to ssh into our vpc and to access any of the various resources that might be addressable via internal private ips in the vpc from the jump server okay so we will leave the other settings to be as they are and we'll click add storage we'll leave this at eight gigs we can add tags if we like we'll configure a security group now so with a security group you can kind of think of this as a firewall and essentially it allows us to configure the various protocols and port ranges and source ip addresses that we want to allow to any particular resource and so we really want to lock down our resources as much as possible for one thing we're using ssh for security but if our security group allows anyone with an ssh key to connect which is what we have set up here then that means if for some reason your ssh key is somehow compromised then anyone from any ip address around the world would technically be able to ssh into your jump server and so one of the ways that we can kind of harden this down is by allowing only specific ip addresses to connect over ssh so for this if you click source you can just select my ip address and you can see what you'll have here is your ip address represented as a cider block so we have forward slash 32 meaning the the single ip address that is listed as the prefix you can of course specify a range of ip addresses i'm going to call this wes ssh so we're allowing connection from my ip address on port 22 which is the default ssh port and there are many different protocols and types of protocols that we can allow here okay so for now we're going to basically lock this down if we want to add other rules where we say add other developers or any other rules that we might want for the jump server we can add those as well but for now we're just going to lock it down to ssh from my computer so we'll review and launch and so we can see we're spinning up in amazon linux 2 ami on a t2 micro instance and we have a pretty secure security group here allowing ssh only as inbound from my ip address so we'll go ahead and launch it's going to ask you to create or select an existing ssh key pair so if you don't have one be sure to create one and this is going to be required for us to actually connect from our development machine into the jump server so that's really important we need to make sure we acknowledge that we have access to this particular key and we'll launch our instance okay so we'll see that our instances are now launching and we can go view instances or we can just click on the instance id and we can see that it's pending so within just a few seconds this will reach a running state while that's happening we can rename it we can call this dotnet demo or net jump demo and you can see we have an instant state of running so if we want to connect to this instance we can select connect here so you can see here we have an example ssh command to connect to this instance on its public address with the key that was set up so we need to make sure we again have access to that private key and of course you're going to want to make sure that you have an ssh client installed on your development machine okay we'll worry about connecting to this a bit later let's go ahead and finish setting up instances that we want to load balance against as well so for this i'm going to go ahead and create one more instance we're going to launch an instance we're going to place this one in our private subnet and it's what's going to be running our net container so we'll select an amazon linux again again we'll use a t2 micro and here we're going to put this in our new vpc and we're going to leave this in a private subnet so i'm going to put this in private subnet one and we're going to not auto assign a public ip this will not be addressable from the internet we'll add storage we can leave this at eight gigs for now we can add tags if we like now here we want to be able to ssh into this particular server only from the jump server and so one way we can do that is by moving this into a security group okay so this security group is named launch wizard1 we'll go ahead and copy the name we probably should have named this something more descriptive we'll come back and basically what we're looking here for is this launch wizard1 security group so we'll select this and this is ssh from uh ssa west's hsg so we're saying anything from this security group can ssh into our new into our new web app server we'll call this one web apps sg and we'll say ssh from jump to web app servers and we'll review and launch go ahead and launch our new instance and i'm going to use the same key okay and i'll click on the id for this and we'll rename this dot net demo app one okay and just in a moment here this will also be running so now what we need to do is we need to get a shell on this particular instance and we'll look at how to do that via the jump server and we want to install docker on this app server so that we can actually run the docker container the dockerized version of the net api we're running so now that it's running i'll show you how you can get set up so you can forward your connection to this private server okay so again as usual for these productive dev videos where i'm working on windows in particular i'll be using windows terminal and as a terminal emulator i'll be using git bash and i have an ssh client installed and so if you don't have an ssh config file i'd recommend creating one you can find this or rather you should place this at your home directory and then dot ssh and then config and feel free to create this file and directory and edit this in your preferred text editor i'm going to just use vim here and you can see what i've set up is an initial set of hosts this is going to provide us with a really convenient way to ssh into first of all our jump server and our any application servers that we access via the jump server so this host entry for demo jump will allow us to basically run the command ssh space demo underscore jump and connect to the particular host that's defined in this config file so this is an old host file so what i'm going to do is get the new ip address for the jump server and we're going to come back to our ec2 dashboard i'm going to go to the dashboard and look at running instances and i'm going to get the public ip address for our dot net jump demo so i can see that here i'm going to go ahead and copy this and we'll come back to our file here and we'll paste in that public ip address okay the user will be ec2 user for these amazon instances if you're running an ubuntu server the user is typically ubuntu you can check that if we open up the connect dialog again you can see that in our case it's ec2 user connecting over ssh here so just be sure to use the correct user and then we have two host entries demo app 1 and demo app 2. for now we've set up a single app server so we want to get the internal ip address for this again it doesn't even have a public ip address so let's grab that we'll head back into ec2 and look at our running instances and we'll look at net demo app one again no public ip address but we do have a private ip address at 10.0.1.121 so we'll go ahead and set that as our hostname and again ec2user is the user with the same private key on port 22 which is the default ssh port and now we have this new directive called proxy command which is basically going to ssh into this particular server via the jump server so via demo jump here and so by running the command ssh space demo app one basically our config file is helping us proxy that ssh connection directly to our private network and we don't need to store our identity file we don't need to store our private ssh key anywhere in the public subnet this just remains directly on our development box later when we set up our second app in just a few minutes we will change the hostname here to match the the correct hostname for the second server okay so let's go ahead and save this so save the file and we can test that it works we can first of all run ssh demo jump and you can see that for the first time we connect needs to make sure that we want to continue and this is going to add this to our list of known hosts you can see now that we're connected we see the ec2 amazon linux 2 ami and we can see where we are we're in home ec2 user okay so that's good we can make sure that we have access to reach out to the public internet at least from the jump server so if we ping aws.com we can see things look good we can ping google.com and things look good okay so let's go ahead and disconnect with control d and if you recall back in our config file we had a host entry for demo app 1. let's try to ssh into demo app 1. we're going to get the same question here whether or not we want to add this to known hosts and we'll say yes and so now we're actually connected to our app instance which is not is not addressable from the public internet but since we jumped into the jump server which is in our public subnet and then ssh from there into the app server here in the private subnet on its private ip okay so we'll disconnect here as well and now our next step is basically to install docker on this app server so in fact we didn't need to disconnect all ssh back in here and we'll run the various commands that we need to run to install docker so for this we're going to use yum and we'll sudo yum update we're going to sudo yum search docker to search for the docker package and we'll run sudo yum install docker if everything looks good and we'll say yes okay so now that that's complete let's go ahead and enable the service at boot time so for this we can say pseudosystem ctl enable docker dot service and we'll sudo system ctl start docker dot service and oops need to fix the typo here system ctl and now we can check to make sure it's running with sudo systemctl status docker.service and we can see that docker is indeed running so now if we want to be able to run docker without using sudo we can add our current user to the docker group so we can do that first of all making sure we have the docker group which it should already exist after the install now we can use our mod dash a capital g docker our current user and now we can control d to log out and ssh back in and if we run docker ps this should now be possible to run without sudo okay if we want to verify that docker can run at all we can do docker run hello world and it's going to pull hello world and we can see that docker is running properly okay so essentially our app server is ready to run a docker image and so it's ready to run our net api now we need to figure out a way to basically get the docker image onto this particular server and one way we can do that is by pushing our built docker image that we created in episode 2 we can push that to ecr and then we can create a user that has permissions to pull images from ecr directly onto this particular server and then run that image so let's look at how to do that now so i'm going to go ahead and exit with control d and you recall that in this directory we have a docker file and so and we can clearly build this docker file that's fine what we want to do is actually push this to ecr which is amazon's elastic container registry sort of you can sort of think of it as a way to create a private docker hub for any of the applications that you might want to manage so we'll head back into the console and we're going to search for container registry or ecr and i'm going to start this and we'll head into the container registry now you can see that i have an old image here i'm going to go ahead and delete this one and we're going to create a new repository from scratch i'm going to call this dot net users api and we'll make sure that it's private and we'll keep all the other settings the same for now we'll go ahead and create the repository and so if we click our repository we can see we have no images associated with it yet we can see the push commands here so here we can see that there's a number of steps that we follow if we're on windows and we have what looks like some powershell commands here since we're running git bash we can follow along with the mac os or linux commands basically we're going to get an auth token which is going to authenticate our docker client to our registry this is going to allow us to build our local image and push it to our ecr repository so for this we want to make sure that we have an aws user set up and so what we're going to do is head over to iam and we're going to set up a user specifically for this purpose so we're going to go to iam i started this as well and you can see i have a user group already created with ecr power user but we'll create this from scratch just to see how things work we'll create a new group and i'm going to call this netdemo devs or in my case i'll just call it productivedivs and we can add users to a group if we have one let's imagine we don't have any users yet so i'm just going to create the group itself and the first permission we're going to give them here is ecr we'll search for this don't see it here so let's look for container and if we scroll down we see amazon ec2 container registry power user this is a set of permissions that allows it looks like basically read and upload access and putting an image but it doesn't actually allow us full admin control or full access which we could see contain some additional or rather all all privileges here we're just going to use the ec2 container registry power user permissions okay so we'll go ahead and create the group so now we see we have productive devs if we click into productive devs the group we don't have any users in the group as far as permissions go though we have our ec2 container registry which is ecr power users so we can have full access to repositories but it doesn't allow for deletion or policy creation so this looks like what we want we want to create a new user now so let's go ahead and select add users actually if we head over to users on the left side we can visit it here and we can click add users as well and i'm going to call mine wes forward slash dev and we want to set up programmatic access okay so this is going to give us an aws access key and secret access key we go to permissions we're going to add it to our productive devs group we're going to go to tags we're going to skip tags for now and we're just going to create this new user so when we do this as mentioned we're going to get an access key and a secret access key so we definitely want to keep our secret access key secret and we generally want to operate on the principle of least privilege meaning that we don't want to give any more privilege than is absolutely necessary for a particular user to do their job that is necessary and so right now we're just operating under the assumption that all this user really needs to do at the moment is the ability to push and pull images from ecr and so that's why they belong to the dev group whose only current permissions are to be able to push and pull images from ecr but anyone with the secret access key and the access key can basically act as this user on their behalf and so we definitely want to keep the secret access key secret so let's set this user up on our local machine so i'm back on the local machine for now we're not connected to any of our ec2 instances and i'm going to run the command aws configure we're going to call this profile wes forward slash dev so it's going to ask us for an aws access key let's head back into our screen here we're going to copy this and there we go it's now going to ask us for our secret access key so we'll copy this and paste this default region name i'm going to set to usc 1 and default output format i'm going to set the json okay so what we have now is a profile called westdev that is utilizing the access key and secret access key that we just created for our new user we can check out where this data is now stored locally if we head to aws credentials so this is in our relative to our user directory in other words our home directory here dot aws forward slash credentials we can see that we have a new entry here westdev with the access key and secret access keys set up okay so that's basically all we need and now we're ready to push our image to ecr so first of all let's make sure the latest version of our docker image is built so we'll run docker build and we will use our productive dev forward slash cloud customers latest in our project directory where our docker file is okay now we're going to run docker tag and we're going to say productivedev so the name of our image cloud customers latest and now we need to get our repository that we just created so for this we'll head back into the console and we'll go back to ecr and you can view in the push commands here basically we want to grab this string here so we'll copy this this is going to point to our repository name and now we need to log into ecr so for this we're going to use our new profile so we're going to say aws ecr get login password region us east1 profile and we're going to say westdev or whatever you named your profile we're going to pipe that to docker login with username aws and password standard in and then this is going to be the url to our repository we can come back and get that we can view push commands to actually get that again the only difference between their login and ours is that we're specifying a profile so we'll go ahead and grab the password here rather the rather the url this is not the password okay and we got login succeeded which means things are set up properly and now we can push so here we're going to docker push we're going to copy the url again oops we need to put the suffix here which again we can get from here so dot net users api latest is what we named the repository okay let's go ahead and try to push and so now we're successfully pushing our image up to aws and specifically amazon ecr okay so now that our image has been pushed if we visit the ecr console we should be able to actually see it so if we just refresh here we can see that our image tagged latest has just been pushed up to our repository okay so now that we have the image pushed to ecr we need to be able to pull this from ecr onto any of our app servers and you might be tempted here to use the same aws profile that you used for your developer user but i would highly recommend not doing that in creating a new im role or user which just has access to pull images from ecr and is not associated in any way with your developer group after all your developer group may expand in its functionalities over time and basically get more privilege and privilege that's not required at all for an app server just to pull a simple ecr image so it may seem like an extra step here but i think it's probably best practice for us to again operate on the principle of least privilege and to think ahead a little bit and so for that reason we're going to create another iam user here so we'll come into users and we're going to call this ecr agent actually we need to add the user sorry not search for it it's going to be called ecr agent and again access key programmatic access permissions we aren't going to add the user to a group but we're going to attach an existing policy directly and we're going to look for container registry again and we're going to give this ecr agent read only access to the ecr and we'll say tags review basically a read-only ecr agent we're going to go ahead and create this user okay so leave this open and we're going to need to set up a new profile this time on our app server with this access key and secret access key id okay so we'll head back here we're going to ssh into demo app one and we're going to say aws configure profile ecr agent and so we're going to use the access key that we just created copy this and again our secret access key default region name will say usc 1 default output format say json and so now again we can actually just take a look at our aws credentials and we can see that we have an ecr agent user here so this means that we should be able to log into ecr and pull our image so let's take a look at how we can do that we'll head back into our ecr console so back in our ecr console if we want to pull this image again the login is the same here so we would actually just use this command except we would specify a profile so let's go ahead and do that i'm going to go back here and we can see that the login has succeeded and for additional security we could configure a credential helper so that our password is not installed and encrypted on this private server and basically we can just run the docker pull command now and we just need to pull from the repository url so we'll copy this paste here and we'll pull latest so you can see we've pulled latest and if we run docker image ls dash a we can see now we have our hello world instance that we pulled but as well we have our new.net users api image that we pulled also okay so let's go ahead and docker run this image just to make sure things are working and we can see that our.net application actually starts up okay so something that i want to do here is we can close and with control c here and then if we docker ps we can see that the container is stopped as well what we want to do now is run a command that basically exposes our api on port 5000 and our load balancer is going to basically send traffic to this instance when we place it in a target group and we can actually just duplicate you know images that we have here of this particular ec2 instance and place those as instances in our cluster in the target group as well so this is why i'm setting up everything on a single ec2 instance to get started and then we can basically create replicas of those using the same image on new ec2 instances all right so let's go ahead and run our image except we're going to run it with some additional flags here so i'm going to dash rm to clean things up and then we're gonna expose port 5000 map that to port 5000 same for 5001. we're going to set asp asp.net core http port to https plus 5001. again we cover this in episode two but we're doing the same here asp.net core urls it's equal to http plus 5000 and then our image so let's go ahead and try to run this okay so we can see we're listening on port 5000 now let's see if we can add this ec2 instance to a target group and actually hit our application from the public internet so let's come back and we're going to go back to ec2 and we're going to go visit our load balancers so if we scroll down and click load balancers let's go ahead and take a look at the listeners and we should see a target group here so let's go ahead and view this forwarding to our target group so we'll visit our target group and let's register a target so we're going to register our net demo app one and include as pending below okay so this is going to forward traffic to port 5000 on our demo app which again is running in our private subnet and it's pending we're going to click register pending targets and in a moment we'll see whether it's healthy or unhealthy should be healthy because we have a forward slash health health check endpoint and it's interesting the health checks can be configured so we have a timeout of 5 seconds with an interval of 30 seconds and the healthy threshold is on 5 consecutive health check successes and if we get two consecutive health check failures we have an unhealthy target and you can see that right now we are getting an unhealthy target so one thing we can think about is why might a request be timing out and if you think about it we have set up our instance without actually altering or creating a security group that allows traffic on the port that we're trying to hit here so let's adjust that we'll leave this open and i'm going to head back into the ec2 dashboard we're going to go to our instances and we're going to look at netmo demo app1 and if we scroll down to security we can see we have our web apps security group which is allowing inbound traffic on port 22 from a security group that we set up for our developers let's now also allow inbound traffic on port 5000 and 5001 so what i'm going to do is edit this inbound rules we're going to add a rule for custom tcp 5000 to 5001 from anywhere and we'll call this netweb api ports and we'll save those okay so now we allow inbound traffic via the security group that's attached to our web application so we'll head back to our target groups and we'll refresh and after a few seconds we see that our target is now healthy so that's good news that means that it looks like things are probably going to work well for us what we're going to do now is to create an ami of the net demo app one ec2 instance that we created earlier and we're going to add a second ec2 instance that's essentially the same image running on a separate vm to our target group so what we'll do here is i'm going to go to actions image and templates and we're going to create an image and we'll call this image docker web app demo and we'll keep all else the same here and we'll go ahead and create the image so now if we visit amis we can see that the status is pending for creating this image once that's done we're going to spin up a new ec2 instance using our custom ami here which already has docker installed and in our case also has our net docker image pulled okay so the last thing that i'd like to do here is to ensure that our load balancer can not only communicate with the registered targets that we have on port 5000 but we need to make sure that traffic can go both ways there so what i'm going to do is create a security group for our elastic load balancer so i'm going to call this elb demo sg and we're going to say allow traffic to and from target groups or tg we'll make sure that the vpc is indeed our new vpc and for inbound rules what we're going to allow here is http traffic from anywhere and we're also going to allow custom tcp traffic from five thousand five thousand one from anywhere and then we're gonna go ahead and create this security group okay with this created let's head back into our ec2 dashboard we're going to go down to our load balancer and here we're going to edit the security group for our load balancer so we'll click actions edit security groups and we're going to remove the default vpc security group and select allow traffic to and from our target groups with that saved we can go ahead and copy our dns name and let's visit this in a tab so we'll do forward slash users and we can see that we get our users now load balanced to our single ec2 instance so though technically we have a load balancer set up what we need to do is to add another ec2 instance to our target group and we can see how the load balancer will balance traffic against both of those instances so to do that let's head back to our ec2 management console we can go to our ec2 dashboard and click on our running instances now you could go through the steps of basically setting up docker on a new ec2 instance just like this one and then ssh into that using an update to our ssh config and we will update our ssh config another thing we could do is we could create an ami of this ec2 instance which is just an image so that's what i've done here if you'd like to create an ami what you can do is go down to amis and you can see the one that i've created called docker web app demo so what we'll do is we'll launch an instance from this image we're going to run this again on a t2 micro instance we're going to make sure that it's in our new vpc and we'll put this in the second private subnet again of course we won't be auto assigning a public ip to this we'll keep storage at eight gigs i won't worry about tags and for security group we're going to select an existing security group which will be our web apps sg that we set up previously this allows ssh from the dev computer as well as opening ports 5000 to 5001 from anywhere and we'll review and launch so let's go ahead and launch we'll use the same keys and acknowledge and our instances are now launching so if we head back we can see that this is now an appendix state if we clear filters let me go ahead and name this one dot net demo app2 and while this is pending let's update our ssh config so that we can ssh into this instance we need to grab its private ip address and then head back to our terminal if your terminal happens to be running a connection to your application server you can control c this is actually going to stop the docker image from running that's fine for now we'll ctrl d to exit so nothing is actually running now on the server i'm going to open up my ssh config file and put in the correct hostname here for demo app 2. so now we have demo app 1 and demo app 2. we can see there in our two different private subnets we've got 10.0.1 and 10.0.2 and we can still proxy into either of those from the jump server which is in our public subnet so we'll go ahead and exit here and we'll ssh into demo app 2. again it's going to ask us if we want to add this as an entry to our known hosts and you can see as an image here that we created from our first app server that we have docker installed in fact if we list images that we have we even have the users api set up so what i'm going to do is i'm going to start our users api on the second app instance and i'm going to start it on the first app instance just so we can see them both in separate terminals running so what we'll do is so what we're going to do is we're going to use our big docker run command and this may be something that you would typically want to write a script for so you wouldn't have to type this out each time i'm going to also pass dash d this is going to run it in detached mode and so you can see we get the container hash back and so if we just docker ps here what i want to do is log our containerize this container id so that we can run docker logs dash f to follow the logs and 8 3d which is just the first three characters so this is running i'm going to open a second terminal now and ssh into our first app instance and i'll make this smaller so here we'll ssh into demo app one we'll run our docker run command again with dash d this kit this time a little docker ps to see that it's running and i can see that the docker id is 891 so i'm going to make this smaller and we'll say docker logs dash f 891 and we can see that our container is now running on our first app instance all right so now here's the fun part we can actually see our load balancer balance traffic against both of our app instances we need to add our second host to the target group so let's go ahead and do that now so we'll come into our load balancers we see under our listeners here we can go ahead and look at our target group and right now our target group just has a single registered target let's go ahead and register our second target and we'll select this one included as pending below and we can see we have an unhealthy health status let's check on that in a moment here but we'll register any pending targets we can see we're getting health checks failed again so we can make sure that things are working properly here in a moment let's see whether or not the health checks on our second instance are working okay it looks like our second instance is healthy for some reason our first instance is not yet healthy let's refresh again okay and after a few refreshes it's healthy sometimes it'll be unhealthy after or for a little while until it gets five consecutive positive health checks and since our application was stopped we were seeing that it was unhealthy for a time okay so if we head back into the load balancer section and again we grab our dns name i'm going to try to open this up to the left here and let's see what happens when we hit our endpoint we should be able to watch logs basically alternate left and right here confirming that our load balancer is working so we'll refresh we see the right side the left side and we can see this load balancing round robin style between the two ec2 instances in our target group so we can also configure other types of more complex routing strategies like weighting percentage of traffic to one instance or the other but this just shows you a very simple sort of crude example of running our.net api on two separate vms and setting up an elastic load balancer to balance http traffic against those two servers okay so now i'd like to just demo how you might tear down the things that we provisioned here so that you're not paying for things that you're not using if you're just doing this for a tutorial so we'll head back into our console and first thing that we're going to do is we're going to terminate any of our running instances so i'm going to go ahead and shut all these down we'll go to instance state terminate instance terminate all of them now keep in mind that our ami still exists so if you no longer need the ami you can also just delete this here we'll de-register now we can head back to the ec2 dashboard and we can go to our load balancers and what we can do is delete our load balancer so if we go actions delete we will delete our load balancer next we'll head down and we'll actually head over to our vpc section we go to our nat gateway which we can click on here on the left or directly here and what we'll do is we'll delete this nat gateway now that our nat gateway is deleting in a few moments we should be able to release this elastic ip that we created this will be grayed out until the nat gateway is completely deleted okay so now after just a few minutes we can release this elastic ip address so this will go back into amazon's pool of ip addresses and if we now visit our vpc dashboard take a look at our vpcs be sure to select the new vpc that you created and not your default vpc we definitely only want to get rid of the new vpc that we created and we're going to go ahead and delete it if there are any remaining resources that it can't delete you'll get a warning here or some errors that will show you where to go to delete those but in our case this should take care of the resources that we provisioned it's going to delete the security groups associated with it including and as well as our subnets and the vpc itself and so with this we we should be good to go be sure to release those elastic ips and double check that you have terminated any instances ec2 instances that you that you created that there are none running and that any instances you created are in the terminated state okay so that should be it if you have any questions at all please let me know in the comments thanks for watching i'd really appreciate it if you got anything out of this video if you liked and subscribed and thanks for watching i'll see you later
Info
Channel: Wes Doyle
Views: 9,306
Rating: undefined out of 5
Keywords: dotnet, dotnet 6, aws, ec2, dockerizing dotnet, .net, .net 6
Id: ywj8Xm6sCKk
Channel Id: undefined
Length: 71min 36sec (4296 seconds)
Published: Thu Feb 10 2022
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.