Conf42 Kube Native 2022 - Online

Edit, Debug, and Secure K8s Manifests: Why is it important and how can you get it right?

Video size:

Abstract

In a clear “how-to” tutorial, learn what’s needed for Development and DevOps teams to work together to manage Kubernetes configuration tasks at scale ensuring better overall productivity and deployment success the first time by leveraging open-source projects to accomplish the following tasks in an easy, straightforward way:

  • Identify & fix validation errors immediately
  • Provide a quick overview of k8s resources and their relationships
  • Debug & validate the output of Kustomize and Helm
  • Find & fix configuration errors. Diff local vs remote resources vs clusters before deployment
  • Leverage easy-to-use editors and templates to ensure best practices, security & consistency across Dev and DevOps teams

Summary

  • Welcome to this talk about Kubernetes manifests and everything you can do with them. Going to walk you through a bunch of things that are important to understand and know when you're working with kubernetes and manifests. Some best practices at the end to round things off.
  • Any object that you want to create in your Kubernetes clusters, you have to specify a manifest that defines the state of that object. These manifests are either in JsON or YAml format. A file can contain multiple objects defined, and then kubernetes will create corresponding objects for you.
  • The manifest specifies the actual properties for the objects that I want to create. API version and kind are used to kind of define the content of the manifests. This shouldn't be confused with the version of Kubernetes itself. Always try to use the latest version.
  • Many of these objects in Kubernetes don't live by themselves, right. They refer cto other objects. Three most common types of references are just by name. Also good to be aware of, obviously the status of your object.
  • Super important to validate your manifests, obviously syntax validation. You want to make sure that your manifests are valid YamL or JSON schema validation. Another step of validation is around links. This is a common cause of spending a lot of time figuring out why things didn't work.
  • Policy validation policies are another kind of rule set on top of the first three. This can be policies related to performance, to resource allocation, to security, networking, et cetera. These policies can be applied either before you deploy or later. There's a lot of them available online on GitHub.
  • Using Kubectl or helm or customize, we can create a simple NgInx deployment. We can then validate it before deploying it to a Kubernetes cluster. Eventually we'll look into automating that using CI CD or even a Gitops approach.
  • Next step is to talk a little bit about templates. Templating is a common need that you'll run into when you start working with multiple clusters or target environments. They just help you do those in different ways. And whatever works for you and your team and what you think is best is always a good start.
  • Helm uses a more custom templating language based on go templates and then packages those into what's called a helm chart. Use helm to package your application and then use customize to overlay any runtime configurations. It's a very powerful concept because it makes the most of both the tools.
  • Always try to use the latest stable API version for your manifest. Keep them simple. Don't add a bunch of default values unnecessarily. Validate manifests before you deploy.
  • Then finally, I really didn't talk a lot about Gitops, something I urge you CTO adopt when you've come for a new journey. Gitops is similar to maybe like adopting agile. The entire team has to do it, and it does impose some constraints on your workflows. Hopefully this was helpful.

Transcript

This transcript was autogenerated. To make changes, submit a PR.
Welcome to this talk about Kubernetes manifests and everything you can do with them that you weren't aware of. Going to walk you through a bunch of things that are important to understand and know when you're working with kubernetes and manifests when you're just getting started, really a lot of things to know. I'm going to be showing do a little bit of a demo as well. But first of all, just going through 101, what is a manifests? Talk about the manifest lifecycle, talk about how to create manifests and validate them. Talk about templating tools and just tooling in general and some best practices at the end to round things off. Hope that will be valuable to you. I have with me the ever lovable Kubernetes mascots here to the right. Say hello to them and let's jump on straight in. So first of all, what are Kubernetes manifests? And if you've worked with kubernetes, I'm sure you know what they are. If you haven't, now you know basically kubernetes. Any object that you want to create in your Kubernetes clusters, you have to specify a manifest that defines the state of that object. These manifests are either in JsON or YAml format. A file can contain multiple objects defined, and once you've defined the object, you apply it to your Kubernetes cluster and then kubernetes will do all its magic and create those corresponding objects for you. So straightforward, a manifest is a YAml or JSON file. Can work with any editors of course that can work with those kind of files. Basic structure of a manifest as you can see here, very straightforward. This is a YAmL example. And generally people mostly use Yaml. Although JSON is valid, every manifest has to have a kind. So telling what kind of object we're creating, the version of the kind. So this is a v one service that I'm creating in this manifest, and then some metadata and the name of the object is required and the namespace is optional. And the name and namespace have to be unique in combination. So you can only create one service with the name pet store. For example, in the default namespace you could have a pet store service in another namespace, but you won't be able to have two pet stores in the same. So good to be aware of. And then you can also add other metadata. You don't see them in here like labels and annotations commonly added by tooling like helm or other tools that you might use can also be helpful, just for your own sake, to organize your objects when they're in your cluster. And once you've kind of passed that initial block of Yaml, coming to the actual meat of the Yaml file or the manifest is what's called the spec or the specification, it could be also data in some objects. This specifies the actual properties for the objects that I want to create. So here you can see this is a service listening on port 80 and targeting port 80 80 using the name of the port is HTTP and then it's a selector telling to which other objects this service is applied. So obviously the content in the spec can be varies a lot between different kinds of services and somewhat between versions, and can be really short like you can see here, but it can also be super super long and elaborate and complicated, depending totally on the kind of object that your manifest is describing. Important to understand, API version and kind, and since those are used to kind of define the schema or the content of the manifests, as we already mentioned. So based on the kind and version, that's where you know kind of which properties and maps and arrays and enumerations, all things you can use to define the state of your resource. And the actual schema languages used underneath to define and validate those properties or specs is derived from OpenapI 30. So it's JSON schema with some limitations. You can read about this on Kubernetes IO. Obviously one thing to be really aware of here is that this shouldn't be confused with the version of Kubernetes itself, right? So currently I think Kubernetes is at version 125, or could it be 124? I don't remember. That version supports multiple versions of the actual object. So for example the crone job kind, you can run either API version, version one, or version one beta one, which is an older version, but you need to keep track of this. Of course if you're using V one beta one for your chrome jobs and you're about to update to Kubernetes 125 that no longer supports that version. So you needed to be on top of these versions and obviously always try to use the latest version. But of course if you're targeting for example a cloud provider, make sure that they support the Kubernetes version that you're using with the objects that you're creating. So always good to be on the safe side and make sure you've got that yourself. That's all covered. Obviously many of these objects in Kubernetes don't live by themselves, right. They refer cto other objects. It's very common with kind of references between objects. So three most common types of references are just by name. So for example here you can see a config map ref. So this is referring to a config map with this name. Another more complex reference is what's called an object reference. So this not only by name but also by kind and API group. So this role ref here could be referring to other kinds of objects in other API groups, whereas this ref up here is always locked to a config map with the current version. Selectors are also very common. We saw a service previously, here's another one. This service applies to any object whats has this label defined. So Kubernetes IO name with this value. So this is a way of applying or creating references of one to many, right? So this service would apply to any object having these labels. So it's a powerful way of kind of referencing more than one object and creating more complex dependencies between objects. Also good to be aware of, obviously the status of your object. So when you're working with your object locally, it doesn't have a status because it's not deployed in Kubernetes. And as soon as you deploy your manifests to Kubernetes, Kubernetes itself is going to add a status property to your yamls or to the manifest. And I'm going to show this in a little while, kind of showing you the current state of the object and any events kind of related to the object in your clusters. So good to know that if you kind of look at the manifest that you have locally, maybe that you created and then the manifests that's actually running inside your cluster, you're going to see some differences there just because Kubernetes could apply some transformations and add some additional metadata, but it'll also add status metadata that kind of lets you know, kind of keep track of the projects. If you were to look at the manifest itself and this is not added for all object types, once again you have to play around or read the documentation just to figure out kind of what values and properties are added for which types of objects. So trying to kind of drill this into a lifecycle, because we all love lifecycles, is usually you start by creating your manifests using some tools or get back to tooling. Later. You edit them, you do validation. I'll get back to that soon. And once you're kind of happy with what you've created, you apply the manifest files to your Kubernetes cluster. And then what Kubernetes does is it takes the manifest and then it tries to, using its internal objects and logic, which I'm not going to go into, create the corresponding object in your cluster and then, in line with how you've defined it, and then there's a loop that can happen in cluster. So let's say the object isn't working as you desired, or you want to make some changes. You can do that straight directly by modifying the manifests in the cluster, and then Kubernetes will kind of update the state of the object accordingly. You can also, if you're a little bit more structured, let's say you made a mistake, whatever mistake you might make, that change out here to the left, and then reapply the manifest to your cluster, which makes for a little bit more of an auditable workflow lifecycle. But usually hot fixing is something that you'll end up doing, at least initially while you're getting to grips with Kubernetes. And at the end you'll delete the object from, you might at least delete it from kubernetes, and then of course the manifest will be removed as well. Not a super complex lifecycle, but good to understand the relationship between your local files containing the Yaml Json and then the actual object generated and created inside the cluster when you apply those files to Kubernetes. So creating can editing manifest is a straightforward thing, right? You can use any editors, obviously you can copy paste from other manifests, which of course is maybe not the best way to do it well, but it's a very productive way of getting things started, and there's a lot of examples out there, so it's a good way to get started. And there's a lot of plugins and code snippets and generators and wizards and stuff online and as plugins to your ides to help you getting started with your manifest. The easiest way maybe is to use Kubectl, which I'm guessing or hoping you're aware of. Kubectl is the command line tool for kubernetes, and there's a simple command that you can use to generate basic manifests for different types of objects. I'm going to show you this in just a little while and walk you through kind of the whole thing just to see how that works. Finally. Not finally, but let's talk a little bit about validating. Super important to validate your manifests, obviously syntax validation. You want to make sure that your manifests are valid YamL or JSON schema validation. You want to make sure that you've defined the right properties, and the properties have values that are in line with the type of properties that they are, and otherwise, obviously Kubernetes is not going to be able to handle the manifest when you apply it. Even though it might be a valid yaml, it might not be a valid schema. Another step of validation is around links. So as you saw as we talked about earlier, super important that if you're referring between objects, that those links are all lined up, that you're referring to the right name. Sometimes you might be referring to objects in other namespaces. You need to make sure that those objects are also there. And this can be tricky because just like I said here, the objects that you're referring to might not actually exist locally in your files. They might already be running in your cluster, so it might be hard to validate these kind of references. Also, some references, as you can see here, can be optional. This is depending on the schema of your object. So for example, there's a secret reference here which is not optional, so this actually has to exist. Others references can be optional so you won't see any errors. You might get a warning, at least depending on the tooling you're using, if that reference is not satisfied. But once again, definitely something to check. And this is a common cause of spending a lot of time figuring out why things didn't work. And just because you might have misspelled some link reference to some config map and it can take a while to figure whats out. The error messages you get from kubernetes are not always super helpful and it can take a while to figure out why these things didn't work. So if you can use some tool initially to validate these references, that can help you save a lot of time. Then finally policy validation policies are another kind of rule set on top of the first three here, and this can be policies related to performance, to resource allocation, to security, networking, et cetera. Or like just local. You might have policies defined by your teams around naming, around labeling, around things that are applicable more to your project than at a kubernetes level or general level. And a common technology used to validate manifest is called OPA open policy agent. It's used by a lot of open source projects out there to validate kubernetes configurations, and these policies can be applied either before you deploy. Right? So in your editor, which is the best place to do it, because that'll save you most of the time fixing those issues. But it's also pretty common to have some kind of gate or validation in kubernetes that just makes sure that you're not deploying things that don't align with your policies, which is still super helpful. Right. But it's a little bit late in the process because then you'll have to kind of go back and make changes and redeploy, et cetera, et cetera. OPA uses a language called rego, which is straightforward. It's not a super complex. Oops, sorry about that construct. And as I said, this could be used to validate anything related to resource, right? Name networking, resource allocation, best practices, et cetera. I'm going to show you in just a little while how what these policies can kind of look like, and there's a lot of them available online on GitHub. And there's also a nice vs code plugin available if you want to create your own and debug your own policies so you can really piggyback off what a lot of the existing open source tools have done, but then adapt those policies to your needs that you might have in your teams. Okay, finally you've created your manifest, you've validated them, and now you're ready to deploy. And usually deploying is something you might initially do manually. Right. You're using Kubectl or helm or customize. Eventually you're going to look into maybe automating that using CI CD or even a Gitops approach. Gitops meaning that you manage all your manifests in git, and then you have a tool like Argo CD or flux that constantly makes sure that the state that you've defined in git is actually the state that your cluster has, which is a super nice approach, but it's a bit of a maturity curve to get there. It requires that everyone's on board, so maybe that's not where you should start, but it's definitely a great endpoint to aim at. Okay, enough talk. Let's have a quick look. I'm going to use a couple of tools just to demo a little bit here. So I'm going to start by just using a Kubectl command to create a very simple NgInx deployment. And I'm going to use a tool called demonical, which is a free open source tool to have a look at that. So you can see here created this conf 42 yaml. It contains one deployment. Let's hide the file explorer. This whats the yaml that was created. You can immediately see here that there are some errors by the generated in the generated yaml. So let's just remove those because null is not a valid value by the schema. So this was the schema validation kicking in. And you can see here there's a reference to an image in Nginx image. You can also see that by default Kubectl adds an empty status property which will then be populated by kubernetes when we deploy, which we're going to do in just a little while. But I did want to show you a little bit around OPA validation. So let's go over here and let's just start enabling some OPA policies. So for example here a process can elevate its own privileges. I've enabled that OPA policy and you can see immediately here that we got an error. Let's hide this because it's a little bit crowded. So you can see the error message saying that this process can elevate its own privileges. And there's actually a recommendation that we should set security context, allow privilege escalation to false in our containers. So let's see if we can do that. Sorry, was that security? Sorry, I don't remember continuous security concepts. Let's set that to false. And now you can see that the error went away and now I can. Let's see if there's more. Let's try. Default capability is not dropped. Oops, we got another error. So we can kind of use this kind of tooling to interactively find those OPA policy validations that we're interested in and fix those before we deploy anything to our cluster. But I am going to. Oops, let's just turn that validation off again so we don't turn them all off to avoid any errors. And let's deploy this. I have a local mini cube cluster running on my machine, just going to press here, deploy. Let's put this in the default namespace and press. Ok so it's been applied to my cluster and so let's have a look at the cluster itself. So you can see here is the actual object, the NgINX deployment. Let's just filter on the default namespace. So this was the object that was applied to Kubernetes, my local mini cube cluster. And as you can see there's a lot more in here now than the initial manifest that you saw. Kubernetes has added a lot of different things. You can see that this property that we set to false is here, but it's also added the status property that I mentioned earlier on. So this is kind of what our object now looks like when it's running in Kubernetes. While obviously very different from the yaml that we had defined outside Kubernetes that we can see here. Okay, great. So we were able to create the manifest, we did some validations, fixed some OPA validation errors, deployed it to Kubernetes, and then connected to our cluster and saw that everything seemed to be up and running. All good. Let's get back here. Next step is to talk a little bit about templates. Templating is a very common need that you'll run into when you start working with multiple clusters or target environments. So let's say you have a dev environment, a staging environment, production environment, and when you deploy your different applications, you'll want to configure them somewhat differently, right? You might want to have different scalability settings, different security settings, different network settings for the same kind of source of manifests. And there's a lot of tools to help you do that. So have one source of manifests and then either kind of parameterize those or kustomize them or whatever to make sure whats, when you actually deploy to different environments, you have the values that are applicable to that environment. So yaml, there's the yaml native approach which is customized. I'm going to show that in a while it's built into Kubectl, so it's a very native way of doing things. Helm and JSON at helm is super popular, which uses a more custom templates language based on go templates. There's a couple of frameworks to actually instead of writing Yaml, you write code and then that code generates your yamls for you. Similar to like terraform would generate infrastructure. You can use things like cdks or decorate to write code to generate manifests. And then of course you can use all code related constructs that you might be happy to use when you're writing code. And there's also abstraction layers like Acorn and others to help you to kind of provide a higher level of abstraction that would then get converted of course to manifests before they are applied to kubernetes. So ultimately all of these result in a YAML or JSON manifest that is applied to kubernetes. They just help you do those in different ways. And whatever works for you and your team and what you think is best is always a good start. Talk a little bit about kustomize. Kustomize basically works by asking you to define the set of base manifests like the one that we looked at and then defining overlays or patches specific for a target environment. So I might have a base set up a deployment for base setup, and then I might have overlays for dev and production environments where I might have different replica accounts or different security settings or namespaces or whatever. And then kustomize when you apply to your cluster customize, you'll tell customize, okay, I want to use the production overlay. So it'll overlay the configuration in production over your base configuration and then take the result and apply that to your clusters. This is a very nice approach. It's Yaml native, so any Yaml tooling will work with it and it scales fairly well. Depends on your needs. Helm I'll mention that as well because it's so widely used and popular for good reasons. Helm uses a more custom templating language based on go templates and then packages those into what's called a helm chart. And these helm charts can contain not just templates, but also tests and a bunch of things that kind of turn into a package for an application. So helm is a really nice way of kind of packaging your entire application and then helping others install that application and then using what's called a values file, which once again is a yaml file as input, you can parameterize those helm templates. So a user would generally use your helm chart, create their own values file where they might specify custom ports or custom namespaces or whatever other ways you might allow your helm chart to be configuration, and then they apply those value files to your helm chart. And then helm can do its magic and take the output and apply that to kubernetes. And these helm charts are distributed through helm repositories, and there's a bunch of them out there. So if you look at artifactory or just search for helm repositories, you'll find a lot and you'll find that there are helm charts for many common infrastructure tools like databases and web gateways and game. Even Minecraft has its own helm chart. I'd like to mention a really neat practice that's been coming up lately and is about using helm and kustomize together. The workflow here is that you would use helm to package your application and then use customize to overlay any runtime configurations, right, because specific CTO your environment, because the creators of the helm chart obviously are not always aware of how you're going to deploy that helm chart. And you might have very specific needs around once again, security, networking, et cetera, which those might not be configurable in the helm chart itself. So what you would do is use helm as an initial phase and then use customize to overlay any runtime specific projects over the output of helm. Sounds complicated and it is complicated, I'll grant you that. But it's a very powerful concept because it really makes the most of both the tools what they're really good at. So definitely something exploring as you kind of venture deeper into the depths of kubernetes, deployments and applications. How do these tools fit into the lifecycle that we managed earlier? Let's just look at that here. Now, instead of jumping straight from edit to validate, there's a phase where you will want to preview, meaning that if you're using helm or customize or any of the other tools, you'll want to run those tools and get the output of them, which is what would be applied to your cluster and then run your validations on that. So you would want to validate the output of customizer helm and make sure that all the OPA policies and anything else are in place. You might also want to validate pre preview of course, but really important to validate what's actually going to be applied to your cluster and not what's kind of input to another tool, whats does something before it applies to your cluster. And I wanted to show that quickly what that looks like. Let's jump back to Monaco. I'm going to go to a Kubernetes example repository which has a customized example. This is just filter on that and have a look here. So here we can see, we start with the file Explorer. You can see there's a base folder here with a deployment, an Nginx deployment and an NgInx service. As you can see here, you can see also links between them marked out in here. And then there are overlays for dev and prod. And if we look at the overlays themselves, you can see here that the dev overlay sets the replicas to one, the production overlay sets it to five, and the excitement, the staging overlay sets it to three. So what this basically means that if I take the dev customization and preview that, so what that means is now we're looking at the output of customize for that customization. You can see that replicas here is set to one. Let's exit and let's have a look at the staging customization and preview that. And then as you can see here, replicas is now set to three. Right. And just for sake of getting it all going through everything, now I'm going to preview the prod customization, and we will hopefully see that replicas is set to five. Right. Ultimately, though, the deployment itself by default actually had replicas set to two. So if I wouldn't have used any of these, I would have gotten replicas of two. But this is a very basic example of showing how you can use customize to set different property values for different target environments. In this case, replicas for my deployment. Okay, that was a really quick demo because we are really a little bit short on time, just quick on tooling. There's a lot of tools out there. Just to kind of break this down a little bit. Here's the manifest lifecycle. We talked about these different phases and then the object lifecycle in your clusters. Kubectl is great for creating manifests and for deploying them. It doesn't really have any support for editing, previewing, validating. Of course, then it's great for updating and deleting projects running in your cluster. So that's where it really shines. Next step here would be ides and plugins. So if you're using visual studio code or intellij, et cetera, the core ide doesn't do much. Right. You're very reliant on plugins, and that's where I've put parentheses. So if you kind of cobble together a bunch of plugins, ids can do most of these things for you, right? They can create, obviously edit. That's what they're good at. Validation plugins. There's plugins for deploying, there's plugins for doing all these different things. The challenge here is that the plugins will maybe not always be very compatible with each other or up to date, et cetera, et cetera. And we're having some transition problems here. Not an issue. Validation tools obviously are great at validating. Templating tools like helm and Kustomize can help you create. They obviously do have support for previewing and applying to your cluster, and creating and updating and deleting what's already running in your cluster. You might be familiar with tools like lens or k nine s or other cluster management tools, great tools. They're very focused on working with Kubernetes itself. So if you're connecting to a clusters, you want to see what's running inside that cluster. They're not really geared at creating manifests, editing them, previewing or validating them. They have some support, maybe for applying helm charts, for example. But a big gap if you're the person that's authoring the pre deployment phase of your applications. And then there's a more niche set of tools, Monaco, which I was showing earlier. You can call them Kubernetes ides or configuration management tools or whatever, but I think the pros of these tools is that they try to support the entire lifecycle in a very productive and integrated way, right? So instead of having to cobble together all these things using more manual tools and Clis, you can just use a tool like Monocle, which is basically a wrapper for all these common tools that you're already using with a nice UI. But once again, do what works best for you and what feels most productive. Not trying CTO say anyone is better worse than another. It's all up to you and the team. Finally, some best practices. First thing, understand manifests I hope this talk helped you do exactly that. Always try to use the latest stable API version for your manifest, obviously in sync with the cluster that you're working with targeting. Keep them simple. Don't add a bunch of default values unnecessarily. It's just going to be confusing for people to work with them. Policies talked about that. Try to use policies. You might not even use a tool to validate policies, just agreeing and discussing. Having a meeting about howto work manifests and some policies around naming is super helpful and creating a shared common knowledge around how people are going to work with manifests. Use templating tools, customize helm, whatever else, whatever works. Don't use them if you don't need them because they do add a level of complexity. Validate manifests before you deploy I know there are great tools for doing in cluster validation, and many CI CD tools can validate for you. From my point of view, that's a little bit too late. You shouldn't be deploying things that have errors, trying to deploy things that have errors in them. Try to deploy as early on in your process, similar to if you're using linting for your source code. That's something you do in your ide, and preferably not only as part of CI process. That being said, you should automate validation as well, right? So you want to have the automated as more as a safety check, but try to do it early on because it'll save you a lot of time. Then finally, I really didn't talk a lot about Gitops, something I urge you CTO adopt when you've come for a new journey. If you've come through all these first seven bullets and you're happy with that, then it's probably a good time to look at. Start using Gitops. Gitops is similar to maybe like adopting agile. It's not something that just one person does. The entire team has to do it, and it does impose some constraints on your workflows, so be aware of those talk within your team so everyone's on board and go for it because it's really awesome. And that's it. All done here. Thank you so much for listening. Hopefully this was helpful. Please reach out to me at this email address or on discord or you can obviously find me in any monocle related assets online. Thank you so much for listening.
...

Ole Lensmar

CTO @ Kubeshop

Ole Lensmar's LinkedIn account Ole Lensmar's twitter account



Join the community!

Learn for free, join the best tech learning community for a price of a pumpkin latte.

Annual
Monthly
Newsletter
$ 0 /mo

Event notifications, weekly newsletter

Delayed access to all content

Immediate access to Keynotes & Panels

Community
$ 8.34 /mo

Immediate access to all content

Courses, quizes & certificates

Community chats

Join the community (7 day free trial)