kubernetes-部署

kubernetes-部署

  • 部署kubernetes master

  • 部署容器網(wǎng)絡(luò)插件

  • 部署worker節(jié)點(diǎn)

  • 部署dashboard可視化插件

  • 部署容器存儲(chǔ)插件

  • 以下操作均是在centos7.6進(jìn)行

  1. 部署kubernetes master
# curl -o /etc/yum.repos.d/CentOS-Base.repo http://mirrors.aliyun.com/repo/Centos-7.repo && curl -o  /etc/yum.repos.d/docker-ce.repo  http://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo

# cat <<EOF > /etc/yum.repos.d/kubernetes.repo
[kubernetes]
name=Kubernetes
baseurl=https://mirrors.aliyun.com/kubernetes/yum/repos/kubernetes-el7-x86_64/
enabled=1
gpgcheck=1
repo_gpgcheck=1
gpgkey=https://mirrors.aliyun.com/kubernetes/yum/doc/yum-key.gpg         https://mirrors.aliyun.com/kubernetes/yum/doc/rpm-package-key.gpg
EOF

# 關(guān)閉selinux
# sed -i 's/enforcing/disabled/g' /etc/sysconfig/selinux

安裝基礎(chǔ)組件

# yum install -y kubelet kubeadm kubectl docker-ce vim iptables-services wget  net-tools 

# systemctl start docker && systemctl enable docker kubelet

導(dǎo)入基礎(chǔ)鏡像

# docker load -i k8s1.15.1.tar

注:以上操作需要在所有節(jié)點(diǎn)執(zhí)行,本次部署需要有互聯(lián)網(wǎng)支持

master節(jié)點(diǎn)進(jìn)行初始化

忽略swap報(bào)錯(cuò)

# vim /etc/sysconfig/kubelet
KUBELET_EXTRA_ARGS="--fail-swap-on=false"

安裝

# kubeadm  init --pod-network-cidr=10.244.0.0/16  --service-cidr=10.96.0.0/12  --ignore-preflight-errors=Swap --kubernetes-version=v1.15.1
注:10.244.0.0/16為pod網(wǎng)絡(luò)  server網(wǎng)絡(luò)默認(rèn)為10.96.0.0/12

kubectl 客戶端用戶配置文件配置

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

記錄安裝后輸出,供后面添加node節(jié)點(diǎn)使用

# kubeadm join 192.168.1.170:6443 --token gpy810.gaq18z5bnks9occf    \
--discovery-token-ca-cert-hash sha256:747559b3a32db293cd063a77559c85d04469026145d99cf97fe4fac002717512

查看節(jié)點(diǎn)信息

# kubectl get nodes 
NAME                    STATUS   ROLES    AGE   VERSION
master.k8s.com   NotReady    master   38m   v1.15.1

以上的get輸出結(jié)果可以看到,master節(jié)點(diǎn)的狀態(tài)是NotReady,在調(diào)試k8s集群時(shí),最重要的手段就是用kubectl describe 命令查看節(jié)點(diǎn)(node)對(duì)象的詳細(xì)信息、狀態(tài)和事件(Event),執(zhí)行以下命令進(jìn)行排查

# kubectl describe node master

...
Conditions:
...

Ready   False ... KubeletNotReady  runtime network not ready: NetworkReady=false reason:NetworkPluginNotReady message:docker: network plugin is not ready: cni config uninitialized

通過(guò)kubectl describe 命令輸出可以看到,NotReady的原因是還沒(méi)有部署網(wǎng)絡(luò)插件

另外,還可以通過(guò)kubectl檢查這個(gè)節(jié)點(diǎn)上各個(gè)系統(tǒng)pod的狀態(tài),其中,kube-system是k8s預(yù)留的系統(tǒng)pod的工作空間。

# kubectl get pods -n kube-system

NAME               READY   STATUS   RESTARTS  AGE
coredns-78fcdf6894-j9syh     0/1    Pending  0     1h
coredns-78fcdf6894-jm8df     0/1    Pending  0     1h
etcd-master           1/1    Running  0     2s
kube-apiserver-master      1/1    Running  0     1s
kube-controller-manager-master  0/1    Pending  0     1s
kube-proxy-xb7u7         1/1    NodeLost  0     1h
kube-scheduler-master      1/1    Running  0     1s

