目标
本文我们将以SpringBoot构建一个简单的服务,然后编写 Dockerfile 构建镜像之后,部署到 k8s 中。
构建服务镜像
你可以用任何语言构建一个 web 服务,本文中就简单以 SpringBoot 为例,基于:
JDK版本:21
SpringBoot版本:3.5.5
项目构建方式:maven
可以使用 https://start.spring.io/ 快速创建一个项目,然后编写如下的测试接口,启动后访问 http://localhost:8080/service-a/hello 即可获得输出。
@RestController
@RequestMapping("/service-a")
public class HelloController {
@Value("${spring.application.name}")
private String serviceName;
@GetMapping("/hello")
public String hello() {
return "hello, this is 【" + serviceName + "】";
}
}
之后,手动执行 mvn clean package 打包出 jar 包,然后编写 Dockerfile
# 运行阶段
FROM openjdk:21-ea-34-jdk-slim
WORKDIR /app
# 复制构建产物
COPY target/*.jar app.jar
# 创建非root用户
RUN groupadd -r appuser && useradd -r -g appuser appuser
USER appuser
# 暴露应用端口
EXPOSE 8080
# 设置健康检查
HEALTHCHECK --interval=30s --timeout=3s --retries=3 \
CMD wget -q -O /dev/null http://localhost:8080/actuator/health || exit 1
# 启动命令
ENTRYPOINT ["java", "-jar", "app.jar"]
执行指令 docker build -t walli.nexus.repo/cloud-demo-service-a:0.0.1 . 构建 Docker 镜像,然后推送到私有仓库中。
部署服务镜像
编写 deply-demo-service-a.yaml 文件来定义所有资源
# 创建 namespace
apiVersion: v1
kind: Namespace
metadata:
name: cloud-services
---
# deployment
apiVersion: apps/v1
kind: Deployment
metadata:
name: cloud-demo-service-a
namespace: cloud-services
spec:
replicas: 1 # 希望运行的副本数量(Pod)
selector:
matchLabels:
app: cloud-demo-service-a
template:
metadata:
labels:
app: cloud-demo-service-a
spec:
containers:
- name: cloud-demo-service-a
image: walli.nexus.repo/cloud-demo-service-a:0.0.1 # 镜像地址
ports:
- containerPort: 8080 # 容器内应用监听的端口
resources:
requests:
memory: "256Mi"
cpu: "250m"
limits:
memory: "512Mi"
cpu: "500m"
---
# service
apiVersion: v1
kind: Service
metadata:
name: cloud-demo-service-a
namespace: cloud-services
spec:
selector:
app: cloud-demo-service-a # 这个选择器必须匹配上面Deployment的Pod标签
ports:
- protocol: TCP
port: 443 # Service对外暴露的端口,因为之前 ingress-nginx 配置了 https,所以此处 443
targetPort: 8080 # 请求转发到Pod的哪个端口(与containerPort一致)
type: ClusterIP # 默认类型,仅在集群内部可访问
执行指令 kubectl apply -f deply-demo-service-a.yaml 来部署应用
然后通过指令 kubectl get pods --all-namespaces 可以看到服务已经启动
映射路由
最后,编写 Ingress 资源文件 ingress-cloud-demo-service-a.yaml,映射访问路由
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: cloud-services-ingress
namespace: cloud-services
annotations:
kubernetes.io/ingress.class: "nginx"
nginx.ingress.kubernetes.io/rewrite-target: /$2
spec:
ingressClassName: nginx
rules:
- host: k8s.test.com # 你的域名
http:
paths:
- path: /cloud-demo-service-a(/|$)(.*)
pathType: ImplementationSpecific
backend:
service:
name: cloud-demo-service-a # 关联到前面的Service
port:
number: 443 # Service的端口
执行指令 kubectl apply -f ingress-cloud-demo-service-a.yaml,配置 ingress 生效
此时访问 https://k8s.test.com/cloud-demo-service-a/service-a/hello,可以看到接口调用成功