 to this session of the jug and I will give the voice to Miquel this one or this one I don't know zoom is always wrong in fact I'm pointing someone it's probably not the right one Miquel is V for the introduction for the session for today thank you Miquel and yes I'm afraid I am okay I'm going to do a to introduce Sergi but without sliders sorry I have a bit of thinking for the issue and that's fine I don't have so much to say so welcome everyone we're super happy to have you tonight and so we are the Singapore Java user group and we are like basically like we've been active for like three four years already and since the COVID-19 situation we started doing virtual events so now we do like one event every like two to three weeks and last time we felt like it was maybe a bit too quiet that's why we asked Jerome if it could be our facilitator so big thanks to Jerome Bourgogne for being our facilitator tonight and yeah and so tonight we have like a very special guest we have Sergi Alamard who's a longtime friend and he has been in the spring community since 2005 so by the time probably most of you guys are not old enough for that but it was like spring 1.2 and there was just like a bunch of people using spring and Sergi was one of the first people to cover the world to teach people about spring to enable them to speak at conferences or like kind of stuff and he's so passionate about spring that he actually created the European conference about spring which happens every year in Barcelona it's actually huge it's like 1,000 people all the the spring engineers all the commuters actually come to Barcelona to speak about spring for like two or three days and it's super awesome so Sergi has been doing it for 10 years of course not this year because we don't have conferences this year but he will be or maybe he will be back like in October and Sergi like came many times to Singapore and he spoke to Box Day Singapore twice about so yeah Sergi it's good well thank you very much Michael it's a pity that I can't be in Singapore this time but well we got an alternative at least so let me just share my screen here okay all right so again thank you very much for having me at the Singapore Java user group I've been with you some other days in person both in the Java user group and at the box days as well which is amazing I really enjoy being in Singapore but well today we're gonna be doing it from Barcelona which is where I am actually my background picture is Barcelona and that's basically where I run the spring at your conference somewhere like here right so that's basically the venue of the spring at your conference right so thank you for for joining and well my name is Sergi and we have a lot of flavors of my name and I guess that you have heard things like Sergei or I don't know Serge many other pronunciation of pronunciation of my names depending on the language that you're using but my name comes from Catalan so I live in Barcelona where we speak Spanish and Catalan and this is the Catalan version of the name and I guess that the ones that got that gets my name better are the Indians I'm not sure how many people from India we have today but I guess that we have a bunch of people from India but when I went to India first time usually people call Ser to someone who they don't know right so they say Ser and they say something but if you would really want to be formal they usually say Sergi right so G is basically the formal version of Ser right so when I first went to India I was hearing Sergi so my name I had all the time and I didn't realize that this was an Indian name I was like oh this cannot be an Indian name right but so apparently they were basically addressing to someone right in a formal way so that's usually where I get my my name best pronounced so a couple of words on me well so I'm basically a Java on spring software engineer where I spend half of my time with clients doing some development and half of my time during doing some trainings right for spring and also for Kafka and as Michael said I'm also the spring at your conference organizer which is the conference in Europe for spring so if you're if you're into spring you should definitely check that out we had a virtual event this year right then the in-person event is scheduled for October we'll see what happens but if you have any chance in any any year to come to Barcelona spring IO is the place to be but today I'm here to tell you a little bit about containers right then well because probably you are a Java developer probably using a spring or spring boot as well and you're used to package your applications as jar files or war files and when we package the application as a jar file we probably send this application to the DevOps team which they basically run so they have to gather the dependencies they might gather things like a gre or maybe a subcontainer or also probably they pass a parameter to your application and that leads to the works of my machine kind of thing right because well the application works in your machine but probably in another environment you don't have the required dependencies or you're running in a completely different environment and that's not ideal right so what we want is to run the application in a an environment which is really close to what we have in in development right so development and production should be quite similar that's why probably a container might be a good idea because in a container we have everything we need to run our application that includes the os uh a file system the application file system things like how to run the application the parameters that we have to pass to the application so we can take this container and run it anywhere right in the same way so you can just build the container yourself and send it to the DevOps team and they will just need to run this container but that means that you now need to create this container and well creating a container might seem a really easy thing right but you'll see that you'll have a lot of power when you create this container this is a way to create a container is by creating a Docker file and so that's basically the easiest way to get started and well uh you might say well I have uh these uh a couple of lines here uh in our Docker file and this gets me a container right so that will create a container but is this container the most optimal container for you and for your application so you could take a look at this uh Docker file so what we do is to basically take a base image coming from Adobe OpenJDK and as the name implies this will kind of give us a GRE right on Java 11 and then we just take the jar file from our Springboard application which is copied inside the container and we define how to execute that application with Java Manager and the application well now you have a container so we could stop here at our presentation you have everything you need inside a container but things are not as easy as we have seen actually in that Docker file you can do whatever you want you can copy stuff you can download things you can do whatever you want you have a lot of power but we know that with a lot of power comes a lot of responsibility so you have to be responsible for a lot of things for instance uh well the first thing that could come into your mind is which base image we should use and the base image implies a bunch of things right so it implies the operating system that you'll be running on it also implies the job distribution whether you want to also uh use a JK or GRE the Java version as well right you want to run on Java 8, Java 11, Java 14 right so this is basically the first question that comes into your mind so we take a look at the um container that the previous Docker file will create and we inspect it by calling Docker history right so that will basically tell you a little bit about the layers inside the container because a container has a bunch of layers so you'll have the layers from the base image usually these are with only layers and it's as we see here in our Docker history the first layers are going to belong to Ubuntu Bionic right so which is 18.04 so this is basically the operating system layers so it's basically contributing some of the operating system layers on top of that we have the layers contributed by the GRE hotspot so that will basically provide the GRE to your container and after that you will see that your layers will be added on top of those base images so on on top of these these base layers so we take a look at the Docker file that we have created every single line will transform in a single layer so notice that well we have the from that basically contributes to the GRE but then the arcs target jar is actually its own layer the copy is another layer on the entry point is another layer so let's take a look at the copy one let's see you'll see here that we have copied the entire jar right so that's actually 18 mechs and in Docker you can actually reuse layers which are which are below you that means that if you change anything in your application with that particular file you'll have to rebuild the jar file and recreate the container and replace the whole layer right so you'll have to change the entire layer because your application is a single a single deployment unit it's a jar file this might not be ideal because probably most of the mechs here in this jar file are going to be like libraries so things that you'll be using which don't change so you'll be changing your code but you won't change the spring version for instance so we can do better by layering a little bit more these docker container and if we layer the docker container a little bit more what we'll achieve is basically faster builds because we don't have to copy the entire application anymore and also when you deploy this or you push the application into a container registry you'll only have to push the layers that have changed if those layers are smaller this is going to be much faster so in terms of bandwidth we're going to save a lot of it so i'm going to introduce some of the features in a spring boot to the tree in a spring boot we have a maven and a griddle plugin which basically creates the artifact right so here we have on the left hand side the spring boot maven plugin which allows you to create a jar file or a war file so basically creates this uber jar but now in spring boot to the tree what we can do is to enable a layered jar right so we are going to pass these layers enabled equals true parameter and this will create an index for the layers that we have in our application so we take a look at the content of the jar file now that we use a layer jar you'll see a file under boot uh hyphen in layers idx that that's the index and this will tell you the layers that you will find in our jar right so we have a layer for the dependencies we have a layer for the loader we have a layer for the snapshot dependencies and we have a layer for the application itself so now we have layered our jar when we have a our jar layered what we can do is to basically copy these different layers in its own um or the different parts of the application in its own layer and here here's a more advanced uh docker file where we use a multi-built right our multi-step uh docker file so the first part is basically getting a base image from the adopt open gdk so 11 grv hotspot and this is only to extract the layers from our jar so basically we're going to explode the jar and extract the layers so this first part of the docker file serves just as the builder so we're going to just um forget about this uh this uh part of the docker file this base image and our container will be created from this other base image where we also i'd accept from the base uh 11 grv hotspot base image and we're copying some of the files from the builder which is what we have created previously so we basically extracted the layers and we're copying those layers in its own um or those parts of the application its own layer in our container and then we're basically changing the entry point to use the jar launcher which might be better than using java minus jar so that's basically what you could do right in spring booted up three but if you're not in spring booted up three you can still use it you'll have to basically uh split your application copy the the different parts of the application into different layers and you'll end up in a much better docker file so now if you change just one part of the application you won't have to push all the layers to the remote repository or to build the container you'll just have to take care of the layer that has changed but you have to take care of more than this by default when you create a container you'll be running as a root user right and we know that running things as a as a root user is not ideal so you should take care of that as well inside your container containers are not not VMs they are not security the security boundaries so you should run as a non-user and as a non-root user you have to understand how the build cache works you have to also understand how the multi-stage build works like we have seen before you'll also have to be aware of tags you have to also be aware of memory allocation how much memory do you need in your container and many other things so you can find some of the best practices on docker.com so if you go to docker.com we have an article on some of the best practices that will tell you how to build a docker file right in a proper way we go to Google cloud they will also have their own best practices so as you see we have to take care of a lot of things inside this docker file so creating a an efficient docker file is not trivial as you'll have to take care of the base image you'll have to take care of a multi-stage build the user maybe you want to trim down the GRE maybe well you have to do a lot of stuff but well we are Java developers right and for instance for myself I don't want to spend time on creating those containers on creating docker files with the best practices is there any way we can get those containers created but having the best practice best practice that we have seen well one option you have is jip so jip allows you to create a a container without any docker file so you have here the URL container Google container tools jip this basically a tool that well has a maven and a griddle plugin you can add it into your spring boot application and it will create the container for you it will use the distro less base image by default you can change that but this will basically be the base image and it will also split the application into multiple layers at least layers for the application for the dependency and for the resources it will also push the the image into a remote registry or into a container registry right so usually the way we expose this container is by pushing that into a registry this could be docker hub this could be a local registry this could be the registry from from google from AWS so any kind of registry and the interesting thing about jip is that it can create the docker container without a docker diamond which makes it really a good fit for CI cities kind of environments where you cannot what you don't have a docker diamond in place and the version 2.4 just came out last day right and it has also an extension framework so if you see that jip is not enough and you want to provide some extra behavior right you can use the extension extension framework to extend it with your own needs so there's actually one option to use jip for the container so you'll get a well-defined container with best practices and so on right another option would be a build packs and if you have used cloud foundry back in today's or Heroku maybe the name build packs is already familiar to you right but in 2018 right the cloud native build packs either were created so that was an initiative right to summarize kind of the way we created those containers and you can find the spec on build packs dot you because the build packs that I owe you'll see that build packs that I owe is just a spec so it doesn't have any implementation on the specs that it defines but the main goal is to end up having an OCI container out of no docker file so basically with zero configuration we want to get an OCI image and we have multiple implementations of the spec we have implementations coming from Google from Heroku from Foundry we have also an implementation called Paquetto which is what we're going to use today right but of course every platform has its own needs so that's why we have different implementations of the build pack specification right but the main goal here is to basically have or end up having containers which are fast build that's which have reusable layers and also that are reproducible so if you recreate the same image multiple times you should end up having the same container right so the same input will leave the same output right so we want to be kind of deterministic here so we take a look at the Paquetto build packs so this is basically what we're going to use today so that's one of the implementations provided by the cloud native sorry the Cloud Foundry team right back in the day so Cloud Foundry we had a bunch of build packs right so now we are basically taking those build packs to outside platforms so you can use them on your maybe local development machine so anywhere else to build your containers so Paquetto will have a bunch of build packs if you take a look at the Java build packs you'll see that we have build packs that will do a lot of things for you for instance if you want to use Tomcat this build pack will contribute Tomcat to you if you want to use the screen boot this will do something for you as well for instance if you want to use a GRE you can use the Liberica build pack for instance to get a GRE in your container so we have a bunch of build packs available here and we'll see how they work within our environment so let's do a quick demo on how to build our containers and I have a really simple application here it's not relevant for the purpose of the demo but this is just a spring boot application it's using the latest version of a spring boot to the 3.1 and it's basically exposing a REST controller that says hi from an endpoint so let's start so let's start and create a container out of it so you have created a Dockerfile let me just quickly get into that this is the Dockerfile that we have seen in the slides so we can actually create a Docker container out of this Dockerfile that's what we're going to see first so we're going to first package the application so this will create my jar file the jar file that we need to build this container because the Dockerfile is not compiling my application we could do that right but it's not doing it so I'll have to create the jar file first and then I'm going to create the container so it's from it's basically compiling passing the test lovely and hopefully in the target directory we'll have our jar file which is this one here so now we can build a a docker container so we can pass that oh sorry we can define a tag let's call it spring boot sg and we should go to the previous directory so I think that this is it okay so hopefully this will get the Dockerfile from the previous directory because that's where we had the dockerfile and it will start creating the dockerfile correct so now if I do docker images and I grab some more actually the one that we have created is this one here and we could inspect it his terry I will see that well we have what we have seen that's how we are going to see that the different commands in our dockerfile will translate into those layers so now we can just run it minus p 8080 and we take the image itself which is this one here and they should run our docker container just running so we go to local host 8080 or let's say this is running maybe I oops I just for I have a typo here I didn't export the port correctly but that would be the easiest way to get a container at the spring boot container all right so we have here hi from docker Singapore that's great so now what we have to do is to push that into a container all right so I have here a local Kubernetes cluster and also a local registry I'm using kind for that right so kind allows you to create a Kubernetes cluster out of docker containers so you don't need much and this is great to run locally and start your Kubernetes cluster locally but now we'll have to push these applications into the registry so I'm going to curl the registry for a second so we have actually a bunch of repositories already in the registry but the way to push the the image to the registry is basically doing docker push right and then pushing that into the registry so I'm going to skip that so as we have a bunch of images already in the repository I'm going to move into the next step which is basically taking a look at the layers so we take a look at the jar file that has been created let me see that so what we can do is to basically inspect the layers that we have in here so we have here a list command that will tell you the different layers that we have in the jar files as we see here we have a bunch of layers which is which are created by spring boots so remember that when you use the maven plugin with layers enabled this will create an index file that will create the layers for you so by using the list command you can see the different layers that your application has you can of course create new layers if you want and if you use extract you'll be able to extract those layers and in this docker file which is the one that we have seen in the slides I'm basically using the extract command to extract all these layers and then build the different layers right in our container but again enough of docker files because as we are Java developers who maybe you're not interested in building the docker file yourself so I'm going to use jeep now in order to create the docker file so I'm going to do a maven compile and I'm going to use the jeep docker build command so if we take a look at the palm file I have added jeep into it let's scroll down so I have the jeep plugin which will create a the container for me and it's going to push it directly to my local registry so local host 500 5000 slide screen boot sg jeep is it's going to be my container name right so this will push into my local registry just by using jeep docker build so let's try to create a docker file with no sorry a docker container with no docker file as we see here we're using the maven plugin for for docker so notice that we're using the distrelas base image as we don't have any any docker file so jeep will choose the base image for us right so you can change that but this is already chosen for for us and it's also splitting the application into multiple layers so now what we can do is to take a look at the built container so this is basically the built container and a really nice tool to dive into the container and see the different layers that layers that we have in our container is dive so you can do dive and the name of the container and this will give you like a pre-visualization of what's inside the container which is really really nice so on the right hand side as we see here we have the different images or different layers of our image so we're going to focus on the three last layers so these three last layers are nothing more than our application notice that this layer that I have selected is contributing is adding the libraries of our application so on the right hand side you can see this in red so it's basically adding these libraries which are 18 megabytes so this is usually what will never change in your application you'll probably change your code but maybe you won't be changing your libraries so that's why this is in a lower layer than your application code but if you take a look at the second layer which are some some bytes these are just the resources so for instance the application properties that you have in your application so it's contributing this part of the image which are the resources and the last layer is contributing your code so these are the application classes here so this is the code that you have correct so we have classes libraries and resources in different layers so let's do one thing now let's go back to our application and let's change something so let's change our class and let's say well I want to show hi from Docker Singapore Jeep and I'm going to build the application again that's what I'm going to use may even compile Jeep Docker so I'm going to compile it again and hopefully this will reuse my existing layers because we don't have to change anything we just need to change the layer for our application and this will create yet another container let's compare these two containers now let's make it a little bit bigger hopefully this will fit in one slide okay all right so let's dive into the new container and we'll compare the hashes of every single layer right so every single layer has a hash so we know whether we can use it or not and let's take a look at the three layers that we have seen and now we're going to take a look at this hash here this is the hash of the container or of the layer so let's compare that with the other container so we take a look at the hash of that layer we see that it's the same right in both containers both containers have the same layer that means that this has been cash and they both use the same layers but it's actually great because these are the dependencies these haven't changed so we could reuse that layer from the cash what about the resources let's take a look at the resources the resources has this hash down here so let's take a look at the the hash from the second container the new container and we see that they are both the same so we have to use the resources as well but what about the last layer which is our application so our application has changed so we take a look at the hashes from both containers we see that they are now not the same so this hash starts with 298 these other hash starts with fdf so the container just differs on the last layer the topmost layer and notice that it's only 3.5 kilobytes that means that if you want to push that into the registry which we have done with chip we have just pushed these 3.5 kilobytes we haven't pushed the entire image which is great right because this leads to faster builds this leads to less bandwidth so when you're developing this is really important right so that's basically what we achieve by layering the container lovely that was a jeep right and basically we compared the different digests or different hashes from the containers so the other alternative that we have seen is was basically the build packs and in the spring boots to that tree we have really nice integration with the build packs and by default we're going to use the paquero build packs so how can we create a build a container right from the build so we have a command which is well maven spring boot build image you can define your image name either which will be a local host 500 5000 spring boot steam and when I do that we're going to use build packs to create the container let's see what happens when we create those those containers well the first thing that will happen is of course building the application compiling it passing the test so that's a normal maven build right but after that when everything is generated we have our jar files you know is that we have here our jar file we're going to start creating the build pack in in sorry the container in um in build packs right I wouldn't have the concept of a base image we have the concept of a builder right so you'll see that we'll be using a builder which is by default a base path from api 0.3 and it comes from the paquero build packs when you create the container more than one build pack can interact or actually participate in that creation of the build pack in our case we see that we have five build packs that we'll be participating when creating this particular container out of 15 right so we're basically creating what's called a build plan and the build plan will define which which build packs are going to participate in the creation of the container so we see that we have something called a bell soft liverica this is basically a gary or well job distribution we have another build pack that will take care of the executable jar and a spring boot correct so well um since that I have run these uh before already so I probably will get a bunch of layers thrown from the cache but let's take a look at the different uh build packs the first build pack that kicks in is the paquero bell soft liverica build pack notice that this will contribute in our case a gary and it will contribute a gary which will be a gary 11 right so depending on what you expect this could contribute a jk or a gary of course having a jdk in production or in a container might not be a good idea right so apart from being or the container being bigger in size this is not a good idea right in uh in a container so probably you'll need a gary to run your application but along with the gary it will start contributing a lot of uh layers for instance the memory calculator memory calculator is quite interesting because it will calculate the amount of memory that your container uh had or requires right based on a bunch of things like the number of threads number of classes that you have so when you start the container the first thing that you will see is the memory calculator kicking in we have another layer another um layer contributed which will be that class counter uh we have another layer which is the jvm kill because when you run out of memory your uh process might might be in an inconsistent state so the jvm kill will be an agent that will take care of killing your your process so it can be recreated by kubernetes for instance we have the local dns so that's basically uh local dns because well the jvm when it resolves an address it catches that address forever right so this will basically uh have a local dns so you can um interact with resources that have or change the ip frequently like in in kubernetes right there where we have different pause different resources that change the ip frequently and you don't want to catch those resources we have also um job security properties and basically certificates so you'll see that we have a bunch of layers added to the container that will give you a lot for free let's say we compare that to the first docker file that we have created that docker file didn't have anything so it lacked a lot of things right and another thing that the bill packs will do is to create a user so you'll be running your container on another user which is not the root user so we have a uh a geary so now we have this executable jar bill pack that will add the um the dn2 point right so that's basically how we're going to execute the char file we have other bill packs that will contribute also for instance the springboard bill pack and many other bill packs i noticed that all of them will basically contribute in different layers in our container right so we're going to see that in a second and eventually we'll get our image created which is this one here so let's take a look at at the image that we have created with dive as i mentioned dive is a really nice tool to investigate the image that's we're going to use dive and we'll see the different images that we have different layers that we have in our container great um so i'm going to jump directly into uh some of these layers let me just change the filters here and just filters and i don't want the unmodified now um so let's take a look at the visa this one here right so this is basically the layer where we see that the bill pack adds something into it right so this basically is something related to the lifecycle but um eventually you'll see that the bill pack uh already uh contributes on some layers so this is the class counter this is basically the job security properties this is the gre so notice the size of it so 140 is basically the entire gre uh then we have another layer which uh contributes the jv and kill agent as we have mentioned another layer that will contribute the the local tns another layer that will contribute the memory calculator and so on and so forth until the uh last layers which basically uh used the layer jar that we have seen to split our code our code into different layers so notice this layer it's 18 max and uh it basically contains the libraries of our application then we have another um another um layer which basically has the boot uh loader we have another layer which has our container our code right so basically we have everything layered in its own uh layer as we have seen in the jar file which is really nice right so at the end of the day we'll end up having a container with highest standards we have a container which has like multiple layers for our application but also contributes or has a bunch of uh things that will make our container uh up and ready right for uh native our cloud native deployment which is really really nice all right so far so good right so now we have our container now that we we know how to build a container different ways to build a container of course um jeep and uh build packs are doing a great job building those containers but uh sometimes we need to go back to docker files so docker files are really really flexible right so if sometimes you might need more flexibility and docker files are also an option so build packs are not a replacement of docker files sometimes right so it's really nice ways to get the container uh done or created but sometimes if you need more power you can go back to the docker files but you'll have to take care of everything that we have mentioned before great so now you have the container right so you're ready to um distribute that container so hopefully you have pushed the the container to a registry and now we can run this container somewhere you could use um uh docker run right uh so you could run your container right so just uh local we could do that um but probably in production you will need some kind of orchestration right so you will need to observe your containers to check whether they're available whether um you want to scale those containers the application you want to have some operability and maintainability and many of the things that so just running your container maybe with docker compose or any other tool won't be enough right so when you go to production maybe you need some kind of a container or a trader and these could be Kubernetes in our case right so well the premises of Kubernetes are really nice so you get a platform where you deploy the application it's going to be constantly monitored and the the platform will restart the the pods or the containers that are not alive and so on but when you get into Kubernetes well someone will tell you that Kubernetes is is great but of course it has a learning curve right so well I you basically see a lot of articles on the internet telling you that Kubernetes is is great it's easy to get started and then when you get into Kubernetes you'll see that well you have to understand a lot of things like what a compute map is what a deployment is what a service is what are the what is our back or the persistent volumes or many other things that's it has a learning curve as well so I'm not going to try to tell you what Kubernetes is but at least I'll tell you a little bit about the bits and bytes that we'll need to push our application into Kubernetes so so far we have what we see here we have a container where we have our application probably we have layered our application and we have pushed our container into a container registry as mentioned this could be Docker Hub or any other container registry which is out there but in Kubernetes we cannot simply deploy a container so the smallest smallest unit of deployment is a pot a pot will contain your your application your container actually in a pot we can run multiple containers but usually we have a one-to-one mapping between your application and a pot right so again you can have multiple containers but this is going to be the deployment unit and the scaling unit as well so if you want to scale you'll be scaling a pot an entire pot that's why well having things like a database inside the same pot as your application might not be a good idea because when you scale the application you'll be scaling the database as well as usually have this one-to-one mapping into the pot but this container right or this pot needs to be replicated at the end of the day having a single instance of the application won't be enough in production so we'll be creating a replica set and the replica set allows us to define the replication of the application can decide well I need three instances of the application so the replication will be three in our case and this will take care of our containers or our pots it will basically check that the current state is the same as the desired state if we mentioned that we wanted three three instances of the application and there are only two Kubernetes or the platform will automatically create an extra pot for you an extra instance of the application for you so it will make sure that you always have the number of replicas that you need but rarely you will be creating a replica set by its own either a pot by its own so you never create a pot by its own and it's it's rare you can do it but usually what we create is a deployment and when we talk about pots or replica sets or deployments in Kubernetes that translates into a YAML file right so we have to go back to writing some files so in in docker we have avoided I voted writing these docker files right by using cheap or build packs but now we have to go back to YAML and create the pot definition or the replica set definition or deployment definition so usually we'll be creating a deployment definition that we'll define the number of replicas of your pot and it will define also the containers in those pots so the base and the images in the registry and so on great but now when we have the pots up and running those pots are not going to be visible outside so they're going to be local in inside the cluster but if you want to make them visible to the outside you need to define the service we have different types of services right if you deploy that into a Kubernetes provider like GKE right this could be about balancer or luckily this could be simply an exposure of or basically defining an IP that will expose those pots so service is nothing more than a way to access your your pots because by default there will be internal and you won't be able to access them so we need to create a service to interact with those pots so in spring but to the three we have something called the liveness or actually the concept or also in Kubernetes we have a concept of of liveness and what is what do we call that a pot is alive right so basically when the internal state of that part of the application is valid right so we basically started the application everything is valid and we can basically say that the application is up and running right so when the a liveness test or prop says well we are not alive so something wrong is in the in the application what Kubernetes will try to do is to restart the container so the liveness test or the probe basically says well can we restart the container and get an application live and in a valid state and so basically it answers this question if restarting the pot or the container will solve the problem then just say well I'm not alive right and in this a liveness probe or actually check you usually don't interact with external resources right because let's imagine that you have a health check against a database and you make this part of your liveness check what will happen is that if your application is up and running and your database is down Kubernetes will try to restart your container but this can uh deal to cascading failures because if you have more than one instance of your application it will this will start restarting all the pots all the containers that you have just because your database is down so usually that's something that we check without external systems and in spring put to the tree we have an endpoint to check for the liveness of the application so back in the days when we didn't have a spring put to the tree we usually set the liveness probe to slash actuator slash info but now we have like a specific endpoint for that called actuator health liveness we have another concept which is the readiness so it could be up and running but maybe you're not ready to accept traffic so let's imagine that your application is up running but you are building the cache maybe from another resource so while you're building the cache your application is not ready to accept traffic so when you're not ready to accept traffic your application will be removed from the services so no traffic will be routed to your applications right so you have to be real careful on what you define here in the readiness check either probe we have some recommendations but at the end of the day it's basically you that you define what makes your application ready right but at the end of the day this needs to be something that you define but then we'll see that in a second so in spring put to the tree as we have the concept of liveness and readiness inside the application we have a couple of components that will be part of your application context that you can use to change the liveness and the readiness state we have a couple of objects called readiness state and and liveness state and by injecting or getting an instance of the application availability right which is already in your application context you'll be able to check the liveness state and the readiness state if you want to change the liveness state and the readiness state inside your application what you can do is to emit an event at the end of the day um when something happens in your application let's say well i'm building the cache you only know when the cache is ready or when we have ended building this cache so at this point you can send an application event and change the state of the application from unready to ready and you can do that with this availability availability change event so let's take a look at it in a second so if i have here a cluster let me just log into the cluster with this token i have here my local cluster which doesn't have much we see here that we don't have any deployments we don't have any pods we don't have any replica sets and what we're gonna do now is to basically take the the the the the token container that we have created and push it into Kubernetes so for that what we'll be creating is basically a deployment let's go back to to our terminal and i'm going to create a folder called Kubernetes just forgot the s but anyway and i'm going to check the registry first and let's see what we have in there let's see what we have here curl catalog all right so we have a bunch of of containers so i'm going to push one of these containers directly into Kubernetes by creating what we call a deployment a deployment is nothing more than a yaml file but as mentioned we might not be willing to create a jaml file so what we're gonna do is to use the kubectl command or kubectl or kubectl however you call it to create a deployment implicitly or interactively without having to create a yaml file we can do it by using the kubectl upgrade deployment i'm going to specify the name of the deployment as spring boot sg and the app image of the deployment which i'm going to choose localhost 500 spring boot sg build pack and notice how i'm using this minus o yaml so that basically generates the output yaml as a yaml file and i'm going to use this dry run dry run simulates the creation of the deployment it's not sending that into our kubernetes cluster it's basically simulating that we create that deployment so that's what this will do is to generate the yaml file corresponding to a deployment i'm going to pipe it to deployment dot jav correct so hopefully we have the deployment created so let's take a look at the the deployment jaml so that's basically my deployment so we see the name of the deployment we see a label we see the replicas as well so by default we get one replica of the application and we see the container that we're going to push into one of these parts so now that we have the yaml file what we can do is to kubectl apply minus f and we pass the deployment dot jaml if we take a look at our cluster let's put it here and we deploy that we'll see that the parts will be created so notice that by deploying or applying the deployment we have a deployment created but also a part created and a replica set created right so remember that's a part is basically the smallest unit of deployment but we have to define how many replicas we want and we also define the deployment so now we have one part and as we see here well this is basically having our container this is running our application internally and what we could do is to change the deployment so i'm going to change the deployment and say well i need a more than one replica i'll be uh or i want three replicas i'm going to deploy that or apply that minus deployment of jaml let's just move to here for a second let's apply that and let's see what happens so here we have one out of one but notice that automatically this will create two other pods right and it will basically start our application now we have three different pods containing our application but these pods are internal we cannot access them as mentioned before so we need to create a service from it great um another thing we can do just real quick is to try to kill one of these pods let's say i want to kill one of these pods and just because we have the replica set we have to see this pod being recreated so i'm going to delete this resource from here i'm going to quickly move into the overview and we'll see that well we have two out of three pods and these will automatically well delete the pod uh that from from um from our cluster and then deploy the new one right so yeah so now we have the three of them up and running so we have detected that one of them was deleted but we needed three pods so we have recreated a new pod so now let's get into creating the service so are we going to use the same approach we'll be creating the service um implicitly without creating a YAML file and we'll do kubectl create service and we have different types of services we'll create a service of type cluster ip that will create a basically an ip right uh inside our cluster right to basically interact with our with our pods but this could be a load balancer if you run within a gke or any other platform and we're going to again right so generate the YAML and we'll do a drive run so that means we're not going to send it to the Kubernetes cluster we'll basically simulate that and send it to a service called a file called service.yaml all right so now we have our service and the service looks like this so it's basically getting access to our pods so we'll need to apply ctl minus apply minus f service we need to apply the service let's take a look at the services real quick and when we apply the service we'll see the service being created here uh that's our created service and notice how it basically has the three pods accessible so that means that if you use the ip of the service you'll be able to access one of these pods or any of these pods but as we are locally what we need to do is to forward the ports from our host machine into the ports of our service are we going to do a port for warding for that just let me open new terminal so we're going to do a port for warding for that so we're going to do keep ctl port forward service the spring boot and we're going to map 8080 to the port 80 so hopefully let me check too many windows here tabs let me check the name of the service um service was called spring boot sg so this needs too much the service so hopefully uh the port for where we'll uh work now and when we access here on our machine local host 8080 so this should actually get into one of the pods and so when we hit that we are actually getting to one of the pods in our Kubernetes cluster all right so um let's take a look at the liveness and the readiness probes in um spring boot to the tree as mentioned we have two special end points that we can configure to um basically define what is an alive application and a ready application so if you use this management.hell that probes that enable equals true you enable those couple of end points if you deploy that into Kubernetes these are already enabled for you but if not uh you can explicitly enable them by using this property remember that we can change the readiness and the liveness by using something called the application event publisher so you have here a class which is nothing more than a rest controller which is exposing a port an endpoint called change readiness so the only thing that this will do is to get the current current state so it will check the current readiness state notice that i'm going to use the application availability which is already in the application context i'm taking it i'm checking the readiness state and if this is equals to application accepting traffic i'm going to change it to refusing refusing traffic and i'm going to publish this event so by just filing publishing this event we're going to change from a ready state to a non-ready state and that will make our port available but it won't get new traffic into it which is quite interesting so what do we need to configure the um um the uh props right the readiness and the liveness props in our um Kubernetes cluster or deployment so we'll be uh let's see we'll see it here i'm going to go to the deployment and i'm going to add a couple of properties right which are the um readiness and the liveness that's here you go so i'm going to set the readiness to equity slash health slash readiness and the liveness to equity slash health slash liveness i have changed my deployment so i'm going to basically apply this deployment real quick keep ctl um apply minus f deployment and hopefully that has changed my change my pots so let's wait a little bit i have something wrong here i'm not sure if i do it right because that should be already up and running apparently i did something wrong in my uh deployment probably there's probably something wrong in the identity of of this uh check that so michael how are we doing with time i think it's okay but there are like quite a few questions for you as well okay so maybe you can uh move on and um leave some time for questions yeah we can go into the chat okay um just a couple of slides um i don't think that the spring put uh two or three introduces is the graceful shutdown um so at the end of the day um if you have a ongoing request and you say i want to terminate the part you cannot leave those requests unprocessed right so you want to finish with those requests and then terminate your application i think it's called graceful shutdown at that point you don't want to accept new requests but you want to wait until everything has finished right and uh that's basically the graceful graceful shutdown which you can enable in spring put the tree with server shutdown graceful and additionally you can define how many seconds you want for a grace period that works for all the server containers both for the server stack and the uh reactive stack so you'll see that when you terminate your pod the pod won't be killed you'll have the grace period to terminate or to uh finish with the request and then your part will terminate right so that's really nice so you don't have uh ongoing requests right and unprocessed and last thing i wanted to show you but we didn't have time to to do it at the end of the day when you are developing uh you you basically go through this build deploy refactor kind of cycle you build your application you have to or actually you change your application you build your container you push it into a registry and then you have to deploy it into kubernetes right and this takes a while some time and you have to maybe uh apply the or create the container apply the the deployment again and many other things so what you can do uh to um be faster well the deploy needs to use a scaffold scaffold allows you to monitor your uh your your source code so when you change the source code it will automatically uh compile the source code create the the image for you deploy it into uh kubernetes and you can see the application up and running into your kubernetes cluster so this will simplify uh a lot right your development uh for sure but you can also use a scaffold for your production environment not only for um for development so if you have liked what you have seen today right i recommend you to check out these couple of workshops right so a really good workshop uh from ran um uh baxter and daysire on spring and kubernetes uh this contains a bunch of the things that we have seen today as how to create the applications with a built and the containers with built packs have deployed that into kubernetes the liveness uh prop the varnish prop and all this stuff scaffold and uh customized and many of the tools actually the uh kubernetes uh environment is huge right so we have a lot of stuff so you'll it is actually a really nice uh workshop to follow and then we have another one from by daysire as well called kubernetes intro which is also exposing or telling you a little bit about uh all these things so that's a they're really similar but the i would recommend you to follow uh both of them they're really detailed and uh they're a great understand how to deploy your applications into um kubernetes and with that i think that uh that's everything from my site um so we can just move into the questions yes again so yeah we have three questions and yes and uh is the first one where from nida we are all around your slide with uh liveness i think so it's what about the spring cloud kubernetes and uh what does bring what does it bring to into the game i think was around your yeah so we haven't talked about spring cloud kubernetes that that's everything that we have seen is on spring boots so without being using spring cloud kubernetes um spring cloud kubernetes will add extra things like being able to use uh this config maps as properties of your application this will allow you to integrate with service discovery and many other cloud projects but again i'd say we are not covering that today but that's actually another project in the portfolio worth checking it i think you're if you want to integrate with config maps and use other parts or bits and pieces of spring cloud as well like service discovery and many other things like client-side load balancing like with ribbon so all this uh integration is part of a spring cloud uh kubernetes thank you after you have a two as a question so i think one um second one is what is the difference between liveness and readiness probes for k8s versus spring boot endpoints okay so uh in spring boot uh before spring boot 2.3 what we usually did is to define the liveness probe as um actuator slash info and the readiness probe to actuator slash health right and um well that was okay but probably health will interact with a lot of external resources and as we now have something called the health groups you can group uh different health checks in a group and we can have more customized health checks uh for kubernetes and that's why spring boot 2.3 adds to endpoints called health slash liveness and health slash readiness that you can customize and at the end of the day those are nothing more than a health check groups that you can define yourself uh what does it readiness mean already mean for your application you have to define define or decide what ready means so the main difference between liveness and readiness is that liveness means that your internal state is uh is okay so how i see it is that you as a standalone process are okay right is you're okay right so that means that nothing wrong happens in your application right um let's imagine that you have a cache and this cache is corrupted right and you cannot live without corrupt cache but if we recreate the container we're going to be able to get an application which is okay which is up and running so i would say that the liveness basically answers the question if i restart your container will we solve the problem if you think about a database right um if the database is done we're starting your container won't solve the problem so that's not it's not something that you might want to put in the liveness check or a liveness probe whereas the readiness basically says i am i able to accept traffic so probably when you start the application you'll have to do some kind of initialization maybe uh i don't know starting the cache or accessing other remote service and at that point you are not ready to accept uh traffic you have to wait and when you have built a cache now that's when you can start accepting uh request i think sergi i think we have quite a few questions which we're running out of time so there are more like ops orientates like how are you managing this can you see the question by the way or yes i can see a question i'm seeing that uh yeah so uh things about service mesh right so well service mesh will build on top of uh Kubernetes uh things like Istio will give you some extra figures uh extras up on top of that uh that's actually uh another topic i would say can you define permifuse kps for readiness and liveness well at the end of the day you can put whatever you want in the readiness check it's it's up to you it's uh basically a health check that you can compose it's basically a group so you have to decide uh what you you want to put in there right but you have to be careful because sometimes when you have uh checks against external resources that might lead to cascading failure so you have to basically decide what makes your application ready and you only know what this means and if you take a look at the spring boot documentation there are some recommendations in there but you'll have to decide what you put in there that's what we cannot decide for you and basically have a uh the right answer for that sorry i i think we have to get the questions because we're gonna run out of time okay very far that's i mean you guys can keep uh checking on on the meetup page if you like you want to take a group picture yes uh if it's possible uh we can uh stop sharing and go to get review and for all the people who want you can just turn on your camera and michael will do uh a small print skin so say just hello to sergi to thank him um and thank the organization so yeah okay so thank you all and uh hope you had a nice um evening and you will be able to see it soon on the recording we'll be on the meetup page thank you all thank you thank you for joining it's all for joining it's really similar to spanish i guess that he kind of for sure ancient spanish together i can hear but it's better with um with alcohol yeah i guess that we can all speak any language with alcohol unfortunately my mexican is coming back after so