生產(chǎn)用例 | 百臺(tái)邊緣設(shè)備上的Kubernetes實(shí)踐

本文由11月7日晚曾永杰,上海全應(yīng)科技運(yùn)維經(jīng)理的技術(shù)分享整理而成。

曾永杰,上海全應(yīng)科技有限公司運(yùn)維經(jīng)理,曾在華為西安研究所云計(jì)算部門承擔(dān)軟件測(cè)試工程師、項(xiàng)目交付、線上運(yùn)維等工作職責(zé),當(dāng)前工作主要為CI/CD流程的建設(shè)與維護(hù)、應(yīng)用的容器化改革和容器云平臺(tái)的運(yùn)維管理。

歡迎添加k3s中文社區(qū)助手微信(微信ID:k3s2019),加入k3s官方中文社區(qū),和大家一起交流k3s使用經(jīng)驗(yàn)。

項(xiàng)目簡(jiǎn)介

背 景

隨著國(guó)家政策的導(dǎo)向,互聯(lián)網(wǎng)基礎(chǔ)設(shè)施的普及,工業(yè)、能源行業(yè)的智能化改造已經(jīng)進(jìn)行的如火如荼,傳統(tǒng)行業(yè)的特點(diǎn)是信息化、智能化水平嚴(yán)重落后于其他行業(yè),在進(jìn)行信息化、智能化改造的過程中,首先第一步,就是要獲取底層系統(tǒng)的全方位的數(shù)據(jù)。

為此,需要部署大量的邊緣設(shè)備來采集數(shù)據(jù)、分析數(shù)據(jù),通過這些數(shù)據(jù)進(jìn)行建模,大量的邊緣設(shè)備一般離散的分布在不同機(jī)房、廠區(qū)、甚至是不同的地理區(qū)域,這對(duì)運(yùn)維人員來講是令人恐懼的事情,維護(hù)這些設(shè)備,管理其上運(yùn)行的應(yīng)用變得極其困難。

我們公司是國(guó)內(nèi)第一批投身于工業(yè)互聯(lián)網(wǎng)改革浪潮中一員,因此上面提到的問題,也是我們面臨的問題。

公司從一開始就采用了微服務(wù)化的開發(fā)模式,除了平臺(tái)框架核心應(yīng)用之外,所有應(yīng)用都是可插拔的微服務(wù)。

與業(yè)務(wù)平臺(tái)不同的是,邊緣設(shè)備具有下面的特點(diǎn):

  • 數(shù)量大,動(dòng)輒有數(shù)十臺(tái)、數(shù)百臺(tái)設(shè)備;

  • 單點(diǎn)故障影響小,一個(gè)設(shè)備只負(fù)責(zé)一小塊區(qū)域的數(shù)據(jù)采集、分析與計(jì)算,因此單臺(tái)設(shè)備的故障導(dǎo)致的局部數(shù)據(jù)的缺失,數(shù)據(jù)分析層面也進(jìn)行了數(shù)據(jù)清洗,因此,單點(diǎn)故障對(duì)全局業(yè)務(wù)影響不大。

需 求

對(duì)于運(yùn)維角色來講:

  • 管理這些邊緣設(shè)備,保持邊緣設(shè)備上運(yùn)行的服務(wù)的高可用性;

  • 快速的上線、升級(jí)

  • 配置的快速更改與應(yīng)用

邏輯拓?fù)鋱D

下面的圖形簡(jiǎn)單描述了項(xiàng)目基礎(chǔ)設(shè)施層的拓?fù)洌?/p>

在這里插入圖片描述

其中,每一個(gè)邊緣側(cè)設(shè)備上運(yùn)行的業(yè)務(wù)會(huì)和中樞業(yè)務(wù)系統(tǒng)通訊,邊緣側(cè)所有設(shè)備在單獨(dú)的一個(gè)網(wǎng)絡(luò)平面中。

運(yùn)維方案選型

在決定運(yùn)維方式時(shí),考慮過下面的幾種方式:

Ansible

我們?cè)谶吘墏?cè)設(shè)備上運(yùn)行的應(yīng)用大部分都是純Java應(yīng)用,再加上一部分Python應(yīng)用,因此部署和啟動(dòng)非常簡(jiǎn)單,外加上supervisord應(yīng)用實(shí)現(xiàn)了應(yīng)用的基本高可用方案。在公司還沒有進(jìn)行容器化轉(zhuǎn)型之前,我們采用傳統(tǒng)的部署形式部署微服務(wù),就是配置好宿主機(jī)的系統(tǒng)環(huán)境,直接將應(yīng)用部署在宿主機(jī)系統(tǒng)上,在這種情況下,我們只需要解決的問題是大批量設(shè)備部署和維護(hù)的問題,因?yàn)椴还苁遣渴疬€是更新升級(jí)、配置,所有邊緣側(cè)使用Ansible可以較好的滿足這一條件。

但是這種方法也有缺點(diǎn),需要維護(hù)一套甚至多套ansible playbook,邊緣側(cè)設(shè)備所在的網(wǎng)絡(luò)條件比較差,異常狀況也比較差,經(jīng)常掉電重啟或者斷網(wǎng),使用ansible 容易造成各個(gè)節(jié)點(diǎn)的配置不同步。

kubeedge

kubeedge是由華為基于kubernetes開發(fā)并開源,專門用于邊緣容器編排的運(yùn)維方案,其基本架構(gòu)如下:

在這里插入圖片描述

從上面的架構(gòu)圖中可以看到,kubeedge實(shí)現(xiàn)了一個(gè)邊緣側(cè)完整的框架,對(duì)我們公司來講,我們自行實(shí)現(xiàn)了例如“DeviceTwin”、“EventBus”、“ServiceBus”以及基于MQTT收發(fā)消息。因此:

  1. 一部分組件與kubeedge重疊了;

  2. 部署不方便,kubeedge要求在各個(gè)節(jié)點(diǎn)上以kubeadmin部署kubernetes集群(0.6版本,現(xiàn)在已經(jīng)更新至1.1版本,不知道現(xiàn)在是否有更簡(jiǎn)便快捷的形式),對(duì)網(wǎng)絡(luò)環(huán)境不好的邊緣側(cè)設(shè)備有較大難度;

  3. kubeedge組件與kubernetes組件基本一致,對(duì)于邊緣設(shè)備寸土寸金的資源來說,不太友好。

通過實(shí)踐,第2點(diǎn)和第3點(diǎn)原因直接打消了我采用kubeedge的念頭。

k3s簡(jiǎn)介

什么是k3s?

k3s is 5 less then k8s,直接翻譯過來就是k3s比k8s少了5個(gè)字符,引申一下就是k3s就是k8s的簡(jiǎn)化版。可以看做k8s的一個(gè)衍生版,特點(diǎn)就是輕量。

k3s的特點(diǎn)有哪些?

apiserver、controller manager、scheduler、kubelet、flannel等組件這到一個(gè)進(jìn)程中(通過指定是server或者agent選項(xiàng)來控制節(jié)點(diǎn)上需要啟動(dòng)哪些組件,server相當(dāng)于k8s的master節(jié)點(diǎn),agent相當(dāng)于worker節(jié)點(diǎn)),占用的內(nèi)存更少了,整個(gè)k3s server進(jìn)程需要的內(nèi)存在500MB以下。

$ systemctl status k3s-server
● k3s-server.service - Lightweight Kubernetes
   Loaded: loaded (/usr/lib/systemd/system/k3s-server.service; enabled; vendor preset: disabled)
   Active: active (running) since 一 2019-10-28 11:35:25 CST; 1 weeks 3 days ago
     Docs: https://k3s.io
 Main PID: 1534 (k3s-server)
    Tasks: 0
   Memory: 210.2M
   CGroup: /system.slice/k3s-server.service
           ? 1534 /usr/bin/k3s server --docker --bind-address=10.0.0.201 --cluster-cidr=10.128.0.0/16 ...

11月 07 14:21:35 test01-201 k3s[1534]: I1107 14:21:35.426083    1534 trace.go:81] Trace[193609352...ms):
11月 07 14:21:35 test01-201 k3s[1534]: Trace[1936093523]: [575.582721ms] [575.489216ms] Listing f...done
11月 07 14:22:14 test01-201 k3s[1534]: W1107 14:22:14.958361    1534 reflector.go:289] object-"te...978)
11月 07 14:23:32 test01-201 k3s[1534]: W1107 14:23:32.403901    1534 reflector.go:289] object-"te...043)
11月 07 14:23:52 test01-201 k3s[1534]: W1107 14:23:52.762578    1534 reflector.go:289] object-"te...061)
11月 07 14:24:08 test01-201 k3s[1534]: W1107 14:24:08.159614    1534 reflector.go:289] object-"ku...074)
11月 07 14:24:20 test01-201 k3s[1534]: W1107 14:24:20.815875    1534 reflector.go:289] object-"te...086)
11月 07 14:24:21 test01-201 k3s[1534]: W1107 14:24:21.038295    1534 reflector.go:289] object-"te...086)
11月 07 14:26:17 test01-201 k3s[1534]: W1107 14:26:17.367497    1534 reflector.go:289] object-"te...183)
11月 07 14:26:27 test01-201 k3s[1534]: W1107 14:26:27.321999    1534 reflector.go:289] object-"te...192)
Hint: Some lines were ellipsized, use -l to show in full.
[asadmin@test01-201 ~]$

從上面看出k3s server進(jìn)程當(dāng)前占用的內(nèi)存是210MB。

去除了k8s中的一些實(shí)驗(yàn)特性、非必須的組件,例如云廠商的驅(qū)動(dòng)、存儲(chǔ)插件,k3s在默認(rèn)狀態(tài)下只會(huì)啟動(dòng)除自身進(jìn)程之外的兩個(gè)應(yīng)用:

  • coredns:提供集群內(nèi)部的DNS解析服務(wù)。

  • traefik:ingress controller的角色。

