《從 0 到 1:搭建一個完整的 Kubernetes 叢集》實踐踩坑

GetaChan發表於2019-12-13

從0到1:搭建一個完整的Kubernetes叢集 實踐踩坑,涉及一些版本問題。

實驗環境

教程提供配置

2 核 CPU、 7.5 GB 記憶體;
30 GB 磁碟;
Ubuntu 16.04;
內網互通;
外網訪問許可權不受限制。

實際採用配置

windows下的vm虛擬機器:

2 核 CPU、 1 GB 記憶體;(至少是2核,如果不是,初始化時會檢查並報錯)
30 GB 磁碟;
Ubuntu 16.04;
內網互通;
外網訪問許可權不受限制。

安裝 kubeadm 和 Docker

教程提供配置

$ curl -s https://packages.cloud.google.com/apt/doc/apt-key.gpg | apt-key add -
$ cat <<EOF > /etc/apt/sources.list.d/kubernetes.list
deb http://apt.kubernetes.io/ kubernetes-xenial main
EOF
$ apt-get update
$ apt-get install -y docker.io kubeadm

實際解決

國內,用阿里雲源安裝就可以了,速度很快:

  1. apt-get update && apt-get install -y apt-transport-https
  2. curl https://mirrors.aliyun.com/kubernetes/apt/... | apt-key add -
  3. 將deb https://mirrors.aliyun.com/kubernetes/apt/ kubernetes-xenial main 加入到下面檔案中,沒有就建立 /etc/apt/sources.list.d/kubernetes.list
  4. apt-get update
  5. apt-get install -y docker.io kubeadm

部署 Kubernetes 的 Master 節點

教程提供配置

apiVersion: kubeadm.k8s.io/v1alpha1
kind: MasterConfiguration
controllerManagerExtraArgs:
  horizontal-pod-autoscaler-use-rest-clients: "true"
  horizontal-pod-autoscaler-sync-period: "10s"
  node-monitor-grace-period: "10s"
apiServerExtraArgs:
  runtime-config: "api/all=true"
kubernetesVersion: "stable-1.11"

2018.09後,出現版本問題的解決辦法

kubeadm最新版本已經為1.12,看到上面很多人遇到提示版本不對,重新安裝低版本就好了
apt remove kubelet kubectl kubeadm

apt install kubelet=1.11.3-00

apt install kubectl=1.11.3-00

apt install kubeadm=1.11.3-00

如果提示kubernetes-cni版本有問題:

apt-get install kubeadm=1.11.3-00 kubelet=1.11.3-00 kubectl=1.11.3-00 kubernetes-cni=0.6.0-00

目前(2019.12)已經是 v1.17.0,嘗試重新安裝版本:

apt remove kubelet kubectl kubeadm

apt-get install kubeadm kubelet kubectl

配置檔案也更新為:

apiVersion: kubeadm.k8s.io/v1beta2
kind: ClusterConfiguration
controllerManager:
        ExtraArgs:
                 horizontal-pod-autoscaler-use-rest-clients: "true"
                 horizontal-pod-autoscaler-sync-period: "10s"
                 node-monitor-grace-period: "10s"
apiServer:
        ExtraArgs:
                runtime-config: "api/all=true"
kubernetesVersion: "v.17.0"

實際解決

由於初始化總提示沒辦法下載 k8s.gcr.io 的映象,網上很多都是採取先下載google映象後tag的方法,測試發現google映象裡面暫時還沒有v1.17的資源,只有v1.15之前的,為避免環境問題,最終還是回到v1.11,按課程走。

apt remove kubelet kubectl kubeadm

apt-get install kubeadm=1.11.1-00 kubelet=1.11.1-00 kubectl=1.11.1-00 kubernetes-cni=0.6.0-00

下載google映象

docker pull mirrorgooglecontainers/kube-apiserver-amd64:v1.11.1

docker pull mirrorgooglecontainers/kube-controller-manager-amd64:v1.11.1

docker pull mirrorgooglecontainers/kube-scheduler-amd64:v1.11.1

docker pull mirrorgooglecontainers/kube-proxy-amd64:v1.11.1

docker pull mirrorgooglecontainers/pause:3.1

docker pull mirrorgooglecontainers/etcd-amd64:3.2.18

docker pull coredns/coredns:1.1.3

tag

docker tag docker.io/mirrorgooglecontainers/kube-apiserver-amd64:v1.11.1 k8s.gcr.io/kube-apiserver-amd64:v1.11.1

docker tag docker.io/mirrorgooglecontainers/kube-controller-manager-amd64:v1.11.1 k8s.gcr.io/kube-controller-manager-amd64:v1.11.1

docker tag docker.io/mirrorgooglecontainers/kube-scheduler-amd64:v1.11.1 k8s.gcr.io/kube-scheduler-amd64:v1.11.1

docker tag docker.io/mirrorgooglecontainers/kube-proxy-amd64:v1.11.1 k8s.gcr.io/kube-proxy-amd64:v1.11.1

docker tag docker.io/mirrorgooglecontainers/pause:3.1 k8s.gcr.io/pause:3.1

docker tag docker.io/mirrorgooglecontainers/etcd-amd64:3.2.18 k8s.gcr.io/etcd-amd64:3.2.18

docker tag docker.io/coredns/coredns:1.1.3 k8s.gcr.io/coredns:1.1.3

swapoff -a

kubeadm init --config kubeadm.yaml --ignore-preflight-errors=SystemVerification

# 初始化成功!顯示以下資訊
...

Your Kubernetes master has initialized successfully!

To start using your cluster, you need to run the following as a regular user:

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

You should now deploy a pod network to the cluster.
Run "kubectl apply -f [podnetwork].yaml" with one of the options listed at:
  https://kubernetes.io/docs/concepts/cluster-administration/addons/

You can now join any number of machines by running the following on each node
as root:

  kubeadm join 192.168.139.136:6443 --token 7ypgpe.qzgh5fs0rga7n9bf --discovery-token-ca-cert-hash sha256:bb0bc404012e9b61e905da6cc2f3028f2625c823                                            2e3d616478b98ba3124558f5

kubeadm 會提示我們第一次使用 Kubernetes 叢集所需要的配置命令:

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

而需要這些配置命令的原因是:Kubernetes 叢集預設需要加密方式訪問。所以,這幾條命令,就是將剛剛部署生成的 Kubernetes 叢集的安全配置檔案,儲存到當前使用者的.kube 目錄下,kubectl 預設會使用這個目錄下的授權資訊訪問 Kubernetes 叢集。

如果不這麼做的話,我們每次都需要通過 export KUBECONFIG 環境變數告訴 kubectl 這個安全配置檔案的位置。

常用管理命令

檢視當前節的狀態

kubectl get nodes

NAME      STATUS     ROLES     AGE       VERSION
ubuntu    NotReady   master    27m       v1.11.1

在除錯 Kubernetes 叢集時,最重要的手段就是用 kubectl describe 來檢視這個節點(Node)物件的詳細資訊、狀態和事件(Event),我們來試一下:

kubectl describe node ubuntu

另外,我們還可以通過 kubectl 檢查這個節點上各個系統 Pod 的狀態,其中,kube-system 是 Kubernetes 專案預留的系統 Pod 的工作空間(Namepsace,注意它並不是 Linux Namespace,它只是 Kubernetes 劃分不同工作空間的單位):

kubectl get pods -n kube-system

部署網路外掛

以 Weave 為例:

kubectl apply -f https://git.io/weave-kube-1.6

部署完成後,我們可以通過 kubectl get 重新檢查 Pod 的狀態:

NAME                             READY     STATUS    RESTARTS   AGE
coredns-78fcdf6894-2lc2v         1/1       Running   0          1h
coredns-78fcdf6894-rjj9r         1/1       Running   0          1h
etcd-ubuntu                      1/1       Running   0          1h
kube-apiserver-ubuntu            1/1       Running   0          1h
kube-controller-manager-ubuntu   1/1       Running   0          1h
kube-proxy-z9fqz                 1/1       Running   0          1h
kube-scheduler-ubuntu            1/1       Running   0          1h
weave-net-p4fh2                  2/2       Running   0          51m

至此,Kubernetes 的 Master 節點就部署完成了。如果你只需要一個單節點的 Kubernetes,現在你就可以使用了。不過,在預設情況下,Kubernetes 的 Master 節點是不能執行使用者 Pod 的,所以還需要額外做一個小操作。

部署 Kubernetes 的 Worker 節點

Kubernetes 的 Worker 節點跟 Master 節點幾乎是相同的,它們執行著的都是一個 kubelet 元件。唯一的區別在於,在 kubeadm init 的過程中,kubelet 啟動後,Master 節點上還會自動執行 kube-apiserver、kube-scheduler、kube-controller-manger 這三個系統 Pod。

所以,相比之下,部署 Worker 節點反而是最簡單的,只需要兩步即可完成。

第一步,在所有 Worker 節點上執行“安裝 kubeadm 和 Docker”一節的所有步驟。

第二步,執行部署 Master 節點時生成的 kubeadm join 指令:

kubeadm join 192.168.139.136:6443 --token 7ypgpe.qzgh5fs0rga7n9bf --discovery-token-ca-cert-hash sha256:bb0bc404012e9b61e905da6cc2f3028f2625c823                                            2e3d616478b98ba3124558f5

