Link to talk: https://springoneplatform.io/2018/sessions/all-you-need-to-know-to-deploy-applications-on-kubernetes
[E & A] - intros
[E] Ok, let's get started. We're going to show you All you need to know to deploy apps on k8s. We spent a lot of time thinking about how to make this as straightforward as possible. So, here you go...
[E] All you need is YAML! If you're having trouble reading it, please move closer to the front. Since this is really all you need, we'll give you about 20 minutes to read through it and then take questions.
[E] Ok... bad joke! While this is a comprehensive example of the YAML needed to deploy an app to k8s, we'll explain this in more detail.
[E] Oh, and we're not really going to cover "ALL you need to know..."
[E] There's a few things we're going to assume you have some knowledge of and other best practices for deploying and operating k8s. For a common starting point, let's assume we have an application in mind and know the basics of packing it as an image and storing the image in a repository. And while we're not going to go into details here, we're going to assume you have access to a Kubernetes cluster. For our talk, we'll be using Google Kubernetes Engine already pre-provisioned for us.
[E] The talk will really focus on these necessary aspects of an app on k8s. How to deploy, access, and make sure it's available.
[E] Since this is a Spring conference, we thought a good app to use would be the Spring Music sample app. If you're not already familiar with it, this is an excellent way to get started with Spring Boot (and if you're so inclined, deploying it to Cloud Foundry). But in this case, we'll deploy to K8s.
[E] Alright, let's get started. Alex, let's go back and look at that wall of YAML and highlight what you need to know with respect to deployment.
[A] First, we need image used for the application, it should be runnable, and versioned. There are multiple guides for how to building docker images.
We'll pull this image when we deploy and when later when scaling up.
Runnable for local developement
And we'll be using a Spring app for the demo
When you have the image, you now build the container
You'll need name, location, and policy. When we scale up, the imagePulPolicy means to pull the latest image. This is why nicknames/versions are important. The version name can be anything you like but should not be mutable (any changes to your app should result in a new name/version.
[A] There are two ways to configure. You can use environment variables (map of name/value). The other way is to use volumes for example a confgmap where the configuration is stored within k8s. For example, you can store your spring boot app properties in the config map.
[E] Oh, I didn't you could do two ways. Which is the preferred way, or what you recommend?
[A] It depends!!! But, one nice feature of using configmap with spring cloud library is that it checks for configmap changes and recreate your container when you change something.
[A] There are two ways to configure. You can use environment variables (map of name/value). The other way is to use volumes for example a confgmap where the configuration is stored within k8s. For example, you can store your spring boot app properties in the config map.
[E] Oh, I didn't you could do two ways. Which is the preferred way, or what you recommend?
[A] It depends!!! But, one nice feature of using configmap with spring cloud library is that it checks for configmap changes and recreate your container when you change something.
A container is a minimal runnable process - but for K8s the minimal entity "pods". It allows group multiple containers in a pod and including shared storage. All those containers will be started together.
You should consider separating functionality of your app into separate pods. For example, keep your database pods separate from your application pods. This will allow you to more easily scale your application and/or database independently.
[E] But how would you handle something like a database migration?
[A] You can use initContaiers for something like that. If you need to perform operations on the database, or configuration changes, then initContainers allow you to execute commands before the pod is created. For deletion you can use some hooks, but lets not jump ahead ( slide about graceful shutdown
[A] But don't use pods directly for deploying an application
[E] Why is that Alex?
[A] Pods are connected to a single node, if a node goes down, the pod (as a primitive) won't be rescheduled by k8s. Another good reason is scaling up/down. Also, pod is immutable. If you want to change something, you have to delete old pod and create a new one.
Kubernetes has abstraction to keep specific amount of pods up and running. But it does not include updates. So for green-blue deployments it has a special object called Deployment
Deployment specifies all the definitions that required to run the application and helps with upgrades, it also allows to rollback to previous working version .
[E] How does deploy?
[A] Under the cover deployment creates a replicaset. For each change, it creates a new replicaset and gradually create new pods and delete old ones.
By default it ensures that at most 25% extra pods created and at least 75% of desired amount of pods are available at any given time.
[E] What is the order the deletion happen?
[A] There is no order. If you need some order for your application, you should use stateful set
AS the name suggests, stateful sets help with the applications that have state. For example that use disk, or that have to be started in specific order.
???
[E] why do you need to create internal service?
[A] I told you that pods are immutable. So every time you change something – pod is recreated. That means that every time you change something – pod IP address is going to change. Services have their own network and have the same ip address all the time which will be resolved to different pods.
External lserice exposes port on the node which then points to the service ip address. Load balancer points that exposed port. So each service just adds something down the way.
[E] So when I have a service and new pod is created, it starts to receive traffic from the service?
[A] Yes, when pod is ready, it starts getting traffic.
And there is a way to show that pod is ready.
[A] Obviously, to make your application highly available you need several replicas. As I mentioned before, pods can be terminated at any moment.
[E] Will 3 replicas be deployed on separate VMs?
[A] Kubernetes by default tries to schedule pods on different nodes, but there is no guarantee.
[E] Why there so many options? (????)
[A] It is very configurable and supports multiple use-cases.
First affinity and antiAffinity, so deploy pods when condition match or not deploy. This long key says require this condition to match before scheduling. There is also preferred.
Next - label selector. It can have labels that are not set by your application.
You can have additional replicas that do not receive traffic and deploy them on the nodes that do not have main service.
As you can see pod anti affinity is an option, there is also affinity option that requires pods to be on some condition match.
Topology key allows to choose where to deploy application by hostname, availability zone or instance type.
[E] So should I always use requiredDuringScheduling?
[A] Not really. It guarantees that pods will be scheduled on different virtual machines. But it also won’t let you scale above the amount of VMs.
[E] But if I have multiple pods on the same node, they will all be unavailable during the upgrade (???)
[A] It can be fixed with Pod Disruption budget
[A] Pod disruption allows you to specify how many pods could unavailable at any given moment or how many should be available
This can help,during upgrade or rollout of Kubernetes deployment. Especially when stopping the pod takes time.
[E] I thought that upgrade just destroys the container
[A] No, the developer can actually control the deletion.
[A] And should control to provide graceful shutdown.
There are three steps to stop each pod. First, pod is marked that it is deleting. After that the pod is removed from service backend, and pre-stop hook is executed. After it finishes or grace period expires, each container gets SIGTERM signal. If the application is not closed after grace period it is killed.
[E] Spring handles SIGTERM signal, so it possible to add shutdown hook to finish processing.
(Transition t the next slide ??? )
[A] This are the nice-to-haves. It worth checking them after you have can start your application in K8s.