DevOps

DevOps: Development 和 Operations 的组合

  • DevOps 看作开发(软件工程)、技术运营和质量保障(QA)三者的交集。
  • 突出重视软件开发人员和运维人员的沟通合作,通过自动化流程来使得软件构建、测试、 发布更加快捷、频繁和可靠。
  • DevOps 希望做到的是软件产品交付过程中 IT 工具链的打通,使得各个团队减少时间损耗,更加高效地协同工作。DevOps 能力图如下,良好的闭环可以大大增加整体的产出。

image-20220311121142708

CI/CD

1、持续集成(Continuous Integration)

持续集成是指软件个人研发的部分向软件整体部分交付,频繁进行集成以便更快地发现 其中的错误。“持续集成”源自于极限编程(XP),是 XP 最初的 12 种实践之一。

CI 需要具备这些:

  • 全面的自动化测试。这是实践持续集成&持续部署的基础,同时,选择合适的自动化测试工具也极其重要
  • 灵活的基础设施。容器,虚拟机的存在让开发人员和 QA 人员不必再大费周折
  • 版本控制工具。Git,CVS,SVN 等
  • 自动化的构建和软件发布流程的工具,如 Jenkins,flow.ci
  • 反馈机制。如构建/测试的失败,可以快速地反馈到相关负责人,以尽快解决达到一个更稳定的版本

image-20220311121324347

2、持续交付(Continuous Delivery)

持续交付在持续集成的基础上,将集成后的代码部署到更贴近真实运行环境的「类生产环境」 (production-like environments)中。持续交付优先于整个产品生命周期的软件部署,建立在高水平自动化持续集成之上。

灰度发布。

持续交付和持续集成的优点非常相似:

  • 快速发布。能够应对业务需求,并更快地实现软件价值
  • 编码->测试->上线->交付的频繁迭代周期缩短,同时获得迅速反馈
  • 高质量的软件发布标准。整个交付过程标准化、可重复、可靠
  • 整个交付过程进度可视化,方便团队人员了解项目成熟度
  • 更先进的团队协作方式。从需求分析、产品的用户体验到交互 设计、开发、测试、运维等角色密切协作,相比于传统的瀑布式软件团队,更少浪费

3、持续部署(Continuous Deployment)

持续部署是指当交付的代码通过评审之后,自动部署到生产环境中。持续部署是持续交付的最高阶段。这意味着,所有通过了一系列的自动化测试的改动都将自动部署到生产环境。它也可以被称为“Continuous Release”。

“开发人员提交代码,持续集成服务器获取代码,执行单元测试,根据测试结果决定是否部署到预演环境,如果成功部署到预演环境,进行整体验收测试,如果测试通过,自动部署到产品环境,全程自动化高效运转。”

持续部署主要好处是,可以相对独立地部署新的功能,并能快速地收集真实用户的反馈。

下图是由 Jams Bowman 绘制的持续交付工具链图

cicd-tools-fullsize

最终部署

kubesphere架构

architecture

有状态服务部署

1、有状态服务抽取配置为 ConfigMap

2、有状态服务必须使用 pvc 持久化数据

3、服务集群内访问使用 DNS 提供的稳定域名

image-20220311125735647

image-20220311131906123

image-20220311131257276

1
2
3
4
5
6
7
8
+ 部署流程
+ configMap
+ pvc
+ 镜像
+ 资源限制
+ 环境变量
+ 挂载pvc
+ 外网访问、集群内访问等

依次部署集群:

MySQL、Redis、RabbitMQ、Elasticsearch、Kibana

Nacos、Zipkin、Nginx、Sentinel

微服务部署

环境准备

1、dockerfile

image-20220311132713759

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
+ 创建项目 dockerfile2、上传项目到服务器。 
+ 进入项目,构建镜像到本地仓库;
+ docker build -t nginx:GA-1.0 -f ./Dockerfile .
+ docker images
+ docker exec -it 容器 id /bin/bash;进入容器,修改容器
+ docker commit -a “leifengyang” -m “nginxxx” 容器 id
+ docker commit [OPTIONS] CONTAINER [REPOSITORY[:TAG]]
+ OPTIONS 说明:
+ -a :提交的镜像作者;
+ -c :使用 Dockerfile 指令来创建镜像;
+ -m :提交时的说明文字;
+ -p :在 commit 时,将容器暂停。
+ docker login : 登陆到一个 Docker 镜像仓库,如果未指定镜像仓库地址,默认为官方仓库 Docker Hub
+ docker login -u 用户名 -p 密码
+ docker logout : 登出一个 Docker 镜像仓库,如果未指定镜像仓库地址,默认为官方仓库 Docker Hub
+ 推送镜像到 docker hub
+ 标记镜像,docker tag local-image:tagname username/new-repo:tagname
+ 上传镜像,docker push username/new-repo:tagname
+ 保存镜像,加载镜像
+ 可以保存镜像为 tar,使用 u 盘等设备复制到任意 docker 主机,再次加载镜像
+ 保存:docker save spring-boot-docker -o /home/spring-boot-docker.tar
+ 加载:docker load -i spring-boot-docker.tar
+ 阿里云操作
+ 登录阿里云,密码就是开通镜像仓库时的密码 docker login --username=qwertyuiopasdf_aa registry.cn-hangzhou.aliyuncs.com
+ 拉取镜像 docker pull registry.cn-hangzhou.aliyuncs.com/atguigumall/gulimall-nginx:v1.0
+ 推送镜像 docker tag [ImageId] registry.cn-hangzhou.aliyuncs.com/atguigumall/gulimall-nginx:v1
docker push registry.cn-hangzhou.aliyuncs.com/atguigumall/gulimall-nginx:v1
1
2
3
4
FROM java:openjdk-8-jre-alpine
WORKDIR /home
COPY target/*.jar /home
ENTRYPOINT java -jar *.jar

2、k8s部署描述文件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
apiVersion: apps/v1
kind: Deployment
metadata:
labels:
app: kubesphere
component: ks-sample
tier: backend
name: ks-sample
namespace: kubesphere-sample-prod
spec:
progressDeadlineSeconds: 600
replicas: 2
selector:
matchLabels:
app: kubesphere
component: ks-sample
tier: backend
strategy:
rollingUpdate:
maxSurge: 100%
maxUnavailable: 100%
type: RollingUpdate
template:
metadata:
labels:
app: kubesphere
component: ks-sample
tier: backend
spec:
containers:
- env:
- name: CACHE_IGNORE
value: js|html
- name: CACHE_PUBLIC_EXPIRATION
value: 3d
image: $REGISTRY/$HARBOR_NAMESPACE/$APP_NAME:$TAG_NAME
readinessProbe:
httpGet:
path: /
port: 8080
timeoutSeconds: 10
failureThreshold: 30
periodSeconds: 5
imagePullPolicy: Always
name: ks
ports:
- containerPort: 8080
protocol: TCP
resources:
limits:
cpu: 300m
memory: 600Mi
requests:
cpu: 100m
memory: 100Mi
terminationMessagePath: /dev/termination-log
terminationMessagePolicy: File
dnsPolicy: ClusterFirst
restartPolicy: Always
terminationGracePeriodSeconds: 30

image-20220311150912792

1
2
3
4
5
6
7
8
9
+ Containerport:容器内服务端口
+ TargetPort
+ pod访问container
+ Port:集群内service端口,域名、ip端口号
+ Nodeport:外部访问集群service
+ 特点
+ Targetport、serviceport端口可以一样
+ 每个service、pod地址都不一样,都是集群内虚拟的
+ Nodeport不能一样,暴露外部端口

3、Jenkinsfile流水线文件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
pipeline {
agent {
node {
label 'maven'
}
}

parameters {
string(name:'TAG_NAME',defaultValue: '',description:'')
}

environment {
DOCKER_CREDENTIAL_ID = 'dockerhub-id'
GITHUB_CREDENTIAL_ID = 'github-id'
KUBECONFIG_CREDENTIAL_ID = 'demo-kubeconfig'
REGISTRY = 'docker.io'
DOCKERHUB_NAMESPACE = '1637872839'
GITHUB_ACCOUNT = '1637872839'
APP_NAME = 'devops-java-sample'
SONAR_CREDENTIAL_ID = 'sonar-qube'
}

stages {
stage ('checkout scm') {
steps {
checkout(scm)
}
}

stage ('unit test') {
steps {
container ('maven') {
sh 'mvn clean -gs `pwd`/configuration/settings.xml test'
}
}
}

stage ('build & push') {
steps {
container ('maven') {
sh 'mvn -Dmaven.test.skip=true -gs `pwd`/configuration/settings.xml clean package'
sh 'docker build -f Dockerfile-online -t $REGISTRY/$DOCKERHUB_NAMESPACE/$APP_NAME:SNAPSHOT-$BRANCH_NAME-$BUILD_NUMBER .'
withCredentials([usernamePassword(passwordVariable : 'DOCKER_PASSWORD' ,usernameVariable : 'DOCKER_USERNAME' ,credentialsId : "$DOCKER_CREDENTIAL_ID" ,)]) {
sh 'echo "$DOCKER_PASSWORD" | docker login $REGISTRY -u "$DOCKER_USERNAME" --password-stdin'
sh 'docker push $REGISTRY/$DOCKERHUB_NAMESPACE/$APP_NAME:SNAPSHOT-$BRANCH_NAME-$BUILD_NUMBER'
}
}
}
}

stage('push latest'){
when{
branch 'master'
}
steps{
container ('maven') {
sh 'docker tag $REGISTRY/$DOCKERHUB_NAMESPACE/$APP_NAME:SNAPSHOT-$BRANCH_NAME-$BUILD_NUMBER $REGISTRY/$DOCKERHUB_NAMESPACE/$APP_NAME:latest '
sh 'docker push $REGISTRY/$DOCKERHUB_NAMESPACE/$APP_NAME:latest '
}
}
}

stage('deploy to dev') {
when{
branch 'master'
}
steps {
input(id: 'deploy-to-dev', message: 'deploy to dev?')
kubernetesDeploy(configs: 'deploy/dev-ol/**', enableConfigSubstitution: true, kubeconfigId: "$KUBECONFIG_CREDENTIAL_ID")
}
}
stage('push with tag'){
when{
expression{
return params.TAG_NAME =~ /v.*/
}
}
steps {
container ('maven') {
input(id: 'release-image-with-tag', message: 'release image with tag?')
withCredentials([usernamePassword(credentialsId: "$GITHUB_CREDENTIAL_ID", passwordVariable: 'GIT_PASSWORD', usernameVariable: 'GIT_USERNAME')]) {
sh 'git config --global user.email "kubesphere@yunify.com" '
sh 'git config --global user.name "kubesphere" '
sh 'git tag -a $TAG_NAME -m "$TAG_NAME" '
sh 'git push http://$GIT_USERNAME:$GIT_PASSWORD@github.com/$GITHUB_ACCOUNT/devops-java-sample.git --tags --ipv4'
}
sh 'docker tag $REGISTRY/$DOCKERHUB_NAMESPACE/$APP_NAME:SNAPSHOT-$BRANCH_NAME-$BUILD_NUMBER $REGISTRY/$DOCKERHUB_NAMESPACE/$APP_NAME:$TAG_NAME '
sh 'docker push $REGISTRY/$DOCKERHUB_NAMESPACE/$APP_NAME:$TAG_NAME '
}
}
}
stage('deploy to production') {
when{
expression{
return params.TAG_NAME =~ /v.*/
}
}
steps {
input(id: 'deploy-to-production', message: 'deploy to production?')
kubernetesDeploy(configs: 'deploy/prod-ol/**', enableConfigSubstitution: true, kubeconfigId: "$KUBECONFIG_CREDENTIAL_ID")
}
}
}
}

4、阿里云镜像仓库

image-20220311152111010

1
2
3
4
+ 创建镜像仓库
+ 登录仓库
+ 拉取镜像
+ 推送镜像

DevOps部署流水线

image-20220311150756780

1、拉取gitee代码&参数化构建&环境变量

  • 配置凭证
  • 配置构建微服务参数
  • 配置运行参数等

2、Sonar代码质量分析

  • 配置阿里云镜像
  • 进入sonar查看分析报告
  • bug修改等

3、构建&推送镜像

  • 配置阿里云私有镜像仓库
  • 根据dockerfile 打包镜像
  • 推送镜像

4、部署到k8s生产环境

5、发布

  • gitee仓库地址

  • tag信息

全链路最终部署

image-20220311151019195

1、数据服务集群

2、微服务集群

3、gateway网关集群

4、nginx集群

5、vue后台

6、ingress controller网关路由

地址——>ingress controller——>动静分离nginx——>gateway——>微服务

1
2
3
4
5
+ 部署方式
+ Jenkins流水线
+ 自己打包部署k8s服务
+ 拉取镜像自己运行
...

集群监控

动态扩容节点

image-20220311132142809

预警信息

image-20220311152935372

监控信息

image-20220311132353545

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
+ k8s概念
+ pod、server
+ nodeport等
+ 应用路由
+ ingress controller
+ 配置中心
+ configMap
+ Devops
+ 自动化流水线
+ 修改推送代码
+ 运行流水线构建
+ 监控资源
+ 集群技术
+ 主从、分片、选领导
+ 各种集群
+ Jenkins file
+ Docker file