WEBVTT

00:00.020 --> 00:02.180
This section is going to discuss service discovery.

00:02.180 --> 00:07.490
But before we start this section off, please delete all the pods that we've deployed so far.

00:07.490 --> 00:13.490
So kubectl delete pods, dash, dash all to delete all the pods in the current context.

00:14.240 --> 00:17.330
That's going to delete the API pod, the portal pod.

00:17.330 --> 00:23.030
So once you've done that then feel free to unpause the video so we can start this lesson.

00:23.030 --> 00:28.760
Port forwarding isn't a very reliable way to access our application.

00:28.760 --> 00:32.180
We need something more stable, something more durable.

00:32.180 --> 00:39.620
And that's going to be the main theme of this lesson a Kubernetes primitive that provides us with stable

00:39.620 --> 00:41.840
endpoints to access our pods.

00:41.870 --> 00:45.410
Now you'll notice I just created a folder called section two.

00:45.650 --> 00:45.950
Okay.

00:45.980 --> 00:51.290
What I want you to do is copy the pod definitions we have so far into the section two folder.

00:51.290 --> 00:52.460
We're done with this one.

00:52.460 --> 00:53.210
We've deleted.

00:53.240 --> 00:58.160
We've deleted the pods um associated with its definitions.

00:58.160 --> 01:00.350
And then these new pod definitions.

01:00.350 --> 01:01.730
Delete the health checkers.

01:01.730 --> 01:02.980
We don't need them.

01:02.980 --> 01:08.920
I just wanted to demonstrate to you the sidecar pattern, where you have one app that simply can't exist

01:08.920 --> 01:10.720
without the creation of another app.

01:10.720 --> 01:16.900
In this case, put them in the same pod where they are created and destroyed together, where they share

01:16.900 --> 01:18.250
the same network namespace.

01:18.250 --> 01:23.500
But in this case, we don't need health checkers, because Kubernetes automatically provides the liveness

01:23.500 --> 01:27.130
and readiness probes that you can leverage out of the box.

01:27.130 --> 01:30.640
I'll show you how to leverage these probes in another section.

01:30.640 --> 01:36.490
But anyway, we're not going to create containers that we don't need so that they can consume valuable

01:36.490 --> 01:37.810
memory and CPU.

01:37.840 --> 01:39.610
Okay, we'll delete those.

01:39.610 --> 01:42.880
We don't want to demo the sidecar pattern anymore.

01:43.690 --> 01:45.100
And let's start this lesson.

01:45.940 --> 01:51.610
Every pod in Kubernetes is given a virtual IP address.

01:51.610 --> 01:59.950
If we think of an IP address as, um, a sequence of characters that identifies the location where our

01:59.950 --> 02:08.670
app is running, then technically we can connect to our app by specifying the IP address, the location

02:08.670 --> 02:13.170
where it's running, followed by the port where it's serving requests.

02:13.230 --> 02:20.130
Okay, this all makes sense until you realize that pods in Kubernetes are ephemeral.

02:20.160 --> 02:21.810
They're not durable.

02:21.840 --> 02:24.930
Pods are constantly created and destroyed.

02:24.930 --> 02:30.390
That's how Kubernetes performs scaling, self-healing, and so on and so forth.

02:30.390 --> 02:35.340
And whenever these pods are created and destroyed, they're given new IP addresses.

02:35.340 --> 02:41.670
So pod IP addresses are not a very reliable way of accessing our applications.

02:41.670 --> 02:50.310
So here we have a pod that is initially confined within the Kubernetes setup that's running on our local

02:50.310 --> 02:50.850
machine.

02:50.880 --> 02:58.080
Remember because we're prototyping, our Kubernetes cluster is just composed of one node, one machine,

02:58.080 --> 03:00.600
your laptop, your desktop, whatever it may be.

03:00.960 --> 03:06.170
And in order to be able to access this, um, great submission portal.

03:06.170 --> 03:11.240
Externally, through our browser, we specify a node port service.

03:11.240 --> 03:15.200
Remember the node being our machine, our local machine.

03:15.200 --> 03:23.630
What the node port service is going to do is it's going to open a static port on your node on your computer.

03:23.630 --> 03:29.030
That static port typically ranges between 30,000 and and 32,000.

03:29.030 --> 03:32.690
And so then we can say localhost 32,000.

03:32.690 --> 03:37.400
And that kind of gives us an entry into our Kubernetes setup.

03:37.400 --> 03:40.280
So our request has made it inside of Kubernetes.

03:40.310 --> 03:45.500
Now we want to direct that request to the great submission portal pod.

03:45.500 --> 03:48.290
And that is done using a label selector.

03:48.290 --> 03:55.370
So the great submission portal has these labels that identify it and categorize it into distinct groups.

03:55.370 --> 04:00.560
And we can query this labeled pod using a label selector.

