 Hello everyone. Welcome to OpenJS for good morning, good afternoon and good evening from wherever you are joining us today. I'm Sandil, a full stack developer and you can reach me at Sandil Marend, Twitter handle. I've written a couple of books, one on full stack development, the other one is on Rust and WebAssembly. The Rust and WebAssembly is the new one, which is written in a cookbook format that will help you in your Rust and WebAssembly journey. If you're learning Rust and WebAssembly for the first time, this book will help you in your other stack. And you can find the links here below and I'll also publish the slides later. Great, let's try to start up. This will be an introduction to Kubernetes Talk, where we will see why we need Kubernetes, what problems does it solve, where you can run it, how it works underneath. So let's get going. We will start with a simple hello with application. So it's a simple ExpressJS application, which runs on port 3000 and exposes the slash end point. On action single, you get a string back saying hello. It's very simple, right? Once you start, once the application is ready, now we are thinking about how to move that into production. So when you are thinking about moving into production, then it's something like Docker you can use to containerize the application and then move it to production. It kind of gives you a lot of advantages, right? So in a Docker, you get a latest image of Node, you do all the required things. For example, NPM install copying all the files and directories. And then finally, once you've done your exposing import port, in our case, is 3000 and a Kickstarter process. Once you've started the process, Docker will run the process. But it will not manage the process. So once the process is dead because of some reason, your application will not be accessible. So Docker will not control that. On the other hand, Docker gives supportability and also it completely abstracts away operating system and high runtime related stuff. Because you need not worry about it as long as you have Docker installed, it might be any machine or any operating system, you can actually run your application inside as a process. That's really awesome, right? And then once you go into production, you obviously will have to scale your applications. If there are a number of uses increasing, and once you're trying to scale the application, the obvious next step is putting a load balancer on top of it and then create a multiple containers. The Docker containers can be running in multiple badly. Put a load balancer, direct the traffic based on the resourcing or round drawing or any method that you choose. Load balancer itself is a complex mechanism, but there are a lot of tools that are available that makes it easier to build a load balancer outside of your system and then control everything together. But over the course of project, we found out there are two different things that we missed out and we create two different services for them. In our case, it's Hello Galaxy and the Andromeda. These two services exactly similar express JS function except for like some differences between Galaxy and Andromeda. So once you have done this, we could follow the same pattern, create a Docker image for that, run it in a Docker containers, multiple containers, scale it across, and then put a load balancer on top through which all the connections will happen. This is fairly straightforward, but these services are not depending on each other. They're completely segregated monolithic application, right? But what if you want to connect these services together? How do you make the communication with them happen? For that, it's an example if you for example, if Hello World wants to talk with Hello Andromeda, you have to understand the IP address or you have to know the IP address of Hello Andromeda. You should request to that Hello Andromeda and then Andromeda will give a response. You get a response, so it back to your customers. This is how it should work. But doing that in a manual way is very inefficient and also takes a lot of time for us to do. For example, if for any reason we have changed the IP address of Hello Andromeda, then you have to deploy your Hello World and then deploy it again with a new upgraded one. So they are kind of interdependent with each other. So in the world of microservices or whenever you talk about microservices, you want to isolate these services completely together outside. So you have to pull them apart, make sure there is no interconnection between them and then deliver their master parade services. That's how you have to do it. So in the world of microservices, all the three services are completely independent and they are abstracted into a single instance right now. So there can be hundreds of instances of Hello Galaxy running, but you can abstract them as a single instance. So that's how the microservices has to be acted in a better way. So the obvious question is how can we enable the communication between them? So we can put in something like a service registry. So the role of service registry is very simple. Whenever a service boots up, it goes to service registry and says like, I'm booting up, please have my IP address. If anybody wants to connect with me, just keep them beside the address so they can connect with me straight away. That's awesome, right? So the service registry will be a highly available service and it will remain there, but it adds a bit of latency because every time when Andromeda wants to connect with Hello World, it has to go to service registry, get information and then go back to Hello World. That's a bit of a workaround, but we can have different workarounds for that, for example, have a service agent running on different services to make sure we are not always doing this two-way communication rather than have an updated node always. But you can solve them. But the other problem that we are going to have here is like when services goes out of life, like if something dies out of blue, the service registry will not have any clue about it. In order to have that, we have to have another service which is called a cell checker. The responsibility of the health checker is very simple. It takes in all the information, sorry, it takes in the heartbeat from the different services and then says like whether a service is alive or not. Whenever a service is not sending a heartbeat or any information, it just remarks that services are not alive and removes that entry from service registry. So no new services or new service request will go to that particular rank. That's great. But when service dies, you obviously need to have a mechanism to restart them and also to replicate them. And for these two functionalities, you might need a couple of services which kind of looks, sits and sees what is happening inside my microservices world and how can I change them? And you need to have this mechanism. And once you have done those things, all the things you're living as a container application. So you need a Docker image from where you can pull the image and then run your application. So there has to be something like a Docker repository or any medium that could help you to download the images and then run them as containers. And then you need to have authentication and authorization between the breakfast when you're communicating, you have to authorize certain things and authenticate certain things based on the roles. You have to have a mechanism in which like allowing retries whenever an area happens and also stopping resource hungry, non polling of processes using something like timeout. So overall, you might need some kind of a setting that lives outside of your services and that could control how your services communicate, talk with each other and respond to each other. So that is the main intention of having these services. Cool. We can have a couple of services that kind of lives outside and make sure that everything is connected to it. And then finally, we have to have a robust monitoring system and also some dashboards that is combined with it. Health checkers will actually help you a lot over here because they receive the heartbeat from the services. So you can use those information and then create certain things out of it. So create some graphs or visualizations out of it. And then you need to have tracing for your services to identify where the problem actually is when something happens and also debug those problems. Find a way to pinpoint a bottleneck in your services and then try to fix that. Over a long run, if you have more services, like for example, more than 10 services and hundreds of thousands of instance of them running, then tracing and debugging will actually help you a lot in drawing out the new features and understanding of your services. So you remove all the three things that we basically started where our entire business logic will live. If you remove all these three things, all the other things that you're seeing in this picture, except for the grayed out ones, are highly available services. Even your application has to be highly available, but it's your code, but all the other things are like generic boilerplate code which has to be highly available and you have to maintain. And you're going to spend a lot of time doing that. And that's where Kubernetes actually comes into picture. Kubernetes is an open source project from Google, of course. And it helps you to automate the department, scaling, and also management of different applications. And all these applications has to be containerized. It has to run in some sort of Docker environment or some sort of container as can be normal. But all the applications that people in the scan handle are the containerized ones. So let's get started by understanding the building blocks of Kubernetes. In the Kubernetes world, we call them as like the object model. So the Kubernetes objects. So let's go and see what are the common objects that we will use more often. In anything inside the Kubernetes world, we will just describe it in the format of the ML file. So you provide an ML file to the Kubernetes and this ML file will clearly specify the running state of the applications. Like for example, if you have some ML files, you can just go ahead and take a look at it. And if you have some Kubernetes configuration files, which is written in ML, of course, so you can just go ahead and take that file and see like, what is currently running in the system? How many replications are running? How many components are there? And what is the problem that we are having with the help of like some probes, which we'll see later. But those are the things that you can infer from the ML file itself. It's very clear and crisp that you can understand it. So all the ML files will start with an API version irrespective of any object model. The ML files will have an API version number at the beginning. So here we have the API version as version one. And then for this particular model, we have a spec. Inside the spec, we actually define whatever the thing set is required. It's basically the custom, our application-related stuff will end up there. So here inside the spec, I could have set in containers. And inside the containers, I have my Hello World image, which we built previously. So I'm just going to use that image and then use the container port 80 to expose these things. Okay, that's pretty simple. So I have the stocker image inside. And then you add in what kind of file it basically is. So the kind basically here determines the cumulus object here. In this case, you're defining it as port. So what is a port? Port is a container that contains more than one docker container. You can have one or more than one docker container inside. So it's a grouping of container. That's where the name port comes from. And cumulus cluster knows how to manage the lifetime of these ports. So what it does is like it goes in a three-stage process. At the beginning, it starts the waiting process, where it sits and pulls the image. It does all the necessary mandatory work before running these images. It does everything together. And then it assigns an IP address to that particular port. And then it also has something called a readiness probe. So the readiness probe is nothing but like it's a probe that you're going to check every now and then to make sure that your application is ready for accepting incoming traffic. And here you're saying execute a particular command and wait for first five seconds because I have to connect with my database. I have to apply and set it secrets and all those things. But after that, for every five seconds, make sure that my application is ready. Once it is ready, it moves the application into running state. And in the running state, you have something called a readiness probe. And readiness probe is very similar to readiness probe. But on the other hand, it checks when the application is live and it can accept a new connection. Once everything is done, your application goes into a terminal in the state where the application has existed, exited and enclosed. Here, cumulus actually waits. If exit happens naturally, I mean like if the exit happens intentionally, cumulus will just leave it out. But if the exit is happening because of some errors or because of something else, cumulus will try to re-instantiate the port and then goes through the same life cycle again. And also every Kubernetes object that you define, you can add a metadata. In the metadata, you can have key value pairs. For example, here, I have a labels. Inside the labels, I have app and logo. So this kind of helps me to have one more level of grouping my components. I can have different pods and then group them with different labels, like for example, environment production. And then apply set of configurations only for that group. So that's where metadata helps you out. It gives another grouping mechanism for you to group things together and then deploy them and then have a value. After the pods, what you basically see is like how many replicas a pod can have. And that's where replica set comes into picture. So replica set, it's very simpler. You have an API version and then the kind as replica set. And then you put a number of replicas that you want to do it. And cumulus cluster actually manages the state. Make sure that if you have given three replicas, three instances, or three containers, or three pods, it's basically running inside so that your application has enough bandwidth to accept all the traffic sets. You can group this deployment and the pods, sorry, you can group this replica set and the pods together and you can call it as deployments. So deployments actually provide a desired state of the application. It also helps you to do seamless rollout and rollback together. So there might be seven components. For example, your your database server and your application always goes in together. So if one of them goes out of business, you can actually tell it the other one, something like that, right? So you can group them together with deployments and say like, okay, so this my application and the database server, I want to rent five replicas and then group them together. And that's what deployment is all about. Cumulus also provides one more level of no aggregation, which is called as namespace. Namespace, you can constantly name spaces a folder inside which you put all your components inside. So you have 10 teams in your company, you can do 10 different namespaces for these teams. And then put a pods and deployments and and replica sets whatever you want inside the namespace and then run it together inside it. So in a more pictorial way, you have this cumulus cluster, you can have a namespace inside, you can have multiple namespaces inside, and then you can inside the namespace, you can have multiple deployments inside a deployment, you have multiple pods inside the pods, you can have multiple containers. That's how cumulus is kind of architected very high. But you have this ML file, now you have to run this inside the cumulus. We know how to, we know what are the basic elements in an ML file, but how we can run this inside the cumulus? And to see that, let's take a division and go through what's the architecture of cumulus, how it is actually architected. Cumulus is actually designed in a cluster format, it's a highly available cluster, of course. It has a control plane, that kind of controls everything that happens in the cumulus, by the cumulus, it is only for the cumulus, I would say. And then there is a worker node set of worker nodes, where actually your application ends up, and this is where your application will live. If you're running a container or a pod, it will live in one of the worker nodes. So basically, cumulus is called as brain of the cumulus cluster or brain of the cumulus, and then the worker nodes is actually where your application live and actually work happens. So you have this ML file, you send this to control plane. Inside the control plane, you have an API server that takes this file and then validates it, whether it's perfect, whether it's correct. Yeah, even before that, you can send the cumulus in three different ways. One is via CLI, as you have seen here, there's a cube CTL, which is a command line tool. So you can use cube CTL, create dash of actor level, which actually pushes this information via CLI. You can also do it via REST API endpoints, or you can also do it with dashboard, which gives a UI for creating these things. So it goes to API server, a base server actually validates them. Once it is validated, it gets the information from the ETCD database. So ETCD database is nothing but a cumulus database, which is a key value base database, and it stores the cluster information. So API server will get the customer information from the ETCD database. It combines all the information that it has, the current state, which is from the ETCD database, and the new configuration that you've added, it wraps them together, plus the no details. The no details here refers to the worker node, which we will see. So it passes all those things in and then pushes into Scheduler. Scheduler is a cube. It works on first and first out. Whenever something comes into it, it goes ahead and tries to schedule it on the worker node. Before scheduling it, it has to ensure that all the requirement that you've asked is actually available in one of the worker nodes. For example, you can go ahead and specify one this particular type of volume for my cumulus point. So Scheduler takes those into category and those into consideration, and then finds a worker node that is best suited for the work, and then calls the worker node. So it goes and says to worker node, hey, can you start the work over here? So once that happened inside the worker node, the worker node is actually made up of container runtime. And the container runtime is nothing but something like Docker runtime, right? So it is like if you're running your cumulus cluster inside the Docker for desktop, this container runtime is just a Docker runtime. It's just kind of an operating system. Kind of you can assume that something like that. So it's kind of a Node.js runtime or a runtime that is specific for the worker. So you pass all these cubes with the information, the control plane, and the control plane will actually forward that to the worker node. But inside the worker node, there is another thing called Node agent or a cubelet. This is basically a second action between the control plane and worker node. So it sends information to the control plane as well as it gets the information from the control plane. So once the scheduler says like this worker node has the capacity to run this requirement, it passes that information to the Node agent, which is a cubelet, and the cubelet will proceed with the work. So going back to our first line, once the start work command is issued to the worker node, the worker node actually does the job, and then it returns even before finishing the job, like everything is fine, I can start my work and then say the work has been started. And that information is passed on to API server with an acknowledgement from the scheduler. And once that happened, API server go ahead and update a new cluster state inside the ADC database. Apart from all these components, control plane also had some crucial component, just called as control manager, which actually does a lot of work for us. The control manager is one that runs continuous loops to ensure the current running state of the Kubernetes cluster is actually equal to the desired state that you have defined in your YAML files. So it is the one that ensures if you have defined fire replicas, all the fire were running. That's the job of this control manager. And then inside the worker node, of course, all the worker node has your application that is running, your containers that are running, and it has to ensure there is a mechanism for having a communication, and that has achieved the help of kube proxy. So kube proxy helps to do the pod to pod communication, pod to outside world communication and things like that. And finally, you have this add-ons, which is another whole suit of tools that is helpful for you to do it. And you can manage them. You can pick and choose whatever you want. Like, for example, if you have your own system logging, you can remove the logging from the kube business cluster itself. So you can have this mix and match over there, but it provides a basic set of add-ons, which is like for logs and dashboards and owner drinks, so you can use them together. So this is how an entire application, an entire kube business looks like in a very, very high level view, right? So it has these components with which they talk with each other and then take schedule and then create your application container as it is. Inside this component, the API server is actually you can have the system very highly available component and there can be multiple instances of API server running. And it is basically to ensure like if something goes wrong or something goes out of the picture, the other API servers can kickstart and start doing the connectivity. It's also very important to note, API server is the only one that can connect to ETCD database on any database, sorry, any ETCD database inside the kube business cluster to ensure that the state reading and also state writing policies or authorizations lose in the API server. Once that is there, the ETCD database need not live inside your kube business cluster itself, you can pull that out and put it somewhere else. It does not manage to live inside and ETCD database is an excellent, resilient, key value storage that you can use it for different applications. The reason of pulling this outside of kube business cluster is basically very simple. If it runs inside the cluster, if the cluster is destroyed for any problem or something like that, then your ETCD database will also destroy with it. You will not have any information about the kube business cluster there. So, ETCD database, you can pull them out and then use them together later. Sorry, you can move this ETCD database outside because when your cluster goes down, all the information about the cluster also goes down with the ETCD database. But if you have it running outside, you can actually recreate the same kube business instance. Even if it fails, you can create a complete new cluster and use the CTCD database as a source of input. So, that's how powerful kube business is. And you can also have this, you know, drill down version of Quota and Lament management. So, for example, on the right side, you can see, you can reference for a set of memory and the CPU. And also, you can limit your memory and CPU to the maximum that you're going to use for your containers. So, you can have this level of, you know, Quota and limitations at the container level, at the port level, at the deployment, at the namespace, at all the levels. Like, you can have it drill down or at a high level. So, you can have all those required steps for you. So, you have this kube CDNML file. You want to apply this to the Kubernetes. You have done it. So, what does it solve once you've put it inside? Based on what we've seen, the port, replication controller, replica sets and deployment kind of addresses all the problems that is with the tick mark over here. So, you can do this image polling policy. Ports actually take care of life cycle. If something goes down, controller manager does the restart and replication part. The liners group and the readiness group actually use it for Eastport health checkers. And then it, Kubernetes also provides add-ons for monitoring and graphing. And also, addition to that for praising and debug, Kubernetes provides a platform in which you can add more things like, for example, put in the agir and then monitor all the services that are running. So, you can do all those weeks and match activities on top of it. So, Kubernetes kind of solves these problems. And the most important thing in the world of microservices is how the communication between services is happening and service industry is very essential. So, let's see how Kubernetes actually solves it. So, Kubernetes has an object model called the services that helps you to address all those connectivity port to port, port to external, and port to other cluster communications. So, you have a port. Of course, a port can have multiple containers inside that are running inside. And it can have a, actually enables port-to-port communication. So, you can have an abstraction on top of this port and call it as a service. So, servers, as you can see in the ML file, it comes with a kind of service. You put in a metadata and labels for the servers, and then you specify where the service has to abstract or what the service has to abstract. See here, we are abstracting on our labels or the selector at her world, which we have used in the first port example. And then it also specifies the protocol in port. So, if you have just applied that particular file which we have shown, it creates a service abstraction in front of the port, and then it assigns an IP to it. But this IP can be used only within the cluster. It can all be used outside of the cluster. So, in order to access this from the outside, you can go for something called as the type node port over here. The type node port is basically assigns a dynamic node port to the IP address. So, for example, here, I put in my target port is like 32765, and this port is attached for my service. So, if I have to access the service, I can call my worker node, get its IP, and then go for the node port, combine them together, and then access it. It will call my service, which will in turn call my port inside which my container is running. So, the very next thing is basically the load balancer. Here, the major difference is the type is node balancer, and then if you have defined node balancer, you're going to give an IP. So, with the load balancer, you can actually connect to the external world, and add it to that. Kubernetes also provides this Ingress configuration, where you can abstract one level more and create an Ingress IP that takes care of handling all the requests that are coming in, and then pass this request to the service, and then back into the port, and then get that information back. So, you can use Ingress for external access, which is the common production-ready access, right? So, with services, Kubernetes actually helps us solving this huge puzzle of service registry, and it kind of enables that you have a proxy environment through which you can access your ports. Using the proxy, we can do a lot of things, and Kubernetes actually works as a service registry. I would not say Kubernetes is 100% perfect service registry, but it kind of helps you to achieve the basic level of service registry. Once it is done, the other components that we have seen, which is like the retries, timeouts, settings, and authorization and authentication, Kubernetes does not provide a complete internet solution, but you can use something like Istio or Linkery, they are called as service measures, that kind of helps you to apply these configurations outside of the environment. So, Kubernetes kind of helps you to solve most of the things that we have seen in this list, and for a few other things, it provides a mechanism or provides a platform on top of which you can add more tools, and then use that, and then use that for making sure your application is running seamlessly. So, as we have seen, it is completely these structures or decouples infrastructure, so you can consider this analogy where you have a big chunk of a land or a server app, and then you give the server app to Kubernetes and say like, form my components, form my services in it, and Kubernetes does that for you. So, you need not worry about like infrastructure, how much memory do I add, what are the things that I have to do, Kubernetes actually does all those things for your box. So, decouples infrastructure completely, it solves most of the microservices common problems, and also provides a platform to ship awesome things like previously before containers, it was difficult for us to abstract away from certain things, but Kubernetes provides a whole new sort of abstraction with which you can ship awesome things to it. With that, if you have any questions about this bro, about Kubernetes, or in general about full stack implement, please feel free to reach out to my Twitter handle, more than happy to help you out. And that's all. Thanks for joining me again today. Have a great day and be safe in this weird times. Bye-bye.