注:
关于Kubesphere及K8S的搭建可参见我之前的博客:
Kubesphere All-in-one模式安装
方式1:未安装KS前进行设置
在安装KS前,可通过编辑config-sample.yaml文件,设置如下:
devops:
enabled: true # 将“false”更改为“true”。
然后通过如下命令安装KS:
./kk create cluster -f config-sample.yaml
方式2:已安装过KS通过管理界面进行设置
若之前已安装过KS,则可通过KS管理界面左侧菜单CRD -> 搜索clusterconfiguration -> 然后编辑其下资源ks-installer
,如下图:
同样设置devops.enabled为true:
Kubesphere Devops详细开启说明可参见:
https://kubesphere.io/zh/docs/pluggable-components/devops/
设置完成后可通过KS管理界面查看系统组件 - DevOps相关资源是否已安装完成,如下图:
企业空间:作为管理项目、DevOps 项目和组织成员的基本逻辑单元,企业空间是 KubeSphere 多租户系统的基础。
项目:KubeSphere 中的项目与 Kubernetes 中的命名空间相同,为资源提供了虚拟隔离。
Devops项目:不同权限的租户可以在 DevOps 项目中执行各种任务,包括创建 CI/CD 流水线和凭证以及管理帐户和角色。
流水线:一系列插件的集合,使您可以持续地测试和构建代码。流水线将持续集成 (CI) 和持续交付 (CD) 进行结合,提供精简的工作流,使您的代码可以自动交付给任何目标。
凭证:具有所需权限的 DevOps 项目用户可以为流水线配置凭证,以便与外部环境进行交互。用户在 DevOps 项目中添加凭证后,DevOps 项目就可以使用这些凭证与第三方应用程序(例如 GitHub、GitLab 和 Docker Hub)进行交互。
整体环境设置及如下:
后续在使用流水线时,Jenkins pipeline脚本需要与外部Git仓库、Docker仓库、K8s集群进行交互,所以需要在其对应的Devops项目中添加凭证(用于访问外部环境的账号密码、密钥等),后续在Jenkins pipeline脚本中会通过凭证名称(ID)进行引用。
测试环境的外部依赖如下:
依赖 | 来源 | 凭证信息 |
---|---|---|
Git代码仓库 | Gitee 代码地址:https://gitee.com/luoex/ks-devops-demo |
Gitee登录账号密码 |
Docker镜像仓库 | 阿里云容器镜像服务ACR - 个人版(免费版) 限额:3命名空间,300个仓库 公网地址:registry.cn-shanghai.aliyuncs.com 命名空间:luo_dev 仓库名称:ks-devops-demo |
ACR docker login账号密码 |
K8s集群 | 当前Kubesphere所在K8s集群 | 当前K8s集群的kubeconfig文件 |
对应上述依赖,在luo-devops项目下新建如下3个凭证:
凭证名称(ID) | 凭证类型 | 凭证说明 |
---|---|---|
gittee-luo | 用户名和密码 | Gitee登录账号密码, 用于流水线拉取代码 |
docker-aliyun-acr | 用户名和密码 | 阿里云容器镜像服务ACR个人版 docker login账号密码, 用于Jenkins脚本推送docker镜像 |
k8s-config-ks | kubeconfig | 当前K8s集群的kubeconfig文件(新建时默认填充), 用于Jenkins脚本部署K8s应用负载 |
除了使用用户名和密码
类型,还可以使用SSH密钥
类型,具体设置方式可参见:
生成SSH密钥对(与gitlab、jenkins集成)
阿里云ACR docker login账号密码获取参见下图:
Kubesphere流水线采用Jenkins进行构建,在构建过程中Jenkins会在创建worker实例去执行具体的构建,如下图为maven构建worker实例:
此Pod的详细配置如下:
查看Pod定义可以发现,可通过修改:
kubesphere-devops-worker命名空间下
ks-devops-agent配置(ConfigMap)中的MavenSetting
来设置自定义的Maven私服配置,
可直接通过如下命令查看对应配置:
kubectl get cm -n kubesphere-devops-worker ks-devops-agent -o yaml
通过配置自定义Maven私服可以:
本例中使用的Maven仓库为阿里云 - 云效 - 制品仓库 - Maven仓库(免费版)
,懒得自己再搭建一个Nexus私服,仅处于测试目的直接使用免费版比较方便,实际企业使用时或者为公有云、或者为企业内部自建Nexus私服等。
自定义maven settings.xml配置可参见如下截图:
关于此Maven settings.xml文件的编写,可结合具体Maven私服地址及账号进行编写,
在阿里云中的Maven仓库支持一键下载:
在通过docker pull拉取镜像时,需先通过docker login进行登录,而在K8S集群中可通过为Deployment设置imagePullSecrets达到类似的登录效果,避免拉取Docker镜像失败。
apiVersion: apps/v1
kind: Deployment
...
spec:
...
template:
...
spec:
imagePullSecrets:
# 通过同K8s namespace的密钥secret名称来指定镜像仓库及凭证信息
- name: docker-aliyun-acr
containers:
- name: app
...
创建阿里云ACR镜像仓库密钥docker-aliyun-acr:
注:
此处的docker仓库地址即为之前提到的阿里云ACR地址相同,
账号密码也和前文提到的ACR账号密码相同(即对应docker-aliyun-acr凭证),
此处的密钥docker-aliyun-acr
用于K8s集群节点拉取镜像,
而前文的Devops项目凭证docker-aliyun-acr
用于Jenkins脚本(即Jenkins工作实例)操作docker镜像。
示例中使用的Gitee代码库ks-devops-demo为一个简单的Spring Boot Web应用,仅提供一个Hello接口,具体项目中可根据需求自行替换为对应实现,该示例的重点是根路径devops目录下的相关脚本:
资源文件 | 说明 |
---|---|
/devops/Jenkinsfile | Jenkins流水线脚本 |
/devops/Dockerfile | Docker镜像构建文件 |
/deploy/k8s.yaml | K8S应用负载定义 |
其中devops/Dockerfile用来给示例Java应用构建Docker镜像:
# 基础JDK镜像
FROM openjdk:11.0.6-jdk-slim-buster
# 维护者
MAINTAINER luo.hq <[email protected]>
# 环境变量设置
ENV TZ "Asia/Shanghai"
ENV JVM_OPTIONS ""
# 拷贝maven构建后的jar包到镜像内/app.jar
ADD /target/*.jar /app.jar
# 暴露端口
EXPOSE 8080
# 启动命令 - 执行Jar
ENTRYPOINT ["sh", "-c", "java ${JVM_OPTIONS} -jar /app.jar"]
devops/k8s.yaml为示例应用对应的K8S部署脚本(Deployment、Service):
注: 可根据具体部署需要进行调整
# K8S服务定义
apiVersion: v1
kind: Service
metadata:
labels:
app: ks-devops-demo
version: v1
name: ks-devops-demo
spec:
# 使用NodePort类型(替换默认ClusterIP,便于测试)
type: NodePort
sessionAffinity: None
selector:
app: ks-devops-demo
version: v1
ports:
- name: http-web
protocol: TCP
port: 8080
targetPort: 8080
---
# K8S工作负载定义
apiVersion: apps/v1
kind: Deployment
metadata:
labels:
app: ks-devops-demo
version: v1
name: ks-devops-demo
spec:
replicas: 1
selector:
matchLabels:
app: ks-devops-demo
version: v1
template:
metadata:
labels:
app: ks-devops-demo
version: v1
spec:
# 设置Docker仓库密钥(用于拉取镜像)
# 通过同K8s namespace的密钥secret名称来指定镜像仓库及凭证信息
imagePullSecrets:
- name: docker-aliyun-acr
containers:
- name: app
# 设置Docker镜像(同Jenkinsfile脚本中的环境变量)
image: $DOCKER_REGISTRY/$DOCKER_NAMESPACE/$APP_NAME:$IMAGE_TAG
imagePullPolicy: Always
# 资源限制
resources:
requests:
cpu: 10m
memory: 128Mi
limits:
cpu: '1'
memory: 1000Mi
# 健康检查
livenessProbe:
failureThreshold: 3
httpGet:
path: /actuator/health
port: 8080
scheme: HTTP
initialDelaySeconds: 60
successThreshold: 1
readinessProbe:
httpGet:
path: /actuator/health
port: 8080
scheme: HTTP
initialDelaySeconds: 20
successThreshold: 1
failureThreshold: 3
# 容器端口映射
ports:
- name: http-web
protocol: TCP
containerPort: 8080
strategy:
# 滚动更新策略
type: RollingUpdate
rollingUpdate:
# 最多不可用比例
maxUnavailable: 25%
# 最多新增比例
maxSurge: 25%
devops/Jenkinsfile为Jenkins流水线的核心构建脚本,用来编排整个流水线的执行过程:
generate tag -> maven build -> docker build & push -> k8s deploy
并将之前的devops/Dockerfile和devops/k8s.yaml串联起来:
pipeline{
agent {
node {
//选择Jenkins agent工作节点
//支持label值:maven | nodejs | go
//具体参见:https://kubesphere.io/zh/docs/devops-user-guide/how-to-use/choose-jenkins-agent/
label 'maven'
}
}
//环境变量设置
environment {
//Docker凭证ID
DOCKER_CREDENTIAL_ID = 'docker-aliyun-acr'
//Docker仓库地址
DOCKER_REGISTRY = 'registry.cn-shanghai.aliyuncs.com'
//Docker仓库命名空间
DOCKER_NAMESPACE = 'luo_dev'
//应用名称(即Docker镜像名称)
APP_NAME = 'ks-devops-demo'
//K8S配置凭证ID
K8S_CONFIG_CREDENTIAL_ID = 'k8s-config-ks'
//K8S部署命名空间(对应Kubesphere项目)
K8S_NAMESPACE = 'ks-devops-demo'
}
//构建阶段
stages {
//生成镜像版本
stage('generate tag') {
steps {
script {
//commitId.buildNum
env.COMMIT_ID = sh(script: 'git rev-parse --short HEAD ', returnStdout: true).trim()
env.IMAGE_TAG = "${COMMIT_ID}.$BUILD_NUMBER"
}
}
}
//maven构建
stage('maven build') {
steps {
container ('maven') {
//maven打包(生产环境建议支持test)
sh 'mvn clean package -Dmaven.test.skip=true'
//归档文件(若不需要可无需归档)
archiveArtifacts 'target/*.jar'
}
}
}
//构建Docker镜像并推送到远程Docker仓库
stage('docker build & push') {
steps {
container ('maven') {
//构建docker镜像
sh 'docker build -f devops/Dockerfile -t $DOCKER_REGISTRY/$DOCKER_NAMESPACE/$APP_NAME:$IMAGE_TAG .'
//登录Docker并推送镜像到远程Docker仓库
withCredentials([usernamePassword(passwordVariable : 'DOCKER_PASSWORD' ,usernameVariable : 'DOCKER_USERNAME' ,credentialsId : "$DOCKER_CREDENTIAL_ID" ,)]) {
sh 'echo "$DOCKER_PASSWORD" | docker login $DOCKER_REGISTRY -u "$DOCKER_USERNAME" --password-stdin'
sh 'docker push $DOCKER_REGISTRY/$DOCKER_NAMESPACE/$APP_NAME:$IMAGE_TAG'
}
}
}
}
//K8S部署
stage('k8s deploy') {
steps {
container ('maven') {
//使用对应K8s配置
withCredentials([
kubeconfigFile(
credentialsId: env.K8S_CONFIG_CREDENTIAL_ID,
variable: 'KUBECONFIG')
]) {
//替换部署脚本中的环境变量后执行k8s部署
sh 'envsubst < devops/k8s.yaml | kubectl apply -n $K8S_NAMESPACE -f -'
}
}
}
}
}
}
在Devops项目luo-devops下新建流水线ks-devops-demo,具体过程如下:
如上设置后,Jenkins在拉取代码后,根据脚本路径(即对应代码根目录下devops/Jenkinfile)提取出Jenkins Pipeline脚本,并据此脚本执行流水线CI/CD。
点击进入具体的流水线活动即可查看当前活动的构建状态:
查看流水线构建日志页面:
如下状态标记为成功的即为执行成功的流水线,若构建失败,可通过查看流水线日志排查相应问题。
测试ks-devops-demo服务是否可以正常访问:
综上便完成了一个Java应用的整个流水线集成及运行。
参考:
https://kubesphere.com.cn/docs/pluggable-components/devops/
https://kubesphere.com.cn/docs/devops-user-guide/how-to-use/credential-management/
https://kubesphere.com.cn/docs/devops-user-guide/examples/a-maven-project/
https://kubesphere.io/zh/docs/devops-user-guide/examples/a-maven-project/#jenkins-agent-中的全局-maven-设置