
個人親自錄制全套DevOps系列實戰(zhàn)教程:??手把手教你玩轉(zhuǎn)DevOps全棧技術(shù)??
(資料圖片)
根據(jù)jenkins官網(wǎng)對自己的描述,它是一個??可集成有1800+插件???的自動化服務(wù),提供構(gòu)建、部署和自動化的工程,可以說是opsdev的大總管,將開發(fā)的代碼工程與環(huán)境緊密結(jié)合起來。以實現(xiàn)CI持續(xù)集成、CD持續(xù)發(fā)布的能力。
中文地址:???https://www.jenkins.io/zh/doc/book/installing/??
拉取jenkins lts長期穩(wěn)定版本[JDK8]
# 從dockerhub上能找到的支持jdk8的長期穩(wěn)定版是2.346.3-2,所以這里就選的這個版本# 可參看官網(wǎng)的jdk支持對照表:https://www.jenkins.io/doc/administration/requirements/java/docker pull jenkins/jenkins:2.346.3-2-lts-centos7
構(gòu)建自定義jenkins鏡像Dockerfile
由于jenkins環(huán)境需要jdk、maven和git的支持,而jenkins現(xiàn)有鏡像是沒有全部集成這三個工具的,所以我們采用自己編寫鏡像文件,基于jenkins/jenkins:2.361.2-lts
??注意:?
?Dockerfile中我們使用了些實現(xiàn)要準(zhǔn)備的文件,如下:都需要拷貝到宿主機/docker/jenkins中(和Dockerfile和docker-compose.yml同目錄)
1. jdk-8u181-linux-x64.tar.gz2. apache-maven-3.8.6-bin.tar.gz3. git-2.38.1.tar.gz4. mvnrepo/settings.xml 因為jenkins作為使用maven的客戶端,需要一個settings.xml,這個文件就是用《DEVOPS系列[三]:詳解Maven倉庫環(huán)境及搭建》的即可(注意localRespository要修改)。5. Dockerfile6. docker-compose.yml7. home:目錄8. mvnrepo/repo:目錄
# 在vi /docker/jenkins中創(chuàng)建Dockerfile文件[避免下載jdk等,并和Dockerfile一起拷貝到宿主機的/docker/jenkins目錄]FROM jenkins/jenkins:2.346.3-2-lts-centos7LABEL maintainer="xxx@126.com"USER rootCOPY * /docker/WORKDIR /usr/localRUN set -e \ && cp /usr/share/zoneinfo/Asia/Shanghai /etc/localtime \ && echo "Asia/Shanghai" > /etc/timezone \ && chmod 755 /docker/* \ && mv -f /docker/jdk-8u181-linux-x64.tar.gz ./ \ && tar -zxf jdk-8u181-linux-x64.tar.gz \ && rm -f jdk-8u181-linux-x64.tar.gz \ && echo "jdk install is complete!" \ && echo "try to install maven ..." \ && mv -f /docker/apache-maven-3.8.6-bin.tar.gz ./ \ && tar -zxf apache-maven-3.8.6-bin.tar.gz \ && rm -f apache-maven-3.8.6-bin.tar.gz \ && echo "maven install is complete!" \ && echo "try to install git ..." \ && mv -f /docker/git-2.38.1.tar.gz ./ \ && tar -zxf git-2.38.1.tar.gz \ && rm -f git-2.38.1.tar.gz \ && yum remove -y git \ && yum install -y curl-devel expat-devel gettext-devel openssl-devel zlib-devel \ && yum install -y gcc-c++ make \ && cd git-2.38.1 && ./configure && make && make install \ && echo "git install is complete!" \ && yum clean allENV JAVA_HOME /usr/local/jdk1.8.0_181ENV CLASSPATH .:$JAVA_HOME/libENV MAVAN_HOME /usr/local/apache-maven-3.8.6ENV GIT_HOME /usr/local/git-2.38.1ENV PATH $JAVA_HOME/bin:$MAVAN_HOME/bin:$GIT_HOME:$PATHENV JAVA_OPTS "-Dfile.encoding=UTF8 -Dsun.jnu.encoding=UTF8 -Djava.security.egd=file:/dev/./urandom"EXPOSE 8080EXPOSE 50000USER jenkins
運行Jenkins容器
為了方便維護,后續(xù)統(tǒng)一使用docker-compose.yml
# 1.首先在宿主機創(chuàng)建jenkins的容器目錄/docker/jenkinsmkdir /docker/jenkins# 2.因為jenkins容器啟動后會自動使用jenkins用戶(所屬組為1000)來進行操作,所以需要給宿主機的/docker/jenkins目錄授權(quán),此處為簡單我們直接使用777授權(quán)chmod -R 777 /docker/jenkins# 3.編寫docker-compose.yml文件:vi docker-compose.ymlversion: "3"services: jenkins: build: context: . dockerfile: Dockerfile image: "lij/jenkins:2.346.3-2-lts-centos7" restart: always container_name: "jenkins" hostname: "jenkins" environment: # 該參數(shù)為避免插件安裝失敗,不校驗 - JAVA_OPTS="-Dhudson.model.DownloadService.noSignatureCheck=true" ports: - "9078:8080" # 50000 端口是jenkins內(nèi)部通過JNLP(java提供的一個通過瀏覽器可以訪問java應(yīng)用的機制) - "50000:50000" networks: - "exist-net-bloom" volumes: - "/docker/jenkins/home:/var/jenkins_home" # maven倉庫的映射,容器中的目錄會自動創(chuàng)建 - "/docker/jenkins/mvnrepo:/mvnrepo" - "/etc/timezone:/etc/timezone:ro" - "/etc/localtime:/etc/localtime:ro"networks: exist-net-bloom: external: name: devops
查看web頁面入口密碼:/var/jenkins_home/secrets/initialAdminPassword入口:10.10.1.199:9078
選擇推薦安裝即可:避免手動安裝麻煩,如果這里安裝失敗也沒關(guān)系,進入jenkins后可以更改為國內(nèi)源后重新安裝。
更新國內(nèi)鏡像源:ManageJenkins -> ManagePlugins -> Advance -> 升級站點輸入:??http://mirror.esuni.jp/jenkins/updates/update-center.json???
重啟:??http://10.10.1.199:9078/restart???
我這里安裝后有一個警告:這個是jenkins內(nèi)置的jetty存在一個漏洞,具體大家可以點過去看一下,因為jenkins一般都在內(nèi)網(wǎng)使用,忽略這個問題就行。
maven的settings.xml我們已經(jīng)通過宿主機的目錄將其映射到容器內(nèi)部,直接選擇即可。
其他參照容器的環(huán)境變量設(shè)置好即可。
路徑:系統(tǒng)管理->全局工具配置[如果路徑不對,頁面會直接報錯,放心配置即可]
集成maven插件:Maven Integration、Pipeline Maven Integration集成gitlab插件:GitLab、Generic Webhook Trigger、Git Parameter(允許選擇分支、tag構(gòu)建)集成ssh插件:Publish Over SSH,讓jenkins具備通過ssh遠程發(fā)布的能力,通俗講就是通過ssh將build后的包發(fā)布到目標(biāo)服務(wù)器(如微服務(wù)服務(wù)器等)?
?-> 安裝完后重啟Jenkins服務(wù)?
?
基于用戶名密碼方法基于RSA公/私鑰免密方式路徑:系統(tǒng)配置->Publish over SSH主要功能就是可以讓jenkins容器能夠通過ssh命令遠程到其他目標(biāo)機器。
jenkins構(gòu)建后的工程會在自身的/var/jenkins_home/workspace目錄,而我們的前、后端服務(wù)一般都是單獨,比如都是用docker,那么jendins構(gòu)建的包就需要發(fā)送給可以構(gòu)建docker鏡像的服務(wù)器(如宿主機、kubernetes等),交由他們?nèi)?gòu)建包打入鏡像,然后部署鏡像運行容器。【我們這里目標(biāo)機器就是宿主機】
通過輸入用戶名和密碼來完成ssh的鑒權(quán),會存在中間人攻擊的風(fēng)險。
原理:首次客戶端要連接ssh服務(wù)時,如果客戶端未攜帶公鑰參數(shù)訪問ssh服務(wù),則ssh服務(wù)將本地的公鑰下發(fā)給客戶端,客戶端使用收到的公鑰將密碼加密后發(fā)送,ssh服務(wù)收到密文后使用私鑰解密,得到密碼然后進行鑒權(quán)。風(fēng)險:中間人攻擊,如果客戶端連接的是中間人的ssh服務(wù),那么中間人很容易就得到了客戶端的密碼。配置方法:用戶名密碼方式比較簡單,重點是RemoteDirectory,就是目標(biāo)機器的目錄,該目錄在目標(biāo)機器需要事先創(chuàng)建好,否則在配置頁面test時會報錯。
客戶端不需要輸入密碼直接連接ssh進行操作。
原理:客戶端需要自己生成一套公私鑰,并提前將公鑰發(fā)送給ssh服務(wù),由ssh服務(wù)存儲在自己的密鑰配置文件(~/.ssh/authorized_keys)中.這樣當(dāng)客戶端與ssh建立連接時,將會把自己的公鑰傳遞給ssh服務(wù),而ssh收到請求后發(fā)現(xiàn)客戶端傳遞了公鑰,所以將使用RSA認證,同時他也不會給客戶端發(fā)送自己的公鑰,而是將收到的公鑰與自己保存的公鑰列表比對,如果成功比對則通過在ssh服務(wù)創(chuàng)建一個隨機數(shù),并用收到的公鑰加密發(fā)給客戶端,客戶端收到密文使用自己的私鑰解密再講解密后的隨機數(shù)發(fā)回ssh服務(wù),ssh服務(wù)收到后與創(chuàng)建時的隨機數(shù)比對,成功則完成連接握手。優(yōu)點:不存在中間人攻擊,安全性高,但效率不如前者。配置方法:①服務(wù)端開啟RSA驗證 ②客戶端生成RSA密鑰對 ③客戶端公鑰提交至服務(wù)端 ④客戶端配置使用RSA進行ssh連接 ⑤修改jenkins的配置1.修改服務(wù)端ssh服務(wù),開啟RSA驗證:
vi /etc/ssh/sshd_config
RSAAuthentication yes #開啟rsa驗證PubkeyAuthentication yes #通過公鑰進行驗證AuthorizedKeysFile .ssh/authorized_keys #保存公鑰的的服務(wù)端文件,該目錄為>~/.ssh/authorized_keys
2.客戶端生成RSA密鑰:
進入jenkins容器,執(zhí)行如下命令生成密鑰對
# 生成密鑰對,因為我們jenkins容器使用的是jenkins用戶,而jenkins容器的默認用戶是我們指定的/var/jenkins_home# 所以此處我們直接回車,使用默認的保存密鑰對目錄:/var/jenkins_home/.ssh/# 繼續(xù)回車會讓輸入私鑰的加密密碼,我們此處不輸入直接回車,即不設(shè)置私鑰密碼(如果設(shè)置的話,打開私鑰文件都需要輸入密碼)ssh-keygen -t rsa
此時進入/var/jenkins_home/.ssh/目錄會發(fā)現(xiàn)已經(jīng)生成了id_rsa(私鑰)和id_rsa.pub(公鑰)文件,其內(nèi)容都是經(jīng)過Base64編碼后的內(nèi)容。
3.客戶端公鑰拷貝到ssh服務(wù)器端:
此處我們使用遠程公鑰發(fā)送命令(在jenkins容器中執(zhí)行如下命令)
ssh-copy-id -i ~/.ssh/id_rsa.pub root@10.10.1.199
期間會要求輸入宿主機root賬號密碼(此處多以演示為主,線上我們一般會專號專用,根據(jù)需求設(shè)置賬號權(quán)限,不會使用root賬號操作)完成后,會在宿主機root賬號的home目錄的.ssh/authorized_keys中增加公鑰內(nèi)容,如果沒有該文件會新建,如果有則會追加。
4.客戶端配置開啟RSA登錄ssh:
vi /etc/ssh/ssh_config 【注意作為客戶端是ssh_config起作用,作為服務(wù)端是sshd_config起作用,注意區(qū)分】
# 注意該文件為root權(quán)限修改,需要以root用戶登錄jenkins容器進行操作docker exec -it -u root jenkins bashvi /etc/ssh/ssh_config# 將以下注釋釋放即可IdentityFile ~/.ssh/id_rsa
至此:配置完畢,可以直接在jenkins容器內(nèi)部,通過ssh連接宿主機測試是否成功,如果不需要密碼直接登錄則表示成功,如下圖:
??
?問題:?
? 此處我們使用的是宿主機的root賬號登錄,權(quán)限最大;如果是自建的普通賬號,那么賬號的home目錄(保存authorized_keys的目錄)需要設(shè)置成不允許其他用戶和組操作,即755權(quán)限,而文件authorized_keys需要指定為700權(quán)限。而客戶端jenkins生成的公私鑰的目錄也要做同樣的權(quán)限修改。
"系統(tǒng)管理"->"系統(tǒng)配置"->"Publish over SSH"
配置完成后,點擊測試提示Success即可。
??問題:?
??有些同學(xué)點擊測試后可能會提示??privatekey(Failed to add SSH key)?
?錯誤。
??解答:?
??這是因為生成的私鑰文件內(nèi)容的格式有些問題,打開內(nèi)容應(yīng)該會發(fā)現(xiàn)開頭是??BEGIN OPENSSH...?
?,而這不是標(biāo)準(zhǔn)的RSA私鑰格式,
我們需要使用工具將內(nèi)容轉(zhuǎn)換成RSA格式,比如使用puttygen工具,有可視化界面,將私鑰文件導(dǎo)入生成新的私鑰再替換到j(luò)enkins容器的id_rsa即可。
當(dāng)然也有命令行工具可以轉(zhuǎn)換,這個交給大家自己去拓展吧,在此就不多說了。
標(biāo)準(zhǔn)RSA私鑰文件內(nèi)容開頭應(yīng)該是??BEGIN RSA...?
?。
??原因:?
?之所以通過ssh-keygen -t rsa會生成"BEGIN OPENSSH..."樣的私鑰,是因為openssh生成密鑰格式有兩種,而老版本是"BEGIN RSA..."開頭,新版本是"BEGIN OPENSSH..."開頭,生成的是哪個版本看openssh的版本,當(dāng)然也可以強制生成老版本格式,比如通過指定參數(shù):
ssh-keygen -m PEM -t rsa,其中-m PEM就是生成RSA格式的密鑰,這個大家知道下就行了,具體可以查看ssh-keygen的使用。
??關(guān)于sftp的簡單了解?
??:其實ssh服務(wù)除了包括sshd服務(wù)還包含sftp服務(wù),即我們設(shè)置了以上的免密登錄,那么sftp也自動變成了免密登錄,而sftp授權(quán)的根目錄是一般是登錄用戶的home目錄,如果需要調(diào)整則要到sshd_config中進行配置,而我用的是root免密,所以共享目錄是/root,如果通過jenkins需要拷貝文件(Transfer Set)到遠程目錄,需要留意一下這個目錄,jenkins設(shè)置的目錄都是基于宿主機的共享目錄之上進行設(shè)置的。
其實和ssh免密登錄幾乎一樣,只不過生成密鑰對時需要指定使用哪個gitlab賬號
# 在jenkins容器中生成密鑰對,并指定gitlag賬號ssh-keygen -t rsa -C “登錄gitlab的郵箱”
生成密鑰對后,只需要2步:
將公鑰內(nèi)容配置到gitlab對應(yīng)賬號的sshkey將私鑰配置到j(luò)enkins的憑證中
注意:這樣配置將會是失敗的,因為我們已經(jīng)生成了2套公私鑰,并且默認使用的是/etc/.ssh/ssh_config中指定的~/.ssh/id_rsa,而gitlab使用的是gitlab的賬號,所以需要單獨配置一下gitlab的認證使用哪個私鑰,否則都去用默認的了,肯定會驗證失敗。
# 修改jenkins容器ssh_config配置文件:vi /etc/ssh/ssh_config# ssh命令讀取配置文件順序:命令行參數(shù) -> ~/.ssh/config -> /etc/ssh/ssh_configHost 10.10.1.199 # 隨意定義的一個名字【但因為我這里gitlab是將22端口映射到宿主機2224上,所以Host要指定為10.10.1.199,否則匹配補上】 HostName 10.10.1.199 # gitlab的ip地址【指定宿主機ip】 Port 2224 # 端口號,我們的gitlab映射ssh端口時指定的為2224 PreferredAuthentications publickey # 指定認證方式 User xxx@126.com # 指定登錄gitlab的賬號 IdentityFile ~/.ssh/gitlab_id_rsa # 指定為gitlab生成的證書的私鑰絕對路徑# 操作完后可以在jenkins容器中先做測試,直接拉取gitlab代碼看是否正常,注意要使用ssh方式拉取git clone ssh://git@10.10.1.199:2224/devops/demo.git
如果是如下結(jié)果,說明配置成功:
?
?更正一個網(wǎng)上錯誤概念:?
??如上操作,其實openssh的配置文件都是以一個Host節(jié)點為單位,可以配置多個Host,而默認的一般是"Host *",表示所有的都生效但是網(wǎng)上有多數(shù)資料,在解決ssh客戶端存在多個證書密鑰時都需要配置一個ssh-add ~/.ssh/gitlab_id_rsa的命令,其實這是不對的,一個很大的誤導(dǎo),ssh-add是向ssh-agent代理認證服務(wù)中添加私鑰證書,如果添加了即便~/.ssh/config配置的不對也是生效的,其實這是兩種方式,前者是ssh自身讀配置去建立連接,而ssh-agent是ssh將認證功能交給代理完成,而代理不會使用默認的配置,而是優(yōu)先使用提交給代理高速緩存的證書進行驗證,而ssh-add就是向高速緩存中存入證書信息,所以指定了ssh-add后,即便不配置~/.ssh/config也是可行的,但ssh-agent是一個臨時存儲,重啟后緩存會清空。???如果要用這種方式,則按如下操作即可:?
?# 加入代理,如果執(zhí)行報錯【Could not open a connection to your authentication agent】# 可以先執(zhí)行命令:[ssh-agent bash],然后執(zhí)行如下命令ssh-add ~/.ssh/gitlab_id_rsa# 查看是否成功ssh-add -l
最后我們在jenkins的倉庫頁面可以看到不會提示報錯了
詳細命令可參考OpenSSH官網(wǎng):???https://www.openssh.com/manual.html??