DevOps(Development和Operations的组合词)是一组过程、方法与系统的统称,用于促进开发(应用程序/软件工程)、技术运营和质量保障(QA)部门之间的沟通、协作与整合。
它是一种重视“软件开发人员(Dev)”和“IT运维技术人员(Ops)”之间沟通合作的文化、运动或惯例。透过自动化“软件交付”和“架构变更”的流程,来使得构建、测试、发布软件能够更加地快捷、频繁和可靠。
它的出现是由于软件行业日益清晰地认识到:为了按时交付软件产品和服务,开发和运营工作必须紧密合作
详细解释
持续集成(continuous integration )指的是,频繁地(一天多次)将代码集成到主干。每次集成都通过自动化的构建(包括编译,发布,自动化测试)来验证,从而尽早地发现集成错误。
它的好处主要有两个。
(1)快速发现错误。每完成一点更新,就集成到主干,可以快速发现错误,定位错误也比较容易。
(2)防止分支大幅偏离主干。如果不是经常集成,主干又在不断更新,会导致以后集成的难度变大,甚至难以集成。
持续集成的目的,就是让产品可以快速迭代,同时还能保持高质量。它的核心措施是,代码集成到主干之前,必须通过自动化测试。只要有一个测试用例失败,就不能集成。
持续部署(continuous deployment)是通过自动化的构建、测试和部署循环来快速交付高质量的产品。
CICD持续集成设计
开发人员提交代码gitlab,gitlab通过hook触发事件,调用jenkins ,jenkins触发一系列动作,抓取代码,质量检查,maven构建,制作镜像,push到私服harbor,更新服务到k8s
机器主备
机器ip | 部署服务 | 描述 |
---|---|---|
192.168.58.144 | jenkins,k8smanager,maven,git | 内存>=2G |
192.168.58.145 | k8sworker,gitlab | 内存>=4G gitlab占用2G内存 |
192.168.58.147 | k8sworker ,harbor | 内存>=2G |
微服务程序使用之前jwt代码
参考 https://blog.csdn.net/liaomin416100569/article/details/86615848
gitlab私服容器最好有4G内存,否则很难部署成功
首先,Docker 容器数据应该存储于卷中,在这里我们使用最简单的本地命名卷:
docker network create gitlab-net
准备好后,开始运行 Gitlab 容器:
docker run -d \
--hostname 你的宿主机ip
-p 8880:80 \
-p 8443:443 \
-p 2222:22 \
--name gitlab \
--restart unless-stopped \
-v /root/gitlab-config:/etc/gitlab \
-v /root/gitlab-logs:/var/log/gitlab \
-v /root/gitlab-data:/var/opt/gitlab \
--network gitlab-net \
twang2218/gitlab-ce-zh:11.1.4
注意 --hostname 你的宿主机ip 不是容器ip啊 这个不加 一般访问首页 都是 响应时间太长的错误
修改 /root/gitlab-config/gitlab.rb
去掉下面这一行的#注释 将 22改成 2222
gitlab_rails['gitlab_shell_ssh_port'] = 2222
修改\root\gitlab-data\gitlab-rails\etc\gitlab.yml 将web端口改成8880
gitlab:
## Web server settings (note: host is the FQDN, do not include http://)
host: 192.168.58.145
port: 8880
https: false
重启 gitlab
docker restart gitlab
访问 http://宿主机:8880
gitlab默认的用户名是root 进入容器内设置密码
[root@swarm02 ~]# docker exec -it gitlab bash
root@192:/# gitlab-rails console production
-------------------------------------------------------------------------------------
GitLab: 11.1.4 (63daf37)
GitLab Shell: 7.1.4
postgresql: 9.6.8
-------------------------------------------------------------------------------------
Loading production environment (Rails 4.2.10)
irb(main):001:0> user = User.where(id: 1).first
=> #
irb(main):002:0> user.password=12345678
=> 12345678
irb(main):003:0> user.password_confirmation=12345678
=> 12345678
irb(main):004:0> user.save!
Enqueued ActionMailer::DeliveryJob (Job ID: 11333c17-1641-43cd-af4f-5fd1bf103d49) to Sidekiq(mailers) with arguments: "DeviseMailer", "password_change", "deliver_now", gid://gitlab/User/1
=> true
irb(main):005:0> quit
root@192:/# exit
exit
设置完成使用用户名root,密码123456登录,也可以自己注册一个账号
使用war包安装参考 https://blog.csdn.net/liaomin416100569/article/details/78431720
使用docker安装
docker run -d -p 8880:8080 -p 50000:50000 -v /root/jenkins_home:/var/jenkins_home -u root --privileged --name jenkins jenkins
使用docker logs jenkins 查看生成的随机密码
INFO:
*************************************************************
*************************************************************
*************************************************************
Jenkins initial setup is required. An admin user has been created and a password generated.
Please use the following password to proceed to installation:
e4addedcc5db483d910fa03794a3ff24
This may also be found at: /var/jenkins_home/secrets/initialAdminPassword
*************************************************************
*************************************************************
*************************************************************
其中我的密码时:e4addedcc5db483d910fa03794a3ff24
也可以通过(挂载容器的volum是/root/jenkins_home)
[root@swarm01 ~]# more /root/jenkins_home/secrets/initialAdminPassword
e4addedcc5db483d910fa03794a3ff24
访问安装宿主机:8880
输入密码 其他操作可以参考https://blog.csdn.net/liaomin416100569/article/details/78431720
安装插件选择
安装所有流水线插件
点击确认,之后就等待安装完成罗
一般流水线都会安装失败,安装失败没关系 继续完成 输入admin的用户名和密码 注意所有字段必填 ,不填会卡住
登录进入后 点击系统管理 很多错误 拉倒最下面 升级到 2.57.1 然后重启,流水线插件就会安装完成,重启再次登录就可以在新建任务列表看到流水线
安装完成后才发现个问题 maven和git都需要安装在容器中 麻烦 拷贝容器的jenkins.war还是在宿主机运行得了
docker cp jenkins:/usr/share/jenkins/jenkins.war /root/jenkins_home/
启动jenkins(要先停止容器)
nohup java -jar jenkins.war --httpPort=8880 &
修改 /root/.jenkins/hudson.model.UpdateCenter.xml
将其中
https://updates.jenkins.io/update-center.json
修改为
http://updates.jenkins.io/update-center.json
杀掉进程重启 如果不修改可能出现This Jenkins instance appears to be offline问题
安装完插件登录有可能卡在登陆卡在SetupWizard界面 重启下jenkins即可解决
私服安装参考https://blog.csdn.net/liaomin416100569/article/details/86599571
144可以先登录到harbor,因为制作镜像上传
docker login --username admin --password 123456 192.168.58.147
将平时用到maven库和索引拷贝到jenkin同一台机器
修改本地仓库到你的本地仓库
比如我的maven安装在/root/apache-maven-3.0.4_localtest 本地仓库在/root/apache-maven-3.0.4_localtest/resp
修改 conf/settings.xml
/root/apache-maven-3.0.4_localtest/resp
设置环境变量到path
sed -e `grep -n PATH= /root/.bash_profile | cut -d: -f1`'a\PATH=$PATH:/root/apache-maven-3.0.4_localtest/bin\' /root/.bash_profile && chmod +x /root/apache-maven-3.0.4_localtest/bin/* && source /root/.bash_profile
查看mvn版本
[root@swarm01 conf]# mvn -v
Apache Maven 3.0.4 (r1232337; 2012-01-17 16:44:56+0800)
Maven home: /root/apache-maven-3.0.4_localtest
Java version: 1.7.0_79, vendor: Oracle Corporation
Java home: /usr/java/jdk1.7.0_79/jre
Default locale: en_US, platform encoding: UTF-8
OS name: "linux", version: "3.10.0-327.el7.x86_64", arch: "amd64", family: "unix"
所有机器安装git,执行命令
yum -y install git
[root@swarm02 ~]# git --version
git version 1.8.3.1
直接使用上篇文章的环境 https://blog.csdn.net/liaomin416100569/article/details/86711655
一般开发时程序需要更新代码到gitlab私服中,假设项目名称是springcloud
具体你可以使用 idea使用git提交
提交过后可以使用CICD(流水线)安装gitlab-runner后进行代码质量检查等
登录jenkins
创建一个自由风格的项目
源代码管理选择git 路径输入 http://192.168.58.145:8880/root/springcloud.git 项目公共 无需配置密码
Build Triggers 选择Trigger builds remotely (e.g., from scripts) 输入秘钥springcloud
触发构建只需要访问:http://192.168.58.144:8880/job/springcloud/build?token=springcloud
接下来添加构建步骤 选择类型 执行shell
我最终配置的shell是
chmod +x ${WORKSPACE}/cicd.sh
${WORKSPACE}/cicd.sh
${WORKSPACE}表示git拉去的源代码目录
将来构建就会自动运行源代码目录的cicd.sh脚本
接下里看我的源代码的结构 三个项目
编写springcloud_userclient的Dockerfile 用于制作镜像,直接访问子项目springcloud_userclient目录下
FROM insideo/jre8:8u121
RUN mkdir /code
COPY ./target/springcloud_userclient-0.0.1-SNAPSHOT.jar /code
WORKDIR /code
CMD ["java","-jar","/code/springcloud_userclient-0.0.1-SNAPSHOT.jar"]
编写springcloud_userservice的Dockerfile文件
FROM insideo/jre8:8u121
RUN mkdir /code
COPY ./target/springcloud_userservice-0.0.1-SNAPSHOT.jar /code/
WORKDIR /code
CMD ["java","-jar","/code/springcloud_userservice-0.0.1-SNAPSHOT.jar"]
在thrift项目根目录下新建build-source.sh 用于构建项目打jar包
mvn clean compile package -Dmaven.test.skip=true
在thrift项目根目录下新建build-images.sh 用于构建镜像 上传到私服
curTime=$1
docker build -t userclient_$curTime ./springcloud_userclient
docker build -t userservice_$curTime ./springcloud_userservice
docker tag userclient_$curTime 192.168.58.147/mylib/userclient_$curTime
docker tag userservice_$curTime 192.168.58.147/mylib/userservice_$curTime
docker push 192.168.58.147/mylib/userclient_$curTime
docker push 192.168.58.147/mylib/userservice_$curTime
在thrift项目根目录下创建项目依赖的redis k8s yaml部署文件 redis-depoyment.yaml
apiVersion: extensions/v1beta1
kind: Deployment
metadata:
name: redis-deployment
spec:
replicas: 1
template:
metadata:
labels:
app: redis
spec:
containers:
- name: redis
image: redis:latest
ports:
- containerPort: 6379
---
apiVersion: v1
kind: Service
metadata:
labels:
run: redis
name: redis
namespace: default
spec:
ports:
- nodePort: 20001
port: 6379
protocol: TCP
targetPort: 6379
selector:
app: redis
sessionAffinity: None
type: NodePort
status:
loadBalancer: {}
在thrift项目根目录下创建项目依赖的eurekak8s yaml部署文件 eureka-depoyment.yaml
apiVersion: extensions/v1beta1
kind: Deployment
metadata:
name: eureka-deployment
spec:
replicas: 1
template:
metadata:
labels:
app: eureka
spec:
containers:
- name: eureka
image: springcloud/eureka:latest
ports:
- containerPort: 8761
---
apiVersion: v1
kind: Service
metadata:
labels:
run: eureka
name: eureka
namespace: default
spec:
ports:
- nodePort: 20002
port: 8761
protocol: TCP
targetPort: 8761
selector:
app: eureka
sessionAffinity: None
type: NodePort
status:
loadBalancer: {}
接下来thrift项目根目录下创建创建最终的cicd.sh文件
这里注意 因为userclient和userservice是我们的项目 一旦需要重新制作镜像就需要产生一个新的
镜像名称 我这里是使用 项目名称_当前时间戳来作为镜像名称
curTime=`date +%s`
#1.编译源代码打包
source ./build-source.sh
#2.构建镜像 上传harbor
source ./build-images.sh $curTime
# 3.安装redis和eureka服务
kubectl apply -f redis-depoyment.yaml
kubectl apply -f eureka-depoyment.yaml
#安装 userclient
cat <
ok准备就绪 点击jenkins项目的开始构建
构建成功后查看harbor 是否多了两个个最近时间的镜像
查看所有pods
[root@swarm01 springcloud]# kubectl get svc -o wide
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE SELECTOR
eureka NodePort 10.68.147.217 8761:20002/TCP 4h app=eureka
kubernetes ClusterIP 10.68.0.1 443/TCP 19d
redis NodePort 10.68.83.252 6379:20001/TCP 4h app=redis
userclient NodePort 10.68.212.41 8000:20003/TCP 19m app=userclient
可以看到 eureka暴露的宿主机的20002端口
userclient 暴露了宿主机的20003端口
访问eureka 查看是否注册了2个userservice 1个userclient
http://192.168.58.145:20003/
访问页面查看是否能互相调用
http://192.168.58.145:20003/login.html
接下里可以在gitlab中 设置
点击系统钩子 url输入jenkins触发的url
jenkins默认是不允许其他网页远程来访问 所以需要关闭权限和cors保护
点击设置-全局安全设置
修改登录页面的代码 提交 测试刷新界面 看是否正常部署