04:00.770 --> 04:05.830
So at this point we've forwarded that traffic to the appropriate pod.

04:05.830 --> 04:13.990
And then once that traffic has been forwarded, the target port that we specify in the node port service

04:14.020 --> 04:21.100
ensures that that request ends up going to the pod port where our application is serving requests,

04:21.100 --> 04:23.500
which ultimately sends back a response.

04:23.500 --> 04:26.230
And we've essentially accessed our app.

04:26.230 --> 04:28.540
So that's one scenario.

04:28.960 --> 04:33.250
Now you'll notice here that the pod IP addresses are changing.

04:33.370 --> 04:38.800
This implies a scenario where the old pod was destroyed for whatever reason.

04:38.800 --> 04:40.690
Maybe it failed and was restarted.

04:40.690 --> 04:43.840
And then a new pod was created with a different IP address.

04:43.870 --> 04:48.880
Well, in this case, we're not connecting to the pod using its IP address.

04:48.910 --> 04:51.010
Not directly at least.

04:51.040 --> 04:58.990
The label selector is querying the pod based on whatever labels it has and forwarding traffic to it.

04:59.020 --> 05:05.980
Now, behind the scenes, what happens is a kube proxy is going to find the pod with the matching labels.

05:05.980 --> 05:11.700
And it knows what that party's IP address is and forwards it that request accordingly.

05:11.700 --> 05:15.450
But we don't need to worry about what's happening behind the scenes.

05:15.450 --> 05:23.100
All we need to know is that the node port service uses label selectors to forward external traffic to

05:23.130 --> 05:24.570
the appropriate pod.

05:25.950 --> 05:34.260
Now let's imagine a scenario where we're actually ready to deploy a real Kubernetes cluster on AWS with

05:34.260 --> 05:35.910
many, many worker nodes.

05:36.120 --> 05:43.710
If we deploy a node port service, what it's going to do is open up a static port on every single machine,

05:43.710 --> 05:48.810
on every single worker node, even the ones that aren't running our app.

05:48.840 --> 05:52.290
This is very, very bad, mainly for security reasons.

05:52.290 --> 05:53.820
It's very clunky.

05:53.850 --> 05:57.030
It makes things very hard to scale.

05:57.060 --> 06:02.700
I'll go over the disadvantages later once we talk about ingress and load balancing.

06:02.700 --> 06:07.710
But ultimately node port is never something that you'd ever, ever use in production.

06:07.710 --> 06:15.230
We use it for prototyping when we have only one node that makes up our Kubernetes cluster, in this

06:15.230 --> 06:16.550
case our local machine.

06:16.550 --> 06:23.930
So in real life, you'd never actually use node port to expose your pods for external traffic.

06:23.960 --> 06:24.830
Okay.

06:24.830 --> 06:28.160
And I added a screaming cat just to emphasize this.

06:30.140 --> 06:30.590
All right.

06:30.590 --> 06:35.390
So a node port service is used to access applications externally.

06:35.390 --> 06:37.340
We mainly use it in prototyping.

06:37.340 --> 06:40.100
Let's go ahead and look at an example right now.

06:40.400 --> 06:46.220
So um here I'm going to create a new file called grade submission.

06:48.320 --> 06:54.020
Portal service dot YAML I'm going to say service.

06:54.020 --> 06:58.370
And thanks to our Kubernetes extension we get the auto generated YAML.

06:58.880 --> 07:02.720
Uh my app is great submission portal.

07:03.770 --> 07:06.680
So I've given the service a name.

07:06.680 --> 07:09.910
And here is the label selector.

07:09.940 --> 07:18.040
The label selector is what we use to query the pod in order to know where to forward traffic.

07:18.070 --> 07:25.510
So we're going to forward traffic to any pod that has the label app Kubernetes.io slash name or no app

07:25.510 --> 07:27.520
dot Kubernetes.io slash instance.

07:27.520 --> 07:29.110
Great submission portal.

07:29.440 --> 07:35.920
So through the selector we've created a link between the great Submission portal service that's going

07:35.950 --> 07:43.480
to receive external traffic to the Great Submission Portal pod, which will respond to requests.

07:44.140 --> 07:45.040
All right.

07:45.070 --> 07:52.120
Now here we specify the service port the target port and the node port.

07:53.050 --> 07:54.100
All right.

07:54.370 --> 08:00.820
Because ultimately this service remember is going to be of type node port.

08:00.820 --> 08:06.130
So under spec I'm going to say type node port.

08:07.270 --> 08:12.690
Uh so the target port is going to be 5001 the node port.

08:12.690 --> 08:14.520
I'm going to say 32,000.

08:14.550 --> 08:19.890
Usually the node port is limited between values of 30,000 to 32,000.

08:19.890 --> 08:22.530
So make sure to specify a value in that range.

