WEBVTT

00:00.050 --> 00:01.280
Welcome back, everybody.

00:01.280 --> 00:06.830
Uh, you've seen so far just how excellent of a container orchestration platform Kubernetes is.

00:06.860 --> 00:13.160
It provides so many benefits that allow us to manage our containers effectively.

00:13.310 --> 00:20.150
Okay, so one of these being declarative deployment, how you can so easily declare, uh, your configuration

00:20.150 --> 00:23.060
inside of these YAML files and deploy them.

00:23.420 --> 00:29.120
Um, uh, you've seen just how easy it is to achieve service discovery and container networking using

00:29.120 --> 00:35.390
the service primitive and all the hard work of networking is done for us behind the scenes.

00:35.900 --> 00:40.190
Uh, how easy it is to provision resources for individual containers.

00:40.190 --> 00:45.440
And now we're going to look at another benefit provided by Kubernetes in the form of resiliency and

00:45.440 --> 00:46.070
self-healing.

00:46.070 --> 00:54.110
So to give you some examples, if a container, uh, within a pod fails for whatever reason.

00:54.110 --> 01:00.800
If, um, if the process inside of it terminates, if the application in it fails, regardless of what

01:00.800 --> 01:02.090
the exit code is.

01:02.090 --> 01:08.600
By default, Kubernetes has mechanisms in place to always restart the container to make sure that it's

01:08.600 --> 01:16.100
always available and healthy to serve requests to minimize downtime and ensure that our applications

01:16.100 --> 01:18.900
can always come back to life, if you will.

01:18.900 --> 01:22.860
So let's look at an example right now.

01:23.010 --> 01:23.940
All right.

01:24.720 --> 01:29.310
Um, don't do what I'm about to do for this tutorial.

01:29.310 --> 01:37.350
Just watch me demo the self-healing, uh, feature, because ultimately I'm going to end up resetting

01:37.350 --> 01:40.200
this configuration back to what it is now.

01:40.200 --> 01:40.980
Okay.

01:41.400 --> 01:42.630
Let's start the lesson.

01:42.660 --> 01:51.510
So by default, uh, every container within a pod is subject to a restart policy of always.

01:51.510 --> 01:55.980
You don't need to write this because this is the default restart policy.

01:55.980 --> 02:01.500
And essentially what it means is if a process within any of these containers.

02:01.500 --> 02:04.050
So we only have one container running in this pod.

02:04.050 --> 02:11.610
But let's imagine we have many containers if a process within them terminates, if the app inside fails

02:11.610 --> 02:19.080
for whatever reason, um, no matter what the exit code is, as long as that process terminated, then

02:19.080 --> 02:25.740
what Kubernetes will do according to the restart policy is try to restart that container, try to restart

02:25.740 --> 02:31.800
the process inside of it, try to bring it back to life so that it's ready to serve requests again,

02:31.800 --> 02:37.260
to minimize downtime and try to keep that application healthy for as long as it can.

02:38.220 --> 02:44.880
Okay, now, in order to demonstrate this, the easiest way to do it is to really limit the amount of

02:44.880 --> 02:48.360
memory that this app has access to.

02:48.390 --> 02:56.850
So we'll limit it to initially request 35MB of memory, and we'll cap the memory at that.

02:56.880 --> 03:01.290
Remember, because memory is incompressible, you can't throttle data.

03:01.290 --> 03:08.520
So once we reach that limit, what Kubernetes will do is terminate this process.

03:08.520 --> 03:15.990
And because this process has terminated, uh, the restart policy is going to try to run the container

03:15.990 --> 03:21.460
again, get it back to a healthy state so that it's ready to serve requests, keeping the application

03:21.460 --> 03:26.590
resilient and always ready to start up again regardless of past failures.

03:26.590 --> 03:29.110
So I'm going to delete.

03:29.470 --> 03:32.410
Let me get the pods inside of great submission.

