十年网站开发经验 + 多家企业客户 + 靠谱的建站团队
量身定制 + 运营维护+专业推广+无忧售后,网站问题一站解决
用k8s+jenkins+github+dockerhub部署应用:
jenkins有两种方式实现CI/CD
1、自由风格,通过shell代码实现
2、pipeline流水线,通过jenkins代码或者jenkinsfile文件实现
Pipeline 有两种创建方法:
1、可以直接在 Jenkins 的 Web UI 界面中输入jenkins代码;
2、也可以通过创建一个 Jenkinsfile 脚本文件放入项目源码库中
成都创新互联公司成立10年来,这条路我们正越走越好,积累了技术与客户资源,形成了良好的口碑。为客户提供成都网站设计、成都做网站、网站策划、网页设计、域名申请、网络营销、VI设计、网站改版、漏洞修补等服务。网站是否美观、功能强大、用户体验好、性价比高、打开快等等,这些对于网站建设都非常重要,成都创新互联公司通过对建站技术性的掌握、对创意设计的研究为客户提供一站式互联网解决方案,携手广大客户,共同发展进步。
构建一个新项目步骤:
1、在github上新建一个项目
2、在本地将项目克隆下来
3、编写代码,dockerfile,jenkinsfile,部署该应用的yaml文件
4、将项目代码push到github上
5、使用jenkins实现CI/CD
示例:
1、在github上新建一个项目nginx-demo(略)
2、克隆代码到本地192.168.1.244
$ git clone https://github.com/dongyali521521/nginx-demo
除了第一次clone,以后每次clone都要先删除原项目再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中新建任务实现CI/CD
一般情况下,除了应用程序代码之外,dockerfile,jenkinsfile和部署该应用的yaml文件都放在源码中一起管理。
一个项目内至少包括如下文件:都需要在实现CI/CD前准备好
$ cd nginx-demo/
$ ls
Dockerfile Jenkinsfile xxx.yaml index.html README.md
在k8s中使用jenkins实现CI/CD(pipeline方式)又包括如下步骤:
1、从git hub把项目克隆到jenkins slave pod的工作目录/home/jenkins/agent/workspace/pipeline-name
2、测试
3、使用Dockerfile构建镜像
4、把构建的镜像push到docker hub上
5、修改yaml文件中的镜像名为刚才构建的镜像
6、在k8s集群中部署应用
以上步骤的代码可以在jenkins master的任务配置界面输入,也可以写入Jenkinsfile文件在项目源码库中管理
前4步属于CI阶段,最后两步属于CD阶段
Jenkins Pipeline 有几个核心概念:
Node:节点,一个 Node 就是一个 Jenkins 节点,Master 或者 slave
Stage:阶段,一个 Pipeline 可以划分为若干个 Stage,每个 Stage 代表一组操作
Step:步骤,Step 是最基本的操作单元,可以是打印一句话,也可以是构建一个 Docker 镜像
用jenkins代码模拟CI/CD步骤
新建任务----名字----流水线
在流水线脚本中输入如下内容----保存立即构建
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"
}
}
假设项目nginx-demo已经开发完毕,并上传到了git hub上
文件包括:
Dockerkfile k8s.yaml index.html README.md
k8s.yaml是部署该应用的文件
$ 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:
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,默认会把应用部署到k8s集群的kube-ops空间,因为jenkins slave pod运行在kube-ops空间内。
下面开始在jenkins中部署上述项目:
因为每次git commit之后都要构建镜像重新部署应用,所以采用git commit的记录作为镜像的 tag
为了安全,把构建的镜像push到docker hub上时,需要输入加密的用户名和密码
凭据----Stores scoped to Jenkin下面的Jenkins----全局凭据----添加凭据:
用户名:docker hub的用户名
密码:输入docker hub的用户密码
ID:dockerHub,可以随便写,后面要用
在CD阶段开始之前需要人工干预,以便于部署到用户选择的环境
http://192.168.1.243:30003
新建任务----名字----流水线
在流水线脚本中输入如下内容----保存立即构建
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}/' 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"
}
}
每次构建,都会启动一个新的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
http://http://192.168.1.243:30185/
下面再使用jenkinsfile文件来部署应用
在项目目录nginx-demo下增加一个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}/' 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源码库中,所以第一步就不需要再clone了,改为checkout scm
然后在jenkins配置任务界面选择:
流水线----pipeline脚本from SCM
SCM:git
Repository URL:https://github.com/dongyali521521/nginx-demo
Credentials:无
保存构建即可。
再测试一个项目
$ 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:
imagePullPolicy: IfNotPresent
name: jenkins-demo
env:
- name: branch
value:
$ git add .
$ git commit -m "4444"
$ git push
新建任务----名字----流水线
在流水线脚本中输入如下内容----保存立即构建
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}/' 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: