AWS ECS Fargate using Node.js with GitHub Actions

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
hello this is erin white and in this tutorial i'm going to show you how to automatically deploy a restful api service it's written in node i'm using typescript we're going to deploy that automatically to aws's elastic container service and i'm using the fargate flavor which is aws's serverless offering for a container orchestration service so in this tutorial you will incur costs if you follow along there's an application load balancer that gets spun up that costs a little bit of money there's also a domain name that is required to follow along with this you could change the code how you want and not have a domain name but for this tutorial i'm actually using a domain name we're going to use a sub domain called api.talentize.com so let's get started by looking at this application it's a very small application i can fire it up by running npm run dev and once it fires up here let me go grab the index file once it fires up i can refresh this and you should see version 2 here if i go in and i change version 2 to version 3 it will automatically re-transpile the code and it will update so this is a very simple endpoint it's really just intended to get you over the hump of several challenges when you're deploying this to aws's ecs service so with that i think we're ready to get started with this and i can go in to aws's console and there are a few things we need so i am using uh these are called cloudformation templates we're using cloudformation templates to deploy this service we're starting off first off with an engine x container and you can see that right here you'll see the nginx image so we're not actually using this node service yet we're just going to get something up and running and then after we do that we're going to point to our image so to get this running i'm going to copy this code at the bottom here and i'm just going to paste it into this environment variables file and what i need is several things i need a vpc to push this to as well as two subnets to support at least two containers so to get that i go into my aws console and i look for vpc again this is a little bit more of an advanced tutorial so you should have some experience with aws i'll go into subnet so i can access the subnets one of the things you'll have to make sure of is that the subnets in the vpc that you're using for this are in the same region so i'm using us east 2. it doesn't matter which subnets i'm using aws kind of randomizes those regardless so i will grab two of them and paste them in and that looks like it works and now i need the vpc i'll grab that paste that in and then i need to change my domain name so i'll change it to talentize so with this you actually do not need let me uh clear that you do not need to put the prefix api on it that's going to be done automatically you can see throughout this cloudformation script i'm appending the domain name which is passed in as a parameter so that's pretty simple you can change any of this if you want this is just the the methodology i use for it for this specific application so i'll paste this in and before i start that let's pull up cloudformation this is where you'll see the script create the stack so if we go over here and we look at our stacks i shouldn't have any in this region and i don't so i will go ahead and run this and after it starts running we'll see a stack start to get created so there are a couple ways i could go about approaching this next step this is a two-step process i run ecs one and then i run ecs2 so what i need is after this is uploaded after everything is created in ecs hyphen one then i need an image for my next uh container system i need an image to use for the containers so i have to somehow get that into aws service so what i'll do is go to ecr and i'll create a uh wrong one i'll create a registry for this i already have an existing one that's okay and i'm just going to copy and paste this in i want it to be a private repository i'll copy and paste this name this all correlates so you don't have to change anything if you clone my github repo over here you can just clone it and you should be able to use very similar names i'll create that and now that it's here i can copy this using that copy function and paste it right in here now a couple of things again you have to make sure this is in the same region it explicitly states es us east 2 here which correlates with this that has to be the same as your region specified uh for your deployment here so now i have that in but the image doesn't actually live in aws currently so i have to get it up into aws somehow and the way i'll go about doing that is using those github actions so to connect github to aws i need permissions so to do that when you think permissions it's usually iam and what i'm going to do here for a second because i don't want to expose publicly any of my user accounts i'm just going to move it over to another screen and i'll hit add user which is a top button there let me uh go ahead and pull that back over here so we're just going to call this uh github talentize user we just want programmatic access i'll hit next we want to attach existing policy so there are a couple of policies we need we need ec2 container full registry we need to be able to access the container or the registry service s3 full access we need ecs full access we also need the github action deploy ecs so that's there we need to be able to retrieve environment secrets and then one last one here uh so we'll do next next review and i will create the user and once i get this access key here what i'll do is go over to my github account and go under settings and we're going to go to uh secrets here so what we need to do is basically copy and paste these uh this access key and and secret access key as values uh that correlate with this aws access key id and secret access key id so let's go ahead and create those new repository secret i'll paste this in copy and paste this so that's our first one so this will give github uh credentials authorization to be able to access aws copy this one and this is all available in my my github repository so you don't have to really do much work you just have to follow this tutorial probably so now i have access uh and my user accounts created again i don't want to expose my user so i'm going to move that to another screen click close i have to come back in here though and do one other thing i don't have enough policies to actually push this image build it on github actions and push it over to eces and the ecr registry unfortunately we're using secrets manager and i'll talk about that a little bit more here and to access secrets i need to add an inline policy so we need to go to secrets manager and we need to be able to read a secret value so i'll review that policy i have to add a resource okay so to do this i actually have to create the secret secrets manager all right when we pull that up we go into secret so i have a couple previous ones here in my code you will see a secrets manager and i think it's called in this it's called talentize app you know what i'm going to change that we're going to make that um application secrets okay there we go we'll call it applications secrets i'll change that in the future um you know what no i'm not you'll just have to change this to something that you like because i don't want to have to do a re-push to github i want to expedite this so we're going to say other types of secrets and we'll just do jwt secret now this correlates with this value right here jwt secret can be anything we want so we could say anything we want one two three just to give it a secret value hit next we call it a secret name so what's going to happen whenever github does this build is it's going to reach out to secrets manager because it's authorized to do that with the permissions we granted it it will pull the value back from this and create a dot env file in our container so we can use secrets in elastic bean stock you can just include them in the user interface but with ecs you don't really have a way of doing that so this is the only way to really grab a secret and this happens at build time you could litter your code with all this content go grab secrets from secrets manager but i like doing this at build time so you don't have that overhead cost now i will remind you that a secret costs 40 cents per month and you can you can have a whole bunch of different keys and values in here so it's not a one for one if i go retrieve the secret value i can edit it and i can add more secrets if i want to so it's not just one you have it's key value storage basically all right so since i have that i have everything in here that i need i believe the last thing i need to do is in iam just probably review this oh i need to get that secrets manager arn that's what i needed so i can copy that so we want to use least privilege it's it's considered a best practice so whenever i come back into this iam permission i i expand this resources and i'm saying a specific resource so i'll paste that in and it will hydrate let me try that again it'll hydrate the secret id and i can hit add i can review the policy and now i have to give it a name so we're going to call it uh github ec secrets manager get secret value i think i spelled that right that's quite quite a long lengthy name but it's very descriptive as well so i'll go ahead and do that and now i have that uh attached to my policy so theoretically if i if i want i should be able to do a build and push this image to uh to ecs so the next step in that process let's make sure we have an elastic container service let's make sure our app was stood up uh and let's go to cloudformation to see where that process is it's still probably creating and one of the reasons for this is it's probably going to be on this acm certificate issue so if we go to certificate manager and i open it you're going to see it's it's going to be stuck here saying pending validation so all you have to do is expand the expand this create this cname record so it validates that it's available and now our cloud formation template should continue here it might take it another second or two um but that's okay it should be it should be well on its way now so the next thing we have to do is somehow get our image into this repository right because looking at it we created the storage for it but we haven't actually pushed it up so all we have to do is some sort of check-in to our github and i have this uh which i'm not going to check this in but what i'll do is just increment my my api service to four and i'll say git add source index i'll make a message with it incremented uh version we'll say and i'll do a get push and that get push should kick off the build process here so you see it already firing up if and the way this works is you have to have your github dot github and an aws file in here so if everything works this should push an image to ecr and so we just have to be a little bit patient waiting for this job and it should do that for us you'll see it's it's running through this checkout it logged into ecr already so we got that now it's building it it already got it already read the secret from secrets manager you can see it's grabbing all that information so that worked pretty seamlessly so while we're waiting on that let's go back to cloud formation here and see if there's a hold up on anything it's probably still this acm it just has to validate that you actually own that domain and it is creating a sub domain for me here called api.talentize.com which i didn't have previously so um what i'll do here actually in another window again i don't want to expose all my domain names and all those types of things so i'll pull up route 53 and i'll go into the talentize.com domain and i'm pulling that up on another screen so we can just review it and uh you don't see it here yet that's what it's creating it's it's validated you should see this uh this validation here for api and the same thing with certificate manager it had to validate that you actually have everything available so let's go to certificate manager once again here as well let's see if there's any progress validating that domain name so it says it was issued so we have the ssl certificate issued and that's available which is really great that's that means that we can take the next step uh we're probably going to see this appear here so now that i have that i could actually start doing automatic deployments here i can update the next script and i can automate my deployment it looks like there was an issue with a task definition though so typescript service is missing this is anticipated so uh between these two scripts i've had some issues which is why i broke them out into multiple uh scripts so let me split my screen here to explain it and i i really quite frankly i don't understand exactly why this is the case it works with some accounts it doesn't in others so the the ecs service that exists in aws ecs right now is suffixed with a svc and not service but my aws yaml file is looking for service it's looking for that so it doesn't match so whenever i deploy this ecs hyphen 2 it will it'll work fine and we can just re-run this so that shouldn't be a problem the only thing we're really waiting on now is cloud formation to complete its thing so let's pull up cloudformation and as soon as it's done and it and it looks like it is which is really great so now i should have uh in route 53 i may not have that domain that subdomain because it creates it in the second one in the second file but we're ready to run this now because we have an ec uh an ecr image already deployed so i'll do the same process here i'm just going to enter hit enter a couple times actually you know what i'm not i'm just going to update this one all i have to do is say instead of uh create stack we'll just say update stack and we'll change this to it too everything else is exactly the same so i'll just copy that do a command k paste it in here and run it and that will update our cloud formation script you can see it's adding the auto scaling and and and that's what this these scripts do for a container system for a container you have some of these auto scaling policies built in auto scaling roll the target min capacity max capacity your scaling based on the cpu cool down 10 scale and scale out all those things that's a little bit outside the scope of this tutorial but i just wanted to at least include that stuff so as you got traffic your your alarms will be set in cloud watch and it will create more containers more instances of those containers through tasks so this shouldn't take a whole long time and once it's done we'll be able to go to api.talentize.com and actually i have to rerun this deployment too because it broke on that task name so all we have to do is come up here and say rerun and everything should work our restful api service should be available at api.talentize.com and you've fully deployed the application at that point so let's get back to cloud formation and see where it's at there's a lot going on under the hood you can see all these scaling policies it's creating a sub domain it's creating the ssl certificate the service if we look at that you'll see the ecs service aws ecs typescript api you can see the tasks associated with it this one if it's the engine x container which i mentioned before which it's not it looks like it's already deploying the image it's already it kind of race condition as i was trying to to demonstrate that it was already getting the uh updated image so what's happening behind the scenes here is it's pulling this image and you'll see another image a next version of this image come in so to speak as soon as this completes its build process so right now it is on the process of building and tagging the docker image it'll push it to ecr and then really quickly after that it will get deployed and what you'll see in this uh ecs service i think i have a couple of those windows what you'll see in this ecs service there's a couple containers here so the new one is pending so if we go back to our ecr service you'll see another version of it here a newer version of it right there and what we can do is we can increment this further but to to demonstrate that you're actually getting a newer version it looks like the build process completed i subtle check so if i refresh this i should have a service coming up here shortly the reason i don't right now is just because it's ping-ponging between two containers if i go back into ecs you have these two different tasks running it looks like we got we got task 12 up and running so now i shouldn't have that issue unless something's wrong with it so it looks like something was wrong here and we can debug that uh it shouldn't be anything major because it's actually worked um the only problem that could that could be would be the port mapping at this point so let's see the port mapping here should be on 8080 and it is and as long as my container is running on port 8080 which it should be we should be able to see this and it should work we didn't have any issues in terms of getting the secrets managers secret in everything worked integrated so it's just a small matter of well buying the world isn't it actually uh working now so let's go back into this task we'll go to the public ip and let's try and run that and and we have to tag on that 8080 so it looks like it's something perhaps with the container itself and that's that's a little alarming not sure why that's not working if i delete this everything else was the same we're using all the same information deployed appropriately and i believe in my ac aws i have that talentize app so it got the environment variable so this is a good opportunity to go in and just debug it and see kind of what's going on with it so if we go into the service and the task so uh it's draining the service because i'm in the wrong service actually it will create that slash service one and now it should be good now it should be good that's probably why there we go so what we had when we renamed this service this is actually really great because you'll run into this at some point when we're renaming this service from svc to hyphen ser vice which really small thing it had to drain that service in in ecs and create the new one so just to prove that this actually still works and we can check in some code and it will do something for us if we make this a five and i add it git add source index git commit i'll just say incremented version get push so our pipeline's all set up here everything should work you'll see it's already incrementing the version it's going to go through the same thing it's going to do the build it's going to do the push now one thing i do want to note here again this this does cost a little bit of money it costs about 40 cents a month for this secret and if you want to update a secret so let's say we want to call this anything we want abc if i save that and i already have a deployed image on ecs or ecr rather it won't update it by just going in here this is kind of an architectural decision it's using a pattern saying i don't want to go into my secrets manager and grab a secret every time somebody requests it from the code so you can sprinkle into your code here a call to go get that secret and retrieve it every time this processes the downside to that if you look at the notes here the trade off so to speak is that you get i think it's 10 000 secrets i'm in the wrong screen let me go back here let's go to secrets manager it's 40 cents per secret per month and then uh 5 cents per 10 000 api calls so when you start getting a lot of calls to secrets manager not only are you taking kind of a hit in performance which is very very minor it's it's a serverless service it's really fast but if you start doing 50 60 000 api calls to your secrets manager service per month you're going to to incur additional costs so what this does uh this aws script is it actually uses this uh repo to go get the secrets pull them out and then put them in a dot env file just like i have here so that's really slick that's really useful um yeah there is the the side of it not getting your secret every time but i think that's a very fairly reasonable trade-off okay post checkout uh the log was not found okay so that that's just a warning it's not really an error so if i refresh this i should get version five here instead of four and we're knocked but if i toggle back and forth for a little bit you'll see we do the reason for that uh is in ecs if i can find it i have a lot of tabs up here you'll see two tasks and they're both running at the same time so different versions so you're toggling between those two so if you're running uh something like react or angular or view a spa framework on the client side sometimes your restful api service needs updated first and you need to make sure that that's been deployed and it's running otherwise you might get variance in which which result you get so we're going to do one more thing here that that really completes the majority of this tutorial but because i want to demonstrate how to update the secrets here uh which i think i already did if i go in it should say i will increment it anything i want instead of 1 2 3 it will be abc and i'll save it okay so simple as that i updated it so now to get this deployed to aws now it's pretty much on 5 so you can see in and let's close that down and you'll see more ecr images here now but in ecs you'll only see one task or you should only see one task 16 and 15 and it still looks like uh it's it could bounce between the two for another minute or so here i'm getting consistently five so my presumption is it's just not dr routing traffic over to the previous version of it so that that's pretty good it's it's deployed i do have a redirect in here so if you do http to your endpoint it will automatically re redirect it if i do whatever query string it'll it'll automatically redirect all that too you can see that here if i search for redirect it's just it's it has an http listener and it's just redirecting all your port 80 requests to port 443 which i love i never want people hitting an api endpoint i shouldn't say never but i can't think of a use case where i'd want them hitting a non-secure endpoint for a restful api service okay so we updated our secrets manager let's just go ahead and do one more build more one more rerun so it gets that new secret and implements it in basically the same code we're not updating the code but what you'll see here is that this secret will the secret value for the jwt will become anything we want abc instead of one two three uh so again when you look here at this value it's anything we want abc so this is a way that you can force getting that updated secret into your application without saying oh i got to come in here and increment my code to five or six or seven or whatever it is so uh just kind of a recap here as that deploys i'm going to open this again in a new tab all the code that i've used in this tutorial is available here obviously you need the aws cli to to push these cloud formation templates i don't know if there's another way of actually doing it maybe you can can point to this and the to these two uh from some aws uh cloudformation script service but uh that that will work for you if you just clone this repository and then put in whatever your domain name is as well all right so we're just waiting on this to to push and i think everything else works it it seems like everything else has worked we have our registry done for ecr should be one task it's it's still kind of interesting that this task is still running to me usually they shut down within 45 seconds or so so it's just a matter of time it might it might run for a couple minutes i suppose this is really now just to document that our image works and now we'll see another i can close some of these tabs out i just i have so many tabs here sometimes that's uh the way it goes in aws so if i refresh here i might have a new service a new task not a new service but a new task so let's see should be built so maybe i'll get that new if i refresh this a couple times so maybe i'll get that new secret abc one or anything we want abc because this this looks like it re rebuilt and it should grab that secret from secrets manager if i saved it i thought i did let's go out and just recheck it just to make sure yep anything we want abc cloudformation we should need to do anything with cloudformation now so really it's just a matter of these containers running if i look at this one and i can potentially get to this by 8080 so anything we want abc so uh 123 rather it's not abc so it doesn't look like it grabbed it and it should have it should it might have been again a race condition so let's just rerun it sometimes you run into this stuff because github's going and grabbing this and maybe i didn't save the secret quickly enough i i would think that's unlikely but it's it's a possibility so we'll hold off here for one more minute while this builds it takes it what was the last couple of minutes something how long are these running for previous runs if you look duration let's go back okay so it'll take another minute and then it will push it and every new image that's created so now we're on 16 so let's refresh it yeah it just it didn't grab the secret but this will i should grab it here it already grabbed it and it probably won't show it in here i hope it doesn't show it in here you see jwt secret yeah it it hides it so you can't tell whether it got the right one or not but that's that's a really nice security feature actually you don't you wouldn't want it printed out in the console log here okay so we get some warning messages um the docker image itself let's go look at that as well um so i wanted to do a typescript app and not just a straight node.js app because of the complexity to it and so the only difference is in this docker container you have to install typescript i'm also using pm2 outside the scope of this tutorial but pm2 just keeps your app alive and then you're installing those globally in the container and then you're copying all those uh all those folders and files and everything into the container image then you're running the typescript transpiler and then you run the the code out of dist index.js which you can see up here so this never actually gets checked into github it gets transpiled on the fly in github and the image gets created and then it pushes it okay so job created again we're going to go into ecs and you'll have a couple containers here looks like they're both running so we might get that bounce around thing again where you see abc123 if i refresh you may or may not bounce back and forth just because the container is running doesn't mean that it's actually uh receiving traffic so everything worked and you're up and running you have the redirect going so you can look at that and every time i try and go to the http version and if i do abc here or something it will redirect you so it's a really nice little snippet or set of snippets of code again you have to deploy this first rename the service i don't exactly know why on on some some deployments i don't have to do that on other ones i do we're switching the port number from 80 here to 8080. i've been told that's more secure haven't really dug into it uh further we start with a base image uh using the engine x container and then once we have a container in ec r uh we point to that one and then when we update github it just pushes it to the ecr registry we'll see a fourth one in here maybe more than that five because we've done a couple deployments it just pulls that image and uses it in acs and you don't really have to worry about uh you know the servers going down with fargate aws manages that for you so i will link my github repository below in the notes to this uh you're free to clone the repository and follow this tutorial i hope you enjoy it thanks bye
Info
Channel: Aaron White
Views: 2,503
Rating: 4.8032789 out of 5
Keywords:
Id: eaS1jza_hy0
Channel Id: undefined
Length: 33min 13sec (1993 seconds)
Published: Thu Mar 11 2021
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.