k3s server默認(rèn)使用本地(已集成)的sqllite作為后端數(shù)據(jù)存儲(chǔ),通訊效率更高一些。

占用資源少:k3s默認(rèn)使用containerd(server節(jié)點(diǎn),不可更改)作為容器運(yùn)行時(shí),不在需要中間層的docker engine,占用資源更少。

部署簡(jiǎn)單:對(duì)環(huán)境依賴少,可離線也可在線部署(不過國(guó)內(nèi)的網(wǎng)絡(luò)環(huán)境不推薦在線部署。),離線部署時(shí),只需要下載一個(gè)大約40MB的二進(jìn)制文件和一個(gè)200MB不到的離線鏡像包,啟動(dòng)k3s節(jié)點(diǎn)幾乎是秒級(jí)的。

上手無代價(jià):

  • 使用k3s與kubernetes習(xí)慣完全一致,對(duì)于使用kubernetes的人來講使用k3s沒有任何代價(jià);

  • 支持部署helm tiller服務(wù)端(盡管tiller端會(huì)在helm 3.x版本中被干掉),直接使用原有charts部署應(yīng)用無障礙;

擴(kuò)縮容方便:增刪節(jié)點(diǎn)極其方便,幾乎是分鐘以內(nèi)就可以完成;

兼容arm架構(gòu)設(shè)備:對(duì)于部分有此種類型的設(shè)備的集群友好。

下面是k3s的架構(gòu)圖:

在這里插入圖片描述

k3s集群的所有數(shù)據(jù)存儲(chǔ)在server(master)節(jié)點(diǎn)本地的SQLite數(shù)據(jù)庫(kù)中,當(dāng)然也支持存儲(chǔ)在諸如MySQL、etcd中,都是支持按照需求在部署節(jié)點(diǎn)時(shí)選擇配置的。server節(jié)點(diǎn)與agent節(jié)點(diǎn)之間采用tunnel隧道通信,增強(qiáng)了安全性,同時(shí)也提升了效率。agent與server節(jié)點(diǎn)即使斷開網(wǎng)絡(luò)連接,也不影響相互各自的業(yè)務(wù)。

因此通過上面的對(duì)比和實(shí)踐驗(yàn)證,我們決定采用k3s來管理邊緣設(shè)備集群。

運(yùn)維架構(gòu)簡(jiǎn)介

下面是一張完整的運(yùn)維架構(gòu)圖:

在這里插入圖片描述

部署k3s集群

由于集群節(jié)點(diǎn)一般存在多個(gè),一臺(tái)臺(tái)手工安裝部署會(huì)占用大量的時(shí)間,吃力不討好,因此,我寫成了ansible playbook來完成k3s集群的多節(jié)點(diǎn)快速自動(dòng)化部署,如有需要,可以聯(lián)系yj.zeng@aliyun.com

各個(gè)組件版本信息:

  • k3s: v0.9.1

  • docker: 18.09.9

  • helm: v2.14.3

  • OS:CentOS Linux release 7.6.1810 (Core)

  • Ansible: 2.8.3(在多節(jié)點(diǎn)下,用來快速批量部署集群節(jié)點(diǎn))

本次實(shí)踐在Centos 7上完成,由于部署k3s節(jié)點(diǎn)需要root用戶權(quán)限,因此本實(shí)踐中所有操作均直接使用root用戶登錄后進(jìn)行。

獲取k3s以及離線鏡像包

k3s GitHub主頁(yè):

https://github.com/rancher/k3s/releases

由于國(guó)內(nèi)訪問GitHub的速度很慢,在線安裝耗時(shí)很長(zhǎng),因此推薦采用離線部署方式部署。

以v0.8.1版本為例,下載下面的兩個(gè)文件:

  • k3s

  • k3s-airgap-images-amd64.tar

準(zhǔn)備工作

假定下載到的文件已經(jīng)上傳到服務(wù)器節(jié)點(diǎn)的~/packages目錄下面。

將k3s二進(jìn)制文件放置到/usr/local/bin目錄下,并賦予可執(zhí)行權(quán)限:

# cp ~/packages/k3s /usr/local/bin/ 
# chmod +x /usr/local/bin/k3s

將離線鏡像包放置到指定的位置:

# mkdir -p /var/lib/rancher/k3s/agent/images/
# cp ~/packages/k3s-airgap-images-amd64.tar /var/lib/rancher/k3s/agent/images/

需要在k3s集群所有節(jié)點(diǎn)上都放置上面的離線文件。

在部署k3s集群之前,需要對(duì)所有節(jié)點(diǎn)做如下的基礎(chǔ)配置。

如果沒有專門的域名服務(wù)器提供主機(jī)名解析服務(wù),那么在每一臺(tái)節(jié)點(diǎn)的/etc/hosts文件中。寫入本節(jié)點(diǎn)的IP與主機(jī)名映射。

給所有節(jié)點(diǎn)安裝并配置相同的NTP服務(wù)器,保證服務(wù)器時(shí)間的正確性。

# yum -y install ntp && systemctl start ntpd && systemctl enable ntpd

為了方便我們直接關(guān)閉防火墻服務(wù):

# systemctl stop firewalld && systemctl disable firewalld

至此,準(zhǔn)備工作完成。

部署k3s server節(jié)點(diǎn)

提醒:

截止目前,k3s server節(jié)點(diǎn)并不支持HA。

k3s server節(jié)點(diǎn)安裝時(shí),可以選在同時(shí)在本地安裝一個(gè)k3s agent節(jié)點(diǎn)用以承載工作負(fù)載,如果選擇不在server節(jié)點(diǎn)上安裝agent節(jié)點(diǎn),則除了k3s集成的kuberntes組件(如kubelet、api server)之外,其余的插件、應(yīng)用均不會(huì)被調(diào)度到server節(jié)點(diǎn)上。

k3s支持使用多種容器運(yùn)行時(shí)環(huán)境,server默認(rèn)以containerd作為運(yùn)行時(shí),不支持更改。agent節(jié)點(diǎn)可以使用contained也可以使用docker,推薦使用docker,因?yàn)閐ocker人機(jī)更友好,可以方便的管理鏡像和容器以及查錯(cuò)。所以如果選擇agent節(jié)點(diǎn)以docker作為容器運(yùn)行時(shí),那么必須要提前安裝并配置好docker服務(wù)。

現(xiàn)在,我們可以啟動(dòng)k3s server節(jié)點(diǎn):

# k3s server \
    --docker \
    --bind-address=10.0.0.201 \
    --cluster-cidr=10.128.0.0/16 \
    --service-cidr=10.129.0.0/16 \
    --kube-apiserver-arg service-node-port-range=1000-65000 \
    --write-kubeconfig=/root/.kube/config \
    --write-kubeconfig-mode=644 \
    --node-label asrole=worker

參數(shù)說明:

  • --docker: k3s server組件以containerd作為容器運(yùn)行時(shí)。可以順便在k3s server節(jié)點(diǎn)上啟動(dòng)一個(gè)agent節(jié)點(diǎn),agent節(jié)點(diǎn)可以使用docker作為容器運(yùn)行時(shí),這樣k3s server節(jié)點(diǎn)也可以當(dāng)做工作節(jié)點(diǎn)用。當(dāng)然也可以不在server節(jié)點(diǎn)上啟動(dòng)agent節(jié)點(diǎn)(添加參數(shù)--disable-agent即可)。

  • --bind-address:k3s監(jiān)聽的IP地址,非必選,默認(rèn)是localhost。

  • --cluster-cidr:與kubernetes一樣,也就是pod所在網(wǎng)絡(luò)平面,非必選,默認(rèn)是10.42.0.0/16.

  • --service-cidr:與kubernetes一樣,服務(wù)所在的網(wǎng)絡(luò)平面,非必選,默認(rèn)是10.43.0.0/16.

  • --kube-apiserver-arg:額外的api server配置參數(shù),具體可以參考kuberntes官方網(wǎng)站了解支持的配置選項(xiàng),非必選。

  • --write-kubeconfig:安裝時(shí)順便寫一個(gè)kubeconfig文件,方便使用kubectl工具直接訪問。如果不加此參數(shù),則默認(rèn)的配置文件路徑為/etc/rancher/k3s/k3s.yaml,默認(rèn)只有root用戶能讀。

  • --write-kubeconfig-mode:與--write-kubeconfig一起使用,指定kubeconfig文件的權(quán)限。

  • --node-label:順便給節(jié)點(diǎn)打上一個(gè)asrole=worker的label,非必選。

k3s支持眾多的安裝參數(shù)和選型,詳細(xì)請(qǐng)參考官方文檔:

https://rancher.com/docs/k3s/latest/en/installation/

完成之后,檢查集群狀態(tài):

# k3s kubectl get nodes
NAME         STATUS   ROLES    AGE   VERSION
test01-201   Ready    master   11m   v1.15.4-k3s.1

可見節(jié)點(diǎn)已經(jīng)呈就緒狀態(tài)。

檢查pod的狀態(tài):

# k3s kubectl get po --all-namespaces
NAMESPACE     NAME                         READY   STATUS      RESTARTS   AGE
kube-system   helm-install-traefik-fhr87   0/1     Completed   0          3m4s
kube-system   svclb-traefik-zlgwx          3/3     Running     0          54s
kube-system   coredns-66f496764-x9svh      1/1     Running     0          3m4s
kube-system   traefik-d869575c8-kvwbc      0/1     Running     0          54s

可以看到,系統(tǒng)命名空間下所有的應(yīng)用都已經(jīng)啟動(dòng)了,server節(jié)點(diǎn)已經(jīng)就緒,接下來可以部署k3s agent工作節(jié)點(diǎn)了。

在上面的命令中,我們均是以k3s kubectl開頭的命令,是否可以直接使用kubectl客戶端呢?當(dāng)然可以,只需要下載一個(gè)對(duì)應(yīng)版本的kubectl二進(jìn)制文件放到系統(tǒng)的path中,賦予可執(zhí)行權(quán)限即可,使用起來與使用kubernetes集群一模一樣!

由于上面的命令是在前臺(tái)執(zhí)行的,一旦斷開SSH鏈接或者終止shell進(jìn)程,k3s server就停止運(yùn)行了,因此我們給他配置一個(gè)systemd服務(wù),用以像管理系統(tǒng)服務(wù)一樣管理k3s server節(jié)點(diǎn)。

創(chuàng)建文件/usr/lib/systemd/system/k3s-server.service,內(nèi)容為:

[Unit]
Description=Lightweight Kubernetes
Documentation=https://k3s.io
After=network-online.target

[Service]
Type=notify
EnvironmentFile=/etc/systemd/system/k3s.service.env
ExecStart=/usr/local/bin/k3s server --docker --bind-address=10.0.0.201 --cluster-cidr=10.128.0.0/16 --service-cidr=10.129.0.0/16 --kube-apiserver-arg service-node-port-range=1000-65000
KillMode=process
Delegate=yes
LimitNOFILE=infinity
LimitNPROC=infinity
LimitCORE=infinity
TasksMax=infinity
TimeoutStartSec=0
Restart=always
RestartSec=5s

[Install]
WantedBy=multi-user.target

然后設(shè)置服務(wù)開機(jī)自啟:

# systemctl enable k3s-server

CTRL+C結(jié)束在前臺(tái)執(zhí)行的命令,我們看到服務(wù)文件中引用了一個(gè)環(huán)境變量文件/etc/systemd/system/k3s.service.env,這個(gè)文件并不存在需要先創(chuàng)建一個(gè)然后才能啟動(dòng)服務(wù):

# touch /etc/systemd/system/k3s.service.env
# systemctl start k3s-server

查看服務(wù)狀態(tài):

# systemctl status k3s-server
● k3s-server.service - Lightweight Kubernetes
   Loaded: loaded (/usr/lib/systemd/system/k3s-server.service; disabled; vendor preset: disabled)
   Active: active (running) since 五 2019-10-11 09:37:09 CST; 15min ago
     Docs: https://k3s.io
 Main PID: 10841 (k3s-server)
    Tasks: 0
   Memory: 223.3M
   CGroup: /system.slice/k3s-server.service
           ? 10841 /usr/local/bin/k3s server --docker --bind-address=10.0.0.201 --cluster-cidr=10.128.0.0/16 --service-cidr=10.129.0.0/16 --...

10月 11 09:37:22 test01-201 k3s[10841]: I1011 09:37:22.920359   10841 event.go:258] Event(v1.ObjectReference{Kind:"Node", Namespace:"", Nam...
10月 11 09:37:22 test01-201 k3s[10841]: I1011 09:37:22.927021   10841 controller_utils.go:1036] Caches are synced for persistent vo...ntroller
10月 11 09:37:22 test01-201 k3s[10841]: I1011 09:37:22.934842   10841 controller_utils.go:1036] Caches are synced for attach detach controller
10月 11 09:37:22 test01-201 k3s[10841]: I1011 09:37:22.940745   10841 controller_utils.go:1036] Caches are synced for garbage colle...ntroller
10月 11 09:37:22 test01-201 k3s[10841]: I1011 09:37:22.956261   10841 controller_utils.go:1036] Caches are synced for garbage colle...ntroller
10月 11 09:37:22 test01-201 k3s[10841]: I1011 09:37:22.956292   10841 garbagecollector.go:137] Garbage collector: all resource moni... garbage
10月 11 09:37:22 test01-201 k3s[10841]: I1011 09:37:22.959183   10841 controller_utils.go:1036] Caches are synced for cidrallocator controller
10月 11 09:37:23 test01-201 k3s[10841]: I1011 09:37:23.292627   10841 controller.go:606] quota admission added evaluator for: jobs.batch
10月 11 09:38:02 test01-201 k3s[10841]: I1011 09:38:02.930061   10841 event.go:258] Event(v1.ObjectReference{Kind:"Node", Namespace...NotReady
10月 11 09:38:02 test01-201 k3s[10841]: E1011 09:38:02.970568   10841 daemon_controller.go:302] kube-system/svclb-traefik failed wi...Link:"/a
Hint: Some lines were ellipsized, use -l to show in full.

提醒:如果出現(xiàn)錯(cuò)誤,可以通過journalctl -u k3s-server查看日志。

部署k3s agent節(jié)點(diǎn)

在server節(jié)點(diǎn)部署完成之后,在server節(jié)點(diǎn)的/var/lib/rancher/k3s/server/目錄下面生成一個(gè)node-token文件,該文件存儲(chǔ)了k3s agent節(jié)點(diǎn)加入集群時(shí)所需的token。

在server節(jié)點(diǎn)上,獲取token:

# cat /var/lib/rancher/k3s/server/node-token 
K10e3dc328c9e2cbb07c195542da31ab435dbe0182b1c99c613f460097b5173dbc7::node:0595ee334f5d2847542b5b1c9300f363

在作為k3s agent節(jié)點(diǎn)的系統(tǒng)中,以root用戶執(zhí)行下面的命令啟動(dòng)k3s agent節(jié)點(diǎn),但是,因?yàn)槲覀儾捎昧薲ocker作為agent節(jié)點(diǎn)的容器運(yùn)行時(shí),所以我們先將離線鏡像導(dǎo)入到docker中:

# docker load -i ~/packages/k3s-airgap-images-amd64.tar 
fb61a074724d: Loading layer [==================================================>]  479.7kB/479.7kB
ed9e1db7c0e6: Loading layer [==================================================>]  40.16MB/40.16MB
Loaded image: coredns/coredns:1.3.0
faf7c252da57: Loading layer [==================================================>]    236kB/236kB
d27d00a62b62: Loading layer [==================================================>]  71.48MB/71.48MB
Loaded image: traefik:1.7.12
d9ff549177a9: Loading layer [==================================================>]  4.671MB/4.671MB
d635f458a6f8: Loading layer [==================================================>]  7.586MB/7.586MB
9ce3955d3fa8: Loading layer [==================================================>]  73.36MB/73.36MB
6c5cc370be91: Loading layer [==================================================>]  4.608kB/4.608kB
Loaded image: rancher/klipper-helm:v0.1.5
767f936afb51: Loading layer [==================================================>]  4.672MB/4.672MB
d9f07b03cc3c: Loading layer [==================================================>]  1.786MB/1.786MB
4d018801281b: Loading layer [==================================================>]  3.072kB/3.072kB
Loaded image: rancher/klipper-lb:v0.1.1
e17133b79956: Loading layer [==================================================>]  744.4kB/744.4kB
Loaded image: k8s.gcr.io/pause:3.1

然后執(zhí)行下面的命令安裝k3s-agent節(jié)點(diǎn)

# k3s agent \
    --docker \
    --server https://10.0.0.201:6443 \
    --token K10e3dc328c9e2cbb07c195542da31ab435dbe0182b1c99c613f460097b5173dbc7::node:0595ee334f5d2847542b5b1c9300f363 \
    --node-ip=10.0.0.202 \
    --node-label asrole=worker

參數(shù)說明:

  • --docker:k3s agent以docker作為容器運(yùn)行時(shí)。

  • --server:k3s server節(jié)點(diǎn)監(jiān)聽的url,必選參數(shù)。

  • --token:k3s server安裝時(shí)生成的token,必選參數(shù)。

  • --node-ip:k3s agent節(jié)點(diǎn)的IP地址,非必選參數(shù)。

  • --node-label:同樣給k3s agent節(jié)點(diǎn)打上一個(gè)asrole=worker的標(biāo)簽,非必選參數(shù)。

稍等一會(huì)兒,在server節(jié)點(diǎn)上查看agent節(jié)點(diǎn)是否已經(jīng)加入到了集群中:

# k3s kubectl get nodes
NAME         STATUS   ROLES    AGE   VERSION
test01-201   Ready    master   12h   v1.15.4-k3s.1
test02-202   Ready    worker   11h   v1.15.4-k3s.1

可以看到節(jié)點(diǎn)已經(jīng)成功加入到了集群中。

同樣給agent節(jié)點(diǎn)配置成systemd可以管理的系統(tǒng)服務(wù),創(chuàng)建/usr/lib/systemd/system/k3s-agent.service,內(nèi)容如下:

[Unit]
Description=Lightweight Kubernetes
Documentation=https://k3s.io
After=network-online.target

[Service]
Type=notify
EnvironmentFile=/etc/systemd/system/k3s.service.env
ExecStart=/usr/local/bin/k3s agent --docker --server https://10.0.0.201:6443 --token K10e3dc328c9e2cbb07c195542da31ab435dbe0182b1c99c613f460097b5173dbc7::node:0595ee334f5d2847542b5b1c9300f363 --node-ip=10.0.0.202 --node-label asrole=worker
KillMode=process
Delegate=yes
LimitNOFILE=infinity
LimitNPROC=infinity
LimitCORE=infinity
TasksMax=infinity
TimeoutStartSec=0
Restart=always
RestartSec=5s

[Install]
WantedBy=multi-user.target

我們終止前臺(tái)執(zhí)行的命令,執(zhí)行下面的命令通過systemd重新啟動(dòng)服務(wù):