03:35.950 --> 03:39.880
Oh I must have already deleted the great submission API pod.

03:39.880 --> 03:42.160
You should have a great submission API pod.

03:42.160 --> 03:42.820
Keep it.

03:42.820 --> 03:43.780
Don't touch it.

03:43.780 --> 03:49.570
I'm going to redeploy a pod with this with these container configurations.

03:50.860 --> 03:53.110
Oh, I got a CD into section three.

03:56.710 --> 04:03.220
Kubectl apply dash f create submission API pod dot YAML.

04:04.300 --> 04:04.960
Beautiful.

04:05.680 --> 04:06.370
Okay.

04:06.880 --> 04:10.540
Kubectl get pods dash and grade submission.

04:12.340 --> 04:12.940
Wonderful.

04:12.940 --> 04:17.530
I'm going to create a new terminal kubectl port forward.

04:17.530 --> 04:27.370
I'm going to forward this pod port to a static port on my machine, just so that I can flood this application

04:27.370 --> 04:31.000
with requests and try to exceed the memory limit.

04:31.000 --> 04:33.490
So the pod whose pod port I want to.

04:33.700 --> 04:35.050
I want to forward.

04:35.500 --> 04:41.020
It's the great summation API, and inside of the great submission and namespace.

04:41.020 --> 04:46.090
It's not going to find the great submission API unless you tell it to look and the great submission

04:46.090 --> 04:46.840
namespace.

04:46.840 --> 04:54.130
Otherwise it'll look inside of default and the port we want to forward outside of the confines of our

04:54.130 --> 05:02.620
Kubernetes setup is the pod port 3000, and I want to forward it to a static port on my machine 9090.

05:02.650 --> 05:09.730
Okay, so now any request I send to localhost 9090 is going to be forwarded to this great submission

05:09.730 --> 05:12.070
API, this container port 3000.

05:12.070 --> 05:13.570
It's going to serve as requests.

05:13.570 --> 05:15.010
Send us back a response.

05:15.010 --> 05:18.250
And ultimately what am I doing.

05:18.250 --> 05:21.890
Um we minimize this, bring it back.

05:21.920 --> 05:30.590
Ultimately, what I want to do is, um, test how the API performs under load.

05:30.590 --> 05:32.150
Perform a load test.

05:32.150 --> 05:38.240
Okay, I'm going to have 50 or let's say 50 too much.

05:38.240 --> 05:46.400
We'll say 25 virtual users making requests to the application, uh, for ten minutes straight.

05:47.390 --> 05:49.190
We're going to press run.

05:50.210 --> 05:57.650
And as this is happening, I'm going to say kubectl get pods dash and great submission.

05:57.650 --> 05:59.750
It's still running serving requests.

05:59.750 --> 06:00.500
Everything is good.

06:00.500 --> 06:01.310
So far.

06:01.310 --> 06:03.710
My computer is just lagging right now.

06:03.710 --> 06:05.360
That's why you're not seeing anything okay.

06:05.360 --> 06:07.580
Our application is sending us back responses.

06:07.580 --> 06:14.240
The responses are fine so far it's healthy, everything is good, but the responses start getting slower

06:14.240 --> 06:14.870
and slower.

06:14.870 --> 06:15.980
Oh, we're back.

06:15.980 --> 06:20.960
We're back to a good, uh, series of responses.

06:20.960 --> 06:22.370
We'll give it some time.

06:23.000 --> 06:29.570
I'm eventually expecting this application to run out of memory, because I'm flooding it with so many

06:29.570 --> 06:30.770
requests, and it just did.

06:30.770 --> 06:32.780
Now it's sending us back errors.

06:33.410 --> 06:40.280
Uh, so if I say kubectl get pods and great submission, it was already restarted and I wasn't able

06:40.280 --> 06:43.250
to show you the on killed exception.

06:44.000 --> 06:47.090
So what happened was let me stop this.

