CI-CD 解決的是代碼從生產到線上的一個距離的問題,有效的管控中間的流程。也是開發和運維之間的問題。
jenkins簡介
- Jenkins是開源CI&CD軟件領導者, 提供超過1000個插件來支持構建、部署、自動化, 滿足任何項目的需要。
- Jenkins用Java語言編寫,可在Tomcat等流行的servlet容器中運行,也可獨立運行。
- CI(Continuous integration持續集成)持續集成強調開發人員提交了新代碼之後,立刻進行構建、(單元)測試。
- CD(Continuous Delivery持續交付) 是在持續集成的基礎上,將集成後的代碼部
署到更貼近真實運行環境(類生產環境)中 。
jenkins安裝
我們在開啓一臺server2主機作爲jenkins服務器.
它需要jdk的支持:
https://mirrors.tuna.tsinghua.edu.cn/jenkins/redhat/
在這裏下載
[root@server2 ~]# rpm -ivh jdk-8u171-linux-x64.rpm
[root@server2 ~]# rpm -ivh jenkins-2.237-1.1.noarch.rpm
# 它在下載的時候會自動的從外網下載軟件包。
[root@server2 ~]# systemctl start jenkins
[root@server2 ~]# netstat -tnlp
Active Internet connections (only servers)
Proto Recv-Q Send-Q Local Address Foreign Address State PID/Program name
tcp 0 0 0.0.0.0:22 0.0.0.0:* LISTEN 3019/sshd
tcp 0 0 127.0.0.1:25 0.0.0.0:* LISTEN 3140/master
tcp6 0 0 :::8080 :::* LISTEN 3315/java
tcp6 0 0 :::22 :::* LISTEN 3019/sshd
tcp6 0 0 ::1:25 :::* LISTEN 3140/master
# 啓動服務會打開8080端口
訪問:
它需要admin用戶的一個密碼,在/var/lib/jenkins/secrets/initialAdminPassword
[root@server2 ~]# cat /var/lib/jenkins/secrets/initialAdminPassword
e5687fa1f9544d13a1e61de6e0ea2518
它接下來會去安裝一些插件,我們更改它的插件源,讓他更快一些:
[root@server2 ~]# cat /var/lib/jenkins/hudson.model.UpdateCenter.xml
<?xml version='1.1' encoding='UTF-8'?>
<sites>
<site>
<id>default</id>
<url>https://mirrors.tuna.tsinghua.edu.cn/jenkins/updates/update-center.json</url>
</site> # 換成清華大學下載站的會快很多
</sites>
[root@server2 updates]# cd /var/lib/jenkins/
[root@server2 jenkins]# ls
updates # 這時就會生成一個更新目錄,裏面
[root@server2 jenkins]# ls
config.xml jenkins.telemetry.Correlator.xml nodes secrets
hudson.model.UpdateCenter.xml jobs plugins updates
identity.key.enc logs secret.key userContent
jenkins.install.UpgradeWizard.state nodeMonitors.xml secret.key.not-so-secret users
[root@server2 jenkins]# cd updates/ && ls
default.json hudson.tasks.Maven.MavenInstaller
# default.json 這個文件記錄了插件的下載路徑,我們還要去這裏面更改
[root@server2 updates]# sed -i.bak 's/http:\/\/updates.jenkins-ci.org\/download/https:\/\/mirrors.tuna.tsinghua.edu.cn\/jenkins/g' default.json
[root@server2 updates]# sed -i 's/http:\/\/www.google.com/https:\/\/www.baidu.com/g' default.json
[root@server2 updates]# systemctl restart jenkins.service
安裝推薦的插件。
推薦安裝了這些,我們還可以手動往裏面添加。
它讓我們創建管理員,我們直接使用右下角的admin就可以
就可以了。
點擊右上角用戶,點擊設置,更改密碼。
我們可以去插件管理那裏下載locale 和Localization: Chinese (Simplified) 這兩個插件來支持中文。
jenkins使用
我們現在新建一個任務:
企業中大多用的都是流水線風格的.
首先在源碼管理這裏我們添加上gitlab的ssh鏈接地址,由於需要認證,所以我們將server1上的私鑰複製下來粘上去,因爲我們在gitlab上傳的是公鑰,需要私鑰與其對應:
這時還無法鏈接倉庫,是因爲我們的server2主機上的jenkins要通過git命令去鏈接gitlab倉庫,所以我們需要在server2上也安裝git。
[root@server2 jenkins]# yum install -y git
這時就沒有報錯了。
然後我們使用輪詢的方式構建觸發器。
構建一條shell命令測試一下。
一分鐘後,
任務執行了。
在控制檯中可以看見用git命令將gitlab倉庫克隆到了 /var/lib/jinkens/workspace/ 下,並執行了ls -l 命令。 /var/lib/jinkens/workspace/ 是jenkins的工作目錄。
[root@server2 workspace]# cd /var/lib/jenkins/workspace/demo
[root@server2 demo]# ls
index.html README.md
使用docker容器進行構建
在server2上安裝docker。
docker-ce-19.03.8-3.el7.x86_64
docker-ce-cli-19.03.8-3.el7.x86_64
[root@server2 ~]# systemctl start docker.service
[root@server2 ~]# docker info
WARNING: bridge-nf-call-iptables is disabled
WARNING: bridge-nf-call-ip6tables is disabled # 這兩個模塊是關閉的
[root@server2 ~]# sysctl -a | grep bridge-nf-call
net.bridge.bridge-nf-call-ip6tables = 0
net.bridge.bridge-nf-call-iptables = 0
我們去打開:
[root@server2 ~]# vim /etc/sysctl.d/bridge.conf
net.bridge.bridge-nf-call-ip6tables = 1
net.bridge.bridge-nf-call-iptables = 1
[root@server2 ~]# sysctl --system # 使其生效
net.bridge.bridge-nf-call-ip6tables = 1
net.bridge.bridge-nf-call-iptables = 1
[root@server2 ~]# docker pull nginx # 拉取一個鏡像
[root@server2 ~]# docker run -d --name web nginx
821e91cf33ac9e6704858597378d53f782e02a923d4e852a2af1a99bf5b6145e
[root@server2 ~]# curl 172.17.0.2
<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title> # 可以運行
這樣我們就可以讓jinkens去自動構建鏡像了。
git --> dockerfile --> gitlab --> jenkins --> plugins --> images build --> harbor
具體的流程如上,開發人員通過 git 將 dockerfile 上傳到 gitlab 倉庫,然後jenkins 從 gitlab 抓取,通過docker的功能插件來完成docker鏡像的構建,然後還可以把鏡像推送到 docker 的 harbor 倉庫中。整個過程沒有人工的干預。
root@server1 demo]# vim Dockerfie
FROM nginx
COPY index.html /usr/share/nginx/html
# 將當前目錄下的index.html 放到容器的發佈目錄中
[root@server1 demo]# cat index.html
www.caoaoyuan.org
[root@server1 demo]# git add dockerfie
[root@server1 demo]# git commit -m "add Dockerfile"
[root@server1 demo]# git push -u origin master # 推送到gitlab
jenkins 已經自動構建了,構建號是2,這是單調遞增的。
[root@server2 demo]# ls
Dockerfie index.html README.md #有了
此時新容器還沒有進行構建,因爲我們還沒有安裝插件:
安裝這個插件,它下面可以看到它會根據dockerfile構建鏡像,並推送到docker倉庫中去。
然後我們在demo在這個項目的配置中就有了這個參數:
docker的構建和發佈,這是我們就需要一個倉庫了,我們先搭建一個:
[root@server2 demo]# docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
nginx latest 2622e6cca7eb 5 days ago 132MB
registry 2 708bc6af7e5e 4 months ago 25.8MB
[root@server2 demo]# docker run -d --name registry -p 5000:5000 registry:2
3bf873cb1234a494a213d1f451464fe9180c581057798fdf4a02a38b95c2bbbd
doc[root@server2 demo]# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
3bf873cb1234 registry:2 "/entrypoint.sh /etc…" 3 seconds ago Up 1 second 0.0.0.0:5000->5000/tcp registry # 已經在運行了
#我們獲取一個測試鏡像。
[root@server2 ~]# docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
nginx latest 2622e6cca7eb 5 days ago 132MB
registry 2 708bc6af7e5e 4 months ago 25.8MB
ikubernetes/myapp v1 d4a5e0eaa84f 2 years ago 15.5MB
ikubernetes/myapp v2 54202d3f0f35 2 years ago 15.5MB
[root@server2 ~]# docker tag ikubernetes/myapp:v1 localhost:5000/myapp:v1
[root@server2 ~]# docker push localhost:5000/myapp
[root@server2 ~]# curl localhost:5000/v2/_catalog
{"repositories":["myapp"]} # 傳上去了,倉庫可用
接着去配置:
標籤名爲構建號,就是 #1 #2.docker主機是套接字文件,倉庫地址是,本地的5000端口。關掉強行拉取,因爲我們本地已經有nginx的緩存了。點開跳過推送,分開進行。
修改docker.sock權限,不然jenkins無法直接執行docker命令:
root@server2 run]# chmod 777 /etc/run/docker.sock
倉庫沒有變化,所以我們手工推送一次。點項目右邊的這個按鈕。
[root@server2 demo]# docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
localhost:5000/myweb 4 8579df46fc59 About a minute ago 132MB
localhost:5000/myweb 5 8579df46fc59 About a minute ago 132MB
localhost:5000/myweb latest 8579df46fc59 About a minute ago 132MB
nginx latest 2622e6cca7eb 5 days ago 132MB
registry 2 708bc6af7e5e 4 months ago 25.8MB
ikubernetes/myapp v1 d4a5e0eaa84f 2 years ago 15.5MB
localhost:5000/myapp v1 d4a5e0eaa84f 2 years ago 15.5MB
ikubernetes/myapp v2 54202d3f0f35 2 years ago 15.5MB
4 和5 都是我剛纔觸發的,直接就構建好了,現在我們關閉剛纔打開的skip Push,讓它上傳到倉庫中去。
[root@server1 demo]# vim index.html
www.caoaoyuan.org
www.hhhhhhh.org # 我們把這個文件改成這樣子
www.hhhhhhh.org
[root@server1 demo]# git add index.html
[root@server1 demo]# git commit index.html -m "update index"
[root@server1 demo]# git push -u origin master # 傳到gitlab
等一分鐘的觸發時間:
jenkins 就進行構建了:
[root@server2 demo]# curl localhost:5000/v2/_catalog
{"repositories":["myapp","myweb"]}
# 並且自動的上傳到了倉庫中
我們測試構建的這個鏡像有沒有問題:
現在server2上給jenkins 加上sudo 權力下放.
[root@server2 demo]# visudo
jenkins ALL=(ALL) NOPASSWD: ALL
然後再web界面新建一個項目。
選擇demo項目構建以後再觸發。
讓他運行我們剛纔構建的容器,不加TAG的話始終使用最新的。
手動觸發一次。
[root@server2 demo]# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
aae25a3115aa localhost:5000/myweb "/docker-entrypoint.…" 2 minutes ago Up 2 minutes 80/tcp webserver
3bf873cb1234 registry:2 "/entrypoint.sh /etc…" About an hour ago Up About an hour 0.0.0.0:5000->5000/tcp registry
[root@server2 demo]# docker inspect webserve
"IPAddress": "172.17.0.3",
[root@server2 demo]# curl 172.17.0.3
www.caoaoyuan.org
www.hhhhhhh.org
www.hhhhhhh.org # 是我們改過的內容。
但是下次運行的話就不行了,因爲webserver這個容器名只能有一個,我們更改一下
每次運行前進行判斷,有就刪除。
在手動觸發一次。
可以看出先刪除了以前的容器,再重新運行了。
我們在最後做一次自動觸發:再server1上進行更改
[root@server1 demo]# vim index.html
[root@server1 demo]# cat index.html
www.caoaoyuan.ooooo
www.hhhhhhh.ooooo # 改動文件內容
www.hhhhhhh.ooooo
[root@server1 demo]# git commit -a -m "update index v2"
[master 3540479] update index v2
1 file changed, 3 insertions(+), 3 deletions(-)
[root@server1 demo]# git push -u origin master #推送
gitlab就直接更新了。
jenkins也自動進行了構建。
[root@server2 demo]# curl localhost
www.caoaoyuan.ooooo
www.hhhhhhh.ooooo
www.hhhhhhh.ooooo
server2上就可以直接訪問到了。
我們只改變了代碼,然後接下來的代碼的提交,鏡像的構建和交付就完全自動化了。這就是持續集成與持續交付。