1 應(yīng)用流程安全
1.1 鏡像安全
1.1.1 構(gòu)建原則
學(xué)習(xí)目標(biāo)
這一節(jié),我們從 基礎(chǔ)知識(shí)、原則解讀、小結(jié) 三個(gè)方面來學(xué)習(xí)。
基礎(chǔ)知識(shí)
k8s平臺(tái)使用業(yè)務(wù)環(huán)境
生產(chǎn)中使用k8s操作業(yè)務(wù)環(huán)境的基本原則
1 保證容器應(yīng)用是正常運(yùn)行的
2 創(chuàng)建專屬的資源對(duì)象文件
3 基于資源對(duì)象文件創(chuàng)建業(yè)務(wù)環(huán)境
4 測試業(yè)務(wù)環(huán)境,如果不滿足則進(jìn)行后續(xù)動(dòng)作,否則不做任何改變
- 調(diào)整容器的鏡像文件
- 重新調(diào)整資源對(duì)象文件
- 基于新資源對(duì)象文件創(chuàng)建并測試新的環(huán)境
需求
鏡像是容器運(yùn)行的基礎(chǔ),容器引擎服務(wù)可使用不同的鏡像啟動(dòng)相應(yīng)的容器。在容器出現(xiàn)錯(cuò)誤后,能迅速通過 刪除容器、啟動(dòng)新的容器來恢復(fù)服務(wù),這都需要以容器鏡像作為支撐技術(shù)。
而Kubernetes作為一種容器任務(wù)編排平臺(tái),它對(duì)于應(yīng)用的管理都是基于鏡像文件創(chuàng)建出來的。
鏡像的使用流程
Docker鏡像加載
對(duì)于Docker鏡像文件整體來說,它是一個(gè)只讀的文件,但是根據(jù)我們對(duì)構(gòu)建過程的理解,我們發(fā)現(xiàn),對(duì)于Docker鏡像還有很多更深層的東西:
1 鏡像文件是基于分層機(jī)制實(shí)現(xiàn)的
- Docker 鏡像的最底層是 bootfs(boot file system), bootfs主要包含 bootloader 和 Kernel , bootloader加載kernel信息到內(nèi)存中,然后內(nèi)存使用權(quán)交給內(nèi)核,接著內(nèi)核卸載bootfs。
- 在 bootfs之上是rootfs(root file system),它包含了不同Linux發(fā)行版(Ubuntu|Centos)文件系統(tǒng)中的標(biāo)準(zhǔn)目錄和文件,比如/dev,/proc,/bin,/etc等。它由內(nèi)核掛載為只讀模式,而后通過"聯(lián)合掛載"在其基礎(chǔ)上掛載一個(gè)"可寫層"。
2 下層鏡像是上層鏡像的父鏡像,最底層的稱為基礎(chǔ)鏡像
- 最上層的是可寫的,其他各層都是只讀的。
總的來說,鏡像文件包含運(yùn)行某個(gè)應(yīng)用軟件所需的所有內(nèi)容,包括代碼、運(yùn)行時(shí)、庫、環(huán)境變量和配置文件。
UnionFS
UnionFS(聯(lián)合文件系統(tǒng)):Union文件系統(tǒng)是一種分層、輕量級(jí)并且高性能的文件系統(tǒng),它支持對(duì)文件系統(tǒng)的修改作為一次提交來一層層的疊加,同時(shí)可以將存在不同物理位置的不同目錄掛載到同一個(gè)虛擬文件系統(tǒng)下,從外面看起來,只能看到一個(gè)包含所有底層的文件和目錄的文件系統(tǒng)。UnionFS可以把只讀和可讀寫文件系統(tǒng)合并在一起,具有寫時(shí)復(fù)制功能,允許只讀文件系統(tǒng)的修改可以保存到可寫文件系統(tǒng)當(dāng)中。
Union文件系統(tǒng)是 Docker 鏡像的基礎(chǔ)。鏡像可以通過分層來進(jìn)行繼承,基于基礎(chǔ)鏡像(沒有父鏡像),可以制作各種具體的應(yīng)用鏡像。
Docker鏡像使用分層最大的好處就是 共享資源。許多鏡像基于相同的base鏡像構(gòu)建而來,宿主機(jī)只需在磁盤上保存一份base鏡像,同時(shí)內(nèi)存中也只需加載一份base鏡像,就可以為所有容器服務(wù)了,而且鏡像的每一層都可以被共享。
原則解讀
構(gòu)建樣式
我們將中間只讀的 rootfs 的集合稱為 Docker 鏡像,Docker 鏡像構(gòu)建時(shí),會(huì)一層層構(gòu)建,前一層是后一層的基礎(chǔ)。每一層構(gòu)建完就不會(huì)再發(fā)生改變,后一層上的任何改變只發(fā)生在自己這一層。UnionFS 使得鏡像的復(fù)用、定制變得更為容易。甚至可以用之前構(gòu)建好的鏡像作為基礎(chǔ)層,然后進(jìn)一步添加新的層,以定制自己所需的內(nèi)容,構(gòu)建新的鏡像。
當(dāng)用docker run啟動(dòng)這個(gè)容器時(shí),實(shí)際上在鏡像的頂部添加了一個(gè)新的可寫層。這個(gè)可寫層也叫容器層。容器啟動(dòng)后,其內(nèi)的應(yīng)用所有對(duì)容器的改動(dòng),文件的增刪改操作都只會(huì)發(fā)生在容器層中,根據(jù)容器鏡像的寫時(shí)拷貝(Copy-on-Write)技術(shù),某個(gè)容器對(duì)基礎(chǔ)鏡像的修改會(huì)被限制在單個(gè)容器內(nèi),對(duì)容器層下面的所有只讀鏡像層沒有影響。
構(gòu)建原則
1、鏡像最小化原則;需要選擇最精簡的基礎(chǔ)鏡像、清理鏡像構(gòu)建的中間產(chǎn)物、減少鏡像的層數(shù)。
2、構(gòu)建速度最快化原則;充分利用鏡像構(gòu)建緩存,再利用構(gòu)建的緩存來加快鏡像構(gòu)建速度。
3、注意優(yōu)化網(wǎng)絡(luò)請(qǐng)求。
實(shí)踐原則
鏡像構(gòu)建實(shí)踐的最佳實(shí)踐原則
1 按照項(xiàng)目功能定制鏡像構(gòu)建目錄結(jié)構(gòu)
2 按照角色定制不同鏡像
3 基于嵌套方式分層構(gòu)建鏡像
分層效果
功能效果
小結(jié)
1.1.2 Dockerfile實(shí)踐
學(xué)習(xí)目標(biāo)
這一節(jié),我們從 基礎(chǔ)知識(shí)、簡單實(shí)踐、小結(jié) 三個(gè)方面來學(xué)習(xí)。
基礎(chǔ)知識(shí)
鏡像構(gòu)建過程
1)從基礎(chǔ)鏡像1創(chuàng)建一個(gè)容器A
2)遇到一條Dockerfile指令,都對(duì)容器A做一次修改操作
3)執(zhí)行完一條指令,提交生成一個(gè)新鏡像2
4)再基于新的鏡像2運(yùn)行一個(gè)容器B
5)遇到一條Dockerfile指令,都對(duì)容器B做一次修改操作
6)執(zhí)行完一條指令,提交生成一個(gè)新鏡像3
...
Dockerfile
在工作中,我們經(jīng)常會(huì)因?yàn)闃I(yè)務(wù)需求,而定制各種各樣的Doker鏡像,由于Dockerfile的便捷性,所以我們經(jīng)常會(huì)基于Dockerfile來創(chuàng)建我們業(yè)務(wù)場景中所需要的各種鏡像。
根據(jù)我自己的工作經(jīng)驗(yàn),我們?cè)谑褂肈ockerfile的過程中,一般只需要關(guān)注三個(gè)方面即可:
1 Dockerfile在使用的過程中,構(gòu)建的指令越少越好,能合并的就合并。
2 基于Docker鏡像的分層特性,我們最好按照項(xiàng)目的架構(gòu)級(jí)別來定制不同層的鏡像
3 Dockerfile構(gòu)建的過程中,功能越簡單越好,最好只有一個(gè)
簡單實(shí)踐
準(zhǔn)備工作
創(chuàng)建Dockerfile專用目錄
mkdir /docker/images/ssh -p
cd /docker/images/ssh
創(chuàng)建秘鑰認(rèn)證
ssh-keygen -t rsa
cat ~/.ssh/id_rsa.pub > authorized_keys
最初的Dockerfile
# 構(gòu)建一個(gè)基于ubuntu的ssh定制鏡像
# 基礎(chǔ)鏡像
FROM ubuntu
# 鏡像作者
MAINTAINER shuji@superopsmsb.com
# 安裝 ssh 服務(wù)
RUN apt-get update
RUN apt-get install -y openssh-server curl vim net-tools git dnsutils jq
RUN mkdir -p /var/run/sshd
RUN mkdir -p /root/.ssh
RUN sed -i "s/.*pam_loginuid.so/#&/" /etc/pam.d/sshd
RUN apt-get autoclean
RUN apt-get clean
RUN apt-get autoremove
# 復(fù)制配置文件到相應(yīng)位置,并賦予腳本可執(zhí)行權(quán)限
ADD authorized_keys /root/.ssh/authorized_keys
# 對(duì)外端口
EXPOSE 22
# 啟動(dòng)ssh
CMD ["/usr/sbin/sshd","-D"]
優(yōu)化后Dockerfile
# 構(gòu)建一個(gè)基于ubuntu的ssh定制鏡像
# 基礎(chǔ)鏡像
FROM ubuntu
# 鏡像作者
MAINTAINER shuji@superopsmsb.com
# 安裝 ssh 服務(wù)
RUN apt-get update && apt-get install -y openssh-server curl vim net-tools git dnsutils jq && mkdir -p /var/run/sshd && mkdir -p /root/.ssh && sed -i "s/.*pam_loginuid.so/#&/" /etc/pam.d/sshd && apt-get autoclean && apt-get clean && apt-get autoremove
# 復(fù)制配置文件到相應(yīng)位置,并賦予腳本可執(zhí)行權(quán)限
ADD authorized_keys /root/.ssh/authorized_keys
# 對(duì)外端口
EXPOSE 22
# 啟動(dòng)ssh
CMD ["/usr/sbin/sshd","-D"]
小結(jié)
1.1.3 構(gòu)建進(jìn)階
學(xué)習(xí)目標(biāo)
這一節(jié),我們從 多階段構(gòu)建、觸發(fā)器、小結(jié) 三個(gè)方面來學(xué)習(xí)。
多階段構(gòu)建
需求
對(duì)于一些大型微服務(wù)項(xiàng)目的研發(fā)來說,研發(fā)階段會(huì)是多個(gè)團(tuán)隊(duì)來進(jìn)行項(xiàng)目的研發(fā),如果每個(gè)研發(fā)人員都是基于使用Docker容器來做項(xiàng)目的部署,這個(gè)時(shí)候后,因?yàn)閹讉€(gè)項(xiàng)目組件可能包含公用文件,從而導(dǎo)致大量的Docker鏡像使用的重復(fù)冗余資源,所以我們有必要為團(tuán)隊(duì)的提供一個(gè)更加豐富的Base鏡像,以滿足所有研發(fā)人員的需求的前提下,極大的節(jié)省資源的消耗。
多階段構(gòu)建
舊版本的Docker軟件僅僅支持1個(gè)FROM,從1.17版本之后開始支持多階段構(gòu)建的能力 -- 也就是說多個(gè)FROM指令,也就是說我們可以使用多個(gè)base image和中間層image來構(gòu)建鏡像層。這里主要用到的指令是 FROM 和 AS。也就是說,它可以讓我在前一個(gè)image層上創(chuàng)建多個(gè)image層,
示例:
FROM image as layer_name
同時(shí)Dockerfile在構(gòu)建的時(shí)候,可以借助于COPY 指令的 --from 參數(shù),docker鏡像中直接獲取相關(guān)文件:
COPY --from=0 /require/file /dest/
從前一個(gè)鏡像層中獲取文件到當(dāng)前鏡像層面指定位置
COPY --from=layer_name /require/file /dest/
從前指定鏡像層中獲取文件到當(dāng)前鏡像層面指定位置
COPY --from=docker.io/nginx /require/file /dest/
從前現(xiàn)有的鏡像中獲取文件到當(dāng)前鏡像層面指定位置
構(gòu)建實(shí)踐
# 基于基礎(chǔ)鏡像構(gòu)建普通功能軟件,將其作為ubuntu環(huán)境使用
FROM python:3 AS base
MAINTAINER shuji@superopsmsb.com
RUN apt-get update && apt-get install -y vim
# 創(chuàng)建一個(gè)專屬的鏡像層來安裝Python依賴軟件
FROM base AS requirements
RUN pip3 install django==3.1.2
# 使用Python鏡像層創(chuàng)建專屬的項(xiàng)目環(huán)境
FROM requirements as django
ADD blog /data/code/blog
ADD scripts/startup.sh /data/scripts/startup.sh
EXPOSE 8000
# 定制容器的啟動(dòng)命令
CMD ["/bin/bash", "/data/scripts/startup.sh"]
構(gòu)建鏡像
docker build -t simple-test .
測試效果
docker run -d --name django-test -p 666:8000 simple-test
curl localhost:666
docker rm -f django-test
結(jié)果顯示:
我們使用FROM和AS指令組合幫助我們?yōu)樗许?xiàng)目創(chuàng)建唯一的層次結(jié)構(gòu)。從而讓我們一次完成所有任務(wù)docker文件,這樣不僅簡化了版本管理, 還可以更好地了解整個(gè)項(xiàng)目, 尤其是通過消除在不同鏡像中的相同文件,并實(shí)現(xiàn)了最終鏡像文件容量縮容。
觸發(fā)器
需求
工作中我們?cè)谧龃罅緿ocker鏡像的時(shí)候,因?yàn)榉謱拥膬?yōu)勢,我們一般先把基礎(chǔ)鏡像做出來,然后在它的基礎(chǔ)上進(jìn)行上層鏡像的構(gòu)建。結(jié)合我們剛才的實(shí)踐,如果將多個(gè)團(tuán)隊(duì)需求的文件都進(jìn)行初始化構(gòu)建的話,導(dǎo)致基礎(chǔ)鏡像容量太大,而且很多功能對(duì)于上層鏡像無用。
所以我們就可以借助于觸發(fā)器的能力,提前將上層鏡像需要的環(huán)境定制出來,但是不執(zhí)行,只有當(dāng)上層鏡像需要的時(shí)候,我們?cè)龠M(jìn)行針對(duì)性環(huán)境的構(gòu)建,這樣可以讓我們的容量更加高效。
指令
Dockerfile 用于 build 鏡像文件,A鏡像和B鏡像分別需要不同的Dockerfile文件來進(jìn)行構(gòu)建,如果B鏡像依賴于A鏡像,我們可以借助于ONBUILD指令,在構(gòu)建B鏡像的時(shí)候,自動(dòng)觸發(fā)A鏡像內(nèi)部的構(gòu)建步驟,當(dāng)A鏡像構(gòu)建完畢后,再開始B鏡像構(gòu)建。
構(gòu)建實(shí)踐
定制兩個(gè)目錄
mkdir father child
定制father項(xiàng)目的Dockerfile文件
FROM python:3
MAINTAINER father-image
RUN echo "father image"
ONBUILD RUN echo "child image"
定制child項(xiàng)目的Dockerfile文件
FROM father-image
MAINTAINER child-image
RUN echo "this is my cmd"
構(gòu)建父級(jí)鏡像
# docker build -t father-image father/
Sending build context to Docker daemon 2.048kB
Step 1/4 : FROM python:3
---> f05c8762fe15
Step 2/4 : MAINTAINER father-image
---> Running in 90bb60b129c3
Removing intermediate container 90bb60b129c3
---> 39be4d0f1254
Step 3/4 : RUN echo "father image"
---> Running in 1ec695c98bfb
father image
Removing intermediate container 1ec695c98bfb
---> dcde17f6a0dc
Step 4/4 : ONBUILD RUN echo "child image"
---> Running in c41f441091a7
Removing intermediate container c41f441091a7 # 結(jié)果顯示:命令沒有執(zhí)行
---> 5dcb262c76e6
Successfully built 5dcb262c76e6
Successfully tagged father-image:latest
構(gòu)建子鏡像
# docker build -t child-image child/
Sending build context to Docker daemon 2.048kB
Step 1/3 : FROM father-image
# Executing 1 build trigger
---> Running in 3e26148923b1
child image # 結(jié)果顯示:子鏡像構(gòu)建的時(shí)候,自動(dòng)執(zhí)行父鏡像的
Removing intermediate container 3e26148923b1
---> ccbcc3569240
Step 2/3 : MAINTAINER child-image
---> Running in a622eba55824
Removing intermediate container a622eba55824
---> bbaee5a9ea61
Step 3/3 : RUN echo "this is my cmd"
---> Running in ee716a0392aa
this is my cmd
Removing intermediate container ee716a0392aa
---> 229bcbf7c314
Successfully built 229bcbf7c314
Successfully tagged child-image:latest
小結(jié)
1.1.4 鏡像檢測
學(xué)習(xí)目標(biāo)
這一節(jié),我們從 基礎(chǔ)知識(shí)、簡單實(shí)踐、小結(jié) 三個(gè)方面來學(xué)習(xí)。
基礎(chǔ)知識(shí)
需求
在基于kubernetes平臺(tái)上的云原生應(yīng)用,基本上都是基于Docker鏡像的方式來運(yùn)行起來的,如果鏡像的來源就是有問題的,那么我們建立該環(huán)境上的應(yīng)用就會(huì)存在所謂0day的現(xiàn)象。雖然可以通過Dockerfile的方式來控制鏡像的構(gòu)建過程,但是這只是我們能夠控制的一部分,還有大量第三方應(yīng)用的鏡像我們無法進(jìn)行強(qiáng)有力的安全控制,如果第三方的平臺(tái)鏡像存在安全漏洞,我們是無法處理的。
在互聯(lián)網(wǎng)中有很多組織和社區(qū),為了實(shí)現(xiàn)某些場景的鏡像安全,自發(fā)或者其他因素影響下,開始從事鏡像安全漏洞的工作,他們研發(fā)了一系列鏡像級(jí)別的安全檢測工具,可以幫助我們進(jìn)行鏡像安全的控制,Trivy就是其中的佼佼者。
根據(jù)2022年<<sysdig云原生和使用報(bào)告>>的統(tǒng)計(jì)數(shù)據(jù)顯示:在生產(chǎn)環(huán)境中運(yùn)行的 85% 的鏡像至少包含一個(gè)可修補(bǔ)漏洞。此外,75% 的鏡像包含“高?!被颉皣?yán)重”的可修補(bǔ)漏洞。使用公共倉庫可能會(huì)帶來風(fēng)險(xiǎn),因?yàn)樗鼈兒苌贂?huì)被驗(yàn)證或檢查漏洞。但是在某些情況下,使用公共庫的便利性大于風(fēng)險(xiǎn),所以很多企業(yè)寧可面對(duì)風(fēng)險(xiǎn)也要用公共鏡像倉庫,并且將其作為最佳實(shí)踐。
trivy
Trivy是一個(gè)簡單而全面的漏洞/錯(cuò)誤配置掃描器,常被應(yīng)用于容器級(jí)別的業(yè)務(wù)安全場景。它主要的工作對(duì)象是 容器鏡像、文件系統(tǒng)、Git存儲(chǔ)庫等。
Trivy提供了大量用于檢測操作系統(tǒng)和程序語言的檢測工具包。它無論是部署還是使用都是非常簡單的。尤其是它對(duì)于其他平臺(tái)環(huán)境的集成非常輕松,常常應(yīng)用在以DevSecOps為代表的CI環(huán)境中。
官方網(wǎng)站:https://trivy.dev/
github: https://github.com/aquasecurity/trivy
最新版本: 0.32.1
軟件部署
Centos定制軟件源
# vim /etc/yum.repos.d/trivy.repo
[trivy]
name=Trivy repository
baseurl=https://aquasecurity.github.io/trivy-repo/rpm/releases/$releasever/$basearch/
gpgcheck=0
enabled=1
安裝軟件
yum makecache fast
yum -y install trivy
Ubuntu定制軟件源
apt-get install wget apt-transport-https gnupg lsb-release
wget -qO - https://aquasecurity.github.io/trivy-repo/deb/public.key | sudo apt-key add -
echo deb https://aquasecurity.github.io/trivy-repo/deb $(lsb_release -sc) main | sudo tee -a /etc/apt/sources.list.d/trivy.list
安裝軟件
apt-get update
apt-get -y install trivy
簡單實(shí)踐
命令解析
鏡像掃描
trivy image [YOUR_IMAGE_NAME]
漏洞檢測
trivy image --severity HIGH,CRITICAL [YOUR_IMAGE_NAME]
信息輸出
trivy image -f json -o results.json [YOUR_IMAGE_NAME]
倉庫檢測
trivy repo https://github.com/knqyf263/trivy-ci-test
容器內(nèi)檢測
curl -sfL https://raw.githubusercontent.com/aquasecurity/trivy/main/contrib/install.sh | sh -s -- -b /usr/local/bin
trivy fs /
簡單實(shí)踐
下載漏洞數(shù)據(jù)庫
trivy image --download-db-only
清理檢測緩存
trivy image --clear-cache
清理所有檢測數(shù)據(jù)庫
trivy image --reset
鏡像檢測
trivy image nginx:latest
注意
在title部分有該漏洞的一些信息https://avd.aquasec.com/nvd/2011/cve-2011-3374/
CVSS:Common Vulnerability Scoring System,即通用漏洞評(píng)分系統(tǒng),是一個(gè)行業(yè)公開標(biāo)準(zhǔn),其被設(shè)計(jì)用來評(píng)測漏洞的嚴(yán)重程度,并幫助確定所需反應(yīng)的緊急度和重要度。
指定檢測級(jí)別測試
trivy image --severity HIGH,CRITICAL nginx:latest
文件系統(tǒng)掃描
trivy fs /tmp/
倉庫掃描
trivy repo https://github.com/kubernetes/kubernetes.git
信息輸出
trivy image -f json -o results.json nginx:latest
harbor實(shí)踐
我們可以在harbor部署的時(shí)候,指定一個(gè)參數(shù)來啟用trivy能力。
./install.sh --with-trivy
這樣的話,我們的鏡像后面就會(huì)多出檢測的能力條,只需要我們配置檢測的規(guī)則,它就會(huì)自動(dòng)檢測
小結(jié)
1.1.5 倉庫升級(jí)
學(xué)習(xí)目標(biāo)
這一節(jié),我們從 基礎(chǔ)知識(shí)、簡單實(shí)踐、小結(jié) 三個(gè)方面來學(xué)習(xí)。
基礎(chǔ)知識(shí)
需求
對(duì)于docker鏡像倉庫來說,默認(rèn)使用的級(jí)別是https的,如果是非https的話,需要將其設(shè)置到一個(gè)非安全的倉庫范圍中,無論是對(duì)于containerd還是docker來說,這都不是一個(gè)很好的現(xiàn)象。
harbor本身是支持https能力的,我們只需要按部就班的實(shí)施就可以了。
修改harbor配置
修改配置 /data/server/harbor/harbor.yml
...
hostname: kubernetes-register.superopsmsb.com
http:
port: 80
https: 注釋ssl相關(guān)的部分
port: 443
certificate: /data/server/harbor/certs/kubernetes-register.superopsmsb.com/kubernetes-register.superopsmsb.com.crt
private_key: /data/server/harbor/certs/kubernetes-register.superopsmsb.com/kubernetes-register.superopsmsb.com.key
harbor_admin_password: 123456
data_volume: /data/harbor/data
準(zhǔn)備證書信息
生成CA證書私鑰
mkdir -p /data/server/harbor/ssl
cd /data/server/harbor/ssl
openssl genrsa -out ca.key 4096
生成CA證書
openssl req -x509 -new -nodes -sha512 -days 3650 \
-subj "/C=CN/ST=Beijing/L=Beijing/O=example/OU=Personal/CN=kubernetes-register.superopsmsb.com" \
-key ca.key \
-out ca.crt
注意:如果使用IP地址,需要在執(zhí)行以上命令前執(zhí)行以下操作:
cd /root
openssl rand -writerand .rnd
cd -
生成服務(wù)器證書私鑰
openssl genrsa -out kubernetes-register.superopsmsb.com.key 4096
生成證書簽名請(qǐng)求(CSR)
openssl req -sha512 -new \
-subj "/C=CN/ST=Beijing/L=Beijing/O=example/OU=Personal/CN=kubernetes-register.superopsmsb.com" \
-key kubernetes-register.superopsmsb.com.key \
-out kubernetes-register.superopsmsb.com.csr
生成一個(gè)x509 v3擴(kuò)展文件
無論您使用FQDN還是IP地址連接到Harbor主機(jī),都必須創(chuàng)建此文件,以便可以為您的Harbor主機(jī)生成符合主題備用名稱(SAN)和x509 v3的證書擴(kuò)展要求。替換DNS條目以反映您的域。
cat > v3.ext <<-EOF
authorityKeyIdentifier=keyid,issuer
basicConstraints=CA:FALSE
keyUsage = digitalSignature, nonRepudiation, keyEncipherment, dataEncipherment
extendedKeyUsage = serverAuth
subjectAltName = @alt_names
[alt_names]
DNS.1=kubernetes-register.superopsmsb.com
DNS.2=kubernetes-register.superopsmsb
DNS.3=kubernetes-register
EOF
使用該v3.ext文件為您的Harbor主機(jī)生成證書
openssl x509 -req -sha512 -days 3650 \
-extfile v3.ext \
-CA ca.crt -CAkey ca.key -CAcreateserial \
-in kubernetes-register.superopsmsb.com.csr \
-out kubernetes-register.superopsmsb.com.crt
提供證書給harbor和docker
將服務(wù)器證書和密鑰復(fù)制到Harbor主機(jī)上的certficates文件夾中
mkdir /data/server/harbor/certs/kubernetes-register.superopsmsb.com -p
cp kubernetes-register.superopsmsb.com.crt /data/server/harbor/certs/kubernetes-register.superopsmsb.com/
cp kubernetes-register.superopsmsb.com.key /data/server/harbor/certs/kubernetes-register.superopsmsb.com/
Docker守護(hù)程序?qū)?span id="n5n3t3z" class="token punctuation">.crt文件解釋為CA證書,并將.cert文件解釋為客戶端證書
openssl x509 -inform PEM -in kubernetes-register.superopsmsb.com.crt -out kubernetes-register.superopsmsb.com.cert
將服務(wù)器證書,密鑰和CA文件復(fù)制到Harbor主機(jī)上的Docker證書文件夾中。您必須首先創(chuàng)建適當(dāng)?shù)奈募A
mkdir -p /etc/docker/certs.d/kubernetes-register.superopsmsb.com/
cp kubernetes-register.superopsmsb.com.cert /etc/docker/certs.d/kubernetes-register.superopsmsb.com/
cp kubernetes-register.superopsmsb.com.key /etc/docker/certs.d/kubernetes-register.superopsmsb.com/
cp ca.crt /etc/docker/certs.d/kubernetes-register.superopsmsb.com/
注意:
如果將默認(rèn)nginx端口443映射到其他端口,請(qǐng)創(chuàng)建文件夾
/etc/docker/certs.d/yourdomain.com:port
或/etc/docker/certs.d/harbor_IP:port
這一步,對(duì)于新版的docker來說可以省略,即使不做這一步,影響不大。
重新啟動(dòng)Docker Engine
systemctl restart docker
harbor啟動(dòng)
進(jìn)入工作目錄
cd /data/server/harbor
重新應(yīng)用harbor配置
./prepare
./install.sh
檢查效果
docker-compose ps
簡單實(shí)踐
瀏覽器測試
修改windows的hosts文件 C:\Windows\System32\drivers\etc\hosts
10.0.0.20 kubernetes-register.superopsmsb.com
瀏覽器訪問 https://kubernetes-register.superopsmsb.com
這個(gè)時(shí)候,就會(huì)使用https方式了,如果需要讓瀏覽器不提示不安全,需要下載ca.crt到本地電腦安裝證書,在Windows環(huán)境下雙擊,安裝選擇受信任的根證書即可。
docker測試
刪除之前的docker認(rèn)證信息
rm -f /root/.docker/config.json
修改docker的私服配置 /etc/docker/daemon.json
"insecure-registries": ["kubernetes-register.superopsmsb.com"],
重啟docker服務(wù)
systemctl restart docker
測試效果
docker login https://kubernetes-register.superopsmsb.com
小結(jié)
1.1.6 高可用倉庫
學(xué)習(xí)目標(biāo)
這一節(jié),我們從 基礎(chǔ)知識(shí)、簡單實(shí)踐、小結(jié) 三個(gè)方面來學(xué)習(xí)。
基礎(chǔ)知識(shí)
需求
docker鏡像很重要,如果harbor倉庫存在單點(diǎn)現(xiàn)象的話,會(huì)導(dǎo)致所有鏡像無法在項(xiàng)目更新的時(shí)候進(jìn)行使用。所以,我們有必要對(duì)于harbor進(jìn)行高可用環(huán)境的定制。
Harbor 提供了很好的性能和安全, 它支持安裝在多個(gè) Registry 節(jié)點(diǎn)的鏡像資源復(fù)制,從而實(shí)現(xiàn)鏡像數(shù)據(jù)的一致性需求,比較適合于負(fù)載均衡、高可用、混合云和多云的場景。
方案
我們選擇的高可用方案是比較簡單的Harbor的雙主復(fù)制,搭建兩個(gè)Harbor節(jié)點(diǎn),節(jié)點(diǎn)之間能夠互相復(fù)制,然后通過haproxy代理Harbor節(jié)點(diǎn)提供外部訪問。
高可用節(jié)點(diǎn)
- 10.0.0.18|19
- keepalived+haproxy
harbor節(jié)點(diǎn)
- 10.0.0.20|21
- harbor
注意:
基于離線安裝包安裝的高可用方案需要保證以下文件在多個(gè)實(shí)例之間的一致性。同時(shí),由于這些文件是在各個(gè) Harbor 實(shí)例的安裝過程中默認(rèn)生成的,所以需要用戶手動(dòng)復(fù)制這些文件來保證一致性。
再一個(gè)Harbor主要是給公司內(nèi)部的開發(fā)人員使用的,由于業(yè)務(wù)使用量不是那么大,所以我們對(duì)于數(shù)據(jù)的一致性能夠保證分鐘級(jí)別也就可以了。
從節(jié)點(diǎn)部署
我們?cè)?10.0.0.21節(jié)點(diǎn)上部署harbor
參考 前一節(jié)的 倉庫升級(jí)內(nèi)容,關(guān)于證書相關(guān)的信息使用復(fù)制即可。
注意:
修改兩個(gè)harbor節(jié)點(diǎn)的hostname為 各自的ip地址
然后執(zhí)行 ./prepare 和 ./install.sh
如果需要啟動(dòng)時(shí)候,添加鏡像檢測功能,我們可以使用如下命令
./install.sh --with-trivy
keepalived配置
主keepalived配置
vrrp_instance VI_2 {
state MASTER
interface eth0
virtual_router_id 52
priority 100
advert_int 1
authentication {
auth_type PASS
auth_pass 1111
}
virtual_ipaddress {
10.0.0.201 dev eth0 label eth0:2
}
}
從keepalived配置
vrrp_instance VI_2 {
state BACKUP
interface eth0
virtual_router_id 52
priority 90
advert_int 1
authentication {
auth_type PASS
auth_pass 1111
}
virtual_ipaddress {
10.0.0.201 dev eth0 label eth0:2
}
}
重啟keepalived
systemctl restart keepalived
haproxy配置
修改haproxy的配置文件
listen harbor-80
bind 10.0.0.201:80
mode tcp
server harbor1 10.0.0.20:80 check inter 3s fall 3 rise 5
server harbor2 10.0.0.21:80 check inter 3s fall 3 rise 5
簡單實(shí)踐
配置主從
我們暫時(shí)訪問 http://10.0.0.20,登陸配置一個(gè)主從角色,將20相關(guān)的配置同步到21主機(jī)。點(diǎn)擊倉庫管理后,創(chuàng)建harbor從角色的信息:
目標(biāo)名:可以隨意定義
目標(biāo)url: 是從harbor節(jié)點(diǎn)的http鏈接地址
訪問id: admin
訪問密碼: 123456
注意:當(dāng)我們點(diǎn)擊確定后,就會(huì)出現(xiàn)圖中下面的倉庫列表樣式
點(diǎn)擊復(fù)制管理后,創(chuàng)建主從同步規(guī)則信息:
名稱和描述:自定義
資源過濾器:定制同步倉庫即可
目標(biāo)倉庫:從列表中選擇即可
觸發(fā)模式:選擇手動(dòng)模式
注意:當(dāng)我們點(diǎn)擊確定后,就會(huì)出現(xiàn)圖中下面的規(guī)則列表樣式
觸發(fā)復(fù)制并驗(yàn)證結(jié)果
1 勾選復(fù)制規(guī)則
2 點(diǎn)擊復(fù)制
3 確認(rèn)復(fù)制
4 查看復(fù)制任務(wù)
harbor2確認(rèn)復(fù)制效果
測試效果
對(duì)于master節(jié)點(diǎn)來說,我們只需要修改/etc/hosts 文件的主機(jī)名解析記錄即可
10.0.0.201 kubernetes-register.superopsmsb.com kubernetes-register
小結(jié)
1.1.7 鏡像策略
學(xué)習(xí)目標(biāo)
這一節(jié),我們從 基礎(chǔ)知識(shí)、簡單實(shí)踐、小結(jié) 三個(gè)方面來學(xué)習(xí)。
基礎(chǔ)知識(shí)
簡介
Kubernetes 對(duì) API 訪問提供了三種安全訪問控制措施:認(rèn)證、授權(quán)和 Admission Control。認(rèn)證解決用戶合法性的問題,授權(quán)解決用戶能做什么的問題,Admission Control 則是資源管理方面的作用。通過合規(guī)的用戶、合理的權(quán)限管理以及合適的準(zhǔn)入控制機(jī)制,能夠保證系統(tǒng)的安全可靠。
注意:關(guān)于插件化的準(zhǔn)入控制是1.9版本之后的能力,之前是需要編譯才可以實(shí)現(xiàn)。
k8s在很多方面都具備可擴(kuò)展性,比如通過cni實(shí)現(xiàn)多種網(wǎng)絡(luò)模型,通過csi實(shí)現(xiàn)多種存儲(chǔ)引擎,通過cri實(shí)現(xiàn)多種容器運(yùn)行時(shí)等等。而AdmissionWebhook就是準(zhǔn)入層面的一種可擴(kuò)展的手段。 它可以已默認(rèn)的Admission插件外,還有自定義的Admission插件,在api-server運(yùn)行時(shí)指定資源對(duì)象的時(shí)候,通過webhook進(jìn)行操作的請(qǐng)求控制。
Admission webhooks是基于HTTP回調(diào)機(jī)制運(yùn)行的,當(dāng)它接收Admission請(qǐng)求并對(duì)它們做一些事情的時(shí)候。Admission webhook對(duì)k8s的請(qǐng)求資源對(duì)象進(jìn)行深層次準(zhǔn)入控制,Admission webhook有兩種控制機(jī)制,MutatingAdmissionWebhook(對(duì)請(qǐng)求對(duì)象的修改)和ValidatingAdmissionWebhook(對(duì)請(qǐng)求的合法性進(jìn)行檢查)。
webhook解析
Admission Webhook 本質(zhì)是 api-server 的一個(gè) webhook 調(diào)用,下面是 api-server 的處理流程:
api-server 通過讀取 mutatingwebhookconfiguration 和 validatingwebhookconfiguration 的 CRD 文件的目標(biāo)地址,然后回調(diào)用戶自定義的服務(wù)。
參考資料:
https://kubernetes.io/docs/reference/access-authn-authz/extensible-admission-controllers/
部署注意事項(xiàng)
1 webhook 的本質(zhì)是 http server,因此,需要用代碼實(shí)現(xiàn)這么一個(gè) server,供 apiserver 調(diào)用
2 mutating webhook 和 validating webhook 沒有直接聯(lián)系,分別實(shí)現(xiàn)了不同的功能,本質(zhì)上說,如果修改/驗(yàn)證都需要,我們需要編寫兩個(gè) http server
3 編寫好的 webhook,建議使用 k8s deployment 部署,同時(shí)使用 service 來暴露能力
4 apiserver 通過MutatingWebhookConfiguration/ValidatingWebhookConfiguration 調(diào)用 webhook
5 apiserver 和 webhook 通信時(shí)的身份認(rèn)證和權(quán)限控制必須合理控制
案例需求
ImagePolicyWebhook是專門用于鏡像獲取的準(zhǔn)入控制器策略,它主要通過驗(yàn)證鏡像字段來判斷,資源在創(chuàng)建時(shí)候是否滿足創(chuàng)建的條件。我們可以在k8s的資源對(duì)象創(chuàng)建的時(shí)候,保證鏡像來源倉庫的可靠。但是該實(shí)踐需要配置涉及到的很多文檔內(nèi)容,包括認(rèn)證、配置、環(huán)境等。
參考資料:
https://kubernetes.io/docs/reference/access-authn-authz/admission-controllers/#configuration-file-format
操作步驟
1 準(zhǔn)備https專用的證書文件
2 構(gòu)建webhook服務(wù)器
3 kubernetes集成鏡像webhook服務(wù)
4 綜合測試
5 收尾動(dòng)作
簡單實(shí)踐
準(zhǔn)備https專用的證書文件
準(zhǔn)備證書工具環(huán)境
mkdir /data/kubernetes/process_secure/ ; cd /data/kubernetes/process_secure/
for i in cfssl cfssljson
do
wget https://github.com/cloudflare/cfssl/releases/download/v1.6.1/$i_1.6.1_linux_amd64
chmod +x $i_1.6.1_linux_amd64
cp $i_1.6.1_linux_amd64 /usr/local/bin/$i
done
準(zhǔn)備專用證書目錄
mkdir /data/kubernetes/process_secure/cert -p
cd /data/kubernetes/process_secure/cert/
準(zhǔn)備CA配置信息,參考 cfssl print-defaults config 命令
cat > ca-config.json <<EOF
{
"signing": {
"default": {
"expiry": "87600h"
},
"profiles": {
"kubernetes": {
"expiry": "87600h",
"usages": [
"signing",
"key encipherment",
"server auth",
"client auth"
]
}
}
}
}
EOF
準(zhǔn)備簽名請(qǐng)求信息參考 cfssl print-defaults csr 命令
cat > ca-csr.json <<EOF
{
"CN": "kubernetes",
"key": {
"algo": "rsa",
"size": 2048
},
"names": [
{
"C": "CN",
"L": "Beijing",
"ST": "Beijing"
}
]
}
EOF
準(zhǔn)備image專屬的webhook請(qǐng)求信息
cat > webhook-csr.json <<EOF
{
"CN": "webhook",
"hosts": [
"10.0.0.12",
"10.0.0.13",
"10.0.0.14",
"127.0.0.1"
],
"key": {
"algo": "rsa",
"size": 2048
},
"names": [
{
"C": "CN",
"L": "BeiJing",
"ST": "BeiJing"
}
]
}
EOF
準(zhǔn)備webhook和apiserver的認(rèn)證信息
cat > apiserver-client-csr.json <<EOF
{
"CN": "apiserver",
"hosts": [],
"key": {
"algo": "rsa",
"size": 2048
},
"names": [
{
"C": "CN",
"L": "BeiJing",
"ST": "BeiJing"
}
]
}
EOF
生成私鑰和證書
cfssl gencert -initca ca-csr.json | cfssljson -bare ca -
生成webhook證書
cfssl gencert -ca=ca.pem -ca-key=ca-key.pem -config=ca-config.json -profile=kubernetes webhook-csr.json | cfssljson -bare webhook
生成apiserver證書
cfssl gencert -ca=ca.pem -ca-key=ca-key.pem -config=ca-config.json -profile=kubernetes apiserver-client-csr.json | cfssljson -bare apiserver-client
構(gòu)建webhook服務(wù)器
定制鏡像專屬目錄結(jié)構(gòu)
mkdir /data/images/web/flask/conf
cd /data/images/web/flask
定制webhook的核心代碼(Flask) main.conf
from flask import Flask,request
import json
# 創(chuàng)建app應(yīng)用
app = Flask(__name__)
# 定制測試url
@app.route("/index")
def index():
return "flask web ok\n"
@app.route('/image_check', methods=['POST'])
def image_policy():
# 獲取用戶提交數(shù)據(jù)并進(jìn)行數(shù)據(jù)反序列化
post_data = request.get_data().decode()
print("--- POST數(shù)據(jù): {}".format(post_data))
data = json.loads(post_data)
# 定制容器鏡像格式的檢測規(guī)則 -- 必須攜帶標(biāo)簽
for container in data['spec']['containers']:
if ":" not in container['image'] or ":latest" in container['image']:
msg="鏡像格式檢測失敗! 鏡像名稱必須攜帶標(biāo)簽,同時(shí)禁用默認(rèn)標(biāo)簽."
allowed, reason = False, msg
break
else:
msg="鏡像格式檢測成功!"
allowed, reason = True, msg
print("--- 檢查結(jié)果: {}".format(reason))
# 定制返回信息
obj_api=data['apiVersion']
obj_kind=data['kind']
obj_image=data['spec']['containers'][0]['image']
result = {"apiVersion": obj_api, "kind": obj_kind, "image_name": obj_image , "status": {"allowed": allowed, "reason": reason}}
print("--- 響應(yīng)數(shù)據(jù): {}".format(result))
# 對(duì)響應(yīng)數(shù)據(jù)進(jìn)行序列化操作,ensure_ascii=False,表示返回信息包含中文
return json.dumps(result, ensure_ascii=False)
if __name__ == "__main__":
app.run(host="0.0.0.0", port=8080, ssl_context=('/data/server/image_check/webhook.pem', '/data/server/image_check/webhook-key.pem'))
定制專屬的Dockerfile文件
# 構(gòu)建一個(gè)基于flask的定制鏡像
# 基礎(chǔ)鏡像
FROM kubernetes-register.superopsmsb.com/superopsmsb/python
# 鏡像作者
MAINTAINER shuji@superopsmsb.com
# 拷貝文件
ADD conf/main.py /data/server/image_check/main.py
# 創(chuàng)建flask環(huán)境
RUN pip install flask && useradd python && chown -R python /data
# 暴露django端口
EXPOSE 8080
USER python
# 定制容器的啟動(dòng)命令
CMD ["python", "/data/server/image_check/main.py"]
注意:
這里使用普通用戶主要后期運(yùn)行時(shí)候的緩存信息及時(shí)顯示的原因
定制鏡像文件
docker build -t kubernetes-register.superopsmsb.com/superopsmsb/image-webhook:v0.1 .
在生成證書的節(jié)點(diǎn)上運(yùn)行鏡像文件
export cert_dir='/data/kubernetes/process_secure/cert/'
export cont_dir='/data/server/image_check'
docker run -d --name=image-webhook -u root -e PYTHONUNBUFFERED=1 -v $cert_dir/webhook.pem:$cont_dir/webhook.pem -v $cert_dir/webhook-key.pem:$cont_dir/webhook-key.pem -p 8080:8080 kubernetes-register.superopsmsb.com/superopsmsb/image-webhook:v0.1
注意:
-u root -e PYTHONUNBUFFERED=1 的作用是將請(qǐng)求相關(guān)的數(shù)據(jù)即時(shí)輸出
檢查效果
]# docker ps | grep image
77bf356ce83e kubernetes-register.superopsmsb.com/superopsmsb/image-webhook:v0.1 "python /data/server…" 9 seconds ago Up 9 seconds 0.0.0.0:8080->8080/tcp, :::8080->8080/tcp image-webhook
]# curl -k https://10.0.0.12:8080/index
flask web ok
結(jié)果顯示:
webhook服務(wù)器已經(jīng)部署完畢了
kubernetes集成鏡像webhook服務(wù)
檢查kubernetes集群是否啟用了準(zhǔn)入注冊(cè) API
]# kubectl api-versions |grep admission
admissionregistration.k8s.io/v1
查看kubernetes集群的準(zhǔn)入控制現(xiàn)狀
]# grep admission /etc/kubernetes/manifests/kube-apiserver.yaml
- --enable-admission-plugins=NodeRestriction
準(zhǔn)備專屬的目錄
mkdir -p /data/kubernetes/process_secure/api_conf
cd /data/kubernetes/process_secure/api_conf
準(zhǔn)備準(zhǔn)入控制的策略文件 admission_configuration.yaml
apiVersion: apiserver.config.k8s.io/v1
kind: AdmissionConfiguration
plugins:
- name: ImagePolicyWebhook
configuration:
imagePolicy:
# 指定image策略專屬連接和認(rèn)證文件
kubeConfigFile: /etc/kubernetes/image-policy/connect_webhook.yaml
allowTTL: 50
denyTTL: 50
retryBackoff: 500
defaultAllow: true
定制image策略專屬連接和認(rèn)證文件 connect_webhook.yaml
apiVersion: v1
kind: Config
clusters:
- cluster:
certificate-authority: /etc/kubernetes/image-policy/webhook.pem
# 定制
server: https://10.0.0.12:8080/image_check
name: webhook
contexts:
- context:
cluster: webhook
user: apiserver
name: webhook
current-context: webhook
preferences: {}
users:
- name: apiserver
user:
client-certificate: /etc/kubernetes/image-policy/apiserver-client.pem
client-key: /etc/kubernetes/image-policy/apiserver-client-key.pem
同步證書相關(guān)信息
cd /data/kubernetes/process_secure/cert/
for i in 12 13 14
do
ssh root@10.0.0.$i mkdir /etc/kubernetes/image-policy -p
scp webhook.pem apiserver-client.pem apiserver-client-key.pem root@10.0.0.$i:/etc/kubernetes/image-policy/
scp ../api_conf/{admission_configuration.yaml,connect_webhook.yaml} root@10.0.0.$i:/etc/kubernetes/image-policy/
done
修改kube-apiserver的配置文件與webhook集成
]# cp /etc/kubernetes/manifests/kube-apiserver.yaml{,.bak}
]# vim /etc/kubernetes/manifests/kube-apiserver.yaml
...
spec:
containers:
- command:
...
- --enable-admission-plugins=NodeRestriction,ImagePolicyWebhook
- --admission-control-config-file=/etc/kubernetes/image-policy/admission_configuration.yaml
...
volumeMounts:
...
- mountPath: /etc/kubernetes/image-policy
name: image-policy
readOnly: true
...
volumes:
- hostPath:
path: /etc/kubernetes/image-policy
type: DirectoryOrCreate
name: image-policy
...
配置解讀:
因?yàn)樯婕暗綄僮C書信息,所以需要hostPath方式進(jìn)行掛載操作
注意:
因?yàn)閗ube-apiserver是靜態(tài)pod,所以文件修改完畢后,就可以重啟了
綜合測試
在master節(jié)點(diǎn)上創(chuàng)建兩個(gè)deployment
kubectl create deployment web1 --image=kubernetes-register.superopsmsb.com/superopsmsb/nginx_web
kubectl create deployment web2 --image=kubernetes-register.superopsmsb.com/superopsmsb/nginx_web:v0.1
查看docker容器日志
docker logs -f image-webhook
環(huán)境收尾
刪除docker容器
docker rm -f image-webhook
清理deployment
kubectl delete deployments.apps web1 web2
還原kube-apiserver環(huán)境
for i in 12 13 14
do
ssh root@10.0.0.$i "mv /etc/kubernetes/manifests/kube-apiserver.yaml.bak /etc/kubernetes/manifests/kube-apiserver.yaml; rm -rf /etc/kubernetes/image-policy"
done
小結(jié)
1.2 配置管理
1.2.1 配置基礎(chǔ)
學(xué)習(xí)目標(biāo)
這一節(jié),我們從 基礎(chǔ)知識(shí)、資源清單、小結(jié) 三個(gè)方面來學(xué)習(xí)。
基礎(chǔ)知識(shí)
場景需求
生產(chǎn)中所有的應(yīng)用程序中,都涉及到配置文件,而配置文件經(jīng)常會(huì)有變更,比如數(shù)據(jù)庫連接、代碼版本號(hào)等,最典型場景就是:
項(xiàng)目經(jīng)歷開發(fā)環(huán)境、測試環(huán)境、預(yù)發(fā)布環(huán)境、線上環(huán)境才能完成發(fā)布,而每個(gè)環(huán)境都有定義其獨(dú)立的各種配置,這些配置手工操作很繁雜,所以好多大公司專門開發(fā)了專用配置管理中心,如百度的disconf等。
如何為容器化應(yīng)用提供配置信息?
1 啟動(dòng)容器時(shí),直接向應(yīng)用程序傳遞參數(shù),args: []
2 將定義好的配置文件焙進(jìn)鏡像之中;
3 通過環(huán)境變量向容器傳遞配置數(shù)據(jù):有個(gè)前提要求,應(yīng)用得支持從環(huán)境變量加載配置信息;
4 制作鏡像時(shí),使用entrypoint腳本來預(yù)處理變量,常見的做法就是使用非交互式編輯工具,將環(huán)境變量的值替換到應(yīng)用的配置文件中;
5 基于存儲(chǔ)卷向容器傳遞配置文件;
注意:
對(duì)于運(yùn)行容器中的配置改變,需要通過應(yīng)用程序重載相關(guān)配置
k8s的配置管理
kubernetes作為分布式容器調(diào)度平臺(tái),肯定會(huì)遇到同樣的問題,那么遇到這種問題后,我們不可能把資源刪除后,重新修改一下,然后在啟動(dòng)生成,這種方法就太繁瑣的。kubernetes提供了對(duì)pod中容器應(yīng)用的集中配置管理組件:ConfigMap、Secret、downwardAPI。通過這些組件來實(shí)現(xiàn)向pod中的容器中注入配置信息的機(jī)制。
資源清單
對(duì)象形式
在kubernetes中,資源對(duì)象有兩種形態(tài):
文件形態(tài) - 編寫出來的資源對(duì)象文件,有大量屬性組成。
對(duì)象形態(tài) - 基于資源對(duì)象文件初始化后出來的應(yīng)用對(duì)象。
對(duì)象初始化
資源對(duì)象初始化的方法主要有兩大類:
命令行工具(kubectl)
- 通過純粹的 "k8s命令及其選項(xiàng)" 來實(shí)現(xiàn)資源的創(chuàng)建
文件方式(API)
- 基于 "k8s命令 + 配置文件" 來實(shí)現(xiàn)資源的創(chuàng)建
- 基于 "聲明式的配置文件 + kubectl" 來實(shí)現(xiàn)資源的創(chuàng)建
使用資源對(duì)象
生產(chǎn)中使用k8s操作業(yè)務(wù)環(huán)境
1 保證容器應(yīng)用是正常運(yùn)行的
2 創(chuàng)建專屬的資源對(duì)象文件
3 基于資源對(duì)象文件創(chuàng)建業(yè)務(wù)環(huán)境
4 測試業(yè)務(wù)環(huán)境,如果不滿足則進(jìn)行后續(xù)動(dòng)作,否則不做任何改變
- 調(diào)整容器的鏡像文件
- 重新調(diào)整資源對(duì)象文件
- 基于新資源對(duì)象文件創(chuàng)建并測試新的環(huán)境
小結(jié)
1.2.2 YAML安全
學(xué)習(xí)目標(biāo)
這一節(jié),我們從 基礎(chǔ)知識(shí)、簡單實(shí)踐、小結(jié) 三個(gè)方面來學(xué)習(xí)。
基礎(chǔ)知識(shí)
需求
資源清單的最大的好處是,讓我們手工繁瑣操作流程變成一個(gè)一個(gè)的資源對(duì)象屬性,通過一個(gè)簡單的kubectl apply -f的方式,基于資源清單文件,實(shí)現(xiàn)業(yè)務(wù)環(huán)境的高度定制化、自動(dòng)化的操作。
大量的資源清單文件在大規(guī)模使用的時(shí)候,往往會(huì)因?yàn)閳鼍暗牟煌枰獙?duì)于同一個(gè)配置文件進(jìn)行修整。如果我們對(duì)于資源清單文件的目錄結(jié)構(gòu)、內(nèi)容樣式、適用場景非常了解的前提下,我們可以隨意的操作這些海量的資源清單文件。
但是我們知道,無論操作人員的能力多么的高,在面對(duì)海量數(shù)據(jù)的時(shí)候,總會(huì)有懈怠的時(shí)候,再加上yaml操作的高速度,一旦yaml文件出現(xiàn)安全問題,那會(huì)導(dǎo)致非常嚴(yán)重的業(yè)務(wù)環(huán)境問題。尤其是當(dāng)我們的能力不足以撐起yaml的優(yōu)勢的時(shí)候,導(dǎo)致的問題會(huì)更大。
所以,我們需要一種yaml文件的安全檢測機(jī)制,來保證yaml文件的安全性。這里的安全性主要體現(xiàn)在三個(gè)層面:
1 yaml文件自身的結(jié)構(gòu) - explain
2 yaml文件本身的安全 - kubesec
3 yaml文件項(xiàng)目的安全 - kustomize
安全機(jī)制
yaml文件自身的結(jié)構(gòu) - explain
所謂文件自身的結(jié)構(gòu),就是結(jié)合explain的資源對(duì)象屬性體系,然后根據(jù)業(yè)務(wù)場景的功能,選擇合適的對(duì)象屬性組合在一起即可。
- 它是kubeadm的一個(gè)子命令
yaml文件本身的安全 - kubesec
所謂文件本身的安全,是借助于專用的資源清單的安全配置評(píng)估的工具,根據(jù)生產(chǎn)的最佳實(shí)踐來驗(yàn)證資源清單文件的安全性并適時(shí)給出建議。Kubesec 可以作為 Web 服務(wù)或準(zhǔn)入控制器的樣式存在,接收 Kubernetes資源作為輸入,并進(jìn)程檢測分析,如果不合格,則禁止執(zhí)行。
- 參考地址:https://github.com/controlplaneio/kubesec
yaml文件項(xiàng)目的安全 - kustomize
所謂的文件項(xiàng)目的安全,是站在項(xiàng)目的角度,對(duì)所有場景中的資源清單文件,按照版本管理的方式進(jìn)行統(tǒng)一安全質(zhì)量控制。kustomize 是 kubernetes 原生的配置管理,以無模板方式來定制應(yīng)用的配置。通過功能復(fù)用、補(bǔ)丁等方式實(shí)現(xiàn)項(xiàng)目級(jí)別的yaml結(jié)構(gòu)安全。
- 參考地址;https://github.com/kubernetes-sigs/kustomize
簡單實(shí)踐
普通方式實(shí)踐kubeasc
Kubesec 可以作為二進(jìn)制包、容器鏡像、準(zhǔn)入控制器甚至 kubectl 插件安裝
cd /data/softs
wget https://github.com/controlplaneio/kubesec/releases/download/v2.12.0/kubesec_linux_amd64.tar.gz
部署kubesec
tar -xvf kubesec_linux_amd64.tar.gz
mv kubesec /usr/local/bin/
注意:
命令格式 kubesec scan /path/to/file.yaml
該命令在第一次檢測的時(shí)候,需要到github中獲取檢測文件
簡單實(shí)踐
]# kubesec scan /data/kubernetes/app_secure/01_kubernetes_application_secure_secret_data.yaml
[
{
"object": "Secret/superopsmsb-secret.default",
"valid": true,
"fileName": "/data/kubernetes/app_secure/01_kubernetes_application_secure_secret_data.yaml",
"message": "This resource kind is not supported by kubesec",
"score": 0,
"scoring": {}
}
]
]# kubesec scan /data/kubernetes/server_secure/01_kubernetes_server_secure_pod_test.yaml
[
{
"object": "Pod/nginx-web.default",
"valid": true,
"fileName": "/data/kubernetes/server_secure/01_kubernetes_server_secure_pod_test.yaml",
"message": "Passed with a score of 0 points",
"score": 0,
"scoring": {
"advise": [
{
"id": "ApparmorAny",
"selector": ".metadata .annotations .\"container.apparmor.security.beta.kubernetes.io/nginx\"",
"reason": "Well defined AppArmor policies may provide greater protection from unknown threats. WARNING: NOT PRODUCTION READY",
"points": 3
},
...
web服務(wù)方式
部署web服務(wù)方式1 - 依賴于gitlab的訪問獲取配置文件
kubesec http 8080 &
部署web服務(wù)方式2 - 容器內(nèi)部的自帶配置文件
docker pull kubesec/kubesec
docker run -d --name kubesec -p 8080:8080 kubesec/kubesec http 8080
使用方式
curl -sSX POST --data-binary @/path/to/file.yaml http://localhost:8080/scan
檢測方式
]# curl -sSX POST --data-binary @/data/kubernetes/server_secure/01_kubernetes_server_secure_pod_test.yaml http://10.0.0.12:8080/scan
[
{
"object": "Pod/nginx-web.default",
"valid": true,
"fileName": "API",
"message": "Passed with a score of 0 points",
"score": 0,
...
其他檢測方式
變種方式
docker run -i kubesec/kubesec scan /dev/stdin < /path/to/file.yaml
注意:
不推薦
webhook方式
參考資料: https://github.com/controlplaneio/kubesec-webhook
小結(jié)
1.2.3 kustomize
學(xué)習(xí)目標(biāo)
這一節(jié),我們從 基礎(chǔ)知識(shí)、應(yīng)用管理、小結(jié) 三個(gè)方面來學(xué)習(xí)。
基礎(chǔ)知識(shí)
實(shí)際現(xiàn)狀
根據(jù)我們之前對(duì) k8s的學(xué)習(xí),尤其是對(duì)各種狀態(tài)應(yīng)用的管理,比如statsfulset資源對(duì)象,redis集群、alertmanager部署等具體的實(shí)踐。當(dāng)我們需要在kubernetes環(huán)境運(yùn)行一個(gè)完整的業(yè)務(wù)項(xiàng)目的時(shí)候,我們需要根據(jù)業(yè)務(wù)需求提前梳理功能,進(jìn)而編寫大量的資源清單文件的YAML文件,通過這些文件來定制項(xiàng)目的預(yù)期目標(biāo)(副本,存儲(chǔ)空間,內(nèi)存和CPU等信息),我們就會(huì)遇到兩種問題:
1 一大堆的部署配置資源清單就是工作量非常大的一件事情。
對(duì)于這些復(fù)雜的應(yīng)用,在k8s之上,我們不建議使用獨(dú)立的部署清單來進(jìn)行配置
2 部署清單本身就有相當(dāng)大的限制約束,導(dǎo)致部署清單的任務(wù)量成倍增加
如果我們要部署多套prometheus集群,我們可以將所有的資源配置清單部署到不同的namespace中
- 這就導(dǎo)致,兩套不同的部署清單文件結(jié)構(gòu)
根據(jù)我們之前說的,持續(xù)交付的解決方案,為了實(shí)現(xiàn)成功的項(xiàng)目交付,我們要在不同的環(huán)境中測試該業(yè)務(wù)是否滿足我們的預(yù)期,所以項(xiàng)目交付的過程中,會(huì)涉及到多種環(huán)境。所以實(shí)際的情況中,我們需要通過復(fù)制+定制的方式,為不同的環(huán)境配置獨(dú)有的一套配置。
我們可以想象得到,一旦我們針對(duì)這么來進(jìn)行管理的話,那當(dāng)我們的業(yè)務(wù)環(huán)境達(dá)到一定量級(jí)的時(shí)候,我們就有多套僅存在細(xì)微差別的配置,對(duì)于后期的方案維護(hù)相當(dāng)?shù)牟挥押谩?
方案規(guī)整
所以,為了便于k8s來管理這些同業(yè)務(wù)的多版本場景,尤其是云原生的時(shí)代,我們應(yīng)該使用一個(gè) git版本控制系統(tǒng)來對(duì)所有的資源配置清單進(jìn)行統(tǒng)一的管控。同時(shí)為了方便后續(xù)技術(shù)支持團(tuán)隊(duì)的管理維護(hù),開發(fā)人員應(yīng)該做如下的三件事情:
1 編寫業(yè)務(wù)項(xiàng)目相關(guān)的部署清單文件,并提交到代碼管理倉庫
- 方便后續(xù)團(tuán)隊(duì),根據(jù)業(yè)務(wù)需求,準(zhǔn)備相關(guān)的資源
2 提供項(xiàng)目持續(xù)維護(hù)的jenkinsfile、Dockerfile文件。
- 方便后續(xù)團(tuán)隊(duì),根據(jù)業(yè)務(wù)的實(shí)際情況,以流水線的方式實(shí)現(xiàn)功能的迭代更新。
3 不同環(huán)境的資源文件,都應(yīng)該有獨(dú)有的一份。
- 以k8s環(huán)境為例,方便后續(xù)團(tuán)隊(duì)在多個(gè)ns中分別創(chuàng)建資源對(duì)象。
由于k8s上還有一種根據(jù)監(jiān)控指標(biāo)實(shí)現(xiàn)自動(dòng)擴(kuò)縮容的功能,所以,一旦我們將持續(xù)交付流水線做完畢后,結(jié)合提前做好的資源清單文件,與項(xiàng)目交付相關(guān)的所有操作,都不需要我們?nèi)斯じ深A(yù)了。
應(yīng)用管理
簡介
根據(jù)我們剛才所描述的信息內(nèi)容,我們可以了解到,越是復(fù)雜的業(yè)務(wù)運(yùn)行環(huán)境,越需要有一套業(yè)務(wù)部署管理工具
- 將業(yè)務(wù)相關(guān)的功能解決方案,將多個(gè)云原生的軟件以組件方式整合在一起,然后統(tǒng)一的進(jìn)行管理
對(duì)于k8s來說,它就提供了這樣的一種工具:kustomize。
官網(wǎng)介紹
Kubernetes native configuration management. Kustomize introduces a template-free way to customize application configuration that simplifies the use of off-the-shelf applications.
kustomize 是 kubernetes 原生的配置管理,以無模板方式來定制應(yīng)用的配置。
也就是說,kustomize 使用 k8s 原生概念幫助創(chuàng)建并復(fù)用資源配置(YAML),允許用戶以一個(gè)應(yīng)用描述文件(YAML 文件)為基礎(chǔ)(Base YAML),然后通過 Overlay 的方式生成最終部署應(yīng)用所需的描述文件。
工具簡介
kustomize允許用戶將不同環(huán)境所共享的配置放在一個(gè)文件目錄下,而將其他不同的配置放在另外的目錄下。通過這種通用+特有的組合方式,讓我們的多業(yè)務(wù)環(huán)境更輕松的來解決適配性的問題。
kustomize是sig-cli的一個(gè)子項(xiàng)目,它的設(shè)計(jì)目的是給kubernetes的用戶提供一種可以重復(fù)使用同一套配置的聲明式應(yīng)用管理,從而在配置工作中用戶只需要管理和維護(hù)kubernetes的API對(duì)象,而不需要學(xué)習(xí)或安裝其它的配置管理工具,也不需要通過復(fù)制粘貼來得到新的環(huán)境的配置。
Kustomize 是一個(gè)用來定制 Kubernetes 配置的工具。它提供以下功能特性來管理 應(yīng)用配置文件:
從其他來源生成資源
為資源設(shè)置貫穿性(Cross-Cutting)字段
組織和定制資源集合
github地址:https://github.com/kubernetes-sigs/kustomize
最新版本:v4.5.7 | 20220803
概念解析
組件 | 解析 |
---|---|
kustomization | 該文件所在的目錄下可以運(yùn)行 kustomize build,自動(dòng)生成配套文件 |
base | kustomization.yaml文件所在目錄,項(xiàng)目的根目錄 |
resource | kubernetes API資源對(duì)象文件 |
patch | kubernetes API資源對(duì)象文件特有的patch屬性信息文件,符合yaml格式。 |
variant | base下的多個(gè)不同業(yè)務(wù)場景的kustomization |
overlay | 聲明了與 base 之間的差異。通過 overlay 來維護(hù)基于 base 的不同 variants(變體) |
入口配置
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
bases <[]string> # 基礎(chǔ)通用配置信息所在目錄
resources <[]string> # 待定制的原始資源配置文件列表,按順序處理
namespace <string> # 資源對(duì)象歸屬目標(biāo)名稱空間
commonLabels <map[string]string> # 資源對(duì)象的通用標(biāo)簽
commonAnnotations <map[string]string> # 資源對(duì)象的通用注解
namePrefix <string> # 資源對(duì)象添加的名稱前綴
nameSuffix <string> # 資源對(duì)象添加的名稱后綴
images <[]Image> # 模板中定制的鏡像文件
- name <String> # 待替換的鏡像名稱
nameName <String> # 要使用的新鏡像名稱
newTag <String> # 要使用的新鏡像的標(biāo)簽
digest <String> # 要使用的新鏡像的sha256校驗(yàn)碼
vars <[]Var> # 可替換的變量列表
- name <String> # 變量的名稱,支持以“$(name)”格式進(jìn)行引用
objref <String> # 包含了要引用的目標(biāo)字段的對(duì)象的名稱
fieldref <String> # 引用的字段名稱,默認(rèn)為metadata.name
配置生成器
ConfigMap生成器:
configMapGenerator <[]ConfigMapGeneratorArgs> # ConfigMap資源生成器列表
- name <String> # 資源對(duì)象名稱
namespace <String> # 命名空間
behavior <String> # 合并策略,可為create/replace/merge;
files <[]String> # ConfigMap文件相對(duì)當(dāng)前項(xiàng)目的路徑
literals <[]String> # 以“key=value”格式的生成ConfigMap
env <String> # 以環(huán)境變量文件格式生成ConfigMap
Secret生成器:
secretGenerator <[]secretGeneratorArgs> # Secret資源生成器列表
- name <String> # 資源對(duì)象名稱
namespace <String> # 命名空間
behavior <String> # 合并策略,可為create/replace/merge;
files <[]String> # Secret文件相對(duì)當(dāng)前項(xiàng)目的路徑
literals <[]String> # 以“key=value”格式的生成Secret
type <String> # 選擇Secret資源類型
生成器選項(xiàng):
generatorOptions <GeneratorOptions> # 生成器額外屬性,為上面兩項(xiàng)的補(bǔ)充內(nèi)容
labels <map[String]String> # 擴(kuò)展的標(biāo)簽
annotations <map[String]String> # 擴(kuò)展的注解
disableNameSuffixHash <Boolean> # 是否禁用hash名稱后綴,默認(rèn)為啟用
資源補(bǔ)丁
patchesJson6902 <[]Json6902> # 待補(bǔ)對(duì)象列表
path <String> # 補(bǔ)丁文件路徑,支持json或yaml格式
target <Target> # 待補(bǔ)資源對(duì)象
group <String> # 資源所屬的群組
version <String> # API版本
kind <String> # 資源類型
name <String> # 資源對(duì)象的名稱
namespace <string> # 資源對(duì)象所屬的名稱空間
patchesStrategicMerge <[]string> # 將補(bǔ)丁補(bǔ)到匹配的資源之上,匹配的方式是根據(jù)資源
# Group/Version/Kind + Name/Namespace判斷
配置示例
資源清單文件:kustomization.yaml
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
bases:
- /config/app1/base
- /config/app2/base
- ...
resources:
- service.yaml
- deployment.yaml
patches:
- patch.yaml
namePrefix: my-
Kustomize的核心目標(biāo)在于為管理的應(yīng)用生成資源配置,而這些資源配置中定義了資源的期望狀態(tài)
小結(jié)
1.2.4 基礎(chǔ)實(shí)踐
學(xué)習(xí)目標(biāo)
這一節(jié),我們從 基礎(chǔ)知識(shí)、簡單實(shí)踐、小結(jié) 三個(gè)方面來學(xué)習(xí)。
環(huán)境準(zhǔn)備
簡介
我們可以通過如下兩種不同方式來安裝kustomize
二進(jìn)制方式:將軟件包解壓到系統(tǒng)命令路徑即可,我們推薦
go方式:go get github.com/kubernetes-sigs/kustomize
k8s方法:從 1.14 版本開始,kubectl 也開始支持使用 kustomization 文件來管理 Kubernetes 對(duì)象。 要查看包含 kustomization 文件的目錄中的資源,執(zhí)行下面的命令:
軟件安裝
下載軟件
mkdir /data/softs && cd /data/softs
wget https://github.com/kubernetes-sigs/kustomize/releases/download/kustomize%2Fv4.5.7/kustomize_v4.5.7_linux_amd64.tar.gz
解壓文件
mkdir /data/server/kustomize/bin
tar xf kustomize_v4.5.7_linux_amd64.tar.gz -C /data/server/kustomize/bin/
環(huán)境變量定制
# vim /etc/profile.d/kustomize.sh
#!/bin/bash
# set kustomize env path
export KUSTOMIZE_HOME=/data/server/kustomize
export PATH=${KUSTOMIZE_HOME}/bin:$PATH
加載環(huán)境變量
chmod +x /etc/profile.d/kustomize.sh
source /etc/profile.d/kustomize.sh
查看命令幫助
]# kustomize --help
...
Available Commands:
build Build a kustomization target from a directory or URL.
cfg Commands for reading and writing configuration.
completion Generate shell completion script
create Create a new kustomization in the current directory
edit Edits a kustomization file
fn Commands for running functions against configuration.
help Help about any command
version Prints the kustomize version
Flags:
-h, --help help for kustomize
--stack-trace print a stack-trace on error
Additional help topics:
kustomize docs-fn [Alpha] 開發(fā)和調(diào)用配置函數(shù)的文檔
kustomize docs-fn-spec [Alpha] 配置函數(shù)規(guī)范文檔.
kustomize docs-io-annotations [Alpha] io使用的注釋文檔
kustomize docs-merge [Alpha] 合并資源的文檔.
kustomize docs-merge3 [Alpha] 合并資源的文檔.
kustomize tutorials-command-basics [Alpha] 使用基本配置命令的教程.
kustomize tutorials-function-basics [Alpha] 使用函數(shù)的教程.
Use "kustomize [command] --help" for more information about a command.
安裝方式2 - k8s子命令
從 1.14 版本開始,kubectl 也開始支持使用 kustomization 文件來管理 Kubernetes 對(duì)象。 要查看包含 kustomization 文件的目錄中的資源,執(zhí)行下面的命令:
kubectl kustomize <kustomization_directory>
要應(yīng)用這些資源,使用參數(shù) --kustomize 或 -k 標(biāo)志來執(zhí)行 kubectl apply:
kubectl apply -k <kustomization_directory>
簡單實(shí)踐
簡單實(shí)踐
創(chuàng)建測試目錄
mkdir -p /data/kubernetes/process_secure/kustomize/kustomize-test -p
創(chuàng)建核心的kustomization.yaml文件,用于核心流程處理
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
resources:
- kustomiz-deployment-test.yaml
- kustomiz-service-test.yaml
commonLabels:
generated-by: kustomize
創(chuàng)建依賴的 kustomiz-deployment-test.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: deployment-nginx-web
spec:
replicas: 1
selector:
matchLabels:
app: nginx-web
template:
metadata:
labels:
app: nginx-web
spec:
containers:
- name: nginx
image: kubernetes-register.superopsmsb.com/superopsmsb/nginx_web:v0.1
imagePullPolicy: IfNotPresent
ports:
- containerPort: 80
name: http
創(chuàng)建依賴的 kustomiz-service-test.yaml
kind: Service
apiVersion: v1
metadata:
name: service-nginx-web
spec:
selector:
app: nginx-web
ports:
- name: http
protocol: TCP
port: 80
targetPort: 80
查看目錄結(jié)構(gòu)
kustomize/kustomize-test]# tree ./
./
├── kustomization.yaml
├── kustomiz-deployment-test.yaml
└── kustomiz-service-test.yaml
0 directories, 3 files
執(zhí)行效果
創(chuàng)建資源對(duì)象
kubectl apply -k ./
查看資源對(duì)象
]# kubectl get pod,svc
NAME READY STATUS RESTARTS AGE
pod/deployment-nginx-web-c77b687c5-6tzmt 1/1 Running 0 9s
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
service/kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 57d
service/service-nginx-web ClusterIP 10.106.243.105 <none> 80/TCP 10s
刪除資源對(duì)象
kubectl delete -k ./
直接以模擬的方式查看效果
kubectl apply -k ./ --dry-run=client -o yaml
僅僅查看生成的配置文件
kustomize build ./
注意:
這種方式可以確認(rèn),創(chuàng)建好的資源對(duì)象是否包含我們剛才定制的相關(guān)屬性信息。
小結(jié)
1.2.5 功能復(fù)用
學(xué)習(xí)目標(biāo)
這一節(jié),我們從 基礎(chǔ)知識(shí)、簡單實(shí)踐、小結(jié) 三個(gè)方面來學(xué)習(xí)。
基礎(chǔ)知識(shí)
簡介
kustomize 可以通過目錄復(fù)用的機(jī)制,實(shí)現(xiàn)在通用功能的基礎(chǔ)上,對(duì)某些特殊的機(jī)制進(jìn)行重寫或者集成
方案解析
我們可以創(chuàng)建一個(gè)base目錄,作為所有相關(guān)項(xiàng)目的根目錄。
然后再另外一個(gè)目錄中,通過 bases 屬性,繼承base目錄的相關(guān)內(nèi)容
簡單實(shí)踐
準(zhǔn)備基礎(chǔ)文件
將我們之前實(shí)踐出來的環(huán)境文件,作為一個(gè)基礎(chǔ)的可以被其他環(huán)境集成的項(xiàng)目目錄
mkdir kustomize-proj/base/ -p
cp -a kustomize-test/* kustomize-proj/base/
環(huán)境實(shí)踐
在base目錄同級(jí)別的位置,創(chuàng)建一個(gè)test目錄
mkdir kustomize-proj/test
創(chuàng)建一個(gè)專用的繼承功能的文件 kustomize-proj/test/kustomization.yaml
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
bases:
- ../base/
resources:
- namespace.yaml
namespace: test
# kustomize支持添加標(biāo)注和注釋,這些標(biāo)注和注釋會(huì)加在每一個(gè)它所管理的API對(duì)象上
commonLabels:
env: test
commonAnnotations:
superopsmsb.io/app: "kustomize"
images:
- name: "kubernetes-register.superopsmsb.com/superopsmsb/nginx_web"
newTag: "v0.1"
屬性解析:
1 通過base繼承原來的應(yīng)用
2 images僅僅是基于原來的鏡像名稱,更改了鏡像的標(biāo)簽。
創(chuàng)建依賴出來的文件 kustomize-proj/test/namespace.yaml
apiVersion: v1
kind: Namespace
metadata:
name: test
查看目錄效果
# tree kustomize-proj/
kustomize-proj/
├── base
│ ├── kustomization.yaml
│ ├── kustomiz-deployment-test.yaml
│ └── kustomiz-service-test.yaml
└── test
├── kustomization.yaml
└── namespace.yaml
2 directories, 5 files
檢查效果
kubectl apply -k kustomize-proj/base/ --dry-run=client -o yaml
kubectl apply -k kustomize-proj/test/ --dry-run=client -o yaml
或者
kustomize build kustomize-proj/base/
kustomize build kustomize-proj/test/
小結(jié)
1.2.6 配置定制
學(xué)習(xí)目標(biāo)
這一節(jié),我們從 基礎(chǔ)知識(shí)、簡單實(shí)踐、小結(jié) 三個(gè)方面來學(xué)習(xí)。
基礎(chǔ)知識(shí)
簡介
ConfigMap 和 Secret 包含其他 Kubernetes 對(duì)象(如 Pod)所需要的配置或敏感數(shù)據(jù)。 ConfigMap 或 Secret 中數(shù)據(jù)的來源往往是集群外部. 例如某個(gè) .properties 文件或者 SSH 密鑰文件。
Kustomize 提供 secretGenerator 和 configMapGenerator,可以基于文件或字面 值來生成 Secret 和 ConfigMap。
簡單實(shí)踐
準(zhǔn)備基礎(chǔ)文件
在base目錄同級(jí)別的位置,創(chuàng)建一個(gè)test目錄
mkdir kustomize-proj/staging
環(huán)境實(shí)踐
創(chuàng)建一個(gè)專用的繼承功能的文件 kustomize-proj/staging/kustomization.yaml
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
bases:
- ../base/
resources:
- namespace.yaml
namespace: staging
commonLabels:
environment: staging
commonAnnotations:
superopsmsb.io/app: "kustomize"
configMapGenerator:
- name: nginx-conf
literals:
- HOST="0.0.0.0"
- PORT="80"
secretGenerator:
- name: nginx-ssl
files:
- secrets/tls.crt
- secrets/tls.key
type: "kubernetes.io/tls"
generatorOptions:
disableNameSuffixHash: true
屬性解析:
1 通過secretGenerator 和 generatorOptions 生成相關(guān)的對(duì)象
2 disableNameSuffixHash 的目的是在基于deployment創(chuàng)建pod的時(shí)候,禁止生成hash后綴
創(chuàng)建依賴出來的文件 kustomize-proj/staging/namespace.yaml
apiVersion: v1
kind: Namespace
metadata:
name: staging
準(zhǔn)備相關(guān)的證書信息
mkdir kustomize-proj/staging/secrets && cd kustomize-proj/staging/secrets
openssl genrsa -out tls.key 2048
openssl req -new -x509 -key tls.key -out tls.crt -subj /C=CN/ST=Beijing/L=Beijing/O=DevOps/CN=shuji.superopsmsb.com
注意:
域名必須是我們使用的域名信息
檢查效果
查看目錄效果
]# tree kustomize-proj/
kustomize-proj/
├── base
│ ├── kustomization.yaml
│ ├── kustomiz-deployment-test.yaml
│ └── kustomiz-service-test.yaml
├── staging
│ ├── kustomization.yaml
│ ├── namespace.yaml
│ └── secrets
│ ├── tls.crt
│ └── tls.key
└── test
├── kustomization.yaml
└── namespace.yaml
4 directories, 9 files
方法1
kubectl apply -k ./base/ --dry-run=client -o yaml
kubectl apply -k ./staging/ --dry-run=client -o yaml
方法2
kustomize build kustomize-proj/base/
kustomize build kustomize-proj/staging/
小結(jié)
1.2.7 補(bǔ)丁實(shí)踐
學(xué)習(xí)目標(biāo)
這一節(jié),我們從 基礎(chǔ)知識(shí)、簡單實(shí)踐、小結(jié) 三個(gè)方面來學(xué)習(xí)。
基礎(chǔ)知識(shí)
簡介
由于軟件開發(fā)是一個(gè)復(fù)雜的過程,組織必須保持警惕以確保系統(tǒng)是最新版本的,涉及到的業(yè)務(wù)功能需要更新,以避免不必要的風(fēng)險(xiǎn)。根據(jù)2022年云原生環(huán)境下容器存活周期的調(diào)查,容器的更新時(shí)間是非常快的,在加上容器業(yè)務(wù)環(huán)境的更新迭代非常高,這就對(duì)于kubernetes場景中海量的資源清單文件的管理,提出了更高的要求。
補(bǔ)丁的作用
補(bǔ)丁管理是針對(duì)當(dāng)前資源對(duì)象進(jìn)行識(shí)別、獲取、部署和驗(yàn)證軟件更新的做法。我們可以借助于kustomize補(bǔ)丁管理策略和解決方案有助于為kuberntes資源管理對(duì)象的統(tǒng)一管理,提供應(yīng)用驗(yàn)證和應(yīng)用更新的便捷方法。
補(bǔ)丁管理的意義對(duì)于網(wǎng)絡(luò)安全行業(yè)來說不言而喻。為了應(yīng)對(duì)高級(jí)威脅,檢測全球威脅情報(bào)源已知的惡意軟件是成功的一半。補(bǔ)丁管理對(duì)于阻止已知威脅而言至關(guān)重要。
屬性解析
資源補(bǔ)丁
patchesJson6902 <[]Json6902> # 待補(bǔ)對(duì)象列表
path <String> # 補(bǔ)丁文件路徑,支持json或yaml格式
target <Target> # 待補(bǔ)資源對(duì)象
group <String> # 資源所屬的群組
version <String> # API版本
kind <String> # 資源類型
name <String> # 資源對(duì)象的名稱
namespace <string> # 資源對(duì)象所屬的名稱空間
patchesStrategicMerge <[]string> # 將補(bǔ)丁補(bǔ)到匹配的資源之上,匹配的方式是根據(jù)資源
# Group/Version/Kind + Name/Namespace判斷
由于定制的補(bǔ)丁信息,主要起的是補(bǔ)充的作用,所以,為了能夠讓補(bǔ)丁信息和所歸屬的資源對(duì)象產(chǎn)生關(guān)聯(lián),我們需要在patch文件中補(bǔ)充原資源對(duì)象的基本屬性信息,比如apiVersion、Kind、Namespace等。
簡單實(shí)踐
準(zhǔn)備基礎(chǔ)文件
在base目錄同級(jí)別的位置,創(chuàng)建一個(gè)prod目錄
mkdir kustomize-proj/prod/patches
環(huán)境實(shí)踐
創(chuàng)建一個(gè)專用的繼承功能的文件 kustomize-proj/prod/kustomization.yaml
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
bases:
- ../base/
resources:
- namespace.yaml
namespace: prod
commonLabels:
env: prod
commonAnnotations:
superopsmsb.io/app: "kustomize"
configMapGenerator:
- name: nginx-conf
literals:
- host="0.0.0.0"
- port="80"
secretGenerator:
- name: nginx-ssl
files:
- secrets/tls.crt
- secrets/tls.key
type: "kubernetes.io/tls"
generatorOptions:
disableNameSuffixHash: true
patchesStrategicMerge:
- patches/nginx-add-check.yaml
- patches/nginx-add-conf.yaml
patchesJson6902:
- target:
version: v1
kind: Service
name: service-nginx-web
path: patches/patch-service-nginx.yaml
屬性解析:
1 通過patchesStrategicMerge 加載相關(guān)的補(bǔ)丁文件
2 patchesJson6902 使用這種規(guī)則進(jìn)行規(guī)范限制
創(chuàng)建依賴出來的文件 kustomize-proj/prod/namespace.yaml
apiVersion: v1
kind: Namespace
metadata:
name: prod
準(zhǔn)備補(bǔ)丁文件
定制配置相關(guān)的補(bǔ)丁文件 kustomize-proj/prod/patches/nginx-add-conf.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: deployment-nginx-web
spec:
template:
spec:
containers:
- name: nginx
env:
- name: PORT
valueFrom:
configMapKeyRef:
name: nginx-conf
key: port
optional: false
- name: HOST
valueFrom:
configMapKeyRef:
name: nginx-conf
key: host
optional: true
volumeMounts:
- name: nginx-certs
mountPath: /etc/certs/
readOnly: true
volumes:
- name: nginx-certs
secret:
secretName: nginx-ssl
定制檢測相關(guān)的補(bǔ)丁文件 kustomize-proj/prod/patches/nginx-add-check.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: deployment-nginx-web
spec:
template:
spec:
containers:
- name: nginx
livenessProbe:
httpGet:
path: '/'
port: 80
initialDelaySeconds: 5
readinessProbe:
httpGet:
path: '/'
port: 80
initialDelaySeconds: 15
準(zhǔn)備純粹的補(bǔ)丁文件 kustomize-proj/prod/patches/nginx-add-sidecar.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: deployment-nginx-web
spec:
template:
spec:
containers:
- name: busybox
image: kubernetes-register.superopsmsb.com/superopsmsb/busybox:v0.1
command: ['/bin/sh','-c']
args: ['sleep 3600']
定制專屬的service修改補(bǔ)丁文件 kustomize-proj/prod/patches/patch-service-nginx.yaml
- op: replace
path: /spec/ports/0/targetPort
value: 8888
- op: add
path: /spec/ports/1
value:
name: https
protocol: TCP
port: 443
targetPort: 8443
準(zhǔn)備相關(guān)的證書信息
mkdir kustomize-proj/prod/secrets && cd kustomize-proj/prod/secrets
openssl genrsa -out tls.key 2048
openssl req -new -x509 -key tls.key -out tls.crt -subj /O=DevOps/CN=shuji.superopsmsb.com
注意:
域名必須是我們使用的域名信息
查看效果
查看目錄效果
]# tree kustomize-proj/prod/
kustomize-proj/prod/
├── kustomization.yaml
├── namespace.yaml
├── patches
│ ├── nginx-add-check.yaml
│ ├── nginx-add-conf.yaml
│ ├── nginx-add-sidecar.yaml
│ └── patch-service-nginx.yaml
└── secrets
├── tls.crt
└── tls.key
2 directories, 8 files
方法1:
kubectl apply -k kustomize-proj/base/ --dry-run=client -o yaml
kubectl apply -k kustomize-proj/prod/ --dry-run=client -o yaml
方法2:
kustomize build kustomize-proj/base/
kustomize build kustomize-proj/prod/
運(yùn)行項(xiàng)目環(huán)境
kubectl apply -k kustomize-proj/prod/
檢測效果
kubectl get all -n prod
小結(jié)
1.3 訪問安全
1.3.1 安全檢測
學(xué)習(xí)目標(biāo)
這一節(jié),我們從 基礎(chǔ)知識(shí)、簡單實(shí)踐、小結(jié) 三個(gè)方面來學(xué)習(xí)。
基礎(chǔ)知識(shí)
需求
國外軟件供應(yīng)商產(chǎn)品歷史上出現(xiàn)了許多惡意后門和網(wǎng)絡(luò)安全事件,譬如服務(wù)源碼泄露漏洞、 黑客攻擊漏洞、木馬事件等,由于這些軟件運(yùn)行本身的安全漏洞,導(dǎo)致在此平臺(tái)之上的應(yīng)用也運(yùn)行在危險(xiǎn)環(huán)境中,我們把這類的安全問題統(tǒng)統(tǒng)成為供應(yīng)鏈安全問題 -- 非項(xiàng)目代碼本身導(dǎo)致的安全問題。由于供應(yīng)鏈安全事件愈演愈烈,從2021年逐漸引起大家注意。
Synopsys 2022年對(duì)市場上17個(gè)行業(yè)2400多個(gè)商用產(chǎn)品的代碼源進(jìn)行了分析。開源軟件代碼使用率超過78%,81%的代碼包含至少一個(gè)安全漏洞,而且53%的代碼存在許可證沖突問題。許可證沖突問題會(huì)影響商務(wù)軟件的使用。
雖然供應(yīng)鏈方面的安全隱患非常多,但是我們可以站在用戶訪問流程的角度,直接從入口進(jìn)行控制,只要我們能夠?qū)⒊R姷挠脩粽?qǐng)求進(jìn)行精細(xì)化的限制的話,我們可以極大程度的降低軟件項(xiàng)目所面對(duì)的安全攻擊手段。
對(duì)于基于kubernetes的容器應(yīng)用來說,我們還可以在Ingress層面進(jìn)行更加高層次的,專門針對(duì)用戶請(qǐng)求數(shù)據(jù)的安全訪問控制。
為什么需要使用Ingress暴露服務(wù)?
Kubernetes主要通過兩種方式實(shí)現(xiàn)集群內(nèi)外的流量訪問:
1 支持通過NodePort、LoadBalancer等方式向集群外部暴露內(nèi)部服務(wù)
2 支持以ingress通過單一IP為多個(gè)服務(wù)提供基于http形式的訪問
- 通過主機(jī)名和路徑將流量路由到特定服務(wù),使得服務(wù)訪問更加靈活,同時(shí)還可以用來提供https服務(wù)。
ingress的兩大實(shí)現(xiàn)軟件:
Kubernetes Ingress Nginx
kubernetes社區(qū)開發(fā)和維護(hù)(Nginx幫忙管理)的ingress-nginx,通過nginx的負(fù)載均衡和反向代理能力實(shí)現(xiàn)流量控制
- kubernetes/ingress-nginx
- https://github.com/kubernetes/ingress-nginx
Nginx Ingress Controller
NGINX公司開發(fā)和維護(hù)的一種Ingress Controller。實(shí)現(xiàn)了nginx更多的能力,包括VS和VSR等,這些都是k8s的ingress默認(rèn)不支持的功能。
- 它主要有兩個(gè)發(fā)行:基于NGINX開源(免費(fèi))和基于NGINX Plus(商業(yè))
- nginxinc/kubernetes-ingress
- https://github.com/nginxinc/kubernetes-ingress/
- https://docs.nginx.com/nginx-ingress-controller/
nginx 控制器的優(yōu)勢
Nginx Ingress Controller和其他Ingress Controller之間的主要區(qū)別在于它們的開發(fā)和部署模型,尤其是這些模型可以基于不同的目標(biāo)和優(yōu)先級(jí)實(shí)現(xiàn)nginx善于負(fù)載均衡和反向代理。
開發(fā)理念
- NGINX 項(xiàng)目和產(chǎn)品的首要任務(wù)是提供一個(gè)快速、輕量級(jí)的工具,并具有長期的穩(wěn)定性和一致性。
集成代碼庫
- 所有代碼都是NGINX自己的代碼和校驗(yàn)過的代碼,保證控制器環(huán)境的高度穩(wěn)定。
高級(jí)流量管理
- 有別于其他Ingress通過注釋、CM、template定制高級(jí)功能。
- Nginx控制器提供原生、類型安全和縮進(jìn)的配置風(fēng)格,高級(jí)功能配置
- 包括 TCP/UDP、斷路、A/B測試、藍(lán)綠部署、雙向TLS認(rèn)證和WAF等。
持續(xù)的生產(chǎn)準(zhǔn)備
- 每個(gè)版本都按照可支持的生產(chǎn)標(biāo)準(zhǔn)進(jìn)行構(gòu)建和維護(hù)。
根據(jù)2022年<<sysdig云原生和使用報(bào)告>>的統(tǒng)計(jì)數(shù)據(jù)顯示:在生產(chǎn)環(huán)境中有了更多的命名空間,每個(gè)命名空間有了更多的 Deployments,每個(gè)命名空間下的 Deployments 構(gòu)成了用戶服務(wù)應(yīng)用的部署單元。
所以說如何讓流量入口適應(yīng)新形勢下的kubernetes應(yīng)用就是非常重要的選項(xiàng)了。
簡單實(shí)踐
清理舊環(huán)境
清理舊有環(huán)境
cd /data/kubernetes/app_secure/
kubectl delete -f ./
清理舊有ingress控制器
kubectl delete -f ingress/deploy-daemonset.yaml
準(zhǔn)備環(huán)境
獲取環(huán)境文件
cd /data/kubernetes/process_secure/
git clone https://github.com/nginxinc/kubernetes-ingress.git --branch v2.4.1
cd kubernetes-ingress/deployments
部署基礎(chǔ)環(huán)境
kubectl apply -f common/ns-and-sa.yaml
kubectl apply -f rbac/rbac.yaml
kubectl apply -f rbac/ap-rbac.yaml
kubectl apply -f rbac/apdos-rbac.yaml
部署通用資源
kubectl apply -f common/default-server-secret.yaml
kubectl apply -f common/nginx-config.yaml
kubectl apply -f common/ingress-class.yaml
創(chuàng)建自定義資源
kubectl apply -f common/crds/k8s.nginx.org_virtualservers.yaml
kubectl apply -f common/crds/k8s.nginx.org_virtualserverroutes.yaml
kubectl apply -f common/crds/k8s.nginx.org_transportservers.yaml
kubectl apply -f common/crds/k8s.nginx.org_policies.yaml
kubectl apply -f common/crds/k8s.nginx.org_globalconfigurations.yaml
創(chuàng)建應(yīng)用保護(hù)資源對(duì)象
kubectl apply -f common/crds/appprotect.f5.com_aplogconfs.yaml
kubectl apply -f common/crds/appprotect.f5.com_appolicies.yaml
kubectl apply -f common/crds/appprotect.f5.com_apusersigs.yaml
創(chuàng)建洪水攻擊防護(hù)資源對(duì)象
kubectl apply -f common/crds/appprotectdos.f5.com_apdoslogconfs.yaml
kubectl apply -f common/crds/appprotectdos.f5.com_apdospolicy.yaml
kubectl apply -f common/crds/appprotectdos.f5.com_dosprotectedresources.yaml
部署環(huán)境
部署應(yīng)用保護(hù)的環(huán)境
kubectl apply -f deployment/appprotect-dos-arb.yaml
kubectl apply -f service/appprotect-dos-arb-svc.yaml
修改ingress的入口 service/nodeport.yaml
...
spec:
externalIPs: ['10.0.0.12'] # 增加該條屬性
...
deployment方式部署ingress控制器
kubectl apply -f deployment/nginx-ingress.yaml
kubectl create -f service/nodeport.yaml
daemonset方式部署ingress控制器
kubectl apply -f daemon-set/nginx-ingress.yaml
注意:
二選一即可,由于daemonset自動(dòng)做了端口的映射,所以不需要做service
環(huán)境檢查
]# kubectl get pods --namespace=nginx-ingress
NAME READY STATUS RESTARTS AGE
appprotect-dos-arb-78fb9d4cbf-82xbt 1/1 Running 0 3m31s
nginx-ingress-6644665fb7-rrtsm 1/1 Running 0 2m34s
其他
環(huán)境的收尾
kubectl delete namespace nginx-ingress
kubectl delete clusterrole nginx-ingress
kubectl delete clusterrolebinding nginx-ingress
kubectl delete -f common/crds/
小結(jié)
1.3.3 簡單實(shí)踐
學(xué)習(xí)目標(biāo)
這一節(jié),我們從 準(zhǔn)備工作、簡單實(shí)踐、小結(jié) 三個(gè)方面來學(xué)習(xí)。
基礎(chǔ)知識(shí)
準(zhǔn)備服務(wù)模板文件
定制資源清單文件 01_ingress_web_resource.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: django
spec:
replicas: 2
selector:
matchLabels:
app: django
template:
metadata:
labels:
app: django
spec:
containers:
- name: django
image: kubernetes-register.superopsmsb.com/superopsmsb/django_web:v0.1
imagePullPolicy: IfNotPresent
ports:
- containerPort: 8000
---
apiVersion: v1
kind: Service
metadata:
name: django-svc
spec:
ports:
- port: 8000
targetPort: 8000
protocol: TCP
name: http
selector:
app: django
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx
spec:
replicas: 2
selector:
matchLabels:
app: nginx
template:
metadata:
labels:
app: nginx
spec:
containers:
- name: nginx
image: kubernetes-register.superopsmsb.com/superopsmsb/nginx_web:v0.1
imagePullPolicy: IfNotPresent
ports:
- containerPort: 80
---
apiVersion: v1
kind: Service
metadata:
name: nginx-svc
labels:
spec:
ports:
- port: 80
targetPort: 80
protocol: TCP
name: http
selector:
app: nginx
應(yīng)用資源清單文件
kubectl apply -f 01_ingress_web_resource.yaml
檢查效果
]# kubectl get deploy,svc
NAME READY UP-TO-DATE AVAILABLE AGE
deployment.apps/django 2/2 2 2 30s
deployment.apps/nginx 2/2 2 2 30s
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
service/django-svc ClusterIP 10.105.153.107 <none> 8000/TCP 30s
service/kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 49d
service/nginx-svc ClusterIP 10.97.65.163 <none> 80/TCP 30s
這里是使用ingressclasses的方式進(jìn)行ingress方式選擇的
]# kubectl get ingressclasses.networking.k8s.io
NAME CONTROLLER PARAMETERS AGE
nginx nginx.org/ingress-controller <none> 26h
功能頁面訪問
]# curl 10.105.153.107:8000
Hello Django, django-548fb788f5-4mckj-1.10.4
]# curl 10.97.65.163
Hello Nginx, nginx-7f7b4d6686-56jc6-1.23.1
定制單域名多url的ingress
定制資源清單文件 02_ingress_mulurl.yaml
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: ingress-test
annotations:
# nginx controller的反向代理,默認(rèn)沒有進(jìn)行重寫,我們需要定制重寫機(jī)制
nginx.org/rewrites: "serviceName=nginx-svc rewrite=/"
spec:
# 對(duì)于nginx的入口控制器,它是以ingressClassName的方式來選擇如何使用的
# 后面的定制格式與kubernetes的ingress格式一致
ingressClassName: nginx
rules:
- host: shuji.superopsmsb.com
http:
paths:
- path: /django
pathType: Prefix
backend:
service:
name: django-svc
port:
number: 8000
- path: /nginx
pathType: Prefix
backend:
service:
name: nginx-svc
port:
number: 80
應(yīng)用資源清單文件
kubectl apply -f 02_ingress_mulurl.yaml
檢查效果
]# kubectl describe ingress ingress-test
Name: ingress-test
...
Ingress Class: nginx
Default backend: <default>
Rules:
Host Path Backends
---- ---- --------
shuji.superopsmsb.com
/django django-svc:8000 (10.244.3.11:8000,10.244.4.11:8000)
/nginx nginx-svc:80 (10.244.3.12:80,10.244.5.10:80)
Annotations: nginx.org/rewrites: serviceName=nginx-svc rewrite=/
...
定制專屬的域名解析,因?yàn)槲覀儗?duì)于ingress的入口進(jìn)行限制了,所以hosts主機(jī)名解析信息如下:
echo '10.0.0.12 shuji.superopsmsb.com' >> /etc/hosts
訪問效果
]# curl shuji.superopsmsb.com/django
Hello Django, django-548fb788f5-xfdjs-1.10.4
]# curl shuji.superopsmsb.com/nginx
Hello Nginx, nginx-7f7b4d6686-qfsfn-1.23.1
配置解析
]# kubectl -n nginx-ingress exec -it nginx-ingress-6644665fb7-54scz -- cat /etc/nginx/conf.d/default-ingress-test.conf
# configuration for default/ingress-test
upstream default-ingress-test-shuji.superopsmsb.com-django-svc-8000 {
zone default-ingress-test-shuji.superopsmsb.com-django-svc-8000 256k;
random two least_conn;
server 10.244.3.11:8000 max_fails=1 fail_timeout=10s max_conns=0;
server 10.244.4.11:8000 max_fails=1 fail_timeout=10s max_conns=0;
}
upstream default-ingress-test-shuji.superopsmsb.com-nginx-svc-80 {
zone default-ingress-test-shuji.superopsmsb.com-nginx-svc-80 256k;
random two least_conn;
server 10.244.3.12:80 max_fails=1 fail_timeout=10s max_conns=0;
server 10.244.5.10:80 max_fails=1 fail_timeout=10s max_conns=0;
}
server {
listen 80;
listen [::]:80;
server_tokens on;
server_name shuji.superopsmsb.com;
set $resource_type "ingress";
set $resource_name "ingress-test";
set $resource_namespace "default";
location /django {
set $service "django-svc";
...
proxy_pass http://default-ingress-test-shuji.superopsmsb.com-django-svc-8000;
}
location /nginx {
set $service "nginx-svc";
...
proxy_pass http://default-ingress-test-shuji.superopsmsb.com-nginx-svc-80/;
}
}
簡單實(shí)踐
定制secret文件
mkdir ingress-tls && cd ingress-tls
(umask 077; openssl genrsa -out tls.key 2048)
openssl req -new -x509 -key tls.key -out tls.crt -subj "/CN=shuji.superopsmsb.com" -days 365
kubectl create secret tls ingress-tls --cert=./tls.crt --key=./tls.key
cd ..
創(chuàng)建資源對(duì)象文件 03_ingress_tlshosts.yaml
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: ingress-test
annotations:
# 定制重寫規(guī)則
nginx.org/rewrites: "serviceName=nginx-svc rewrite=/"
spec:
ingressClassName: nginx
# 添加tls認(rèn)證信息
tls:
- hosts:
- shuji.superopsmsb.com
secretName: ingress-tls
rules:
- host: shuji.superopsmsb.com
http:
paths:
- path: /django
pathType: Prefix
backend:
service:
name: django-svc
port:
number: 8000
- path: /nginx
pathType: Prefix
backend:
service:
name: nginx-svc
port:
number: 80
應(yīng)用ingress資源對(duì)象
kubectl delete -f 02_ingress_mulurl.yaml
kubectl apply -f 03_ingress_tlshosts.yaml
查看效果
]# kubectl describe ingress ingress-test
Name: ingress-test
...
TLS:
ingress-tls terminates shuji.superopsmsb.com
Rules:
Host Path Backends
---- ---- --------
shuji.superopsmsb.com
/django django-svc:8000 (10.244.3.11:8000,10.244.4.11:8000)
/nginx nginx-svc:80 (10.244.3.12:80,10.244.5.10:80)
Annotations: nginx.org/rewrites: serviceName=nginx-svc rewrite=/
...
訪問效果
]# curl -k https://shuji.superopsmsb.com/django
Hello Django, django-548fb788f5-xfdjs-1.10.4
]# curl -k https://shuji.superopsmsb.com/nginx
Hello Nginx, nginx-7f7b4d6686-qfsfn-1.23.1
環(huán)境收尾
kubectl delete -f 01_ingress_web_resource.yaml -f 03_ingress_tlshosts.yaml
小結(jié)
1.3.3 虛擬主機(jī)
學(xué)習(xí)目標(biāo)
這一節(jié),我們從 基礎(chǔ)知識(shí)、簡單實(shí)踐、小結(jié) 三個(gè)方面來學(xué)習(xí)。
基礎(chǔ)知識(shí)
需求
Nginx Ingress Controller提供了基于虛擬主機(jī)的路由分發(fā)策略,可以讓不同的應(yīng)用位于不同的namespace環(huán)境,然后基于虛擬主機(jī)的方式在k8s中存在,然后定制一個(gè)專屬的總路由進(jìn)行配置,從而實(shí)現(xiàn)流量的分發(fā)。這種方式與傳統(tǒng)意義上的應(yīng)用流量分發(fā)基本一致。
配置解析
虛擬主機(jī)屬性解析
apiVersion: k8s.nginx.org/v1
kind: VirtualServer
metadata:
name: <vs_name>
namespace: <namespace>
spec:
host: 訪問域名
tls:
secret: https依賴的tls
routes:
- path: /分發(fā)url
route: namespace/虛擬主機(jī)名稱
虛擬主機(jī)路由配置
apiVersion: k8s.nginx.org/v1
kind: VirtualServerRoute
metadata:
name: <vs_name>
namespace: <namespace>
spec:
host: 訪問域名
upstreams:
- name: <應(yīng)用service組名>
service: <應(yīng)用service組名>
port: <應(yīng)用service端口>
subroutes:
# 反向代理配置
- path: /<應(yīng)用url>
action:
proxy:
upstream: <應(yīng)用service組名>
requestHeaders:
pass: true
set:
- name: 定制請(qǐng)求頭
value: 定制請(qǐng)求值
responseHeaders:
add: # 增加響應(yīng)頭
- name: 定制響應(yīng)頭
value: 定制響應(yīng)結(jié)果
always: true # 是否永遠(yuǎn)存在
rewritePath: / # 設(shè)定轉(zhuǎn)發(fā)規(guī)則
# 根據(jù)條件請(qǐng)求路由分發(fā)
- path: /<應(yīng)用url>
matches:
- conditions:
- cookie: version
value: v2
action:
pass: django-v2
案例需求
應(yīng)用解析
nginx命名空間
nginx的deployment和svc,以及專屬的虛擬主機(jī)路由
django命名空間
django的deployment和svc,以及專屬的虛擬主機(jī)路由
django同時(shí)部署兩個(gè)版本,v1和v2
shuji命名空間
定制專屬虛擬主機(jī)
訪問解析
https://shuji.superopsmsb.com/nginx - 默認(rèn)訪問nginx命名空間的nginx應(yīng)用
https://shuji.superopsmsb.com/django - 默認(rèn)訪問django命名空間的django的v2版本
訪問django的時(shí)候,攜帶"version=v1"請(qǐng)求頭 - 訪問django命名空間的django的v1版本
簡單實(shí)踐
準(zhǔn)備基礎(chǔ)環(huán)境
定制資源清單文件 04_ingress_vs_base.yaml
apiVersion: v1
kind: Namespace
metadata:
name: django
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: django-v1
namespace: django
spec:
replicas: 2
selector:
matchLabels:
app: django-v1
template:
metadata:
labels:
app: django-v1
spec:
containers:
- name: django
image: kubernetes-register.superopsmsb.com/superopsmsb/django_web:v0.1
imagePullPolicy: IfNotPresent
ports:
- containerPort: 8000
---
apiVersion: v1
kind: Service
metadata:
name: django-v1-svc
namespace: django
spec:
ports:
- port: 8000
targetPort: 8000
protocol: TCP
name: http
selector:
app: django-v1
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: django-v2
namespace: django
spec:
replicas: 2
selector:
matchLabels:
app: django-v1
template:
metadata:
labels:
app: django-v1
spec:
containers:
- name: django
image: kubernetes-register.superopsmsb.com/superopsmsb/django_web:v0.2
imagePullPolicy: IfNotPresent
ports:
- containerPort: 8000
---
apiVersion: v1
kind: Service
metadata:
name: django-v1-svc
namespace: django
spec:
ports:
- port: 8000
targetPort: 8000
protocol: TCP
name: http
selector:
app: django-v1
---
apiVersion: v1
kind: Namespace
metadata:
name: nginx
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx
namespace: nginx
spec:
replicas: 2
selector:
matchLabels:
app: nginx
template:
metadata:
labels:
app: nginx
spec:
containers:
- name: nginx
image: kubernetes-register.superopsmsb.com/superopsmsb/nginx_web:v0.1
imagePullPolicy: IfNotPresent
ports:
- containerPort: 80
---
apiVersion: v1
kind: Service
metadata:
name: nginx-svc
namespace: nginx
spec:
ports:
- port: 80
targetPort: 80
protocol: TCP
name: http
selector:
app: nginx
---
apiVersion: v1
kind: Namespace
metadata:
name: shuji
準(zhǔn)備子路由主機(jī)
定制nginx虛擬主機(jī)路由資源清單文件 05_ingress_vs_nginx.yaml
apiVersion: k8s.nginx.org/v1
kind: VirtualServerRoute
metadata:
name: nginx
namespace: nginx
spec:
host: shuji.superopsmsb.com
upstreams:
- name: nginx
service: nginx-svc
port: 80
subroutes:
- path: /nginx
action:
proxy:
upstream: nginx
requestHeaders:
pass: true
set:
- name: My-Header
value: NGINX-Best
responseHeaders:
add:
- name: My-Header
value: ${http_user_agent}
- name: IC-Nginx-Version
value: ${nginx_version}
always: true
rewritePath: /
定制django虛擬主機(jī)路由資源清單文件 06_ingress_vs_django.yaml
apiVersion: k8s.nginx.org/v1
kind: VirtualServerRoute
metadata:
name: django
namespace: django
spec:
host: shuji.superopsmsb.com
upstreams:
- name: django-v1
service: django-v1-svc
port: 8000
- name: django-v2
service: django-v2-svc
port: 8000
subroutes:
- path: /django
matches:
- conditions:
- cookie: version
value: v2
action:
pass: django-v2
action:
pass: django-v1
定制虛擬服務(wù)主機(jī)
定制虛擬主機(jī)的資源清單 07_ingress_vs_shuji.yaml
apiVersion: k8s.nginx.org/v1
kind: VirtualServer
metadata:
name: shuji
namespace: shuji
spec:
host: shuji.superopsmsb.com
tls:
secret: ingress-tls
routes:
- path: /nginx
route: nginx/nginx
- path: /django
route: django/django
創(chuàng)建secret
kubectl -n shuji create secret tls ingress-tls --cert=./ingress-tls/tls.crt --key=./ingress-tls/tls.key
測試效果
應(yīng)用資源清單文件
kubectl apply -f 04_ingress_vs_base.yaml -f 05_ingress_vs_nginx.yaml -f 06_ingress_vs_django.yaml -f 07_ingress_vs_shuji.yaml
檢查命名空間
kubectl get ns | egrep 'shuji|django|nginx'
檢查資源對(duì)象
kubectl get vs -n shuji
kubectl get vsr,deploy,svc -n django
kubectl get vsr,deploy,svc -n nginx
普通http檢查
]# curl -k https://shuji.superopsmsb.com/nginx
Hello Nginx, nginx-7f7b4d6686-g66wh-1.23.1
]# curl -k https://shuji.superopsmsb.com/django
Hello Django, django-v1-fddf5c955-h8rrz-1.10.4
指定請(qǐng)求版本檢查
]# curl -k --cookie "version=v1" https://shuji.superopsmsb.com/django
Hello Django, django-v1-fddf5c955-h8rrz-1.10.4
環(huán)境收尾
kubectl delete -f 07_ingress_vs_shuji.yaml -f 06_ingress_vs_django.yaml -f 05_ingress_vs_nginx.yaml -f 04_ingress_vs_base.yaml
1.3.4 四層實(shí)踐
學(xué)習(xí)目標(biāo)
這一節(jié),我們從 基礎(chǔ)知識(shí)、簡單實(shí)踐、小結(jié) 三個(gè)方面來學(xué)習(xí)。
基礎(chǔ)知識(shí)
需求
Nginx ingress 不僅僅可以做http級(jí)別的ingress,還支持ip:port級(jí)別的ingress。這個(gè)功能需要GlobalConfiguration能力的支持。
準(zhǔn)備工作
改造 deployment資源對(duì)象 deployment/nginx-ingress.yaml
...
spec:
...
template:
...
spec:
...
containers:
- image: nginx/nginx-ingress:2.4.1
...
ports:
...
- name: tcp-8001
containerPort: 8001
- name: tcp-8002
containerPort: 8002
...
args:
...
- -global-configuration=$(POD_NAMESPACE)/nginx-configuration
配置解析:
開啟-global-configuration啟動(dòng)參數(shù),開啟專屬容器端口映射
改造service資源對(duì)象 service/nodeport.yaml
...
...
spec:
externalIPs: ['10.0.0.12']
type: NodePort
ports:
...
- port: 8001
targetPort: 8001
protocol: TCP
name: tcp-8001
- port: 8002
targetPort: 8002
protocol: TCP
name: tcp-8002
配置解析:
開啟專屬容器端口映射
重啟環(huán)境
kubectl apply -f deployment/nginx-ingress.yaml
kubectl apply -f service/nodeport.yaml
簡單實(shí)踐
創(chuàng)建基礎(chǔ)應(yīng)用環(huán)境
kubectl apply -f 01_ingress_web_resource.yaml
創(chuàng)建資源對(duì)象文件
創(chuàng)建 08_ingress_globalconfiguration_listener.yaml
apiVersion: k8s.nginx.org/v1alpha1
kind: GlobalConfiguration
metadata:
name: nginx-configuration
namespace: nginx-ingress
spec:
listeners:
- name: tcp-8001
port: 8001
protocol: TCP
- name: tcp-8002
port: 8002
protocol: TCP
創(chuàng)建專屬的代理配置 09_ingress_transportserver.yaml
apiVersion: k8s.nginx.org/v1alpha1
kind: TransportServer
metadata:
name: nginx
spec:
listener:
name: tcp-8001
protocol: TCP
upstreams:
- name: nginx
service: nginx-svc
port: 80
action:
pass: nginx
---
apiVersion: k8s.nginx.org/v1alpha1
kind: TransportServer
metadata:
name: django
spec:
listener:
name: tcp-8002
protocol: TCP
upstreams:
- name: django
service: django-svc
port: 8000
action:
pass: django
應(yīng)用資源清單文件
kubectl apply -f 01_ingress_web_resource.yaml -f 08_ingress_globalconfiguration_listener.yaml -f 09_ingress_transportserver.yaml
檢查效果
]# curl 10.0.0.12:8001
Hello Nginx, nginx-7f7b4d6686-fkbbj-1.23.1
]# curl 10.0.0.12:8002
Hello Django, django-548fb788f5-pdgzw-1.10.4
環(huán)境收尾
對(duì)于globalconfiguration環(huán)境來說,這個(gè)資源千萬不要?jiǎng)h除,如果非要?jiǎng)h除的話,可以清理該對(duì)象的配置即可,資源對(duì)象文件:10_ingress_globalconfiguration_reset.yaml
apiVersion: k8s.nginx.org/v1alpha1
kind: GlobalConfiguration
metadata:
name: nginx-configuration
namespace: nginx-ingress
spec:
清理環(huán)境
kubectl delete -f 01_ingress_web_resource.yaml -f 09_ingress_transportserver.yaml -f 10_ingress_globalconfiguration_reset.yaml
小結(jié)
1.3.5 策略實(shí)踐
學(xué)習(xí)目標(biāo)
這一節(jié),我們從 基礎(chǔ)知識(shí)、簡單實(shí)踐、小結(jié) 三個(gè)方面來學(xué)習(xí)。
基礎(chǔ)知識(shí)
需求
Nginx ingress 提供了大量與waf等相關(guān)的內(nèi)容,我們可以在ingress中,為不同的應(yīng)用定制各自的訪問策略信息。
屬性解讀
apiVersion: k8s.nginx.org/v1
kind: Policy
metadata:
name: <policy_name>
spec:
rateLimit:
rate: 100r/s # 每秒 100 個(gè)請(qǐng)求的速率
burst: 50 # 超過burst數(shù)量的過多的請(qǐng)求會(huì)被延遲。
noDelay: true # 在請(qǐng)求受到限制時(shí)禁用延遲過多請(qǐng)求。delay如果兩者都設(shè)置,則覆蓋。
key: ${binary_remote_addr} # 應(yīng)用速率限制的鍵。可以是文本、變量${}或組合。
zoneSize: 10M # 設(shè)定共享內(nèi)存區(qū)域的大小
rejectCode: 444 # 設(shè)置狀態(tài)碼以響應(yīng)被拒絕的請(qǐng)求而返回。必須落入范圍400..599。默認(rèn)為503。
參考資料:
https://docs.nginx.com/nginx-ingress-controller/configuration/policy-resource/
工具部署
git clone https://github.com/wg/wrk.git wrk
cd wrk
make
cp wrk /usr/local/bin
命令幫助
語法格式: wrk <選項(xiàng)> <被測HTTP服務(wù)的URL>
語法參數(shù)
-c, --connections <N> 跟服務(wù)器建立并保持的 TCP 連接數(shù)量
-d, --duration <T> 壓測時(shí)間
-t, --threads <N> 使用多少個(gè)線程進(jìn)行壓測
-s, --script <S> 指定 Lua 腳本路徑
-H, --header <H> 為每一個(gè) HTTP 請(qǐng)求添加 HTTP 頭
--latency 在壓測結(jié)束后,打印延遲統(tǒng)計(jì)信息
--timeout <T> 超時(shí)時(shí)間
-v, --version 打印正在使用的 wrk 的詳細(xì)版本信息
<N>代表數(shù)字參數(shù),支持國際單位 (1k, 1M, 1G)
<T>代表時(shí)間參數(shù),支持時(shí)間單位 (2s, 2m, 2h)
簡單實(shí)踐
簡單對(duì)象
定制資源對(duì)象 11_ingress_vs_nginx.yaml
apiVersion: k8s.nginx.org/v1
kind: VirtualServer
metadata:
name: shuji
spec:
host: shuji.superopsmsb.com
# policies:
# - name: rate-limit-policy
upstreams:
- name: nginx
service: nginx-svc
port: 80
routes:
- path: /
action:
pass: nginx
運(yùn)行資源對(duì)象
kubectl apply -f 01_ingress_web_resource.yaml -f 11_ingress_vs_nginx.yaml
測試效果
]# wrk -t2 -c10 -d10s http://shuji.superopsmsb.com
Running 10s test @ http://shuji.superopsmsb.com # 壓測時(shí)間10s)
2 threads and 10 connections # 共1個(gè)測試線程,10個(gè)連接
Thread Stats Avg Stdev Max +/- Stdev
Latency 5.48ms 4.97ms 109.56ms 93.11% # 延遲信息
Req/Sec 1.02k 229.62 1.48k 70.50% # 處理中請(qǐng)求
20466 requests in 10.05s, 5.44MB read # 10.05s處理20466個(gè)請(qǐng)求
# 讀取5.44MB數(shù)據(jù)
Requests/sec: 2037.01 # 平均每秒處理完成2037.01個(gè)請(qǐng)求
Transfer/sec: 554.91KB # 平均每秒讀取數(shù)據(jù)554.91KB
策略實(shí)踐文章來源:http://www.zghlxwxcb.cn/news/detail-543997.html
定制策略文件 12_ingress_policy_limit.yaml
apiVersion: k8s.nginx.org/v1
kind: Policy
metadata:
name: rate-limit-policy
spec:
rateLimit:
rate: 10r/s
burst: 50
noDelay: true
key: ${binary_remote_addr}
zoneSize: 5M
rejectCode: 444
修改虛擬主機(jī)文件 11_ingress_vs_nginx.yaml
...
spec:
host: shuji.superopsmsb.com
policies:
- name: rate-limit-policy
...
應(yīng)用資源清單文件
kubectl apply -f 12_ingress_policy_limit.yaml -f 11_ingress_vs_nginx.yaml
測試效果:
]# wrk -t2 -c10 -d10s http://shuji.superopsmsb.com
Running 10s test @ http://shuji.superopsmsb.com
2 threads and 10 connections
Thread Stats Avg Stdev Max +/- Stdev
Latency 5.72ms 3.58ms 28.40ms 83.44%
Req/Sec 11.90 35.35 282.00 98.02%
151 requests in 10.05s, 41.14KB read
Socket errors: connect 0, read 29404, write 0, timeout 0
Requests/sec: 15.02
Transfer/sec: 4.09KB
結(jié)果顯示:
Requests/sec 的值從原來的 2000左右,下降到了10左右,說明限制生效了。
查看控制器pod
]# kubectl get pod -n nginx-ingress
NAME READY STATUS RESTARTS AGE
nginx-ingress-79fbbb9dc-s4qnz 1/1 Running 0 64m
查看日志效果
]# kubectl logs nginx-ingress-79fbbb9dc-s4qnz -n nginx-ingress
...
2022/10/24 06:33:31 [error] 138#138: *81481 limiting requests, excess: 50.470 by zone "pol_rl_default_rate-limit-policy_default_shuji", client: 10.244.0.1, server: shuji.superopsmsb.com, request: "GET / HTTP/1.1", host: "shuji.superopsmsb.com"
10.244.0.1 - - [24/Oct/2022:06:33:31 +0000] "GET / HTTP/1.1" 444 0 "-" "-" "-"
結(jié)果顯示:
限制策略實(shí)施成功了
環(huán)境收尾文章來源地址http://www.zghlxwxcb.cn/news/detail-543997.html
kubectl delete -f 12_ingress_policy_limit.yaml -f 11_ingress_vs_nginx.yaml -f 01_ingress_web_resource.yaml
到了這里,關(guān)于K8S應(yīng)用流程安全(鏡像安全 配置管理 訪問安全)的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!