Kubernetes — 從0到1:搭建一個完整的Kubernetes集羣

 準備工做

 首先,準備機器。最直接的辦法,天然是到公有云上申請幾個虛擬機。固然,若是條件容許的話,拿幾臺本地的物理服務器來組集羣是最好不過了。這些機器只要知足以下幾個條件便可:html

  • 知足安裝 Docker 項目所需的要求,好比 64 位的 Linux 操做系統、3.10 及以上的內核版本;
  • x86+或者+ARM+架構都可;
  • 機器之間網絡互通,這是未來容器之間網絡互通的前提;
  • 有外網訪問權限(***),由於須要拉取鏡像;
  • 可以訪問到gcr.io、quay.io這兩個 docker registry,由於有小部分鏡像須要在這裏拉取;
  • 單機可用資源建議 2 核 CPU、8 GB 內存或以上,再小的話問題也不大,可是能調度的 Pod 數量就比較有限了;
  • 30 GB 或以上的可用磁盤空間,這主要是留給 Docker 鏡像和日誌文件用的

 安裝 kubeadm 和 Docker node

《Kubernetes 一鍵部署利器:kubeadm》它的一鍵安裝很是方便,咱們只須要添加 kubeadm 的源,而後直接使用 apt-get 安裝便可,具體流程以下所示:linux

curl -s https://packages.cloud.google.com/apt/doc/apt-key.gpg | apt-key add -

把官方源列表加入到k8s節點本地源列表配置目錄中git

vi  /etc/apt/sources.list.d/kubernetes.list

輸入如下內容github

deb http://apt.kubernetes.io/ kubernetes-xenial main

更新包索引 docker

apt-get update

安裝docker 這裏我用的是docker 17.03.3-ce版本ubuntu

添加Docker的官方GPG密鑰:後端

curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo apt-key add -

添加官方源倉庫  centos

sudo add-apt-repository "deb [arch=amd64] https://download.docker.com/linux/ubuntu  $(lsb_release -cs) stable"

更新包索引api

apt-get update

安裝17.03版本

apt-get install docker-ce=17.03.3~ce-0~ubuntu-xenial

安裝 kubelet kubctl kubeadm

apt install kubelet=1.11.1-00
apt install kubectl=1.11.1-00
apt install kubeadm=1.11.1-00

  

部署 Kubernetes 的 Master 節點

kubeadm 能夠一鍵部署 Master 節點。不過,在本篇文章中既然要部署一個「完整」的 Kubernetes 集羣,那咱們不妨稍微提升一下難度:經過配置文件來開啓一些實驗性功能。

因此,這裏我編寫了一個給 kubeadm 用的 YAML 文件(名叫:kubeadm.yaml):

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: "v1.11.1"

 

 這個配置中,我給+kube-controller-manager+設置了

horizontal-pod-autoscaler-use-rest-clients: "true"

  

 這意味着,未來部署的 kube-controller-manager 可以使用自定義資源(Custom Metrics)進行自動水平擴展。

其中,「stable-1.11」就是 kubeadm 幫咱們部署的 Kubernetes 版本號,即:Kubernetes release 1.11 最新的穩定版,在個人環境下,它是 v1.11.1。你也能夠直接指定這個版本,好比:kubernetesVersion:「v1.11.1」。而後,咱們只須要執行一句指令:

kubeadm init --config kubeadm.yaml

  

就能夠完成 Kubernetes+Master 的部署了,這個過程只須要幾分鐘。部署完成後,kubeadm 會生成一行指令

kubeadm join 209.250.244.253:6443 --token 4srvlc.6ug9t7ikb3ao0m06 --discovery-token-ca-cert-hash sha256:b71d09fee04a19c53787b44bd18df39b50256de6beeee90f3acc2665948d18b8

 這個 kubeadm join 命令,就是用來給這個 Master 節點添加更多工做節點(Worker)的命令。咱們在後面部署 Worker 節點的時候立刻會用到它,因此找一個地方把這條命令記錄下來。此外,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 命令來查看當前惟一一個節點的狀態了:

kubectl get nodes

能夠看到,這個 get 指令輸出的結果裏,Master 節點的狀態是 NotReady,這是爲何呢?

在調試 Kubernetes 集羣時,最重要的手段就是用 kubectl describe 來查看這個節點(Node)對象的詳細信息、狀態和事件(Event),咱們來試一下:

kubectl describe node master

經過 kubectl describe 指令的輸出,咱們能夠看到 NodeNotReady 的緣由在於,咱們還沒有部署任何網絡插件。

