IMRC - Kubernetes v1.21 Instalation Guide with Ubuntu 20.04 === ###### tags: `IMRC` `Container` `Docker` `Kubernetes` `v1.21` `Hybrid Cluster` `Mixed Nodes` `Linux` `Windows` `Documentation` > Written by Benny Suryajaya, compiled from various sources. > NOTE: This guide is far from perfect. Please contribute to fix and/or complete this guide. ## Preface A continuation of the previous [Kubernetes v1.18 Installation Guide](https://hackmd.io/@kolmibeni/k8s-118-install). Since it involves newer versions of environment (Kubernetes v1.21 and Ubuntu 20.04), installation steps may differ from the previous guide. This guide is a perpetual work-in-progress. Updates, changes, and improvements may be added in the future. ## Table of Content [ToC] ## 1. Install Docker in Linux Prepare node: ```bash=1 # Set your hostname # Change into your preferred hostname sudo hostnamectl set-hostname [your-hostname] # Add root password sudo passwd root sudo sed -i '/cdrom:/ s/^\(.*\)$/#\1/g' /etc/apt/sources.list sudo apt-get update sudo apt-get install -y openssh-server sudo apt-get install -y vim sudo apt-get update sudo apt-get install -y apt-transport-https ca-certificates curl sudo apt-get install -y software-properties-common gnupg2 ``` Add Docker official GPG key: ```bash=+ curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo apt-key --keyring /etc/apt/trusted.gpg.d/docker.gpg add - ``` Add Docker apt repository: ```bash=+ sudo add-apt-repository \ "deb [arch=amd64] https://download.docker.com/linux/ubuntu \ $(lsb_release -cs) \ stable" ``` Install Docker CE, you can adjust the version here: ```bash=+ sudo apt-get update && sudo apt-get install -y \ containerd.io=1.2.13-2 \ docker-ce=5:19.03.11~3-0~ubuntu-$(lsb_release -cs) \ docker-ce-cli=5:19.03.11~3-0~ubuntu-$(lsb_release -cs) ``` Set Docker to use systemd as control group: ```bash=+ cat <<EOF | sudo tee /etc/docker/daemon.json { "exec-opts": ["native.cgroupdriver=systemd"], "log-driver": "json-file", "log-opts": { "max-size": "100m" }, "storage-driver": "overlay2" } EOF sudo mkdir -p /etc/systemd/system/docker.service.d sudo systemctl daemon-reload sudo systemctl restart docker ``` Give administrative right to user Docker: ```bash=+ sudo usermod -aG docker ${USER} su ${USER} id -nG ``` Test Docker installation: ```bash=+ docker version ``` ## 2. Install Kubernetes v1.21 in Linux Disable swap: ```bash=1 sudo swapoff -a sudo sed -i '/ swap / s/^\(.*\)$/#\1/g' /etc/fstab ``` Check the content of resolv.conf: ```bash=+ cat /etc/resolv.conf ``` Modify the nameserver in resolv.conf: ```bash=+ # If your current nameserver is 127.0.0.53 (Ubuntu 18 and Ubuntu 20) sudo sed -i -e \ 's/nameserver 127.0.0.53/nameserver 8.8.8.8 8.8.4.4/i' \ /etc/resolv.conf ``` Switch to the root user ```bash=+ su ``` Update and upgrade package list: ```bash=+ sudo apt-get update -y && apt-get upgrade -y ``` Ensure net.bridge.bridge-nf-call-iptables is set to 1 in your sysctl config: ```bash=+ cat <<EOF | sudo tee /etc/sysctl.d/k8s.conf net.bridge.bridge-nf-call-ip6tables = 1 net.bridge.bridge-nf-call-iptables = 1 EOF sudo sysctl --system ``` Make sure that the br_netfilter module is loaded: ```bash=+ sudo modprobe br_netfilter ``` Update the `apt` package index and install packages needed to use the Kubernetes `apt` repository: ```bash=+ # Run as root user apt-get update && sudo apt-get install -y apt-transport-https curl ``` Download the Google Cloud public signing key: ```bash=+ # Run as root user curl -fsSLo /usr/share/keyrings/kubernetes-archive-keyring.gpg https://packages.cloud.google.com/apt/doc/apt-key.gpg # NOTE 20230824: # Run this too to add another pubkey, sometimes above key is invalid curl -fsSLo /usr/share/keyrings/kubernetes-archive-keyring.gpg https://dl.k8s.io/apt/doc/apt-key.gpg ``` Add the Kubernetes `apt` repository: ```bash=+ # # Run as root user # echo "deb [signed-by=/usr/share/keyrings/kubernetes-archive-keyring.gpg] \ # https://apt.kubernetes.io/ kubernetes-xenial main" \ # | sudo tee /etc/apt/sources.list.d/kubernetes.list echo "deb [signed-by=/usr/share/keyrings/kubernetes-archive-keyring.gpg] https://apt.kubernetes.io/ kubernetes-xenial main" | sudo tee /etc/apt/sources.list.d/kubernetes.list ``` Proceed to update `apt` package index, install kubelet, kubeadm and kubectl, and pin their version: ```bash=+ apt-get update -y apt-get install -y kubelet=1.21.14-00 kubeadm=1.21.14-00 kubectl=1.21.14-00 apt-mark hold kubelet kubeadm kubectl ``` ## 3. Create Kubernetes Cluster Master > If you are using iMRC K8s Ubuntu Template (20220526), then continue from here. ### Initialize the Kubernetes cluster in Linux Reset config, disable swap, and reset iptables: ```bash=1 # Run this as root user sudo rm -Rf $HOME/.kube/config sudo yes | kubeadm reset sudo iptables -F && iptables -t nat -F && iptables -t mangle -F && iptables -X sudo swapoff -a sudo sed -i '/ swap / s/^\(.*\)$/#\1/g' /etc/fstab ``` Initialize cluster: ```bash=+ # Run this as root user kubeadm init --pod-network-cidr=10.244.0.0/16 --service-cidr=10.96.0.0/12 # OPTIONAL # Run this command if you need to add extra IP for the API Server. # Otherwise, skip to the next section. kubeadm init --pod-network-cidr=10.244.0.0/16 \ --service-cidr=10.96.0.0/12 \ --apiserver-cert-extra-sans=140.116.86.178 ``` Setup config file for kubectl ```bash=+ # Run this as root user mkdir -p $HOME/.kube sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config sudo chown $(id -u):$(id -g) $HOME/.kube/config export KUBECONFIG=/etc/kubernetes/admin.conf #Exit the root user exit # Run the commands one more time as normal user mkdir -p $HOME/.kube sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config sudo chown $(id -u):$(id -g) $HOME/.kube/config ``` ### Setup the Network for Hybrid Cluster Prepare Kubernetes control plane for Flannel: ```bash=1 sudo sysctl net.bridge.bridge-nf-call-iptables=1 ``` ~~Download & configure latest Flannel manifest for Linux:~~ ```bash=+ # DOES NOT WORK, READ BELOW wget https://raw.githubusercontent.com/coreos/flannel/master/Documentation/kube-flannel.yml ``` Newer version of Flannel (v0.19.1) does not work with Kubernetes v1.21. Get the working Flannel manifest (v0.18.1) from [here](https://hackmd.io/@kolmibeni/flannel-0181) and upload it to the Master node. Modify the net-conf.json section of the flannel manifest (~/kube-flannel.yml) in order to set the VNI to 4096 and the Port to 4789. It should look as follows: ```json= net-conf.json: | { "Network": "10.244.0.0/16", "Backend": { "Type": "vxlan", "VNI" : 4096, "Port": 4789 } } ``` Apply the Flannel manifest and validate: ```bash=3 kubectl apply -f kube-flannel.yml ``` Check all Kubernetes system pods: ```bash=+ kubectl get pods -A ``` Make sure all system pods are ready and running. If you are using Flannel 0.19, notice that Flannel pods are located in `kube-flannel` namespace, while other system pods are in `kube-system`. ![](https://i.imgur.com/CvGIs2C.png) If you are using Flannel 0.18, all pods are in the `kube-system` namespace. ![](https://i.imgur.com/J7b21r4.png) Add Windows Flannel and kube-proxy DaemonSets: ```bash=+ curl -L https://github.com/kubernetes-sigs/sig-windows-tools/releases/latest/download/kube-proxy.yml \ | sed 's/VERSION/v1.21.14/g' \ | kubectl apply -f - # 1. If using overlay/vxlan kubectl apply -f https://github.com/kubernetes-sigs/sig-windows-tools/releases/latest/download/flannel-overlay.yml # 2. If using overlay/vxlan, and network name is not 'Ethernet' # (e.g.: 'Ethernet0 2') curl -L https://github.com/kubernetes-sigs/sig-windows-tools/releases/latest/download/flannel-overlay.yml \ | sed 's/Ethernet/Ethernet0 2/g' \ | kubectl apply -f - ``` ## 4. Install Docker in Windows Ensure the following things in your Windows node: * Using the English version of Windows Server 2019 version 1809 * OS Build is 17763.379 (KB4489899) or newer * Selecting "English (United State)" as current system locale in Administrative language settings Enable Hyper-V from PowerShell: ```shell=1 Enable-WindowsOptionalFeature -Online -FeatureName Microsoft-Hyper-V -All ``` After Hyper-V has been enabled, **restart** the Windows node. (Optional): Allow downloaded script files to run in the current session ``` Set-ExecutionPolicy -ExecutionPolicy RemoteSigned -Force -Scope Process; ``` ### 1. ~~ONLINE MODE~~ > **20230913 Update**: Below steps are already deprecated since the Powershell gallery fails. > Please go to step 3.USING INSTALLATION SCRIPT Open an elevated PowerShell session and install the Docker-Microsoft PackageManagement Provider from the PowerShell Gallery. ```shell=+ Install-Module -Name DockerMsftProvider -Repository PSGallery -Force ``` If you're prompted to install the NuGet provider, type Y to install it as well. If you get an error opening the PowerShell gallery, you may need to set the TLS version used by the PowerShell client to TLS 1.2. To do this, run the following command: ```shell=+ # Set the TLS version used by the PowerShell client to TLS 1.2. [System.Net.ServicePointManager]::SecurityProtocol = [System.Net.SecurityProtocolType]::Tls12; ``` Use the PackageManagement PowerShell module to install the latest version of Docker. ```shell=+ # Install latest version Install-Package -Name docker -ProviderName DockerMsftProvider # Install version 19.03.11 Install-Package -Name docker -ProviderName DockerMsftProvider -RequiredVersion 19.03.11 -Force -Verbose ``` When PowerShell asks you whether to trust the package source 'DockerDefault', type A to continue the installation. After the installation completes, restart the computer. ```shell=+ Restart-Computer -Force ``` (Obsolete) Run the install script in the machine with internet enabled. ```shell=+ .\install.ps1 ``` After Docker has been installed, **restart** the Windows node. ### 2. ~~OFFLINE MODE~~ > **20230913 Update**: Below steps are already deprecated since the Powershell gallery fails. > Please go to step 3.USING INSTALLATION SCRIPT Run the install.ps1 with the DownloadOnly parameter in the machine with internet enabled. This doesn’t install anything, it only downloads the zip file. ```shell=+ .\install.ps1 -DownloadOnly ``` Copy the install.ps1 file and the installation zip file over to the air-gapped (offline) machine and run the install with the -Offline parameter. ```shell=+ .\install.ps1 -Offline ``` ### 3. USING INSTALLATION SCRIPT Download the installation script for Docker Community Edition and run the script using PowerShell with elevated permission (administrator mode). ```shell=+ Invoke-WebRequest -UseBasicParsing "https://raw.githubusercontent.com/microsoft/Windows-Containers/Main/helpful_tools/Install-DockerCE/install-docker-ce.ps1" -o install-docker-ce.ps1 .\install-docker-ce.ps1 ``` ## 5. Install Kubernetes in Windows > If you are using iMRC K8s Ubuntu Template (20220526), then continue from here. Prepare installation directory (e.g.: C:\k). ```shell= mkdir C:\k; cd C:\k; ``` Install wins, kubelet, and kubeadm. ```shell=+ [Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12 curl.exe -LO https://github.com/kubernetes-sigs/sig-windows-tools/releases/latest/download/PrepareNode.ps1 .\PrepareNode.ps1 -KubernetesVersion v1.21.14 ``` Install kubectl ```shell=+ curl.exe -LO https://storage.googleapis.com/kubernetes-release/release/v1.18.0/bin/windows/amd64/kubectl.exe curl.exe -LO https://storage.googleapis.com/kubernetes-release/release/v1.21.14/bin/windows/amd64/kubectl.exe ``` Add kubectl to path ```bash=+ # Add C:\k\ directory to path [Environment]::SetEnvironmentVariable("Path", $env:Path + ";C:\k", [EnvironmentVariableTarget]::Machine) # Add KUBECONFIG environment variable referring to C:\k\config file [Environment]::SetEnvironmentVariable("KUBECONFIG", "C:\k\config",[EnvironmentVariableTarget]::User) ``` Using SCP, copy cluster config file from master node (**Step 3**: $HOME/.kube/config directory in Linux master node) to the C:\k directory in Windows worker node. First, install the Posh-SSH module to the PowerShell ```shell=+ Install-Module -Name Posh-SSH ``` Remove all SSH trusted hosts ```bash=+ Get-SSHTrustedHost | Remove-SSHTrustedHost ``` Copy the config file with the following command. When asked, supply with username and password for Linux master node authentication. ```bash=+ # Replace [MASTER_NODE_IP] with the IP address of your Linux master node # Replace [USERNAME] with the username of your Linux master node Get-SCPFile -ComputerName '[MASTER_NODE_IP]' ` -RemoteFile "/home/[USERNAME]/.kube/config" ` -LocalFile "C:\k\config" # OR scp [USERNAME]@[MASTER_NODE_IP]:/home/[USERNAME]/.kube/config C:\k\config ``` ![](https://i.imgur.com/pfEBhIx.png) Open **a new PowerShell window**, then test the kubectl functionality: ```bash=+ kubectl cluster-info ``` ## 6. Join Windows Node to Cluster Get the join token by executing the following command on the Linux master node: ```bash=1 kubeadm token create --print-join-command ``` Run the join command in the Windows worker node ```bash=+ # Example: kubeadm join 192.168.13.43:6443 \ --token b29c63.aqvsg0953edz2ozw \ --discovery-token-ca-cert-hash \ sha256:529c64ad705bf356a2efa3c1bdb8181b852e2bc5d46f5d161dee1105e872bae6 ``` Verify your installation ```shell=+ kubectl get nodes -o wide ``` ![](https://i.imgur.com/9nUZiTt.png) All Flannel installation must be ready. It will take approx. 15 minutes for the system to finish deploying kube-flannel and kube-proxy in Windows node. ```bash=+ # to view all system pods kubectl get pods -n kube-system # to view only Flannel pods kubectl get pods -n kube-system -l app=flannel ``` ![](https://i.imgur.com/bRvAOeH.png) ## 7. Join Linux Node to Cluster Follow **Step 1** and **Step 2** to install Docker and Kubernetes in Linux worker node. After that, follow the commands below to join Linux worker node to the cluster. Get the join token by executing the following command on the Linux master node: ```bash=1 kubeadm token create --print-join-command ``` Run the join command in the Linux worker node ```bash=+ # Run this command using root user: kubeadm join 192.168.13.43:6443 \ --token b29c63.aqvsg0953edz2ozw \ --discovery-token-ca-cert-hash \ sha256:529c64ad705bf356a2efa3c1bdb8181b852e2bc5d46f5d161dee1105e872bae6 ``` Copy the config file from Linux master node ```bash=+ # Replace [MASTER_NODE_IP] with the IP address of your Linux master node # Replace [USERNAME] with the username of your Linux master node scp [USERNAME]@[MASTER_NODE_IP]:/home/[USERNAME]/.kube/config \ /home/[USERNAME]/.kube/config ``` Set the `KUBECONFIG` variable: ```bash=+ export KUBECONFIG=$HOME/.kube/config ``` Verify your installation, then test the kubectl functionality: ```bash=+ kubectl cluster-info ``` ## 8. Install Kubernetes Dashboard In Linux master node, deploy Kubernetes Dashboard by executing this command: ```bash=1 # latest version kubectl apply -f https://raw.githubusercontent.com/kubernetes/dashboard/v2.5.0/aio/deploy/recommended.yaml ``` In Linux master node, create admin-user service account to give permission for Kubernetes Dashboard to manage the cluster by executing the following commands: ```bash=+ cat <<EOF | kubectl apply -f - apiVersion: v1 kind: ServiceAccount metadata: name: admin-user namespace: kubernetes-dashboard EOF cat <<EOF | kubectl apply -f - apiVersion: rbac.authorization.k8s.io/v1 kind: ClusterRoleBinding metadata: name: admin-user roleRef: apiGroup: rbac.authorization.k8s.io kind: ClusterRole name: cluster-admin subjects: - kind: ServiceAccount name: admin-user namespace: kubernetes-dashboard EOF ``` In Linux master node, get the token for the Kubernetes Dashboard admin-user by executing the following command. This token will be used for logging in to Kubernetes Dashboard. ```bash=+ kubectl -n kubernetes-dashboard describe secret \ $(kubectl -n kubernetes-dashboard get secret \ | grep admin-user \ | awk '{print $1}') ``` In Windows worker node, open a PowerShell window and execute this command to open a proxy to Kubernetes Dashboard. Let this PowerShell window open and keep the command running. ```bash=+ kubectl proxy ``` In Windows worker node, access Kubernetes Dashboard from the following URL, then use the above-mentioned token to login. > http://localhost:8001/api/v1/namespaces/kubernetes-dashboard/services/https:kubernetes-dashboard:/proxy/ ## 9. Install Helm For better CI/CD workflow, we will use Helm to deploy our containerized applications to Kubernetes. To install Helm in Windows, first install Chocolatey package manager. ```bash= Set-ExecutionPolicy Bypass -Scope Process -Force; [System.Net.ServicePointManager]::SecurityProtocol = [System.Net.ServicePointManager]::SecurityProtocol -bor 3072; iex ((New-Object System.Net.WebClient).DownloadString('https://community.chocolatey.org/install.ps1')) ``` Test your Chocolatey installation. ```bash=+ choco # or choco -? ``` Install Helm using Chocolatey. ```bash=+ choco install kubernetes-helm ``` Test your Helm installation. ```bash=+ helm # or helm ls ``` ## [Optional 1] Delete and Re-join Windows Node In some cases, our cluster installation fails due to some issue with the Windows worker node and we may need to remove the failed Windows node from cluster and rejoin it again. First, get the name of Windows node by running this command in the Linux master node: ```bash=1 kubectl get nodes ``` ![](https://i.imgur.com/GVE2emc.png) On Linux master node, drain and delete the Windows node: ```bash=+ kubectl drain win-8uja2qmijvm --delete-local-data --force --ignore-daemonsets --delete-emptydir-data kubectl delete node win-8uja2qmijvm ``` On Windows node, reset kubeadm and remove related services: ```bash=+ # Reset kubeadm kubeadm reset -f # Remove HNS Network get-hnsnetwork | remove-hnsnetwork # Remove firewall rule remove-netfirewallrule kubelet # Remove kubelet service without confirmation nssm remove kubelet confirm # Stop and remove wins service without confirmation stop-service rancher-wins nssm remove rancher-wins confirm ``` Following directories can be deleted on Windows node: ``` C:\etc C:\opt C:\run C:\usr C:\var All contents of C:\k, EXCEPT: PrepareNode.ps1, config, and kubectl.exe ``` Get the join token again by executing the following command on the Linux master node: ```bash=+ kubeadm token create --print-join-command ``` Afterwards, on Windows node, re-install Kubernetes components and re-join the node (or follow **Step 7**) ```bash=+ # Install Kubernetes components .\PrepareNode.ps1 -KubernetesVersion v1.21.14 # Join Windows node to cluster kubeadm join 192.168.13.43:6443 \ --token b29c63.aqvsg0953edz2ozw \ --discovery-token-ca-cert-hash \ sha256:529c64ad705bf356a2efa3c1bdb8181b852e2bc5d46f5d161dee1105e872bae6 ``` ## [Optional 2] Delete and Re-join Linux Node Just like what happened with Windows worker node, Linux worker node may also has issue and makes our cluster installation fails, and we may need to remove the failed Linux node from cluster and rejoin it again. First, get the name of Linux worker node by running this command in the Linux master node: ```bash=1 kubectl get nodes ``` On Linux master node, drain and delete the Linux worker node: ```bash=+ # For example, Linux worker node name is ubuntu-worker-1 kubectl drain ubuntu-worker-1 --delete-local-data --force --ignore-daemonsets kubectl delete node ubuntu-worker-1 ``` On Linux worker node, reset kubeadm: ```bash=+ # Reset kubeadm kubeadm reset ``` Redo **Step 2** to install Kubernetes in Linux worker node again. Get the join token again by executing the following command on the Linux master node: ```bash=+ kubeadm token create --print-join-command ``` Afterwards, on Linux worker node, re-join the node ```bash=+ # Join Linux worker node to cluster kubeadm join 192.168.13.43:6443 \ --token b29c63.aqvsg0953edz2ozw \ --discovery-token-ca-cert-hash \ sha256:529c64ad705bf356a2efa3c1bdb8181b852e2bc5d46f5d161dee1105e872bae6 ``` ## [Optional 3] Rebuild the Kubernetes Cluster In some terribly unlucky times, problems keep appearing in our Kubernetes Cluster and nothing we do works. If the situation allows, we may consider to rebuild the Kubernetes cluster from beginning. First, execute **[Optional 1]** and **[Optional 2]** to remove all Windows and Linux worker nodes. In Linux master node, check that all worker nodes have been removed and only the master node remains. ```bash= kubectl get nodes ``` In Linux master node, reset all Kubernetes setting. ```bash=+ kubeadm reset ``` Redo the installation from **Step 3** until **Step 8**. ## [Optional 4] Add more Users to access Kubernetes Add new user in Ubuntu. ```bash= sudo adduser newuser ``` Add the `newuser` into `sudo` and `docker` group. ```bash=+ sudo usermod -aG sudo newuser sudo usermod -aG docker newuser ``` Login as the newuser. ```bash=+ su newuser ``` Add Kubernetes config file to enable access to `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 ``` If Kubernetes config file doesn't exist in `/etc/kubernetes/admin.conf`, then copy the config file from another user. ```bash=+ mkdir -p $HOME/.kube sudo cp -i /home/administrator/.kube/config $HOME/.kube/config sudo chown $(id -u):$(id -g) $HOME/.kube/config ``` If all users don't have the Kubernetes config file, then copy the config file from Linux master node. ```bash=+ # Replace [MASTER_NODE_IP] with the IP address of your Linux master node # Replace [USERNAME] with the username of your Linux master node scp [USERNAME]@[MASTER_NODE_IP]:/home/[USERNAME]/.kube/config /home/[USERNAME]/.kube/config # Example: scp administrator@192.168.0.146:/home/administrator/.kube/config /home/newuser/.kube/config ``` Set the `KUBECONFIG` variable: ```bash=+ export KUBECONFIG=$HOME/.kube/config ``` ## References Below are the references used in this guide, including how-to-install and various troubleshooting manuals. Future references will be included later. * [Install Mirantis Docker Container Runtime on Windows Server](https://docs.mirantis.com/docker-enterprise/v3.1/dockeree-products/mcr/mcr-windows.html) * [Intro to Windows support in Kubernetes](https://kubernetes.io/docs/setup/production-environment/windows/intro-windows-in-kubernetes/) * [Installing kubeadm](https://kubernetes.io/docs/setup/production-environment/tools/kubeadm/install-kubeadm/) * [Installing kubectl](https://kubernetes.io/docs/tasks/tools/install-kubectl/#install-kubectl-binary-via-curl) * [Adding Windows nodes to Kubernetes cluster](https://kubernetes.io/docs/tasks/administer-cluster/kubeadm/adding-windows-nodes/) * [Kubernetes Dashboard](https://kubernetes.io/docs/tasks/access-application-cluster/web-ui-dashboard/) * [Guide for scheduling Windows containers in Kubernetes](https://kubernetes.io/docs/setup/production-environment/windows/user-guide-windows-containers/) * [Kubernetes and Windows](https://www.chenshaowen.com/blog/add-windows-node-for-k8s.html) * [Troubleshooting kubeadm](https://kubernetes.io/docs/setup/production-environment/tools/kubeadm/troubleshooting-kubeadm/) * [CoreDNS fails to run in Kubernetes cluster](https://stackoverflow.com/questions/52645473/coredns-fails-to-run-in-kubernetes-cluster) * https://www.cnblogs.com/aresxin/p/K8S-issue1.html * https://www.techrunnr.com/how-to-reset-kubernetes-cluster/