
DevOps 提供一系列持续集成 (CI) 和持续交付 (CD) 工具,可以使 IT 和软件开发团队之间的流程实现自动化。在 CI/CD 工作流中,每次集成都通过自动化构建来验证,包括编码、发布和测试,从而帮助开发者提前发现集成错误,团队也可以快速、安全、可靠地将内部软件交付到生产环境。
DevOps CI/CD 流水线基于底层 Kubernetes Jenkins Agent 运行。这些 Jenkins Agent 可以动态扩缩,即根据任务状态进行动态供应或释放。Jenkins Controller 和 Agent 以 Pod 的形式运行在 KubeSphere 节点上。Controller 运行在其中一个节点上,其配置数据存储在一个持久卷声明中。Agent 运行在各个节点上,但可能不会一直处于运行状态,而是根据需求动态创建并自动删除。
当 Jenkins Controller 收到构建请求,会根据标签动态创建运行在 Pod 中的 Jenkins Agent 并注册到 Controller 上。当 Agent 运行完任务后,将会被释放,相关的 Pod 也会被删除。
资源分配合理:动态分配已创建的 Agent 至空闲节点,避免因单个节点资源利用率高而导致任务排队等待。
高可扩缩性:当集群因资源不足而导致任务长时间排队等待时,支持向集群新增节点。
高可用性:当 Jenkins Controller 故障时,DevOps 会自动创建一个新的 Jenkins Controller 容器,并将持久卷挂载至新创建的容器,保证数据不会丢失,从而实现集群高可用。
pipeline {
agent {
node {
label 'maven'
}
}
stages {
stage('拉取代码') {
agent none
steps {
container('maven') {
// 使用指定的凭证拉取代码,指定分支
// 注意凭证需要先创建
git(url: 'https://gitee.com/heyangyi/grpcs.git', credentialsId: 'heyangyi-git-account' , branch: 'dev', changelog: true, poll: false)
sh 'ls -al'
}
}
}
stage('构建镜像') {
agent none
steps {
container('maven') {
// 注意此处Dockerfile文件地址:GRPCS/GRPCS.NoticeService/Dockerfile GRPCS/
sh 'docker build -t $REGISTRY/$DOCKERHUB_NAMESPACE/$APP_NAME:$BRANCH_NAME-$BUILD_NUMBER -f GRPCS/GRPCS.NoticeService/Dockerfile GRPCS/'
sh 'docker images'
}
}
}
stage('推送-构建编号-镜像') {
agent none
steps {
container('maven') {
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:$BRANCH_NAME-$BUILD_NUMBER'
}
}
}
}
stage('推送-latest-镜像') {
steps {
container('maven') {
sh 'docker tag $REGISTRY/$DOCKERHUB_NAMESPACE/$APP_NAME:$BRANCH_NAME-$BUILD_NUMBER $REGISTRY/$DOCKERHUB_NAMESPACE/$APP_NAME:latest '
sh 'docker push $REGISTRY/$DOCKERHUB_NAMESPACE/$APP_NAME:latest '
}
}
}
stage('部署到Test环境') {
steps {
container('maven') {
//input(id: 'deploy-to-dev', message: 'deploy to dev?')
withCredentials([kubeconfigContent(credentialsId : 'kubeconfig-credential-id' ,variable : 'KUBECONFIG_CONFIG' ,)]) {
sh 'mkdir -p ~/.kube/'
sh 'echo "$KUBECONFIG_CONFIG" > ~/.kube/config'
// 注意:此处为源代码所在目录的deploy.yaml文件地址
sh 'envsubst < GRPCS/GRPCS.NoticeService/deploy.yaml | kubectl apply -f -'
}
}
}
}
}
environment {
// 阿里云镜像仓库账号密码凭证:用于推送镜像
DOCKER_CREDENTIAL_ID = 'aliyun-docker-registry'
// gitee账号密码凭证:用于拉取源代码
GITHUB_CREDENTIAL_ID = 'heyangyi-git-account'
// KUBECONFIG:连接和认证Kubernetes集群所需的各种参数和凭证信息
KUBECONFIG_CREDENTIAL_ID = 'kubeconfig-credential-id'
// 阿里云镜像仓库地址
REGISTRY = 'registry.cn-hongkong.aliyuncs.com'
// 阿里云镜像仓库命名空间
DOCKERHUB_NAMESPACE = 'learn-work'
// APP名称
APP_NAME = 'grpcs'
// APP在K8S命名空间:注意在KubeSphere是企业空间下的项目名称,需要先创建
APP_NAMESPACE = 'demo-product'
// 副本数
REPLICAS = 1
// 分支名称
BRANCH_NAME = 'dev'
// ASP.NET CORE 环境名称
ASPNETCORE_ENVIRONMENT = 'ASPNETCORE_ENVIRONMENT'
// ASP.NET CORE 环境名称值
ASPNETCORE_ENVIRONMENT_VALUE = 'Development'
// ASP.NET CORE 环境名称
ASPNETCORE_URLS = 'ASPNETCORE_URLS'
// ASP.NET CORE 环境名称值
ASPNETCORE_URLS_VALUE = 'http://*:8080'
// ASP.NET CORE 环境名称
ASPNETCORE_TZ = 'TZ'
// ASP.NET CORE 环境名称值
ASPNETCORE_TZ_VALUES = 'Asia/Shanghai'
// APP端口
APP_PORT = '8080'
}
parameters {
string(name: 'TAG_NAME', defaultValue: '', description: '')
}
}上面使用的凭证:aliyun-docker-registry、heyangyi-git-account、kubeconfig-credential-id

