文章目录
一. 安装
1.1 下载yaml
mkdir -p /root/i/yaml/kubesphere && cd /root/i/yaml/kubesphere
wget https://github.com/kubesphere/ks-installer/releases/download/v3.3.0/kubesphere-installer.yaml
wget https://github.com/kubesphere/ks-installer/releases/download/v3.3.0/cluster-configuration.yaml
查看
[root@master kubesphere]# ls
cluster-configuration.yaml kubesphere-installer.yaml
1.2 设置默认StorageClass
[root@master kubesphere]# kubectl get sc | grep nfs-storage
nfs-storage nfs-storage Retain Immediate false 115d
[root@master kubesphere]# kubectl patch storageclass nfs-storage -p '{ "metadata" : { "annotations" :{"storageclass.kubernetes.io/is-default-class": "true"}}}'
storageclass.storage.k8s.io/nfs-storage patched
[root@master kubesphere]# kubectl get sc | grep nfs-storage
nfs-storage (default) nfs-storage Retain Immediate false 115d
如果没有设置,不会安装
1.3 安装
kubectl create ns kubesphere-system
kubectl apply -f kubesphere-installer.yaml
安装成功
[root@master kubesphere]# kubectl get pods -n kubesphere-system
NAME READY STATUS RESTARTS AGE
ks-installer-c9655d997-hpqns 1/1 Running 0 72s
1.4 配置
kubectl apply -f cluster-configuration.yaml
检查安装日志
kubectl logs -n kubesphere-system $(kubectl get pod -n kubesphere-system -l 'app in (ks-install, ks-installer)' -o jsonpath='{.items[0].metadata.name}') -f
1.5 查看
新建了命名空间
kubesphere-controls-system:
kubesphere-monitoring-federated:联邦集群,多集群
kubesphere-monitoring-system:集群监控
kubesphere-system:
其他资源
[root@master kubesphere]# kubectl get pods -n kubesphere-system
NAME READY STATUS RESTARTS AGE
ks-apiserver-66cd784f8f-jn2k5 1/1 Running 0 11m
ks-console-5c5676fb55-h6krc 1/1 Running 0 11m
ks-controller-manager-6d6b54464d-qrxfs 1/1 Running 0 11m
ks-installer-c9655d997-kz4gb 1/1 Running 0 12m
[root@master kubesphere]# kubectl get svc -n kubesphere-system
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
ks-apiserver ClusterIP 10.109.250.63 <none> 80/TCP 11m
ks-console NodePort 10.102.49.78 <none> 80:30880/TCP 11m
ks-controller-manager ClusterIP 10.101.243.88 <none> 443/TCP 11m
[root@master kubesphere]# kubectl get pods -n kubesphere-monitoring-system
NAME READY STATUS RESTARTS AGE
alertmanager-main-0 2/2 Running 0 8m58s
alertmanager-main-1 2/2 Running 0 8m57s
alertmanager-main-2 2/2 Running 0 8m56s
kube-state-metrics-645c64569c-pkvkj 3/3 Running 0 9m55s
node-exporter-2t6pq 2/2 Running 0 9m54s
node-exporter-bstgl 2/2 Running 0 9m54s
node-exporter-mts6g 2/2 Running 0 9m55s
notification-manager-deployment-7dd45b5b7d-p4bpr 2/2 Running 0 5m15s
notification-manager-deployment-7dd45b5b7d-sp8vw 2/2 Running 0 5m15s
notification-manager-operator-8598775b-vppz6 2/2 Running 0 9m34s
prometheus-k8s-0 2/2 Running 0 8m57s
prometheus-k8s-1 2/2 Running 0 8m55s
prometheus-operator-57c78bd7fb-jbfxs 2/2 Running 0 9m56s
[root@master kubesphere]# kubectl get pvc -n kubesphere-monitoring-system
NAME STATUS VOLUME CAPACITY ACCESS MODES STORAGECLASS AGE
prometheus-k8s-db-prometheus-k8s-0 Bound pvc-9046cbb5-8c31-4014-9342-6a63fb348fb3 20Gi RWO nfs-storage 9m9s
prometheus-k8s-db-prometheus-k8s-1 Bound pvc-5816cdfc-0976-4312-918c-d4dc361d5ec9 20Gi RWO nfs-storage 9m7s
1.6 页面
访问 http://192.168.4.27:30880,默认账号密码admin/P@88w0rd
,然后要求修改密码Ww$19930327
二. 流水线部署
2.1 开启流水线设置
2.1.1 未安装KS前进行设置
在安装KS
前,可通过编辑config-sample.yaml
文件,设置如下:
devops:
enabled: true # 将"false"更改为true
2.1.2 已安装过KS通过管理界面进行设置
若之前已安装过KS
,则可通过KS
管理界面(平台管理->集群管理)左侧菜单定时资源定义(CRD)
-> 搜索clusterconfiguration
-> 然后编辑其下资源ks-installer
,如下图:
点击进入
同样设置devops.enabled
为true
:
在 kubectl
中执行以下命令检查安装过程:
kubectl logs -n kubesphere-system $(kubectl get pod -n kubesphere-system -l 'app in (ks-install, ks-installer)' -o jsonpath='{.items[0].metadata.name}') -f
Kubesphere Devops
详细开启说明可参见:
https://kubesphere.io/zh/docs/pluggable-components/devops/
2.2 查看流水线安装
设置完成后可通过KS
管理界面查看系统组件 - DevOps
相关资源是否已安装完成,如下图:
状态都是
健康
,安装成功
2.3 创建企业空间
工作台 -> 企业空间 -> 创建
2.4 创建DevOps项目
2.5 Devops项目添加凭证
后续在使用流水线时,Jenkins pipeline
脚本需要与外部Git仓库
、Docker仓库
、K8s集群(可以是外部集群)
进行交互,所以需要在其对应的Devops
项目中添加凭证(用于访问外部环境的账号密码、密钥等),后续在Jenkins pipeline
脚本中会通过凭证名称(ID
)进行引用。
测试环境的外部依赖如下:
凭证名称(ID) | 凭证类型 | 凭证说明 |
---|---|---|
gitee-wanfei | 用户名和密码 | Gitee登录账号密码,用于流水线拉取代码 |
docker-aliyun | 用户名和密码 | 阿里云容器镜像服务ACR个人版 docker login账号密码,用于Jenkins脚本推送docker镜像 |
k8s-config-ks | kubeconfig | 当前K8s集群的kubeconfig文件(新建时默认填充),用于Jenkins脚本部署K8s应用负载 |
双击 DevOps
项目名称进入
具体凭证列表如下图:
2.6 自定义 Jenkins Agent(忽略这一步)
2.6.1 查看agent配置
配置->配置字典->搜索jenkins-casc-config
->编辑YAML
搜索data.jenkins_user.yaml:jenkins.clouds.kubernetes.templates
2.6.2 自定义agent配置(label没有发现)
也可以添加自定义镜像,例如:
- name: "maven-jdk11" # 自定义 Jenkins Agent 的名称。
label: "maven jdk11" # 自定义 Jenkins Agent 的标签。若要指定多个标签,请用空格来分隔标签。
inheritFrom: "maven" # 该自定义 Jenkins Agent 所继承的现有容器组模板的名称。
containers:
- name: "maven" # 该自定义 Jenkins Agent 所继承的现有容器组模板中指定的容器名称。
image: "kubespheredev/builder-maven:v3.2.0jdk11" # 此镜像只用于测试。您可以使用自己的镜像。
2.6.3 java8
官方镜像:kubesphere/builder-maven:v3.2.0
,但是helm
版本是2
2.6.4 java11
官方镜像:kubesphere/builder-maven:v3.2.1-jdk11
,但是helm
版本是2
2.6.5 maven-pvc(可以不用pvc执行挂载hostPath)
添加maven-pvc
,也可以使用现有的devops-jenkins
pvc
,存储maven
下载的jar
,多次部署不用重复下载
2.7 测试流水线Jenkinsfile(可以跳过)
2.7.1 使用自带的label
maven
pipeline {
agent {
node {
label 'maven'
}
}
stages {
stage('Print Maven and JDK version') {
steps {
container('maven') {
sh '''
mvn -v
java -version
'''
}
}
}
}
}
参考 https://kubesphere.io/zh/docs/v3.3/devops-user-guide/how-to-use/pipelines/choose-jenkins-agent/
2.7.2 使用自定义得label
maven && jdk11
(报错label发现不了)
pipeline {
agent {
node {
label 'maven && jdk11'
}
}
stages {
stage('Print Maven and JDK version') {
steps {
container('maven') {
sh '''
mvn -v
java -version
'''
}
}
}
}
}
参考 https://kubesphere.io/zh/docs/v3.3/devops-user-guide/how-to-use/pipelines/customize-jenkins-agent/
2.7.3 yaml
pipeline {
agent {
kubernetes {
//cloud 'kubernetes'
label 'mypod'
yaml """
apiVersion: v1
kind: Pod
spec:
containers:
- name: maven
image: kubesphere/builder-maven:v3.2.1-jdk11
command: ['cat']
tty: true
"""
}
}
stages {
stage('Print Maven and JDK version') {
steps {
container('maven') {
sh '''
mvn -v
java -version
'''
}
}
}
}
}
2.8 测试流水线
2.8.1 项目添加Jekinsfile``2.7.1
2.8.2 创建流水线
输入git
仓库地址和凭证
2.8.3 查看git分支
双击流水线名称进入
2.8.4 运行
运行中
双击进入
2.8.5 查看日志
点击右上角 查看日志
可以看到执行了
Jenkinsfile
配置的流水线脚本
2.9 项目Jenkinsfile
def label = "slave-${UUID.randomUUID().toString()}"
def helmLint(String chartDir) {
println "校验 chart 模板"
sh "helm lint ${chartDir}"
}
def helmDeploy(Map args) {
if (args.dry_run) {
println "Debug 应用 ${args.profile} 环境"
sh "helm upgrade --install --dry-run --debug --install ..."
} else {
println "部署应用 到 ${args.profile} 环境"
sh "helm upgrade --install --set global.pullPolicy=Always --set global.javaOpts='-Xms256m -Xmx1024m -Xss512k -XX:+PrintGC' \
--set global.imagePullSecrets=${args.imagePullSecrets} --set global.imageHub.server=${args.imageHubServer}\
--set global.imageHub.project=${args.imageHubProject} --set global.version=${args.imageTag} \
--set global.profiles=${args.profile} --set global.namespace=${args.namespace} ${args.name} ${args.chartDir}"
echo "应用 ${args.name} 部署成功. 可以使用 helm status ${args.name} 查看应用状态"
}
}
podTemplate(label: label,
containers: [
containerTemplate(name: 'maven', image: 'kubesphere/builder-maven:v3.2.1-jdk11', command: 'cat', ttyEnabled: true),
containerTemplate(name: 'helm', image: 'hypnoglow/kubernetes-helm:3.0.2', command: 'cat', ttyEnabled: true)
],
volumes: [
hostPathVolume(hostPath: '/var/run/docker.sock', mountPath: '/var/run/docker.sock'),
hostPathVolume(hostPath: '/var/data/jenkins_maven_cache', mountPath: '/root/.m2'),
hostPathVolume(mountPath: '/var/data/jenkins_sonar_cache', hostPath: '/root/.sonar/cache')
]) {
node(label) {
// checkout scm 下载代码
def myRepo = checkout scm
def gitCommit = myRepo.GIT_COMMIT
def gitBranch = myRepo.GIT_BRANCH
// Docker凭证ID
def dockerCredentialId = "docker-aliyun"
def imageHubServer = "registry.cn-shanghai.aliyuncs.com"
def imageHubProject = "wanfei"
def imageTag = "1.0.0-dev"
// K8S配置凭证ID
def k8sConfigCredentialId = 'k8s-config-ks'
stage('代码编译打包') {
container('maven') {
echo "1. 代码编译打包阶段"
echo "当前commit: ${gitCommit}, 分支: ${gitBranch}"
sh """
ls -la
mvn clean package -Dmaven.test.skip=true
"""
}
}
stage('构建 Docker 镜像') {
container('maven') {
withCredentials([usernamePassword(credentialsId: "${dockerCredentialId}", passwordVariable : 'DOCKER_PASSWORD' ,usernameVariable : 'DOCKER_USERNAME')]) {
echo "2. 构建 Docker 镜像阶段"
sh """
ls -la
echo "$DOCKER_PASSWORD" | docker login "${imageHubServer}" -u "$DOCKER_USERNAME" --password-stdin
sh ./script/deploy/buildImage.sh -v "${imageTag}" -s "${imageHubServer}" -p "${imageHubProject}"
"""
}
}
}
stage('运行 Helm') {
container('helm') {
echo "3. [INFO] 开始 Helm 部署"
// 使用对应K8s配置
withCredentials([
kubeconfigFile(
credentialsId: "${k8sConfigCredentialId}",
variable: 'KUBECONFIG')
]) {
helmDeploy(
dry_run : false,
imagePullSecrets : "",
imageHubServer : "${imageHubServer}",
imageHubProject : "${imageHubProject}",
imageTag : "${imageTag}",
profile : "dev",
namespace : "default",
name : "devops-demo",
chartDir : "./script/deploy/chart/"
)
echo "[INFO] Helm 部署应用成功..."
}
}
}
}
}
2.10 Jenkins
访问 http://192.168.4.27:30180/ ,账号密码admin / P@88w0rd
参考 https://kubesphere.io/zh/docs/v3.3/faq/devops/install-jenkins-plugins/
三. 集成sonar
3.1 helm安装sonar
helm upgrade --install sonarqube sonarqube \
--repo https://charts.kubesphere.io/main \
-n kubesphere-devops-system \
--create-namespace \
--set service.type=NodePort \
--set service.nodePort=32590
repo
地址:https://charts.kubesphere.io/main
- 安装版本:
8.9-community
界面访问 http://192.168.4.27:32590/ 账号密码 admin / admin
,修改密码为www19930327
3.2 创建 SonarQube 管理员令牌 (Token)
点击右上角字母 A,然后从菜单中选择 My Account 以转到 Profile 页面。
点击 Security 并输入令牌名称,例如 kubesphere
。
点击 Generate 并复制此令牌。
c0500471a49371f7fa4053f3b9dc50e091fc3d72
将上面生成的token
保存到Jenkins
凭据中
3.3 创建 Webhook 服务器
执行以下命令获取 SonarQube Webhook 的地址。(就是Jenkins地址)
export NODE_PORT=$(kubectl get --namespace kubesphere-devops-system -o jsonpath="{.spec.ports[0].nodePort}" services devops-jenkins)
export NODE_IP=$(kubectl get nodes --namespace kubesphere-devops-system -o jsonpath="{.items[0].status.addresses[0].address}")
echo http://$NODE_IP:$NODE_PORT/sonarqube-webhook/
预期输出结果:
http://192.168.4.27:30180/sonarqube-webhook/
依次点击 Administration、Configuration 和 Webhooks 创建一个 Webhook。
点击 Create。
在弹出的对话框中输入 Name 和 Jenkins Console URL(即 SonarQube Webhook 地址)。点击 Create 完成操作。
3.4 将 SonarQube 配置添加到 ks-installer
执行以下命令编辑 ks-installer。
kubectl edit cc -n kubesphere-system ks-installer
搜寻至 devops。添加字段 sonarqube 并在其下方指定 externalSonarUrl 和 externalSonarToken。
devops:
enabled: true
jenkinsJavaOpts_MaxRAM: 2g
jenkinsJavaOpts_Xms: 512m
jenkinsJavaOpts_Xmx: 512m
jenkinsMemoryLim: 2Gi
jenkinsMemoryReq: 1500Mi
jenkinsVolumeSize: 8Gi
sonarqube: # Add this field manually.
externalSonarUrl: http://192.168.4.27:32590 # The SonarQube IP address.
externalSonarToken: c0500471a49371f7fa4053f3b9dc50e091fc3d72 # The SonarQube admin token created above.
完成操作后保存此文件。
3.5 将 SonarQube 服务器添加至 Jenkins
3.5.1 配置sonar服务器
登录Jenkins
点击 系统管理 -> 系统配置
搜寻到 SonarQube servers,然后点击 Add SonarQube。
sonar
http://192.168.4.27:32590
sonar-token
点击确定
3.5.2 全局配置SonarQube Scanner
点击 系统管理 -> 全局工具配置
点击保存
3.6 将 sonarqubeURL 添加到 KubeSphere 控制台
您需要指定 sonarqubeURL,以便可以直接从 KubeSphere 控制台访问 SonarQube。
执行以下命令:
kubectl edit cm -n kubesphere-system ks-console-config
搜寻到 data.client.enableKubeConfig,在下方添加 devops 字段并指定 sonarqubeURL。
client:
enableKubeConfig: true
devops: # 手动添加该字段。
sonarqubeURL: http://192.168.4.27:32590 # SonarQube IP 地址。
保存该文件。
3.7 重启服务
kubectl -n kubesphere-devops-system rollout restart deploy devops-apiserver
kubectl -n kubesphere-system rollout restart deploy ks-console
3.8 项目Jenkinsfile
def label = "slave-${UUID.randomUUID().toString()}"
def helmLint(String chartDir) {
println "校验 chart 模板"
sh "helm lint ${chartDir}"
}
def helmDeploy(Map args) {
if (args.dry_run) {
println "Debug 应用 ${args.profile} 环境"
sh "helm upgrade --install --dry-run --debug --install ..."
} else {
println "部署应用 到 ${args.profile} 环境"
sh "helm upgrade --install --set global.pullPolicy=Always --set global.javaOpts='-Xms256m -Xmx1024m -Xss512k -XX:+PrintGC' \
--set global.imagePullSecrets=${args.imagePullSecrets} --set global.imageHub.server=${args.imageHubServer}\
--set global.imageHub.project=${args.imageHubProject} --set global.version=${args.imageTag} \
--set global.profiles=${args.profile} --set global.namespace=${args.namespace} ${args.name} ${args.chartDir}"
echo "应用 ${args.name} 部署成功. 可以使用 helm status ${args.name} 查看应用状态"
}
}
podTemplate(label: label,
containers: [
containerTemplate(name: 'maven', image: 'kubesphere/builder-maven:v3.2.1-jdk11', command: 'cat', ttyEnabled: true),
containerTemplate(name: 'helm', image: 'hypnoglow/kubernetes-helm:3.0.2', command: 'cat', ttyEnabled: true)
],
volumes: [
hostPathVolume(hostPath: '/var/run/docker.sock', mountPath: '/var/run/docker.sock'),
hostPathVolume(hostPath: '/var/data/jenkins_maven_cache', mountPath: '/root/.m2'),
hostPathVolume(mountPath: '/var/data/jenkins_sonar_cache', hostPath: '/root/.sonar/cache')
]) {
node(label) {
// checkout scm 下载代码
def myRepo = checkout scm
def gitCommit = myRepo.GIT_COMMIT
def gitBranch = myRepo.GIT_BRANCH
// Docker凭证ID
def dockerCredentialId = "docker-aliyun"
def imageHubServer = "registry.cn-shanghai.aliyuncs.com"
def imageHubProject = "wanfei"
def imageTag = "1.0.0-dev"
// K8S配置凭证ID
def k8sConfigCredentialId = 'k8s-config-ks'
stage('代码编译打包') {
container('maven') {
echo "1. 代码编译打包阶段"
echo "当前commit: ${gitCommit}, 分支: ${gitBranch}"
sh """
ls -la
mvn clean package -Dmaven.test.skip=true
"""
}
}
stage('代码扫描') {
echo "2. 代码扫描阶段"
// jenkins配置的 sonar-server name
withSonarQubeEnv('sonar') {
def SCANNER_HOME = tool 'sonar-scan'
sh """
${SCANNER_HOME}/bin/sonar-scanner \
-Dsonar.projectKey=devops-demo1 \
-Dsonar.projectName=devops-demo1 \
-Dsonar.projectVersion=1.0 \
-Dsonar.sourceEncoding=UTF-8 \
-Dsonar.language=java \
-Dsonar.sources=src \
-Dsonar.java.binaries=target/classes
"""
}
}
stage('检查结果分析') {
echo "3. 检查结果分析阶段"
timeout(5) {
// 等待sonarqube结果回调过来
def qg = waitForQualityGate()
echo "结果状态: ${qg.status}"
if (qg.status != 'OK') {
error "未通过Sonarqube的代码质量阈检查,请及时修改!failure: ${qg.status}"
}
}
}
stage('构建 Docker 镜像') {
container('maven') {
withCredentials([usernamePassword(credentialsId: "${dockerCredentialId}", passwordVariable : 'DOCKER_PASSWORD' ,usernameVariable : 'DOCKER_USERNAME')]) {
echo "4. 构建 Docker 镜像阶段"
sh """
ls -la
echo "$DOCKER_PASSWORD" | docker login "${imageHubServer}" -u "$DOCKER_USERNAME" --password-stdin
sh ./script/deploy/buildImage.sh -v "${imageTag}" -s "${imageHubServer}" -p "${imageHubProject}"
"""
}
}
}
stage('运行 Helm') {
container('helm') {
echo "5. [INFO] 开始 Helm 部署"
// 使用对应K8s配置
withCredentials([
kubeconfigFile(
credentialsId: "${k8sConfigCredentialId}",
variable: 'KUBECONFIG')
]) {
helmDeploy(
dry_run : false,
imagePullSecrets : "",
imageHubServer : "${imageHubServer}",
imageHubProject : "${imageHubProject}",
imageTag : "${imageTag}",
profile : "dev",
namespace : "default",
name : "devops-demo",
chartDir : "./script/deploy/chart/"
)
echo "[INFO] Helm 部署应用成功..."
}
}
}
}
}
3.9 测试
四. 提交代码自动构建
4.1 查看Webhook 推送 URL
流水线 -> 编辑
复制URL
4.2 gitee添加webhook
添加
因为部署再本地环境,
gitee
无法访问,所以配置下内网穿透测试
# 原地址
http://192.168.4.27:30880/devops_webhook/git/?url=https://gitee.com/www19930327/devops-demo.git
# 内网穿透后
http://frp-tai.wanfei.wang/devops_webhook/git/?url=https://gitee.com/www19930327/devops-demo.git
添加成功
4.3 测试
随便添加一行代码
触发自动构建
代码检查通过
构建成功