# touch /etc/systemd/system/k3s.service.env
# systemctl daemon-reload && systemctl enable k3s-agent
# systemctl enable k3s-agent
Created symlink from /etc/systemd/system/multi-user.target.wants/k3s-agent.service to /usr/lib/systemd/system/k3s-agent.service.
# systemctl start k3s-agent
# systemctl status k3s-agent
● k3s-agent.service - Lightweight Kubernetes
   Loaded: loaded (/usr/lib/systemd/system/k3s-agent.service; enabled; vendor preset: disabled)
   Active: active (running) since 五 2019-10-11 10:05:12 CST; 1min 30s ago
     Docs: https://k3s.io
 Main PID: 13631 (k3s-agent)
    Tasks: 0
   Memory: 149.0M
   CGroup: /system.slice/k3s-agent.service
           ? 13631 /usr/local/bin/k3s agent --docker --server https://10.0.0.201:6443 --token K10e3dc328c9e2cbb07c195542da31ab435dbe0182b1c9...

10月 11 10:05:13 test02-202 k3s[13631]: I1011 10:05:13.074705   13631 cpu_manager.go:156] [cpumanager] reconciling every 10s
10月 11 10:05:13 test02-202 k3s[13631]: I1011 10:05:13.074731   13631 policy_none.go:42] [cpumanager] none policy: Start
10月 11 10:05:13 test02-202 k3s[13631]: I1011 10:05:13.079218   13631 plugin_manager.go:116] Starting Kubelet Plugin Manager
10月 11 10:05:13 test02-202 k3s[13631]: I1011 10:05:13.350068   13631 kube.go:134] Node controller sync successful
10月 11 10:05:13 test02-202 k3s[13631]: I1011 10:05:13.350282   13631 vxlan.go:120] VXLAN config: VNI=1 Port=0 GBP=false DirectRouting=false
10月 11 10:05:13 test02-202 k3s[13631]: I1011 10:05:13.353705   13631 flannel.go:75] Wrote subnet file to /run/flannel/subnet.env
10月 11 10:05:13 test02-202 k3s[13631]: I1011 10:05:13.353740   13631 flannel.go:79] Running backend.
10月 11 10:05:13 test02-202 k3s[13631]: I1011 10:05:13.353767   13631 vxlan_network.go:60] watching for new subnet leases
10月 11 10:05:13 test02-202 k3s[13631]: I1011 10:05:13.412763   13631 reconciler.go:203] operationExecutor.VerifyControllerAttachedVolume s...
10月 11 10:05:14 test02-202 k3s[13631]: I1011 10:05:14.215209   13631 reconciler.go:150] Reconciler: start to sync state
Hint: Some lines were ellipsized, use -l to show in full.

可以看到k3s agent節(jié)點(diǎn)已經(jīng)成功啟動(dòng)了。

如果還需要加入新的agent節(jié)點(diǎn)到集群中,可以按照上述方式配置啟動(dòng)新節(jié)點(diǎn),完成后,新節(jié)點(diǎn)自動(dòng)加入到集群中。

部署應(yīng)用

通過helm部署應(yīng)用

一般情況下,我們會(huì)通過helm chart安裝應(yīng)用和升級(jí)應(yīng)用,在k3s集群中,同樣可以采用helm來安裝部署應(yīng)用。

下載helm的客戶端二進(jìn)制文件后,放置到/usr/local/bin目錄下并賦予可執(zhí)行權(quán)限。執(zhí)行下面的命令初始化helm客戶端:

# k3s kubectl -n kube-system create serviceaccount tiller
serviceaccount/tiller created
# k3s kubectl create clusterrolebinding tiller \
>   --clusterrole=cluster-admin \
>   --serviceaccount=kube-system:tiller
clusterrolebinding.rbac.authorization.k8s.io/tiller created
# helm init --service-account tiller \
> --tiller-image registry.cn-hangzhou.aliyuncs.com/google_containers/tiller:v2.14.3 --skip-refresh
Creating /root/.helm 
Creating /root/.helm/repository 
Creating /root/.helm/repository/cache 
Creating /root/.helm/repository/local 
Creating /root/.helm/plugins 
Creating /root/.helm/starters 
Creating /root/.helm/cache/archive 
Creating /root/.helm/repository/repositories.yaml 
Adding stable repo with URL: https://kubernetes-charts.storage.googleapis.com 
Adding local repo with URL: http://127.0.0.1:8879/charts 
$HELM_HOME has been configured at /root/.helm.

Tiller (the Helm server-side component) has been installed into your Kubernetes Cluster.

Please note: by default, Tiller is deployed with an insecure 'allow unauthenticated users' policy.
To prevent this, run `helm init` with the --tiller-tls-verify flag.
For more information on securing your installation see: https://docs.helm.sh/using_helm/#securing-your-helm-installation

查看helm信息:

# helm version --short
Client: v2.14.3+g0e7f3b6
Server: v2.14.3+g0e7f3b6

可見helm的服務(wù)端已經(jīng)在集群中創(chuàng)建成功了,下面就可以使用helm chart安裝應(yīng)用了。在此我們進(jìn)行演示:

#  helm repo add edge https://xxxx.xxxx.com
"edge" has been added to your repositories
# helm install edge/iotgateway
NAME:   idolized-wombat
LAST DEPLOYED: Fri Oct 11 11:26:04 2019
NAMESPACE: default
STATUS: DEPLOYED
...

查看pod的情況:

# k3s kubectl get po -o wide
NAME               READY   STATUS    RESTARTS   AGE     IP           NODE         NOMINATED NODE   READINESS GATES
iotgateway-6c242   1/1     Running   0          2m42s   10.0.0.201   test01-201   <none>           <none>
iotgateway-pqsx2   1/1     Running   0          2m38s   10.0.0.202   test02-202   <none>           <none>

可見應(yīng)用已經(jīng)創(chuàng)建成功。

使用Rancher管理k3s集群

在Rancher上添加一個(gè)集群,然后按照步驟將該集群導(dǎo)入到Rancher平臺(tái)中,可以使用Rancher管理和維護(hù)集群:

在這里插入圖片描述

FAQ

1、在邊緣計(jì)算中,往往涉及到訪問硬件資源,如何從容器內(nèi)部訪問硬件資源?

Linux系統(tǒng)中,所有的硬件資源都體現(xiàn)為/dev/目錄下面的一個(gè)設(shè)備,因此只要能夠訪問/dev/目錄下面的設(shè)備文件即可,有的同學(xué)會(huì)說,那是不是將/dev/目錄掛載到容器里面就可以了呢?經(jīng)過我的實(shí)踐證明不行,因?yàn)閽燧d到容器里面,即便容器里面是以root用戶運(yùn)行,然是仍舊有可能無法訪問一些特殊資源文件,也就是說容器中的“root”用戶與宿主機(jī)的root用戶在訪問權(quán)限上還是有差別。只需要將容器的運(yùn)行模式設(shè)置為“privileged”即可,如下:

resources:
  limits:
    cpu: 300m
    memory: 512Mi
  requests:
    cpu: 50m
    memory: 256Mi
securityContext:
  privileged: true

2、如何備份集群數(shù)據(jù)?

k3s集群數(shù)據(jù)全部存儲(chǔ)在/var/lib/rancher下面,在/etc/rancher、/etc/kubernetes下面會(huì)存儲(chǔ)一些配置文件和證書,因此我們可以周期性備份這幾個(gè)目錄的數(shù)據(jù)即可。也可以給k3s server節(jié)點(diǎn)掛載一個(gè)高可靠性的存儲(chǔ)設(shè)備。

3、節(jié)點(diǎn)宕機(jī)怎么恢復(fù)?

對(duì)于agent節(jié)點(diǎn),邊緣節(jié)點(diǎn)只負(fù)責(zé)一個(gè)小區(qū)域的業(yè)務(wù),單個(gè)節(jié)點(diǎn)宕機(jī)對(duì)整個(gè)集群業(yè)務(wù)影響很有限,只需要重新啟動(dòng)將節(jié)點(diǎn)加入集群中即可恢復(fù)業(yè)務(wù)運(yùn)行。對(duì)于server節(jié)點(diǎn),如果有數(shù)據(jù)備份,可以用數(shù)據(jù)備份進(jìn)行恢復(fù)(將備份數(shù)據(jù)放置到對(duì)應(yīng)的目錄重新按照原有參數(shù)啟動(dòng)server節(jié)點(diǎn)服務(wù)即可),如果沒有備份,那么重新安裝一個(gè)server節(jié)點(diǎn),更改agent節(jié)點(diǎn)的啟動(dòng)參數(shù)中的token,重新將agent注冊(cè)到新的server節(jié)點(diǎn),但是因?yàn)榧簲?shù)據(jù)丟失,可能需要重新安裝應(yīng)用,因此盡可能對(duì)server節(jié)點(diǎn)的數(shù)據(jù)進(jìn)行周期性備份并妥善存儲(chǔ)保管。

4、k3s是否可以外部存儲(chǔ)系統(tǒng)?

當(dāng)然是可以的,如果涉及到應(yīng)用必須要訪問持久化存儲(chǔ),那么也可以像kubernetes一樣給其接入外部存儲(chǔ)系統(tǒng),但是不推薦這么做,因?yàn)檫吘壴O(shè)備一般比較分散,網(wǎng)絡(luò)環(huán)境也不穩(wěn)定,外接存儲(chǔ)系統(tǒng)會(huì)導(dǎo)致性能打折扣,因此建議:

  • 對(duì)于必須將數(shù)據(jù)存儲(chǔ)在外部存儲(chǔ)上的應(yīng)用,可以通過nodeSelector限制其到某幾個(gè)特定的比較可靠穩(wěn)定的節(jié)點(diǎn)上,然后接入外部存儲(chǔ)系統(tǒng);

  • 對(duì)于daemonset類型的應(yīng)用,非關(guān)鍵核心數(shù)據(jù)可以通過hostPath存儲(chǔ)在宿主機(jī)系統(tǒng)上

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

推薦閱讀更多精彩內(nèi)容