您好,登錄后才能下訂單哦!
用k8s+jenkins+github+dockerhub部署應(yīng)用:
jenkins有兩種方式實(shí)現(xiàn)CI/CD
1、自由風(fēng)格,通過shell代碼實(shí)現(xiàn)
2、pipeline流水線,通過jenkins代碼或者jenkinsfile文件實(shí)現(xiàn)
Pipeline 有兩種創(chuàng)建方法:
1、可以直接在 Jenkins 的 Web UI 界面中輸入jenkins代碼;
2、也可以通過創(chuàng)建一個(gè) Jenkinsfile 腳本文件放入項(xiàng)目源碼庫(kù)中
構(gòu)建一個(gè)新項(xiàng)目步驟:
1、在github上新建一個(gè)項(xiàng)目
2、在本地將項(xiàng)目克隆下來
3、編寫代碼,dockerfile,jenkinsfile,部署該應(yīng)用的yaml文件
4、將項(xiàng)目代碼push到github上
5、使用jenkins實(shí)現(xiàn)CI/CD
示例:
1、在github上新建一個(gè)項(xiàng)目nginx-demo(略)
2、克隆代碼到本地192.168.1.244
$ git clone https://github.com/dongyali521521/nginx-demo
除了第一次clone,以后每次clone都要先刪除原項(xiàng)目再clone
$ rm -rf nginx-demo
3、修改代碼
$ cd nginx-demo/
$ vim index.html
4、將修改后的代碼push到github
$ git add .
$ git commit -m "2222"
$ git push #需要輸入github的用戶名和密碼
5、在jenkins中新建任務(wù)實(shí)現(xiàn)CI/CD
一般情況下,除了應(yīng)用程序代碼之外,dockerfile,jenkinsfile和部署該應(yīng)用的yaml文件都放在源碼中一起管理。
一個(gè)項(xiàng)目?jī)?nèi)至少包括如下文件:都需要在實(shí)現(xiàn)CI/CD前準(zhǔn)備好
$ cd nginx-demo/
$ ls
Dockerfile Jenkinsfile xxx.yaml index.html README.md
在k8s中使用jenkins實(shí)現(xiàn)CI/CD(pipeline方式)又包括如下步驟:
1、從git hub把項(xiàng)目克隆到j(luò)enkins slave pod的工作目錄/home/jenkins/agent/workspace/pipeline-name
2、測(cè)試
3、使用Dockerfile構(gòu)建鏡像
4、把構(gòu)建的鏡像push到docker hub上
5、修改yaml文件中的鏡像名為剛才構(gòu)建的鏡像
6、在k8s集群中部署應(yīng)用
以上步驟的代碼可以在jenkins master的任務(wù)配置界面輸入,也可以寫入Jenkinsfile文件在項(xiàng)目源碼庫(kù)中管理
前4步屬于CI階段,最后兩步屬于CD階段
Jenkins Pipeline 有幾個(gè)核心概念:
Node:節(jié)點(diǎn),一個(gè) Node 就是一個(gè) Jenkins 節(jié)點(diǎn),Master 或者 slave
Stage:階段,一個(gè) Pipeline 可以劃分為若干個(gè) Stage,每個(gè) Stage 代表一組操作
Step:步驟,Step 是最基本的操作單元,可以是打印一句話,也可以是構(gòu)建一個(gè) Docker 鏡像
用jenkins代碼模擬CI/CD步驟
新建任務(wù)----名字----流水線
在流水線腳本中輸入如下內(nèi)容----保存立即構(gòu)建
node('dongyali-jnlp') {
stage('Clone') {
echo "1.Clone Stage"
}
stage('Test') {
echo "2.Test Stage"
}
stage('Build') {
echo "3.Build Docker Image Stage"
}
stage('Push') {
echo "4.Push Docker Image Stage"
}
stage('YAML') {
echo "5. Change YAML File Stage"
}
stage('Deploy') {
echo "6. Deploy Stage"
}
}
假設(shè)項(xiàng)目nginx-demo已經(jīng)開發(fā)完畢,并上傳到了git hub上
文件包括:
Dockerkfile k8s.yaml index.html README.md
k8s.yaml是部署該應(yīng)用的文件
$ cd nginx-demo/
$ cat Dockerfile
FROM docker.io/nginx
MAINTAINER dongyali
ADD index.html /usr/share/nginx/html/
EXPOSE 80
CMD ["nginx", "-g","daemon off;"]
$ cat k8s.yaml
apiVersion: extensions/v1beta1
kind: Deployment
metadata:
name: nginx-demo
namespace: default
spec:
replicas: 3
template:
metadata:
labels:
app: nginx-demo
spec:
containers:
- image: dongyali521521/nginx-demo:<BUILD_TAG>
imagePullPolicy: IfNotPresent
name: nginx-demo
ports:
- containerPort: 80
---
apiVersion: v1
kind: Service
metadata:
name: nginx-demo
namespace: default
spec:
selector:
app: nginx-demo
type: NodePort
ports:
- protocol: TCP
port: 80
targetPort: 80
name: myapp-http
如果不指定namespace,默認(rèn)會(huì)把應(yīng)用部署到k8s集群的kube-ops空間,因?yàn)閖enkins slave pod運(yùn)行在kube-ops空間內(nèi)。
下面開始在jenkins中部署上述項(xiàng)目:
因?yàn)槊看蝕it commit之后都要構(gòu)建鏡像重新部署應(yīng)用,所以采用git commit的記錄作為鏡像的 tag
為了安全,把構(gòu)建的鏡像push到docker hub上時(shí),需要輸入加密的用戶名和密碼
憑據(jù)----Stores scoped to Jenkin下面的Jenkins----全局憑據(jù)----添加憑據(jù):
用戶名:docker hub的用戶名
密碼:輸入docker hub的用戶密碼
ID:dockerHub,可以隨便寫,后面要用
在CD階段開始之前需要人工干預(yù),以便于部署到用戶選擇的環(huán)境
http://192.168.1.243:30003
新建任務(wù)----名字----流水線
在流水線腳本中輸入如下內(nèi)容----保存立即構(gòu)建
node('dongyali-jnlp') {
stage('Clone') {
echo "1.Clone Stage"
git url: "https://github.com/dongyali521521/nginx-demo.git"
script {
build_tag = sh(returnStdout: true, script: 'git rev-parse --short HEAD').trim()
}
}
stage('Test') {
echo "2.Test Stage"
}
stage('Build') {
echo "3.Build Docker Image Stage"
sh "docker build -t dongyali521521/nginx-demo:${build_tag} ."
}
stage('Push') {
echo "4.Push Docker Image Stage"
withCredentials([usernamePassword(credentialsId: 'dockerHub', passwordVariable: 'dockerHubPassword', usernameVariable: 'dockerHubUser')]) {
sh "docker login -u ${dockerHubUser} -p ${dockerHubPassword}"
sh "docker push dongyali521521/nginx-demo:${build_tag}"
}
}
stage('Deploy') {
echo "5. Deploy Stage"
def userInput = input(
id: 'userInput',
message: 'Choose a deploy environment',
parameters: [
[
$class: 'ChoiceParameterDefinition',
choices: "Dev\nQA\nProd",
name: 'Env'
]
]
)
echo "This is a deploy step to ${userInput}"
sh "sed -i 's/<BUILD_TAG>/${build_tag}/' k8s.yaml"
if (userInput == "Dev") {
// deploy dev stuff
} else if (userInput == "QA"){
// deploy qa stuff
} else {
// deploy prod stuff
}
sh "kubectl apply -f k8s.yaml --record"
}
}
每次構(gòu)建,都會(huì)啟動(dòng)一個(gè)新的jenkins slave pod
查看部署情況:
$ kubectl get pod
nginx-demo-65f6f679c6-5ljvd 1/1 Running 0 34m
nginx-demo-65f6f679c6-p4g6m 1/1 Running 0 34m
nginx-demo-65f6f679c6-xr7mx 1/1 Running 0 34m
$ kubectl get svc
nginx-demo NodePort 10.103.13.141 <none> 80:30185/TCP 18h
http://http://192.168.1.243:30185/
下面再使用jenkinsfile文件來部署應(yīng)用
在項(xiàng)目目錄nginx-demo下增加一個(gè)Jenkinsfile文件,并上傳到git hub上
$ cd nginx-demo/
$ cat Jenkinsfile
node('dongyali-jnlp') {
stage('Prepare') {
echo "1.Prepare Stage"
checkout scm
script {
build_tag = sh(returnStdout: true, script: 'git rev-parse --short HEAD').trim()
}
}
stage('Test') {
echo "2.Test Stage"
}
stage('Build') {
echo "3.Build Docker Image Stage"
sh "docker build -t dongyali521521/nginx-demo:${build_tag} ."
}
stage('Push') {
echo "4.Push Docker Image Stage"
withCredentials([usernamePassword(credentialsId: 'dockerHub', passwordVariable: 'dockerHubPassword', usernameVariable: 'dockerHubUser')]) {
sh "docker login -u ${dockerHubUser} -p ${dockerHubPassword}"
sh "docker push dongyali521521/nginx-demo:${build_tag}"
}
}
stage('Deploy') {
echo "5. Deploy Stage"
def userInput = input(
id: 'userInput',
message: 'Choose a deploy environment',
parameters: [
[
$class: 'ChoiceParameterDefinition',
choices: "Dev\nQA\nProd",
name: 'Env'
]
]
)
echo "This is a deploy step to ${userInput}"
sh "sed -i 's/<BUILD_TAG>/${build_tag}/' k8s.yaml"
if (userInput == "Dev") {
// deploy dev stuff
} else if (userInput == "QA"){
// deploy qa stuff
} else {
// deploy prod stuff
}
sh "kubectl apply -f k8s.yaml --record"
}
}
由于Jenkinsfile和其他代碼都在git hub源碼庫(kù)中,所以第一步就不需要再clone了,改為checkout scm
然后在jenkins配置任務(wù)界面選擇:
流水線----pipeline腳本from SCM
SCM:git
Repository URL:https://github.com/dongyali521521/nginx-demo
Credentials:無
保存構(gòu)建即可。
再測(cè)試一個(gè)項(xiàng)目
$ git clone https://github.com/dongyali521521/jenkins-demo.git
$ cd jenkins-demo
$ ls
Dockerfile k8s.yaml main.go README.md
$ cat Dockerfile
FROM golang:1.8.0-alpine
ADD . /go/src/app
WORKDIR /go/src/app
RUN GOOS=linux GOARCH=386 go build -v -o /go/src/app/jenkins-app
CMD ["./jenkins-app"]
$ cat main.go
package main
// Import the fmt for formatting strings
// Import os so we can read environment variables from the system
import (
"fmt"
"os"
)
func main() {
fmt.Println("Hello, Kubernetes!I'm from Jenkins CI!4444")
fmt.Println("BRANCH_NAME:", os.Getenv("branch"))
}
$ cat k8s.yaml
apiVersion: extensions/v1beta1
kind: Deployment
metadata:
name: jenkins-demo
namespace: default
spec:
template:
metadata:
labels:
app: jenkins-demo
spec:
containers:
- image: dongyali521521/jenkins-demo:<BUILD_TAG>
imagePullPolicy: IfNotPresent
name: jenkins-demo
env:
- name: branch
value: <BRANCH_NAME>
$ git add .
$ git commit -m "4444"
$ git push
新建任務(wù)----名字----流水線
在流水線腳本中輸入如下內(nèi)容----保存立即構(gòu)建
node('dongyali-jnlp') {
stage('Clone') {
echo "1.Clone Stage"
git url: "https://github.com/dongyali521521/jenkins-demo.git"
script {
build_tag = sh(returnStdout: true, script: 'git rev-parse --short HEAD').trim()
}
}
stage('Test') {
echo "2.Test Stage"
}
stage('Build') {
echo "3.Build Docker Image Stage"
sh "docker build -t dongyali521521/jenkins-demo:${build_tag} ."
}
stage('Push') {
echo "4.Push Docker Image Stage"
withCredentials([usernamePassword(credentialsId: 'dockerHub', passwordVariable: 'dockerHubPassword', usernameVariable: 'dockerHubUser')]) {
sh "docker login -u ${dockerHubUser} -p ${dockerHubPassword}"
sh "docker push dongyali521521/jenkins-demo:${build_tag}"
}
}
stage('Deploy') {
echo "5. Deploy Stage"
def userInput = input(
id: 'userInput',
message: 'Choose a deploy environment',
parameters: [
[
$class: 'ChoiceParameterDefinition',
choices: "Dev\nQA\nProd",
name: 'Env'
]
]
)
echo "This is a deploy step to ${userInput}"
sh "sed -i 's/<BUILD_TAG>/${build_tag}/' k8s.yaml"
if (userInput == "Dev") {
// deploy dev stuff
} else if (userInput == "QA"){
// deploy qa stuff
} else {
// deploy prod stuff
}
sh "kubectl apply -f k8s.yaml --record"
}
}
$ kubectl get pod
jenkins-demo-67db45cf6c-mjdl4 0/1 CrashLoopBackOff 3 65s
$ kubectl logs jenkins-demo-67db45cf6c-mjdl4
Hello, Kubernetes!I'm from Jenkins CI!4444
BRANCH_NAME:
免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長(zhǎng)郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。