Conf42 Site Reliability Engineering 2021 - Online

Level-up Your DevOps with GitHub Actions and Kubernetes

Video size:


Are you looking to rapidly deploy your content? Are Docker containers in your future? Come for this demo-only presentation where we start from scratch, build up a DevOps pipeline in GitHub Actions, and deploy to Kubernetes. Once setup, commit, and watch the magic flow into place. You too can automate your deployments.


  • You can enable your DevOps for reliability with chaos native. AZ give camp brings volunteer DevOps together with charities to build free software. If you're in Phoenix, come join us for the next AZ givecamp.
  • Our first step in building up a DevOps pipeline for containers is to have something to include in our container. Let's start out by creating a new website. Next up, let's create a docker file.
  • We're using net 5.0 as our base image. We're using the 50 alpine tag that includes the build tools, the SDK, and now we have all of. Net in place. Now we need to run some build commands. Each of them is going to build a separate layer. Let's split this in half.
  • Now our next step is to create a Kubernetes Yaml file. And let's use those secrets to build up our GitHub actions. Here's the GitHub actions build script that will allow us to get the content into place.
  • We're going to build our docker image doing all of the steps inside of our docker file. We will then replace all the secrets inside of the Kubernetes yaml file. After the build we will log out. With GitHub actions hosted on GitHub they automatically purge the vm that kicked off my build.
  • Building a new workflow for DockerPr Yaml. This will run for pull requests. It will build on all branches that are not main and it will only do all of the build steps inside of our docker file. With that in our registry then we will push that up to Kubernetes.
  • Robrich shows how you can level up your DevOps for containers with Docker and Kubernetes. Thanks for joining us at Comp 42. At it comp 42 Sre 2021 conference thanks.


This transcript was autogenerated. To make changes, submit a PR.
Are you an SRE, a developer? A quality engineer who wants to tackle the challenge of improving reliability in your DevOps? You can enable your DevOps for reliability with chaos native. Create your free account at Chaos native. Litmus Cloud hi, welcome to Comp 42 dot Com's SRE 2021 conference. We get to talk about level up your DevOps with GitHub actions in kubernetes. Here's the part where I tell you that I'm going to post my slides, but there are no slides. This is it. That GitHub, that notepad document. That's it. Now you can go grab the code for this. It's online right now here on GitHub. Yeah, we need to go build this code. But if you didn't grab this URL, go to slash presentations and here's level up your DevOps. The code is online right now, and once we finish build it, it will be up there on GitHub while you're Click on about me and you'll see some of the things that I've done recently. I'm a Microsoft MVP, a friend of Redgate, a docker captain, and a cyral developer, automate AZ give camp is really fun AZ give camp brings volunteer DevOps together with charities to build free software. We start Friday after work. Sunday afternoon, we deliver the completed software to the charities. Sleep is optional, caffeine provided. If you're in Phoenix, come join us for the next AZ give camp. Or if you'd like a give camp in your area, hit me up on email or on Twitter and let's get a give camp in your neighborhood too. Some of the other things that I've done, I do a lot with containers, consulting and training, and one of the things I'm particularly proud of I replied to a Net Rocks podcast episode. They sent me a mug. Yeah, that's cool. They read my comment on the air. And there's my coveted net rocks mug. So let's dig in. We have here all of the code that we need to yep, we've got an empty folder. So our first step in building up a DevOps pipeline for containers is to have something to include in our container. Let's do that. So let's start out by creating a new website. Net new. Net New allows us to scaffold out lots of different types of websites in. Net. And so we could do an MVC site, a website blazor angular react. Those are all great projects. Let's do this. Net new MVC and we'll give it a name of levelup DevOps and an output folder of the current folder. If we didn't give it a name, it would use the name of our folder, in this case demo. And if we didn't give it an output folder, it would create a new folder inside this folder for that content. So we created it in the current folder and now we have some content. Let's open it up inside vs code. Now we've got controllers. Let's close all this content. We've got controllers, we've got views. Here's our home view. And it says welcome to comp 42 SrE 2021. Woohoo. Now we've got our website. Okay, now we need to get our website into containers. Our first step is to worry about git. So let's first create a git ignore file. Git ignore. That isn't it? Git rename git ignore. There we go. Oh, do we want to add assets? Yes. Now it's going to add for us this vs code folder. And this vs code folder will give us the things that we need to be able to debug our application. Okay, back to our git ignore file. Now here are all the things that we don't want to commit to our repository. So our bin folder, our OB folder, those built assets, also user specific files like Star user Star Suo, the vs folder. If we were using visual studio, and that's a pretty good spot for removing content from git. We could also include the star log or Star TMP, any other files that we wanted to exclude. But for now, this list is pretty good. Now we want to be able to create a Docker ignore file that has the exact same syntax as our git ignore file. Now this docker ignore file docker ignore is the exact same syntax. So in fact we can start with our git ignore and just use that as a docker ignore. In fact, if we don't have a docker ignore file, but we do have a git ignore file, then docker will use that instead. Now this is everything. We don't want to end up inside of our container. So we've got bin and obed star user star suo. But we also want debug content. So for example, appsettings development JSOn. And here in the properties folder, launchsettings JSOn. Now launchsettings JSON is all of the things that we need to be able to debug our application. So should we start? Kestrel, what port do we want to debug on? And those aren't necessary inside of a production runtime container. Okay, now we've got our Docker ignore file. Next up, let's create a docker file. New file docker file. Now it's important this be named Docker file and not Dockerfile txt. If you did accidentally create it with Dockerfile. Txt, easy enough rename and just make it Dockerfile. Now I have the docker extension installed in vs code so I can see the whale. It turned into beautiful colors. That's perfect. Now let's build up our configuration as code that explains how to get from our source code to a running container inside of kubernetes. Now we'll start off with the various lines for a docker file from copy run CmD. These are the main commands inside of a docker file. In fact, if you know these four commands, you can probably read pretty much any docker file and understand what's going on. Let's start off with from now this specifies the base image that we're going to build on top of. We want to stand on the shoulders of giants so let's head up to Docker hub and take a look at the content. Now I'm going to search for. Net and land here on this. Net image repository. Now it's a meta repository. It shows me where the other images are. Now we can go to. Net samples. That's great for understanding various docker files that build. Net in interesting ways. Net monitor is pretty cool. Net runtime depths that's the base content that we need to be able to install. Net on top of. On top of that is the. NET runtime which will include content for running console applications. On top of that is ASP. NeT which will allow us to host web servers and on top of that is built the SDK, the build tools. Now we want to build inside of our container. So let's start there. Here inside of Docker Hub with the. Net SDK here's the image that we want. We're using net 5.0 so that's the correct image that we'll use as our base image. Scrolling down a little bit we can see that the various tags available and the various docker files used to build those tags. And if we were just using the 50 tag that was specified above, we'd end up on Debian. Now Alpine is a really really small version of Linux so let's use the 5.0 alpine tag instead. Okay, so back here in our Docker file we're going to say from thatalpine. Now we're using the 50 alpine tag that includes the build tools, the SDK, and now we have all of. Net in place. Our next step is to copy all of the content here from our folder. So we'll copy all of the content from the folder where we run the docker build command into the current folder in our image. Well, where is that current folder? Let's specify that workdur is Src. Now there's nothing magic about src. We could put it in Varlib wherever we wanted it to, but in this case I'll just have it at src, and that's a good spot for it. Now it'll create that directory and change into it if it doesn't exist. So we're copying all of our content into that Src directory, and now we need to run some build commands. Now if we were at the command line, the commands that we would run to be able to do this, we would say net restore. That would restore all of our nuget packages. Net build will build in release mode. Net test that will run all of our tests will also do that in release mode so that release mode so that we don't accidentally get debug and release content in place. And then net publish and we'll publish to the disk folder. Now NEt publish is that same command like right click publish inside of visual studio, but we're doing it here inside of our build process. So it'll be identical every time. It will go gather all the HTML CSS files, all the Javascript files, and also all of those built dlls. But it will leave behind all of our CsHTML and c sharp files. Okay, so here's all the commands that we would run from the command line, and we need to run them as part of our docker build. So let's run this one and run this one and run this one and run this one. There we go. Now we've got our docker build file executing each of these tasks. Now each of them is going to build a separate layer, so we could do interesting things like combine them together. But in this case we really like that. Docker will cache each of these layers, so having them specified here is kind of nice. Next thing we need to run this. So we need to say net levelup DevOps Dll and that is in workder dist. Now there's a few more things that we need to copy into place. Let's go grab some environment variables. Now this says we should run in production mode and we should run on port 80 and we'll add some additional metadata to our container so that we know to hook into port 80. Perfect. Now we could use this build file as is and it would work great. But there's a few things that we can tidy up here to make our production runtime image a little bit smaller. Right now we're including our source code and our build tools in our production image. Let's see if we can go grab some content here on the Docker hub for ASP. Net and see if we can run just the website. Now this Asp. Net base image will allow us to just run the website. It doesn't include build tools and scrolling down a little bit we can see that it also has an alpine variant. So let's come back into our Docker file and let's split this in half. Let's go here alpine now we have now two images that we're building with one Docker file. We'll call this one our build server image and this one will be our production runtime server image. And I put server in air quotes because well it's not actually a server, it's an image but we can think of it kind of like a server. This top part will do all the building and then once we're done building, this bottom part will only include those pieces that are specific to our application. Now we do need to let's switch this to an app folder. We do need to copy the content from the disk folder into this folder so that we can be able to run it this way. But right now it's going to copy it from the disk folder on my host machine, not from this other container. So let me say, I will say as build. No, from equals build. Now I've said from equals build. So it's going to go look for the build stage. So let's name this one as build. Now we could also name this one as prod or whatever but we're not going to use that label so that's fine, we'll just leave it off. But this very specifically says copy from the disk folder in this build image into the current folder, this app folder here on this new image. That's great. Now that we've split our file into a multistage build, this stage will include all of our source come and build tools and this stage will not. The next thing we can do is take a look at these layers. Now we're going to copy in all of our content and then we're going to run restore to grab all of our dependencies and then we're going to build. Well what if I just change a JavaScript file? I'm going to re restore my dependencies. Really? I want to restore my dependencies first and then copy all my files. Well, I still need to grab my manifest, so let's copy levelup DevOps Csproj into the current folder. Then we'll net restore, then we'll copy everything else and then we'll build, test and publish. Now that means if I change just a cshtml file or just a JavaScript file that I'm not going to re restore my nuget packages Docker will continue caching this layer, it'll start here, invalidating this layer and it will start our build from here. Now if our build fails, it'll stop at this step. If our tests fail, it'll stop here. If our publish fails, it'll stop here. And so we'll only get to a production runtime image. If we restore all the things correctly and we build correctly and all our tests pass and we're able to publish. But if something fails and we're not changing the dependencies that the packages we depend on, then we can start here copying all of the new files and continuing on. Perfect. Now we have a docker file that is great in being able to build our content, cache the layers correctly in docker and separate it into this multi stage build that allows us to have a really lightweight production runtime container. Now our next step is to create a Kubernetes Yaml file. Now Kubernetes Yaml files can get kind of big, so let's just go grab the file that we used last time. Here's the file that we used last time. We've got a deployment that specifies the number of replicas. In this case we're only going to run one. We have a service that will load balance across all of those one containers. We have an ingress that will grab our content and resolve DNS and point it at the particular service. But we do have some things that we can replace here. Here's our AKs URL that will work on DNS. Here is our image label, our Githash. Here's our container registry URL. We do need to replace last time, so let's replace this with levelup DevOps and we've got that in place. We could also tune other things like the number of replicas, the resource limits, any other dependencies that we want. But at this point I think this one works pretty well. Okay, so we've got now our docker file that will build our content, our Kubernetes Yaml file that will deploy it to Kubernetes. And let's get all of this up to GitHub. Switching over in vs come I will stage all of these changes and I could pop open each file inside of vs code and see the old and new. But every file in this is new. So far they're all added. So I'll just look through and make sure that I don't have any files that I didn't want to commit. Did I perhaps forget to exclude the bin or Obs folders? No, it looks good. Initial commit, perfect. So now that I've got that commit in place git status, we can see that we've got that in place. Let's get push origin main and push that up to GitHub. Now if you grab this URL up on GitHub, you can see that we've got the code in place and it's looking really nice. Now this was a pretty much empty GitHub repository, but I did do a few things on my way in. I went here into settings and I went to secrets and I created a few secrets that we can use in our GitHub actions build. What is our containers, registry password URL and username, what is our Kubernetes URL and the kubeconfig that we need to be able to log into it. So let's use those secrets to build up our GitHub actions. Now when we click on actions for the first time, it will give us lots of templates that we can use. So if we want to do an openshift or Alibaba cloud deployment or terraform rust, there's lots of integrations that we can get to here. That's pretty cool. Now it did guess that this was a Jekyll site, but in this case I think I liked the publish a docker container workflow instead. Now we could definitely start from a blank file as well. It's just a docker file. And I'm going to rename this to Docker Kubernetes. Okay, so here's the GitHub actions build script that will allow us to get the content into place. Docker build and push Kubernetes apply. Now in this case I'm not going to run it on a schedule. We'll come back to pull request. And so in this case I'm only going to run it on the main branch. Perfect. Now I'm going to remove these environment variables in this case and let's get straight to the content that we want to do. I'm going to delete this and this and this. And let's create a new stage. This will be name Docker build and push Kubectl apply and let's run this script. Now the script that I want to run is first off I'm going to say Docker, Docker build. That's the current folder where I want to start my building. And let's tag this on our way through as well. So I'm going to tag it with levelup DevOps. And now let's go use some of those secrets. I want to be able to grab that GitHub, the secret here for my registry URL. And so taking a look at how secrets work inside of GitHub, we've got our secrets here, they're all in place. And now we can use this dollar curly Curly to be able to get at that secret. Perfect. So here in my GitHub actions build file, let's say dollar curly query. And I'm going to say secrets acr URL. There I've tagged it with my container registry so that when it comes time to push it, it knows exactly where to push it. I'm also going to give it a version. In this case I will use GitHub Shaw, which is the GitHub hash associated with this commit. Now we could definitely grab something like a build number or other details. This just makes sure it's unique and allows me to quickly go from the container running in production to the source code that created it. Okay, so I've got my container built and it's going to do all of those steps inside the build file. Once I've got my image built, let's push it. So docker push and I will go grab this image and I will push that up to my docker registry. Now what's that registry? I think I probably need to authenticate into it first. And that's a great place to go grab some content from the marketplace. So let's do this. Let's do a docker login. Now I need to log into my registry. So here's one. And is that the one that I'm after? Yeah, that one will work. Now here's the yaml associated with it that I'll need to include. I could pull into the full marketplace listing and take a look at the details. It's not uncommon to get from there into the GitHub repository that includes this content. But that's the action that I need to grab. So let's grab this yaml and let's set it in place right here. I will need to indent it a little bit to get that lined up. There we go. Now we need to log in to our registry. So what's our registry? Well we happen to have a secret for that. So let's say secrets Acr URL. There's our registry URL. What's our username? We have a secret for that as well. Let's do secrets Acr URL. No, Acr username. Perfect. And what's the password? Let's go grab the secret for that as well. Secrets ACr password. There we go. And then log out. Now this is optional and the default is true. This will log out not at the end of this step, but at the end of the entire build. Now if I'm on a shared build agent where I don't necessarily have control over that content, then I definitely want to clear out these secrets after the build. With GitHub actions hosted on GitHub they automatically purge the vm that kicked off my build so I don't need to worry about it. But yeah, it's a good idea just to clear the secrets on the way through. Perfect. So we'll do our docker build, we'll push that up to our container registry. The next step is to kubectl apply and I'll give it the k eight s Yaml file that we built. Now here in this k eight s Yaml file is a bunch of the secrets that we needed to replace Acr URL image label. So let's go replace those. Now this said command is a little swirly, so let me just copy it into place. Let's go do this replacement. Now here in the Kubernetes KDES Yaml file we're going to replace the content, not back it up. We'll go grab the Acr URL and replace it with that secret. We'll go grab the aks URL, replace it with that secret and go grab the image label and replace it with that secret. And we're going to do this globally. So we'll replace all of the instances here inside our Kubernetes yaml file. Now I'm very specifically doing this after I pushed it to the registry because if I were to do it earlier, like maybe here and then say for example, I forgot to exclude that from my docker, ignore. So yes, we forgot KDEF Yaml here, then those secrets would get embedded into my container and I really don't want to do that. So I'm very specifically going to put these secrets replacement after I've pushed my container up to my registry. Now I know that even if that Kubernetes Yaml file leaked into my image that it doesn't include those secrets. Perfect. Now we do need to log into our Kubernetes cluster to be able to do a kubectl apply. So let's head back out to the marketplace and let's look for a Kubernetes Kubectl. No, kubernetes set context. There we go. There we go. Kubernetes set context. Let's go grab this one. Yeah, that'll work. Is this one the one that I'm after though? No, I did want that one. Here we go. I should have looked at the stars. So let's copy this one and we'll set it in place. We probably need to adjust the yaml to get that to line up. Yep, there we go. Now here with Kubernetes set context, our first stop is with the method. So let's remove some other things and we are going to use the cubeconfig method. Now because we have the cube config method we need to specify the cube config. Good thing we've got a secret for that. Secrets, secrets cubeconfig. And I grabbed that by grabbing the cube config on my local machine. I went into my user profile directory, grabbed the cube folder and inside there the config file and extracted that portion referencing this particular cluster. So with that cube config in place I don't need the other ways to authenticate to it. So let's remove those. And now I've got my build in place. So we're going to start out checking out our content. Then we will do a docker login logging into our docker registry. Then we'll do a Kubernetes login logging into our Kubernetes cluster. And then we'll do all the steps associated with our build. We're going to build our docker image doing all of the steps inside of our docker file. We will push that resulting image to our image registry. We will replace all the secrets inside of our Kubernetes yaml file and finally apply that Yaml file into kubernetes. That looks great. So with this in place let's start the commit and this will be create GitHub actions build. Perfect. Now this just puts a file inside of our repository, inside the GitHub workflows folder. And we named the file Kubernetes Yaml. It's just a regular file inside of our build. So if I come in here and I say git pull, then we can pull that down and get at that content here inside of vs code as well. So if we need to adjust this, we can just pull out content. So in this case I added an extra comment. We can remove that and we're doing just fine. Oh, I've got an extra line there too. Now because we have a folder inside GitHub workflows, it kicked off a build. So let's come back here and we can see this build is running. There's our orange dot and we can pop open the details of that build. Now it's going to do each of those steps. So it checked out all of our content, did the docker login Kubernetes set context. Now it's digging through all of the steps inside of our docker file. Finally, once it gets done with the docker file, it's going to push that up to our container registry and then finally do that content of getting it into kubernetes. So it looks like it just finished pushing it up to our container registry. And there's our Kubectl apply and we can see that our build is green. Very nice. Now let's do a cubectl get all and we can see our service is starting to spin up. If I hurry I can find it starting, but it's already running perfect. Now it does take a while for the DNS to propagate associated with our ingress controller. And so as a shortcut for that, there is a mechanism where we can use port forwarding to jump straight into the content. Now we could port forward into a specific pod or into a deployment or into a replica set or into a service. Let's do that. So here I'm going to say Kubectl port forward servicelevelup DevOps and I can forward port 80 on my local machine to port 80 inside the container or inside the service. But maybe I've got something else running on port 80 on my machine. So I'll use port 80 80 instead. Okay, now with that set up I can come here into localhost 80 80. And I can see that we've got our website online. Welcome to comp 42 SRE 2021. Woohoo. Now it did all of those steps to get from our source code all the way to our running container inside of kubernetes. Now we did skip a few steps. It could be nice if we built a readme here and we did skip over pull requests, so let's come back to that. Now first up let's build a reaDme. I'm going to build a readme MD and let's go grab some content for that readme. Here's some readme content. And wouldn't it be cool if we could put a status badge here showing the status of our builds. Let's come back here into actions and pick our build and let's create a status badge. I'll copy that content into place and let's paste it right here. There we go. There's our status badge. Now let's take a look at the content that we've got. Ready to go? Let's stage all these changes in our docker ignore file. Oh yes, we forgot to ignore the kdes yaml file. Here's our new readme file and we modified a few things here. So add readme and fix typos. Let's commit that and then push that into place. Git, push origin main, that will send that up to GitHub. And because we have that content in place, it's actually going to kick off a new build. Let's watch it because it's really fun. Last time we went in here and we went to details to get out our build. This time let's go to actions and we can choose our particular workflow. Or I see the build started right here. That's great. Let's dig into that particular build and watch it go. So the first step is to Docker login and then Kubernetes login. It did both of those. Now it's pulling down the dependencies and starting into each of those steps inside of our docker file. Our first step is to copy the CS proge and then run net restore. Looks like that worked out great. Then we'll copy in everything else and run our net build. In this case our build succeeded. That was wonderful. Let's run all of our tests. There are no failing tests because there are no tests. Then we'll run our net publish, finally copying that into our new production runtime image and push that image up to our registry. We're back in our regular docker script and with that in our registry then we will push that up to Kubernetes and we have the latest version running inside of Kubernetes. Perfect. The other thing we have now that we have this readme is this status badge that will get us straight to the build results associated with that build. Perfect. Now the other thing we wanted to take on is to do pull requests. So let's close this and close this now here's the build that we built so far. We could definitely come in here to GitHub and we could click on edit and get back into the designer where we have the marketplace and we can edit the things. But in this case let's just modify it as a file here in our repository. Now I want to build a new workflow for DockerPr Yaml and this will run for pull requests. So here I want to do the docker build for prs. Now I want to run on all the branches that are not main in case I do pull requests based on other branches. And then I also want to say pull request and branches. I will do this on all branches. So if I do a pull request from any branch I will kick off this run. And if I commit to any other branch then I'll also kick off this run. Now as part of doing a pull request. I definitely don't want to deploy to my production kubernetes environment. So let's delete that step because I'm not deploying. I don't need to put secrets in place because I'm not deploying. I also don't need to log into kubernetes. Let's delete that step. I also don't want to push the resulting image into my container registry. Let's delete that step. Now I also don't need to log in, so let's delete that step. Docker build APR and now I don't even necessarily want to tag it with my container registry. I'll just say level up DevOps PR there we go. Now we have a build suitable for pull requests. It will build on all branches that are not main. It will build on all pull requests and it will only do all of the build steps inside of our docker file. Now this still will do all of the build, test and publish, make sure that our image will build successfully. And if we have any failing unit tests or if we have any syntax errors in our source code, then our pr will definitely fail. Okay so let's commit this content to our registry and we will say PR build and let's commit it and push that up to git push origin main now we changed our main branch. We didn't change a pull request. So because we changed our main branch it's going to kick off a new build. Perfect. This is so much fun to watch. It's going to do exactly those steps. It will do all of the steps inside of our build script. And so our first step is to log into Docker and Kubernetes. The next is to start enumerating through all of our steps in our docker file. The first step is to go grab all of the base image and then we copy in all of our content. Net restore. That net restore worked really well. We'll do a net build. Let's see if our source code worked. Yes, no warnings, no errors. That's great. Let's run all of our tests, no failing tests. Let's publish. Then we'll copy that content into our new image. And now we're done with our docker file. And the next step is to push that image inside into our containers registry and finally start that new copy inside of kubernetes. That worked. And if we now come into our actions, we see that we not only have that build that we just did, but we also have a new build for pull requests. Perfect. Now what if we want to do builds for other environments? Maybe a dev test environment. So we could do a similar thing. We could come in here and we could duplicate this build, switch this from main to develop and start replacing these. Maybe this is the ACR URL for develop and the username for develop. Well that gets a little crazy. Let's instead use GitHub environments. So we're going to modify this same build, the normal build that we want to do our things and it will be on the main branch and the develop branch, which means we need to come here in our pull request and say, but this is also not develop. And now let's set up our GitHub actions secrets for environments. So I'm going to come here into settings and I will come here into secrets. And right now all these secrets are not associated with a particular environment or branch, but I can create environment specific secrets. Now that's perfect. If I create environment specific secrets for each branch, then I can put the develop branch secrets that have the exact same names with the develop specific values. Now I only need to have one build file that will use the exact same secrets as all of the details. But because I have five different secrets, I can now push to my develop environment with that exact same build script. So let's commit this content. We've got our, we'll stage our change to our build file that adds the develop branch and our pr build that removes the develop branch and add a build for develop. Now because we're using environment specific secrets, we can do all this with one build file. Now we just kicked off a build. So actually, let me git push origin main we just kicked off a build and we've seen that work a bunch of times. It is really fun. This was really cool getting to show you GitHub actions and how you can level up your DevOps for containers with Docker and Kubernetes. You can grab the code that we just built up on Slash Robrich levelup DevOps, GitHub actions, kubernetes or go to, click on presentations and it's right there. Find me at that spot where the conference is designated for live Q and A. Or if you're watching this video later, hit me up on Twitter at Robrich. And this has been so much fun getting to show you this build. Thanks for joining us at Comp 42. At it comp 42 Sre 2021 conference thanks.

Rob Richardson

Developer Advocate @ Cyral

Rob Richardson's LinkedIn account Rob Richardson's twitter account

Awesome tech events for

Priority access to all content

Video hallway track

Community chat

Exclusive promotions and giveaways