Devops简介

k8s助力Devops在企业落地实践

传统方式部署项目为什么发布慢,效率低?

上线一个功能,有多少时间被浪费了?

如何解决发布慢,效率低的问题呢?

什么是Devops?

敏捷开发

提高开发效率,及时跟进用户需求,缩短开发周期。

敏捷开发包括编写代码和构建代码两个阶段,可以使用git或者svn来管理代码,用maven对代码进行构建。

持续集成(CI)

持续集成强调开发人员提交了新代码之后,立刻自动的进行构建、(单元)测试。根据测试结果,可以确定新代码和原有代码能否正确地集成在一起。持续集成过程中很重视自动化测试验证结果,对可能出现的一些问题进行预警,以保障最终合并的代码没有问题。

常见的持续集成工具:

Jenkins

Jenkins是用Java语言编写的,是目前使用最多和最受欢迎的持续集成工具,使用Jenkins,可以自动监测到git或者svn存储库代码的更新,基于最新的代码进行构建,把构建好的源码或者镜像发布到生产环境。Jenkins还有个非常好的功能:它可以在多台机器上进行分布式地构建和负载测试 TeamCityTravis CIGo CDBambooGitLab CICodeship

它的好处主要有以下几点:

较早的发现错误:每次集成都通过自动化的构建(包括编译、发布、自动化测试)来验证,哪个环节出现问题都可以较早的发现快速的发现错误:每完成一部分代码的更新,就会把代码集成到主干中,这样就可以快速的发现错误,比较容易的定位错误提升团队绩效:持续集成中代码更新速度快,能及时发现小问题并进行修改,使团队能创造出更好的产品防止分支过多的偏离主干:经常持续集成,会使分支代码经常向主干更新,当单元测试失败或者出现bug,如果开发者需要在没有调试的情况下恢复仓库的代码到没有bug的状态,只有很小部分的代码会丢失

持续集成的目的是提高代码质量,让产品快速的更新迭代。它的核心措施是,代码集成到主干之前,必须通过自动化测试。只要有一个测试用例失败,就不能集成。

Martin Fowler说过:“持续集成并不能消除bug,而是让它们非常容易发现和纠正。”

持续交付

持续交付在持续集成的基础上,将集成后的代码部署到更贴近真实运行环境的“类生产环境”中。交付给质量团队或者用户,以供评审。如果评审通过,代码就进入生产阶段。

如果所有的代码完成之后一起交付,会导致很多问题爆发出来,解决起来很麻烦,所以持续集成,也就是每更新一次代码,都向下交付一次,这样可以及时发现问题,及时解决,防止问题大量堆积。

持续部署

持续部署是指当交付的代码通过评审之后,自动部署到生产环境中。持续部署是持续交付的最高阶段。

k8s在Devops中的核心作用

docker和k8s的出现使devops变得更加普及,更加容易实现。在传统运维中我们服务时需要针对不同的环境去安装不同的版本,部署方式也杂、多。那么有了docker之后,一次构建、到处运行,只需要构建一次镜像,那么只要有docker的主机,就可以基于镜像把应用跑起来。

在至多微服务中,每天可能需要去处理各种服务的崩溃,而服务间的依赖调用关系也极其复杂,这队解决问题带来了很大的复杂度。要很好的解决这个问题,就需要用到容器编排工具。

kubernetes的出现主宰了容器编排的市场,也进化了过去的运维方式,将开发与运维联系的更加紧密。而且让devops这一角色变得更加清晰,它是目前可用的很流行的容器解决方案之一。

自动化

敏捷开发---->持续集成---->持续交付---->持续部署

多集群管理

可以根据客户需求对开发,测试,生产环境部署多套kubernetes集群,每个环境使用独立的物理资源,相互之间避免影响。

多环境一致性

kubernetes是基于docker的容器编排工具,因为容器的镜像是不可变的,所以镜像把OS、业务代码、运行环境、程序库、目录结构都包含在内,镜像保存在我们的私有仓库,只要用户从我们提供的私有仓库拉取镜像,就能保证环境的一致性。

实时反馈和智能化报表

每次集成或交付,都会第一时间将结果通过多途径的方式反馈给你,也可以定制适合企业专用的报表平台。

前情提要:

我的节点以及k8s版本

主从的ip:

ipwentaomaster1192.168.184.10wentaonode1192.168.184.20

安装nfs存储

#安装nfs并设置开机自启动,主从都需要安装

[root@wentaomaster1 ~]#yum install -y nfs-utils

[root@wentaomaster1 ~]#systemctl enable nfs --now

[root@wentaonode1 ~]#yum install -y nfs-utils

[root@wentaonode1 ~]#systemctl enable nfs --now

#配置nfs存储目录,仅在master节点配置

[root@wentaomaster1 ~]# vim /etc/exports

/data/v2 *(rw,no_root_squash)

#使nfs配置生效

[root@wentaomaster1 ~]# exportfs -arv

创建数据存储挂载

创建项目所用的名称空间

[root@wentaomaster1 jenkins-k8s]# kubectl create namespace jenkins-k8s

namespace/jenkins-k8s created

创建存储用的pv

[root@wentaomaster1 jenkins-k8s]# cat pv.yaml

apiVersion: v1

kind: PersistentVolume

metadata:

name: jenkins-k8s-pv

spec:

capacity:

storage: 10Gi

accessModes:

- ReadWriteMany

nfs:

server: 192.168.184.10

path: /data/v2

[root@wentaomaster1 ~]# kubectl apply -f pv.yaml

创建pvc

[root@wentaomaster1 jenkins-k8s]# cat pvc.yaml

kind: PersistentVolumeClaim

apiVersion: v1

metadata:

name: jenkins-k8s-pvc

namespace: jenkins-k8s

spec:

resources:

requests:

storage: 10Gi

accessModes:

- ReadWriteMany

[root@wentaomaster1 ~]# kubectl apply -f pvc.yaml

创建serviceaccount并RBAC授权

创建一个服务账号sa并对其授权

[root@wentaomaster1 ~]# kubectl create sa jenkins-k8s-sa -n jenkins-k8s

#对sa服务账号授予系统角色cluster-admin的权限【RBAC】

[root@wentaomaster1 ~]# kubectl create clusterrolebinding jenkins-k8s-sa-cluster -n jenkins-k8s --clusterrole=cluster-admin --serviceaccount=jenkins-k8s:jenkins-k8s-sa

准备项目需要的镜像

在工作节点上,从dockerhub上拉取jenkins镜像(我用的2.418)

#用于安装jenkins用

[root@wentaonode1 ~]# docker pull jenkins/jenkins:2.418

创建一个dockerfile构建镜像jenkins-slave-latest:v1

[root@wentaomaster1 slave]# cat dockerfile

FROM jenkins/jnlp-slave:4.13.3-1-jdk11

USER root

# 安装Docker

RUN apt-get update && apt-get install -y \

docker.io

# 将当前用户加入docker用户组

RUN usermod -aG docker jenkins

RUN curl -LO https://dl.k8s.io/release/stable.txt

RUN curl -LO https://dl.k8s.io/release/$(cat stable.txt)/bin/linux/amd64/kubectl

RUN chmod +x kubectl

RUN mv kubectl /usr/local/bin/

ENV DOCKER_HOST unix:///var/run/docker.sock

#k8s中装好jenkins后,是有主从的,构建jenkins时候会在集群里再创建一个jenkins从,我用jenkins-slave-latest这个镜像来构建jenkins从

[root@wentaomaster1 slave]# docker build -t=jenkins-slave-latest:v1 .

安装jenkins

给nfs的数据目录/data/v2做下权限

[root@wentaomaster1 ~]# chown -R 1000.1000 /data/v2

使用deployment控制器创建jenkins pod

[root@wentaomaster1 ~]# cat jenkins-deploy.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: docker.io/jenkins/jenkins:2.418

imagePullPolicy: IfNotPresent

ports:

- containerPort: 8080

name: web

protocol: TCP

- containerPort: 50000

name: agent

protocol: TCP

resources:

limits:

cpu: 2000m

memory: 2Gi

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

[root@wentaomaster1 ~]# kubectl apply -f jenkins-deploy.yaml

给jenkins pod前端加上service,对外部提供网络访问

[root@wentaomaster1 ~]# 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

[root@wentaomaster1 ~]# kubectl apply -f jenkins-service.yaml

#通过kubectl get svc -n 看到对外提供的端口是30002

登录jenkins web页面

浏览器网址栏输入192.168.184.10:30002

可以看到提示为:初始密码在跑jenkins的pod里面的/var/jenkins_home/secrets/initialAdminPassword文件中

将密码复制后,点击继续

选择“安装推荐的插件”

安装完成之后,创建管理员用户

实例配置不改,用默认url

更新kubernetes插件

点击安装后,下滑到最下面,勾选安装后重启

安装完成后,再安装jenkins自动化部署的ui界面Blue Ocean

输入之前设置的用户、密码,选择保持登录状态

jenkins对接kubernetes自动生成jenkins从节点

新增一个云kubernetes