另外,咱們還能夠經過+kubectl+檢查這個節點上各個系統 Pod 的狀態,其中,kube-system 是 Kubernetes 項目預留的系統 Pod 的工做空間(Namepsace,注意它並非 Linux Namespace,它只是 Kubernetes 劃分不一樣工做空間的單位):

kubectl get pods -n kube-system

能夠看到,CoreDNS 等依賴於網絡的 Pod 都處於 Pending 狀態,即調度失敗。這固然是符合預期的:由於這個 Master 節點的網絡還沒有就緒

部署網絡插件

在 Kubernetes 項目「一切皆容器」的設計理念指導下,部署網絡插件很是簡單,只須要執行一句 kubectl apply 指令,  

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

部署完成後,咱們能夠經過 kubectl get 從新檢查 Pod 的狀態:  

能夠看到,全部的系統 Pod 都成功啓動了,而剛剛部署的 Weave 網絡插件則在 kube-system 下面新建了一個名叫 weave-net-cmk27 的+Pod,通常來講,這些 Pod 就是容器網絡插件在每一個節點上的控制組件。 Kubernetes 支持容器網絡插件,使用的是一個名叫 CNI 的通用接口,它也是當前容器網絡的事實標準,市面上的全部容器網絡開源項目均可以經過 CNI 接入 Kubernetes,好比 Flannel、Calico、Canal、Romana 等等,它們的部署方式也都是相似的「一鍵部署」。

至此,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 209.250.244.253:6443 --token 4srvlc.6ug9t7ikb3ao0m06 --discovery-token-ca-cert-hash sha256:b71d09fee04a19c53787b44bd18df39b50256de6beeee90f3acc2665948d18b8

在這裏我想master中加入了2個Worker節點

 

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

默認狀況下 Master 節點是不容許運行用戶 Pod 的。而 Kubernetes 作到這一點,依靠的是 Kubernetes 的 Taint/Toleration 機制。它的原理很是簡單:一旦某個節點被加上了一個 Taint,即被「打上了污點」,那麼全部 Pod 就都不能在這個節點上運行,由於 Kubernetes 的 Pod 都有「潔癖」。

除非,有個別的 Pod 聲明本身能「容忍」這個「污點」,即聲明瞭 Toleration,它才能夠在這個節點上運行。

