前言
首先介绍一下原理:原理很简单,即将configmap配置成卷,文件名为application.properties,挂载至容器中springboot可读取的路径上,springboot应用在启动时读取application.properties的内容 。
之前本机环境一直在使用Rancher Desktop提供的k3s集群环境。k3s是k8s的瘦身版,其完全实现了 Kubernetes API,但剔除了很多不必要的驱动程序,转而使用附加组件对其进行替换,这样使得k3s只需要极少的资源就可以运行,所以k3s通常更适用于一些边缘计算和物联网场景,或其它一些非核心集群的场景,如开发测试等。
由于Rancher Desktop了解的人不多,大多数人还是偏向使用minikube来部署开发测试环境,所以我也安装一套minikube环境。MiniKube可以部署成VM,container或bare-metal,不同OS提供的不同类型driver支持。具体可以查看官方说明:minikube.sigs.k8s.io/docs/driver… 如果基于docker部署成container的话,需要每次都开启Rancher Desktop,或者重新安装一个docker,这样会和rancher desktop的docker冲突,故选择基于Windows Hyper-V虚拟机安装minikube。
本文源代码:github.com/tzjavadmg/j…
基于Windows Hyper-V安装minikube
官方参考文档
管理员身份打开 powershell
Enable-WindowsOptionalFeature -Online -FeatureName Microsoft-Hyper-V -All
启动minikube,首次启动时间会比较长,因为要下载相关镜像文件。中途如果停顿时间过长,可以终止进程后运行minikube stop命令,再重新开始。
minikube start --vm-driver=hyperv --image-mirror-country=cn
当看到以下输出时,表示minikube启动成功
- Done! kubectl is now configured to use "minikube" cluster and "default" namespace by default
查看上下文环境信息,现在我有两个context了,一个是minikube,一个是之前使用的rancher-desktop. 默认环境是minikube,此时使用kubectl命令操作的都是minikube集群。
PS C:\WINDOWS\system32> kubectl config get-contexts
CURRENT NAME CLUSTER AUTHINFO NAMESPACE
* minikube minikube minikube default
rancher-desktop rancher-desktop rancher-desktop
如果希望管理rancher-desktop集群,将应用部署至rancher-desktop,则可以使用如下命令切换context
PS C:\WINDOWS\system32> kubectl config use-context rancher-desktop
Switched to context "rancher-desktop".
PS C:\WINDOWS\system32> kubectl config get-contexts
I1102 20:03:35.321147 16964 versioner.go:56] Remote kubernetes server unreachable
CURRENT NAME CLUSTER AUTHINFO NAMESPACE
minikube minikube minikube default
* rancher-desktop rancher-desktop rancher-desktop
创建Spring boot工程
下面创建一个spring boot 工程custom-resource,工程如下图所示:
工程使用自定义的Dockerfile和yaml资源描述文件。在CustomResourceController中将演示从configmap读取配置项数据。代码如下:
@RestController
public class CustomResourceController {
@Value("${welcome:no config}")
private String welcome;
@Value("${name:no config}")
private String name;
@RequestMapping("/")
public String index() {
return name + " " + welcome;
}
}
配置Maven连接minikube docker
由于minikube部署的k8s集群中的docker容器位于Hyper-V虚拟机中,避免构建镜像还需要上传仓库的麻烦,直接配置Maven使用minikube的docker环境构建应用程序的镜像。
首先用minikube docker-env命令查看minikube的docker环境。
PS C:\WINDOWS\system32> minikube docker-env
$Env:DOCKER_TLS_VERIFY = "1"
$Env:DOCKER_HOST = "tcp://172.19.27.78:2376"
$Env:DOCKER_CERT_PATH = "C:\Users\Lenovo\.minikube\certs"
$Env:MINIKUBE_ACTIVE_DOCKERD = "minikube"
# To point your shell to minikube's docker-daemon, run:
# & minikube -p minikube docker-env --shell powershell | Invoke-Expression
根据输出的环境信息,修改maven配置如下:
<properties>
<jkube.docker.host>tcp://172.19.27.78:2376</jkube.docker.host>
<jkube.docker.certPath>C:\Users\Lenovo.minikube\certs</jkube.docker.certPath>
</properties>
这样就可以直接使用maven命令来构建docker镜像至minikube环境。
构建Docker镜像
编写Dockerfile文件,存放于工程根目录下(也可以放于src/main/docker目录,或者在pom里配置成其它目录)。
FROM maven:3.8.3-openjdk-17
EXPOSE 8080/tcp
COPY maven/target/*.jar /opt/app.jar
WORKDIR /opt
ENTRYPOINT [ "java", "-jar", "/opt/app.jar" ]
执行maven命令构建docker镜像
mvn package k8s:build
[INFO] --- kubernetes-maven-plugin:1.9.1:build (default-cli) @ docker-file ---
[INFO] k8s: Building Docker image in Kubernetes mode
[INFO] k8s: Using Dockerfile: D:\i-workspace\jkube-examples\docker-file\Dockerfile
[INFO] k8s: Using Docker Context Directory: D:\i-workspace\jkube-examples\docker-file
[INFO] k8s: [jkube-examples/docker-file:latest]: Created docker-build.tar in 1 second
[INFO] k8s: [jkube-examples/docker-file:latest]: Built image sha256:49570
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
使用minikube image list命令查看镜像
PS C:\WINDOWS\system32> minikube image list --format table
|-----------------------------------------------------------------------------|------------------|---------------|--------|
| Image | Tag | Image ID | Size |
|-----------------------------------------------------------------------------|------------------|---------------|--------|
| registry.cn-hangzhou.aliyuncs.com/google_containers/kube-scheduler | v1.25.2 | ca0ea1ee3cfd3 | 50.6MB |
| registry.cn-hangzhou.aliyuncs.com/google_containers/kube-proxy | v1.25.2 | 1c7d8c51823b5 | 61.7MB |
| registry.cn-hangzhou.aliyuncs.com/google_containers/pause | 3.8 | 4873874c08efc | 711kB |
| registry.cn-hangzhou.aliyuncs.com/google_containers/etcd | 3.5.4-0 | a8a176a5d5d69 | 300MB |
| registry.cn-hangzhou.aliyuncs.com/google_containers/coredns | v1.9.3 | 5185b96f0becf | 48.8MB |
| registry.cn-hangzhou.aliyuncs.com/google_containers/storage-provisioner | v5 | 6e38f40d628db | 31.5MB |
| docker.io/jkube-examples/docker-file | latest | 495705464559c | 805MB |
| docker.io/jkube-examples/custom-resource | latest | 0649d5f3d8b1d | 805MB |
| registry.cn-hangzhou.aliyuncs.com/google_containers/kube-apiserver | v1.25.2 | 97801f8394908 | 128MB |
| registry.cn-hangzhou.aliyuncs.com/google_containers/kube-controller-manager | v1.25.2 | dbfceb93c69b6 | 117MB |
| docker.io/library/maven | 3.8.3-openjdk-17 | 0b9ddcb8259ea | 785MB |
| k8s.gcr.io/pause | 3.6 | 6270bb605e12e | 683kB |
|-----------------------------------------------------------------------------|------------------|---------------|--------|
如上所示,docker.io/jkube-examples/custom-resource 即为刚才构建的docker 镜像
部署spring boot应用至minikube k8s集群
编写k8s配置文件
service.yml
metadata:
annotations:
api.service.kubernetes.io/path: /
spec:
type: NodePort
ports:
- name: http
port: 8080
nodePort: 30000
使用NodePort Type直接暴露30000端口访问服务。
configmap.yml
metadata:
name: ${project.artifactId}
data:
application.properties: |
# spring application properties file
welcome = Hello from Kubernetes ConfigMap!!!
name = codyzeng
deplyment.yml
spec:
replicas: 1
template:
spec:
volumes:
- name: config
configMap:
name: ${project.artifactId}
items:
- key: application.properties
path: application.properties
containers:
- volumeMounts:
- name: config
mountPath: /opt/config
env:
- name: MY_POD_NAMESPACE
valueFrom:
fieldRef:
apiVersion: v1
fieldPath: metadata.namespace
serviceAccount: codyzeng
配置一个名为config的卷,引用configMap,然后将其挂载至容器的/opt/config目录下。 为什么挂载至此目录下?看Dockerfile,应用程序启动的工作目录是/opt,springboot应用读取的配置文件可以存放在工作目录根目录,也可以存放在工作目录的config目录下。config目录比根目录优先级更高。
这里注意工作目录是指运行java命令的当前目录,并不是指应用程序Jar包存放的目录。
运行mvn clean k8s:resource k8s:apply 目录部署应用至k8s
PS D:\i-workspace\jkube-examples\custom-resource> mvn clean k8s:resource k8s:apply
[INFO] Scanning for projects...
[INFO]
[INFO] --------------------< com.codyzeng:custom-resource >--------------------
[INFO] Building custom-resource 1.0-SNAPSHOT
[INFO] --------------------------------[ jar ]---------------------------------
[INFO]
[INFO] --- maven-clean-plugin:3.2.0:clean (default-clean) @ custom-resource ---
[INFO] Deleting D:\i-workspace\jkube-examples\custom-resource\target
[INFO]
[INFO] --- kubernetes-maven-plugin:1.9.1:resource (default-cli) @ custom-resource ---
[INFO] k8s: Using Dockerfile: D:\i-workspace\jkube-examples\custom-resource\Dockerfile
[INFO] k8s: Using Docker Context Directory: D:\i-workspace\jkube-examples\custom-resource
[INFO] k8s: Using resource templates from D:\i-workspace\jkube-examples\custom-resource\src\main\jkube
[INFO] k8s: jkube-healthcheck-spring-boot: Adding readiness probe on port 8080, path='/actuator/health', scheme='HTTP', with initial delay 10 seconds
[INFO] k8s: jkube-healthcheck-spring-boot: Adding liveness probe on port 8080, path='/actuator/health', scheme='HTTP', with initial delay 180 seconds
[INFO] k8s: jkube-service-discovery: Using first mentioned service port '8080'
[INFO] k8s: jkube-revision-history: Adding revision history limit to 2
[INFO] k8s: Updated ConfigMap: custom-resource\target\jkube\applyJson\default\configmap-custom-resource.json
[INFO] k8s: Updating Deployment from kubernetes.yml
[INFO] k8s: Updated Deployment: custom-resource\target\jkube\applyJson\default\deployment-custom-resource.json
[INFO] k8s: HINT: Use the command `kubectl get pods -w` to watch your pods start up
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
使用minikube dashboard查看集群和部署信息
运行minikube dashboard命令,会自动打开dashboard界面。
PS C:\WINDOWS\system32> minikube dashboard
* 正在开启 dashboard ...
- Using image docker.io/kubernetesui/dashboard:v2.7.0
- Using image docker.io/kubernetesui/metrics-scraper:v1.0.8
* 正在验证 dashboard 运行情况 ...
* Launching proxy ...
* 正在验证 proxy 运行状况 ...
* Opening http://127.0.0.1:3984/api/v1/namespaces/kubernetes-dashboard/services/http:kubernetes-dashboard:/proxy/ in your default browser...
面板首页即可看到刚才部署的Deployments:custom-resource
从【配置和存储】-【Config Maps】菜单下可以查看config map配置,如下图:
点进去查看详细信息:
从【工作负载】-【Pods】菜单可以查看Pod卷挂载配置,如下图
也可以进入容器使用命令行查看文件是否已经正确挂载
浏览器展示最终效果
通过虚拟主机IP:30000端口访问结果如下: