搭建个人的DevOps流水线
可以把部署和发布脚本打成Charts包, 托管在仓库里, 发布的时候使用Helm命令, 从仓库中拉取也可以写一个通用的部署发布模板,模板中关键参数使用占位符, 在Jenkins脚本中, 使用Helm命令部署发布项目, 参数在命令上指定我的chartmuseun没有开放外网端口使用docker部署, 命令为helm的命令# 创建目录helm create 目录名打包需要进入到目录中# 对当前目录构建
1 简介
在腾讯云服务器搭建流水线, 个人的云服务器配置为4核 8G内存, 系统为CentOS 7,用到的技术有Docker, Kubernetes, Jenkins, Helm, Harbor, Kubeode, 因为内存吃紧, 代码仓库使用的gitee, 并没有在服务器中搭建gitlab. 在云服务器中搭建的话, 注意防火墙的端口, 什么要开,什么不要开.
我不是专业的运维人员, 这个流水线也只是私人在用, 如果哪里有问题或者有更好的方案,欢迎在评论区探讨. 希望大家帮忙多多点赞,评论. 蟹蟹!!!!!!
2 安装Docker
2.1 安装
# 安装工具
sudo yum install ‐y yum‐utils device‐mapper‐persistent‐data lvm2
# 加入阿里云yum仓库提速docker下载过程
sudo yum-config-manager --add-repo https://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo
# 更新仓库源信息
sudo yum makecache fast
# 下载docker
sudo yum -y install docker-ce
# 启动docker服务
sudo service docker start
# 验证docker是否安装成功
docker version
2.2 设置阿里云镜像加速
2.3 设置开机自动启动
# 启用Docker服务:
sudo systemctl enable docker
# 重新加载systemd配置
sudo systemctl daemon-reload
# 重新启动Docker服务
sudo systemctl restart docker
验证:
输入 sudo systemctl status docker, 显示active (running), 表示设置成功
3 安装JDK,Maven,Node.js之类的环境
根据个人的需求, 需要用到什么就安装什么, Jenkins发布项目的过程,如果编译,打包的过程中用到的话, 是要配置搭配Jenkins中的.
4 安装Jenkins
Jenkins是特别流行的开源免费持续集成工具,整个项目代码打包构建发布流程可以由Jenkins来驱动.
Jenkins使用Docker安装, 安装启动之后, 在初始化安装Jenkins插件的时候, 哪怕插件源换成国内的, 插件还是总安装不上, 安装不上的话, 可以从Jenkin插件的官网上, 手动下载插件文件, 然后上传到Jenkins上, Jenkins有上传插件的页面
日志里面会有Jenkins的初始化密码, 需要自己保存一下
4.1 安装Jenkins
# 删除旧的目录的镜像, 如果未安装过不用执行
rm -rf /var/jenkins/
docker rm -f jenkins
# 创建目录
mkdir -p /var/jenkins/
# 开放权限, 这个文件存储的是jekins生成的可执行文件, 没有权限的话会导致无法执行
chmod -R 777 /var/jenkins/
# 拉取镜像,启动服务, 设置端口映射和文件挂载,项目用到了jdk,maven, node, 设置清华源
sudo docker run --name jenkins \
--restart=always \
-p 9080:8080 -p 50000:50000 \
-v /var/jenkins/:/var/jenkins_home/ \
-v /usr/local/jdk:/usr/local/jdk \
-v /usr/local/maven:/usr/local/maven \
-v /usr/local/node:/usr/local/node \
-e JENKINS_UC=https://mirrors.tuna.tsinghua.edu.cn/jenkins/ \
-e JENKINS_UC_DOWNLOAD=https://mirrors.tuna.tsinghua.edu.cn/jenkins/ \
-d jenkins/jenkins:2.387.2
# 查看日志
docker logs -f jenkins
初始化密码
4.2 配置Jenkins
4.3 安装插件
拉取代码: git parameter
连接服务器: publish over ssh
4.3 配置JDK, Maven, Node
系统管理 --> 全局工具配置
5 安装harbor
5.1 安装docker-compose
# curl 后面的为下载地址,由官方改成了国内 后面的路径是安装路径
sudo curl -L "https://get.daocloud.io/docker/compose/releases/download/1.29.2/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose
# 为安装目录授权
sudo chmod +x /usr/local/bin/docker-compose
# usr/local,目录下的Docker Compose 需要做一个软连接, 连接到bin目录下, harbor才可以知道Docker COmpose的存在
sudo ln -s /usr/local/bin/docker-compose /usr/bin/docker-compose
# 验证,查看版本
docker-compose version
# 重启docker
service docker restart
5.2 安装harbor
下载安装包
cd /usr/local
wget --no-check-certificate https://github.com/goharbor/harbor/releases/download/v1.10.14/harbor-offline-installer-v1.10.14.tgz
tar xzvf harbor-offline-installer-v1.10.14.tgz
harbor.yml为harbor的配置文件
hostname: 主机ip,改成自己的
port: 端口, 设置成合适的
配置文件中有默认密码
安装harbor
./install.sh
5.3 访问harbor
http://ip:端口/harbor
账号:admin
密码: 默认密码
6 部署K8S集群
使用kubeode部署K8S, kubeode可以实现一键式部署K8S集群, 这个工具除了会给部署K8S集群, 还会安装Kuboard, 普罗米修斯, grafina等
仓库地址: readme中有使用教程
我使用的版本为
解压 --> 进入到解压之后的目录 ---> 执行 bash install.sh
安装的时候根据实际情况选择, 我用的是单节点, 没钱租太多服务器,呜呜!!
按照提示走完后续流程, 具体的可以参考kubeode项目仓库的文档
kuboard的地址为 http://ip:30080
默认账号: admin
默认密码: Kuboard123
集群grafan监控地址为http://IP:30000
默认账户密码admin admin
7 Helm的安装
Helm会基于仓库, 对K8S的包进行管理, 可以通过Helm来快速部署项目
7.1 安装Helm
下载Helm安装包
https://github.com/helm/helm/releases
Helm的仓库地址
我用版本为: helm-v3.10.0-linux-amd64.tar.gz 下载完成之后对压缩包解压, 解压之后, 将helm文件移动到/usr/bin目录下, 任何位置都可以使用helm命令
在任何地方都可以使用helm命令
7.2 安装Helm的私有仓库发布自定义的Charts
可以把部署和发布脚本打成Charts包, 托管在仓库里, 发布的时候使用Helm命令, 从仓库中拉取
也可以写一个通用的部署发布模板,模板中关键参数使用占位符, 在Jenkins脚本中, 使用Helm命令部署发布项目, 参数在命令上指定
我的chartmuseun没有开放外网端口
使用docker部署, 命令为
docker run --name chartmuseum \
--restart=always \
-p 9082:8080\
-d bitnami/chartmuseum:0.15.0
helm的命令
# 创建目录
helm create 目录名
打包需要进入到目录中
# 对当前目录构建压缩包, 构建完之后当前目录会出现一个压缩包
helm package .
# 推送至Chart仓库
curl --data-binary "@包名称.tgz" http://ip:端口/api/charts
# 查询Chart
curl http://ip:端口/api/charts
# 删除Chart
curl -X DELETE http://ip:端口/api/charts/包名称/版本号
# 例子
curl -X DELETE http://1.1.1.1:9082/api/charts/application-nei-charts/1.0.0
如果想要使用Helm从自己的仓库中拉取包, 需要将自己的仓库添加到Helm
# 增加自己的helm仓库
helm repo add 仓库名 http://ip:端口/
# 例子 helm repo add my-repo http://1.1.1.1:8080/
# 查看仓库
helm repo list
# 对当前的仓库缓存进行更新, 保证是最新的
helm repo update
# 查询
helm search repo 仓库名
拉取仓库中的包安装的命令, 这些是写在在Jenkins脚本中的, 不需要手动执行, Helm的更多用法可以自己去查找
# 写在
helm uninstall 资源名
# 安装
helm install 资源名 仓库名/包名
# 查看列表
helm list
7.3 通用模板的编写
我是写了一个脚本模板, 打成Chart包, 推送到了仓库
deployment.yaml如下所示
# 指明了deploy的版本号
apiVersion: apps/v1
# 说明种类, Deployment脚本, 用于发布的
kind: Deployment
# 元数据, 说明部署文件的名字是什么
metadata:
name: {{.Values.name}}
namespace: {{.Values.namespace}}
# spec下的配置项, 都与部署有关系
spec:
# 部署两个副本, 创建2个pod
replicas: {{.Values.replicas}}
selector:
matchLabels:
# 匹配下面的创建模板
app: {{.Values.app}}
template:
metadata:
# 设置模板的标签, 部署好之后每一个副本都会有定义好的标签, 在后面进行服务配置也会用到
labels:
app: {{.Values.app}}
spec:
# 容器
containers:
# 容器副本名称
- name: {{.Values.name}}
# 镜像名称
image: {{.Values.image}}
# 容器对外暴露的端口
ports:
- containerPort: {{.Values.port}}
service.yaml如下所示
# serice工具版本
apiVersion: v1
# 服务类型
kind: Service
# 元数据
metadata:
# 名称
name: {{.Values.name}}
namespace: {{.Values.namespace}}
# 细节的说明
spec:
# 节点端口, 当设置为NodePort时, K8S会允许直接由节点对外暴露端口
type: ClusterIP
selector:
# 设置所有拥有这个APP标签的pod, 都会被这个service绑定, 相当于pod的筛选工具
app: {{.Values.app}}
ports:
# pod的端口
- port: {{.Values.port}}
# 端口名称
name: service-port
# 容器内部服务的端口
targetPort: {{.Values.port}}
# 节点端口, k8要求端口在30000-32767之间才可以
# nodePort: {{.Values.nodePort}}
Chart.yaml
apiVersion: v2
name: application-nei-charts
description: A Helm chart for Kubernetes
# A chart can be either an 'application' or a 'library' chart.
#
# Application charts are a collection of templates that can be packaged into versioned archives
# to be deployed.
#
# Library charts provide useful utilities or functions for the chart developer. They're included as
# a dependency of application charts to inject those utilities and functions into the rendering
# pipeline. Library charts do not define any templates and therefore cannot be deployed.
type: application
# This is the chart version. This version number should be incremented each time you make changes
# to the chart and its templates, including the app version.
# Versions are expected to follow Semantic Versioning (https://semver.org/)
version: 1.0.0
# This is the version number of the application being deployed. This version number should be
# incremented each time you make changes to the application. Versions are not expected to
# follow Semantic Versioning. They should reflect the version the application is using.
appVersion: stable
7.4 通用模板打包,发送至仓库
# 进入到目录下, 打包
helm package .
// 推送至Chart仓库
curl --data-binary "@包名.tgz" http://ip:端口/api/charts
查询仓库
8 配置流水线, 添加Dockerfile和Jenkins脚本
部署的项目是开源项目: JeecgBoot
仓库地址:
8.1 项目添加Dockerfile
Dockerfile如下所示:
FROM openjdk:8-slim
WORKDIR /var/docker_image/jeecg-management
COPY jeecg-system-start-3.4.3.jar .
# 校准时间
RUN ln -sf /usr/share/zoneinfo/Asia/Shanghai /etc/localtime && echo "Asia/Shanghai" > /etc/timezone
EXPOSE 8080
ENTRYPOINT ["java","-Djava.security.egd=file:/dev/./urandom", "-jar", "jeecg-system-start-3.4.3.jar", "--server.port=8080"]
8.2 Jenkins配置项目
Jenkins脚本也可以托管到代码仓库里, 本次示例直接在Jenkins中写的
Jenkins提供了脚本生成器, 可以把配置生成脚本
点击这里,可以进入到生成脚本的页面
配置git仓库示例, 下面配置流水线会用到
SSH Publish
Jenkins配置流水线
使用Heml的话, 需要配置要执行Helm命令的服务器的ip, 这个插件会连接配置的服务器, 在服务器上执行指定的命令
java后端项目Jenkins脚本示例
pipeline {
agent any
parameters {
gitParameter branch: '', branchFilter: '.*', defaultValue: 'origin/master', description: '选择要构建的分支', name: 'branchName', quickFilterEnabled: false, selectedValue: 'NONE', sortMode: 'NONE', tagFilter: '*', type: 'GitParameterDefinition', useRepository: 'https://gitee.com/仓库地址.git'
}
stages {
stage('拉取代码') {
steps{
timeout(time: 1, unit: 'MINUTES') {
checkout scmGit(branches: [[name: "${branchName}"]], extensions: [], userRemoteConfigs: [[credentialsId: 'Jenkins中配置的账号密码凭据id', url: 'https://gitee.com/仓库地址.git']])
echo "拉取${branchName}分支代码成功"
}
}
}
stage('Maven打包') {
steps{
timeout(time: 10, unit: 'MINUTES') {
sh '/usr/local/maven/bin/mvn package -Pdev'
echo 'meven构建成功'
}
}
}
stage('构建镜像') {
steps{
timeout(time: 5, unit: 'MINUTES') {
sshPublisher(publishers: [sshPublisherDesc(configName: 'image-nei', transfers: [sshTransfer(cleanRemote: false, excludes: '', execCommand: '', execTimeout: 120000, flatten: false, makeEmptyDirs: false, noDefaultExcludes: false, patternSeparator: '[, ]+', remoteDirectory: 'jeecg-management', remoteDirectorySDF: false, removePrefix: 'jeecg-module-system/jeecg-system-start/target', sourceFiles: 'jeecg-module-system/jeecg-system-start/target/*.jar'), sshTransfer(cleanRemote: false, excludes: '', execCommand: '''docker build --no-cache -t ip:端口号/harbor仓库的项目名称/jeecg-management:1.0 /var/docker_image/jeecg-management
docker login -u admin -p 密码 ip:端口号
docker push ip:端口/harbor仓库的项目名称/jeecg-management:1.0''', execTimeout: 120000, flatten: false, makeEmptyDirs: false, noDefaultExcludes: false, patternSeparator: '[, ]+', remoteDirectory: 'jeecg-management', remoteDirectorySDF: false, removePrefix: 'docker', sourceFiles: 'docker/*')], usePromotionTimestamp: false, useWorkspaceInPromotion: false, verbose: false)])
}
}
}
stage('项目发布') {
steps{
timeout(time: 5, unit: 'MINUTES') {
sshPublisher(publishers: [sshPublisherDesc(configName: 'helm-nei', transfers: [sshTransfer(cleanRemote: false, excludes: '', execCommand: '''bash -c \'if helm ls --all-namespaces | grep -q jeecg-management; then
echo "执行helm upgrade"
helm upgrade jeecg-management my-repo/application-nei-charts --set name=jeecg-management --set replicas=1 --set image=ip:端口/harbor仓库项目名/jeecg-management:1.0 --set port=8080 --set namespace=default --set app=jeecg-management-pod --recreate-pods
else
echo "执行helm install"
helm install jeecg-management my-repo/application-nei-charts --set name=jeecg-management --set replicas=1 --set image=ip:端口/harbor项目名/jeecg-management:1.0 --set port=8080 --set namespace=default --set app=jeecg-management-pod
fi\'''', execTimeout: 120000, flatten: false, makeEmptyDirs: false, noDefaultExcludes: false, patternSeparator: '[, ]+', remoteDirectory: '', remoteDirectorySDF: false, removePrefix: '', sourceFiles: '')], usePromotionTimestamp: false, useWorkspaceInPromotion: false, verbose: false)])
}
}
}
}
}
8.3 完成之后示例
Jenkins:
KuBoard: 目前部署了一个前端项目, 一个后端项目, 一个Nginx
8.4 遇到的坑
8.4.1 Helm重新发布项目网络资源会重新创建的问题
在K8S集群中部署了一个Nginx, 一个前端项目, 一个后端项目. Nginx做反向代理, 但是每次在Jenkins中重新发布项目, Nginx根据服务名找不到集群内的项目,必须重启Nginx之后才能正常访问, Nginx配置如下:
Helm删除就项目,重新发布项目, 会重新分配网络资源, 把Jenkins脚本中执行Shell脚本中Helm发布项目改成先判断是都存在指定的资源, 不存在的话新建, 存在的话, 更新
bash -c \'if helm ls --all-namespaces | grep -q jeecg-management; then
echo "执行helm upgrade"
helm upgrade jeecg-management my-repo/application-nei-charts --set name=jeecg-management --set replicas=1 --set image=ip:端口/harbor仓库项目名/jeecg-management:1.0 --set port=8080 --set namespace=default --set app=jeecg-management-pod --recreate-pods
else
echo "执行helm install"
helm install jeecg-management my-repo/application-nei-charts --set name=jeecg-management --set replicas=1 --set image=ip:端口/harbor项目名/jeecg-management:1.0 --set port=8080 --set namespace=default --set app=jeecg-management-pod
fi\
8.4.2 可以在KuBoard里面使用ConfigMap做Nginx的配置文件挂载
更多推荐
所有评论(0)