什么是?DevOps?
DevOps?中的?Dev?是?Devlopment(開(kāi)發(fā)),Ops?是?Operation(運(yùn)維),用一句話來(lái)說(shuō)?DevOps?就是打通開(kāi)發(fā)運(yùn)維的壁壘,實(shí)現(xiàn)開(kāi)發(fā)運(yùn)維一體化。DevOps?整個(gè)流程包括敏捷開(kāi)發(fā)->持續(xù)集成->持 續(xù)交付->持續(xù)部署。

2.1.1?敏捷開(kāi)發(fā)
提高開(kāi)發(fā)效率,及時(shí)跟進(jìn)用戶(hù)需求,縮短開(kāi)發(fā)周期。 敏捷開(kāi)發(fā)包括編寫(xiě)代碼和構(gòu)建代碼兩個(gè)階段,可以使用?
git?或者?svn?來(lái)管理代碼,用?maven?對(duì)代碼 進(jìn)行構(gòu)建
2.1.2?持續(xù)集成(CI) 持續(xù)集成強(qiáng)調(diào)開(kāi)發(fā)人員提交了新代碼之后,立刻自動(dòng)的進(jìn)行構(gòu)建、(單元)測(cè)試。根據(jù)測(cè)試結(jié)果,我 們可以確定新代碼和原有代碼能否正確地集成在一起。持續(xù)集成過(guò)程中很重視自動(dòng)化測(cè)試驗(yàn)證結(jié)果, 對(duì)可能出現(xiàn)的一些問(wèn)題進(jìn)行預(yù)警,以保障最終合并的代碼沒(méi)有問(wèn)題。
常見(jiàn)的持續(xù)集成工具:
1. Jenkins
Jenkins?
是用?Java?語(yǔ)言編寫(xiě)的,是目前使用最多和最受歡迎的持續(xù)集成工具,使用?Jenkins,可以 自動(dòng)監(jiān)測(cè)到?git?或者?svn?存儲(chǔ)庫(kù)代碼的更新,基于最新的代碼進(jìn)行構(gòu)建,把構(gòu)建好的源碼或者鏡像發(fā) 布到生產(chǎn)環(huán)境。Jenkins?還有個(gè)非常好的功能:它可以在多臺(tái)機(jī)器上進(jìn)行分布式地構(gòu)建和負(fù)載測(cè)試?2. TeamCity
3. Travis CI
4. GoCD
5. Bamboo
6. GitLab CI?
7. Codeship

它的好處主要有以下幾點(diǎn):
?1)較早的發(fā)現(xiàn)錯(cuò)誤:每次集成都通過(guò)自動(dòng)化的構(gòu)建(包括編譯,發(fā)布,自動(dòng)化測(cè)試)來(lái)驗(yàn)證,哪個(gè) 環(huán)節(jié)出現(xiàn)問(wèn)題都可以較早的發(fā)現(xiàn)。?
2)快速的發(fā)現(xiàn)錯(cuò)誤:每完成一部分代碼的更新,就會(huì)把代碼集成到主干中,這樣就可以快速的發(fā)現(xiàn) 錯(cuò)誤,比較容易的定位錯(cuò)誤。?
3)提升團(tuán)隊(duì)績(jī)效:持續(xù)集成中代碼更新速度快,能及時(shí)發(fā)現(xiàn)小問(wèn)題并進(jìn)行修改,使團(tuán)隊(duì)能創(chuàng)造出更 好的產(chǎn)品。?
4)防止分支過(guò)多的偏離主干:經(jīng)常持續(xù)集成,會(huì)使分支代碼經(jīng)常向主干更新,當(dāng)單元測(cè)試失敗或者 出現(xiàn)?bug,如果開(kāi)發(fā)者需要在沒(méi)有調(diào)試的情況下恢復(fù)倉(cāng)庫(kù)的代碼到?jīng)]有?bug?的狀態(tài),只有很小部分 的代碼會(huì)丟失。 持續(xù)集成的目的是提高代碼質(zhì)量,讓產(chǎn)品快速的更新迭代。它的核心措施是,代碼集成到主干之前, 必須通過(guò)自動(dòng)化測(cè)試。只要有一個(gè)測(cè)試用例失敗,就不能集成。
Martin Fowler?說(shuō)過(guò),"持續(xù)集成并不能消除?Bug,而是讓它們非常容易發(fā)現(xiàn)和改正。"
2.1.3?持續(xù)交付 持續(xù)交付在持續(xù)集成的基礎(chǔ)上,將集成后的代碼部署到更貼近真實(shí)運(yùn)行環(huán)境的「類(lèi)生產(chǎn)環(huán)境」 (production-like environments)中。交付給質(zhì)量團(tuán)隊(duì)或者用戶(hù),以供評(píng)審。如果評(píng)審?fù)ㄟ^(guò),代 碼就進(jìn)入生產(chǎn)階段。如果所有的代碼完成之后一起交付,會(huì)導(dǎo)致很多問(wèn)題爆發(fā)出來(lái),解決起來(lái)很麻 煩,所以持續(xù)集成,也就是每更新一次代碼,都向下交付一次,這樣可以及時(shí)發(fā)現(xiàn)問(wèn)題,及時(shí)解決, 防止問(wèn)題大量堆積。
2.1.4?持續(xù)部署 持續(xù)部署是指當(dāng)交付的代碼通過(guò)評(píng)審之后,自動(dòng)部署到生產(chǎn)環(huán)境中。持續(xù)部署是持續(xù)交付的最高階 段。Puppet,SaltStack?和?Ansible?是這個(gè)階段使用的流行工具。容器化工具在部署階段也發(fā)揮著 重要作用。?Docker?和?k8s?是流行的工具,有助于在開(kāi)發(fā),測(cè)試和生產(chǎn)環(huán)境中實(shí)現(xiàn)一致性。 除此之 外,k8s?還可以實(shí)現(xiàn)自動(dòng)擴(kuò)容縮容等功能。
2.2.1?自動(dòng)化
敏捷開(kāi)發(fā)
->持續(xù)集成->持續(xù)交付->持續(xù)部署。
2.2.2?多集群管理
可以根據(jù)客戶(hù)需求對(duì)開(kāi)發(fā),測(cè)試,生產(chǎn)環(huán)境部署多套?
kubernetes?集群,每個(gè)環(huán)境使用獨(dú)立的物理資 源,相互之間避免影響。
2.2.3?多環(huán)境一致性
Kubernetes?是基于?docker?的容器編排工具,因?yàn)槿萜鞯溺R像是不可變的,所以鏡像把?OS、業(yè)務(wù) 代碼、運(yùn)行環(huán)境、程序庫(kù)、目錄結(jié)構(gòu)都包含在內(nèi),鏡像保存在我們的私有倉(cāng)庫(kù),只要用戶(hù)從我們提供 的私有倉(cāng)庫(kù)拉取鏡像,就能保證環(huán)境的一致性。
2.2.4?實(shí)時(shí)反饋和智能化報(bào)表 每次集成或交付,都會(huì)第一時(shí)間將結(jié)果通過(guò)多途徑的方式反饋給你,也可以定制適合企業(yè)專(zhuān)用的報(bào)表 平臺(tái)。

2.3
Jenkins+K8S+harbor+git+sonarqube+nexus?構(gòu)建?DevOps?容器云平臺(tái)流程
Jenkins?是開(kāi)源的?CI&CD?工具, 提供超過(guò)?1000?個(gè)插件來(lái)支持構(gòu)建、部署、自動(dòng)化, 滿(mǎn)足任何項(xiàng) 目的需要。完整的?DevOps?流程:
開(kāi)發(fā)提交代碼到代碼倉(cāng)庫(kù)?
gitlab-→jenkins?檢測(cè)到代碼更新-→調(diào)用?k8s api?在?k8s?中創(chuàng)建?jenkins slave pod:
d?拉取代碼---→通過(guò)?maven?把拉取的代碼進(jìn)行構(gòu)建成?war?包或者?jar?包--->上傳代碼到?Sonarqube,進(jìn)行靜態(tài)代碼掃描- -->基于?war?包構(gòu)建?docker image-->把鏡像上傳到?harbor?鏡 像倉(cāng)庫(kù)-->基于鏡像部署應(yīng)用到開(kāi)發(fā)環(huán)境-->部署應(yīng)用到測(cè)試環(huán)境--->部署應(yīng)用到生產(chǎn)環(huán)境。

基于?Jenkins+k8s+Git?等技術(shù)鏈構(gòu)建企業(yè)級(jí)?DevOps?自動(dòng)化容器云平臺(tái)
?1、安裝?Jenkins
可用如下兩種方法
1)通過(guò)?docker?直接下載?jenkins?鏡像,基于鏡像啟動(dòng)服務(wù)?2)在?k8s?中部署?Jenkins?服務(wù)
2、安裝?nfs?服務(wù)
#選擇自己的任意一臺(tái)機(jī)器,我選擇?k8s?的控制節(jié)點(diǎn) god63 1)、在 god63?上安裝?nfs,作為服務(wù)端
# yum install nfs-utils -y?
~]# systemctl start nfs
# systemctl enable nfs
2在 od63 和god64?上安裝?nfs,作為客戶(hù)端
yum install nfs-utils -y
systemctl start nfs && systemctl enable nfs
3、在 god63?上創(chuàng)建一個(gè)?nfs?共享目錄
# mkdir /data/v1 -p
# cat /etc/exports
/data/v1 192.168.1.0/24(rw,no_root_squash) #
使配置文件生效
# exportfs -arv
# systemctl restart nfs
3、在?kubernetes?中部署?jenkins
(1)創(chuàng)建名稱(chēng)空間
kubectl create namespace jenkins-k8s
(2)創(chuàng)建?pv
cat pv.yaml
apiVersion: v1
kind: PersistentVolume
metadata:
? name: jenkins-k8s-pv
spec:
? capacity:
? ? storage: 10Gi
? accessModes:
? - ReadWriteMany
? nfs:
? ? path: /data/v1
? ? server: 192.168.172.163
kubectl apply -f pv.yaml
(3)創(chuàng)建?pvc
cat pvc.yaml
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
? name: jenkins-k8s-pvc
? namespace: jenkins-k8s
spec:
? resources:
? ? requests:
? ? ? storage: 10Gi
? accessModes:
? - ReadWriteMany
kubectl apply -f pvc.yaml
#查看?pvc?和?pv?綁定是否成功
kubectl get pvc -n jenkins-k8s
NAME? ? ? ? ? ? ? STATUS? VOLUME? ? ? ? ? CAPACITY? ACCESS MODES? STORAGECLASS? AGE
jenkins-k8s-pvc? Bound? ? jenkins-k8s-pv? 10Gi? ? ? RWX? ? ? ? ? ? ? ? ? ? ? ? ? 33s
(4)創(chuàng)建一個(gè)?sa?賬號(hào)
kubectl create sa jenkins-k8s-sa -n jenkins-k8s
(5)把上面的?sa?賬號(hào)做?rbac?授權(quán)
# kubectl create clusterrolebinding jenkins-k8s-sa-cluster -n jenkins-k8s --clusterrole=cluster-admin --serviceaccount=jenkins-k8s:jenkins-k8s-sa
(6)通過(guò)?deployment?部署?jenkins
jenkins.tar.gz?和?jenkins-jnlp.tar.gz,把這兩個(gè)壓縮包上傳到?k8s?的 god64?和 god62?節(jié)點(diǎn),用如下方法手動(dòng)解壓:
cat jenkins-deployment.yaml
kind: Deployment
apiVersion: apps/v1
metadata:
? name: jenkins
? namespace: jenkins-k8s
spec:
? replicas: 1
? selector:
? ? matchLabels:
? ? ? app: jenkins
? template:
? ? metadata:
? ? ? labels:
? ? ? ? app: jenkins
? ? spec:
? ? ? serviceAccount: jenkins-k8s-sa
? ? ? containers:
? ? ? - name: jenkins
? ? ? ? image: ?god/jenkins:v1
? ? ? ? imagePullPolicy: IfNotPresent
? ? ? ? ports:
? ? ? ? - containerPort: 8080
? ? ? ? ? name: web
? ? ? ? ? protocol: TCP
? ? ? ? - containerPort: 50000
? ? ? ? ? name: agent
? ? ? ? ? protocol: TCP
? ? ? ? resources:
? ? ? ? ? limits:
? ? ? ? ? ? cpu: 1000m
? ? ? ? ? ? memory: 1Gi
? ? ? ? ? requests:
? ? ? ? ? ? cpu: 500m
? ? ? ? ? ? memory: 512Mi
? ? ? ? livenessProbe:
? ? ? ? ? httpGet:
? ? ? ? ? ? path: /login
? ? ? ? ? ? port: 8080
? ? ? ? ? initialDelaySeconds: 60
? ? ? ? ? timeoutSeconds: 5
? ? ? ? ? failureThreshold: 12
? ? ? ? readinessProbe:
? ? ? ? ? httpGet:
? ? ? ? ? ? path: /login
? ? ? ? ? ? port: 8080
? ? ? ? ? initialDelaySeconds: 60
? ? ? ? ? timeoutSeconds: 5
? ? ? ? ? failureThreshold: 12
? ? ? ? volumeMounts:
? ? ? ? - name: jenkins-volume
? ? ? ? ? subPath: jenkins-home
? ? ? ? ? mountPath: /var/jenkins_home
? ? ? volumes:
? ? ? - name: jenkins-volume
? ? ? ? persistentVolumeClaim:
? ? ? ? ? claimName: jenkins-k8s-pvc
kubectl apply -f jenkins-deployment.yaml
kubectl get pods -n jenkins-k8s
NAME? ? ? ? ? ? ? ? ? ? ? READY? STATUS? ? ? ? ? ? RESTARTS? AGE
jenkins-567cbdf4c8-zpp4x? 0/1? ? CrashLoopBackOff? 2? ? ? ? ? 29s
#上面可以看到?CrashLoopBackOff,解決方法如下:
kubectl describe pods jenkins-567cbdf4c8-zpp4x -n jenkins-k8s
#查看?jenkins-567cbdf4c8-zpp4x ?日志
kubectl logs jenkins-567cbdf4c8-zpp4x -n jenkins-k8s
touch: cannot touch '/var/jenkins_home/copy_reference_file.log': Permission denied
Can not write to /var/jenkins_home/copy_reference_file.log. Wrong volume permissions?
#上面問(wèn)題是因?yàn)?data/v1?目錄權(quán)限問(wèn)題,按如下方法解決:
chown -R 1000.1000 /data/v1/
kubectl delete -f jenkins-deployment.yaml
kubectl apply -f jenkins-deployment.yaml
kubectl get pods -n jenkins-k8s
NAME? ? ? ? ? ? ? ? ? ? ? READY? STATUS? ? RESTARTS? AGE
jenkins-567cbdf4c8-j5s5l? 1/1? ? Running? 1? ? ? ? ? 101s
(7)把?jenkins?前端加上?service,提供外部網(wǎng)絡(luò)訪問(wèn)
cat jenkins-service.yaml
apiVersion: v1
kind: Service
metadata:
? name: jenkins-service
? namespace: jenkins-k8s
? labels:
? ? app: jenkins
spec:
? selector:
? ? app: jenkins
? type: NodePort
? ports:
? - name: web
? ? port: 8080
? ? targetPort: web
? ? nodePort: 30002
? - name: agent
? ? port: 50000
? ? targetPort: agent
kubectl apply -f jenkins-service.yaml
kubectl get svc -n jenkins-k8s
NAME? ? ? ? ? ? ? TYPE? ? ? CLUSTER-IP? ? ? EXTERNAL-IP? PORT(S)? ? ? ? ? ? ? ? ? ? ? ? ? AGE
jenkins-service? NodePort? 10.102.145.119? <none>? ? ? ? 8080:30002/TCP,50000:31457/TCP? 45s
4、配置?Jenkins
在瀏覽器訪問(wèn)?jenkins?的?web?界面:

1)獲取管理員密碼
在 nfs?服務(wù)端,也就是我們的 god63?節(jié)點(diǎn)獲取密碼:
# cat /data/v1/jenkins-home/secrets/initialAdminPassword f9b0b4400c4a4d6eaec6762616db6d63?把獲取到的密碼拷貝到上面管理員密碼下的方框里
點(diǎn)擊繼續(xù),出現(xiàn)如下界面
2)安裝插件 安裝推薦的插件
離線安裝?jenkins?插件:
https://plugins.jenkins.io/

用戶(hù)名和密碼都設(shè)置成?admin,需要設(shè)置成復(fù)雜的密碼 修改好之后點(diǎn)擊保存并完成,出現(xiàn)如下界面 點(diǎn)擊保存并完成

5、測(cè)試?jenkins?的?CI/CD
#在?Jenkins?中安裝?kubernetes?插件 (1)在?jenkins?中安裝?k8s?插件
Manage Jnekins------>插件管理------>可選插件------>搜索?kubernetes------>出現(xiàn)如下

選中?kubernetes?之后------>點(diǎn)擊下面的直接安裝------>安裝之后選擇重新啟動(dòng)?jenkins---> http://192.168.172.63:30002/restart-->重啟之后登陸?jenkins?即可