 In this talk, I want to look at Kubernetes from a developer point of view, more from a Java developer point of view. So I work with Red Hat as an architect. I contribute to few Apache projects and I have two camel related books. So more and more businesses are moving to microservices, and that has been further enforced by making containers accessible to developers to Docker, which in turn enabled DevOps practices. I'm saying that all these forces do change the way we design, implement, and manage Java applications. If you don't change the way you design the applications, you won't succeed in microservices. So what is a Cloud Native? There are many definitions out there and I just added mine. A Cloud Native for me, these are applications which are implemented following microservices principles. They typically run on containers which are managed by platforms on some kind of Cloud infrastructure. By Cloud, I don't mean necessarily Amazon, but more infrastructure that can scale up and down, that can come and go, and if you don't design your application to succeed to survive in this kind of environment seat, you won't succeed with microservices. That also means that any container orchestrator is basically a Cloud Native platform, and there are many of those as you can see on this diagram. In this talk, we'll look at Kubernetes more in-depth, but all of these container orchestrator engines are maturing at the moment and they provide similar capabilities, and more or less they have a future parity at the moment. I think your application will need to have this Cloud Native design patterns if you want to run your application in one of these environments. The bottom two are slightly different. They are actually the one who coined the term Cloud Native from Spring Cloud and Netflix OSS, but they were started way before containers were popular. So they are more based on Amazon images and having a Cloud Native platform as a part of your Java application rather than a separate thing. Now, let's say you decided to use Kubernetes as a developer. There are actually a number of ways to run Kubernetes just by using your mouse without have to run any scripts. So Google Cloud and Microsoft has a Kubernetes cluster as a service. Red Hat's OpenShift Online, you can create an account and use a multi-tenant environment. So basically you share your cluster with other users. But probably for developers, the more interesting options are Minicube which is a lightweight VM where you can run it locally and have a Kubernetes running, or the Fabric8 Maven plugin which relies on Minicube but allows you to manage your Kubernetes cluster straight from Maven. So as a developer, you can start and stop Kubernetes cluster from Maven. You can deploy your application, update it, etc. A few words about Fabric8. It's a project that enables developer to write microservices on Kubernetes. So if you are a Java developer and looking at Kubernetes, it's a really good place to have a look and to start from. You have to learn a few Kubernetes primitives and concepts. So inevitable, there is some learning curve. So you have to know containers, both labels, namespaces, etc. But once you started with Kubernetes, the next step is you have to write your Java application and package it here. We can see which one is the most popular framework at the moment. That's the spring put. But following the same trend, other frameworks such as Wildfire, Swarm and Carav are also turning into this Uberjar format. So at compile time, you create your application as a Uberjar with all your dependencies, which makes it easy to put in a Docker container. All of these frameworks, basically offer you things like HTTP server, REST, JSON, health checks, etc. Once you have your application written in Java, the next step is to put that in a Docker container. There are a number of issues when you want to put Java in a Docker container. Do you want to put the JDK or Jerry if you put the Oracle JDK in a Docker container and push that Docker container to Docker Hub. You might be violating Oracle licenses, so you might have to use Oracle OpenJDK. Other issues around CPU and memory, for example, Java at the moment doesn't see the memory that's allocated to your container, but it sees all the memory on the host. Similarly for CPU, it sees all the cores on the host rather than just the cores specified for your Docker container. I've put here a few examples and workarounds how you can get around those, and the OpenJDK issue numbers which fix these issues. So future versions of Java will be easier to run in Docker, but at the moment you have to do some kind of work around and basically there are a lot of container best practices you have to learn before going into containers and Kubernetes. Again, there is a Maven plugin from Fabric which allows you to build a Docker container from Maven. So at the end of your build process, in addition to your regular Maven built, you get the Docker container that's built from your project. The good thing is it's based from your POM file. So your POM and your Docker image are in sync if you add a new dependency to your POM that gets into your Docker image. Once we have our Docker image, the next step is talking to Kubernetes, basically telling it how to run our Docker image. The way to do that is basically you have to write, I called it application descriptor, but that's either JSON or YAML, and you have to tell it how much resources to give to your Docker container, what dependencies it has, what ports it needs, etc. With Maven plugin from Fabricate, you can generate such a YAML file, again, directly from Maven. At the bottom, I put an example, a couple of Maven commands. So with the first one, we can start Kubernetes. With the second one, we can build a Docker container, and third one, we deploy Docker container into Kubernetes. This makes Kubernetes almost like your application server running locally, where you can easily start, deploy your Docker containers, update them, shut it down, etc., etc. Now, for your application to be Cloud-native or to run on Kubernetes on similar environments, it needs to provide certain capabilities, and the first one is it has to be observable. What I mean by that is it needs to have endpoints where the managing platform can check its health status. We can see that popular projects such as Spring Boot, Drop Wizard, Wildfly, they all have libraries which allows you to expose the health status of your application. So your application needs to tell that it's healthy that it started, etc., etc. Kubernetes by default will check that the Docker process of your container is up, but that's usually not enough. We have seen in the Java world, many examples where the JVM throws out of memory exceptions or the JVM is still up, but it's actually not functioning. So to catch these issues, we have health checks. Actually, the concept of health checks is so important that it was added to Java EE proposal. You can see at the bottom health checks and configuration management. So at some point, it will become part of Java, but unfortunately, I believe it was revised again and it has moved to Java 9. But you don't have to wait for Java 9. You can use any of the existing libraries and just add health checks to your application. The other important piece is your application needs to listen to the signals that are coming from Kubernetes and similar platforms. Basically, your application needs to stop when it gets sick term otherwise it will get killed in 30 seconds. Similarly, there are other events like pre-stop, post-stop, you have to listen and maybe you have to do something. In the future, there might be signals, for example, for your application to shrink and consume less resources or maybe to replicate itself, et cetera, et cetera. Here is another example about service discovery and law balancing. In the Java world, what we used to do is, when we write and produce a service and we scale that, typically we have in the JVM some agent, like a Zookeeper agent or a Eurica agent that registers the server into some registry and the service consumer also has a similar agent and looks up in the registry and this is how you find the service. In the Kubernetes world, actually all that is handled by the platform. Well, with Kubernetes you don't need any more agents or actually you are also not tied to Java. Your services are directly registered by the platform and then also updated in the proxy. So on the consumer side, when you call a service, you just call the proxy and the proxy finds a instance of the service and it does law balancing, et cetera, et cetera. So we can see this is just an example how some kind of non-functional or close functional requirements are moving away from the JVM to the platform. So you don't have to care about all that in your Java application. Once you have health checks and listen to events and service discovery, basically this allows you to further do till it's like rolling the deployments.