其中,爲節點打上「污點」(Taint)的命令是(master節點默認就有Taint,因此master上默認不能運行用戶的pod

kubectl taint nodes node1 foo=bar:NoSchedule

這時,該 node1 節點上就會增長一個鍵值對格式的 Taint,即:foo=ANoSchedule。其中值裏面的 NoSchedule,意味着這個 Taint 只會在調度新 Pod 時產生做用,而不會影響已經在 node1 上運行的 Pod,哪怕它們沒有 Toleration。 那麼 Pod 又如何聲明 Toleration 呢?

咱們只要在 Pod 的.yaml 文件中的 spec 部分,加入 tolerations 字段便可:

apiVersion: v1
kind: Pod
...
spec:
  tolerations:
  - key: "foo"
    operator: "Equal"
    value: "bar"
    effect: "NoSchedule"

這個 Toleration 的含義是,這個 Pod 能「容忍」全部鍵值對爲 foo=bar 的 Taint( operator:「Equal」,「等於」操做)。

如今回到咱們已經搭建的集羣上來。這時,若是你經過 kubectl describe 檢查一下master 節點的 Taint 字段,就會有所發現了:

kubectl describe node master

能夠看到,master  節點默認被加上了node-role.kubernetes.io/ANoSchedule這樣一個「污點」,其中「鍵」是node-role.kubernetes.io/Fmaster,而沒有提供「值」。

此時,你就須要像下面這樣用「Exists」操做符(operator:「Exists」,「存在」便可)來講明,該 Pod 可以容忍全部以 foo 爲鍵的 Taint,才能讓這個 Pod 運行在該  Master 節點上:

apiVersion: v1
kind: Pod
...
spec:
  tolerations:
  - key: "foo"
    operator: "Exists"
    effect: "NoSchedule"

  

固然,若是你就是想要一個單節點的 Kubernetes,刪除這個  Taint 纔是正確的選擇:  

kubectl taint nodes --all node-role.kubernetes.io/master-

  

如上所示,咱們在「node-role.kubernetes.io/master」這個鍵後面加上了一個短橫線「-」,這個格式就意味着移除全部以「node-role.kubernetes.io/master」爲鍵的 Taint。

到了這一步,一個基本完整的 Kubernetes 集羣就部署完畢了。是否是很簡單呢?

有了 kubeadm 這樣的原生管理工具,Kubernetes 的部署已經被大大簡化。更重要的是,像證書、受權、各個組件的配置等部署中最麻煩的操做,kubeadm 都已經幫你完成了。

接下來,咱們再在這個 Kubernetes 集羣上安裝一些其餘的輔助插件,好比 Dashboard 和存儲插件。

部署 Dashboard 可視化插件

在 Kubernetes 社區中,有一個很受歡迎的 Dashboard 項目,它能夠給用戶提供一個可視化的 Web 界面來查看當前集羣的各類信息。絕不意外,它的部署也至關簡單:

wget https://raw.githubusercontent.com/kubernetes/dashboard/v1.10.0/src/deploy/recommended/kubernetes-dashboard.yaml

爲了便於本地訪問,修改yaml文件,將service改成NodePort 類型:  

部署

kubectl apply -f kubernetes-dashboard.yaml

部署完成以後,咱們就能夠查看 Dashboard 對應的 Pod 的狀態了:

kubectl get pods -n kube-system

須要注意的是,因爲 Dashboard 是一個 Web Server,不少人常常會在本身的公有云上無心地暴露  Dashboard 的端口,從而形成安全隱患。因此,1.7 版本以後的 Dashboard 項目部署完成後,默認只能經過 Proxy 的方式在本地訪問。具體的操做,你能夠查看 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

 

查詢全部pods 的namespace

kubectl get pods --all-namespaces

查看 pod rook-ceph-operator-5496d44d7c-nw5hz 詳細信息

kubectl describe pod  rook-ceph-operator-5496d44d7c-nw5hz -n rook-ceph-system

在部署完成後,你就能夠看到 Rook 項目會將本身的 Pod 放置在由它本身管理的兩個 Namespace 當中:

kubectl get pods -n rook-ceph-system

kubectl get pods -n rook-ceph

這樣,一個基於 Rook 持久化存儲集羣就以容器的方式運行起來了,而接下來在 Kubernetes 項目上建立的全部 Pod 就可以經過 Persistent Volume(PV)和 Persistent Volume Claim(PVC)的方式,在容器裏掛載由 Ceph 提供的數據捲了。

而 Rook 項目,則會負責這些數據卷的生命週期管理、災難備份等運維工做。關於這些容器持久化存儲的知識,我會在後續章節中專門講解。

這時候,你可能會有個疑問:爲何我要選擇 Rook 項目呢?

其實,是由於這個項目頗有前途。 若是你去研究一下 Rook 項目的實現,就會發現它巧妙地依賴了 Kubernetes  提供的編排能力,合理的使用了不少諸如 Operator、CRD 等重要的擴展特性(這些特性我都會在後面的文章中逐一講解到)。這使得 Rook 項目,成爲了目前社區中基於 Kubernetes API 構建的最完善也最成熟的容器存儲插件。我相信,這樣的發展路線,很快就會獲得整個社區的推崇。

其實,在不少時候,你們說的所謂「雲原生」,就是「Kubernetes 原生」的意思。而像 Rook、Istio 這樣的項目,正是貫徹這個思路的典範。在咱們後面講解了聲明式 API 以後,相信你對這些項目的設計思想會有更深入的體會。

備忘: 

查看所有節點

kubectl get pods --all-namespaces

查看pods

kubectl describe pod -n kube-system

查看具體問題

kubectl describe pod kubernetes-dashboard-767dc7d4d-mg5gw -n kube-system

查看pod日誌

kubectl logs -f podname -n cotainname

 

若是初始化過程出現問題,使用以下命令重置:

kubeadm reset

根據 kubeadm 版本查看其所需鏡像  

kubeadm config images list --kubernetes-version v1.11.1

 

 

 

centos安裝步奏

systemctl stop firewalld
systemctl disable firewalld

  

官方安裝地址

https://docs.docker.com/install/linux/docker-ce/centos/

 

安裝docker

yum install -y --setopt=obsoletes=0 \
   docker-ce-17.03.2.ce-1.el7.centos.x86_64 \
   docker-ce-selinux-17.03.2.ce-1.el7.centos.noarch

  

參考:

https://www.datayang.com/article/45

https://www.cnblogs.com/hongdada/p/9761336.html

https://www.liyang.pro/archives/134

https://blog.csdn.net/huangjun0210/column/info/32515
相關文章
相關標籤/搜索