您好,登錄后才能下訂單哦!
研究K8S有一陣子了,這個東西很好用,但是也有很多坑,個人覺得很多地方還有待改進(jìn),K8S的靜態(tài)Pod是一個利器,但也必須對它有全面的了解才能運作。
今天給大家示例一個從頭到尾自己研究出來的項目,需要一定的基礎(chǔ),拋磚引玉,大家學(xué)會了可以自己去發(fā)揮。
K8S最大作用是面向集群業(yè)務(wù)型的和面向研發(fā)CI/CD,我這個例子偏向CI/CD。
步入正題:
環(huán)境:
1,首先,你得至少已經(jīng)搭建了單節(jié)點的K8S平臺;
2,會熟悉的部署Dockerfile;
3,?? 會K8S基本的命令操作;
4,對K8S基本運作有比較清晰的認(rèn)識,不然排錯是一個很大的障礙;
項目說明:
在上K8S之前各種計劃任務(wù),比如,定時備份,定時重啟,定時檢索日志發(fā)送郵件等等都是通過一臺CentOS虛擬機(jī)的crontab來執(zhí)行各種shell,python腳本來完成。
但是虛擬機(jī)也有因為停電,硬件故障導(dǎo)致系統(tǒng)崩潰的風(fēng)險,所以,將這臺虛擬機(jī)容器化并遷移至K8S內(nèi)就健壯多了。
只要鏡像在,并且K8S編排腳本在,那么一切都在,并且健康的運行,非??煽俊?/p>
最重要的,我需要將所有的管理腳本外置于外部NAS存儲,并且掛載到K8S容器內(nèi),來達(dá)到數(shù)據(jù)持久化和代碼集中化管理,
并且,我不需要登入容器,只需要在外部修改好crontab文件,刪除掉當(dāng)前pod,K8S會很乖的重新起一個容器,順便加載了最新的crontab配置,巧妙利用K8S的特性來簡化管理。
不廢話,上干貨,首先,需要把一切需要的東西封裝到centos鏡像中:
1,我需要在容器內(nèi)執(zhí)行python腳本,而且需要3以上的版本;
2,我需要shell執(zhí)行遠(yuǎn)程ssh,那么需要安裝sshpass;(當(dāng)然你也可以選擇其他方式)
3,我需要expect工具免交互腳本,那么需要安裝expect;
4, 因為容器默認(rèn)是沒有安裝crontab的,要做任務(wù)計劃怎么能少了這個;
5,最重要的是安裝supervisor進(jìn)程守護(hù)管理工具,以免K8S的容器循環(huán)重啟;(原理不作解釋)
可能有一些不必要的插件,自己去優(yōu)化吧,這里達(dá)到實驗?zāi)康募纯?,沒有做鏡像大小優(yōu)化,
貼上Dockerfile源碼:
FROM??????centos:centos7.6.1810 MAINTAINER?gavin.guo<379783667@qq.com> ENV?TZ?"Asia/Shanghai" ENV?TERM?xterm ENV?LANG?en_US.utf8 ADD?aliyun-mirror.repo?/etc/yum.repos.d/CentOS-Base.repo ADD?aliyun-epel.repo?/etc/yum.repos.d/epel.repo RUN?yum?install?-y?zlib-devel?bzip2-devel?openssl-devel?ncurses-devel?sqlite-devel?readline-devel?tk-devel?gdbm-devel?db4-devel?libpcap -devel?xz-devel?&&?\ ????yum?install?-y?curl?wget?tar?bzip2?unzip?vim-enhanced?passwd??yum-utils?hostname?net-tools?rsync?man?&&?\ ????yum?install?-y?gcc?gcc-c++?git?make?automake?cmake?patch?logrotate?python-devel?libpng-devel?libjpeg-devel?&&?\ ????yum?clean?all ADD?Python-3.6.2.tgz??/root RUN?cd?/root/Python-3.6.2/??&&?\ ????mkdir?/usr/local/python3?;?./configure?--prefix=/usr/local/python3?&&?\ ????make?&&?make?install?&&?\ ????ln?-s?/usr/local/python3/bin/python3?/usr/bin/python3?;?ln?-s?/usr/local/python3/bin/pip3?/usr/bin/pip3?&&?\ ????cd?/root?;?rm?-rf?Python-3.6.2?&&?\ ????yum?-y?install?net-snmp-utils?crontabs?sshpass?expect?;?sed?-i?'s/required???pam_loginuid.so/sufficient???pam_loginuid.so/'?/etc/pam.d/crond?&&?\ ????pip3?install?supervisor?&&?\ ????mkdir?-p?/etc/supervisor.conf.d?&&?\ ????mkdir?-p?/var/log/supervisor COPY?supervisord.conf?/etc/supervisord.conf COPY?supervisor_crontab.conf?/etc/supervisor.conf.d/crontab.conf EXPOSE?22 COPY?start.sh?/root/start.sh RUN?chmod?+x?/root/start.sh ENTRYPOINT?["/root/start.sh"]
Dockefile 同目錄下,需要放置python3.6的二進(jìn)制源碼安裝包,防止版本漂移和加快構(gòu)建速度,和啟動腳本start.sh
#!?/bin/bash cp?/root/script/root?-f??/var/spool/cron/ /usr/local/python3/bin/supervisord?-n?-c?/etc/supervisord.conf
這個小小的腳本一行都不能少,少了第一行,那么K8S在啟動Pod的時候會報錯,因為找不到shell的執(zhí)行路徑;
第二行用來每次啟動新的Pod的時候加載最新的crontab文件,而不需要操作pod容器;
第三行,啟動supervisord,保證pod健康運行而不退出;
crontab的supervisord的啟動配置文件貼一下:
[program:crond] directory=/ command=/usr/sbin/crond?-n user=root autostart=true autorestart=true stdout_logfile=/var/log/supervisor/%(program_name)s.log stderr_logfile=/var/log/supervisor/%(program_name)s.log
使用命令開始封裝鏡像:
docker?build?-t??gavin/mycron:v1?.
封裝完成后,開始編寫K8S編排文件:
創(chuàng)建一個mycron.yaml文件:
apiVersion:?v1 kind:?Pod metadata: ??name:?mycron spec: ??containers: ??-?name:?mycron ????image:?gavin/mycron:v1 ????ports: ????-?containerPort:?22 ????volumeMounts: ????-?name:?script ??????mountPath:?/root/script ??volumes: ??-?name:?script ????hostPath: ??????path:?/root/K8S_PV/script ??????type:?DirectoryOrCreate
代碼很簡單,但我們重點看主機(jī)磁盤卷的掛載,這里雖然用的是hostPath,但是/root/K8S_PV/Script并不是普通的本地路徑,而是我掛載到本地的NAS共享文件夾:
注意:
使用命令將配置好的NAS共享文件掛載到K8S宿主機(jī)內(nèi),并用hostPath的方式將其映射到master節(jié)點的Pod內(nèi),這個是官方教程和權(quán)威指南里面都沒有說過的,不是親身實驗是無從得知的,但理論和實際上都是可行的;
講操作:
掛載NAS共享文件夾:
mount?-o?username=XXX,password=XXX?//NAS服務(wù)器的IP/K8S_PV???/root/K8S_PV
K8S允許掛載NFS的PV,但是遇上NAS是有權(quán)限驗證的,有權(quán)限驗證的NFS如何引入PV,? 官方和網(wǎng)上都沒有資料,這也是我說它為什么需要改進(jìn)的,不能都要求用戶去單獨搭一個NFS服務(wù)器吧!
而且對于小型存儲需求來講,PV和PVI這一套顯得繁瑣,沒有本地直接掛載然后hostPath簡單粗暴好用。
掛載完畢后,然后在K8S_PV里面新建一個目錄script,將所有腳本丟進(jìn)去即可;
將mycron.yaml文件復(fù)制到目錄/etc/kubernetes/manifests/, K8S會自動啟動靜態(tài)Pod;
那么我們進(jìn)入容器內(nèi)看看是否一切正常:
kubectl?exec?-it?mycron-master??/bin/bash 運行crontab?-e
發(fā)現(xiàn)定時任務(wù)配置已經(jīng)順利同步:
并且腳本路徑順利加載至pod:
以后我們需要修改定時任務(wù)或者腳本,只需要在NAS服務(wù)器上修改下文件,刪除一下Pod即可,非常快捷方便,并且做到高可用,高可靠,集中化管理。
◆★◆★◆排錯◆★◆★◆
在我后面修改了root賬戶下的crontab的配置文件,在K8S里面刪除這個pod,異想天開以為美好的事情會按照預(yù)期的發(fā)生,卻發(fā)現(xiàn)問題來了,crontab并沒有更新到容器內(nèi),反復(fù)試了多次依然如故。
分析:
我們知道靜態(tài)Pod是不受kubelet直接干預(yù)的特殊pod,K8S內(nèi)置一套檢查和恢復(fù)機(jī)制去完成它,刪除k8s內(nèi)創(chuàng)建的靜態(tài)Pod實例(我們目的是為了得到新的更新實例)有三種途徑,:
1,釜底抽薪,直接干掉或者移除/etc/kubernetes/manifests/內(nèi)的yaml編排文件,K8S會自我銷毀創(chuàng)建的靜態(tài)Pod,完畢再復(fù)制yaml文件回去,它又將自我重建;
2,在K8S-dashboard的web頁面操作刪除:
3,使用命令刪除:
目前第一種過于繁瑣,我采取的是第二種和第三種方式,發(fā)現(xiàn)沒有效果,只要當(dāng)?shù)谝环N方式容器內(nèi)才更新成功,何故?
好,我們來使用docker命令來查看每種刪除方式后的容器發(fā)生了什么變化,來找出問題在哪里:
我們發(fā)現(xiàn)第二種和第三種方法對容器沒有變化,因為它的容器創(chuàng)建時間和容器名稱沒有發(fā)生改變,你大爺還是你大爺。
當(dāng)使用第一種方式刪除的時候,奇跡出現(xiàn)了,該發(fā)生的都發(fā)生了,我們可以看到雖然容器注冊名沒有發(fā)生改變,但是創(chuàng)建時間改變了,它已經(jīng)不是從前的它了:
◆★◆★◆思考◆★◆★◆
為什么一定要去撤銷yaml編排文件,容器才能得到徹底銷毀呢?個人覺得,這要從K8S的機(jī)制說起,我們知道,K8S系統(tǒng)在容器的基礎(chǔ)上又抽象出一個沙箱概念:Pod,這個豆莢是我們在k8S系統(tǒng)內(nèi)所能操作的最小單位,但實際上容器實例才是最小顆粒單位。我們刪除pod,并不代表刪除了容器,恰恰相反,由于K8S的各種檢查和恢復(fù),銷毀機(jī)制,如果不銷毀yaml文件,那么K8S檢測到容器依然是活躍并健康的,根本不會銷毀和置換一個新的容器給你,而是重新套上一個pod包裝箱,事實上容器連停止和重啟的動作都不會進(jìn)行。這也是為什么刪除pod和啟動新的pod為什么速度那么快,因為K8S只是換了個Pod而沒有換容器。不要感覺被騙了,因為K8S覺得沒有那個必要,這就是它自作聰明之處。
知道這個道理后,那么我們知道如何去應(yīng)對,有幾種方式去重建容器:
1,K8S只有當(dāng)容器出現(xiàn)崩潰或者說不健康了,才會銷毀和重建容器(這種是自然發(fā)生,不可控)
2,銷毀或者說改動yaml編排文件,那么意味著新的部署,容器才能得以徹底銷毀重建;
3,使用docker rm -f 容器名,強(qiáng)制刪除容器,那么也會得到新的容器;
4,如果你能分析K8S源碼,能欺騙健康檢查機(jī)制去銷毀和重建容器也是可以的,但是一般人做不到;
個人認(rèn)為非常經(jīng)典的一個實驗,實踐了以下內(nèi)容:
1,靜態(tài)Pod的創(chuàng)建;
2,hostPath存儲的掛載,外部NAS存儲的巧妙引用;
3,測試了靜態(tài)Pod的特性;
4,Docker鏡像的封裝, 關(guān)鍵點還在于入口腳本的設(shè)置;
5,了解了pod和容器之間的關(guān)系和行為;
???? 一般來說,通常Dockerfile的最后一行為:
?ENTRYPOINT?["/usr/local/python3/bin/supervisord"?,"-n","-c"?"/etc/supervisord.conf"]
?這個是supervisord的啟動進(jìn)程命令,但是很多時候并不是這么簡單,可能在容器啟動的時候有很多初始化的復(fù)雜操作,那么全部放入一個start腳本里面去執(zhí)行,并且保證supervisord在最后執(zhí)行即可;
就像本例,我需要在啟動進(jìn)程前將掛載存儲路徑里面的配置文件更新到相應(yīng)的目錄,來達(dá)到重起容器即更新配置的目的,那么非腳本不可。
學(xué)會了嗎?試試看,打造你的私有鏡像并且使用啟動腳本來更新容器,可能更有妙用。
免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進(jìn)行舉報,并提供相關(guān)證據(jù),一經(jīng)查實,將立刻刪除涉嫌侵權(quán)內(nèi)容。