08:22.530 --> 08:28.740
The service port allows for internal access will make it the same value as the target port.

08:28.770 --> 08:32.520
Let's just go ahead and say kubectl apply or no.

08:32.550 --> 08:35.190
We'll have to go inside of section two.

08:37.320 --> 08:43.350
Um we'll go inside or we'll just say kubectl apply dash f.

08:43.350 --> 08:50.250
Great submission portal pod dot YAML kubectl apply dash f.

08:50.250 --> 08:56.640
Great submission service, great submission portal service dot YAML.

08:58.560 --> 09:01.350
And now a port has been exposed.

09:01.350 --> 09:08.190
A static port hasn't been exposed on our node such that if we say localhost 32,000, that request is

09:08.190 --> 09:15.500
going to be forwarded to the pod that has this label grade submission portal.

09:15.530 --> 09:24.620
And then once the pod receives that request, the target port ensures that it goes to the pod port 5001,

09:24.620 --> 09:28.760
where that request will get processed and a response will be sent back.

09:28.790 --> 09:30.530
Let's go ahead and try it out.

09:34.610 --> 09:36.500
Localhost 32,000.

09:37.850 --> 09:39.020
Wonderful.

09:39.170 --> 09:41.750
Now when we submit grade data.

09:45.650 --> 09:55.730
Nothing happens because we need to instrument our grade submission portal to connect to the grade submission

09:55.730 --> 09:58.730
API pod, which we've not deployed yet.

09:58.730 --> 10:03.950
And that connection is going to be made through a cluster IP service.

10:03.980 --> 10:09.050
The conduit is going to be a cluster IP service.

10:09.050 --> 10:12.610
The conduit for internal pod to pod Communication.

10:12.610 --> 10:15.640
Now a cluster IP service is given.

10:15.640 --> 10:21.520
As the name implies, a cluster IP address that can be used to communicate with it.

10:21.550 --> 10:28.570
Now, you don't actually have to know the IP address, because the name of your cluster IP service will

10:28.600 --> 10:30.970
automatically resolve to it.

10:31.000 --> 10:38.440
So the Great Submission portal can interact with the cluster IP service by making a request to the service

10:38.440 --> 10:47.710
name, followed by the service port, a logical port that allows us to interact with the service itself.

10:47.740 --> 10:54.640
And then once that request from our great Submission portal has been sent to the cluster IP service,

10:54.670 --> 11:03.100
it's going to forward that request to whatever pod whose label matches the label selector.

11:03.160 --> 11:03.790
Okay.

11:03.790 --> 11:09.700
And once that request has been forwarded to the right pod, in this case, the great submission API

11:09.730 --> 11:19.920
pod that target port ensures that that request gets sent to the port where requests are being processed

11:19.920 --> 11:22.830
by the actual grade submission API app.

11:22.830 --> 11:31.080
So in this case, in a cluster IP service, we just define the service port and the target port.

11:31.080 --> 11:34.980
So let's go ahead and orchestrate this I'm going to create a grade.

11:36.900 --> 11:48.210
What am I doing within section two I'll create a new file a grade submission API service dot YAML.

11:49.170 --> 11:55.470
Um I'm going to say service auto generate the skeleton app name grade submission API.

11:55.500 --> 12:03.570
Under spec, we specify how we want the service to behave, such that it's going to select any app that

12:03.570 --> 12:05.670
has the following label.

12:06.210 --> 12:11.760
It's going to query apps that have this label and forward any traffic.

12:11.790 --> 12:21.020
Get that gets sent to it's service port 3000 to a target port of 3000 as well.

12:22.190 --> 12:22.910
Okay.

12:23.120 --> 12:24.290
And that's pretty much it.

12:24.320 --> 12:27.350
I'm going to go ahead and say kubectl apply dash f.

12:27.350 --> 12:31.820
Great submission API service dot YAML.

12:32.750 --> 12:39.380
Uh great submission API dot YAML or pod dot YAML.

12:41.510 --> 12:42.320
Beautiful.

12:42.350 --> 12:47.630
So now we've got let me go ahead and say kubectl get pods.

12:47.720 --> 12:53.390
We've got two pods each one running one container kubectl get services.

12:54.740 --> 12:57.230
We've got two services.

12:57.230 --> 12:58.160
You can ignore this one.

12:58.160 --> 13:04.460
It's created by default one great submission API cluster IP service and one great submission portal

13:04.460 --> 13:06.410
node port service.

13:06.410 --> 13:14.450
So this service has been set up to forward all traffic to any pod that matches this label.

13:14.450 --> 13:22.000
And then once that traffic gets there, it's going to ensure that the target port within this pod is

13:22.000 --> 13:26.080
able to receive the traffic and send back a response.

13:26.110 --> 13:32.260
Okay, but how do we make sure that the Great Submission Portal actually sends a request to the Great

13:32.260 --> 13:34.600
Submission API service?

13:34.600 --> 13:37.630
How can we get it to make this request?

13:37.660 --> 13:40.180
Well, let me show you some code.

13:40.210 --> 13:43.510
This application was programmed.

13:43.510 --> 13:45.700
This is something your developer would need to do.

13:45.700 --> 13:52.090
This application was programmed to receive an environment variable, a variable from the environment

13:52.090 --> 13:57.670
that it's running in, in order to fill this URL with the correct host.

13:57.700 --> 13:58.210
Okay.

13:58.210 --> 14:02.260
So this application, this portal has been packaged up into an image.

14:02.260 --> 14:07.540
And subsequently a container was created from this image.

14:07.540 --> 14:15.250
And the container must give the underlying app that's running in it the environment variable that it

14:15.250 --> 14:19.260
needs in order to make requests at the correct URL.

14:19.260 --> 14:25.470
In this case, the URL needs to be grade submission.

14:25.500 --> 14:32.640
API needs to refer to the service name followed by the service port, which was already hard coded into

14:32.640 --> 14:33.690
the app.

14:33.960 --> 14:41.820
Okay, how do we ensure that the container gives its underlying application an environment variable?

14:41.850 --> 14:42.870
Very simple.

14:42.870 --> 14:51.420
Here we say env such that the container is going to give its underlying app one environment variable.

14:51.420 --> 14:55.590
The underlying app has been programmed to expect the environment variable.

14:55.620 --> 14:59.400
Grade service host okay.

14:59.580 --> 15:09.090
And we're going to set the grade service host to have a value of grade submission API.

15:09.090 --> 15:17.670
So once this environment variable penetrates our app, it it will resolve to sending requests to the

15:17.690 --> 15:29.810
following URL, and it should therefore be able to connect to the cluster IP service at its service

15:29.840 --> 15:35.900
port, which will in turn forward that traffic to the correct pod by virtue of having the correct label

15:35.930 --> 15:38.390
selector matching that pods label.

15:38.390 --> 15:44.360
And the target port that we define over here is going to make sure that the request goes to the container

15:44.360 --> 15:48.080
port where our great submission API is listening for traffic.

15:48.110 --> 15:57.710
And that's all guys I'm going to go ahead and say kubectl apply um, dash f everything inside of section

15:57.710 --> 15:58.430
two.

15:58.910 --> 16:02.300
So we can just say dot to say current directory.

16:08.510 --> 16:09.140
Oh.

16:12.020 --> 16:14.000
Let me go ahead and delete the pod.

16:16.400 --> 16:18.260
Great submission portal.

16:22.750 --> 16:23.710
Okay.

16:24.340 --> 16:31.360
Then I'll say kubectl apply dash f create submission portal pod dot YAML.

16:35.020 --> 16:43.330
So now the pod was recreated such that the container is giving its underlying app the environment variable

16:43.330 --> 16:46.930
that it needs to connect to the service.

16:47.260 --> 16:48.670
I think we should be good guys.

16:48.670 --> 16:50.170
Let's go ahead and test it out.

16:54.160 --> 16:58.510
So I accessed the first app using a Nodeport service.

16:58.510 --> 17:00.280
Everything is working fine so far.

17:00.310 --> 17:08.920
Now, um, as I submit GRE data to the front end, we expect the front end to make that request to this

17:08.920 --> 17:12.670
cluster IP service, forwarding it to the Great Submission API.

17:12.700 --> 17:13.900
Will that work?

17:13.930 --> 17:19.360
Harry will give him a 64 in potions.

17:19.390 --> 17:20.670
Fingers crossed.

17:20.700 --> 17:21.600
Submit.

17:21.930 --> 17:22.860
Beautiful.

17:22.890 --> 17:24.300
Ignore the ugly UI.

17:24.330 --> 17:28.560
The app doesn't run well on Safari, but it is what it is.

17:28.560 --> 17:29.970
And that's pretty much it.

17:29.970 --> 17:30.810
Guys.

17:30.810 --> 17:32.520
Hope you enjoyed this lesson.

17:32.520 --> 17:42.840
I hope it's clear why we want the service port and the target port to match, because from the application's

17:42.840 --> 17:48.150
perspective, it doesn't know that it's making requests to a cluster IP service.

17:48.150 --> 17:56.430
This looks like it's making requests directly to the Great Submission API at its normal port.

17:56.430 --> 18:00.510
And that's simply because we named the service Great Submission API.

18:00.510 --> 18:07.350
And we made sure that the service port that we specify matched the container port itself.

18:07.350 --> 18:15.120
So that's pretty much the difference between a cluster IP service and a node port service one is used

18:15.120 --> 18:18.840
for external access, one is used for internal pod to pod communication.

18:18.840 --> 18:19.620
That's all.

18:19.650 --> 18:20.940
See you in the next section.
