minimal CI/CD 工具 skaffold
minimal CI/CD 工具 skaffold
阅读时长:30min
背景
项目上使用了很多的ops工具,但是每一个ops的工具又只使用了一部分的功能。其中Jenkins用来构建我们的pipeline主体框架,打包镜像是采用的skaffold中jib模式,镜像的推送采用的是jenkinsX,部署又是使用的helm+argocd。工具太多,看得人天花乱醉的。让人觉得这个项目很高大上哈哈哈。然后我们不想让这个项目在我们看起来很高大上,所以我们准备一个一个的把这些ops工具来变low(熟悉)。在这篇文章中,我会给大家讲讲如何使用skaffold, 因为skaffold的作用远不止只有打包镜像。除了项目中用到的这一个功能,skaffold还能当做一个小型的pipeline。囊括了镜像构建,测试以及部署。Skaffold是什么?
Skaffold是一个可以让kubernetes本地应用程序的持续开发更容易的命令行工具,换句话来说Skaffold能够用很便捷的方式在本地k8s集群中很快部署的一类工具。
* 利用dockerfile,jib(Maven&Gradle)等工具打包镜像以及推送镜像
* 与kubectl或者helm chart集成,在本地k8s集群中部署docker镜像
* 利用container-structure-test或者test command测试镜像或者代码
* 热更新服务
* 端口暴露- Skaffold的主要workflow包括代码变动的检查,代码镜像的构建,镜像的测试,镜像的推送以及镜像的部署。是一个可以实现一个最小单元的minimal pipeline,如摘自官网的【图一】所示。
- Skaffold是一个基于golang开发的cobra.Command library的CLI应用工具。使用brew install skaffold安装好之后,skaffold的可执行文件被移动到了系统的 /usr/local/bin目录下。
【图一】
怎么用?
上面说了这么多的skaffold的介绍,那么这个工具具体怎么用?本文将以java webflux application来作为我们的demo。- Prerequisite
- 统一用Homebrew的工具
- Java 1.8
brew install java
- Maven
brew install maven
- Skaffold
brew install skaffold
- Minikube
brew install minikube
- Docker
brew install docker
- Java 1.8
- kubectl
curl -LO https://storage.googleapis.com/kubernetes-release/release/v1.7.0/bin/darwin/amd64/kubectl
chmod +x ./kubectl
sudo mv ./kubectl /usr/local/bin/kubectl
- Jib (在pom文件中插入一个plugin section)
- 统一用Homebrew的工具
- workflow
Skaffold初始化
- 在当前项目的目录下执行Skaffold init,skaffold会根据项目构建工具来进行打包。因为在pom文件中指定了jib打包,如【图二】所示。当skaffold检测到项目中使用的jib 插件打包项目镜像时,将会出现如【图三】所示的提示。
【图二】
【图三】
- Tips:
如果使用skaffold的init命令来初始化manifest,默认会初始化使用kubectl的方式来部署镜像。所以会出现如【图四】所示的错误。处理方式很简单,在当前目录下添加上k8s manifest(最简单就是一个pods.yaml文件,如果需要配置更多,加上对应的deployment,
如果对于k8s manifest没有什么特殊的要求(只需要让当前项目能够在本地的k8s cluster中run起来)
- 生成k8s manifest
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23kubectl create deployment my-app --image=my-image --dry-run -o yaml > deployment.yaml
```
* 在run skaffold init生成对应的skaffold
service)即可。

<p style="text-align:center" > 【图四】 </p>
* 构建镜像
* 运行命令<font style="font-family:courier;" size="4">***skaffold build***</font>
* skaffold提供给了多种打包方式,包括Dockerfile,jib maven&gradle,buildpacks,Bazel,Ko,custom script。
* 当前demo中使用了jib maven的方式打包,只需要在skaffold中指定build的方式如下所示的配置:
```yaml
build:
artifacts:
- image: skaffold-webflux-example
jib:
args:
- -Psync
sync:
auto: true
local: {}
- 生成k8s manifest
- 在运行docker images查看镜像是否,打包成功,如【图五】所示:
【图五】
- 在当前项目的目录下执行Skaffold init,skaffold会根据项目构建工具来进行打包。因为在pom文件中指定了jib打包,如【图二】所示。当skaffold检测到项目中使用的jib 插件打包项目镜像时,将会出现如【图三】所示的提示。
测试镜像
- 当镜像构建成功之后,运行skaffold test –images skaffold-webflux-example测试镜像是否打包成功,以及使用shell脚本运行unit test或者其他测试内容。
- 测试的种类
- structureTests(镜像的结构测试,如command测试,fileExist测试,fileContent测试)
- Custom (指定测试脚本)
部署镜像
- 部署方式的支持
- Kubectl * (在demo中采用kubectl apply的方式来部署镜像)
运行命令Skaffold deploy,并在skaffold.yaml中加入如下的配置:
1
2
3
4deploy:
kubectl:
manifests:
- k8s-web.yaml使用kubectl get pods,查看节点是否部署成功,如【图六】所示:
使用kubectl port-forward 【pods name】 8080:8080, 运行
curl --get http://localhost:8080/hello
,查看服务是否能够成功被访问。(部署之后,k8s中的服务的端口并没有被暴露,所以需要操作一下端口映射)。
- Helm
- Kustomize
- Docker
- Kubectl * (在demo中采用kubectl apply的方式来部署镜像)
- 部署方式的支持
其他功能
- Clean up(清除部署)
- ctrl+C
- Skaffold delete
- Tagpolicy(镜像版本号)
- Git commit的索引号
- Sha256编码
- 环境变量
- 时间戳
- Port forward (端口映射)
1
2
3
4
5
6portForward:
- resourceType: deployment
resourceName: skaffold-webflux-example-web
namespace: default
port: 8080
localPort: 8080 - File sync(热部署)
- auto,仅适用于jib,bulidpack的打包模式,加入一下配置
1
2
3jib:
args:
- -Psync - infer
- manual
- auto,仅适用于jib,bulidpack的打包模式,加入一下配置
- Clean up(清除部署)
完整skaffold yaml manifest
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36apiVersion: skaffold/v2beta26
kind: Config
metadata:
name: rxjavademo
build:
tagPolicy:
envTemplate:
template: "{{.FOO}}"
artifacts:
- image: skaffold-webflux-example
jib:
args:
- -Psync
sync:
auto: true
local: {}
deploy:
kubectl:
manifests:
- k8s-web.yaml
test:
- image: skaffold-webflux-example
structureTests:
- './structure-test/*'
custom:
- command: ./scripts/test.sh
timeoutSeconds: 60
portForward:
- resourceType: deployment
resourceName: skaffold-webflux-example-web
namespace: default
port: 8080
localPort: 8080
- Prerequisite
坑!!!
这个是做这个分享中最坑的一个部分!!!根据文档中的介绍,如果是使用jib模式的话,可以采用
auto aync
的方式。设置之后,并不生效,反而会报错,WARN[0044] Skipping deploy due to sync error: copying files: didn't sync any files
在git上遇见相同的问题
Skipping deploy due to sync error: copying files: didn’t sync any files #4246当时我使用的版本是1.35.0,然后我升级到了最新的版本
brew ungrade skaffold
,然后deploy镜像,满心欢喜的想着,改变代码,能够热部署。文件确实被显示生效了,但是,application的内容并没有更新。如下所示:
没生效之前采用的部署模式是skaffold+helm的模式(为啥没有生效得继续读读源码了23333),我换了一种模式,采用了skaffold+kubectl的部署模式。首先在项目的pom文件中添加一个id为sync的Profiles,该依赖的作用是,只要类路径上的文件发生变化,使用spring-boot-devtools的应用程序就会自动重启,如下所示:
1
2
3
4
5
6
7
8
9
10
11
12<profiles>
<profile>
<id>sync</id>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
<optional>true</optional>
</dependency>
</dependencies>
</profile>
</profiles>然后在skaffold.yaml的build的section中加了以下的内容,这样可以为maven传递参数,从而激活profile,让application重新启动
1
2
3jib:
args:
- -Psync终于成功了!!!!
应用场景
- 作为pipeline中的镜像打包和上传工具
- 本地镜像构建工具
- Minimal pipeline
- Demo showcase
总结
- Pros
- Skaffold可以让本地的k8s部署变得更简单,只需要配置好对应的manifest
- 功能可以拆分使用,比较灵活
- Skaffold配置内容比较简单
- Open-source 工具,有社区力量支持
- Cons
- 如果要了解更多的内容可能需要一定的学习成本,包括golang的基础,k8s的部署基础。
- Pros
- 感谢大家看到最后,如果不正确的地方,不吝赐教
- Title: minimal CI/CD 工具 skaffold
- Author: Xiao Qiang
- Created at : 2023-03-05 14:57:57
- Updated at : 2025-03-08 10:49:30
- Link: http://fdslk.github.io/tech/ops/CD/2023/03/05/ops-skaffold/
- License: This work is licensed under CC BY-NC-SA 4.0.