 That's perfectly fine, right? Yep, looks good to me. Okay. All right, take it away. Yeah. Okay, so welcome to this presentation about Kubernetes operators, but in this case, in Java. So for some of you that are already familiar with operators, probably you are familiar with the breakers meeting goal. And in this case, we are going to touch the creation of an operator in Java. Also, let me also introduce these operators concept for those of you that do not know still what are those operators things that some people are talking about. So let's start. And welcome my special guest today that it is, well, here we call it super radon. And I think for you it's, well, independent on where you're living, but probably it's mighty mouse. Well, when I was a very small kid, I liked a lot this, this cartoon. So this is a bit of contents of what can you expect from this presentation? First, I will introduce myself, obviously, because most of you do not know me. And then which are the real expectations about the talk. And then the main problem. So the main question that every presentation should try to solve is exactly what we want to solve. In this case, operators is a way of doing it, but which is the real problem that we want to solve. Then I will introduce what are operators briefly in the process of creation, testing, publishing and executing an operator. And then I want to also to wrap up, just giving to you a bit of a list of references that what you can use in order to expand your knowledge as I did. And obviously, thank you for being patients. During this presentation, you will see several computers that for some of us, they have been very present on our lives. This was one of the first computers, not exactly this one, we will see the concrete one that I had when I was 14. But, well, these are very emotional computers. So, who am I? Well, I'm Java Champion. I am also a co-leader at the Barcelona Java User Group. Also co-founder of the JBC and Conf is a Java conference that happens every year. And this 2022, we are going to have our seventh edition. And I'm working as a software engineer at Red Hat in the Key Cloud, Cloud Native Distribution Team. You can find me in all those links. So Twitter, you can follow me and I usually post things about technology, Java, Cloud, Red Hat, and also sometimes complaining about politics or the weather, you know. Also, you can find my email where you can send me questions or doubts. And my blog post where you can find also some posts about testing in production, but in a CI environment, also migrating an application from Spring Boot to Quarkus and other stuff that probably can be of your interest. And also my GitHub account where you will find my personal repositories and also my Red Hat work that it's also, everything is public there. So, what can you expect about this presentation? Well, basically it's my experience. I will talk about what I suffered, what I discovered, what I learned just creating an operator in Java. And also you are going to receive an introductory knowledge so we are not trying to go super deep into the operators because I don't have time. And, but you won't find a magistral lecture or the way. So, it's only a way, it's my experience including my good decisions, my bad decisions. Well, in the end, there are no bad decisions. At least this is how I feel. There are decisions and there are results expected and not expected. So, I had several non-expected results too. And I will tell you about all this process. That's a very interesting computer too, wow. Okay, so what is the problem that we want to solve or in our team what we wanted to solve? So, let's imagine that you have an application that you want to obviously publish in communities. You want, if you want to distribute this application easily to possible consumers, well, you have several markets, but well, one is operatorhab.io. It's a place where several operators are together. So, your possible consumers will be easily installing your application. So, this is one step. Another one, if you want to automate tasks that at the moment you are or your people are doing manually. So, when you want to scale or when you scale your application, there are several tasks involved and you want to automate that. So, you only want to say, okay, I want three replicas of my application. And then several tasks are going to be triggered. Also, when upgrading in this case, it's very easy to upgrade an application. Well, at least the operator, but the operator should take care of upgrading the application and all the knowledge about all the things that need to be done in order to upgrade an application. So, first, I don't know doing a backup of the database, doing a backup of configuration files or stopping some services before upgrading. Well, your operator can do all of that. So, it's like a way of putting your manual scripts into one place that are going to be triggered automatically. And also, if you want to do complex tasks when you need to react to changes and those changes can be, I don't know, deploy Postgres database or create a database and create some users and also assign those users to that role or create a, I don't know, a realm in KickLog and assign users to that. And there are several things that can be involved like a business action, then your operator can automate all of that. Also, if you want, let's say, a robot to take care of issues. So, what happens when a pod is failing or health checks are failing? Now, well, those pods can fail at a number of times restarting, they will remain down and then someone will receive a notification and will try to solve that. But what if you could automate some of the resiling or solving tasks you can automate them into an application that will do several things when the pod is failing considering different situations. So, in the end, reducing the time of manual intervention. And in the end, if you want to have more control about your applications, but not having someone just there inspecting everything. So, automating metrics of, I don't know, usage or automating metrics of resources consumption, whatever. So, if you want to have more control, even if you want to have auto config turning, so if the cluster has more memory, your application will get more memory without no one doing anything manually. So, in fact, what's an operator? Well, in operator, it's an extension of the Kubernetes API. So, you have, I don't know, deployment, you have ingresses, you have secrets. But let's imagine that our application is, I don't know, a video club. There is no such element in Kubernetes. But we want to control how many video clubs we have, which are the properties, which is the lifecycle of each one. Then the operator gives us the opportunity to create this extension of the API. So, we are going, in fact, create this video club object. So, in this case, as you can see on the left, this cookie cutter named CRD. So, with this CRD, we are going to define which are the attributes and the elements of every video club. So, we can have one, I don't know, one video club in Miami that serves old movies, another one in New York that serves, I don't know, sci-fi movies, whatever. So, you have two, three CR that are the implementations of these definitions. Okay, now we have this video club in New York and one in Miami, and then what? So, okay, we have those objects, but nothing is happening. So, now we need the important part that it is the watcher and the controller. So, we need someone that it is just simply listening constantly to those video club events. So, now it is watching that there is one video club in New York created. So, there are some things that need to be done and another one in Miami. So, it is watching two events that are happening on those objects and then we have a controller that will do, okay. Now, we have these events, these changes on these objects. Now, I need to do some tasks because the user has said I want one video club in New York with three stores. So, the controller needs to check how many stores are already for that video club in New York. If there is one, it needs to add two. If there are four, it needs to close down one. So, those are the things that in the world of the operators, we call desire state and real state. So, the real state is always compared to the desire state and doing the tasks that will move the real or the current state into the desire state. So, in order to create an operator, well, we have different ways. This is a matrix of maturity for operators and you can create them using Helm. Helm talks about you will go up to phase two. So, there are upgrades without any intervention, but it cannot go farther. It's only happening on the installation and on the upgrade. Also, with Ansible and we can have all the maturity levels. As I said, we go and the go SDK that is an abstraction that tends to make everything easier for you to create an operator. But also with Java. In this case, I'm putting here this example of migration toolkit for applications. This is one of the operators that I created in the past and it's created in Java and well, it's already published. So, to create our operator, what we need is, in this case, open JDK 11, fabricate Kubernetes client that it is in fact the library that it is connecting to the Kubernetes API. Jeep, that it is the one used for producing images, container images. Then Quarkus because it's the framework that we are using for everything. Then tools to connect to the cluster. Well, you can have Qtcl or OC for OpenShef and then dive that will connect to a particular image and will give you the different layers and files for each layer. Well, if you want to debug a bit, the image created. Podman because it's a runtime used for running images, container, sorry. The registry is quay.io that it is where we are going to deploy our image for our operator. And then to test everything locally, we can use Minicube or Kine. You can use whichever you want. So the parts for the creation of the operator. Well, first we create a Quarkus Java application skeleton. Then we create the objects defining the elements for the operator for Kubernetes. So we need to create a namespace. We need to create or define the CRDs. Those are cluster wide. And then namespace wide, we are going to have a service account for our operator. So this is like our operator needs like a user to interact with the cluster and it goes in the service account, the role. So the definition of the things that can be done and the role winding that it is in fact, connecting the service account and the role. Okay. And then we have our Kubernetes client beans. So we need to have an object representing the namespace where our operator is running, a Kubernetes client that it is like the general proposed client to connect to everything in Kubernetes and then a CR client. So for each CRD that we are creating, we are going to have a like type safe client that will react only for those changes happening in those CRDs. Then we are going to have the watcher. So the listener in those CR changes that it is using the CR client. Then we are going to have also a watcher on deployments because we need to know when we deploy everything, we need to know when it is ready. And to know what is ready, we need to check all the deployments, all the pods and to see if they are really ready. And then when everything is ready, our application is ready. And then to build, push and deploy, we are going to use Maven and then Qubectl to execute the deployment YAML. And yes, we are going to use YAML because YAML is the language used for all these descriptor files. That's it. This is the Java skeleton for our operator. First, you can see two controllers, one in this case, windup is the name of the application. Okay, and we are having only one CRD. This is the windup. So we are going to have the watchers and we are going to have these controllers. These controllers are going to execute different things in this case for the windup CR and also for the windup deployments. As I said before, we are going to watch deployments. So we are going to react to them. Then we have the model, so the representation of everything, of all the objects that are going to be used. And finally, the beans and clients that connect to the cluster. Also, we have some files, descriptors to implement and to deploy these objects into Kubernetes. And finally, we have these files that will allow us to deploy our operator into operatorhub.io. About the Kubernetes objects, those YAML objects. Here, please focus only on the highlighted texts. So for the CRD, that is a custom resource definition, it's defining those custom objects. So in this case, it is saying, can this object is name spaced? So it's only contained into a name spaced. And we have this open API v3 schema where we are going to define which are the properties that can be configured by the user into that object. So for instance, it could be city, it could be a type of movies. It could be, I don't know, branding color for, and we will have the New York one saying city, New York, type of movie, sci-fi, branding color blue. And then we will have another one that will be city, Miami, type of movies, classic branding color red. That's it. Then we have this role that is going to define which are the actions, verbs, that a user with the role can execute in some objects. Then we have the role binding that will connect the role with the service account. And then finally, the service account that defines which is the user to be used by the operator. And this is the deployment for the operator. So we are going to define, okay, we want a deployment for our operator. We need to provide obviously a container image that is going to be deployed. And then, well, basically, this watch name space, environment variable, and yeah, basically that's it for the operator. It's easy. Regarding the Java clients, well, we have this global Kubernetes client that as I said is going to be used in some cases just to connect to the Kubernetes to get, I don't know how many deployments that are in the cluster for that name space or other objects that are convenient for the operator. Then we have the CRD specific client. As I said, it's a client that works exclusively for CRD, the window in that case, video cloud for our case. And this CRD context for the CRD client, it's a convenient class, so don't put a lot of attention on it. It's a convenient class that we need to use, but that's it. And also the name space, so we need a bin that it is providing the name space object for the whole application. About the watchers, we have in the operator, let's say, main code, as you can see here, we are creating the CRD client that will watch with this class with window controller. And then we have the general watch in deployments that is going to use this other controller. So we are specifying which are the classes that are going to receive those events happening on, in this case, windows, or in deployments in a particular name space. And in this code, we have events that are on add, on update, or on delete. So we are going to do different things depending on the type of event that you receive. There are other approaches that are simply reacting to any change done, particularly putting attention on which is the event that is using the reconcile method. But in this case, it was used with this separated events approach. Regarding this concept of reconciliation, so if the user is requesting three instances or has changed any value on any particular CR, we need to check that the value in the current state is the same. If not, we need to change what it is different in the current state. So in this case, whenever we receive an event, we do update our CR and we are going to execute these changes. So in this case, set status. So in this case, we are reacting to changes to deployments and when everything is ready, we are going to set the readiness property in our event. Sorry, in our CR. In order to test the operator, well, I'm not going to focus on unit test because it's the same for each Java class. So let's go with a more interesting thing. So with integration test, okay, you have your operator, but then what, how do you test it? Well, you can use the Kubernetes mock server that it's provided by a fabricate Kubernetes client that what it will provide is an API that simply reacts to requests following the same API as Kubernetes. So your client is going to send, okay, there's a change here. This new CR has been created and then that Kubernetes mock server is going to react as if it was the Kubernetes real cluster. And then we can check how many requests have happened in which are the different values that have been pushed in order to know that whenever you have created a CR, several deployment requests have been executed, several ingress creation have been executed and so on. So when you have those numbers, then you say, okay, my operator has created the expected elements. You can also use it as to check updates. So my operator has received several updates that I was expecting, yes. Then I see that everything is more or less working as I wanted. Regarding a local test, well, you can use in this case, kind. It will create a local cluster. And then what we did is we build our application with Maven and it is creating a local image and then we are loading that image inside the kind registry. As you can see in the second line. Then I apply all the descriptors. I deploy a CR into the cluster and then what I do is I simply a sleep for an amount of time. And then I check the number of elements in the cluster with this Qubectl get all. And then I check that all the number of objects is the one that I expected. And then I have this script that I can execute with one command or even you can put it on the CI environment. So here is a GitHub action that what it is doing is creating a Kubernetes cluster. Every time a pull request receives a push, then it just starts a mini Q, it puts the image inside, it executes the descriptors and then waits for an amount of time and then checks that the number of objects are the expected. So for every change, you can see that nothing has been broken and that the operator is reacting as it is expected. In this case, it is not checking the real status of the application because this operator only works on OpenShift because the underlying image is used. So there are some pods that are not going to start correctly. That's why we cannot check the status. In order to publish the operator to operatorhub.io and the internal operatorhub screen as you can see in OpenShift, it's a matter of cloning this repository and then adding those files that I showed you at the very beginning containing the CSV that is a file that is containing a lot of information about your operator and also the CRDs and you create a pull request to that project and then if it's merged, it will appear in operatorhub and then you can install it in Kubernetes Vanilla or if you put it in another repository, you will be more or less doing the same, you would publish this operator in the OpenShift operatorhub screen. These are the parts of the CSV. As you can see here, it contains the, which are the CRDs contain different information that are going to appear in the screen, which is the image and the keywords for searching the operator. And also to test the operator in operatorhub in OpenShift, then it's about creating a bundle, then it's creating a catalog, as you can see here in the instructions, you can check it offline after the stock and then you will create a catalog, a test catalog that will be deployed in OpenShift and then you can install an operator from that catalog that will be yours and then check that everything is working fine before publishing to operatorhub. The execution flow in operatorhub embedded screen is you search for an operator, as you can see here, when in this case, migration toolkit for applications, then you will receive this screen with all the description about the operator, then you will install it in the namespace that you want and then you will see the operator installed. After that, you are going to create the CRs. So in this case, there's only windup, as you can see here, create instance, you are going to see some attributes in a form, you put those attributes and then the operator will execute everything and as you can see, it will deploy a deployment service, replica set, port service deployment, it will execute everything and you will have your application deployed. Also want to mention that as although this project didn't use the Java operator SDK as it was not ready yet at that moment, I encourage you to totally check this framework. Recently, yesterday, they released 196 release and includes several features. I totally encourage you to use this operator SDK because it will make your life easier to create operators. And here you have this slide with all the references and I totally encourage you to check all of them, but again, if you need any help, if you have questions, doubts, please reach for me and I will try to help you as much as I can and thank you very much for attending the talk and I'm very glad to share my knowledge. Thank you very much. Thank you so much, Jonathan. This has been an awesome talk. I really wish that we had time for questions but we're a minute over. If you guys, if anyone here is interested in following up with John, you can find the link to the breakout room where you can just continue the conversation. I really wish I could join as I have so many questions. Okay, thank you. Thank you very much to all of you. Let's meet and greet at the breakout room. All right, next up we have Lisa Runchbar.