Unknownpgr

Building a Kubernetes Cluster [1] - Virtual Machines

2021-06-25 17:10:36 | English, Korean

This post was translated from Korean into English by AI.

Vagrant logo

As you may know if you saw my previous post, I recently bought a fairly powerful mini computer. One of the main reasons I bought it was to study Kubernetes. So I tried installing Kubernetes, and I would like to document the process here.

Vagrant

I had actually tinkered with Kubernetes a little before. I do not remember the details very well, but I must have installed something incorrectly, because I struggled with it for quite a while before giving up. Back then, using a virtual machine did not occur to me, so I repeatedly installed and uninstalled Kubernetes directly on the host computer. This time, however, I first set up a virtual machine with Vagrant and then installed Kubernetes on top of it so that the same thing would not happen again.

Vagrant is a kind of Infrastructure as Code (IaC)-based virtual machine management tool. As the name suggests, IaC refers to a system that lets you manage infrastructure in the form of code. That code might be yaml or json, or it might literally be a script written in something like python. Vagrant lets you create virtual machines from a configuration file called a Vagrantfile. Therefore, as long as you have the Vagrnatfile, you can always create the same virtual machine. This makes it very useful when you need to create several virtual machines with identical environments or run tests repeatedly in the same environment. And because this Vagrantfile, like a Dockerfile, is just a text file, it can also be version-controlled with Git.

One difference between a Dockerfile and a Vagrantfile is that a Dockerfile uses its own language, whereas a Vagrantfile is simply a script written in Ruby. It is intuitive enough, of course, that you can easily understand it even if you know no Ruby at all.

Vagrant itself, however, is neither a virtual machine nor virtualization software. Vagrant interacts with virtualization software such as VirtualBox and VMware, or platforms such as AWS and GCP, to manage their virtual machines. To use Vagrant, therefore, you need either to have VirtualBox or something similar installed already, or to integrate it with a platform such as AWS.

Vagrant manages virtual machines on a per-directory basis. Create a file named Vagrantfile in a directory, enter the appropriate settings in it, and run the vagrant up command; a virtual machine will then be created and started according to the settings in the Vagrantfile. You can connect to the resulting virtual machine with the vagrant ssh command.

Information about the virtual machine created this way is stored in a hidden directory called .vagrant. I have never experienced this myself, but apparently editing the Vagrantfile incorrectly can sometimes cause conflicts with a previously created virtual machine. In that case, you can delete the .vagrant directory.

Writing a Vagrantfile

A Vagrantfile is, in fact, an ordinary Ruby script. I do not know how to use Ruby, of course, so I just worked it out by intuition. Below is the Vagrantfile I wrote. If you want to use this script, you will need to change the IP address as appropriate for your own network.

Vagrant.configure("2") do |config|
  config.vm.box = "ubuntu/focal64"
  config.vm.network "public_network", ip: "172.30.1.100"
  config.vm.synced_folder '.', '/vagrant', disabled: true
  config.vm.provider "virtualbox" do |v|
    v.memory = 16384
    v.cpus = 4
  end
  config.disksize.size = '200GB'
  config.vm.provision "shell", path: "bootstrap.sh"
end

Alongside the Vagrantfile in the same directory is the following bootstrap.sh file.

ip route add default via 172.30.1.1
echo 'vagrant:some-password-for-vagrant' | sudo chpasswd
sed -i 's/PasswordAuthentication no/PasswordAuthentication yes/g' /etc/ssh/sshd_config
systemctl restart sshd.service
curl -sfL https://get.k3s.io | sh -s - --write-kubeconfig-mode 644

Configuring Virtual Machine Accounts and the Rabbit Holes I Went Down

Virtual Machine Network Modes and the Rabbit Holes I Went Down

Virtual machines can use several network modes. The two most commonly used modes are Network Address Translation (NAT) mode and Bridged Adapter mode. This article explains them in great detail, so I will provide only a brief explanation here.

Network Address Translation (NAT)

Intuitively, you can think of NAT mode as creating a virtual router for the virtual machine inside your computer. (Real routers use NAT too, so it really is essentially the same thing.) Think of it as creating a router whose external IP address is the host machine's IP address. Just as we can access both the router's own IP address from behind a router (I do not mean accessing the configuration page through the default gateway; I mean that the router's external IP address is accessible) and the internet, this method allows you to access both the host machine and the internet from inside the virtual machine.

When you use a router, packets created inside the router's network all appear from outside the router to have originated from the router itself. Likewise, packets created by a virtual machine in NAT mode all appear from outside the host to have originated from the host.

Also, just as you cannot access devices behind a router from outside it without port forwarding, NAT mode makes it impossible to access the virtual machine from the host machine or the internet. You can, of course, use NAT mode and configure port forwarding on the host machine, but in that case using the Bridged Network mode described below is much more convenient.

Bridged Adapter

Bridged Adapter mode directly connects the virtual machine, through one of the host's network cards, to the network to which the host is connected. Thus, although there is physically one machine, there are logically two devices. As you can see in the Vagrantfile above, I connected the server to my router and connected the virtual machine using a Bridged Adapter. After doing so, the router's network page showed two IP addresses and two MAC addresses. It is equivalent to connecting another physical machine to the router in parallel, rather than a virtual machine.

Naturally, the virtual machine and the host machine can therefore access each other over the LAN, and the virtual machine can also be accessed externally if you configure port forwarding on the router.

This may appear completely trouble-free, but the real problem lies inside the virtual machine. When I manually set the IP address in the Vagrantfile for the purpose of port forwarding, DHCP did not work at all, so a default gateway was not assigned automatically either. With a configuration like mine, however, the virtual machine's internal network consists of NAT mode enabled by default with a Bridged Adapter added on top. Consequently, the internet works just fine, making it appear as though Bridged Adapter mode has been configured correctly, while external connections still fail—an odd situation indeed. I had no idea this was happening and assumed only that something was wrong with the Bridged Adapter configuration, so I wandered around in circles for quite a while yet again.

The correct approach is either to configure DHCP or, as I did, use a shell script to add another default gateway.

Connecting to the Virtual Machine

If the Vagrantfile has been written correctly, you can connect using the vagrant up command as mentioned earlier. Of course, because the Vagrantfile above permits password-based connections, you can also connect with the ssh vagrant@172.30.1.100 command.

References


- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -