Vagrant install Kubernetes on VirtualBox
Tags: vagrant, devops, kubernetes, k8s
Published: 2020-03-31 17:35:22

> จำลอง สร้าง k8s cluster ด้วย vagrant + virtualbox

### Require
```sh
- Vagrant
- VirtualBox
```

### Environments
- master
- node 1
- node 2

---

### Vagrantfile

#### - ส่วน Environments
```sh
IMAGE_NAME = "bento/ubuntu-18.04"
COUNTER = 2
Vagrant.configure("2") do |config|
  config.vm.box = IMAGE_NAME
  config.vm.provider "virtualbox" do |v|
    v.memory = 1024
    v.cpus = 2
  end

  ...
  ...
end
```

> - กำหนด Environments ที่จะต้องใช้ ในแต่ละ vm
> - ** ขั้นต่ำในการลง k8s คือ CPUs 2 core


#### - ส่วน Init 

> ส่วนที่ต้องลงทุก vm

```sh
  ....
  ....
  
  config.vm.provision "shell", privileged: false, inline: <<-SCRIPT
      sudo swapoff -a
      sudo sed -i '/swap/d' /etc/fstab
      sudo apt-get update
      sudo apt-get install -y docker.io apt-transport-https curl
      sudo systemctl start docker
      sudo systemctl enable docker
      sudo apt-get update
      sudo apt-get install -y apt-transport-https
      curl -s https://packages.cloud.google.com/apt/doc/apt-key.gpg | sudo apt-key add -
      sudo touch /etc/apt/sources.list.d/kubernetes.list
      echo "deb http://apt.kubernetes.io/ kubernetes-xenial main" | sudo tee -a /etc/apt/sources.list.d/kubernetes.list
      sudo apt-get update
      sudo apt-get install -y kubeadm 
      
  SCRIPT
  ...
  ...
```

#### - ส่วน Master

> ส่วนการจัดการ ของ vm สำหรับ master node

```sh
  config.vm.define "k8s-master" do |master|
    master.vm.box = IMAGE_NAME
    master.vm.network "private_network", ip: "10.0.0.10"
    master.vm.hostname = "k8s-master"
    master.vm.provision "shell", inline: <<-SHELL
      rm -rf /vagrant/join.sh
      sudo kubeadm init --apiserver-advertise-address=10.0.0.10 --pod-network-cidr=10.244.0.0/16  
      sudo kubeadm token create --print-join-command > /vagrant/join.sh
      chmod +x /vagrant/join.sh
      mkdir -p $HOME/.kube  
      sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config
      sudo chown $(id -u):$(id -g) $HOME/.kube/config  
      kubectl apply -f https://raw.githubusercontent.com/coreos/flannel/master/Documentation/kube-flannel.yml  
      SHELL
  end
```

> ``sudo kubeadm token create --print-join-command`` จะได้ในส่วนของ ``script สำหรับ ให้ worker แต่ละตัวไปใช้ เพื่อ join หา master node `` 

```sh
kubeadm join <ip master>:6443 --token xxxx --discovery-token-ca-cert-hash sha256:xxxx
```

> แล้วเอาส่วนเราทำการ ให้มัน echo ลง ไฟล์ ``/vagrant/join.sh`` 

#### - ส่วน Worker node 1 - 2

> ส่วนของ vm ของ แต่ละ worker node

```sh
  ...
  ...
  ...
  (1..COUNTER).each do |i|
    config.vm.define "node-#{i}" do |node|
        node.vm.box = IMAGE_NAME
        node.vm.network "private_network", ip: "10.0.0.#{i + 11}"
        node.vm.hostname = "node-#{i}"
        node.vm.provision "shell", privileged: false, inline: <<-SHELL
          sudo /vagrant/join.sh
          echo 'Environment="KUBELET_EXTRA_ARGS=--node-ip=10.0.0.#{i + 11}"' | sudo tee -a /etc/systemd/system/kubelet.service.d/10-kubeadm.conf
          sudo systemctl daemon-reload
          sudo systemctl restart kubelet
        SHELL
    end
  end
```

> ``sudo sh /vagrant/join.sh`` ทำการ run คำสั่ง ``join master``


#### - Vagrantfile ทั้งหมด

```sh
IMAGE_NAME = "bento/ubuntu-18.04"
COUNTER = 2
Vagrant.configure("2") do |config|
  config.vm.box = IMAGE_NAME
  config.vm.provider "virtualbox" do |v|
    v.memory = 1024
    v.cpus = 2
  end

  config.vm.provision "shell", privileged: true, inline: <<-SCRIPT
      sudo swapoff -a
      sudo sed -i '/swap/d' /etc/fstab
      sudo apt-get update
      sudo apt-get install -y docker.io apt-transport-https curl
      sudo systemctl start docker
      sudo systemctl enable docker
      sudo apt-get update
      sudo apt-get install -y apt-transport-https
      curl -s https://packages.cloud.google.com/apt/doc/apt-key.gpg | sudo apt-key add -
      sudo touch /etc/apt/sources.list.d/kubernetes.list
      echo "deb http://apt.kubernetes.io/ kubernetes-xenial main" | sudo tee -a /etc/apt/sources.list.d/kubernetes.list
      sudo apt-get update
      sudo apt-get install -y kubeadm 
      
  SCRIPT

  config.vm.define "k8s-master" do |master|
    master.vm.box = IMAGE_NAME
    master.vm.network "private_network", ip: "10.0.0.10"
    master.vm.hostname = "k8s-master"
    master.vm.provision "shell", inline: <<-SHELL
      OUTPUT_FILE=/vagrant/join.sh
      rm -rf /vagrant/join.sh
      sudo kubeadm init --apiserver-advertise-address=10.0.0.10 --pod-network-cidr=10.244.0.0/16  
      sudo kubeadm token create --print-join-command > /vagrant/join.sh
      chmod +x $OUTPUT_FILE
      mkdir -p $HOME/.kube  
      sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config
      sudo chown $(id -u):$(id -g) $HOME/.kube/config  
      kubectl apply -f https://raw.githubusercontent.com/coreos/flannel/master/Documentation/kube-flannel.yml  
      SHELL
  end
  
  (1..COUNTER).each do |i|
    config.vm.define "node-#{i}" do |node|
        node.vm.box = IMAGE_NAME
        node.vm.network "private_network", ip: "10.0.0.#{i + 11}"
        node.vm.hostname = "node-#{i}"
        node.vm.provision :shell, privileged: true, inline: <<-SHELL
        sudo /vagrant/join.sh
        echo 'Environment="KUBELET_EXTRA_ARGS=--node-ip=10.0.0.#{i + 11}"' | sudo tee -a /etc/systemd/system/kubelet.service.d/10-kubeadm.conf
        sudo systemctl daemon-reload
        sudo systemctl restart kubelet
        SHELL
    end
  end
end
```

#### Run Vagrantfile

```sh
$ vagrant up
```

---

#### Check Node All 

> - master 

```sh
$ vagrant ssh k8s-master
...
vagrant@k8s-master:~$ sudo -i 
root@k8s-master:~$ kubectl get nodes
NAME         STATUS   ROLES    AGE    VERSION
k8s-master   Ready    master   15m    v1.18.0
node-1       Ready    <none>   12m    v1.18.0
node-2       Ready    <none>   9m6s   v1.18.0

```

---