[MUSIC PLAYING]
SPEAKER: With a whole universe of things to learn,
it's important to start with the essentials.
Let's go over the concepts that make
Kubernetes usable, scalable, and just downright awesome.
Are you ready?
KASLIN FIELDS: Hello.
I'm Kaslin Fields.
I'm a developer advocate at Google Cloud,
where I focus on Kubernetes and Google Kubernetes Engine.
Today, we're going to be demonstrating
what it's like to get hands-on with some Kubernetes
essentials.
And to guide us, we have an expert, Anthony Bushong.
Anthony, would you introduce yourself?
ANTHONY BUSHONG: Yeah, happy to.
Thanks for having me here, Kaslin.
My name's Anthony Bushong.
I'm a specialist customer engineer at Google.
I'm focused on working with users
who are trying to run Kubernetes on GKE in production.
KASLIN FIELDS: Wow.
So you must have some really cool insights
into how this stuff works in the real world,
so I'm really excited to see what
you're going to teach us today.
ANTHONY BUSHONG: Definitely just trying to build on the concepts
that you and Carter have introduced in previous episodes
of "Kubernetes Essentials."
Specifically, we're going to take a look
at how you can work with namespaces and services
when something is going wrong with the deployment
of your application in Kubernetes.
They each have respective properties
that we can take a look at to help us debug
and help us remediate whatever issue we're
running into in our Kubernetes environment.
KASLIN FIELDS: Cool.
So what are we going to start out with?
ANTHONY BUSHONG: Well, for starters,
we're going to have a sample application running
in a Kubernetes cluster.
And that sample application is comprised
of a frontend pod, which is fronted by a service-type load
balancer, so we have a public IP address so we can access it
in a browser.
And that frontend pod is communicating
with the backend pod.
And so the backend pod is returning a whole bunch
of information and metadata about the environment
in which it's running.
And we can actually see here the specific requests
that the frontend is issuing to the backend.
If we take a look at the Kubernetes manifest,
we'll see here that they're both represented by deployments,
and they each reside within their own specific namespaces.
So in this specific scenario, we have the frontend
that is managed by Team A, running in namespace team-a.
And then we have the backend application,
which is owned by Team B, running in namespace team-b.
KASLIN FIELDS: Cool.
So here we have a website which has a frontend and a backend,
and the frontend and the backend are each
owned by separate teams.
And those teams are utilizing different namespaces.
So what are we going to look into next?
ANTHONY BUSHONG: Well, we're going
to take a look at the namespaces a bit
further so that we can understand what constraints
could actually be defined at the namespace level that
might actually affect the deployments of our pods
and applications.
So as you can see, namespaces are a great way
to divide the resources within a given
cluster across various teams.
And namespaces give you a lot of control
between what you can actually access within a given cluster.
So as you can see here, we have the frontend
is owned by Team A, and we have a namespace called team-a.
And then we have the backend, which is owned by Team B,
and it's in the namespace team-b.
KASLIN FIELDS: Cool.
So let's take a deeper look at these namespaces.
ANTHONY BUSHONG: So when digging into the namespaces
within a given cluster, it can often
be a bit difficult to navigate and understand
which namespace you're working against.
So the kubens tool is a great tool
to show all the namespaces in your cluster,
as well as which one your Kubernetes context is currently
configured to interact with.
Once we know what namespace we're working with--
team-b in this case--
we can run commands like kubectl auth can-i
and define the verbs and resources
that we want to interact with.
So if we want to delete or create,
let's say, pods, we want to be able to check and ensure
that we can actually interact with these resources
in that given namespace.
And so once that we have verified
that we have permissions to the namespace
to interact with the resources we need to,
we can actually describe the namespace
and take a look at some of the constraints that are
defined at a namespace level.
The first one is resource quotas.
So it's a great way to limit the resources
that a team can use within a given Kubernetes cluster.
So in this case, we're defining a pod resource quota,
and it's a great use case for trying
to preserve IP allocation across multiple teams sharing
the same Kubernetes cluster.
So in this case, we're ensuring that this team can only
run five pods, which means five IPs that it will consume.
We also want to define resource limits.
Basically, these are just limit ranges
that define our minimum and maximum amount of CPU
that containers can request when running in this namespace.
And it's a great place to troubleshoot,
because either of these could be reasons
why your deployment fails or why your deployment
is being blocked because there are constraints in place
within that given namespace.
KASLIN FIELDS: So namespaces give us
a way to manage and isolate resources on some basis--
in this case, on a team basis.
And there are also controls in there
that we can use to make sure that all
of the resources for that team are running
the way that we expect them to.
ANTHONY BUSHONG: Exactly.
Exactly.
Like limit ranges, resource quotas-- these
are all things that could be defined for various teams.
Role-based access control is a really good way
to not just isolate individual user access
to various resources, but also service accounts
that workloads use if they require
different levels of access within the cluster, as well.
And this is just the tip of the iceberg.
There are many things that are namespace-scoped-- network
policies, for example.
That can be, again, different constraints
that are defined for where your workloads run.
KASLIN FIELDS: Cool.
So what are we going to dive into next?
ANTHONY BUSHONG: So we took a little bit
about what we can do to understand
how namespaces may be affecting our interactions
with Kubernetes.
So the next thing that we're going to take a look at
are Kubernetes services and how we can interact with them
to understand what may be going wrong with our application
running in a Kubernetes cluster.
KASLIN FIELDS: Cool.
So let's take a deeper look at them.
ANTHONY BUSHONG: Happy to.
So if we take a look at the frontend that we deployed,
we can actually see the host that the frontend--
or the hostname that the frontend is actually
issuing a request against, which is the backend service that
is owned by Team B.
And so Kubernetes services, as you've
talked about in the past, Kaslin,
are a nice abstraction on top of Kubernetes pods or replicas
of a given pod.
And so rather than trying to think about a per-pod level,
we can think about a service level
that maps to numerous replicas of a pod.
And it's represented by the objects
you see here-- pods, services, and endpoints.
And so when we want to troubleshoot something locally,
we can actually port forward against the service
where we actually are, again, port forwarding
interactions with our backend to our local 8080 port.
So as you can see, I'm going to issue a command
to localhost on port 8080, and we're actually
going to get a response directly from our backend that
is running in the team-b namespace.
So basically, when you're going through the debugging cycle,
if you need to interact with services locally
or things that are a little harder to visualize with a web
UI or something like that, you can actually
port forward it to your development workstation
and begin to interact with it on your localhost.
KASLIN FIELDS: So services give us
a way to interact with workloads running on Kubernetes.
We can run our apps in pods.
But if you have multiple copies of those pods,
then how do you interact with the workload as a whole?
And services give us that.
ANTHONY BUSHONG: Exactly.
And you get a DNS record that gets provisioned.
So again, you don't even have to remember that virtual IP
or that cluster IP address.
You can actually natively interact with it
with a DNS hostname that gets-- or a DNS
record that gets provisioned to kube-dns or your cluster's DNS.
And so it's really useful for, again, clients within a cluster
to interact with your application.
But it's, again, also useful for end users
trying to understand what's going
on with the port forward command with kubectl.
KASLIN FIELDS: Nice.
So where do we go from here?
ANTHONY BUSHONG: Well, we showed a little bit about DNS.
See, now there's the age old joke about how it's always DNS,
so I think it's important to understand a bit more about how
we can interact and troubleshoot with the DNS
in our Kubernetes cluster.
KASLIN FIELDS: All right, so let's take a look at it.
What have you got to show us when we're debugging DNS?
ANTHONY BUSHONG: So I think the first thing that's
important to capture and understand
is where kube-dns is actually running within our cluster.
So we're going to run kubens again,
and we're actually going to see a namespace called kube-system.
And so kube-system is where system pods that
are required for the cluster to function, like DNS, typically
reside.
So if we actually run kubectl get pods in grep for kube-dns,
we're going to see a few pods running--
two replicas of kube-dns, as well as an autoscaler.
So I think it's really important to understand,
as your cluster scales up, as your workloads scale up,
the number of DNS queries also typically goes up.
And so typically, you want to make sure
that your kube-dns pods are actually scaling up properly
and are able to handle all of the various volume of DNS
queries coming from your services.
And so when something is going wrong,
if you take a look at this, we've
navigated to a YAML file for a dnsutils container.
And this is actually giving us a way to interact with kube-dns
without having to package up tools
that we would use to troubleshoot
into our application containers.
So once we actually apply the dnsutils.yaml file,
you'll see that this single pod called
dnsutils has been created.
And then we're going to take and just verify
what namespace it's in.
And so we're going to switch to cluster-utils--
again, a great way to separate tooling we
use to troubleshoot from application workloads.
Then we're going to run the kubectl exec command.
And we're actually going to pass in a couple flags, -i and -t.
And this is basically a way for us
to kick off an interactive shell within the dnsutils pod.
And the dnsutils pod will have tooling
that we may want to use to troubleshoot DNS,
like nslookup.
And so it's also important to know
that, while you could get the interactive shell by passing
-i and -t, you can also just execute the single command
if that's what the use case calls for,
and not an interactive shell.
So what we're doing here is we're actually
testing the DNS resolution for our backend service.
So we're using gceme-backend.team-b,
and we'll see that we actually got the cluster IP returned
to us properly.
And so once we actually run kubectl get svc,
we'll actually see that this is the same cluster
IP that was returned from the DNS resolution.
KASLIN FIELDS: Cool.
So what you did here is really interesting.
You created a new pod within Kubernetes
that had these dnsutils on it, and then you
used that pod to debug what was going on
with DNS in the cluster.
That's really interesting and gives you
a really nice way to debug what's
happening with DNS without even messing
with your other existing applications in the cluster.
ANTHONY BUSHONG: Yeah.
Exactly, right?
I think it gives you a safe way to package up a set of tools
that you only need to use for a specific period of time,
and then you can spin it down once you're
done troubleshooting or you've identified the root cause.
And I think this really helps minimize what we actually
need to bake into our application containers.
And that's useful for a whole bunch of reasons,
whether it's security, whether it's performance.
There are a bunch of different angles and benefits
that we get from making sure that we're not basically
causing bloat within our application containers.
KASLIN FIELDS: So what else do we want to go over today?
ANTHONY BUSHONG: Well, I think it
was really cool to see the exec functionality within kubectl
for our toolbox or dnsutils container.
But I also want to show that this is something
that you could do with your application containers,
as well.
So we'll take a little bit further look
as to when we would running an exec into our application
containers.
So kubectl exec-- great for utilizing
with utility or debugging containers,
but also can be used with your application containers,
as well.
This is useful if you need to take
a look at the environment in which your application is
running.
KASLIN FIELDS: So if something's going
wrong with your application as it's running in Kubernetes,
we can use this tool to dive into them
and figure out what's happening.
ANTHONY BUSHONG: Exactly.
So just building upon the example
that we have in this video today here,
we're going to take a look at--
we're going to switch back to the team-b namespace,
and we're actually going to take a look
at our backend container or our pod here that's
running serving our backend.
And we're actually going to run the same kubectl exec command,
and we're going to provide the pod name.
So in this case, the backend production
pod with a specific hash at the end.
And then we're going to kick off an interactive shell
once again.
And so this is a way for us to understand
what's going on in our actual runtime environment.
So I just ran print env, and I can actually
see all of the different environment variables that
are configured within this environment, this container.
And so it's really useful if you need
to take a peek at things that might change or want to verify
that things are correct within the actual container
that you're running.
And another thing that's interesting about this
is that, going back to, again, the conversation of creating
minimal containers, sometimes, you actually won't even
have a running shell or something that you
could initiate a connection to.
And so in those scenarios, kubectl
has actually added functionality for mounting a debugging
container into that running pod.
So if you don't have a running shell,
there's actually relatively new functionality
that enables you to still get that interactive environment
where you can do things like check environment variables
or other things that might affect your application
while you're troubleshooting.
KASLIN FIELDS: Thanks for that demo, Anthony.
You covered a lot of really cool stuff in there
and a lot of tips and tricks that even I didn't know.
ANTHONY BUSHONG: And I really think
we're just scratching the tip of the iceberg here, right?
I think I just really wanted to take a look at namespaces,
and services, and some of the essentials
that are important that folks interacting with Kubernetes
should be aware of when trying to figure out when things are
going wrong, why they are going wrong,
trying to remediate them.
But, of course, there's so much more to dive into, right?
KASLIN FIELDS: Today we learned about how Kubernetes namespaces
can help you isolate and manage resources-- for example,
on a per-team basis.
And we learned how services can help you reach your workloads
and can help you debug them.
Then we learned some great tips and tricks
for debugging both networking problems from kube-dns
and how to get into your applications
to debug them using kube exec.
Thank you so much for watching.
If you want to explore more, we'll
have links to additional resources in the description
below.
And be sure to like and subscribe for more content
from Google Cloud.
We'll see you next time.