shaowenchenK零SK贰SK壹S
- 已编辑
1. KubeSphere DevOps
工具软件的价值在于,让一件很复杂的事情变得简单。从时间和人力上,显著降低成本,提升效率。
近年来,DevOps 正在以编排引擎为核心快速整合各种工具链,尝试打造更加完整一致的开发体验。KubeSphere Devops 结合 Kubernetes 为此而生。工具原子组合成流水线,更进一步,流水线也可以对外进行输出,提供 API 调用。
这些流水线可以用于替代一些 iPaaS 组件、微服务。只要能用脚本和工具原子实现的都可以考虑。下面以 S2I/B2I 为例进行实践,但边界远不止于此。
2. S2I/B2I 是什么
文档 上是这样介绍的:
Source-to-image (S2I) 是一个直接将源代码构建成镜像的自动化构建工具,它是通过将源代码放入一个负责编译源代码的 构建器镜像(Builder image) 中,自动将编译后的代码打包成 Docker 镜像。
文档漏了一个关键点。S2I 是可以独立 KubeSphere 运行的,它是基于 CRD 实现的,相关仓库可以查看 s2ioperator,在使用上 S2I 与 B2I 一样。
实际上,s2ioperator 只是管理 S2I 的运行数据,真正干活的是 s2irun 。s2irun 是本文需要使用到的功能,也是一个独立工具,通过设置配置文件路径,执行 builder 命令即可完成 S2I/B2I 的构建。
需要说明的是,这里的 kubesphere/s2irun 镜像配置了 CMD 命令,起来之后立马就退出了,没法在 Jenkins 中使用。于是,我仅注释了 Dockerfile 的最后一行 CMD 命令,再次编译推送了镜像 shaowenchen/s2irun:v2.1.1-keep
。你也可以自行编译推送。
3. 创建 Jenkins 流水线
使用 KubeSphere 创建流水线,并将以下 Jenkinsfile 内容贴入其中。
pipeline {
agent {
kubernetes {
label 's2irun'
yaml '''apiVersion: v1
kind: Pod
spec:
containers:
- name: s2irun
image: shaowenchen/s2irun:v2.1.1-keep
tty: true
volumeMounts:
- name: dockersock
mountPath: /var/run/docker.sock
- name: dockerbin
mountPath: /usr/bin/docker
volumes:
- name: dockersock
hostPath:
path: /var/run/docker.sock
- name: dockerbin
hostPath:
path: /usr/bin/docker
'''
defaultContainer 's2irun'
}
}
parameters {
string(name: 'username', defaultValue: '', description: '')
string(name: 'password', defaultValue: ' ', description: '')
string(name: 'builderImage', defaultValue: '', description: '')
string(name: 'tag', defaultValue: '', description: '')
string(name: 'sourceUrl', defaultValue: '', description: '')
string(name: 'revisionId', defaultValue: '', description: '')
}
stages {
stage('s2i') {
steps {
catchError(buildResult: 'SUCCESS', stageResult: 'FAILURE') {
sh '''
mkdir -p /root/data
touch /root/data/config.json
cat > /root/data/config.json <<-EOF
{
"displayName":"For S2I",
"sourceUrl":"$sourceUrl",
"builderImage":"$builderImage",
"tag":"$tag",
"export":true,
"pushAuthentication":{
"username":"$username",
"password":"$password"
},
"revisionId":"$revisionId"
}
EOF
/root/builder -v=4 -logtostderr=true
'''
}
}
}
}
}
其中:
username ,推送镜像账户名
password, 推送镜像账户密码
builderImage,构建的基础镜像,下面是可选列表:
- kubesphere/tomcat85-java11-centos7:v2.1.0
- kubesphere/tomcat85-java8-centos7:v2.1.0
- kubesphere/java-11-centos7:v2.1.0
- kubesphere/java-8-centos7:v2.1.0
- kubesphere/nodejs-8-centos7:v2.1.0
- kubesphere/nodejs-6-centos7:v2.1.0
- kubesphere/nodejs-4-centos7:v2.1.0
- kubesphere/python-36-centos7:v2.1.0
- kubesphere/python-35-centos7:v2.1.0
- kubesphere/python-34-centos7:v2.1.0
- kubesphere/python-27-centos7:v2.1.0
tag,构建的产出镜像,例如 shaowenchen/hello-python:latest
sourceUrl,仓库地址,密码可以拼在 url 中,类似 http://username:password@gitlab.com
revisionId,仓库分支
可以点击执行看看效果:
4. 开启 KubeSphere ApiGateway 访问
相关文档可以参考,如何调用 API ,非常详细,这里就不粘贴复制了。
假设这里的访问方式是 NodePort: 30881 ,访问 Token 是 eyJhbGciOiJxxx 。
5. API 调用
Pipeline 相关的 API 文档:Pipeline
这里使用 Postman 进行测试,运行 Pipeline。获取运行日志的接口是 GetRunLog ,获取运行状态的接口是 SearchPipelineRuns ,这里就不一一演示。
调用 API 之前需要进入 Jenkins 的管理页面,关闭 CSRF 校验:
去掉上图所示的勾选即可。
- 设置 Token
- 设置参数,按照文档,输入 Jenkins 的参数
- 调用 API
- 页面查看运行状态
- 检查是否推送成功
附1:适用于 2.1
关闭 Jenkins 的 CSRF 会带来安全风险,下面是一段 Python 脚本,可以用于脚本触发流水线
# -*- coding: utf-8 -*-
import json
import requests
user = "admin"
pwd = "P@88w0rd"
# 需要提前放开 APIGW 的端口
host = "http://{APIGW_HOST}:{APIGW_PORT}"
devops_name = "project-W4zNlwJLzgRB"
pipeline_name = "1"
# 参数选填,如果不填将使用默认值
parameters = json.dumps({"parameters": [{
"name": "Value1",
"value": "ccc"}, {
"name": "Value2",
"value": "dddd"}]})
pipeline_uri = "/kapis/devops.kubesphere.io/v1alpha2/devops/" \
+ devops_name + "/pipelines/" + pipeline_name + "/runs"
crumbissuer_uri = "/kapis/devops.kubesphere.io/v1alpha2/crumbissuer"
login_uri = "/kapis/iam.kubesphere.io/v1alpha2/login"
try:
login_data = requests.post(host + login_uri, headers={
"content-type": "application/json"}, json={
"username": user,
"password": pwd})
token = login_data.json()["access_token"]
crumb_data = requests.get(host + crumbissuer_uri, headers={
"Authorization": "Bearer " + token})
# 如果不带参数可以去掉 data 部分
data = requests.post(host + pipeline_uri, headers={
"content-type": "application/json",
"Authorization": "Bearer " + token,
'Jenkins-Crumb': crumb_data.json()['crumb']},
data=parameters)
if str(data.status_code) == "200":
print("Jenkins job is triggered")
else:
print("Failed to trigger the Jenkins job")
except Exception as e:
print("Exception: " + str(e))
附件2,适用于 3.0
# -*- coding: utf-8 -*-
import json
import requests
user = "admin"
pwd = "P@88w0rd"
# 需要提前放开 ks-apiserver 的端口
host = "http://{{API_HOST}}:30980"
devops_name = "demoz2ts7"
pipeline_name = "hello"
# 参数选填,如果不填将使用默认值
parameters = json.dumps({"parameters": [{
"name": "Value1",
"value": "ccc"}, {
"name": "Value2",
"value": "dddd"}]})
pipeline_uri = "/kapis/devops.kubesphere.io/v1alpha2/devops/" \
+ devops_name + "/pipelines/" + pipeline_name + "/runs"
crumbissuer_uri = "/kapis/devops.kubesphere.io/v1alpha2/crumbissuer"
login_uri = "/oauth/token"
def run(i):
try:
login_data = requests.post(host + login_uri, headers={
"Content-Type": "application/x-www-form-urlencoded"}, data={
"grant_type": "password",
"username": user,
"password": pwd
})
token = login_data.json()["access_token"]
crumb_data = requests.get(host + crumbissuer_uri, headers={
"Authorization": "Bearer " + token})
# 如果不带参数可以去掉 data 部分
print(crumb_data)
data = requests.post(host + pipeline_uri, headers={
"content-type": "application/json",
"Authorization": "Bearer " + token,
'Jenkins-Crumb': crumb_data.json()['crumb']},
data=parameters)
if str(data.status_code) == "200":
print(str(i) + "----Jenkins job is triggered")
else:
print("Failed to trigger the Jenkins job")
except Exception as e:
print("Exception: " + str(e))
if __name__ == "__main__":
for i in range(2):
run(i)
refer to https://www.chenshaowen.com/