About this video
What You'll Learn
- Deploy complex Kubernetes applications with Kluctl's deployment projects, targets, templating, and dependency ordering.
- Use cluster-loaded variables and Jinja templates to keep manifests environment-specific without duplication.
- Inspect GitOps and CLI deployments in the WebUI, including remote clusters and manual actions.
Alexander Block returns to walk through what's new in Kluctl: the GitOps controller for pull-based deploys alongside the CLI, the WebUI for visibility, and a live demo bootstrapping a kind cluster and handing off to GitOps.
Jump to a chapter
- 1:48 Introduction
- 2:32 What is Kluctl?
- 4:57 Overview of New Features
- 5:55 Slide Presentation: Kluctl Concepts
- 7:14 Project Structure and Targets
- 9:31 Templating and Variables
- 13:01 Deployment Order and Dependencies
- 14:33 Deployment Hooks
- 15:01 Kluctl GitOps Controller
- 18:23 Kluctl WebUI
- 19:46 Demo Time: Setting Up the Cluster
- 24:21 Bootstrapping the Cluster
- 29:32 Exploring the WebUI (Local)
- 33:33 Using the Installed WebUI
- 36:59 Deploying Sample Applications (PotatoHat Structure)
- 41:39 Deploying PotatoHat (Test Target)
- 42:41 Deploying PotatoHat (Prod Target)
- 43:08 WebUI: Viewing Application Deployments
- 43:54 Demo: Updating Configuration and Pruning
- 46:16 Introduction to GitOps Management via CRD
- 52:18 Setting Up GitOps Configuration
- 55:25 Deploying the GitOps Configuration
- 58:24 Controller Reconciliation and Debugging
- 1:03:27 GitOps Handoff Demo
- 1:08:20 Sneak Peek: Template Controller
- 1:13:46 Conclusion and Call to Action
Full transcript
Generated from the English captions. Timestamps jump the player to that moment.
Read the full transcript
1:48 Introduction
1:48 Hello, and welcome back to the Rawkode Academy. Today is another episode of Rawkode Live where we take a look at the tools that are help shaping and making the Kubernetes and cloud native ecosystem that little bit easier. And today, we're doing an update video from when we previously took a look at Clue CTL, Clue Control, Clue Cuddle, Clue Cuddle, whatever you prefer. And to give us a overview and guided tour of the new features and updates as its creator and maintainer. Kotablock. Hey, man. How's it going? Long time. Hey. Thanks for having me. Yep. Long time
2:24 ago, and quite some things have happened in the Kluctlical ecosystem. Alright. Well, for anyone who is not familiar, let's just do a little bit of context and background. So number one, tell us who you are. And number two, tell us what Kluctl is, please. So I'm Alex or known as CoderBlock. If you see me online, I'm a developer, DevOps engineer. Depends on what I'm doing right now. I'm working on on my Kluctl project mostly when I have time. It's an Opsource project providing you the ability to manage and deploy complex and simple Kubernetes deployments. Yeah. That's what I do. I'm also a
2:32 What is Kluctl?
3:12 freelancer, but I let's put it this way. If I would have the possibility to work on Kluctl all day, I would do that. But family has to be provided. Always. Definitely. Yeah. Priority. Alright. Well, thank you for sharing. So I can't remember when we did our last video, but, you know, the do you know? I think it's about a year ago. A year? Wow. Okay. Cool. Quite some time. But I have been keeping an eye on the project because it's it's just super useful. Right? Anyone who's not familiar with the last video of the demo
3:53 or even a project, I'll put a link in the comments once we get started today. But just go check it out. It's a tool that kinda tries to enable new features that just aren't possible with Kube control and I think everyone who's watched any video on this channel knows of my distaste for helm and how that we need better tooling to handle the complexities of a modern application deployment to Kubernetes. You know, let's face it. We're not getting away with 20 lanes of a deployment YAML, six lanes of a service, and then ingress. It's just not the way the applications run
4:25 on Kubernetes anymore. And Kluctl had one of those secret features, which I've been longing for for so long, which is the ability to augment template and rich those manifests from end cluster resources, which was the highlight of the last video for me. However, you've been adding loads of new features. I've been keeping a little bit of an eye on the release notes, and you've been kind enough to share the blogs and stuff in the Discord server as well, which has been really cool. And I won't give anything away. Maybe you wanna give us the TLDR,
4:52 the overview, the highlights of what we're gonna be taking a look at today. Yep. So the ham thing was kind of a motivation for me as well in the beginning, but it's very important. Kluctl is not a replacement for Helm. It's really kind of an interface to Helm and customize and more. So it's built on top of it to manage helm and manage, customize and so on. Yeah, I think maybe best is if I do a small slide where I give an overview about what Kluctl is, do it as fast as possible so that we can go into,
4:57 Overview of New Features
5:35 yeah, live coding as fast as we can. Okay. Pull up your slide, and then I'll share your screen. Yes. Give me a second. Okay. Alright. Live. Take it away. Okay. So as I said, I'm going to present what Kluctl is. Try to be as fast as possible. Best is actually to look see video that we made last year. But yes, let's do it. So what is Kluctl? Kluctl deployment Kluctl is multiple things. It allows you to define deployment projects for simple, complex, small and large deployments. It doesn't really matter. Deployments in the sense of Kluctl are not Kubernetes
5:55 Slide Presentation: Kluctl Concepts
6:24 deployment objects. They are like really the big picture, the deployments with everything. Kluctl is a CLI that allows you to deploy these deployments in a push fashion. This now the new things come. The Kluctl GitOps controller allows you to deploy stuff in a pull fashion without losing the ability to do push at the same time if you need to, if there are ever any reason to do that. And the WebUI is also new, which gives you visibility and control about your GitOps deployments and also about your CLI deployments because both are handled by the WebUI.
7:09 I'll continue to describe the projects very fast. So, Kluctl deployment projects try to be as boilerplate free as possible. That means you can always start with a very small deployment project, having the stuff that you need to do your current task. So for example, if you just need to deploy NGINX, you really just have one deployment YAML that includes one deployment item, which is the NGINX deployment being a customization or customized deployment. And that's basically it. With these files, you can already do your first deployment. Then you see CLI, yeah, just to Kluctl deploy. Very important, at this point, you already have
7:14 Project Structure and Targets
7:56 one of the most important features of Kluctl, which is templating. You can give the CLI arguments, which are key value pairs. Actually, key and the value can be arbitrary YAML, so it could be everything. In this case, it's just a string, and you can use it through simple Jinja templating everywhere, including the customization YAML, just everywhere. David, if you have questions in between on notes or something like that, just tell me and I'll stop and explain something different. Yeah, of course. Also, are built on top of each other. So, as said, you try to start small.
8:37 And then, if you realize, for example, I have a quite complex configuration when it comes to the different targets, You can then use the next feature on top of the deployment project, which is the Kluctl YAML defining your targets. And the targets are kind of a shortcut to what you would usually pass through the CLI. For example, the arguments, which you've seen before, we set environment to some value. We can do the same here through the targets. And then the idea is that instead of manually passing them time and time again, you just do a deployment on
9:12 the target. The idea is that you can also bind targets to a context, for example. So you can say that the simple target is always deployed to cluster X, while another target is deployed to cluster Y with different configuration and so on. Templating, as already mentioned, is kind of one of the most important features. It's the glue. It allows you to use configuration wherever you need it. Of course, you should try to keep it as simple as possible and not overdo the templating because everyone knows how templating can make life very hard. If you look at hand charts, for example, it can
9:31 Templating and Variables
9:54 easily happen. So in this case, let's say we need replicas being different on two different targets. We could introduce that variable. And Okay, how to explain this? Okay, I skipped one point. So these variables can be passed through arguments, since they are always prefixed with the args. But you can also load variables and configuration from files. There are multiple variable sources available. File is a simple one. You can load from git, from different branches, tags, from master, main, whatever you want. You can do HTTP requests and load configuration from there. You can use Vault, AWS secrets manager.
10:43 Azure is just being added right now and so on. It supports config maps as well. Right? Sorry? Does it can those configs not be loaded from a config map? I think we we did that last week. It can do that as well. So you can also load a YAML file from an existing config map on the cluster or from a secret, whatever you need. So you can actually have information inside the cluster to be used in the deployments to do proper configuration of your targets. For example, cluster name is a good example. It doesn't make sense to have the cluster
11:21 name in all your deployment projects or, for example, the base DNS name where everything's served on. Instead of that, you can have it in a conflict map on the cluster, and every deployment can just load it and use that for whatever it needs it. Yep. Perfect. Great feature. Yeah. Makes things a lot easier. We had that in the past where we had to copy and paste all these configuration files to all different deployments that was not very nice. So in this example, we have the deployment YAML. In the old example, it was just including the NGINX deployment. This time, it's also loading
12:00 some configuration. And the idea is that templating is really possible everywhere, so even while loading the configuration. In this case, we have the target name. If you look at the list of targets, we always have the name of the target. And we can, for example, already use it to have some dynamic configuration loading. For example, for the simple target, we would load this configuration. For another target, we would load this configuration with having different replicas, for example. And then, as described before, you do Closedale deploy, target another, and it will also give you a diff and ask you
12:36 if you really want to apply it. And then you say yes or no, and then you actually apply it. Next thing is you want to say Sorry. No, no. Was just saying cool. I don't mean to throw you off there. Sorry. Yeah, we have a little bit of lag, unfortunately. Network is really bad in this office right now. So order and dependencies are easy to master. It turned out that so this was also one of the reasons why I even started this project. If you use Helm, just Helm, you get into problems when it comes to orchestration of all
13:01 Deployment Order and Dependencies
13:16 the different Helm charts that need to be installed. There are solutions. Helm5, for example, can, I think, define order? You can also do it with Flux by defining dependencies between Helm releases and so on. In ClueCDL, it's quite easy, actually. You just have the list of deployments, and that's the order. It's that easy. The idea is that everything that you give here is deployed in parallel until it reaches a barrier. Then it waits for everything to finish that's above the barrier and then it continues with the next one. So this is all you need to have order and
13:56 dependency management. So a good example is, very often, have to deploy namespaces first, and you cannot start to deploy something into these namespaces before the namespace is deployed. Same with custom resource definitions. Selium, for example, provides some. You cannot do anything before the custom resource definitions are deployed. I mean, you cannot deploy the custom resources before the CRDs are deployed and so on. Hooks can be used to even have more advanced control about your deployments. For example, Selium, even though stuff is applied to the cluster, it's still not ready. So you might need a hook that waits
14:33 Deployment Hooks
14:50 for it to actually completely become ready. So you can also do that with Hooks, for example. So next thing is this is new since the last time we did the last video. And not really. At that time, I already had an implementation of GitOps, which tried to integrate itself into the Flux ecosystem, but I realized pretty fast that Kluctl does not depend on Flux and should not depend on Flux. And it should actually completely live on its own. So the solution was to implement the Clue Cutter controller, which now completely lives on its own. It
15:01 Kluctl GitOps Controller
15:32 provides a Clue serial deployment, CRD. The idea is that the CRD implements the same interface as the CLI. So whatever you are used to provide to the CLI, for example, passing arguments, passing tags, passing options like dry run mode or if it should wait or not can also be passed through the Kluctlesteo deployment. So it tries to mirror it one to one. Yeah, here's a list of what you can so, yeah, the target name, for example, it's in the CRD. You can define it through the CRD and the CLI arguments. Yeah. Encryption is supported and can also be configured
16:19 through the CRD. Very important, if you start to use GitOps with the Cluster Deployment CRD, you can still use push based deployments. So you can still use the CLI. And you can mix it if you need to if it makes sense, depends on your use case. In my opinion, it makes sense. For example, if you want to have a dev environment where you want to have iterations, where you just want to try something out, deploy it, try something out, deploy it. And for prod, for example, you want to have a proper GitOps workflow. So the idea is that the same projects
17:01 allow you do both. Here's a simple example of a close to the old deployment GitOps deployment asset. You give it the source, so the URL of the Git repository, some subdirectory, target name, context. So the default context means deploy to the same cluster where the controller is running. You can also give it context to actually a full kube config through a secret to another cluster. You can tell it if it should prune or not, if it should delete the whole deployment on deletion of the custom resource and so on. So you can look at the Kluctl deployment. It will give
17:51 you some basic information. For example, if there's some drift, it will do internal drift detection, like figure out if something has been changed by someone else than the controller. This is currently not implemented. I plan it for one of the next releases. Then you will also be able to trigger a forced redeployment through the CLI. Currently, it's only possible through the WebUI or through some manipulation of the custom resource. The WebUI is also new. I'm going to show it later as well. The idea is that it shows you the projects, so basically, git projects, the targets
18:23 Kluctl WebUI
18:35 and the historical results from commands that you did on these targets. The UI is not the most beautiful UI of the world. That happens when a developer does React. So if someone wants to improve it, I'm happy for contributors. Zwap UI is easy to start with. It does not you don't have to install it. I mean, of course, it's recommended to install it because then you have other features like OADC integration. But if you just want to try it out or there is no way to install it somewhere properly, you can just run it through krlutecdlWebUI
19:13 run and it will just run locally and connect to the remote cluster. Multi cluster support is implemented in some way, but it's still a lot of stuff to do there. So it's also very important. The UI is very early stage, so a lot of improvements and features will come. But it's already good enough to be of some good help in daily business. Yeah. That's it for now. Demo time. Should I directly switch to demo time, or do you want to say something or ask something first? No. Let's go straight into the XAML. I have questions, but we'll bring them up as
19:46 Demo Time: Setting Up the Cluster
19:55 we we work through the the rest of Okay. I prepared a little bit. I tried to not prepare too much. What I prepared is a Bootstrap deployment and some applications that we are going to deploy into a kind cluster, a local kind cluster. Reason I prepared this is in the previous video, I did a full setup of a project. So if you want to learn how to do that, best is to watch that video first. And here, we assume that you already know how to do that or at least know how to figure out how
20:31 to do that. So let's open the terminal. As said, I'm going to deploy this to a local kind cluster. I have some configuration here for the kind cluster, which is a one control plane to worker node setup running locally in my Docker setup. To showcase the capabilities of Clue CDL, I decided to not give it a CNI and disable KubeProxy completely. That means we get a naked cluster. It's not completely naked because it still has CSI installed, but at least there is no CNI, and that means it's actually useless without doing proper bootstrapping. Let's create a cluster.
21:21 Of course, I'm in the wrong folder. Okay. So you can ask your questions in between while we have we will have some waiting times when stuff starts up after bootstrapping. Yeah. Well, I'm a big fan of people deploying useless slash broken clusters. So, you know, always fun to see. Now you said that let's go back to the flux stuff you were talking about, Eric. You said that Kluctl tried to kind of integrate there, but you decided that it should be a dependency about your own controller. Yep. I mean, I'm just curious. Like, that's that's a mission. Right? Like, even
22:07 using something like controller runtime is still a lot of effort and work that needs to go into this. And as we've seen from the example output, it does drift control and status checks and all of this like Yep. So what realized is that all the controller related stuff, it's not that much actually because the real work has gone into CluSDL itself. So all the drift detection, everything, all the features that are in some way important is already implemented through Kluctl because all the features that you get through the GitOps controller, you already have them through the CLI.
22:44 So there was at that point, it was not so much effort to implement the important features. There was one dependency in regard to Git repositories. So Flux uses dedicated CRDs for source management. So you have your Git repositories to actually load the code, and then you refer it in your customizations, for example. And that's, for example, something that is not really comparable to Kluctl because Kluctl does its own source management or source control. It does its own checking out of and cloning of repositories. It has git include. So if you have maybe you remember the list of deployment items,
23:32 So far, just had path entries, but there are also git includes possible. So you can load git repositories and have deployments scattered around through multiple repositories. So this was all stuff reusing stuff from Plux would not give any benefit because I would still have to do my own stuff inside ClueCL. In the end, I decided to completely go on my own in that regard. Unfortunately, I don't have an example of getting oh, I actually have. Maybe let's jump to that first before you can oh, no. Let's do the Bootstrap deployment. And while all this starts up, because it
24:17 takes some time, I'm going to explain the Bootstrap deployment a little bit. So as said, we now have a naked kind cluster locally. It's not completely naked because it still has CSI, for example, installed to local pass provisioner. CoreDNS is preinstalled, but it's all not running because the nodes are not ready. We have three nodes. They are all not ready because the networking is just not up and running. With the Bootstrap deployment, we can now just run ClueCDL Deploy. It will do a dry run first. The dry run, in this case, fails because it cannot dry run stuff if some stuff
24:21 Bootstrapping the Cluster
25:00 is missing. For example, the namespace has not been created yet, so it can try to simulate some of that stuff, but it's not perfect. So even so it tells me there are errors, I know that if I actually apply it, it will work after some time. So I said, yes, we are going to deploy this now. What's happening now is it has applied already a few resources, and then it encountered Helm hook because Helm hooks are fully supported and now waits for the hook to finish. You should be able to see that on the cluster.
25:33 So if you look at the pods so you already see, Cilium pods are starting up. The Hubble generator job is already running, which is the hooks that we are currently waiting for. And as said, this will take some time until all this is green. So maybe jump to the git includes that I just mentioned. So the Bootstrap deployment has multiple deployment items that are being installed. Selium, then it does the barrier. Selium wait is a just a small pot that is kind of to so that the deployment knows the cluster is really up and running because
26:21 when the first pot can be started, we know everything is fine. So I use a simple hook to make sure that we don't continue before it's really up and running, the cluster. Some namespaces. In this case, just the Ingress NGINX namespace that we can later install the Ingress controller. We have a barrier in this case because we cannot install the ingress controller before the namespace is actually there. Then we have cert manager. I'm installing it, but I'm not really using it in this example because I don't have external DNS setup and everything. But yes, maybe it's a good example to just
27:02 show that we do Helm here, for example. So SAP Manager is actually a deployment item that pulls in a Hound chart. We give it the repo, chart name, chart version, release name, namespace. This is I'm not going to explain this part. The good thing is you can use templating here already, at least partially, not everywhere, but partially. For example, I could here already do some fancy templating to have a dynamic namespace, which we actually will do later. So what do we have here? Yeah. I prepared the bootstrap deployment two hours before the session, so it's not perfect.
27:49 When in run it again. Sorry? When in run it again. Exactly. And it tells us two objects are missing. The SelumNetworkPolicy did not finish for the template controller, which I'm also going to show later. The ingress did not finish. Probably, it actually told us the the webhook of the ingress controller was not ready. So I forgot some barrier or some weight readiness there. So as you already said, let's just retry it. And this time, it should actually just start up. Yes. So it looks healthy now. Yeah. It's now again waiting for the Selium weight pot.
28:36 And it's finished as well now. So yeah, it looks good. And now ingress controller is being deployed. So the hooks are actually rerun. And we are done. Everything is green now. In this case, I didn't check why it's happening. Cellium is adding some labels into deployment that I don't know why. I didn't check why it did that. But I can see it. That's already nice. So I know something is interfering with my deployments, and I would be able to debug that now. So we have a usable cluster now. Very important, we have an Ingress controller and
29:25 we have the ClusterDealController running. I'm going to show the ClusterDealController later. What I can show already now is the WebUI. As said, you can just run it locally via Kluctl dot slash WebUI run. The default port is already used, so I have to use another one right now. And there it is. So it's just using the current context, connecting to the cluster, reading all the necessary information, and it already knows that there were some command line invocations, the ones that we've just seen. And we can get some information about it. For command line information, there's for command line
29:32 Exploring the WebUI (Local)
30:08 invocations, there's not much information available. But what you can see is at least what has happened. As an example, what you have just seen in the CLI output can also be seen here. So the diff with the strange IDs being replaced. We see that the two new objects have been created that we've seen. And we would see basically everything that we see in the CLI here. You can also see ODA results. This is the first invocation we had. We see a lot of new objects. No changed objects. We can also open the complete project here
30:49 and see all the rendered objects, applied objects, on cluster objects and so on as an example. Let's see. What do we have here? Here's some config map. And we see this is the version that was rendered. This is the version that got applied. This is the remote version before we applied it, so you can do some debugging here to figure out what happened. Yeah. Any So because this wasn't installed, the way that this is working right now is that if you, on your local machine, have access to the Kubernetes cluster and enough permissions to be able to read,
31:30 I guess, the clear control custom resources, the status fields, and so forth, then it's able to just represent all of that on a UI and you can just view it. But like you said, like, you don't get the OIDC integrations. If you need a privileged user locally on your own machine to be able to access it. Okay. Yeah. I love that it shows the command line implications, and it's not just restricted to the clear control deployment CRD, which is pricey. That's what I tried to explain. The all the functionality of Kluctl is part of Kluctl
31:59 itself. It's not part of the controller. The controller is really just on top of it, like an interface to what it already provides. So it doesn't really make a difference what caused these deployments. It's the same in the end. Regarding the Z Chelsea command line, there are some improvements that are planned because if you have a lot of deployments and we have clusters with a lot of deployments where we also do a lot of manual stuff because in daily work, it's required for us, it can the command line cards can kind of it gets too much.
32:39 So there needs to be some some improvements and filtering capabilities and so on. With regards to the command line stuff, does it tell you the user? I know Kubernetes doesn't really have a concept of user. Right? But it does have, like, token, has authentication. Has any of that propagated into the history? No. Not yet. And I'm not sure if that's even a good thing because data protection in at least in Germany and the EU, not sure if they would be happy with the I don't know. I'm not a lawyer, so I don't want to put personal information into some clusters.
33:20 Doesn't feel Makes sense. Okay. So I've shown you the locally run version now. I can also install it, as explained. The Bootstrap deployment actually does that. So we have a Kluctl include here. Or maybe I can the list of deployment items has different types of deployment items. The most basic one is referenced through path, which is just a list of manifests or it can be a customized deployment or it can be a hound chart that is being installed. Then there are includes. Includes means the path that I provide here contains another Clue CDL deployment. So you can kind of
33:33 Using the Installed WebUI
34:09 continue here the same way you did in the root deployment. You again have a deployment YAML, and you have a list of deployment items, and you could have the simple items with the path here again. That's what we have here, for example, and so on. So you can have it as deep as you want. And the idea is that if you have configuration values loaded, you can pass them into sub deployments as well, as deep as you want. And at any level, you can introduce new configuration that is based on the one that was passed before
34:41 and so on. So you can do some nice things there. In this case, we have a git include. That's what I mentioned before. This one is pointing to the public Kluctl repository into the subdirectory install controller, which contains the Kluctl deployment that has all the necessary stuff to deploy the ClueSlide controller. Same with the WebUI. This gives the basic installation of the controller. For the controller, that's enough, actually. It doesn't need anything else. The WebUI, because it's a very plain deployment with just a service and no ingress and stuff like that, I think in most cases will require some
35:22 additional stuff, which we see here. So we have an ingress also deployed after this, which just gives us the web UIs through the ingress controller. I'm using local host TV, which always resolves to localhost, so one dot seven zero zero one. So if I go to that URL where is my Chrome browser? Why does it not work? Okay. I first have to go to the console and then it works. I have just oh, okay. It's already working. Great. So this is the UI installed to the cluster. If you install it without OIDC, it will create some basic users, two users, one admin
36:11 user and one viewer user. We are going to use the admin user. The password is, by default, pre generated by the WebUI itself and written into the WebUI secret. And, yeah, you see the same as before with the difference that you can log out now. So for now on, I will use the installed version instead of the local version. Cool. What else? So, as explained, we now have a basic cluster up and running. We have bootstrapped it. Oh, what? No, I do not want to move. Okay, so we have the bootstrapped thing. Now the idea is,
36:59 Deploying Sample Applications (PotatoHat Structure)
37:01 of course, that's not enough. You, of course, also want to have some applications deployed to it. I prepared two applications, Podinfo and PotatoHat, which we are going to deploy now. Let's start with maybe Potato Head. It doesn't really matter. This one is using plain manifests everywhere. So we have a root deployment that includes the sub deployment of potato services. This one has some simple deployment items with customized deployments having plain manifests with some templating, not too much, just the stuff that is really necessary. Sorry, I need to change something. Yeah, plain manifest, nothing special. Namespace again
38:02 with order being properly managed through a barrier. And another special thing, I called it the template service. This is a deployment item that has a little bit more of templating. And the idea is that you can include this one multiple times with different configuration. So the original potato services project has, I don't know, maybe like seven microservices, and each one has its own folder kind of containing the same files. And I changed it to have just one template manifest folder, and I'm including it multiple times. So for example, for the hat, I am including it,
38:47 giving it some configuration. As said, on any level in the deployment, you can introduce new configurations that are then available from for the deployment in question and all the sub deployments of that. So here, for example, we give it this configuration. Then we have the leg deployment, left leg and later the right leg. Some conditionals can be used. For example, if you just want to have legs when legs are actually enabled through the configuration. So if this would be false, this would be completely skipped. What do we have here? Just an example that you can also use JSON because it's
39:28 a subset of YAML. Makes things shorter in some cases. Yeah. Oh, maybe the configuration, a little bit. So this one is using a pattern that I really like. We have some common configuration loaded through the root deployment. The common configuration, for example, gives us some configuration about the replicas for the different microservices. It tells us that legs are by default enabled because we need legs. Here, we have some image configuration, which can, as you can see, pass from the outside world as well through the -a argument. Base DNS, which we are then using in ingresses.
40:23 Then the idea is that after loading the command configuration, we can load more specific configuration. And as already explained before, we can already use templating here. So, for example, we say that the config file with the name envtype is loaded here as well. The idea is that this is merged. So this one is loaded, building up the templating context, then this one is loaded. This one can already use everything from the first one. So everything that was defined here can be used here. And everything that this one defines that was already there is overwritten, so you can stack it on top of
41:01 each other. So what do we have here? We have the non prod deployment, which just overrides the hat replicas. Maybe we need some more hats in non prod environments for whatever it is. We don't need legs. And for prod, we say front end should be a little bit more replicated. We can also change the image here, which is overriding what we've defined here. So you can do whatever you want. It's completely free to free. Cool. So I think I explained enough. Let's deploy that thing. This one has currently defined two targets, test and prod. They are currently deploying to the same cluster
41:39 Deploying PotatoHat (Test Target)
41:50 to the same context, which is the one configured right now. I could also say that the context is fixed to, for example, this one, which is the same right now. But I think you can imagine what I could do here. I could say that, okay, this one should always go to this context and so on so that errors are not happening so easily. These are the arguments that you have maybe seen here already, which are being overwritten. And, yeah, let's just do it. Again, it tells us what it will do, a lot of new objects.
42:24 We are happy with that. We say yes, and we see them appear. A lot of potato hat services. And two hats. And two hats, yeah, as promised. I can also do a prod deployment now. Maybe one important thing is the namespace is templated, so we can deploy to the same cluster multiple times just by using the target name as a prefix. And now we have another potato head. I'm not going to open the ingress now because it's nothing nothing special here. Or do you want to see it? No. But I would like to see the
43:08 WebUI: Viewing Application Deployments
43:08 web UI again. Oh, yeah. Sure. That's actually more interesting. So more command line entries. So this is still the cluster bootstrap. Nothing has happened here. But we see that there is a new project with tune new targets, prod and test, both invoked through the command line and actually see different amount of new objects. That's probably because one has lags enabled and the other one not. So if you would check this, we would see that this one has lags and the other one does not have lags. Now maybe to showcase the UI a little bit more,
43:50 let's actually change something here. Let's say non prod has now three heads, and we need some legs. So we realized not having legs is a bad idea. So I'm redeploying test again. And as mentioned before, it would show what it's going to do. It tells us four new objects. One has changed, and this is the diff of the changed objects. This is what you would have expected. So we say yes, and now it confirms this is what I actually did. And the UI is not popping up again. And here, we see another card on top
43:54 Demo: Updating Configuration and Pruning
44:33 of this one here, and we see four new objects and one changed object. We can see the legs have appeared and the replicas have been changed. We can now also undo what we did here. And now it's also very interesting. We have created new objects, and now these objects are not in the deployment anymore because we changed the configuration in a way that makes them disappear. That also means we usually want them to get removed from the cluster as well. Kluctl edu will detect that these objects are orphan and ask you actually, not now, but I can do a prune
45:14 call afterwards to actually clean up the cluster. So Bart, we can see replicas back to two. We say, yes, we are happy with that. And then we also say we actually want to get rid of these orphan objects. And then they are gone. And the UI will then show us that two commands have been invoked. This is the first one where we see the replicas. It tells us even though it did a few changes, it also detected a few orphans. But we then immediately handled that situation and deleted them through the prune invocation. Nice. I like that.
45:54 So let's keep it this way with the potato hat. Yeah. I think I have shown enough when it comes to the push based stuff. How do you think? Yeah. That's great. Definitely. Okay. Cool. Then let's start with something new. This is something I have not prepared. I'm going to do it on the fly. The good thing is you can manage ClueCDL deployments through ClueCDL. Makes sense because why not? So what we are going to do now is define Is that mean can do a handoff, like where you do ClueControl deploy locally, which has a ClueControl deployment that then brings
46:16 Introduction to GitOps Management via CRD
46:43 itself under management. Right? Exactly. That's what we actually do all the time. So we have kind of one entry point into GitOps. We deploy it once, and then GitOps takes over. So let's start with the podinfo deployment this time. Let's open the documentation and figure out how to do that because I cannot remember by myself. I think I have it here already. So kluctl.io is the website having documentation and examples and blog posts and tutorials. And, of course, also the documentation for the GitHub stuff. So let's take this as an example and put it in here
47:29 and go through all the individual fields. So this is pod info interval. Let's have a smaller one so that we don't have to wait that long. Let's use this Git repository, but we use the HTTP version, HTTPS, I mean. And the path is an apps podinfo. In most cases, we just have the path submitted because we have the deployment on the root level already. Timeout means how long to wait until cancel everything. This is very important if you are waiting for stuff. For example, the cluster bootstrap would need a higher time out, if you would like to do that.
48:26 Let's deploy the target test first. Context is default, which means deploy to the cluster or the context that we are currently running inside. Is default the default value? Can you just delete that lane? No. In that case, it will use the context defined in the project. In that case, I think there is no context defined. So let's assume here there would be a context that would use this one, which will not work because the GitOps controller does not know about that context. You would have to explicitly give it a kubeconfig that has that context. In most cases,
49:06 we don't do that. In most cases, we just deploy to the default context, which means into the cluster we are on right now. We have one special case where we have a cluster API creating clusters and then bootstrapping the workload cluster that is being created with the help of the kube configs that is created by Cluster API. So that's the case where, for example, we would actually give it the real context name and a kube config Config with a secret ref and key and so on. It's a little bit like what you know from Kluctlx maybe
49:41 if you want to support multiple clusters. Yeah. By default, pruning is disabled. Deletion is disabled. Let's ignore this one. I'm going to explain that later. But it makes sense to enable it. It's disabled because it's really dangerous if you don't know what you're doing. If you make a mistake, you can easily just delete your whole cluster. I think everyone who does GitOps has made that experience in the past, and it's painful. So default is to be on the safe side and be very explicit about these dangerous things. And I think that's it. So you asked for the handoff. We could
50:24 do that. I could put that into the podinfo deployment, for example, and send to the handoff, but it would be a little bit more complicated. So let's, in this case, do it a little bit easier. Let's have its own deployment. What I like to do is have a directory structure, for example, clusters. Then we have directories called like, the clusters are named. And what you can then do is deployment. So, we can do now something like clusters target. Name. And now, we can create new clusters based on directory names. But we, of course, still need the targets,
51:27 so let's have a target named kind, kind. Oh, wait, let's oh, yeah. That's what I did, actually. We need a discriminator, which is just let's say GitOps. As the discriminator is used to so everything that is created by Kluctl gets labels attached that allow it to identify everything that belongs to this deployment. So actually, it should be something like that. So if you have multiple targets, for example, you need different discriminators so that pruning actually identifies the correct objects that need to be pruned from a target or a deployment. It's optional, it's recommended because without that, you
52:14 cannot do pruning. So let's put this into this one now. And I think that's it. We now have a deployment that is responsible for Clusidl deployments. We can do the handoff here as well now in a different way, but maybe let's do that later. So let's go into GitOps. We should now be able to what is wrong? File is not a directory. So what did I do wrong now? Kluctl dot Yamal. Oh. It's in the wrong directory. Right? Oh, no. Looks like No. It's not it's not the correct one. So Kluctl dot Yamal. K. This must be a very stupid mistake.
52:18 Setting Up GitOps Configuration
53:29 Oh, yeah. Oh, your target name? No. No. It's okay. I thought it was supposed to be kind prod, but maybe it's kind kind. Yeah. In this case, we are referring cluster names. In this case, I just have this one. Because we are managing GitOps on cluster level, that cluster can deploy multiple targets and so on. But it's all up to you how you want to manage this. What is wrong here? Missing resource meter data. Oh, wait. You've called the failed Kluctl dot YAML, not dot Kluctl dot YAML. Mhmm. Okay. Did it start with a dot?
54:21 This one started with a dot. Yes. Alright. Okay. Target kind kind. I don't get it. Why does this not work? Let's okay. So it's already on the root level. Dot Kluctl dot Yamal. Yeah. This is really stupid right now. Deployment. What the okay. As assumed, it's a very stupid mistake. Then if I do workday, because I didn't spot it. So, yeah, easy one. Oh, we already see I made a mistake. I deployed to the default namespace, which is usually not what you want to do. Let's use the Kluctl system namespace. Very important, the controller uses service accounts
55:25 Deploying the GitOps Configuration
55:42 for RBAC. So if you deploy if you add a Clustered deployment to a namespace, it will, by default, use the service account of that namespace to do the actual deployment to the cluster. You can override that by giving it another service account name, but usually, you don't need that. This means that I cannot use the default namespace, for example, because the service account doesn't even have the necessary permissions to do the deployment. I could introduce that by introducing a special service account with all the necessary roles and bindings and so on. But to make things
56:17 easier, I'm doing it this way now. So now we see it's in the correct namespace, and let's go for it. No error. That's always good. And something has happened. That's not how I wanted to show it, but we see that an ingress immediately appeared. So on K9S, we should see the Kluctl deployment object now. And we see some information. We see the name. Dry run is disabled. It was deployed a few seconds ago. It's not ready. It will only become ready when all the deployments are green, which will happen maybe in the next reconciliation loop. So when one minute is over, it
57:02 will probably turn ready. Yes, we already see it here. Validate has failed. No drift, which is good. And let's see the same in the UI. And what you see here now is a new project appearing with a target, the podinfo test, status information and the deployment that happened in the controller already. And here, it's the same. We can see the changes, some new objects, nothing special. And now, as mentioned, next reconciliation loop turned its green because all the pods are ready now. We can do some stuff with that deployment now. For example, we can force a reconciliation.
57:46 So it's happening before the one minute has passed. We can tell it to validate now. We can tell it to deploy now. In this case, nothing will happen because nothing has changed. It tells us result is empty, nothing happens. We can prune, but again, nothing will happen. If we need to do some very strange stuff and we are afraid that GitOps will kill us, so for example, some refactorings in secret repositories, we can always suspend the deployments, so nothing bad will happen. We can resume it again. And yeah, now let's actually do some changes. Actually,
58:24 Controller Reconciliation and Debugging
58:30 let's do something different. So we have podinfo test. Let's also introduce podinfo prod to the same cluster. I'm not going to rename this one because deleting and recreating this one means that due to the delete being true, stuff is actually getting deleted and recreated, which in this case is probably Okay, but let's not risk that. So prod, and I think that's it. It tells us when new object is being created. Yes. And in the UI, we should see it appear. And we see another target, the prod target, having some new objects and so on. I
59:27 think we can in this case, it maybe makes sense to actually show the ingress. So we have the test pod info and the prod pod info, test and prod. Let's open this one. I have to switch to HTTP because and we have a green one, and we have a blue one. And this is simply because we have the same setup here, where we load some configuration based on ENV type. And here, we just change the color depending on prod or non prod. So prod uses the default configuration and non prod overrides the color to be green. So
1:00:11 default configuration is to be blue, which comes through this one. What else can we show now? Yeah. Let's actually do some changes. So let's say let's say we want reds on non prod, and we want replicas on props to be different. Okay, I made it a little bit unnecessary complex here to showcase some stuff in the past. We can also override that value through the ARCs. As I described, the Kluctl deployment is just an interface to the CLI. So I can also just say not an interface to the CLI, but it has the same interface as the CLI.
1:01:09 So we know we can here give it podinfo replicas, and let's say we want three replicas. Let's hope this is not the default because then nothing will happen. Yes, it's not the default. So what we did now is we changed the non prod deployment. We did not touch the prod deployment, but we changed the GitOps object for prod, which means it still has an effect. Hope it's not too complicated what I'm doing here. Let's just do a VIP commit. And if you wait a minute now, we should see that the WebUI will update both, actually.
1:02:02 But as I'm I don't want to wait, I'm telling it to reconcile now. Nothing happens. Oh, okay. No. Okay. No change. Oh, actually, it didn't change. No wait. So test has been deployed. Something has changed. We can now verify that it has become red. It is already red. Funny. So it reloaded itself, actually. Interesting. This one, it's interesting that this one has no effect now, even though it should. Let's force the deployment. Didn't do anything. Interesting. I might have missed something. So is it really correct what I'm doing here? So common setting says axe pod info dot
1:03:01 replicas. Did actually no, I actually have to deploy that, okay. So I made a thinking around now. I assumed that changing this would actually already have an effect on the GitOps deployment. But as the GitOps deployment itself are not managed by GitOps right now, I could introduce that, but maybe that's too much for now. Of course, nothing's happening. Yeah. Yeah. Yeah. Okay. Yeah. I get it. I mean, you could do it. That's what you asked with the handoff. I can now act maybe let's do it. Why not? Let's have a GitOps YAML. Call it GitOps
1:03:27 GitOps Handoff Demo
1:03:48 GitOps target is kind to kind. Contact is default because we are still deploying to the same cluster as the controller is running on. Let's do pruning and deletion. And very important, I now really have to commit and push it first, because if I deploy that, the controller will delete everything immediately because it's not in Git. That's the fun part about GitOps sometimes. So now I deploy it once to activate the GitOps deployment. So we now see there is a new Kluctl deployment being the GitOps deployment. The other one has changed now with the thing that I was confused about.
1:04:35 And we should now see so prod has been deployed, nice. Replicas has been changed, as expected. Of course, we will not see anything different here now. And we should see the GitOps deployment. Nice. It tells us that there is a validation error. Ah, okay. When it did the validation, the reconciliation was not ready yet, not done yet for the new for one of the deployments, so it tells us. So it's red now. I need to drink something. Very cool. So now, if I would have done what I did before, it would actually happen. So if I would change the pod info, Kluctl.com,
1:05:22 then stuff would actually happen. Not sure if I should showcase that now. By the way, how long are we already streaming? Like, an hour? Yeah. An hour. What do you think? How long should we continue? I mean, I have change and then we'll see what happens. Okay. The one thing that's popped into my head, right, is that, you know, when it comes to the handoff, I probably want as few pieces of YAML as possible. Now I know that in GetOps clusters can kind, we've got the GetOps.YAML, the pod info prod, the pod info test. But, I mean, I could just have one
1:06:03 global deployment that does a whole bunch of includes. Right? And then I don't have to Yeah. Yeah. So for example, we started with having a lot of Git repositories being involved, doing hand off, hand off, hand off, and it can get really hard to follow, let's put it this way. We've just seen a very simple example. We changed something and we're very confused that nothing happens. And this can become a lot worse if too many Git repositories are involved that, at the same time, are deployed through Clusively Deployment Objects. So the other way is, as you already mentioned,
1:06:44 just using git includes. So you have one entry point, and this one is doing everything. But it all depends. Sometimes deployments take so long that you actually don't want to mix them with other stuff. So it really depends on on your need. Yeah. I guess it it depends where your risk appetite is as well. Like, if you just wanna automate everything and you'll lower it, then sure have one. But maybe if you wanna minimize the blast radius for errors and having multiple CRDs, multiple deployments and isolating them to either get repositories, CRDs, whatever is a better approach. My
1:07:21 risk adversity is low. I don't care if I blow up my production cluster, so I generally just go for the was the minimal amount of Yamal I need to approach. Yeah. This is cool. Like, we've seen some really come up to the project. The web UI is great. I know you were kind of self deprecating yourself and say this is what happens when a developer does a design or a UI, but to honest, look, it's super functional. And it does does exactly what it needs to do. It shows you the changes and it gives you the ability
1:07:47 to interface with the controller for the revalidation, for the reconciliation, drift detection. Like, that is just perfect. The controller itself is doing its job in the background. Like, these are some wonderful updates to an already pretty fantastic project. So I I applaud you. Good work. Thank you. So I don't know if you have anything else to show, but maybe if you don't, you could just tell us like, what is what's next in your wish list of ideas for click control? Where are you going? What's going to be happening? Yeah. Take it away. So I had
1:08:20 Sneak Peek: Template Controller
1:08:23 I planned to show more, especially the template controller, but this will take another thirty minutes or so. Maybe that's already too much for this session. Maybe just a few words about that. Yeah, sure. So in the ClueSlideal ecosystem, there's also the template controller, which is independent from the ClueSlideal controller, so you can install and run it on its own without any dependencies into Kluctl. And what it allows you is to take arbitrary on that page? Sorry. Sorry? Can you zoom in on that that YAML? Do what? Zoom. Make it bigger. Zoom? Sure. If I figure out how to do that.
1:09:08 Command plus. Command plus. Yes. Finally. Perfect. Thank you. So, yes, the idea is the object template takes a matrix of input resources, which is whatever you like, for example, a config map or a secret or a Clusiddial deployment or a Git projector or GitHub comment list, GitLab and so on, and take a list of templates and then use templating to generate an arbitrary set of other objects. It has multiple use cases. The original use case why I started that was to have something like preview environments, a little bit like what you know from application sets from ArgoCity.
1:09:56 So, for example, you have the git projector object, which internally clones the git project and makes parts of the repository available through the status of that resource. So if you apply that, the resource will get the status populated with, for example, a list of branches, a list of file contents, whatever you configure it. Based on that, you can use that as the input into the object template and tell it to generate, for example, Clusidl deployment objects based on the list of branches that you found in some repository. This basically allows you to do preview environments
1:10:45 depending on the repositories branches. You can do the same, but based on GitHub pull requests. So instead of reading branches in Git repositories, you can also tell it to use the GitHub API to get a list of pull requests and, based on that, create preview environments. Then you can use GitHub comment objects to actually post some comments into the pull requests that you just listed and templated and so on. Yes, the idea is that you can build up your whatever you need in regard to dynamic creation of environments. So this is one use case. It's a pretty complicated use case.
1:11:39 It needs a lot of YAML to set it up, a lot of these thingies. But in the future, I hope I can provide some good example starting points how to implement preview environments with that. Another use case is transformation of secrets or other types of objects. For example, if you have some operator that creates a Postgres password and username, you might need that information somewhere else in a JDBC URL, for example. So you can use that as an input and create another secret that has a different form of that secret, which is very helpful, especially for cross plane stuff
1:12:23 or the AWS Kubernetes operators and so on. Wow. So, yeah, that's a sneak preview. Maybe we can, if if you're interested, have a session just for that topic. Yeah. Definitely. I think what would be really interesting for us to do is obviously just to get another session where we show the preview environment based on a new pull request and the comment and stuff like that. Yep. But then, you know, the first time that popped into my head as soon as I've seen those those list of kind of I don't know if you got them plug ins
1:12:55 or extensions, but like how difficult would it be for me to integrate that with another source? Like, could I build preview environments based on tweaks? Like, I think we could have some fun than random shit there. Definitely. The idea is really the object template, so the most important resource that this controller provides, does not care what it loads. It really here, it can load everything. So if you come up with a controller operator that loads tweets, you can use the result of that here without any the template controller. Okay. I'm on it. I'm gonna make that
1:13:35 happen. Nice. Alright. Cool. Okay. Let's pop back over. Mhmm. Yeah. Alright. We covered a lot there. I had no idea, but that that last set of features either. That's that's wild. I can't believe all that already exists. And it's only been twelve months since we lasted the the demo. So again, great work on this project and it's it's just nice to see a bit of alternatives, but not just alternatives to this to this call, but super powerful and flexible alternatives just to score. So cool. Alright. Is that coming soon? Is that already available for people to play with? And what what
1:13:46 Conclusion and Call to Action
1:14:17 else have you got on the the pipeline for Kluctl? So all this is already available. It's all released, all usable. All Kluctlr related is, I think, quite stable, so I'm confident to use it in production. Template controller, yes, you can use it, but it's still alpha, I would say, but still already very powerful. So what's in the pipeline? The WebUI needs a lot of improvements. The problem is I'm not a UI designer. I'm also not good at HTML, CSS, JavaScript and all that. I can do the most basic stuff, and it was with the help of some freelancers that I
1:15:02 hired. It was enough to implement the WebUI. But there's a lot that I wish that I could finish in the next months. For example, multi cluster support so that you have one single instance of the WebUI managing and visualizing all your clusters. That's something. What else? Yeah. Most of the stuff, Kluctlr related, is actually just details, like small features that need to be added. I know you are asking for OCI integration since quite some time, so that's maybe something I should actually tackle, and it's not so complicated. I just need to find time for that.
1:15:49 And it's Yeah. Just to context Sorry. Hey. Just to add context to that. Like, the reason that's important to me is that I'm a big I I use a lot of mono repositories. Mhmm. And I like my Kubernetes YAML to live as close to the application itself, which means I have a mono repository with dozens to hundreds of services all with their own YAML. And sure way that I could have Kluctl pull in the entire model repository. And I'm sure it does some great caching and only fetches the latest version and stuff like that. Because
1:16:20 I just don't want all that code hanging about in the cluster even though it's all public either. I think OCI is a great way of being able to keep the developer workflow happy and still satisfy the machines at runtime. So, yeah, I would love to see that feature. I know. I said it's in my head, I have it kind of solved. It's really it's not complicated. But the time. I mean Of course. Currently, the state is still, when it comes to developing and maintaining the project, it's mostly me. Some it gets some checks. Some people are
1:16:57 showing up and implementing smaller features. I hope it gets more. I need support as much as I can get contributors. So, yeah, time is the limiting factor. It would be just me deciding that I would just work on Clue CDL. But Well, hopefully, the people that tune in to the previous episodes on this episode, their interest has peaked. They can start to adopt the control within their teams or organization, and of course, contribute back whenever possible. So definitely get involved and check out the GitHub repository. Is there anything else you would like to share with us before we wrap up today's
1:17:37 session? Can you repeat? Is there anything else you would like to say, share? I don't know. Before we before before we say goodbye. I think I've said said all. Alright. So thanks for having me again. Thanks for listening. I know people get out. Definitely my pleasure, and I hope that everyone else that watches this is excited by the project as I am. Some fantastic updates, and I can't wait to do another episode and whenever that's gonna be. So we'll we'll work that out on a Discord. But Yep. Thank you for joining me. Thank you for everyone that's watching.
1:18:15 We'll be back again soon, and have a great day. Thanks. Bye bye.
Technologies featured
Meet the Cast
Stay ahead in cloud native
Tutorials, deep dives, and curated events. No fluff.
Comments