LFS258 [2/15]: Kubernetes Installation and Configuration
Tags: lfs258, kubernetes, devops
Published: 2020-01-19 13:47:33

> **คำเตือน!** บทความนี้ไม่ใช้ How To นะคร๊าบ 😘

# Installation Tools

ในการเริ่มต้นทำความรู้จักกับ Kubernetes แค่อ่านอย่างเดียวคงเบื่อแย่ มันต้องมี cluster ของตัวเองซัก cluster และการที่จะได้มาซึ่ง cluster ก็มี 4 วิธีให้เลือก
- **เล่นผ่าน web**: [Play with Kubernetes](https://labs.play-with-k8s.com/) และ [Katacoda](https://www.katacoda.com/) เหมาะสำหรับการ walk through เพื่อทำความรู้จักเบื้องต้น
- **ใช้ managed service ของ cloud provider** ซึ่งส่วนใหญ่จะมี free tier ให้ลองใช้กัน เช่น [`GKE`](https://cloud.google.com/kubernetes-engine/) ของ Google Cloud, [`AKS`](https://azure.microsoft.com/en-us/services/kubernetes-service/) ของ Azure, [`EKS`](https://aws.amazon.com/eks/) ของ AWS และ น้องใหม่อย่าง [`ACK`](https://www.alibabacloud.com/product/kubernetes) ของ Alibaba Cloud เป็นต้น

|<img src="https://thepracticaldev.s3.amazonaws.com/i/vmzd67z6rap0g2fluhw4.png" alt="drawing" width="200"/>|<img src="https://thepracticaldev.s3.amazonaws.com/i/gnxdrb0ntj3zfbtwvo28.png" alt="drawing" width="200"/>|<img src="https://thepracticaldev.s3.amazonaws.com/i/eq94kbtu5h9o5347z8js.png" alt="drawing" width="200"/>|<img src="https://thepracticaldev.s3.amazonaws.com/i/pbgpm0msjj2h70kv6ilk.png" alt="drawing" width="200"/>|
|:--:|:--:|:--:|:--:|
|<center>GKE</center>|<center>AKS</center>|<center>EKS</center>|<center>ACK</center>|

- **ลงมื่อสร้างด้วยตัวเองแบบ single node cluster** ซึ่งเพียงพอกับการทำความเข้าใจเบื้องต้น โดยสามรถใช้ tools เช่น [`minikube`](https://github.com/kubernetes/minikube) ซึ่งจะเป็นการ download Linux Guest ที่มี kubernetes เรียบร้อยแล้วมา run บน VirtualBox ของเครื่องเรา  หรือ [`MicroK8s`](https://microk8s.io/) ที่มีใน Ubuntu 16.04 และ 18.04 ซึ่งเป็นของ Canonical หรือจะเป็น [`hyperkube`](https://github.com/kubernetes/kubernetes/tree/master/cluster/images/hyperkube) ซึ่งเป็น container image ที่มี kubernetes อยู่ในนั้น

|<img src="https://thepracticaldev.s3.amazonaws.com/i/w7qnb84w3bj8c9ul4vrg.png" alt="drawing" width="200"/>|<img src="https://thepracticaldev.s3.amazonaws.com/i/wlcjtw2ig8ikrtzx5mir.png" alt="drawing" width="200"/>|
|:--:|:--:|
|<center>Minikube</center>|<center>MicroK8S</center>|

- **ลงเป็น multi-node cluster** ถ้าอยากทำความเข้าใจให้มากขึ้น โดย ใช้ Tools [`kubeadm`](https://github.com/kubernetes/kubeadm) ซึ่งเป็น community-suggested tool ในการ setup kubernetes cluster ที่ลงง่ายและไม่ยึดติดกับ platform ใดๆ, ถ้าอยากได้สำเร็จรูปเลย อาจใช้พวก automation อย่าง [`kubespray`](https://github.com/kubernetes-sigs/kubespray) หรือ [`kops`](https://github.com/kubernetes/kops) แต่ `kops` ต้องใช้บน AWS เท่านั้น

|<img src="https://thepracticaldev.s3.amazonaws.com/i/kvbopzke040yx6d68wuv.png" alt="drawing" width="200"/>|<img src="https://thepracticaldev.s3.amazonaws.com/i/w3ezgy4kqkbvlb7urov4.png" alt="drawing" width="200"/>|<img src="https://thepracticaldev.s3.amazonaws.com/i/imwjufocelj407jruh4c.jpg" alt="drawing" width="200"/>|
|:--:|:--:|:--:|
|<center>kubeadm</center>|<center>kubespray</center>|<center>kops</center>|

---

# Installing kubectl

<img src="https://thepracticaldev.s3.amazonaws.com/i/izoy1kzgmj1vwa746dy6.png" alt="drawing" width="200"/>

`kubectl` เป็น command ที่ใช้ในการ configure และ manage kubernetes cluster ถ้าไม่ใช้ `kubectl` เราก็สามารถจัดการ kubernetes cluster ของเราได้เช่นกัน โดยใช่ curl หรือเขียน client โดยใช้ Go library เช่นกัน แต่ชีวิตก็จะลำบากหน่อยๆ

การที่จะได้มาซึ่ง `kubectl` มี 3 ทาง
- **Install จาก respository ของ OS ที่เราใช้** เช่น ถ้าใช้ RHEL7/CentOS7 `kubectl` จากอยู่ใน Package **kubernetes-client**
- **Download pre-build release** จาก [Github](https://github.com/kubernetes/kubectl/releases) ผมแนะนำวิธีนี้ เพราะจะได้ `kubectl` version ตรงกับ kubenetes cluster ของเราและไม่ต้อง compile เองให้ยุ่งยาก
- **Download source code** จาก [Github](https://github.com/kubernetes/kubectl) มา compile เอง ใช้วิธีนี้เฉพาะตอนที่อยากลอง หรือ pre-build release ไม่ support OS ที่เราใช้เท่านั้น แต่โดยปกติถ้า OS ไหนลง Kubernetes ได้ ก็ใช้ pre-build release ได้แน่นอน

command `kubectl` จะอ่าน configure จาก `~/.kube/config` เพื่อ connect ไปยัง cluster ของเรา ใน file นี้จะประกอบด้วย
- **clusters**: เป็นรายละเอียดของ cluster เช่น ชื่อ cluster, credential ของ cluster และ url ของ `kube-apiserver` (endpoint)
- **users**: เป็น username และ credential ของ user นั้นๆ
- **contexts**: เป็นชื่อ context, ชื่อ cluster และ username ที่ใช้ในการ connect ไปยัง cluster นั้นๆ

> เราสามารถ switch context เพื่อเปลี่ยน user ที่ Login เข้าไปใน cluster หรือ เปลี่ยน cluster ที่ ได้โดยใช้ **`kubectl config use-context <context_name>`**

Reference: [The Kubectl Book](https://kubectl.docs.kubernetes.io/)

---

# Using Minikube

<img src="https://thepracticaldev.s3.amazonaws.com/i/w7qnb84w3bj8c9ul4vrg.png" alt="drawing" width="200"/>

การ install Minikube นั้นง่ายมาก แค่ไป load pre-build binary จาก GitHub มา แล้ว run ได้เลย แต่ต้องแน่ใจก่อนว่า เครื่องเรา install hypervisor KVM หรือ VirtualBox ไว้แล้ว

สามารถอ่านวิธีการ setup ได้จาก Doc ของ Kubernetes ได้เลย
- [Install Minikube](https://kubernetes.io/docs/tasks/tools/install-minikube/)

ทำเสร็จแล้วก็ลองทำ lab ของ Kubernetes ได้เลย
- [Installing Kubernetes with Minikube](https://kubernetes.io/docs/setup/learning-environment/minikube/)

โดยใน VM ที่ Minikube run ขึ้นมา ภายใยจะเป็นการ run binary ชื่อ `localkube` ซึ่งจะไป run components ของ kubernetes ทั้งหมดขึ้นมาให้เราใช้งาน และ Container runtime ที่ Minikube ทำให้เราคือ **Docker**

---

# Installing with kubeadm

<img src="https://thepracticaldev.s3.amazonaws.com/i/kvbopzke040yx6d68wuv.png" alt="drawing" width="200"/>

เรามาสร้าง cluster จริงๆ กันบ้าง `kubeadm` เป็น tool ที่ตรงไปตรงมาที่สุดในการ setup multi-node kubernetes cluster โดย เริ่มมีมาตั้งแต่ kubernetes v1.4.0 และเปลี่ยนสถานะจาก beta เป็น statble ใน kubernetes v1.15.0 พร้อมทั้งเพิ่ม function HA เข้าไปด้วย

สามารถดูวิธีการ install `kubeadm` ได้จาก
- [Installing kubeadm](https://kubernetes.io/docs/setup/production-environment/tools/kubeadm/install-kubeadm/)

จากนั้นลอง setup cluster แบบ single control plane (ไม่มี HA) ได้จาก
- [Creating a single control-plane cluster with kubeadm](https://kubernetes.io/docs/setup/production-environment/tools/kubeadm/create-cluster-kubeadm/)

และลองของใหม่ แบบที่มี HA ได้จาก
- [Creating Highly Available clusters with kubeadm](https://kubernetes.io/docs/setup/production-environment/tools/kubeadm/high-availability/)

ในการ join cluster ของ `kubeadm` นั้นต้องใช้ token ที่ hash ด้วย SHA256 เป็นอย่างต่ำ โดยข้อมูลนี้จะได้มาหลังจากที่เรา run `kubeadm init` ที่ master node สำเร็จ

Step ในการ setup cluster คร่าวจะเป็นแบบนี้
- `kueadm init` ที่ master node
- create cluster network เช่น `kubectl create -f https://git.io/weave-kube`
- `kubeadm join --token <token> https://<MasterIP>:<Port>` ที่ worker nodes

เมื่อทุกอย่างเรียกร้อยอย่าลืม copy config ของ kubectl ทาไว้ที่ home ของ user ที่จะใช้งาน kubectl 

``` bash
$ mkdir -p $HOME/.kube
$ sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config
$ sudo chown $(id -u):$(id -g) $HOME/.kube/config
```

จากนั้น Logout และ login ก็จะใช้ kubectl เพื่อ interact กับ cluster ได้แล้ว

---
<a name="Pod-Networking"></a>

# Installing a Pod Network

ก่อนที่จะ initial cluster ต้องเลือก network ให้ได้เสียก่อนว่าจะใช้อะไร เพราะต้องวางแผน IP ไว้ให้ดี อย่าให้มี IP ซ้ำ โดย network ที่นิยมๆ กันมีดังต่อไปนี้

|<img src="https://thepracticaldev.s3.amazonaws.com/i/aolpcv43uxflmt4dark3.png" alt="drawing" width="200"/>|<img src="https://thepracticaldev.s3.amazonaws.com/i/a2tcniaypof0dsm0eg8j.png" alt="drawing" width="200"/>|<img src="https://thepracticaldev.s3.amazonaws.com/i/iog6al27ui1hc5cad5ad.png" alt="drawing" width="200"/>|<img src="https://thepracticaldev.s3.amazonaws.com/i/oc4k5pi5yfsbsofw54a8.png" alt="drawing" width="200"/>|<img src="https://thepracticaldev.s3.amazonaws.com/i/26fc12vfgs826vd4vpbz.png" alt="drawing" width="200"/>|
|:--:|:--:|:--:|:--:|:--:|
|<center>Calico</center>|<center>Flannel</center>|<center>Kube-router</center>|<center>Romana</center>|<center>Weave Net</center>|

- **[Calico](https://docs.projectcalico.org/v3.11/getting-started/kubernetes/installation/calico)**: เป็น flat layer 3 network ที่สื่อสารกันโดยไม่มี IP encapsulation ใช้ได้ทั้ง Kubernetes, Openshift, Docker, Mesos และ Openstack เป็น network model ที่ง่ายและยืดหยุ่น สามารถ scale ในระบบใหญ่ๆ ได้ดี ทำ policy ได้ และ **สามาถใช้ option Canal เพื่อ integrate กับ Flannel ได้**
- **[Flannel](https://github.com/coreos/flannel)**: เป็น Layer 3 IPv4 network ที่เชื่อต่อระหว่าง nodes ใน cluster ได้รับการพัฒนาโดย CoreOS สามารถใช้ backend mechanism ได้หลายแบบเช่น VXLAN เป็นต้น มี `flanneld` เป็น host agent
- **[Kube-router](https://github.com/cloudnativelabs/kube-router)**: claim ว่าเป็น "single binary do it all" ยังอยู่ใน alpha stage และมีแผนว่าจะมี distributed load balancer, firewall และ router ทำมาเพื่อ kubernetes โดยเฉพาะ
- **[Romana](https://romana.io/)**: เป็นอีก project ที่เน้น automation ของ network และ security สามาถใช้กับ cluster ใหญ่ๆ ได้ IPAM-Aware Topology และ integrate กับ `kops` ได้
- **[Weave Net](https://www.weave.works/docs/net/latest/kubernetes/)**: เป็น add-on ที่ได้มาตรฐาน CNI

[Container Network Interface (CNI)](https://github.com/containernetworking/cni) เป็น project ของ [CNCF](https://www.cncf.io/) ที่จะทำให้ network ใน ของ container เป็นมาตรฐาน ไม่ผูกติดกับ vendor ใด vendor หนึ่ง และกำลังได้รับความนิยมเป็นอย่างมาก

---

# More Installation Tools

Kubernetes ก็เหมือน application ทั่วไปที่เราลงใน server ดังนั้น เราสามารถใช้ configuration management system เช่น Chef, Puppet, Ansible หรือ Terraform ในการลงแบบอัตโนมัติได้ โดย Tools ที่เราสามารถใช้ได้มีดังนี้
- **[kubespray](https://github.com/kubernetes-sigs/kubespray)**: ตอนี้เข้ามาเป็น incubator project ของ CNCF แล้ว เป็น Ansible playbook ที่สามารถ setup kubernetes ได้หลากหลาย OS หลากหลาย network providers ชื่อเดิม kargo
- **[kops](https://github.com/kubernetes/kops)**: ทำให้การ setup kubernetes cluster บน AWS เป็นเรื่องไม่ยาก ตอนนี้กำลังทำให้ใช้ได้บน GKE, VMware และ Openstack แต่ยังเป็น beta version อยู่
- **[kube-aws](https://github.com/kubernetes-incubator/kube-aws)**: เป็น Tool ที่ใช้ feature Cloud Formation ของ AWS ในการ setup cluster
- **[kubicon](http://kubicorn.io/)**: ทำให้ `kubeadm` set up cluster ได้ง่ายขึ้น เค้า claim ว่าไม่มี dependency เกี่ยวกับ DNS, run ได้หลาย OS, สามารถ snapshot cluster แล้ว ย้ายไปที่อื่นได้

ถ้าอยากเข้าใจการ setup Kubernetes แบบลึกซึ้ง... ในทำตาม ["Kelsey Hightower walkthrough: kubernetes the hard way"](https://github.com/kelseyhightower/kubernetes-the-hard-way) ลึกซึ้งจริงๆ นะ ผมลองมาแล้ว

---

# Installation Considerations

ก่อนอื่นควรลอง install แบบ single node ด้วย Minikube ก่อน จากนั้นค่อยลองทำ Multi Node Cluster โดยก่อนการ set up cluster ให้ตอนคำถามเหล่านี้ก่อน

| Type | Question |
|:--:|:--:|
| **Provider** | จะลงใน platform ไหน public หรือ private cloud ลงบน Physical หรือ VM |
| **OS** | จะใช้ OS อะไร ? |
| **Network** | จะใช้ network provider ไหน ? เป็น overlay ไหม ? |
| **ETCD** | จะ install etcd แบบ standalone หรือ cluster จะไว้ใน kubenetes หรือ ข้างนอก |
| **HA** | จะทำ HA ให้กับ Master ไหม ? |

---

# Main Deployment Configuration

รูปแบบในการ set up kubernetes cluster มี 4 แบบให้เลือกดังนี้
- **Single-Node**: สำหรับการทดสอบ เรียนรู้ หรือ พัฒนา application เบื้องต้น
- **Single Master, Multiple Workers**: สำหรับการทดสอบ เรียนรู้ หรือ พัฒนา application ที่ต้องอาศัย feature clustering
- **Multiple Masters with HA, Multiple Workers**: เพื่อความน่าเชื่อถือของระบบ สามารถใช้ใน production ได้ แต่ต้องมี load balancer วางไว้หน้า cluster เพื่อ share traffic มายัง worker nodes และ จาก worker node ไปยัง Master Node ที่เป็น leader
- **HA etcd, HA Masters, Multiple Workers**: น่าเชื่อถือสุดๆ เพราะ HA ทุก component อาจเอา etcd ไปไว้นอก cluster เพื่อเพิ่ม reliability

> เราสามารถทำ [Federation](https://kubernetes.io/docs/concepts/cluster-administration/federation/) เพื่อเพิ่ม HA ระหว่าง cluster โดย join หลายๆ clusters เข้าด้วยกัน เพื่อให้ใช้ control plane เดียวกัน ทำให้สามารถ move resource ข้าม cluster เพื่อ cluster ใด cluster หนึ่ง fail แต่ ใน version นี้ยังมีปัญหาเยอะ รอดูว่า [v2](https://github.com/kubernetes-sigs/kubefed) ถ้าดีขึ้นจะเป็นประโยชน์มาก

---

# Systemd Unit Files for Kubernetes

ในการ setup kubernetes cluster ด้วย `kubeadm` จะมีแค่ `kubelet` เท่านั้นที่ run เป็น standard system daemon (systemd) แต่เราสามารถนำ component อื่นๆ ของ kubernetes ออกมา run เป็น standard system daemon ได้เช่นกัน

---

# Using Hyperkube

Hyperkube เป็น image ใน Repository ของ Google ([gcr](https://console.cloud.google.com/gcr/images/google-containers/GLOBAL/hyperkube))

ในการใช้งาน `hyperkube` ต้องลง `kubelet` เป็น system daemon และ configure มันให้อ่าน manifest files ที่จะระบุวิธีการ run แต่ละ component โดยแต่ละ component คือ `hyperkube`

---

# Compiling from Source

list ของ [binary release](https://github.com/kubernetes/kubernetes/releases) สามารถดูได้ใน GitHub แต่ถ้าจะ compile เองมี 2 ทางให้เลือก
- **Build ด้วย Golang**: 
    - [Install Golang](https://golang.org/doc/install)
      
``` bash
$ mkdir -p $GOPATH/src/k8s.io
$ cd $GOPATH/src/k8s.io
$ git clone https://github.com/kubernetes/kubernetes
$ cd kubernetes
$ make
```

- **Build ด้วย Docker**:
    - [Install Docker](https://docs.docker.com/engine/)

``` bash
$ git clone https://github.com/kubernetes/kubernetes
$ cd kubernetes
$ make quick-release
```

> binary จะอยู่ที่ `_output/bin`

---