一、前期準備
1)前提條件
- 三臺兼容的 Linux 主機。Kubernetes 項目為基于 Debian 和 Red Hat 的 – – Linux 發(fā)行版以及一些不提供包管理器的發(fā)行版提供通用的指令
- 每臺機器 2 GB 或更多的 RAM (如果少于這個數(shù)字將會影響你應用的運行內存)
- 2 CPU 核或更多
- 集群中的所有機器的網(wǎng)絡彼此均能相互連接(公網(wǎng)和內網(wǎng)都可以)
- 節(jié)點之中不可以有重復的主機名、MAC 地址或 product_uuid。
- 開啟機器上的某些端口。
- 禁用交換分區(qū)。為了保證 kubelet 正常工作,必須 禁用交換分區(qū)。
2)機器信息
機器類型 | 操作系統(tǒng) | 網(wǎng)卡 | IP | 節(jié)點類型 |
VMware虛擬機 | centos8 | ens33 | 192.168.0.113 | k8s-master |
VMware虛擬機 | centos8 | ens33 | 192.168.0.114 | k8s-node1 |
VMware虛擬機 | centos8 | ens33 | 192.168.0.115 | k8s-node2 |
修改主機名
# 在192.168.0.113執(zhí)行$ hostnamectl set-hostname k8s-master# 在192.168.0.114執(zhí)行$ hostnamectl set-hostname k8s-node1# 在192.168.0.115執(zhí)行$ hostnamectl set-hostname k8s-node2
時間同步
$ yum install chrony -y$ systemctl start chronyd$ systemctl enable chronyd$ chronyc sources
3)確保每個節(jié)點上 MAC 地址和 product_uuid 的唯一性
- 你可以使用命令 ip link來獲取網(wǎng)絡接口的 MAC 地址
- 可以使用 sudo cat /sys/class/dmi/id/product_uuid 命令對 product_uuid 校驗
一般來講,硬件設備會擁有唯一的地址,但是有些虛擬機的地址可能會重復。 Kubernetes 使用這些值來唯一確定集群中的節(jié)點。 如果這些值在每個節(jié)點上不唯一,可能會導致安裝 失敗。
4)允許 iptables 檢查橋接流量(可選)
- 確保 br_netfilter 模塊被加載。這一操作可以通過運行 lsmod | grep br_netfilter 來完成。若要顯式加載該模塊,可執(zhí)行 sudo modprobe br_netfilter。
- 為了讓你的 Linux 節(jié)點上的 iptables 能夠正確地查看橋接流量,你需要確保在你的 sysctl 配置中將 net.bridge.bridge-nf-call-iptables 設置為 1。所有節(jié)點都執(zhí)行以下命令:
$ cat <<EOF | sudo tee /etc/modules-load.d/k8s.confbr_netfilterEOF$ cat <<EOF | sudo tee /etc/sysctl.d/k8s.confnet.bridge.bridge-nf-call-ip6tables = 1net.bridge.bridge-nf-call-iptables = 1EOF# 手動加載所有的配置文件$ sudo sysctl –system
5)檢查所需端口
=》master節(jié)點
協(xié)議 | 方向 | 端口范圍 | 作用 | 使用者 |
TCP | 入站 | 6443 | Kubernetes API 服務器 | 所有組件 |
TCP | 入站 | 2379-2380 | etcd | 服務器客戶端 API |
TCP | 入站 | 10250 | Kubelet API | kubelet 自身、控制平面組件 |
TCP | 入站 | 10251 | kube-scheduler | kube-scheduler 自身 |
TCP | 入站 | 10252 | kube-controller-manager | kube-controller-manager 自身 |
=》node(work)節(jié)點
協(xié)議 | 方向 | 端口范圍 | 作用 | 使用者 |
TCP | 入站 | 10250 | Kubelet API | kubelet 自身、控制平面組件 |
TCP | 入站 | 30000-32767 | NodePort 服務 | 所有組件 |
NodePort 服務 的默認端口范圍。
二、安裝 runtime
為了在 Pod 中運行容器,Kubernetes 使用 容器運行時(Container Runtime)。
默認情況下,Kubernetes 使用 容器運行時接口(Container Runtime Interface,CRI) 來與你所選擇的容器運行時交互。
如果你不指定運行時,則 kubeadm 會自動嘗試檢測到系統(tǒng)上已經(jīng)安裝的運行時, 方法是掃描一組眾所周知的 Unix 域套接字。 下面的表格列舉了一些容器運行時及其對應的套接字路徑:
運行時 | 域套接字 |
Docker | /var/run/dockershim.sock |
containerd | /run/containerd/containerd.sock |
CRI-O | /var/run/crio/crio.sock |
如果同時檢測到 Docker 和 containerd,則優(yōu)先選擇 Docker。 這是必然的,因為 Docker 18.09 附帶了 containerd 并且兩者都是可以檢測到的, 即使你僅安裝了 Docker。 如果檢測到其他兩個或多個運行時,kubeadm 輸出錯誤信息并退出。kubelet 通過內置的 dockershim CRI 實現(xiàn)與 Docker 集成。
裝完docker后會僅有containerd
containerd簡介
containerd是一個工業(yè)級標準的容器運行時,它強調簡單性、健壯性和可移植性。containerd可以在宿主機中管理完整的容器生命周期,包括容器鏡像的傳輸和存儲、容器的執(zhí)行和管理、存儲和網(wǎng)絡等。
Docker vs containerd
containerd是從Docker中分離出來的一個項目,可以作為一個底層容器運行時,現(xiàn)在它成了Kubernete容器運行時更好的選擇。
K8S為什么要放棄使用Docker作為容器運行時,而使用containerd呢?
如果你使用Docker作為K8S容器運行時的話,kubelet需要先要通過 dockershim 去調用Docker,再通過Docker去調用containerd。
如果你使用containerd作為K8S容器運行時的話,由于containerd內置了 CRI (Container Runtime Interface:容器運行時接口)插件,kubelet可以直接調用containerd。
所有機器安裝docker步驟如下
# 安裝yum-config-manager配置工具$ yum -y install yum-utils# 設置yum源$ yum-config-manager –add-repo http://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo# 安裝docker-ce版本$ sudo yum install -y docker-ce# 啟動$ sudo systemctl start docker# 開機自啟$ sudo systemctl enable docker# 查看版本號$ sudo docker –version# 查看版本具體信息$ sudo docker version# Docker鏡像源設置# 修改文件 /etc/docker/daemon.json,沒有這個文件就創(chuàng)建# 添加以下內容后,重啟docker服務:{ “registry-mirrors”: [“http://hub-mirror.c.163.com”]}$ sudo systemctl restart docker
三、安裝 kubeadm、kubelet 和 kubectl
你需要在所有機器上安裝以下的軟件包:
- kubeadm:用來初始化集群的指令。
- kubelet:在集群中的每個節(jié)點上用來啟動 Pod 和容器等。
- kubectl:用來與集群通信的命令行工具。
kubeadm 不能 幫你安裝或者管理 kubelet 或 kubectl,所以你需要 確保它們與通過 kubeadm 安裝的控制平面的版本相匹配。 如果不這樣做,則存在發(fā)生版本偏差的風險,可能會導致一些預料之外的錯誤和問題。
1)配置hosts
$ echo “192.168.0.113 k8s-master” >> /etc/hosts$ echo “192.168.0.114 k8s-node1” >> /etc/hosts$ echo “192.168.0.115 k8s-node2” >> /etc/hosts# 查看$ cat /etc/hosts
2)關閉防火墻
$ systemctl stop firewalld$ systemctl disable firewalld
3)關閉swap
kubelet 在 1.8 版本以后強制要求 swap 必須關閉。要不然kubelet 無法正常啟動
# 臨時關閉;關閉swap主要是為了性能考慮$ swapoff -a# 可以通過這個命令查看swap是否關閉了$ free# 永久關閉 $ sed -ri ‘s/.*swap.*/#&/’ /etc/fstab
4)將 SELinux 設置為 disabled模式(相當于將其禁用)
# 臨時關閉$ sudo setenforce 0 # 永久禁用$ sudo sed -i ‘s/^SELINUX=enforcing$/SELINUX=disabled/’ /etc/selinux/config
5)配置yum源,這里配置阿里云的源
$ cat > /etc/yum.repos.d/kubernetes.repo << EOF[k8s]name=k8senabled=1gpgcheck=0baseurl=https://mirrors.aliyun.com/kubernetes/yum/repos/kubernetes-el7-x86_64/EOF
6)開始安裝kubeadm,kubelet和kubectl
$ sudo yum install -y kubelet kubeadm kubectl –disableexcludes=kubernetes# disableexcludes=kubernetes:禁掉除了這個kubernetes之外的別的倉庫# 設置為開機自啟并現(xiàn)在立刻啟動服務 –now:立刻啟動服務$ sudo systemctl enable –now kubelet# 查看狀態(tài)$ systemctl status kubelet
查看狀態(tài)會發(fā)現(xiàn)
重新安裝(或第一次安裝)k8s,未經(jīng)過kubeadm init 或者 kubeadm join后,kubelet會不斷重啟,這個是正?,F(xiàn)象……,執(zhí)行init或join后問題會自動解決,對此官網(wǎng)有如下描述,也就是此時不用理會kubelet.service。
先查看k8s版本
$ kubectl version$ yum info kubeadm
7)使用 kubeadm 創(chuàng)建集群(master節(jié)點)
初始化,–kubernetes-version版本就是上面查詢出來的,可以不寫,默認會自動獲取版本,–image-repository:默認是官網(wǎng)k8s.gcr.io,但是很慢,這里換成了阿里云的;–apiserver-advertise-address=192.168.0.113:這里的ip為master節(jié)點ip,記得更換。
$ kubeadm init –apiserver-advertise-address=192.168.0.113 –image-repository registry.aliyuncs.com/google_containers –kubernetes-version v1.22.1 –service-cidr=10.1.0.0/16 –pod-network-cidr=10.244.0.0/16# –image-repository string: 這個用于指定從什么位置來拉取鏡像(1.13版本才有的),默認值是k8s.gcr.io,我們將其指定為國內鏡像地址:registry.aliyuncs.com/google_containers# –kubernetes-version string: 指定kubenets版本號,默認值是stable-1,會導致從https://dl.k8s.io/release/stable-1.txt下載最新的版本號,我們可以將其指定為固定版本(v1.22.1)來跳過網(wǎng)絡請求。# –apiserver-advertise-address 指明用 Master 的哪個 interface 與 Cluster 的其他節(jié)點通信。如果 Master 有多個 interface,建議明確指定,如果不指定,kubeadm 會自動選擇有默認網(wǎng)關的 interface。# –pod-network-cidr 指定 Pod 網(wǎng)絡的范圍。Kubernetes 支持多種網(wǎng)絡方案,而且不同網(wǎng)絡方案對 –pod-network-cidr有自己的要求,這里設置為10.244.0.0/16 是因為我們將使用 flannel 網(wǎng)絡方案,必須設置成這個 CIDR。
但是會報如下錯誤:registry.aliyuncs.com/google_containers/coredns:v1.8.4 not found
【解決】由于安裝的是Kubernetes v1.22.1版本,在初始化的時候報錯信息中提示需要registry.aliyuncs.com/google_containers/coredns:v1.8.4版本的coredns鏡像,手動拉取registry.aliyuncs.com/google_containers/coredns:v1.8.4版本的鏡像時發(fā)現(xiàn)沒有,所以就只能拉取一個默認版本的阿里云coredns鏡像,拉取下來之后自己再手動修改一下鏡像的tag信息為v1.8.4版本。
# 手動拉取默認版本的coredns鏡像$ docker pull registry.aliyuncs.com/google_containers/coredns
查看拉取下來的coredns鏡像
$ docker images
將拉取的默認版本的coredns鏡像tag信息修改為v1.8.4版本
$ docker tag registry.aliyuncs.com/google_containers/coredns:latest registry.aliyuncs.com/google_containers/coredns:v1.8.4 $ docker images
再執(zhí)行上面初始化命令
$ kubeadm init –apiserver-advertise-address=192.168.0.113 –image-repository registry.aliyuncs.com/google_containers –kubernetes-version v1.22.1 –service-cidr=10.1.0.0/16 –pod-network-cidr=10.244.0.0/16
報錯如下:
$ tail /var/log/messages
上述日志表明:kubelet的cgroup driver是cgroupfs,docker的 cgroup driver是systemd,兩者cgroup driver不一致導致kubelet啟動失敗。
【解決】
重啟kubelet
$ systemctl daemon-reload$ systemctl restart kubelet
這里不真正用這個方式,而是修改docker的cgroup driver2. 修改docker的cgroup driver(修改docker的,也就是這個方式),修改或創(chuàng)建/etc/docker/daemon.json,加入下述內容:
{ “exec-opts”: [“native.cgroupdriver=systemd”]}
重啟docker
$ cat /etc/docker/daemon.json$ systemctl daemon-reload$ systemctl restart docker# 查看docker的cgroup driver$ docker info | grep Cgroup
先重置
# 重置$ kubeadm reset# 重啟$ systemctl restart kubelet
重新初始化
$ kubeadm init –apiserver-advertise-address=192.168.0.113 –image-repository registry.aliyuncs.com/google_containers –kubernetes-version v1.22.1 –service-cidr=10.1.0.0/16 –pod-network-cidr=10.244.0.0/16
根據(jù)上圖提示,要使非 root 用戶可以運行 kubectl,請運行以下命令, 它們也是 kubeadm init 輸出的一部分:
$ mkdir -p $HOME/.kube$ sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config$ sudo chown $(id -u):$(id -g) $HOME/.kube/config
或者,如果你是 root 用戶,則可以運行,這里我使用root用戶,但是生產(chǎn)環(huán)境一般不會用root用戶的:
# 臨時生效(退出當前窗口重連環(huán)境變量失效)$ export KUBECONFIG=/etc/kubernetes/admin.conf# 永久生效(推薦)$ echo “export KUBECONFIG=/etc/kubernetes/admin.conf” >> ~/.bash_profile$ source ~/.bash_profile
如果不加入環(huán)境變量,會出現(xiàn)如下報錯:
8)安裝Pod網(wǎng)絡插件(CNI:Container Network Interface)(master)
你必須部署一個基于 Pod 網(wǎng)絡插件的 容器網(wǎng)絡接口 (CNI),以便你的 Pod 可以相互通信。
$ kubectl apply -f https://raw.githubusercontent.com/coreos/flannel/master/Documentation/kube-flannel.yml
如果上面安裝失敗,則下載我百度里的,離線安裝
鏈接:https://pan.baidu.com/s/1HB9xuO3bssAW7v5HzpXkeQ提取碼:8888
$ kubectl apply -f kube-flannel.yml$ docker images
查看集群信息
$ kubectl get nodes
9)Node節(jié)點加入集群
如果沒有令牌,可以通過在控制平面節(jié)點上運行以下命令來獲取令牌:
$ kubeadm token list
默認情況下,令牌會在24小時后過期。如果要在當前令牌過期后將節(jié)點加入集群, 則可以通過在控制平面節(jié)點上運行以下命令來創(chuàng)建新令牌:
$ kubeadm token create# 再查看$ kubeadm token list
如果你沒有 –discovery-token-ca-cert-hash 的值,則可以通過在控制平面節(jié)點上執(zhí)行以下命令鏈來獲取它:
$ openssl x509 -pubkey -in /etc/kubernetes/pki/ca.crt | openssl rsa -pubin -outform der 2>/dev/null | openssl dgst -sha256 -hex | sed ‘s/^.* //’
如果執(zhí)行kubeadm init時沒有記錄下加入集群的命令,可以通過以下命令重新創(chuàng)建(推薦)一般不用上面的分別獲取token和ca-cert-hash方式,執(zhí)行以下命令一氣呵成:
$ kubeadm token create –print-join-command
以下命令在node節(jié)點執(zhí)行**
# 查看集群信息$ kubectl get nodes
【問題】這里可能會報錯 localhost:10248拒絕訪問,這個無解,重裝系統(tǒng)解決
【解決】重置節(jié)點信息
$ kubeadm reset
需要將master節(jié)點的 /etc/kubernetes/admin.conf復制到node節(jié)點的相同位置
$ scp /etc/kubernetes/admin.conf 192.168.0.114:/etc/kubernetes/$ scp /etc/kubernetes/admin.conf 192.168.0.115:/etc/kubernetes/
執(zhí)行下面的代碼加入環(huán)境變量
$ echo “export KUBECONFIG=/etc/kubernetes/admin.conf” >> ~/.bash_profile$ source ~/.bash_profile
修改docker的cgroup driver,修改或創(chuàng)建/etc/docker/daemon.json,加入下述內容:
{ “exec-opts”: [“native.cgroupdriver=systemd”]}
重新加載
$ systemctl daemon-reload$ systemctl restart docker$ docker info | grep Cgroup$ kubectl get nodes
安裝flannel網(wǎng)絡插件,采用離線安裝,kube-flanel.yml文件上面有
$ kubectl apply -f kube-flannel.yml
將node節(jié)點加入到集群中
$ kubeadm token create –print-join-command# –v=5:顯示詳細信息$ kubeadm join 192.168.0.113:6443 –token cgmxso.bfgou00m72tnbpz4 –discovery-token-ca-cert-hash sha256:b4792b0f3b54c8b8b71a4a484129b4e2acfe5014c37b1b18dbebbc0c8f69fc15 –v=5
另一個node節(jié)點同上操作
【問題】STATUS一直為NotReady首先使用如下命令來看一下kube-system的 pod 狀態(tài):
$ kubectl get pod -n kube-system$ kubectl get pod -n kube-system -o wide
如上,可以看到 pod kube-flannel 的狀態(tài)是ImagePullBackoff,意思是鏡像拉取失敗了,所以我們需要手動去拉取這個鏡像。這里可以看到某些 pod 運行了兩個副本是因為我有兩個節(jié)點存在了。
也可以通過kubectl describe pod -n kube-system 來查看某個服務的詳細情況,如果 pod 存在問題的話,你在使用該命令后在輸出內容的最下面看到一個[Event]條目,如下:
$ kubectl describe pod kube-flannel-ds-4j2mp -n kube-system
【解決】手動拉取鏡像
$ docker pull quay.io/coreos/flannel:v0.14.0
修改完了之后過幾分鐘 k8s 會自動重試,等一下就可以發(fā)現(xiàn)不僅flannel正常了,其他的 pod 狀態(tài)也都變成了Running,這時再看 node 狀態(tài)就可以發(fā)現(xiàn)問題解決了:
四、清理
如果你在集群中使用了一次性服務器進行測試,則可以關閉這些服務器,而無需進一步清理。你可以使用 kubectl config delete-cluster 刪除對集群的本地引用。
1)先將節(jié)點設置為維護模式(k8s-node1是節(jié)點名稱)
$ kubectl drain k8s-node1 –delete-local-data –force –ignore-daemonsets
2)在刪除節(jié)點之前,請重置 kubeadm 安裝的狀態(tài):
$ kubeadm reset
3)重置過程不會重置或清除 iptables 規(guī)則或 IPVS 表。如果你希望重置 iptables,則必須手動進行:
$ iptables -F && iptables -t nat -F && iptables -t mangle -F && iptables -X
4)如果要重置 IPVS 表,則必須運行以下命令:
$ ipvsadm -C
5)現(xiàn)在刪除節(jié)點:
$ kubectl delete node k8s-node1
五、搭建K8S Dashboard
1)下載dashboard文件:
$ curl -o kubernetes-dashboard.yaml https://raw.githubusercontent.com/kubernetes/dashboard/master/aio/deploy/recommended/kubernetes-dashboard.yaml
如果地址不可用可以使用下面的地址下載
鏈接:https://pan.baidu.com/s/1-tEablkFTrMC-N9-8T7rrA提取碼:8888
安裝
$ kubectl apply -f kubernetes-dashboard.yaml
驗證,查看服務被分配到哪個節(jié)點上:$ kubectl get pods -n kube-system -o wide
$ kubectl get pods -n kube-system -o wide
從上圖可知,服務被分配到了k8s-node1,對外端口為nodePort:31080,配置文件里的。谷歌瀏覽器訪問不了,原因是部署UI的鏡像中默認自帶的證書是一個不可信任的證書,則先用火狐訪問:https://nodeIp:nodePort
https://192.168.0.114:31080
獲取token測試
$ kubectl get secret -n kube-system|grep kubernetes-dashboard-token# 根據(jù)自己情況輸入命令$ kubectl describe secret kubernetes-dashboard-token-m7b7b -n kube-system
解決谷歌瀏覽器不能訪問的問題,通過生成新的證書永久解決
# 創(chuàng)建一個用于自簽證書的目錄$ mkdir kubernetes-dashboard-key && cd kubernetes-dashboard-key # 生成證書請求的key$ openssl genrsa -out dashboard.key 2048 # 192.168.0.113為master節(jié)點的IP地址$ openssl req -new -out dashboard.csr -key dashboard.key -subj ‘/CN=192.168.0.113’ # 生成自簽證書$ openssl x509 -req -in dashboard.csr -signkey dashboard.key -out dashboard.crt# 刪除原有證書$ kubectl delete secret kubernetes-dashboard-certs -n kube-system# 創(chuàng)建新證書的secret$ kubectl create secret generic kubernetes-dashboard-certs –from-file=dashboard.key –from-file=dashboard.crt -n kube-system# 查找正在運行的pod$ kubectl get pod -n kube-system# 刪除pod,讓k8s自動拉起一個新的pod,相對于重啟kubectl delete pod kubernetes-dashboard-7d6c598b5f-fvcg8 -n kube-system
服務調度到k8s-node2節(jié)點上了,訪問
https://192.168.0.115:31080
現(xiàn)在Google瀏覽器也可以訪問了再獲取token登錄
$ kubectl get secret -n kube-system|grep kubernetes-dashboard-token# 根據(jù)自己情況輸入命令$ kubectl describe secret kubernetes-dashboard-token-m7b7b -n kube-system
以上就是完整版K8s和K8s Dashboard的安裝過程了~