文章目录
DevOps 环境搭建

Gitlab
GitLab 是一个用于仓库管理系统的开源项目,使用 Git 作为代码管理工具,并在此基础上搭建起来的 Web 服务。
Gitlab 是被广泛使用的基于 git 的开源代码管理平台, 基于 Ruby on Rails 构建, 主要针对软件开发过程中产生的代码和文档进行管理, Gitlab 主要针对 group 和 project 两个维度进行代码和文档管理, 其中 group 是群组, project 是工程项目, 一个 group 可以管理多个project , 可以理解为一个群组中有多项软件开发任务, 而一个 project 中可能包含多个 branch, 意为每个项目中有多个分支, 分支间相互独立, 不同分支可以进行归并。
- 安装 Gitlab
# 下载安装包
wget https://packages.gitlab.com/gitlab/gitlab-ce/packages/el/7/gitlab-ce-15.3.3-ce.0.el7.x86_64.rpm/download.rpm
# 安装
mv download.rpm gitlab-ce-15.3.3-ce.0.el7.x86_64.rpm
rpm -i gitlab-ce-15.3.3-ce.0.el7.x86_64.rpm
# 编辑 /etc/gitlab/gitlab.rb 文件
# 修改 external_url 访问路径 http://<ip>:<port>
# 其他配置修改如下
gitlab_rails['time_zone'] = 'Asia/Shanghai'
puma['worker_processes'] = 2
sidekiq['max_concurrency'] = 8
postgresql['shared_buffers'] = "128MB"
postgresql['max_worker_processes'] = 4
prometheus_monitoring['enable'] = false
# 更新配置并重启
gitlab-ctl reconfigure
gitlab-ctl restart
# 默认为80端口访问
- 页面配置
# 查看默认密码
cat /etc/gitlab/initial_root_password
# 登录后修改默认密码 > 右上角头像 > Perferences > Password
# 修改系统配置:点击左上角三横 > Admin
# Settings > General > Account and limit > 取消 Gravatar enabled > Save changes
# 关闭用户注册功能
# Settings > General > Sign-up restrictions > 取消 Sign-up enabled > Save changes
# 开启 webhook 外部访问
# Settings > Network > Outbound requests > Allow requests to the local network from web hooks and services 勾选
# 设置语言为中文(全局)
# Settings > Preferences > Localization > Default language > 选择简体中文 > Save changes
# 设置当前用户语言为中文
# 右上角用户头像 > Preferences > Localization > Language > 选择简体中文 > Save changes
- 为项目配置 Webhook
进入项目点击侧边栏设置 > Webhooks 进入配置即可
URL:在 jenkins 创建 pipeline 项目后
触发来源:
- 推送事件:表示收到新的推送代码就会触发
- 标签推送事件:新标签推送才会触发
- 评论:根据评论决定触发
- 合并请求事件:创建、更新或合并请求触发
添加成功后,可以在下方点击测试按钮查看 jenkins 是否成功触发构建操作
- 卸载
# 停止服务
gitlab-ctl stop
# 卸载 rpm 软件(注意安装的软件版本是 ce 还是 ee)
rpm -e gitlab-ce
# 查看进程
ps -ef|grep gitlab
# 干掉第一个 runsvdir -P /opt/gitlab/service log 进程
# 删除 gitlab 残余文件
find / -name *gitlab* | xargs rm -rf
find / -name gitlab | xargs rm -rf
Harbor
- 下载harbor离线安装包:https://github.com/goharbor/harbor/releases
解压缩:
tar -zxvf harbor-offline-installer-v2.14.1.tgz
- 复制模板并编辑配置文件
cp harbor.yml.tmpl harbor.yml
vim harbor.yml
关键配置项说明:
# 主机名(必须设置为你的服务器域名或 IP)
hostname: harbor.example.com
# HTTPS 配置(推荐启用)
https:
port: 443
certificate: /your-path/harbor.example.com.crt
private_key: /your-path/harbor.example.com.key
# 如果不使用 HTTPS,可注释掉 https 部分,保留 http(默认端口 80)
# http:
# port: 80
# 数据库密码(可自定义)
database:
password: your_strong_password
# Harbor 管理员初始密码(默认是 Harbor12345)
harbor_admin_password: YourAdminPass123!
# 数据持久化路径
data_volume: /data/harbor
# 可选:启用 Trivy 扫描器、Notary、ChartMuseum 等
trivy:
enabled: true
- 运行安装脚本
确保已安装 Docker 和 Docker Compose
./install.sh
SonarQube
使用 docker run(简单测试)
docker run -d --name sonarqube -p 9000:9000 -p 9092:9092 sonarqube:community
访问 http://<服务器IP>:9000,默认账号密码:admin / admin
使用 Docker Compose(含 PostgreSQL)
- 创建 docker-compose.yml 文件
version: '3'
services:
sonarqube:
image: sonarqube:community
container_name: sonarqube
depends_on:
- db
environment:
- SONAR_JDBC_URL=jdbc:postgresql://db:5432/sonarqube
- SONAR_JDBC_USERNAME=sonar
- SONAR_JDBC_PASSWORD=sonarpass
volumes:
- ./data:/opt/sonarqube/data
- ./logs:/opt/sonarqube/logs
- ./extensions:/opt/sonarqube/extensions
ports:
- "9000:9000"
- "9092:9092" # 用于调试或插件通信(可选)
networks:
- sonarnet
restart: unless-stopped
db:
image: postgres:15
container_name: sonarqube_db
environment:
- POSTGRES_USER=sonar
- POSTGRES_PASSWORD=sonarpass
- POSTGRES_DB=sonarqube
volumes:
- ./postgres_data:/var/lib/postgresql/data
networks:
- sonarnet
restart: unless-stopped
networks:
sonarnet:
driver: bridge
- 启动服务
docker-compose up -d
Jenkins
- 创建持久化目录
sudo mkdir -p /jenkins_home
- 启动 Jenkins 容器
docker run -d \
--name jenkins \
-p 8080:8080 \
-p 50000:50000 \
-v /jenkins_home:/var/jenkins_home \
--restart unless-stopped \
jenkins/jenkins:lts
K8S CICD 案例
使用springboot写一个最简单的功能,只有一个Restful接口
Dockerfile:
## 基础镜像
## AdoptOpenJDK 停止发布 OpenJDK 二进制,而 Eclipse Temurin 是它的延伸,提供更好的稳定性
FROM eclipse-temurin:8-jre
## 作者
LABEL org.opencontainers.image.authors="daiwuliang@126.com"
## 定义参数
## 创建并进入工作目录
RUN mkdir -p /works
WORKDIR /works
## maven 插件构建时得到 buildArgs 种的值
COPY target/*.jar app.jar
## 设置 TZ 时区
## 设置 JAVA_OPTS 环境变量,可通过 docker run -e "JAVA_OPTS=" 进行覆盖
ENV TZ=Asia/Shanghai JAVA_OPTS="-Xms256m -Xmx256m"
## 暴露端口
EXPOSE 5001
## 容器启动命令
## CMD 第一个参数之后的命令可以在运行时被替换
CMD java ${JAVA_OPTS} -Djava.security.egd=file:/dev/./urandom -jar app.jar
k8s yaml
---
apiVersion: apps/v1
kind: Deployment
metadata:
labels:
app: k8s-cicd-demo
component: daiwuliang-devops
tier: backend
name: k8s-cicd-demo
namespace: k8s-cicd
spec:
progressDeadlineSeconds: 600
replicas: 1
selector:
matchLabels:
app: k8s-cicd-demo
component: daiwuliang-devops
tier: backend
strategy:
rollingUpdate:
maxSurge: 100%
maxUnavailable: 100%
type: RollingUpdate
template:
metadata:
labels:
app: k8s-cicd-demo
component: daiwuliang-devops
tier: backend
spec:
imagePullSecrets:
- name: harbor-secret
containers:
- name: k8s-cicd-demo
image: REGISTRY/DOCKERHUB_NAMESPACE/APP_NAME:TAG_NAME
readinessProbe:
httpGet:
path: /users
port: 8080
timeoutSeconds: 10
failureThreshold: 30
periodSeconds: 5
imagePullPolicy: Always
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
---
apiVersion: v1
kind: Service
metadata:
labels:
app: k8s-cicd-demo
component: daiwuliang-devops
name: k8s-cicd-demo
namespace: k8s-cicd
spec:
ports:
- name: http
port: 8080
protocol: TCP
targetPort: 8080
selector:
app: k8s-cicd-demo
component: daiwuliang-devops
tier: backend
sessionAffinity: None
type: NodePort
Jenkinsfile
pipeline {
agent {
kubernetes {
label 'maven'
}
}
parameters {
gitParameter name: 'BRANCH_NAME', branch: '', branchFilter: '.*', defaultValue: 'origin/master', description: '请选择要发布的分支', quickFilterEnabled: false, selectedValue: 'NONE', tagFilter: '*', type: 'PT_BRANCH'
string(name: 'TAG_NAME', defaultValue: 'snapshot', description: '标签名称,必须以 v 开头,例如:v1、v1.0.0')
}
environment {
DOCKER_CREDENTIAL_ID = 'harbor-user-pass'
GIT_REPO_URL = 'git-url'
GIT_CREDENTIAL_ID = 'git-user-pass'
GIT_ACCOUNT = 'gitlab-account'
KUBECONFIG_CREDENTIAL_ID = ''
REGISTRY = 'harbor-address'
DOCKERHUB_NAMESPACE = ''
APP_NAME = 'k8s-cicd-demo'
SONAR_CREDENTIAL_ID = 'sonarqube-token'
}
stages {
stage('checkout scm') {
steps {
checkout scmGit(branches: [[name: "$BRANCH_NAME"]], extensions: [], userRemoteConfigs: [[credentialsId: "$GIT_CREDENTIAL_ID", url: 'url']])
}
}
stage('unit test') {
steps {
sh 'mvn clean test'
}
}
stage('sonarqube analysis') {
steps {
withCredentials([string(credentialsId: "$SONAR_CREDENTIAL_ID", variable: 'SONAR_TOKEN')]) {
withSonarQubeEnv('sonarqube') {
sh 'mvn sonar:sonar -Dsonar.projectKey=$APP_NAME'
}
}
timeout(time: 1, unit: 'HOURS') {
waitForQualityGate abortPipeline: true
}
}
}
stage('build & push') {
steps {
sh 'mvn clean package -DskipTests'
sh 'docker build -f Dockerfile -t $REGISTRY/$DOCKERHUB_NAMESPACE/$APP_NAME:SNAPSHOT-$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-$BUILD_NUMBER'
}
}
}
stage('push latest') {
steps {
sh 'docker tag $REGISTRY/$DOCKERHUB_NAMESPACE/$APP_NAME:SNAPSHOT-$BUILD_NUMBER $REGISTRY/$DOCKERHUB_NAMESPACE/$APP_NAME:latest'
sh 'docker push $REGISTRY/$DOCKERHUB_NAMESPACE/$APP_NAME:latest'
}
}
stage('deploy to dev') {
steps {
input(id: 'deploy-to-dev', message: 'deploy to dev?')
sh '''
sed -i'' "s#REGISTRY#$REGISTRY#" deploy/cicd-demo-dev.yaml
sed -i'' "s#DOCKERHUB_NAMESPACE#$DOCKERHUB_NAMESPACE#" deploy/cicd-demo-dev.yaml
sed -i'' "s#APP_NAME#$APP_NAME#" deploy/cicd-demo-dev.yaml
sed -i'' "s#BUILD_NUMBER#$BUILD_NUMBER#" deploy/cicd-demo-dev.yaml
kubectl apply -f deploy/cicd-demo-dev.yaml
'''
}
}
stage('push with tag') {
when {
expression {
return params.TAG_NAME =~ /v.*/
}
}
steps {
input(id: 'release-image-with-tag', message: 'release image with tag?')
withCredentials([usernamePassword(credentialsId: "$GIT_CREDENTIAL_ID", passwordVariable: 'GIT_PASSWORD', usernameVariable: 'GIT_USERNAME')]) {
sh 'git config --global user.email "daiwuliang@126.com" '
sh 'git config --global user.name "daiwl" '
sh 'git tag -a $TAG_NAME -m "$TAG_NAME" '
sh 'git push http://$GIT_USERNAME:$GIT_PASSWORD@$GIT_REPO_URL/$GIT_ACCOUNT/k8s-cicd-demo.git --tags --ipv4'
}
sh 'docker tag $REGISTRY/$DOCKERHUB_NAMESPACE/$APP_NAME:SNAPSHOT-$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?')
sh '''
sed -i'' "s#REGISTRY#$REGISTRY#" deploy/cicd-demo.yaml
sed -i'' "s#DOCKERHUB_NAMESPACE#$DOCKERHUB_NAMESPACE#" deploy/cicd-demo.yaml
sed -i'' "s#APP_NAME#$APP_NAME#" deploy/cicd-demo.yaml
sed -i'' "s#TAG_NAME#$TAG_NAME#" deploy/cicd-demo.yaml
kubectl apply -f deploy/cicd-demo.yaml
'''
}
}
}
}
1632

被折叠的 条评论
为什么被折叠?



