通过此篇文章你讲会学会什么
- 创建一个基本的Spring Boot应用
- 为Spring Boot应用构建一个Docker镜像
-
自动提交镜像到镜像仓库(下一篇) - 在Kubernetes上创建一个Deployment和Service
- 在Kubernetes上部署Spring Boot应用
-
额外的Kubernetes配置和服务发现(下一篇)
环境准备
- 了解Spring和Kubernetes基本的知识
- JDK 8 或者更高的版本
- 安装Docker Desktop
- 安装一个IDE, 推荐 IntelliJ
现阶段Docker Desktop 对Kubernetes有良好的支持,可以开箱即用,搭建本地Kubernetes集群. 参考官方文档安装Docker Desktop
创建一个Spring Boot 应用
- 下载一个基本的Spring Boot应用, 或者在 start.spring.io 创建
- 解压下载的zip文件,并使用IDE打开项目
添加一个RestController
修改 K8sDemoApplication.java 添加 @RestController , 添加一个@GetMapping
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
@SpringBootApplication
@RestController
public class K8sDemoAppApplication {
public static void main(String[] args) {
SpringApplication.run(K8sDemoAppApplication.class, args);
}
@GetMapping("/")
public String hello() {
return "Hello World";
}
}
运行Spring Boot应用
在命令行输入
./mvnw clean package && java -jar ./target/*.jar
测试Spring Boot应用
访问一个HTTP请求 http://localhost:8080
$curl http://localhost:8080
Hello World
测试Spring Boot Actuator Endpoint
在Spring Boot应用添加了Actuator包之后, Spring会提供一些Production ready Features
$ curl localhost:8080/actuator; echo
{
"_links": {
"self": {
"href": "http://localhost:8080/actuator",
"templated": false
},
"health": {
"href": "http://localhost:8080/actuator/health",
"templated": false
},
"info": {
"href": "http://localhost:8080/actuator/info",
"templated": false
}
}
继续下面的步骤前先确保停止之前启动的Spring Boot应用, 否则可能会导致端口冲突因为端口8080被占用
容器化应用
在Kubernetes上运行该应用程序的第一步是为该应用生成一个镜像,然后将其部署到Kubernetes
构建一个Docker容器
Spring Boot 2.3.x 支持直接构建一个Docker容器无需任何额外的配置文件或者插件
-
使用命令构建Docker容器
$ ./mvnw spring-boot:build-image
运行 docker images 查看构建的Docker容器
docker images | grep k8s-demo-app
k8s-demo-app 0.0.1-SNAPSHOT c7f56cf022f7 40 years ago 224MB
使用Docker命令运行Docker容器
$ docker run --name k8s-demo-app -p 8080:8080 k8s-demo-app:0.0.1-SNAPSHOT
测试在Docker运行中的Spring Boot应用
$ curl http://localhost:8080
Hello World
继续下面的步骤前先确保停止在Docker运行的应用
部署到Kubernetes
我们现在可以在本地Kubernetes集群上运行打包好的应用. 如果需要在非本地Kubernetes集群运行的话,需要推送镜像到镜像仓库,此处先略过推送到镜像仓库的步骤,下一篇会讲。
Deployment 描述文件
Deployment 官方概念的概述
- Kubernetes 使用yaml文件提供了一种方法来描述如何将应用部署到集群
- 你可以使用Kubernetes文档作为参考如何编写这些文件
- 或者你可以使用kubectel来生成一个Deployment文件
- 使用—dry-run 标记运行我们生成文件而且不会真正的运行kubectl命令
mkdir k8s
kubectl create deployment k8s-demo-app --image k8s-demo-app:0.0.1-SNAPSHOT -o yaml --dry-run > k8s/deployment.yaml
生成的deployment.yaml文件如下
apiVersion: apps/v1
kind: Deployment
metadata:
creationTimestamp: null
labels:
app: k8s-demo-app
name: k8s-demo-app
spec:
replicas: 1
selector:
matchLabels:
app: k8s-demo-app
strategy: {}
template:
metadata:
creationTimestamp: null
labels:
app: k8s-demo-app
spec:
containers:
- image: k8s-demo-app:0.0.1-SNAPSHOT
name: k8s-demo-app
imagePullPolicy: IfNotPresent
resources: {}
status: {}
注意需要在deployment.yaml 文件需要添加一个imagePullPolicy: IfNotPresent,因为我们还没有将镜像推送到镜像仓库中,因此需要使用本地镜像
Service 描述文件
- 将运行在一组Pod上的应用程序公开为网络服务的抽象方法。
$ kubectl create service clusterip k8s-demo-app --tcp 80:8080 -o yaml --dry-run > k8s/service.yaml
生成的service.yaml文件如下
apiVersion: v1
kind: Service
metadata:
creationTimestamp: null
labels:
app: k8s-demo-app
name: k8s-demo-app
spec:
ports:
- name: 80-8080
port: 80
protocol: TCP
targetPort: 8080
selector:
app: k8s-demo-app
type: ClusterIP
status:
loadBalancer: {}
部署 Deployment 和 Service YAML
- Deployment 和Service 通过命令创建在k8s文件夹里面
- 运行它们
$kubectl apply -f ./k8s
deployment.apps/k8s-demo-app created
service/k8s-demo-app created
$kubectl get all
NAME READY STATUS RESTARTS AGE
pod/k8s-demo-app-56bb6b8ddf-2w9ct 1/1 Running 0 3s
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
service/k8s-demo-app ClusterIP 10.109.188.161 <none> 80/TCP 3s
NAME READY UP-TO-DATE AVAILABLE AGE
deployment.apps/k8s-demo-app 1/1 1 1 3s
NAME DESIRED CURRENT READY AGE
replicaset.apps/k8s-demo-app-56bb6b8ddf 1 1 1 3s
测试运行在Kubernetes上的应用
- Service 的类型是 ClusterIP, 这意味着只有集群内部才可以访问
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
service/k8s-demo-app ClusterIP 10.109.188.161 <none> 80/TCP 3s
- 可以使用 kubectl pord-forward 命令来访问 Service
kubectl port-forward service/k8s-demo-app 8080:80
- 现在你可以访问 http://localhost:8080 而且会转发到集群中的应用中去
$ curl http://localhost:8080
Hello World
Congrats you have deployed your first app to Kubernetes 🎉
继续下面的步骤前先确保停止在Docker运行的应用, 使用命令 docker rm -f k8s-demo-app
公开应用服务
NOTE: LoadBalancer 类型的 Service 是基于特定平台的, 更改为此类型后,应用的可见性很大程度上取决于其部署位置(Google Cloud Platform 等),因此在本地测试我们可以使用NodePort 类型来暴露服务
修改service.yaml 里面type为NotePort,且添加nodePort参数,注意nodePort范围为(30000-32767)
apiVersion: v1
kind: Service
metadata:
creationTimestamp: null
labels:
app: k8s-demo-app
name: k8s-demo-app
spec:
ports:
- name: 80-8080
port: 80
protocol: TCP
targetPort: 8080
nodePort: 30081
selector:
app: k8s-demo-app
type: NodePort
status:
loadBalancer: {}
- 更新文件后,使用命令使其生效
kubectl apply -f ./k8s
测试公开的服务
现在我们可以通过 http://{任何集群节点的IP}:{NodePort} 的方式来访问
$ kubectl get service k8s-demo-app -w
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
k8s-demo-app NodePort 10.109.188.161 <none> 80:30080/TCP 7m41s
curl http://localhost:30080
hello World
恭喜, 你已经将你的Spring Boot 应用成功部署到Kubernetes!