可以看到,coredns、kube-controller-manager等依賴于網(wǎng)絡(luò)的pod都處于Pending狀態(tài),也就是調(diào)度失敗,這是符合預(yù)期效果的,因?yàn)檫@個(gè)master節(jié)點(diǎn)的網(wǎng)絡(luò)還沒(méi)部署。

  1. 部署容器網(wǎng)絡(luò)插件
# kubectl apply -f kube-flannel.yml

部署完成后,可以通過(guò)kubectl get 重新檢查一遍pod狀態(tài)。

# kubectl get pods -n kube-system
NAME                                     READY   STATUS    RESTARTS   AGE
coredns-5c98db65d4-cp2zj                 1/1     Running   0          11d
coredns-5c98db65d4-t6rqq                 1/1     Running   0          11d
etcd-master.k8s.com                      1/1     Running   0          11d
kube-apiserver-master.k8s.com            1/1     Running   0          11d
kube-controller-manager-master.k8s.com   1/1     Running   0          11d
kube-flannel-ds-amd64-gkck5              1/1     Running   1          11d
kube-proxy-gjswz                         1/1     Running   1          11d
kube-proxy-s48w4                         1/1     Running   0          11d
kube-scheduler-master.k8s.com            1/1     Running   0          11d

可以看到,所有的pod都啟動(dòng)成功了,而剛剛部署的flannel網(wǎng)絡(luò)插件則在kube-system新建了一個(gè)名叫kube-flannel-ds-amd64-gkck5的pod,一般來(lái)說(shuō),這些pod就是容器網(wǎng)絡(luò)插件在每個(gè)節(jié)點(diǎn)上的控制組件。

k8s支持容器網(wǎng)絡(luò)插件,使用的是一個(gè)叫CNI的通用接口,它也是當(dāng)前容器網(wǎng)絡(luò)的標(biāo)準(zhǔn),市面上所的所有容器網(wǎng)絡(luò)開(kāi)源項(xiàng)目都可以通過(guò)CNI接入k8s,比如剛部署的flannel還有calico、canal、romana等等,它們的部署方式也都是類似的“一鍵部署”。

至此k8s的master節(jié)點(diǎn)就部署完成了,如果只需要一個(gè)蛋節(jié)點(diǎn)的k8s,現(xiàn)在就可以使用了,不過(guò)在默認(rèn)情況下,k8s的master節(jié)點(diǎn)是不能運(yùn)行用戶pod的,所以還需要額外做一個(gè)小操作。

使用taint/toleration調(diào)整master執(zhí)行pod的策略。

它的原理非常簡(jiǎn)單,一旦某個(gè)節(jié)點(diǎn)被加上一個(gè)taint,也就是被打上了“污點(diǎn)”,那么所有pod就都不能在這個(gè)節(jié)點(diǎn)上運(yùn)行,因?yàn)閗8s是有潔癖的。

除非有個(gè)別的pod聲明自己能“容忍”這個(gè)“污點(diǎn)”,也就是聲明了toleration,它才可以在這個(gè)節(jié)點(diǎn)上運(yùn)行。

其中,為節(jié)點(diǎn)打上"污點(diǎn)"(taint)的命令如下:

# kubectl taint nodes master.k8s.com foo=bar:NoSchedule

這時(shí)master.k8s.com這臺(tái)master節(jié)點(diǎn)就會(huì)增加一個(gè)鍵值對(duì)格式的taint,其中值里面的NoSchedule,意味著這個(gè)taint只會(huì)在調(diào)度新pod的時(shí)候生效,而不會(huì)影響到已經(jīng)發(fā)布到master節(jié)點(diǎn)上的pod,即便他們沒(méi)有toleration。

聲明toleration,只需要在pod的yaml文件中spec部分,加入tolerations字段即可,如下:

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

這個(gè)toleration的含義是,這個(gè)pod能“容忍”所有鍵值對(duì)為foo=bar的taint(operator:"Equal",“等于”操作)。

回到已經(jīng)部署的集群個(gè)上,這時(shí),如果通過(guò)kubectl describe檢查一下master節(jié)點(diǎn)的taint字段,就會(huì)有些發(fā)現(xiàn)

