{"id":570,"date":"2019-08-18T12:21:37","date_gmt":"2019-08-18T19:21:37","guid":{"rendered":"http:\/\/35.243.195.209\/?p=570"},"modified":"2020-10-25T14:41:54","modified_gmt":"2020-10-25T21:41:54","slug":"how-to-install-kubernetes-and-enable-dashboard","status":"publish","type":"post","link":"https:\/\/nanzhou.cc\/index.php\/2019\/08\/18\/how-to-install-kubernetes-and-enable-dashboard\/","title":{"rendered":"How to Install Kubernetes and Enable Dashboard"},"content":{"rendered":"\n\n\n<h2 class=\"wp-block-heading\">Summary<\/h2>\n\n\n\n<p>In this post, I will introduce how to create a single control-node Kubernetes cluster with version v1.15.x and enable an accessible dashboard. With this post, you can easily deploy a cluster from scratch for testing.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Details<\/h2>\n\n\n\n<p>Before we start, note that there are problems like single node failure and security, which makes the deployment not production-ready.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">1. Prerequest<\/h3>\n\n\n\n<h4 class=\"wp-block-heading\">1). Operation Systems<\/h4>\n\n\n\n<p>The most common ones are<\/p>\n\n\n\n<figure class=\"wp-block-table\"><table><thead><tr><th>OS<\/th><th>Version<\/th><\/tr><\/thead><tbody><tr><td>Ubuntu<\/td><td>16.04+<\/td><\/tr><tr><td>Debian<\/td><td>9<\/td><\/tr><tr><td>CentOS<\/td><td>7<\/td><\/tr><\/tbody><\/table><\/figure>\n\n\n\n<p>There will be many compatibility issues in some packages if you are using the old version of systems. I took a lot of effort and tried to solve the compatibility issues manually in Ubuntu 14.04 but failed. Please consider upgrading the system first if possible.<\/p>\n\n\n\n<h4 class=\"wp-block-heading\">2). Required Ports<\/h4>\n\n\n\n<h5 class=\"wp-block-heading\">Control-plane node(s)<\/h5>\n\n\n\n<figure class=\"wp-block-table\"><table><thead><tr><th>Protocol<\/th><th>Direction<\/th><th>Port Range<\/th><th>Purpose<\/th><th>Used By<\/th><\/tr><\/thead><tbody><tr><td>TCP<\/td><td>Inbound<\/td><td>6443*<\/td><td>Kubernetes API server<\/td><td>All<\/td><\/tr><tr><td>TCP<\/td><td>Inbound<\/td><td>2379-2380<\/td><td>etcd server client API<\/td><td>kube-apiserver, etcd<\/td><\/tr><tr><td>TCP<\/td><td>Inbound<\/td><td>10250<\/td><td>Kubelet API<\/td><td>Self, Control plane<\/td><\/tr><tr><td>TCP<\/td><td>Inbound<\/td><td>10251<\/td><td>kube-scheduler<\/td><td>Self<\/td><\/tr><tr><td>TCP<\/td><td>Inbound<\/td><td>10252<\/td><td>kube-controller-manager<\/td><td>Self<\/td><\/tr><\/tbody><\/table><\/figure>\n\n\n\n<h5 class=\"wp-block-heading\">Worker node(s)<\/h5>\n\n\n\n<figure class=\"wp-block-table\"><table><thead><tr><th>Protocol<\/th><th>Direction<\/th><th>Port Range<\/th><th>Purpose<\/th><th>Used By<\/th><\/tr><\/thead><tbody><tr><td>TCP<\/td><td>Inbound<\/td><td>10250<\/td><td>Kubelet API<\/td><td>Self, Control plane<\/td><\/tr><tr><td>TCP<\/td><td>Inbound<\/td><td>30000-32767<\/td><td>NodePort Services**<\/td><td>All<\/td><\/tr><\/tbody><\/table><\/figure>\n\n\n\n<p>It is very import to open these ports especially when you are using provided virtual machines like EC2, where typically the required ports are closed.<\/p>\n\n\n\n<h4 class=\"wp-block-heading\">3). Runtime<\/h4>\n\n\n\n<p>Install docker.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code class=\"\"># Uninstall old versions\nsudo apt-get remove docker docker-engine docker-ce docker.io\n\nsudo apt-get install \\\n    apt-transport-https \\\n    ca-certificates \\\n    curl \\\n    gnupg-agent \\\n    software-properties-common\ncurl -fsSL https:\/\/download.docker.com\/linux\/ubuntu\/gpg | sudo apt-key add -\nsudo apt-key fingerprint 0EBFCD88\n\n# pub   rsa4096 2017-02-22 [SCEA]\n#      9DC8 5822 9FC7 DD38 854A  E2D8 8D81 803C 0EBF CD88\n# uid           [ unknown] Docker Release (CE deb)  &lt;docker@docker.com>\n# sub   rsa4096 2017-02-22 [S]\n\nsudo add-apt-repository \\\n   \"deb [arch=amd64] https:\/\/download.docker.com\/linux\/ubuntu \\\n   $(lsb_release -cs) \\\n   stable\"\nsudo apt-get update\nsudo apt-get install docker-ce docker-ce-cli containerd.io\ndocker --version\n\n# Set up the Docker daemon\ncat &lt;&lt;EOF | sudo tee \/etc\/docker\/daemon.json\n{\n  \"exec-opts\": [\"native.cgroupdriver=systemd\"],\n  \"log-driver\": \"json-file\",\n  \"log-opts\": {\n    \"max-size\": \"100m\"\n  },\n  \"storage-driver\": \"overlay2\"\n}\nEOF\n\nsudo mkdir -p \/etc\/systemd\/system\/docker.service.d\n\n# Restart Docker\nsudo systemctl daemon-reload\nsudo systemctl restart docker\nsudo systemctl enable docker<\/code><\/pre>\n\n\n\n<h3 class=\"wp-block-heading\">2. Install kubeadm, kubelet, and kubectl<\/h3>\n\n\n\n<p>You will install these packages on all of your machines:<\/p>\n\n\n\n<ul class=\"wp-block-list\"><li><code>kubeadm<\/code>: the command to bootstrap the cluster.<\/li><li><code>kubelet<\/code>: the component that runs on all of the machines in your cluster and does things like starting pods and containers.<\/li><li><code>kubectl<\/code>: the command line util to talk to your cluster.<\/li><\/ul>\n\n\n\n<pre class=\"wp-block-code\"><code class=\"\">apt-get update &amp;&amp; apt-get install -y apt-transport-https curl\ncurl -s https:\/\/packages.cloud.google.com\/apt\/doc\/apt-key.gpg | apt-key add -\ncat &lt;&lt;EOF >\/etc\/apt\/sources.list.d\/kubernetes.list\ndeb https:\/\/apt.kubernetes.io\/ kubernetes-xenial main\nEOF\napt-get update\napt-get install -y kubelet kubeadm kubectl\napt-mark hold kubelet kubeadm kubectl<\/code><\/pre>\n\n\n\n<h3 class=\"wp-block-heading\">3. Init Cluster and Add Network Add-on<\/h3>\n\n\n\n<p>Before you apply any other configurations, you should apply the network add-ons. Here we use <a href=\"https:\/\/docs.projectcalico.org\/v3.8\/introduction\/\">Calico<\/a>, which provides networking and network security solutions for containers in Kubernetes. Remember that your cluster will not work without network add-ons.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code class=\"\"># swap off\nroot@ubuntu:\/home\/ubuntu# sudo swapoff -a\n\nroot@ubuntu:\/home\/ubuntu# sudo kubeadm init --pod-network-cidr=192.168.0.0\/16\nroot@ubuntu:\/home\/ubuntu# kubectl apply -f https:\/\/docs.projectcalico.org\/v3.8\/manifests\/calico.yaml<\/code><\/pre>\n\n\n\n<p>You will see the following outputs.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code class=\"\">Your Kubernetes control-plane has initialized successfully!\n\nTo start using your cluster, you need to run the following as a regular user:\n\n  mkdir -p $HOME\/.kube\n  sudo cp -i \/etc\/kubernetes\/admin.conf $HOME\/.kube\/config\n  sudo chown $(id -u):$(id -g) $HOME\/.kube\/config\n\nYou should now deploy a pod network to the cluster.\nRun \"kubectl apply -f [podnetwork].yaml\" with one of the options listed at:\n  https:\/\/kubernetes.io\/docs\/concepts\/cluster-administration\/addons\/\n\nThen you can join any number of worker nodes by running the following on each node as root:\nkubeadm join x.x.x.x:6443 --token xxx \\\n    --discovery-token-ca-cert-hash sha256:xxx<\/code><\/pre>\n\n\n\n<p>Now you can log in to other machines and join in the clusters. To verify your cluster, on any node, run<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code class=\"\">sudo kubectl get nodes<\/code><\/pre>\n\n\n\n<p>If the node is not ready, check the problem, use<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code class=\"\">sudo kubectl describe node irp125a-v36g01<\/code><\/pre>\n\n\n\n<p>Note that the token will <strong>expire in 24 hours<\/strong>. You can create a new one on the master node by<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code class=\"\">kubeadm token create --print-join-command<\/code><\/pre>\n\n\n\n<p>You may also want to taint the master node so that you can deploy pods on the master node.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code class=\"\">root@ubuntu:\/home\/ubuntu#~$ sudo kubectl taint nodes --all node-role.kubernetes.io\/master-\nnode\/xxx untainted\nerror: taint \"node-role.kubernetes.io\/master:\" not found<\/code><\/pre>\n\n\n\n<h3 class=\"wp-block-heading\">4. Start Dashboard<\/h3>\n\n\n\n<p>We use the fastest set-up.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code class=\"\">kubectl apply -f https:\/\/raw.githubusercontent.com\/kubernetes\/dashboard\/v1.10.1\/src\/deploy\/recommended\/kubernetes-dashboard.yaml<\/code><\/pre>\n\n\n\n<p>However, for now, the dashboard is only available by the localhost. Apply the following snippets if you want to remote access.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code class=\"\"># dashboard-adminuser.yaml\napiVersion: v1\nkind: ServiceAccount\nmetadata:\n  name: admin-user\n  namespace: kube-system\n---\napiVersion: rbac.authorization.k8s.io\/v1\nkind: ClusterRoleBinding\nmetadata:\n  name: admin-user\nroleRef:\n  apiGroup: rbac.authorization.k8s.io\n  kind: ClusterRole\n  name: cluster-admin\nsubjects:\n- kind: ServiceAccount\n  name: admin-user\n  namespace: kube-system<\/code><\/pre>\n\n\n\n<pre class=\"wp-block-code\"><code class=\"\">root@ubuntu: sudo kubectl apply -f dashboard-adminuser.yaml<\/code><\/pre>\n\n\n\n<p>Then you can get token by using<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code class=\"\">root@ubuntu: sudo kubectl -n kube-system describe secret $(kubectl -n kube-system get secret | grep admin-user | awk '{print $1}')<\/code><\/pre>\n\n\n\n<p>Note that you may get many tokens, any of them is good to use.<br>After that, we should expose the dashboard. <a href=\"https:\/\/kubernetes.io\/docs\/concepts\/services-networking\/service\/#nodeport\">NodePort<\/a> is a good choice.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code class=\"\">root@ubuntu: sudo kubectl -n kube-system edit service kubernetes-dashboard<\/code><\/pre>\n\n\n\n<p>You will get the following output.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code class=\"\"># Please edit the object below. Lines beginning with a '#' will be ignored,\n# and an empty file will abort the edit. If an error occurs while saving this file will be\n# reopened with the relevant failures.\n#\napiVersion: v1\n...\n  name: kubernetes-dashboard\n  namespace: kube-system\n  resourceVersion: \"343478\"\n  selfLink: \/api\/v1\/namespaces\/kube-system\/services\/kubernetes-dashboard-head\n  uid: 8e48f478-993d-11e7-87e0-901b0e532516\nspec:\n  clusterIP: 10.100.124.90\n  externalTrafficPolicy: Cluster\n  ports:\n  - port: 443\n    protocol: TCP\n    targetPort: 8443\n    nodePort: 30001 # specify your desired port\n  selector:\n    k8s-app: kubernetes-dashboard\n  sessionAffinity: None\n  type: NodePort # change this line\nstatus:\n  loadBalancer: {}<\/code><\/pre>\n\n\n\n<p>Verify the dashboard by<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code class=\"\">root@ubuntu:~$ sudo kubectl -n kube-system get service kubernetes-dashboard\nNAME                   TYPE       CLUSTER-IP     EXTERNAL-IP   PORT(S)         AGE\nkubernetes-dashboard   NodePort   x.x.x.x   &lt;none>        443:30001\/TCP   7m58s<\/code><\/pre>\n\n\n\n<p><code>443:30001\/TCP<\/code> means it is exposed to external networks.<br>Open your browser and type <code>https:\/\/x.x.x.x:30001<\/code>, where <code>x.x.x.x<\/code> is the public IP of any node.<br><img decoding=\"async\" src=\"http:\/\/35.243.195.209\/wp-content\/uploads\/2019\/08\/Screen-Shot-2019-08-18-at-12.14.07-PM.png\" alt=\"k8s_dashboard\"><\/p>\n\n\n\n<p>Remember it is <code>https<\/code> and use the token you get from <code>dashboard-adminuser<\/code>.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Reference<\/h2>\n\n\n\n<p><a href=\"https:\/\/kubernetes.io\/docs\/setup\/production-environment\/tools\/kubeadm\/create-cluster-kubeadm\/#before-you-begin\">K8s Official Guide<\/a><br><a href=\"https:\/\/github.com\/kubernetes\/dashboard\/blob\/master\/README.md\">Dashboard Official Guide<\/a><br><a href=\"https:\/\/docs.projectcalico.org\/v3.8\/introduction\/\">Calico<\/a><\/p>\n","protected":false},"excerpt":{"rendered":"<p>Summary In this post, I will introduce how to create a single control-node Kubernetes cluster with version v1.15.x and enable an accessible dashboard. With this post, you can easily deploy a cluster from scratch for testing. Details Before we start, note that there are problems like single node failure and security, which makes the deployment&#8230;<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[14,42,43,13],"tags":[],"class_list":["post-570","post","type-post","status-publish","format-standard","hentry","category-backend","category-distributed-system","category-kubernetes","category-web"],"_links":{"self":[{"href":"https:\/\/nanzhou.cc\/index.php\/wp-json\/wp\/v2\/posts\/570","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/nanzhou.cc\/index.php\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/nanzhou.cc\/index.php\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/nanzhou.cc\/index.php\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/nanzhou.cc\/index.php\/wp-json\/wp\/v2\/comments?post=570"}],"version-history":[{"count":6,"href":"https:\/\/nanzhou.cc\/index.php\/wp-json\/wp\/v2\/posts\/570\/revisions"}],"predecessor-version":[{"id":1524,"href":"https:\/\/nanzhou.cc\/index.php\/wp-json\/wp\/v2\/posts\/570\/revisions\/1524"}],"wp:attachment":[{"href":"https:\/\/nanzhou.cc\/index.php\/wp-json\/wp\/v2\/media?parent=570"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/nanzhou.cc\/index.php\/wp-json\/wp\/v2\/categories?post=570"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/nanzhou.cc\/index.php\/wp-json\/wp\/v2\/tags?post=570"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}