06:48.140 --> 06:54.590
What happened is the the, um, it exceeded the memory limit of 35MB.

06:54.590 --> 07:02.000
So the container, the process inside of the container was terminated Because it was terminated, Kubernetes

07:02.000 --> 07:08.210
sought to restart it to bring it back to life so that it's ready to serve requests again, which it

07:08.210 --> 07:09.770
indeed just did.

07:09.770 --> 07:14.990
So that's how Kubernetes ensures that our applications are resilient to failure.

07:14.990 --> 07:20.540
It tries to it tries to keep them as available as possible to continue serving requests.

07:20.540 --> 07:26.670
And upon the container dying, the container port didn't exist anymore.

07:26.670 --> 07:27.570
So I accept.

07:27.570 --> 07:32.100
I expect my my port forward to have stopped as well.

07:32.100 --> 07:40.170
So I'm going to re, uh, I'm going to re execute the port forward command and I'm going to try to catch

07:40.170 --> 07:41.970
the OAM killed exception.

07:44.010 --> 07:46.020
Uh we'll run this again.

07:48.660 --> 07:50.700
I think 25 users was fine.

07:54.570 --> 08:00.360
Okay, so we'll let this keep running until the app runs out of memory.

08:12.180 --> 08:15.810
Okay, let's check now because it's a bit delayed.

08:15.840 --> 08:17.760
It's still going so far.

08:17.790 --> 08:18.780
Beautiful.

08:18.870 --> 08:20.790
This response is very slow.

08:28.350 --> 08:28.800
All right.

08:28.800 --> 08:29.640
It's still going.

08:29.670 --> 08:31.170
Oh, it just died.

08:31.590 --> 08:37.200
Cut it o o m killed, uh, by sending so many requests.

08:37.200 --> 08:41.010
Eventually our app ran out of memory, exceeded the memory limit.

08:41.010 --> 08:44.280
Our process in the container was terminated.

08:44.280 --> 08:51.480
But based on the restart policy of always, whenever a container process is terminated, keyword terminated.

08:51.480 --> 08:57.930
For whatever reason, regardless of the exit code, it's going to bring it back to life, which it just

08:57.930 --> 08:58.710
did.

08:58.710 --> 09:04.500
That's what makes applications deployed on Kubernetes so resilient because they have the ability to

09:04.500 --> 09:06.180
self-heal after failure.

09:06.180 --> 09:10.530
So I demonstrated one failure, which is the running out of memory failure.

09:10.530 --> 09:15.960
But there are many types of failures that can occur, failures that occur within the application if

09:15.960 --> 09:22.440
they're not programmed correctly, regardless of the failure, if they happen, Kubernetes will try

09:22.440 --> 09:24.240
to bring it back to life.

09:24.240 --> 09:28.720
It will restart the container, hoping that it's ready to serve the next batch of requests.

09:28.750 --> 09:32.710
Okay, I'm going to put this back to 128MB.

09:32.710 --> 09:37.720
Don't need to specify the restart policy of always because that's what it is by default.

09:38.140 --> 09:40.480
And yep that's it guys.

09:40.480 --> 09:42.010
See you in the next one.

09:42.010 --> 09:46.480
And now I know I didn't show you how to use postman, but this is not a postman.

09:46.510 --> 09:46.840
Course.

09:46.840 --> 09:53.740
I just wanted to demonstrate uh, self-healing and how it's achieved in Kubernetes.

09:53.740 --> 10:00.580
And to show you just what you have at your disposal when you deploy your apps in a Kubernetes cluster.

10:00.580 --> 10:00.820
Okay.

10:00.820 --> 10:04.120
But you don't actually need to download postman and set up the runner.

10:04.120 --> 10:11.320
There's no point because I've reset my configuration to what we had previously, and in the next section

10:11.320 --> 10:13.150
we're going to move on to discuss deployments.

10:13.180 --> 10:14.020
See you then.