kubectl describe node master

Name:               master
Roles:              master
Taints:             node-role.kubernetes.io/master:NoSchedule

可以看到,master節(jié)點(diǎn)默認(rèn)被加上了node-role.kubernetes.io/master:NoSchedule這樣一個(gè)“污點(diǎn)”,其中"鍵"是node-role.kubernetes.io/master,而沒(méi)有提供“值”。

此時(shí),就需要像下面這樣用“Exists”操作符(operator:"Exists",“存在”即可)來(lái)說(shuō)明,該pod能夠容忍所有以foo為鍵的taint,才能讓這個(gè)pod運(yùn)行在該master節(jié)點(diǎn)上。

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

當(dāng)然,如果就是像要一個(gè)單節(jié)點(diǎn)的k8s,刪除這個(gè)taint才是正確的選擇,操作如下:

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

在“node-role.kubernetes.io/master”這個(gè)鍵后面加上了一個(gè)短橫線"-",這個(gè)格式就意味著移除所有以“node-role.kubernetes.io/master”為鍵的taint

  1. 部署worker節(jié)點(diǎn)

node節(jié)點(diǎn)執(zhí)行剛才獲取的命令

# kubeadm join 192.168.1.170:6443 --token gpy810.gaq18z5bnks9occf    \
--discovery-token-ca-cert-hash sha256:747559b3a32db293cd063a77559c85d04469026145d99cf97fe4fac002717512

查看節(jié)點(diǎn)信息

# kubectl  get nodes
NAME                    STATUS   ROLES    AGE   VERSION
master.k8s.com   Ready    master   38m   v1.15.1
node.k8s.com            Ready    <none>   34m   v1.15.1

有了kubeadm這樣的原生管理工具,k8s的部署已經(jīng)被大大簡(jiǎn)化,更重要的是,像證書(shū)、授權(quán)、各個(gè)組件的配置等部署中最麻煩的操作,kubeadm都已經(jīng)幫忙完成了。

至此,整個(gè)k8s集群就部署完成了,可以使用命令行的方式進(jìn)行應(yīng)用的發(fā)布和管理了,但是用起來(lái)可能不是很爽,下面就介紹下k8s的dashboard的部署方式。

  1. 部署dashboard可視化插件

在k8s社區(qū)中,又一個(gè)很受歡迎的dashboard項(xiàng)目,它可以給用戶提供一個(gè)可視化的web界面來(lái)查看當(dāng)前集群的各種信息,毫不意外,它的部署也相當(dāng)簡(jiǎn)單。

kubectl apply -f https://raw.githubusercontent.com/kubernetes/dashboard/master/src/deploy/recommended/kubernetes-dashboard.yaml

部署完成后我們可以查看dashboard的pod狀態(tài)。

#  kubectl get pods -n kube-system
kubernetes-dashboard-6f9887bccc-qc47t    1/1     Running   1          11d

需要注意的是,由于dashboard是一個(gè)web server,很多人經(jīng)常會(huì)在自己的公有云上無(wú)意地暴露dashborad的端口,從而造成安全隱患,所以,1.7版本之后的dashboard部署完成后,默認(rèn)只能通過(guò)proxy的方式在本地訪問(wèn),具體操作,可以查看dashboard的官方文檔。

而如果想從集群外訪問(wèn)這個(gè)dashboard的話,就需要用到ingress。

  1. 部署容器存儲(chǔ)插件

很多時(shí)候我們需要用數(shù)據(jù)卷(volume)把外面宿主機(jī)上的目錄或者文件掛載進(jìn)容器的mount namespace中,從而達(dá)到容器和宿主機(jī)共享這些目錄或文件的目的,容器里的應(yīng)用就可以在這些數(shù)據(jù)卷中新建和寫(xiě)入文件了。

可是,如果在某一臺(tái)機(jī)器上啟動(dòng)一個(gè)容器,顯然無(wú)法看到其他機(jī)器上的容器在它們的數(shù)據(jù)卷里寫(xiě)入的文件,這就是容器最典型的特征之一:無(wú)狀態(tài)