apiVersion: app.k8s.io/v1beta1
kind: Application
metadata:
name: ${APP_NAME}
namespace: ${APP_NAMESPACE}
labels:
app.kubernetes.io/version: v1
app.kubernetes.io/name: ${APP_NAME}
annotations:
servicemesh.kubesphere.io/enabled: "true"
spec:
selector:
matchLabels:
app.kubernetes.io/version: v1
app.kubernetes.io/name: ${APP_NAME}
addOwnerRef: true
componentKinds:
- group: ""
kind: Service
- group: apps
kind: Deployment
- group: apps
kind: StatefulSet
- group: extensions
kind: Ingress
- group: servicemesh.kubesphere.io
kind: Strategy
- group: servicemesh.kubesphere.io
kind: ServicePolicy
---
apiVersion: apps/v1
kind: Deployment
metadata:
namespace: ${APP_NAMESPACE}
labels:
version: v1
app: ${APP_NAME}
app.kubernetes.io/version: v1
app.kubernetes.io/name: ${APP_NAME}
name: ${APP_NAME}-v1
annotations:
servicemesh.kubesphere.io/enabled: "true"
spec:
replicas: ${REPLICAS}
selector:
matchLabels:
version: v1
app: ${APP_NAME}
app.kubernetes.io/version: v1
app.kubernetes.io/name: ${APP_NAME}
template:
metadata:
labels:
version: v1
app: ${APP_NAME}
app.kubernetes.io/version: v1
app.kubernetes.io/name: ${APP_NAME}
annotations:
sidecar.istio.io/inject: "true"
spec:
containers:
- name: container-${APP_NAME}
imagePullPolicy: Always
image: $REGISTRY/$DOCKERHUB_NAMESPACE/$APP_NAME:$BRANCH_NAME-$BUILD_NUMBER
ports:
- name: grpc-${APP_NAME}
protocol: TCP
containerPort: ${APP_PORT}
env:
- name: ${ASPNETCORE_ENVIRONMENT}
value: ${ASPNETCORE_ENVIRONMENT_VALUE}
- name: ${ASPNETCORE_URLS}
value: ${ASPNETCORE_URLS_VALUE}
- name: ${ASPNETCORE_TZ}
value: ${ASPNETCORE_TZ_VALUES}
serviceAccount: default
affinity: {}
initContainers: []
volumes: []
imagePullSecrets:
- name: ${DOCKER_CREDENTIAL_ID}
strategy:
type: RollingUpdate
rollingUpdate:
maxUnavailable: 25%
maxSurge: 25%
---
apiVersion: v1
kind: Service
metadata:
namespace: ${APP_NAMESPACE}
labels:
version: v1
app: ${APP_NAME}
app.kubernetes.io/version: v1
app.kubernetes.io/name: ${APP_NAME}
annotations:
kubesphere.io/serviceType: statelessservice
servicemesh.kubesphere.io/enabled: "true"
name: ${APP_NAME}
spec:
sessionAffinity: None
selector:
app: ${APP_NAME}
app.kubernetes.io/version: v1
app.kubernetes.io/name: ${APP_NAME}
ports:
- name: grpc-${APP_NAME}
protocol: TCP
port: 80
targetPort: ${APP_PORT}
---Kubesphere 扩展组件使用 - CICD - DevOps
注意:安装DevOps扩展组件的过程中遇到一些问题,多数情况是镜像下载不下来,遇到下载不下来的情况下建议在安装过程中查看kubesphere-devops-system项目下容器组的镜像,发现下载不下来的镜像在本机拉取下来,然后导出到本机上传到k8s节点,再还原上去。
#导出单个镜像
docker save -o [输出文件名].tar [镜像名称或ID]#加载单个镜像
docker load -i [输入文件名].tar

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。