通過 Taint/Toleration 調整 Master 執行 Pod 的策略

預設情況下 Master 節點是不允許執行使用者 Pod 的。而 Kubernetes 做到這一點,依靠的是 Kubernetes 的 Taint/Toleration 機制。

這部分屬於策略配置問題,自行搜尋解決。

部署 Dashboard 視覺化外掛

在 Kubernetes 社群中,有一個很受歡迎的 Dashboard 專案,它可以給使用者提供一個視覺化的 Web 介面來檢視當前叢集的各種資訊。毫不意外,它的部署也相當簡單:

教程給的地址已失效,以下可用
kubectl apply -f https://raw.githubusercontent.com/kubernetes/dashboard/v1.10.0/src/deploy/recommended/kubernetes-dashboard.yaml

或者將配置複製到本地檔案
kubectl apply -f dashboard.yaml

由於本次實驗是vm裡面的虛擬機器,windows主機無法訪問dashboard,教程提到:如果想從叢集外訪問這個 Dashboard 的話,需要用到 Ingress。

部署容器儲存外掛

Kubernetes 叢集的最後一塊拼圖:容器持久化儲存。

很多時候我們需要用資料卷(Volume)把外面宿主機上的目錄或者檔案掛載進容器的 Mount Namespace 中,從而達到容器和宿主機共享這些目錄或者檔案的目的。容器裡的應用,也就可以在這些資料卷中新建和寫入檔案。

由於 Kubernetes 本身的鬆耦合設計,絕大多數儲存專案,比如 Ceph、GlusterFS、NFS 等,都可以為 Kubernetes 提供持久化儲存能力。在這次的部署實戰中,教程選擇部署一個很重要的 Kubernetes 儲存外掛專案:Rook。

Rook 專案是一個基於 Ceph 的 Kubernetes 儲存外掛(它後期也在加入對更多儲存實現的支援)。不過,不同於對 Ceph 的簡單封裝,Rook 在自己的實現中加入了水平擴充套件、遷移、災難備份、監控等大量的企業級功能,使得這個專案變成了一個完整的、生產級別可用的容器儲存外掛。

得益於容器化技術,用兩條指令,Rook 就可以把複雜的 Ceph 儲存後端部署起來:

kubectl apply -f https://raw.githubusercontent.com/rook/rook/master/cluster/examples/kubernetes/ceph/operator.yaml

kubectl apply -f https://raw.githubusercontent.com/rook/rook/master/cluster/examples/kubernetes/ceph/cluster.yaml

這樣,一個基於 Rook 持久化儲存叢集就以容器的方式執行起來了,而接下來在 Kubernetes 專案上建立的所有 Pod 就能夠通過 Persistent Volume(PV)和 Persistent Volume Claim(PVC)的方式,在容器裡掛載由 Ceph 提供的資料捲了。

而 Rook 專案,則會負責這些資料卷的生命週期管理、災難備份等運維工作。

可能遇到的問題

master當機重啟後引起的coredns Error:

kubectl -n kube-system get deployment coredns -o yaml | \
  sed 's/allowPrivilegeEscalation: false/allowPrivilegeEscalation: true/g' | \
  kubectl apply -f -

嘗試將work節點加入master的過程:

token可能過期
## master上執行
kubeadm token list 檢視所有token
kubeadm token create 重新生成
kubeadm token create --print-join-command  重新生成並列印join的命令

worker埠可能被佔用
netstat -ltnp
kill -9 XXX

worker 操作過join並且已有配置檔案產生
kubeadm reset 或者 刪除相應提示的配置
kubeadm join 192.168.139.136:6443 --token adwc73.dhfggnt6f3xlqbyl --discovery-token-ca-cert-hash sha256:bb0bc404012e9b61e905da6cc2f3028f2625c8232e3d616478b98ba3124558f5 --ignore-preflight-errors=SystemVerification

實驗結論

實際上,整個k8s叢集,只成功部署了master(包括網路外掛、視覺化外掛、儲存外掛),在worker join的過程,也提示docker版本的問題,忽略之後,有提示該節點已加入叢集,如下:
kubeadm實踐踩坑
但master上始終沒看到worker的資訊。檢視master的日誌,如下:
kubeadm實踐踩坑
從上面資訊來看,個人認為是版本問題,畢竟v1.11.1是一年前的版本。

我盡力了,雖然暫時沒有成功,或者等我學習更多k8s的知識,我能解決目前的問題。

如果有基於ubuntu16.04、k8s v1.11.1搭建成功的小夥伴,也可以給我留言。

其實網上有很多基於centos搭建成功的,可以參考。

本作品採用《CC 協議》,轉載必須註明作者和本文連結

相關文章