而容器的持久化存儲(chǔ),就是用來(lái)保存容器存儲(chǔ)狀態(tài)的重要手段,存儲(chǔ)插件會(huì)在容器里掛載一個(gè)基于網(wǎng)絡(luò)或其他機(jī)制的遠(yuǎn)程數(shù)據(jù)卷,使得在容器里創(chuàng)建的文件,實(shí)際上保存在遠(yuǎn)程存儲(chǔ)服務(wù)器上,或者以分布式的方式保存在多個(gè)節(jié)點(diǎn)上,而與當(dāng)前宿主機(jī)沒(méi)有任何綁定關(guān)系,這樣無(wú)論在其他哪個(gè)宿主機(jī)上啟動(dòng)新的容器,都可以請(qǐng)求掛載指定的持久化存儲(chǔ)卷,從而訪問(wèn)到數(shù)據(jù)卷里的的數(shù)據(jù),這就是"持久化"的含義。

由于k8s本身的松耦合設(shè)計(jì),絕大多數(shù)存儲(chǔ)項(xiàng)目,如ceph、glusterfs、nfs等,都可以為k8s提供持久化存儲(chǔ)能力,在這次的部署實(shí)戰(zhàn)中,選擇了rook插件進(jìn)行存儲(chǔ)的部署實(shí)驗(yàn)。

rook是一個(gè)基于ceph的k8s存儲(chǔ)插件(它后期也在加入對(duì)更多存儲(chǔ)實(shí)現(xiàn)的支持),不同ceph的簡(jiǎn)單封裝,rook在自己的實(shí)現(xiàn)中加入了水平擴(kuò)展、遷移、災(zāi)難備份、監(jiān)控等大量的企業(yè)級(jí)功能,使得這個(gè)項(xiàng)目變成了一個(gè)完整的,生產(chǎn)級(jí)別可用的容器存儲(chǔ)插件。

得益于容器化技術(shù),以下三條命令就可以將rook部署起來(lái),如下:

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

# 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項(xiàng)目會(huì)將自己的pod放置在由它自己管理的namespace當(dāng)中,如下:

# kubectl  get pod -n rook-ceph
NAME                                            READY   STATUS        RESTARTS   AGE
csi-cephfsplugin-provisioner-7c85779954-cz7g4   4/4     Running       0          5m11s
csi-cephfsplugin-provisioner-7c85779954-dmcq2   4/4     Running       0          5m11s
csi-cephfsplugin-th86r                          3/3     Running       0          5m11s
csi-rbdplugin-provisioner-5474976bf6-6vx2n      5/5     Running       0          5m11s
csi-rbdplugin-provisioner-5474976bf6-lnr4t      5/5     Running       0          5m11s
csi-rbdplugin-sb6qj                             3/3     Running       0          5m11s
rook-ceph-agent-rx7jf                           1/1     Running       0          5m13s
rook-ceph-detect-version-fww7w                  0/1     Terminating   0          11s
rook-ceph-operator-b947787bc-b2kvd              1/1     Running       0          7m10s
rook-discover-rc59k                             1/1     Running       0          5m13s

這樣,一個(gè)基于rook持久化存儲(chǔ)集群就以容器的方式運(yùn)行起來(lái)了,而接下來(lái)在k8s上創(chuàng)建的所有pod就能夠通過(guò)persistent volume(PV)和persistent volume claim(pvc)的方式,在容器里掛載由ceph提供的數(shù)據(jù)卷里。

而rook則會(huì)負(fù)責(zé)這些數(shù)據(jù)卷的生命周期管理、災(zāi)難備份等運(yùn)維工作。

選擇rook其實(shí)是因?yàn)檫@個(gè)項(xiàng)目很有前途,如果去研究下rook項(xiàng)目的實(shí)現(xiàn),就會(huì)發(fā)現(xiàn)它巧妙地依賴了k8s提供等編排能力,合理的使用了很多諸如operator、CRD等重要的擴(kuò)特性,這使得rook成為了目前社區(qū)中機(jī)遇k8s api構(gòu)建的最完善也最成熟的容器存儲(chǔ)插件,可以想象,應(yīng)該很快就會(huì)得到整個(gè)社區(qū)的推崇。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容