填写云kubernetes配置内容

名称:kuberneteskubernetes地址:https://192.168.184.10:6443

6443是kubernetes apiserver的端口 kubernetes命名空间:jenkins-k8s

Jenkins UI界面配置访问Dockerhub凭据

添加dockerhub凭据

jenkins+k8s自动化发布项目

准备好各个环境的命名空间

#创建开发、生产、测试的命名空间

[root@wentaomaster1 ~]# kubectl create ns devlopment

[root@wentaomaster1 ~]# kubectl create ns production

[root@wentaomaster1 ~]# kubectl create ns qatest

创建流水线自动化发布任务,左侧栏点击新建任务

node('testtan') {

stage('Clone') {

echo "1.Clone Stage"

git url: "https://github.com/twttwttwt/jenkins-sample/"

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 twttwt/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 twttwt/jenkins-demo:${build_tag}"

}

}

stage('Deploy to dev') {

echo "5. Deploy DEV"

sh "sed -i 's//${build_tag}/' k8s-dev.yaml"

sh "sed -i 's//${env.BRANCH_NAME}/' k8s-dev.yaml"

// sh "bash running-devlopment.sh"

sh "kubectl apply -f k8s-dev.yaml --validate=false"

}

stage('Promote to qa') {

def userInput = input(

id: 'userInput',

message: 'Promote to qa?',

parameters: [

[

$class: 'ChoiceParameterDefinition',

choices: "YES\nNO",

name: 'Env'

]

]

)

echo "This is a deploy step to ${userInput}"

if (userInput == "YES") {

sh "sed -i 's//${build_tag}/' k8s-qa.yaml"

sh "sed -i 's//${env.BRANCH_NAME}/' k8s-qa.yaml"

// sh "bash running-qa.sh"

sh "kubectl apply -f k8s-qa.yaml --validate=false"

sh "sleep 6"

sh "kubectl get pods -n qatest"

} else {

//exit

}

}

stage('Promote to pro') {

def userInput = input(

id: 'userInput',

message: 'Promote to pro?',

parameters: [

[

$class: 'ChoiceParameterDefinition',

choices: "YES\nNO",

name: 'Env'

]

]

)

echo "This is a deploy step to ${userInput}"

if (userInput == "YES") {

sh "sed -i 's//${build_tag}/' k8s-prod.yaml"

sh "sed -i 's//${env.BRANCH_NAME}/' k8s-prod.yaml"

// sh "bash running-production.sh"

sh "cat k8s-prod.yaml"

sh "kubectl apply -f k8s-prod.yaml --record --validate=false"

}

}

}

点击保存后回到dashboard,可以看到已经多出来了一条任务,点击构建

[root@wentaomaster1 ~]# kubectl get pod -n production

[root@wentaomaster1 ~]# kubectl get pod -n devlopment

[root@wentaomaster1 ~]# kubectl get pod -n qatest

#通过上面可以看到jenkins对接k8s,可以把应用发布到k8s集群的开发、测试、生产环境了。

访问github中index配置的web页面

devops自动化版本更新

修改上图web页面的index文件

此时访问web页面,暂时没有改动

回到dashboard,重新执行一次pipeline文件

可以看到,已成功更新

Devops自动化版本回滚

新建任务

node('testtan') {

stage('git clone') {

git url: "https://github.com/twttwttwt/jenkins-rollout"

sh "ls -al"

sh "pwd"

}

stage('select env') {

def envInput = input(

id: 'envInput',

message: 'Choose a deploy environment',

parameters: [

[

$class: 'ChoiceParameterDefinition',

choices: "devlopment\nqatest\nproduction",

name: 'Env'

]

]

)

echo "This is a deploy step to ${envInput}"

sh "sed -i 's//${envInput}/' getVersion.sh"

sh "sed -i 's//${envInput}/' rollout.sh"

sh "bash getVersion.sh"

// env.WORKSPACE = pwd()

// def version = readFile "${env.WORKSPACE}/version.csv"

// println version

}

stage('select version') {

env.WORKSPACE = pwd()

def version = readFile "${env.WORKSPACE}/version.csv"

println version

def userInput = input(id: 'userInput',

message: '选择回滚版本',

parameters: [

[

$class: 'ChoiceParameterDefinition',

choices: "$version\n",

name: 'Version'

]

]

)

sh "sed -i 's//${userInput}/' rollout.sh"

}

stage('rollout deploy') {

sh "bash rollout.sh"

}

}

保存后回到首页

推荐文章

评论可见,请评论后查看内容,谢谢!!!评论后请刷新页面。