通过 skaffold 疾速部署微服务
随着技术的一直倒退,程序员们相熟的传统单体利用开发流程,慢慢地无奈适应当下微服务化的潮流趋势。同时随着云原生开发的理念一直推广,越来越多的服务运行在不可变的基础设施之上,随之而来的是传统单体利用开发流程与云化水平日益加深服务之间的隔膜越发微小,开发人员越来越难以容忍反复繁琐且容易出错的低效率开发流程。因而,一款面向开发人员而运维施行人员的继续构建与继续部署工具
skaffold
应运而生
skaffold 简介
[skaffold]() 是一款 Google
推出的继续构建与继续部署工具,它次要面向开发人员而非运维施行人员,指标是突破本地开发与云化部署之间的隔膜,加重开发人员的心智累赘,帮忙开发人员专一于杰出地实现日常开发工作,防止开发人员在缭乱繁冗的运维流程中过多耗费贵重的精力与工夫。
根本架构
skaffold
的工作流依照开发流程的不同阶段,分为 4 个局部组成:
- 本地开发(文件同步)
- 继续构建
- 继续测试
- 继续部署
以上四个局部均能够依据理论需要进行定制化批改。
本地开发
skaffold
对支流的编程语言以及配套应用的技术栈都有着十分不错的反对,例如 Go
、Java
、JavaScript
等
本地开发的核心内容是 文件同步
,文件同步的监听对象大略能够分为 源代码
和 编译产物
。
skaffold
官网的举荐做法是监听源代码变动,而后自动化把源代码复制到 Docker 容器中进行编译和构建。
这种做法的问题不少,首先是源代码变动十分频繁,而编译和构建过程往往十分耗时,因而主动触发构建不太正当。
其次,在 Docker 容器中编译和构建,须要把握编写 Multi Stage Dockerfile
技能,否则构建进去的镜像大小会占据十分大的空间,另外还要耗费本就不拮据的带宽进行镜像传输。
最初,在 Docker 容器中编译和构建,要解决环境变量,代理设置、缓存构建两头后果等一系列问题,对老手十分不敌对。
因而,集体举荐,在本地开发环节尽量采纳手动触发编译构建,通过监听编译产物的形式来触发热更新等流程。
继续构建
因为抉择手动触发编译,所以本环节的内容次要讲述如何打包镜像的内容
目前 skaffold
官网反对的构建形式有三种:Docker
、Jib(maven/gradle)
、Bazel
- Docker
- Jib(maven/gradle)
- Bazel
这里以最常见 Docker
为例:
build:
local:
push: false # 镜像打包胜利后是否推送到远端的镜像仓库
artifacts: # 反对打包多个不同组件的镜像
- image: datacenter-eureka # 打包后的镜像名称
context: "eureka" # Dockerfile 相对路径,就放在 eureka 目录下
docker:
dockerfile: Dockerfile
- image: datacenter-school # 打包后的镜像名称
context: "school" # Dockerfile 相对路径
docker:
dockerfile: Dockerfile
- image: datacenter-teacher # 打包后的镜像名称
context: "teacher" # Dockerfile 相对路径
docker:
dockerfile: Dockerfile
- image: datacenter-student # 打包后的镜像名称
context: "student" # Dockerfile 相对路径
docker:
dockerfile: Dockerfile
当运行 skaffold dev
时,会依照 编译 —> 构建 -> 测试 -> 部署
的规范流程走一遍。
当监听到指定门路下的文件发生变化时,skaffold 工具会尝试通过相似于 kubectl cp
命令的形式,间接把产生变动后的文件拷贝到运行中的容器外部,防止从新走一遍编译构建 / 上传镜像的步骤,缩小同步代码更改而耗费的工夫。
须要特地留神,这种形式对于反对 代码热更新
的技术栈十分实用,例如 Java
和 Javascript
,但对于 Go
这类不反对 热更新
的技术栈来说成果非常无限,因为即使文件同步实现,仍然重启主过程能力让批改后的性能失效。
接着说 Jib(maven/gradle)
,Jib
也是由谷歌开发的一款专门针对 Java
生态的 CI/CD
工具,跟 skaffold
通用 CI/CD
不同,同时还有 VSCode
和 IDEA
插件,但作者自己并没有用过,所以等当前有机会再开展讲。
至于 Bazel
是微软开发的全平台构建工具,次要反对 C#
语言,甚至连前端相干 Javascript
我的项目也能够应用,但毛病就是十分轻便,这里也不开展讲。
此外,skaffold 还反对 Customize
自定义构建,这个形式的构建更自在可控,比方有些 WSL
环境的用户不违心为了装置 Docker
环境而重复折腾,甚至有些企业外部不容许员工在开发电脑装置虚拟机等等,通过自定义构建流程都能够解决,放到文章最初再具体解说。
继续测试
skaffold
官网的测试计划是把代码拷贝到定制化的测试环境容器中执行测试用例,这种办法十分麻烦,测试相干的内容这里就不开展讲。
感兴趣的读者能够查看 skaffold 官网配置文档
继续部署
skaffold
官网反对的部署形式有很多种,这里以 helm
为例:
deploy:
helm:
releases:
- name: datacenter
chartPath: package
artifactOverrides:
image:
eureka: datacenter-eureka # 镜像名称要跟后面构建环节的镜像名称保持一致,但不能呈现镜像标签
school: datacenter-school # 镜像名称要跟后面构建环节的镜像名称保持一致,但不能呈现镜像标签
teacher: datacenter-teacher # 镜像名称要跟后面构建环节的镜像名称保持一致,但不能呈现镜像标签
student: datacenter-student # 镜像名称要跟后面构建环节的镜像名称保持一致,但不能呈现镜像标签
imageStrategy:
helm: {}
配置参考
残缺的配置文件能够参考:datacenter
上手实际
后期筹备
- skaffold
- helm
点击上述两个组件的链接,下载到本地,再讲二进制退出 PATH
环境变量,具体装置过程不再赘述。
根本开发环境配置
像 JDK
、maven
或 Gradle
这类 Java 开发必备的工具请自行装置,这里就不开展讲了。
初始化 helm chart
在一个空白目录下运行 helm create datacenter
命令,即可疾速创立 chart
包,包的目录构造如下所示:
├── Chart.yaml
├── charts
├── templates
│ ├── NOTES.txt
│ ├── _helpers.tpl
│ ├── deployment.yaml
│ ├── hpa.yaml
│ ├── ingress.yaml
│ ├── service.yaml
│ ├── serviceaccount.yaml
│ └── tests
│ └── test-connection.yaml
└── values.yaml
能够依据本身的理论需要,增删批改包的文件内容,例如这里用不到 hpa.yaml
、serviceaccount.yaml
和 tests/*
,所以都删除了。
而后把 datacenter
重命名为 package
,而后挪动到本来的代码目录下,这是约定成俗的习惯。
部署 MySQL 服务
经典的 Web 利用往往离不开数据库,而在 k8s 上运行数据库,则须要提供长久化存储,否则数据库的容器重启后数据就失落了。
首先,在 package/templates
目录下创立 pv.yaml
文件,而后写入以下内容:
kind: PersistentVolume
apiVersion: v1
metadata:
name: mysql-pv-volume
namespace: spring-cloud
labels:
type: local
spec:
storageClassName: manual
capacity:
storage: 2Gi
accessModes:
- ReadWriteOnce
hostPath:
path: "/opt/data/mysql"
解释:创立长久化卷 PersistentVolume
,简称 PV
,存储门路就用宿主机目录 /opt/data/mysql
而后,在同一个目录下创立 pvc.yaml
文件,而后写入以下内容:
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: mysql-pv-claim
namespace: spring-cloud
spec:
storageClassName: manual
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 2Gi
解释:创立长久卷应用申明 PersistentVolumeClaim
,简称 PVC
,绑定后面创立的 PV
。PVC
的容量是 2G
,必须小或等于 PV
的容量,否则无奈绑定,能够依据理论状况调整容量大小。
为了避免卸载过程中意外删除 PV 卷导致数据失落的状况,helm 不会执行删除 PV 的操作,必须要用户手动执行。
因而如果部署过程呈现 PVC 与 PV 无奈绑定而导致无奈持续的状况,请手动删除再从新 PV 以及 PVC 的形式排除故障
最初,在同一个目录下创立 statefulset.yaml
文件,而后写入以下内容:
apiVersion: v1
kind: Service
metadata:
name: mysql # 同一个命名空间的其余服务能够通过域名“mysql”来拜访 MySQL 服务
namespace: spring-cloud # 通过命名空间来隔离不同的我的项目
spec:
type: ClusterIP
ports:
- name: mysql
protocol: TCP
port: 3306
targetPort: 3306
selector:
app: mysql # 通过定义标签选择器,只转发申请给带有 app: mysql 的 Pod
---
apiVersion: apps/v1
kind: StatefulSet
metadata:
name: mysql
namespace: spring-cloud
spec:
selector:
matchLabels:
app: mysql
strategy:
type: Recreate
template:
metadata:
labels:
app: mysql
spec:
containers:
- image: mysql:5.6
name: mysql
env:
- name: MYSQL_ROOT_PASSWORD
value: bocloud@2019 # 明码属于高度敏感秘密,倡议在生成环境中通过 ServiceAccount 和 ConfigMap 等形式注入
ports:
- containerPort: 3306
name: mysql
volumeMounts:
- name: mysql-persistent-storage
mountPath: /var/lib/mysql
volumes:
- name: mysql-persistent-storage
persistentVolumeClaim:
claimName: mysql-pv-claim # 将后面定义的 pvc 挂载成卷,给容器应用
解释:创立 mysql 的 Service
和 StatefulSet
。因为 mysql 是个数据库,属于 有状态利用
,所以倡议应用 StatefulSet
来治理。
另外因为 k8s
的机制问题,Pod 重启后 IP 地址会扭转,所以 Pod 之间的通信不适宜间接通过拜访 Pod IP 的形式进行,最佳实际是通过创立特定 Service
, 申请方的 Pod 向特定 Service 发送申请,再由特定 Service 转发申请给被申请方的 Pod。
部署微服务
在 package/templates
目录下清空 deployment.yaml
文件,而后写入以下内容:
apiVersion: apps/v1
kind: Deployment
metadata:
name: datacenter-dep
namespace: spring-cloud # 同一个我的项目的命名空间肯定要雷同
labels:
app: datacenter # 自定义标签
spec:
replicas: 1 # 正本数量
selector:
matchLabels:
app: datacenter # 通过统计有多少个带有 app: datacenter 的 Pod 来确定正本的数量
template:
metadata:
labels:
app: datacenter # 给 Pod 打上 app: datacenter 标签,不便统计
spec:
containers:
- name: school
image: {{.Values.image.school.repository}}:{{.Values.image.school.tag}} # 注入真正的镜像
imagePullPolicy: IfNotPresent
env:
- name: MYSQL_ADDRESS
value: mysql:3306
- name: MYSQL_PASSWORD
value: bocloud@2019 # 明码属于高度敏感秘密,不倡议在实在环境应用明文明码,这里仅为展现
ports:
- containerPort: 8084
- name: teacher
image: {{.Values.image.teacher.repository}}:{{.Values.image.teacher.tag}} # 注入真正的镜像
imagePullPolicy: IfNotPresent
env:
- name: MYSQL_ADDRESS
value: mysql:3306
- name: MYSQL_PASSWORD
value: bocloud@2019 # 明码属于高度敏感秘密,不倡议在实在环境应用明文明码,这里仅为展现
ports:
- containerPort: 8082
- name: student
image: {{.Values.image.student.repository}}:{{.Values.image.student.tag}} # 注入真正的镜像
imagePullPolicy: IfNotPresent
env:
- name: MYSQL_ADDRESS
value: mysql:3306
- name: MYSQL_PASSWORD
value: bocloud@2019 # 明码属于高度敏感秘密,不倡议在实在环境应用明文明码,这里仅为展现
ports:
- containerPort: 8083
解释:依据 k8s
的标准要求,应该通过 Deployment
来部署 无状态利用
。
而后,在同一个目录下清空 service.yaml
文件,而后写入以下内容:
apiVersion: v1
kind: Service
metadata:
name: datacenter
namespace: spring-cloud
spec:
type: ClusterIP
selector:
app: datacenter
ports:
- name: school
protocol: TCP
port: 8084
targetPort: 8084
- name: teacher
protocol: TCP
port: 8082
targetPort: 8082
- name: student
protocol: TCP
port: 8083
targetPort: 8083
解释:创立 Service
裸露到集群外部,供集群外部的其余服务调用
最初,批改 package/values.yaml
文件,而后写入以下内容:
image:
school:
repository: datacenter-school
tag: latest
teacher:
repository: datacenter-teacher
tag: latest
student:
repository: datacenter-student
tag: latest
解释:helm 举荐通过 values.yaml
文件对立治理 chart
模板的变量。skaffold
也是通过批改 values.yaml
注入不同的镜像名称,动静更新运行中容器镜像
装置配置 kubectl 和 docker
装置 kubectl 与 k8s 通信
版本:v1.23.0
- windows amd64
- darwin amd64
- linux amd64
点击上述链接,下载到本地,再讲二进制退出 PATH
环境变量,具体装置过程不再赘述。
K8S 配置
个别保留在主节点的 ~/.kube
目录下,将残缺目录复制到本地目录下,关上目录下的 .kube/config
,能够相似的内容如下:
apiVersion: v1
clusters:
- cluster:
certificate-authority-data: "****" # 证书颁发机构的证书
server: https://172.24.86.22:6443 # k8s 的 apiserver 地址
name: kubernetes # k8s 集群的名称
contexts:
- context:
cluster: kubernetes # 上下文的 k8s 集群的名称
user: kubernetes-admin # 上下文的 k8s 凭证的用户名称
name: kubernetes-admin@kubernetes
current-context: kubernetes-admin@kubernetes # 设置以后上下文的所应用的 k8s 集群
kind: Config
preferences: {}
users:
- name: kubernetes-admin # k8s 凭证的用户名称
user:
client-certificate-data: "****" # 用户证书
client-key-data: "****" # 用户密钥
而后设置环境变量 KUBECONFIG
指向本地的 ./kube/config
门路,kubectl
便能够通过凭证与 k8s
的 APIServer
通信。
批改环境变量后,记得运行命令更新环境变量,Windows 平台执行 refreshenv
命令。
装置 docker
用于打包镜像
如果你的本地电脑环境存在 docker 环境,能够跳过 docker 装置配置环节
装置 Docker 客户端
点击这里,
下载到本地,再讲二进制退出 PATH
环境变量,具体装置过程不再赘述。
配置 Docker
假如你的 WSL 环境中存在 Docker
环境,又或者近程 Linux 服务器上存在 Docker
环境,
能够通过批改 Docker
守护过程的配置,将 Docker
过程裸露到内网供其余设施进行应用。
首先,编辑 /etc/systemd/system/multi-user.target.wants/docker.service
文件,将 ExecStart
行改成以下内容:
ExecStart=/usr/bin/dockerd --containerd=/run/containerd/containerd.sock
重点是去掉 fd://
,接着编辑 /etc/docker/daemon.json
文件,重点是 hosts
加上 fd://
和 tcp://0.0.0.0:10086
,
注意事项:降级 docker 后会笼罩以后设置,导致 docker 无奈失常运行,须要参考上述步骤从新设置 docker.service 文件能力失常运行
端口号能够依据理论状况调整
{
"hosts": [
"fd://",
"tcp://0.0.0.0:10086"
],
"registry-mirrors": [
"https://docker.mirrors.ustc.edu.cn/",
"https://dockerhub.azk8s.cn/",
"https://hub-mirror.c.163.com/"
],
"exec-opts": ["native.cgroupdriver=systemd"],
"log-driver": "json-file",
"log-opts": {"max-size": "100m"},
"storage-driver": "overlay2"
}
接口执行以下命令,重启 docker
systemctl daemon-reload
systemctl restart docker
最初,在本地设置环境变量 DOCKER_HOST=<eth0IP>:10086
,把 <eth0IP>
换成近程 Linux 服务器的实在 IP。
因为 WSL 每次重启 eth0 的 IP 会变动,须要从新设置
DOCKER_HOST
变量
在本地命令行界面,执行 docker info
命令查看是否设置胜利。
C:\WINDOWS\system32>docker info
Client:
Context: default
Debug Mode: false
Plugins:
buildx: Docker Buildx (Docker Inc., v0.7.1)
compose: Docker Compose (Docker Inc., v2.2.1)
scan: Docker Scan (Docker Inc., 0.9.0)
Server:
Containers: 0
Running: 0
Paused: 0
Stopped: 0
Images: 30
Server Version: 20.10.12
Storage Driver: overlay2
Backing Filesystem: extfs
Supports d_type: true
Native Overlay Diff: true
userxattr: false
Logging Driver: json-file
Cgroup Driver: systemd
Cgroup Version: 1
Plugins:
Volume: local
Network: bridge host ipvlan macvlan null overlay
Log: awslogs fluentd gcplogs gelf journald json-file local logentries splunk syslog
Swarm: inactive
Runtimes: io.containerd.runc.v2 io.containerd.runtime.v1.linux runc
Default Runtime: runc
Init Binary: docker-init
containerd version: 7b11cfaabd73bb80907dd23182b9347b4245eb5d
runc version: v1.0.2-0-g52b36a2
init version: de40ad0
Security Options:
seccomp
Profile: default
Kernel Version: 5.10.74.3-microsoft-standard-WSL2+
Operating System: Ubuntu 20.04.3 LTS
OSType: linux
Architecture: x86_64
CPUs: 8
Total Memory: 7.239GiB
Name: LAPTOP-MAGICBOOKPRO
ID: EXNQ:FGLE:MROB:C7FG:WJXC:R7YV:HUFB:6A46:4KAW:LG2A:TM3J:SAAB
Docker Root Dir: /var/lib/docker
Debug Mode: false
Registry: https://index.docker.io/v1/
Labels:
Experimental: false
Insecure Registries:
127.0.0.0/8
Registry Mirrors:
https://docker.mirrors.ustc.edu.cn/
https://dockerhub.azk8s.cn/
https://hub-mirror.c.163.com/
Live Restore Enabled: false
填写 skaffold 配置并运行
在我的项目根目录下,创立 skaffold.yaml
文件,填写以下内容
apiVersion: skaffold/v2beta26 # version of the configuration.
kind: Config # always Config.
metadata:
name: datacenter
build:
local:
push: false
artifacts:
- image: datacenter-school # must match in artifactOverrides
context: "school"
docker:
dockerfile: Dockerfile
- image: datacenter-teacher # must match in artifactOverrides
context: "teacher"
docker:
dockerfile: Dockerfile
- image: datacenter-student # must match in artifactOverrides
context: "student"
docker:
dockerfile: Dockerfile
deploy:
helm:
releases:
- name: datacenter
chartPath: package
artifactOverrides:
image:
school: datacenter-school # no tag present!
teacher: datacenter-teacher # no tag present!
student: datacenter-student # no tag present!
imageStrategy:
helm: {}
先执行以下命令创立 spring-cloud
命名空间,k8s 通过命名空间来隔离不同微服务的资源
kubectl create namespace spring-cloud
再执行 skaffold dev
命令,如果后面的步骤和配置都正确,应该能够看到以下输入
C:\Users\huang\Documents\datacenter>skaffold dev
time="2022-02-14T00:13:29+08:00" level=warning msg="failed to detect active kubernetes cluter node platform. Specify the correct build platform in the `skaffold.yaml` file or using the `--platform` flag" subtask=-1 task=DevLoop
Listing files to watch...
- datacenter-eureka
- datacenter-school
- datacenter-teacher
- datacenter-student
Generating tags...
- datacenter-eureka -> datacenter-eureka:13577a5
- datacenter-school -> datacenter-school:13577a5
- datacenter-teacher -> datacenter-teacher:13577a5
- datacenter-student -> datacenter-student:13577a5
Checking cache...
- datacenter-eureka: Found. Tagging
- datacenter-school: Found. Tagging
- datacenter-teacher: Found. Tagging
- datacenter-student: Found. Tagging
Tags used in deployment:
- datacenter-eureka -> datacenter-eureka:769afdbaaf2a35acada2a56cf1d1cccbc8a8ab8196396a8ff9e2803cf6a49490
- datacenter-school -> datacenter-school:b89167e724932d41e40945a39ff04d84e419345957c4c0a022e7c4694153b609
- datacenter-teacher -> datacenter-teacher:9d013f9295b7bd3e75b68b2d8a9df434a77cbc9514df1ae36a967b6841c4328f
- datacenter-student -> datacenter-student:3f5267479ce35cec929485edce5f1dfc2cb1017136bbc90f2a0de5cd4f48f808
Starting deploy...
按 Ctrl+C
即可进行服务,如果 kubernetes
集群中仍旧存在 datacenter
相干的资源,能够通过 helm uninstall datacenter
手动革除。
[可选]应用 Buildah 代替 Docker
对于 WSL1
或者 厌弃在 WSL2
装置 docker
环境太麻烦的 windows
用户,以及不想在本地装置 docker
的 Mac
用户,
能够尝试装置 redhat
开源的 buildah
依照官网教程自行装置即可。
装置完结后运行 buildah image
,若遇到以下谬误:
kernel does not support overlay fs: 'overlay' is not supported over <unknown> at "/home/zaoying/.local/share/containers/storage/overlay": backing file system is unsupported for this graph driver
WARN[0000] failed to shutdown storage: "kernel does not support overlay fs:'overlay'is not supported over <unknown> at \"/home/zaoying/.local/share/containers/storage/overlay\": backing file system is unsupported for this graph driver"
ERRO[0000] exit status 125
只须要装置 fuse-overlayfs
即可:
# for debian/ubuntu
apt install fuse-overlayfs
buildah
基于 fork
模型,不须要 daemon
守护过程,因而不依赖于 systemd
,不须要 root 权限即可运行。
装置完后即可应用,不须要额定的配置。但 skaffold
尚未提供 buildah
官网反对,因而须要自定义构建脚本。
apiVersion: skaffold/v2beta26 # version of the configuration.
kind: Config # always Config.
metadata:
name: datacenter
build:
local:
push: false
artifacts:
- image: datacenter-school # must match in artifactOverrides
context: "school"
custom:
buildCommand: |
buildah bud -t $IMAGE -f .
- image: datacenter-teacher # must match in artifactOverrides
context: "teacher"
custom:
buildCommand: |
buildah bud -t $IMAGE -f .
- image: datacenter-student # must match in artifactOverrides
context: "student"
custom:
buildCommand: |
buildah bud -t $IMAGE -f .
deploy:
helm:
releases:
- name: datacenter
chartPath: package
artifactOverrides:
image:
school: datacenter-school # no tag present!
teacher: datacenter-teacher # no tag present!
student: datacenter-student # no tag present!
imageStrategy:
helm: {}
更多具体的自定义构建器帮忙,请查看官网文档
[可选]代码热更新
代码热更新在日常的开发过程十分实用,能够放慢个性开发与性能验证的效率。
skaffold
能够解析 Dockerfile
,依据 COPY
和 ADD
等指令,主动抉择监听和同步哪些文件。
当批改完代码后,手动执行 mvn clean & mvn package
命令,skaffold
监听 jar 包变动,主动从新打包镜像并替换。
整个过程算不上真正意思上的热更新,次要的起因是 spring boot
通过 jar
包部署,每次只做了很小的改变都须要从新打包镜像,消耗十分多的工夫。
如果改为 exploded war
的形式部署,就能够实现 class
粒度的 热更新
。
间接跳过 mvn package
打包环节,间接将编译的两头产物 .class
字节码文件同步到运行中的容器中,从而在不重启容器的前提下实现代码热更新。
实践上来说,skaffold 的代码热更新性能同时实用于
Java
和Javascript
等技术栈。但限于篇幅,本文仅限于 Java。
首先要革新 pom.xml
配置,把 <package>jar</package>
改成 <package>war</package>
<packaging>war</packaging>
而后加上 spring-boot-starter-tomcat
,scope
改为 provided
,以及减少 start-class
属性,填写全门路的启动类
...
<properties>
...
<start-class>com.springcloud.eureka.SchoolApplication</start-class>
...
</properties>
...
<dependencys>
...
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-tomcat</artifactId>
<scope>provided</scope>
</dependency>
...
</dependencys>
关上启动类 SpringApplication.java
,减少 extends SpringBootServletInitializer
并重载 configure
办法
@SpringBootApplication
@EnableEurekaClient
@EnableFeignClients
public class SchoolApplication extends SpringBootServletInitializer {
@Override
protected SpringApplicationBuilder configure(SpringApplicationBuilder application) {return application.sources(SchoolApplication.class);
}
public static void main(String[] args) {SpringApplication.run(SchoolApplication.class, args);
}
}
接着,批改 Dockerfile
, 如果你不违心在生产环境采纳 war
,这里能够另存为 Dockerfile.dev
FROM tomcat:9.0.62-jre11-temurin-focal
RUN rm -rf /usr/local/tomcat/webapps.dist
# 通过批改 server.xml 的形式批改端口
RUN sed -i 's/redirectPort="8443"//' /usr/local/tomcat/conf/server.xml && sed -i 's/8005/8004/' /usr/local/tomcat/conf/server.xml && sed -i 's/8080/8084/' /usr/local/tomcat/conf/server.xml
COPY target/exploded /usr/local/tomcat/webapps/ROOT
COPY target/classes /usr/local/tomcat/webapps/ROOT/WEB-INF/classes
CMD ["catalina.sh", "run"]
以上操作都是针对单个服务,因而每个服务都要反复一遍上述操作,但以下操作则是针对整体服务。
最初批改 skaffold.yaml
,减少自定义构建脚本
apiVersion: skaffold/v2beta26 # version of the configuration.
kind: Config # always Config.
metadata:
name: datacenter
build:
local:
push: false
artifacts:
- image: datacenter-eureka # must match in artifactOverrides
context: "eureka"
custom:
buildCommand: |
mvn clean package && 7z x target/eureka-0.0.1-SNAPSHOT.war -otarget/exploded && docker build -t %IMAGE% -f Dockerfile.dev %BUILD_CONTEXT%
dependencies:
paths:
- target/classes
- Dockerfile.dev
ignore:
- target/exploded
- image: datacenter-school # must match in artifactOverrides
context: "school"
custom:
buildCommand: |
mvn clean package && 7z x target/school-0.0.1-SNAPSHOT.war -otarget/exploded && docker build -t %IMAGE% -f Dockerfile.dev %BUILD_CONTEXT%
dependencies:
paths:
- target/classes
- Dockerfile.dev
ignore:
- target/exploded
- image: datacenter-teacher # must match in artifactOverrides
context: "teacher"
custom:
buildCommand: |
mvn clean package && 7z x target/teacher-0.0.1-SNAPSHOT.war -otarget/exploded && docker build -t %IMAGE% -f Dockerfile.dev %BUILD_CONTEXT%
dependencies:
paths:
- target/classes
- Dockerfile.dev
ignore:
- target/exploded
- image: datacenter-student # must match in artifactOverrides
context: "student"
custom:
buildCommand: |
mvn clean package && 7z x target/student-0.0.1-SNAPSHOT.war -otarget/exploded && docker build -t %IMAGE% -f Dockerfile.dev %BUILD_CONTEXT%
dependencies:
paths:
- target/classes
- Dockerfile.dev
ignore:
- target/exploded
deploy:
helm:
releases:
- name: datacenter
chartPath: package
artifactOverrides:
image:
eureka: datacenter-eureka # no tag present!
school: datacenter-school # no tag present!
teacher: datacenter-teacher # no tag present!
student: datacenter-student # no tag present!
imageStrategy:
helm: {}
图中所展现的 buildCommand
是在 Windows
平台执行的,如果是 Linux
或 MacOS
,请参考以下命令
# 打包 eureka
mvn clean package && unzip target/eureka-0.0.1-SNAPSHOT.war -o target/exploded && docker build -t $IMAGE -f Dockerfile.dev $BUILD_CONTEXT
# 打包 school
mvn clean package && unzip target/school-0.0.1-SNAPSHOT.war -o target/exploded && docker build -t $IMAGE -f Dockerfile.dev $BUILD_CONTEXT
# 打包 teacher
mvn clean package && unzip target/teacher-0.0.1-SNAPSHOT.war -o target/exploded && docker build -t $IMAGE -f Dockerfile.dev $BUILD_CONTEXT
# 打包 student
mvn clean package && unzip target/student-0.0.1-SNAPSHOT.war -o target/exploded && docker build -t $IMAGE -f Dockerfile.dev $BUILD_CONTEXT
仅第一次运行须要打包 war
再解压的操作,后续可通过 mvn compile
即能够 class
为粒度实现 热更新
总结
本次演示所应用的微服务项目是很多年前笔者为了学习 Spring Cloud
而编写的 Demo
。
时隔多年 Spring Cloud
曾经不再举荐 Eureka
作为服务发现与注册核心。
同时 k8s
自身也反对将 CoreDNS
作为服务发现 / 注册的组件应用。
所以读者不用纠结 Demo
代码中的谬误,因为本文的重点是 skaffold
的配置与应用。