What you'll learn
- Compare managed Kubernetes services with self-managed kubeadm clusters, including cloud logging and elastic worker node scaling
- Prepare an Amazon VPC and EC2 Linux host for kubeadm, including disabled swap and routing for control plane traffic on TCP 6443
- Install kubeadm and its dependencies, including the container runtime and iptables configuration, on a supported Linux host
- Initialize a Kubernetes master node with kubeadm and verify API server connectivity with kubectl version
- Install the Project Calico CNI by downloading its YAML manifest and applying it with kubectl apply
- Troubleshoot a pending pod with kubectl describe by identifying the master node taint that blocks kube-scheduler placement
Free 57-minute video lesson with a full transcript and knowledge checks. No account needed to watch.
Note: Some content in this skill may be outdated due to changes in AWS and Project Calico. While certain details have evolved, the core concepts remain useful for deploying a Kubernetes cluster. Please refer to the latest documentation for updated practices.
Overview
Join Trevor Sullivan as he explores the fundamentals behind Kubernetes (also known as K8s), the premiere Cloud Native Computing Foundation (CNCF) and open source project that enables you to orchestrate container-based microservices.
Recommended Experience
- Six months of hands-on experience using the AWS Cloud platform is recommended.
Related Job Functions
- IT Professional
- System Administrator
- Cloud Administrator
- System Engineer
- Cloud Engineer
Trevor Sullivan has been a CBT Nuggets trainer since 2020 and has received a variety of AWS certifications. His areas of expertise include Amazon Web Services, Docker, Microsoft Azure, and PowerShell automation.
Intro to Kubernetes Deployment Tools
Trevor Sullivan introduces the kubeadm utility for building Kubernetes clusters from scratch.
Knowledge Check
Kubeadm is the official tool from the Kubernetes development team for installing a Kubernetes cluster. True or false?
Prepare Amazon VPC and EC2 Instance for Kubeadm
Let's set up an Amazon VPC and an EC2 instance to run kubeadm on.
Knowledge Check
Swap partitions help improve the performance of Kubernetes master nodes. True or false?
Install Kubeadm and Dependencies for Kubernetes
Let's install Kubeadm and some other dependencies for building up a cluster.
Knowledge Check
Which of the following TCP ports is NOT used by Kubernetes master nodes?
Initialize Kubernetes Master Node with Kubeadm
Let's initialize our Kubernetes cluster with Kubeadm and ensure that Docker is configured to use systemd as its cgroupdriver.
Knowledge Check
Which of the following must match between the Kubernetes kubelet and Container Runtime Interface (CRI) configuration?
Install Project Calico Container Network Interface
To deploy pods, we first need to configure a Container Network Interface (CNI) on our Kubernetes cluster.
Knowledge Check
Which of the following services will not begin running until a Container Network Interface (CNI) has been deployed to your Kubernetes cluster?
Conclusion
I hope this has been informative for you and I would like to thank you for consuming.
View Transcript
Intro to Kubernetes Deployment Tools
0:11Hi, guys. My name is Trevor Sullivan. And welcome to another CBT Nuggets skill. In this skill, we are going to be exploring how you can set up your own self-managed cluster with Kubernetes. And we're going to be using a tool known as kubeadm, or kubeadmin, depending on what your preference is in pronunciation, in order to set up that cluster. Now, before we get too deep into kubeadm specifically, I wanted to provide a overview of the landscape of utilities that you can use to set up a Kubernetes cluster.
0:46And this will give you a better understanding of where exactly kubeadm fits into the picture. Now, there's really two primary different mechanisms that you can use to deploy a Kubernetes cluster if you need it. You can do something that is self-managed, as with all the options right down here in the bottom section. Or you could use a major cloud vendor solution in order to deploy a Kubernetes cluster. Most of the major cloud vendors out there, like Microsoft Azure and Amazon Web Services or Google Cloud, Digital Ocean, and Linode all offer managed Kubernetes services.
1:24In Microsoft Azure, they call it Azure Kubernetes Service, or AKS. And in AWS, they call it EKS, or Elastic Kubernetes Service. They have a much longer name, which is a little bit more formal. I think it's Elastic Container Service for Kubernetes. But that's just more of a formality. Most people know it as EKS. Google Cloud has their GKE engine that allows you to spin up a cluster. And then Digital Ocean and Linode both have their own managed Kubernetes offerings as well, which really fundamentally operate similarly to the big three cloud vendors.
2:01Now, what's really nice about these services is that it makes it very easy to spin up a cluster. So you don't really have to know anything about Kubernetes in order to use these managed services. As long as you have an account with those vendors, you can spin up a Kubernetes cluster and then immediately start using it. Also, they take care of doing things like handling automated upgrades of the cluster. So if you need to increment your Kubernetes version when a new release becomes available, then you can use that cloud vendor's upgrade path in order to manage that upgrade and offload some of that process off to the cloud vendor.
2:38So you as an administrator don't have to do as much work to upgrade the cluster and then verify that everything's been upgraded correctly because that's part of the value that's offered by a managed Kubernetes service. Also, the cloud vendors such as Azure, AWS, Google Cloud, et cetera offer built-in monitoring and logging of the Kubernetes master nodes. And this is really helpful because you don't need to worry about, as an administrator, going and hunting down log files on the file system. That can be a little bit of a pain if you are having to go out and troubleshoot a cluster.
3:12And so by using built-in monitoring and logging solutions-- such as in AWS, they call it Amazon CloudWatch-- you can benefit from having a central place to go look for logs about your applications rather than having to go log into different virtual machines, all the different master nodes in your cluster, for example, and then hunt down those files on the file system and make sure that you're looking at the right data. So that's a value-add with the major cloud vendors in terms of offering a managed Kubernetes service. We also have the ability to do scaled compute.
3:44So because we're not self-hosting the compute nodes that are part of our Kubernetes cluster, we're able to benefit from the scalability, or what's known as the elasticity of the cloud. And what that essentially just means is that the cloud has free compute capacity that's inside of their data centers. And when you are ready to consume that compute capacity, you can simply provision it into your account and basically take it out of their pool of compute capacity, and then pay for the provisioned amount of compute capacity that you have.
4:17So if your application needs to scale up very rapidly, then it's really nice to be using a cloud vendor because then you can simply add more virtual machines, more worker nodes, to your Kubernetes cluster. And you don't have to worry about purchasing hardware and installing operating systems, configuring low-level networking, installing device drivers, and just all of the complexities that come along with the traditional IT infrastructure configuration where you're responsible for that physical layer on up.
4:47Now, there are lots of other options that you have in the Kubernetes ecosystem to deploy a Kubernetes node. And some of those options have the names in their logos here. Some of the logos can be a little bit weird. Like this one down here in the bottom left corner, that's actually K0S. You've also got this option right here. This is the logo for, I believe it's minikube. And minikube is basically a command line tool that you can use to rapidly spin up a Kubernetes cluster. It gives you the ability to spin one up inside of a virtual machine or inside of a container or directly on a bare metal machine that you might have in your environment as well.
5:27K3s is actually really cool. I like K3s, and I've toyed around with that in the past a little bit. It's a very lightweight distribution that comes packaged up as just a single binary. And so this makes it very easy to install because really all you have to do is copy this local binary to your system, and then you can immediately start calling the different commands inside of K3s. It also makes it very easy to set up the initial cluster and then run kubectl commands in order to administer the cluster. You've also got options like Rancher.
5:59So Rancher, you can think of like an orchestrator of orchestrators. So it allows you to rapidly deploy Kubernetes clusters. They also have their own distribution of Kubernetes as well. I forget what the name of that is, but they do offer a distribution of Kubernetes that you can simply spin up yourself. Also, "kind" is known as Kubernetes in Docker. And if you'd like to run a Kubernetes cluster as an array of Docker containers, you can do that as well. It's a really convenient option if you're looking to isolate that cluster and then very easily be able to tear it down and then rebuild it again so that you can very easily do rapid development on your environment.
6:35And you don't have to worry about spinning up an entirely new operating system every time to make sure that you're starting from a clean slate. By working with containers, you're actually helping to ensure that every time you spin it up, it's going to start with a clean slate. One of the easiest ways to spin up a Kubernetes environment as well is Docker Desktop. And so if you're looking for just the most straightforward option to create a Kubernetes cluster, you'll probably just want to install Docker Desktop on your dev system. Docker Desktop runs on Linux, Mac, and Windows.
7:06And you can actually run Kubernetes directly inside of Docker Desktop on the Windows platform, for example. There's a little systray icon. You can just go down into that systray and then indicate that you want to go into Kubernetes mode, at which point, Docker Desktop will allow you to run kubectl commands against a cluster that it sets up itself. Also, Ubuntu-- or Canonical, I should say, the makers of Ubuntu Linux, have a distribution of Kubernetes known as MicroK8s. And depending on which distribution you choose here, you're going to be looking at different options that are available.
7:41Some distributions might have things like support for Kubeflow or support for GPU compute inside of containers on your Kubernetes cluster. Other options might include authentication options that are available, and also things like logging systems that are built in. Like, you might have a Fluentd agent that's built in to automate the obtaining of logs so you can troubleshoot that cluster. So depending on which distribution of Kubernetes you choose, you'll have a different kind of combination of options there. But if you're looking for something really easy to get started, definitely recommend Docker Desktop.
8:15If you're looking for just having a raw interface to run Kubernetes in containers, you probably want to look at kind. If you're looking for something that's very simple and lightweight, K3s definitely takes the cake since it's just a single binary distribution. But we're actually going to be focusing on kubeadm here, which is the official tool from the Kubernetes group that is basically administering Kubernetes itself as a project. That's their official tool to set up a Kubernetes cluster, and so that's the one that we're going to be exploring. And in particular, we're going to be using kubeadm on an Amazon Web Services EC2 instance in order to provide the virtual machine compute and virtual networking platform in order to create a cluster.
8:56So in any case, let's go ahead and jump in to our next video, where we'll actually take a look at the steps to install the kubeadm utility. And then we'll take a look at some of the dependencies that you're going to need in order to create a Kubernetes cluster, things like your container runtime, as well as your container network interface as well. In this particular skill, we're going to be using an open-source project out there known as Calico for our container networking. So let's go ahead and jump into our next video and start taking a look at kubeadm itself. I hope this has been informative for you, and I'd like to thank you for viewing.
Prepare Amazon VPC and EC2 Instance for Kubeadm
0:11Hi, guys. And welcome back. Let's go ahead and take a look at the documentation for how to install kubeadm. And then we'll spin up an Amazon Web Services EC2 instance or Elastic Compute Cloud, which is basically just a virtual machine running Ubuntu Linux. And then we'll install kubeadm on that Linux virtual machine in order to give us the ability to then initialize a new Kubernetes cluster. So in order to take a look at the documentation, we're going to head over to the kubernetes.io website under Docs.
0:43And they've got some really excellent documentation here that talks about how to bootstrap a cluster with kubeadm. And then that's broken down into a bunch of different subtopics, such as how to install kubeadm itself, how to troubleshoot any problems that you might come across with kubeadm. And then, of course, how to create a cluster once you've got kubeadm itself installed, how do I initialize a Kubernetes cluster, and things like that. So let's head up for starters up to Installing kubeadm here and just explore what we need.
1:16So for starters, we're going to need a compatible Linux host. Now, I often prefer to use Ubuntu Linux. However, there are plenty of other supported distributions of Linux out there that you could use as well. You could use SUSE Linux. In fact, SUSE acquired Rancher back in late 2020, I believe. And so they're definitely a good supporter of the Kubernetes project. You could also use just Debian Linux as well, or Red Hat Linux, which is a very population distribution. So there's a bunch of different ones out there.
1:46I'm going to be using Ubuntu, which is actually based on Debian Linux. So that is definitely compatible. You will want to make sure that you have a couple of gigs of RAM available on each of your virtual machines as well. And this is important for especially the master nodes in your Kubernetes cluster because you're going to want to make sure that the master nodes have enough space to run all of the different components, like the Kubernetes Controller Manager, the Kubernetes Scheduler, as well as the API server that kubectl communicates with in order to administer your Kubernetes cluster.
2:17And if you don't have enough RAM to run all of those different components, then you may run into things like system crashes. You might run into just odd behavior from your Kubernetes cluster. And you can avoid that by ensuring that your master nodes have plenty of RAM. Now, as far as the worker nodes go, any worker nodes that you join to your cluster you're going to want to make sure have enough RAM as well because those worker nodes are the nodes in your cluster that are actually going to be running your different pods and containers inside of those pod specs. And so if you don't have enough RAM to run your different application components, like maybe you're running database servers like MySQL inside of containers, maybe you're running web servers, maybe you're running some middleware servers in there, if you don't have enough RAM to run your containers, then you're not going to be able to reliably run your application, as well as scale that application up when you actually need it.
3:08You also want to make sure you have enough CPU capacity as well just so that your application components aren't fighting for CPU utilization. If you're running very CPU heavy processes, maybe you're building a website like YouTube, for example, where they're doing very heavy video processing, which is very CPU intensive work, if you are building a service like that, then your focus on having enough CPU and memory capacity for that matter is going to be essential. Also, you're going to want to make sure that you have network connectivity between the machines in the cluster.
3:38So this is really important, especially if you are dealing with things like multicloud scenarios, where maybe you've got some virtual machines running in Microsoft Azure, maybe you've got some virtual machines running in Amazon Web Services and other cloud vendors. In order to ensure that your cluster is functioning properly, you're going to want to make sure that you have routing between your different networks in different cloud vendors. Or if you're doing something even just as simple as multi-region setups in something like Amazon VPC, where you've got two different VPCs that exist in different regions, then you want to make sure that you have routing setup between those VPCs so that your worker nodes can communicate with the master nodes, and so that the master nodes themselves can communicate with each other on TCP 6443.
4:25And of course, your load balancers and ingress controllers and all of your pods are going to need to make sure that they have network connectivity as well. Also, this is kind of something I would take for granted, I should say, but oftentimes, you might not be thinking about it. And you do want to make sure that you have a unique hostname and MAC address for all of the nodes in your cluster just to ensure that all of those nodes are uniquely identified within the cluster itself. Also, disabling swap is very important in order for the kubelets to work properly.
4:58And the kubelet is basically the component of software that you use as part of a Kubernetes cluster in order to register all of the nodes in your cluster with the Kubernetes master node. So that ensures that your worker nodes are going to be able to communicate with the API server and receive any instructions from the scheduler through the API server that they need to process, like starting up pods or deleting pods or creating services, that kind of thing.
5:29All right, so let's go ahead and start by spinning up a virtual machine. And then we're going to go ahead and basically just verify that we meet all of the dependencies in order to install kubeadm and get our cluster up and running. So I'm going to head over to the AWS Management Console here. And what we're going to do for starters is just provision a new virtual private cloud. And this is basically the network environment that's going to host our cluster and allow all of our nodes to communicate with each other.
6:00Of course, we're going to start simple. We're just going to have a single node for starters. But if you did have additional nodes, you of course want to deploy them into the same VPC. Or if you're doing a more complex network setup, then you'd want to make sure that you have that routing all set up ahead of time. Now, on the Amazon VPC Dashboard here, you can just go to the Launch VPC Wizard. And you can provision a VPC with both public and private subnets. And so we're going to go ahead and do that for now. And then you want to make sure that you just choose a private CIDR block for your cluster. So I'll do something kind of random like 10.77/16.
6:33And then I'll call this k8s just so I can find this VPC later on. And then for our public subnet's CIDR block, we're going to do something like 10.77.10/24. And then we'll do, for our private subnet, we'll do 10.77.110.0/24. So those are just a couple of different CIDR blocks for public and private. And we're also going to need to make sure that we allocate an elastic IP for our NAT gateway.
7:06So I'm going to head back to Services and go over to VPC. And we'll head down to Elastic IPs. Actually, I think that's over in EC2. So let's go over to-- oh, here it is, Elastic IPs. Some of those things only appear in EC2 Console. But let's go to Allocate Elastic IP. We'll just do our region here, and do Allocate. And then I'll just go ahead and give it a name like k8s. And let's come back here to our VPC Console.
7:36And now we should be able to choose that elastic IP. And we'll go ahead and hit Create VPC. So we'll give that a second to create. And then once our VPC has been created, we'll go ahead and spin up a virtual machine over in EC2 that is going to be a member of this VPC. All right, so our VPC has been created here. So we'll go ahead and head over to the EC2 console here, and we'll create a new virtual machine with Ubuntu Linux. So I'm going to go to Launch Instances here.
8:07And then I'll find Ubuntu 20.04 Focal Fossa right here. So I'm going to use that image. And then we're going to choose just a relatively small EC2 instance type. Of course, we want to make sure it's got enough vCPU and RAM. So I'm going to choose a t3.medium here because that has 2 virtual CPUs and 4 gigs of RAM. And then on our Instance Details here, I'm going to go ahead and choose my VPC. So let's choose our k8s VPC. Choose our public subnet because we want to remotely log in to that virtual machine with SSH.
8:41And then we'll enable auto-assign public IP so that we can remotely access that virtual machine. All right, let's go ahead and head to the Storage screen next. And for storage, I'm going to make sure that my master nodes have, let's say, 30 gigabytes of storage. And then we'll go ahead and do Review and Launch. And then we'll hit Launch. And I'm going to go ahead and create a new key pair here. And I'll just call this k8scluster, hit Download Key Pair to download the private key for the cluster.
9:14And then we'll go ahead and hit Launch Instance. All right, so while that's launching, we need to make sure that we have access to log into this EC2 instance. So I'm going to head back over to EC2 here. And we're going to find the virtual machine that we just spun up, which is this t3.medium right here. And then I'm going to go over to security and find the security group. And we need to make sure that we have inbound SSH access. And it looks like the automatically generated security group already has a rule that allows inbound access from anywhere online to TCP port 22.
9:49So we'll be able to log into this virtual machine here in just a second. So let me call this k8smaster just to give it a friendly name in our console here. And now to log into it, I'll head over to the Details tab and find the public IPv4 address, and just click on this button to copy it to my clipboard. And then I'm going to go ahead and fire up a new terminal. And we're going to go ahead and just run ssh. And then we'll do ubuntu@ IP address. And then I also need to specify my private key, or my what's known as the identity file.
10:22So I'll do -i and then go into my Download folder and then look for the k8sscluster key. And we'll go ahead and run that. And we'll confirm our host key. Hit yes. And now we have our virtual machine here. So this is the virtual machine that we just spun up. So I'm going to go ahead and do a standard sudo apt update and sudo apt upgrade just to make sure that all of our base operating system packages are up to date. And then we'll go ahead and disable swap as one of the first steps that we needed to do.
10:57Awesome. Now that our packages are up to date, let's go ahead and check to make sure that swap is disabled. So I'll do sudo vim /etc/fstab. And it looks like there is no swap actually configured on this Focal Fossa image that AWS provides. But you do just want to make sure that in fstab that you don't have a swap partition there. Also, if I exit out of vim and I do a cat /proc/swaps, then that will show you any swap partitions that are configured on your system here.
11:28And you can see that I have empty output. I'm also going to go ahead and change the hostname of my node here. So by default, the Amazon Web Services platform assigns this IP address as its name. But I'm just going to go ahead and do sudo vim /etc/hostname. And we'll go ahead and just delete that line with a dd command. And then I'll do insert, i for insert. And then we'll go ahead and call it k8smaster01. All right, now that I've renamed our node, let's go ahead and do a sudo reboot.
12:01And we'll let our system reboot, and we should have it named something else. So now that we've got this node up and running, we can go ahead and proceed with installing kubeadm. I hope this has been informative for you, and I'd like to thank you for viewing.
Install Kubeadm and Dependencies for Kubernetes
0:11Hey, guys, and welcome back. Now that we've got our virtual machine set up and we've ensured swap is disabled and we've renamed our node here, let's go ahead and take a look at what the next steps are in order to get kubeadm installed on our system. So I'm going to head back over to our kubeadm documentation here. And we've already ensured that we have a unique MAC address. Of course, we're only dealing with one node here, so we don't really need to worry about that. And MAC addresses are pretty much always unique.
0:41Not something you really need to check, but they do provide the commands that you can do to check that, as well as the product UUID on a Linux system. So the other thing we need to do here is to configure IP tables. And they provide the steps to do that right here. It's basically going to load a kernel module called br_netfilter, and ensure that these bridging options are enabled in our configuration for that module. So let's go ahead and copy this to our clipboard.
1:13And then we'll switch over to our terminal and paste that in. And then once our IP tables is configured here, we can go ahead and move on. Of course, there are a variety of different network ports that you'll need to ensure are open between nodes. And in this particular case, we're only dealing with a single node at the moment. So we're not going to be doing any internode configuration. However, you will want to ensure that your control plane nodes have the following ports open. You've, of course, got 6443 for your Kubernetes API server.
1:43That's what kubectl is talking to in order to manage the cluster. For etcd, you have ports 2379 and 2380 for the etcd server API. You've also got the Kubelet API at 10250. And then 10259 for kube-scheduler and 10257 to for the controller-manager. So if we were running multiple nodes, then we'd want to go back to our security group in Amazon VPC here. And we would want to ensure that we have rules set up to allow all of those different ports.
2:18So if we, for example, wanted to access, let's say, kubectl across port 6443, we'd go ahead and do a new security group rule here for TCP 6443. And then we'd specify either the CIDR blocks that we want to allow to access it-- so we could do something like 10.77/16, and that would allow anything from our VPC here-- or we could go ahead and choose the security groups that we want to allow to access. So if we created a virtual machine that had the default security group, we could go ahead and just assign that.
2:53And then that would allow anybody who has that default security group to communicate with port 6443. But because we're just dealing with a single node for now, I'm just going to go ahead and cancel that. And so SSH will be the only port that we are allowing inbound access to at the moment. Now, they do provide a telnet command that you can use in order to validate connectivity. But at this point, we don't have any services that are actually listening on TCP 6443. So you'd actually have to install the cluster node first and get the API server up and running.
3:25And then that would be listening on 6443, and then you could use this telnet command to validate that you actually do have connectivity to that port on a particular node. Now, one of the other things you'll need to install is what's known as a container runtime. And the container runtime is essentially what Kubernetes is going to use to deploy pods into your cluster. Now, you do have several different options that are available. You can use the Docker engine, you can use the containerd project, or you can use the container runtime interface here as well.
3:59I'm going to be installing Docker. And we're going to use that as the container runtime. So essentially, when Kubernetes wants to spin up any containers, it will actually be using the Docker API in order to do that. So what we're going to do for now is just go ahead and head back over to our virtual machine. And we'll do a sudo apt get install docker.io --yes. And then once you've got the Docker engine installed, you'll want to go ahead and just make sure that your Ubuntu user account is able to communicate with the daemon just for verification purposes.
4:33So in order to do that, we need to actually add our user to the Docker group. So the installation process creates the group called docker, and anybody who's in the docker group will have access to manage the Docker daemon. But by default, if we try to run a docker command, you can see we don't have access to it. So we'll do a sudo usermod --groups docker --append, and then the username that we want to append the docker group to. And that's ubuntu. And so we'll go ahead and run that command.
5:04And we'll just run exit. And then we'll ssh back into that virtual machine so that we can continue working on it. So let's do groups now. And we should in our groups list see docker. Sure enough, there it is. So now if I run docker ps, you can see I'm able to communicate with the Docker daemon. You could also run docker version or docker info. Both of those will verify that you have connectivity to the server component through the Docker socket as well. So once you've got your container runtime installed, let's go ahead and see what's next.
5:37So now we need to actually install kubeadm itself. And that's the utility we use to initialize the cluster and join nodes to the cluster. And then we also have the kubelet. And the kubelet is that component that registers our nodes with the cluster. And then we've finally got kubectl, which is the command-line utility that we use to communicate with the API server once that's been installed. So there are a few different steps that we need to run through in order to install these components. First of all, we need to install these components right here.
6:09So we'll just paste that in. And then once the ca-certificates and curl and everything is installed, we can download the Google Cloud public signing key. This will allow us to talk to the Google Cloud package repositories from our Linux VM here. And then finally, we'll add the apt repository for Kubernetes in particular, which uses that GPG key. And we'll paste that in. And then once that repository has been configured, we now need to update our apt cache.
6:40So we'll do a sudo apt update. And then once our package cache is installed, we can then install all of these components with a single apt install command. So let's do apt get install on kubelet to kubeadm and kubectl. And as you can see, those components are getting installed. And it'll show you the version numbers of each of those that's getting installed. So it looks like we're going to be using Kubernetes version 1.23. That's the latest as of this recording. So now the other thing you'll want to do is use apt-mark here in order to hold those packages at their current version.
7:16And so basically, we're going to pin version 1.23 of kubelet, kubeeadm, and kubectl on this particular node. And so that's basically just setting a flag indicating that if a new version of these packages comes out, we do not want those to be upgraded unless we explicitly unhold them and then actually perform the upgrade ourselves once we're ready to do that. So that helps just ensure consistency on the version of Kubernetes that's going to run on your cluster here.
7:48All right, so now we are just about at the point where we can go ahead and use kubeadm to initialize our cluster. And we'll do that in the next video. I hope this has been informative for you, and I'd like to thank you for viewing.
Initialize Kubernetes Master Node with Kubeadm
0:00[MUSIC PLAYING] Hey, guys, and welcome back. The one other thing that you'll see at the end here in the documentation for installing kubeadm is called configuring a cgroup driver. Now on Ubuntu Linux, we're actually going to be using the systemd driver here, but it does actually talk about configuring a cgroup driver. This is actually the document that I want here, kind of talks about how to configure either the systemd driver or the cgroupfs driver.
0:38But in this particular case, they recommend that if you're using kubeadm, then you should be using systemd. And I believe that's actually the default. And you could pass that into your configuration file for kubeadm, but I'm just going to go ahead and let it use the default value for that. So now we're ready to go ahead and go over to creating a cluster with kubeadm. And so we're going to use kubeadm to initialize a brand new Kubernetes cluster, and then we'll validate that the cluster is actually functioning and can deploy pods and things like that.
1:11So, of course, we've already gone through the process of installing kubeadm itself. And so we've gone through most of these preliminary steps that are kind of duplicated from the other documentation here. So at this point, what we want to do is actually initialize the control plane node or what's known as a master node in kubernetes. And one of the things that you can do as a preliminary step is to download the necessary container images. Of course, kubeadm does that itself as well. So you don't have to do that. But if you want to speed up the kubeadm command itself, you could go ahead and pre-download those container images if you'd like.
1:49So we'll open up this document here called running kubeadm without an internet connection. And this will show me how to list the images that are required for kubeadm, as well as the pull command that will allow Kubernetes to, or rather, kubeadm itself to pull those images and cache them locally. So let's head over to our cluster here. I'm going to head over to my cluster node, and then I'll just paste in these commands. And it doesn't look like it's copied that correctly.
2:22So let me just do kubeadm, and then we'll take a look at the contexts that are available here, and we'll do config, we'll do kubeadm config, and then we'll do --help to take a look at the subcontexts there. And then we've got the images context here. We will do images, oops, let me do images --help. And then, of course, I have the list command here. So we'll do list, and these are the images that Kubernetes is going to require. We've got etcd, which is the backing key value store for the Kubernetes cluster.
2:57So that it can share state amongst all the master nodes. Then we've also got all of our core components, like our API server that kubectl talks to. We've got the controller manager that's responsible for working with any deployments and determining what needs to happen in terms of spinning up pods. Then we've got the kube-scheduler that actually schedules pods onto nodes. We've got kube-proxy, pause, and then core-dns, which is an essential component for Kubernetes as well to handle DNS resolution of pods and services.
3:28So let's go ahead and do an up arrow, and then we'll change list to pull and pre-cache all of those images. And then while that's running, we'll go ahead and take a look at the next steps here back under creating a cluster documentation. Now, for initializing your first master node, there are several different options that are available. If you are going to be spinning up multiple nodes in your cluster, multiple master nodes for high availability purposes, then you can specify a parameter here called control-plane-endpoint and set the shared endpoint that you'd like to use for all of those control plane nodes.
4:05And then you can put a load balancer in front of that, and load balance your traffic across all of your different nodes. Now in this case, I'm just going to have a single node. So I'm not going to go ahead and specify that option, but that is something that you'd want to do if you are going to have high availability for your kubeadm cluster. Also you are going to need to install a pod networking add-on, and you are going to need to set the pod-network-cidr, and that's going to be the cluster network that we're going to use for pods to obtain IP addresses from the cluster once they are deployed.
4:42So you want to be thinking about what CIDR block do I want to use in my network in order to assign pods? And of course, you don't want that to overlap with any other important CIDR blocks. So for example over here in our VPC console, I think we chose to use 10.77/16. Yep, that's our CIDR block there. So we wouldn't want to use 10.77/16 as our CIDR block for our pod network because then we could run into potential IP conflicts, and that could cause our cluster to just fail.
5:16So we probably don't want to use that. But you could choose something else like, I don't know, 10.88/16 or 192.168. something. It's kind of up to you what you'd like to use for your CIDR block there. There's a couple of other important options on kubeadm here as well. Item number 3 here is referring to the container runtime interface that you're going to be using with your Kubernetes cluster. Now in the earlier video, we actually installed a Docker as our container runtime interface.
5:47So our Kubernetes cluster is going to be using Docker. However, since version 1.14, kubeadm actually will automatically detect your container runtime based on the domain sockets that are accessible. So if the Docker socket is accessible, then Kubernetes will automatically detect that the Docker socket is available, and it will configure the Docker as the container runtime interface for your cluster. So we don't have to specify this, but if you did want to override that to a specific socket, you could use the cri-socket parameter on kubeadm init.
6:24And then finally, if your virtual machine has multiple network interfaces, then you can specify which network interface you want to use for your Kubernetes cluster here. But in our case, we only have a single network interface on our virtual machine, and we can kind of verify that by going back to our command line here. And then if we use the IP command to take a look at IP links, that's the command we can use to check out our network interfaces. And of course, we have our standard loopback interface, which would not make sense to use for a cluster.
6:56We've also got our Docker network interface here as well, which is not a physical interface. It's basically just a virtual interface that Docker uses for its bridge networking. And then that leaves us with by process of elimination just ens5 here, which is our actual VPC network interface or elastic network interface that is attached to our EC2 instance. So we don't need to specify that, but if we did have multiple interfaces, then we could specify which one we want to use for the cluster in the kubeadm init command.
7:29So the only option that I'm really going to be using here to initialize our cluster is pod network CIDR. So let's go ahead and run kubeadm init, and then we'll pass in that option, and that will initialize our cluster here. So let's come back to our terminal, and we'll run kubeadm. And then we'll do init. Take a look at the help with the --help parameter here. And as you can see, we've just got a whole bunch of different flags here. And I'm just going to be specifying the pod-network-cidr, which is basically just a string value with the CIDR block for our pods.
8:06And so I'll do kubeadm init --pod-network-cidr. And then I'll set that to let's do 10.88.0.0/16. All right, so of course, I need to run that as superuser. So I'll run sudo in front of it. And that should give us access to run it now. And so now kubeadm is going to go through a whole bunch of steps to set up certificates for all of the different services here, and it's going to spin up a cd, it's going to spin up the kube-proxy, the API server, and all of those components that actually create the cluster here.
8:43And as you can see, it's going to spin up things like kube-scheduler, kube-controller-manager, kube-apiserver, and pretty much everything that our cluster needs to run. I believe it also spins up coredns here as well. And so once this command is done executing, we should have a cluster up and running. However, we're going to have kind of a crash looping process occurring, and we'll take a look at how to resolve that. All right, so it seems like our kubelet isn't healthy here. And so that's kind of causing the kubeadm init process to hang a bit here.
9:19And so we need to kind of figure out why exactly the kubelet is failing. So what we can do is use journalctl to explore our logs in our operating system here. However, I need to specifically find the kubelet component because we're dealing with lots and lots of different services here. So if I do journalctl --help, there's actually a parameter here called -t or --identifier, and you can set the identifier to kubelet and find just the relevant logs for the kubelet component.
9:56So let's do a journalctl --identifier, and then set that to kubelet. And I'm going to head all the way to the bottom here, you see what our latest logs look like. So as you can see, we've got some logs right over here. And if I scroll over just a little bit, you can see it says failed to run kubelet, and then in the more detailed message here, it says that there's a misconfiguration, and that the kubelet cgroup driver systemd is different from the doker cgroup driver, which is set to cgroupfs.
10:30All right, so that is actually an indicator that we do need to manually configure our cgroup driver on the Docker engine, which is our container runtime over to systemd as well. So I'm going to hit Q to quit out of journalctl. And now I'm going to run docker info here just to confirm. And sure enough, the cgroup driver that's being used by default when we installed the Docker package on our operating system here is sure enough, it's actually cgroupfs.
11:01So what I need to do is to reconfigure the Docker engine to use systemd instead of cgroupfs. So how do we do that? Well, first of all, we need to figure out where the unit file for Docker is. I'm going to do systemctl status on docker.service. And it looks like our unit file for the docker engine is under lib/systemd/syst em/docker.service. So I'm going to do sudo vim etc, sorry, /lib/systemd/sys tem/docker.service.
11:37All right now, inside of this systemd unit file, we basically need to reconfigure docker to run with the systemd cgroup driver instead. So I'm going to come down here under exec start, because this is the command line that's going to be used to spin up the Docker daemon. I'm going to go to the end of the line here and we'll add in the exec option and set it to native.cgroupdriver equals systemd. And so that should configure the Docker engine to use systemd as the cgroup driver instead.
12:11So I'll hit Escape and then :wq to save and quit that file. And then we'll do a sudo systemctl restart on the docker.service unit file. And we, of course, need to run systemctl daemon reload here, because we reloaded or we changed the unit file. We'll do sudo systemctl reload on the engine here. And then we'll go ahead and do sudo systemctl restart docker.service once more.
12:42All right, so that time it restarted, and let's just make sure that it's actually running. So I'm going to use my status command here again. And sure enough, it looks like the Docker engine is back up and running. And now if I do docker info again, let's just confirm that the cgroup driver has changed. And sure enough, you can see right here cgroup driver is now set to systemd. Now if this happens, you'll want to make sure that you actually reset kubeadm, and then re-initialize your cluster. So I'm going to go ahead and clean out our configuration by doing sudo kubeadm. And then there is a command called reset.
13:18And go ahead and just confirm that you do want to reset your cluster back to scratch. And this command will basically go and stop all those containers for Kubernetes that were spun up when you attempted to initialize it the first time. And it will go ahead and reset a bunch of stuff. And then the other thing that we need to do is to delete our kube/config file because that's going to get regenerated. So I'm just going to go ahead and delete that kube/config from our directory. And then we'll go ahead and try to re-initialize our cluster with the same command that we used before.
13:50And hopefully, everything will work fine this time. So let's give that a minute to run and see what we get back. OK, so that works pretty quickly there. And you can see we get much nicer output here. We're not getting any errors anymore. Plus it installs things like coredns, as well as kube-proxy here, which would have gotten skipped in the previous initialization, since we had that error with the kubelet. All right, so now let's go ahead and run these commands here. And this is going to take our config file in admin.conf and copy it to our home directory.
14:23So I'm going to go ahead and just run these commands here. And now we should be able to use the kubectl command line utility to interact with our clusters. So one of the most basic things you can do is just run kubectl version. And if you get an error down here under a server version, it will basically tell you that you can't connect for one reason or another, maybe the API server is not running or maybe your credentials file is incorrect or something. But if you do get back a client version and a server version here without any error messages, then you are successfully connected to your Kubernetes cluster.
14:59So let's do kubectl, and then we'll do get namespace. And this will just list out the default name spaces in our cluster here. So we've got default kube-node-lease, we've got kube-public, and kube-system. So let's take a look at kube default actually for starters. So I'll say get all from namespace default. And that just has our cluster IP in there for Kubernetes. And then if we take a look at kube-system, this is where the bulk of the pods are pertaining to the actual Kubernetes cluster.
15:32So let's explore get all on kube-system. And so this is where you can see we've got things like coredns, we've got etcd, that's our key value store, we've got our API server up and running, our controller manager, proxy, and scheduler as well. So everything looks to be up and running just fine here with one exception, which you might see these two coredns pods are actually zero out of one ready, and they're just sitting here in a pending state. And if you take a look at our deployments down here for coredns, you'll see that the deployment requested that there be two pods running.
16:09However, we have zero out of two that are actually ready to go. And so what's happening here is that coredns is actually failing. And that's because we haven't installed a container network interface yet. So coredns will sit here in a pending state until you actually install that CNI into your cluster. So we'll go ahead and do that in the next video. I hope this has been informative for you, and I'd like to thank you for viewing.
Install Project Calico Container Network Interface
0:11Hey, guys. And welcome back. Let's go ahead and resolve this issue with CoreDNS not starting up in our cluster here. And we are going to do that by, of course, installing our CNI. And so we're going to head over to the documentation here. And if you take a look at the documentation, somewhere right in here it does tell you that CoreDNS will not start. Let me just do a quick search for CoreDNS here. There's a lot of text in this documentation. And sure enough, under Installing a Pod network add-on, installing a CNI, a Container Network Interface, it says that Cluster DNS (CoreDNS) will not start up before a network is installed.
0:54So we need to install a Container Network Interface in order for CoreDNS to spin up. Now, there's a bunch of different supported Container Network Interfaces out there. However, there is one in particular that I like, that I've tested out, that works well, which is called Project Calico. So if you just head out and search for Project Calico, this is an open-source project from a company called Tigera. And Project Calico provides your Container Network Interface, as well as network policy capabilities as well.
1:28So this is a really cool open-source project that is available out on GitHub. So I am going to go ahead and go back and just add on GitHub to our search here. And once we get over to GitHub here, this should take us over to the project page here. And then we are going to look for how to get started running Calico. So they've got a link to a quick start guide on their documentation that describes how to get Calico up and running on your Kubernetes cluster. And they've got a few different options.
1:59So if you're using a managed public cloud offering, like EKS or GKE or AKS, they've got directions for those. They've also got self-managed public cloud options here as well. But in this particular case, I'm actually going to do self-managed on-premises, and choose that option. And then we're just going to scroll down a little bit here and look for how to install Calico with the Kubernetes API datastore of 50 nodes or less. And so they've got a really simple command to just download a YAML configuration file for Calico here.
2:36So we're going to download that. And then we are going to just run kubectl apply on that YAML file, and that should get projectcalico, the CNI, up and running inside of our environment. And you can see what features we get here. We get network policy, IP address management-- of course, the CNI itself-- the overlay routing capabilities, as well as the data store integration here. So let's run our curl command here. For starters, just copy that to my clipboard.
3:08And download that file, and then we can explore it. So we'll just cat that file here. And this is a really, really large file. But it basically contains all of the necessary components in order for Calico to get up and running. You can see we have a deployment there. And we've also got-- let's see. What else? If we keep scrolling up, we've also got a rolling update strategy here for a DaemonSet. So we've got a DaemonSet that's running a calico-node right here. And we've also got a ClusterRoleBinding here and a bunch of other resources.
3:42But I won't bore you with all the details on that. And then let's go ahead and do a kubectl apply. So we'll just copy this command here. I could just type it out, but I'm just feeling lazy right now. And that's going to go ahead and apply the entire YAML file to our network here. And that should get projectcalico up and running. And if we come back and run kubectl get all on our kube-system namespace here, once projectcalico gets fully up and running we should see coredns eventually start up here.
4:15So right now, coredns is just kind of crashing and restarting on its own. But once Calico is up and running and initialized here, you'll see that, sure enough, coredns is up and running. And it looks like calico-node is up and running as well. And calico-kube-controllers is still in the creation process. But in a few more seconds, you'll see that that comes up running as well. So now we've got a fully functioning cluster here. We've got coredns running. We've also got projectcalico running as our Container Network Interface.
4:46And so we could go ahead and run a test pod. So I'm going to use an nginx test pod as an example just to make sure that we can spin something up. So for starters, I'm going to create a namespace. So I'll run kubectl. Let's say create namespace. And I'll give that a name. Let's call it something like trevor. So now we've got a new namespace. So if I do kubectl get ns, you can see we've got this trevor namespace. So let's go ahead and do a kubectl run. And we'll take a look at the help for that.
5:19There's a whole bunch of options here. But we could do run pod with the name nginx. And then we use the image nginx off of the Docker Hub. And that should be a pretty good example. So I'll actually just copy that to my clipboard and then paste it in. And I also want to tack on the namespace option so that the pod gets run inside of our trevor namespace. So we'll do that. And sure enough, it created that pod. So now we need to verify that it's actually running.
5:50So I'll do a kubectl get all for the namespace trevor. And as you can see, that pod is pending. So I'm going to do a kubectl. Let's say describe. We'll do describe pod in namespace trevor. And so this gives us some more details on it. And as you can see, we get this message saying that 0 of 1 nodes are available. And it actually tells us the specific reason that no nodes are available, because the only node that we have in our cluster has something known as a [garbled].
6:25And that [garbled] is basically specifying that the node is a master node. And so because this is a master node, the kube-scheduler is refusing to schedule this pod that we've just run on this node and so therefore it's just failing because there's no other nodes in the cluster that can satisfy this pod's needs. So what we can do, if we switch back to our documentation here, they actually provide a command that we can use to untaint the node with that master annotation.
6:59So I'm just going to run this kubectl [garbled] nodes command, and that will remove-- you can see we've got a minus sign here at the end. That will remove the master [garbled] from our node, and it'll allow the kube-scheduler to schedule our pod to run on our one and only node in our cluster. All right, so now the k8smaster01 node has been untainted. And if we come back up here and run our describe command, you can see that in a matter of seconds, the scheduler says OK, I'm now going to schedule you to run on this node.
7:33And it pulls the image from Docker Hub and then it starts the pod with the container nginx inside of it. So now if we do a kubectl get all on namespace trevor, you can see that that pod is actually running. So our Container Network Interface seems to be working just fine. You can see that our pod was able to get an IP address on our pod CIDR block here, which is 10.88/16. And we are good to go to continue working with our Kubernetes cluster. So that's how we can use kubeadm to spin up a Kubernetes cluster on your own self-managed node.
8:10I hope this has been informative for you, and I'd like to thank you for viewing.
Frequently asked questions
What does the Deploy a Kubernetes Cluster using Kubeadm lesson cover?
The lesson shows how to build a self-managed Kubernetes cluster with kubeadm on an Amazon EC2 Linux host. It covers preparing the VPC and instance, installing kubeadm with its container runtime and iptables configuration, initializing the master node, and installing the Project Calico CNI. It closes by troubleshooting a pending pod with kubectl describe.
How long is the kubeadm lesson and how does it fit the CKA course?
The lesson runs 57 minutes and is part of the Certified Kubernetes Administrator (CKA) course, which maps to the Certified Kubernetes Administrator certification, exam CKA. The full course is about 17 hours per learner and goes on to RBAC, networking, upgrades, HA control planes, etcd, and storage.
Should a team use a managed Kubernetes service or a self-managed kubeadm cluster?
The lesson compares the two options so a Team Lead can weigh the tradeoffs. Managed cloud services add centralized logging, such as Amazon CloudWatch, and elastic scaling of worker nodes. A kubeadm cluster gives the team direct ownership of the control plane and node setup.
How do you prepare a Linux host and network for kubeadm?
The lesson uses a supported Linux distribution such as Ubuntu, disables swap, renames the node, and configures iptables. It also sets up routing so worker nodes and master nodes can communicate on TCP 6443. That routing matters in multi-region VPC and multicloud setups.
Why does a pod stay pending on a new single-node kubeadm cluster?
The lesson runs kubectl describe on the pending pod to show that the cluster's single node carries a master node taint. Because of that taint, kube-scheduler refuses to place the pod, and no other nodes are available to run it. Team members learn to read the scheduler message and identify the cause.
How can an IT Director or Training Manager roll this lesson out to a team?
The course Technical Copy recommends assigning the course before production cluster ownership or kubeadm upgrades, so the team practices the same admin workflows. Team reporting shows per-learner progress and completion, cohort and group views, and completion exports for audit evidence. Virtual labs and practice exams in the catalog support hands-on practice and readiness checks.
Team training path
Turn this skill into assignable team training
This free skill is a preview of the courses your team can assign, track, and report on with CBT Nuggets.
Free training library
More free lessons from CBT Nuggets
Kubernetes
Introduction to Certified Kubernetes Application Developer (CKAD)
Free lesson from Certified Kubernetes Application Developer (CKAD) · 58m
Microsoft Windows Server
Microsoft PowerShell 4 Foundations
Free lesson from PowerShell · 7h 57m
DevOps
Docker (v18.06.3)
Free lesson from Docker · 2h 6m
Networking
Border Gateway Protocol (BGP): Basic Operations
Free lesson from Border Gateway Protocol (BGP) · 60m
Networking
Define Wireless Network Architectures
Free lesson from Wireless Design Professional Training · 55m
Python
Introduction to Programming and Python
Free lesson from Certified Associate in Python Programming (PCAP) · 57m
$59
seat / mo, billed annually
