Java 部署:K8s Service 与 Ingress 配置(外部访问)

Java 部署:K8s Service 与 Ingress 配置(外部访问)
在这里插入图片描述
👋 大家好,欢迎来到我的技术博客!
📚 在这里,我会分享学习笔记、实战经验与技术思考,力求用简单的方式讲清楚复杂的问题。
🎯 本文将围绕Java部署这个话题展开,希望能为你带来一些启发或实用的参考。
🌱 无论你是刚入门的新手,还是正在进阶的开发者,希望你都能有所收获!

文章目录

Java 部署:K8s Service 与 Ingress 配置(外部访问) 🚀

在现代云原生应用架构中,将 Java 应用部署到 Kubernetes(简称 K8s)集群已成为行业标准。然而,仅仅将应用容器化并运行在 Pod 中远远不够——如何让外部用户或系统安全、高效地访问这些服务,是每个开发者必须掌握的核心技能。本文将深入探讨 Kubernetes 中 ServiceIngress 的原理、配置方式及其在 Java 应用外部访问中的实际应用,并通过完整的代码示例和架构图,帮助你构建一个可生产级的部署方案。

无论你是刚接触 K8s 的 Java 开发者,还是已有一定经验但希望系统梳理网络暴露机制的工程师,这篇文章都将为你提供清晰、实用的指导。让我们从基础开始,逐步深入,最终实现一个可通过公网访问的 Spring Boot 应用。🌐


为什么需要 Service 和 Ingress?🤔

在 Kubernetes 中,Pod 是最小的调度单元,但它们具有动态性:IP 地址会随着 Pod 的创建和销毁而变化。如果直接依赖 Pod IP 进行通信,系统将极其脆弱。因此,Kubernetes 引入了 Service 资源,为一组 Pod 提供稳定的网络端点。

然而,Service 默认仅在集群内部可达。若要让外部用户(如浏览器、移动端或其他外部服务)访问你的 Java 应用,就需要进一步的网络暴露机制。这就是 Ingress 发挥作用的地方。

简而言之:

  • Service:解决集群内部服务发现与负载均衡。
  • Ingress:解决集群外部流量路由与 HTTPS 终止等高级功能。
💡 小贴士:Ingress 并不是 Service 的替代品,而是其上层抽象。Ingress 通常通过 Ingress Controller(如 Nginx、Traefik)将外部请求转发到后端的 Service。

准备工作:一个简单的 Java Web 应用 🧪

在深入 K8s 配置之前,我们先准备一个轻量级的 Spring Boot 应用作为示例。该应用将暴露两个 HTTP 接口,用于验证部署是否成功。

项目结构

java-k8s-demo/ ├── pom.xml └── src/ └── main/ ├── java/ │ └── com/example/demo/ │ ├── DemoApplication.java │ └── ApiController.java └日晚间 resources/ └── application.properties 

Maven 依赖(pom.xml)

<?xml version="1.0" encoding="UTF-8"?><projectxmlns="http://maven.apache.org/POM/4.0.0"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"><modelVersion>4.0.0</modelVersion><groupId>com.example</groupId><artifactId>java-k8s-demo</artifactId><version>1.0.0</version><packaging>jar</packaging><parent><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-parent</artifactId><version>3.2.0</version><relativePath/></parent><dependencies><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency></dependencies><build><plugins><plugin><groupId>org.springframework.boot</groupId><artifactId>spring-boot-maven-plugin</artifactId></plugin></plugins></build></project>

主启动类(DemoApplication.java)

packagecom.example.demo;importorg.springframework.boot.SpringApplication;importorg.springframework.boot.autoconfigure.SpringBootApplication;@SpringBootApplicationpublicclassDemoApplication{publicstaticvoidmain(String[] args){SpringApplication.run(DemoApplication.class, args);}}

控制器(ApiController.java)

packagecom.example.demo;importorg.springframework.web.bind.annotation.GetMapping;importorg.springframework.web.bind.annotation.RestController;importjava.net.InetAddress;importjava.net.UnknownHostException;@RestControllerpublicclassApiController{@GetMapping("/health")publicStringhealth(){return"OK";}@GetMapping("/info")publicStringinfo(){try{String hostname =InetAddress.getLocalHost().getHostName();return"Hello from Java app! Host: "+ hostname;}catch(UnknownHostException e){return"Hello from Java app! Host: unknown";}}}

配置文件(application.properties)

server.port=8080 

构建与测试本地运行

执行以下命令打包应用:

mvn clean package -DskipTests 

生成的 JAR 文件位于 target/java-k8s-demo-1.0.0.jar。本地运行验证:

java -jar target/java-k8s-demo-1.0.0.jar 

访问 http://localhost:8080/health 应返回 OKhttp://localhost:8080/info 返回包含主机名的信息。✅


容器化 Java 应用 🐳

Kubernetes 运行的是容器,因此我们需要将 Java 应用打包成 Docker 镜像。

编写 Dockerfile

# 使用官方 OpenJDK 17 镜像作为基础 FROM openjdk:17-jdk-slim # 设置工作目录 WORKDIR /app # 将 JAR 文件复制到容器中 COPY target/java-k8s-demo-1.0.0.jar app.jar # 暴露端口 EXPOSE 8080 # 启动应用 ENTRYPOINT ["java", "-jar", "app.jar"] 

构建镜像

docker build -t java-k8s-demo:1.0.0 .
🔒 安全建议:生产环境中应使用多阶段构建以减小镜像体积,并避免将构建工具留在最终镜像中。

推送镜像到镜像仓库

为了在 K8s 集群中拉取镜像,需将其推送到可访问的镜像仓库(如 Docker Hub、阿里云 ACR、AWS ECR 等)。假设你已登录 Docker Hub:

docker tag java-k8s-demo:1.0.0 your-dockerhub-username/java-k8s-demo:1.0.0 docker push your-dockerhub-username/java-k8s-demo:1.0.0 
⚠️ 注意:后续 YAML 配置中需使用你实际推送的镜像名称。

Kubernetes Deployment:运行 Java 应用 📦

Deployment 是管理 Pod 生命周期的核心资源。它确保指定数量的 Pod 副本始终运行,并支持滚动更新、回滚等操作。

deployment.yaml

apiVersion: apps/v1 kind: Deployment metadata:name: java-app-deployment labels:app: java-app spec:replicas:3selector:matchLabels:app: java-app template:metadata:labels:app: java-app spec:containers:-name: java-app image: your-dockerhub-username/java-k8s-demo:1.0.0 ports:-containerPort:8080resources:requests:memory:"256Mi"cpu:"200m"limits:memory:"512Mi"cpu:"500m"livenessProbe:httpGet:path: /health port:8080initialDelaySeconds:10periodSeconds:15readinessProbe:httpGet:path: /health port:8080initialDelaySeconds:5periodSeconds:10

应用 Deployment

kubectl apply -f deployment.yaml 

验证 Pod 是否正常运行:

kubectl get pods -l app=java-app 

你应该看到 3 个处于 Running 状态的 Pod。


Service:集群内部的服务发现 🔍

现在 Java 应用已在集群中运行,但外部无法访问。首先,我们创建一个 ClusterIP 类型的 Service,这是默认类型,仅在集群内部可达。

service.yaml

apiVersion: v1 kind: Service metadata:name: java-app-service labels:app: java-app spec:type: ClusterIP selector:app: java-app ports:-protocol: TCP port:80targetPort:8080

关键字段说明:

  • selector: 匹配带有 app=java-app 标签的 Pod。
  • port: Service 对外暴露的端口(集群内其他服务通过此端口访问)。
  • targetPort: Pod 中容器监听的端口(即 Java 应用的 8080)。

应用 Service:

kubectl apply -f service.yaml 

验证 Service:

kubectl get svc java-app-service 

输出类似:

NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE java-app-service ClusterIP 10.96.123.45 <none> 80/TCP 10s 

此时,集群内的其他 Pod 可通过 http://java-app-service:80/health 访问该服务。


外部访问方案一:NodePort 🌐

如果你的 K8s 集群运行在裸机或 VM 上(非托管云服务),NodePort 是最简单的外部访问方式。它会在每个节点的特定端口(默认 30000-32767)上开放服务。

修改 Service 类型为 NodePort

apiVersion: v1 kind: Service metadata:name: java-app-service spec:type: NodePort selector:app: java-app ports:-protocol: TCP port:80targetPort:8080nodePort:30080# 可选,若不指定则自动分配

应用后,获取节点 IP(假设为 192.168.1.100),即可通过 http://192.168.1.100:30080/health 访问应用。

⚠️ 局限性:NodePort 不适合生产环境,原因包括:端口号不友好(非 80/443)无法基于域名路由缺乏 TLS 终止等高级功能

外部访问方案二:LoadBalancer(云环境)☁️

在 AWS、GCP、Azure 等云平台上,将 Service 类型设为 LoadBalancer 会自动创建一个云负载均衡器,并分配公网 IP。

apiVersion: v1 kind: Service metadata:name: java-app-service spec:type: LoadBalancer selector:app: java-app ports:-protocol: TCP port:80targetPort:8080

应用后,执行:

kubectl get svc java-app-service 

等待几分钟,EXTERNAL-IP 字段将从 <pending> 变为实际 IP。通过该 IP 即可访问应用。

💡 优势:简单、自动集成云平台。
❌ 缺点:每个 Service 对应一个 LB,成本高;不支持基于路径或主机名的路由。

外部访问方案三:Ingress(推荐)🔥

Ingress 是 Kubernetes 官方推荐的外部流量入口方案。它通过一个统一的入口(通常由 Ingress Controller 实现,如 Nginx Ingress Controller)将外部请求路由到不同的后端 Service,支持:

  • 基于主机名(Host)的路由
  • 基于路径(Path)的路由
  • TLS/SSL 终止
  • 负载均衡策略
  • 速率限制等高级功能

Ingress 工作原理

HTTP Request

Routes to

Routes to

Internet User

Ingress Controller

Service A

Service B

Pod A1

Pod A2

Pod B1

Ingress Controller 本身是一个 Deployment + Service(通常是 LoadBalancer 或 NodePort),它监听外部流量,并根据 Ingress 规则转发请求。

安装 Nginx Ingress Controller

大多数云厂商提供托管 Ingress Controller,但你也可以手动安装。以 Helm 为例(需先安装 Helm):

helm repo add ingress-nginx https://kubernetes.github.io/ingress-nginx helm repo update helm install ingress-nginx ingress-nginx/ingress-nginx 
📚 更多安装方式请参考 官方文档

安装完成后,获取 Ingress Controller 的外部 IP:

kubectl get svc -n ingress-nginx 

你会看到一个名为 ingress-nginx-controller 的 Service,其 EXTERNAL-IP 即为公网入口。


配置 Ingress 资源 🛠️

现在,我们创建一个 Ingress 资源,将流量路由到 java-app-service

ingress.yaml

apiVersion: networking.k8s.io/v1 kind: Ingress metadata:name: java-app-ingress annotations:nginx.ingress.kubernetes.io/rewrite-target: / spec:ingressClassName: nginx # 指定 Ingress Classrules:-host: java-app.example.com # 替换为你的域名http:paths:-path: / pathType: Prefix backend:service:name: java-app-service port:number:80

关键点:

  • host: 必须是你拥有的域名,并已解析到 Ingress Controller 的 IP。
  • pathType: Prefix: 表示路径前缀匹配(K8s 1.18+ 推荐)。
  • ingressClassName: 指定使用的 Ingress Controller 类型(需与安装时一致)。

应用 Ingress:

kubectl apply -f ingress.yaml 

验证 Ingress

kubectl get ingress java-app-ingress 

输出应包含 HOSTS 和 ADDRESS 字段。

本地测试(无真实域名)

若无真实域名,可通过修改本地 /etc/hosts 文件模拟:

<INGRESS_CONTROLLER_IP> java-app.example.com 

然后访问 http://java-app.example.com/health


支持 HTTPS:TLS 终止 🔒

生产环境中,HTTPS 是必须的。Ingress 支持通过 TLS Secret 配置证书。

步骤 1:准备 TLS 证书

你可以使用 Let’s Encrypt 免费获取证书,或使用自签名证书测试。

生成自签名证书(仅用于测试):

openssl req -x509 -nodes -days 365 -newkey rsa:2048 \ -keyout tls.key -out tls.crt -subj "/CN=java-app.example.com"

步骤 2:创建 Kubernetes Secret

kubectl create secret tls java-app-tls-secret \ --key tls.key \ --cert tls.crt 

步骤 3:更新 Ingress 配置

apiVersion: networking.k8s.io/v1 kind: Ingress metadata:name: java-app-ingress spec:ingressClassName: nginx tls:-hosts:- java-app.example.com secretName: java-app-tls-secret rules:-host: java-app.example.com http:paths:-path: / pathType: Prefix backend:service:name: java-app-service port:number:80

应用后,即可通过 https://java-app.example.com/health 安全访问应用。

✅ 最佳实践:在生产环境中,建议使用 cert-manager 自动管理 Let’s Encrypt 证书。

高级 Ingress 配置示例 🧩

多服务路由(基于路径)

假设你有两个 Java 服务:user-serviceorder-service

apiVersion: networking.k8s.io/v1 kind: Ingress metadata:name: multi-service-ingress spec:ingressClassName: nginx rules:-host: api.example.com http:paths:-path: /users pathType: Prefix backend:service:name: user-service port:number:80-path: /orders pathType: Prefix backend:service:name: order-service port:number:80

访问 https://api.example.com/users → user-service
访问 https://api.example.com/orders → order-service

基于主机名的多租户

rules:-host: tenant1.example.com http:paths:-path: / backend:...-host: tenant2.example.com http:paths:-path: / backend:...

启用 gzip 压缩

通过 annotations 启用 Nginx 的 gzip:

metadata:annotations:nginx.ingress.kubernetes.io/gzip:"true"

限流(Rate Limiting)

metadata:annotations:nginx.ingress.kubernetes.io/rate-limit-connections:"10"nginx.ingress.kubernetes.io/rate-limit-rpm:"300"

故障排查技巧 🛠️

部署过程中可能遇到问题,以下是常见排查步骤:

1. 检查 Pod 状态

kubectl get pods -l app=java-app kubectl logs <pod-name>

确保应用正常启动,无异常日志。

2. 验证 Service 是否关联正确 Pod

kubectl describe svc java-app-service 

查看 Endpoints 字段,应列出 Pod IP。若为空,说明 selector 不匹配。

3. 测试集群内部访问

进入一个临时 Pod:

kubectl run -it --rm debug --image=busybox --restart=Never -- sh

在容器内执行:

wget -qO- http://java-app-service/health 

若失败,说明 Service 配置有问题。

4. 检查 Ingress 状态

kubectl describe ingress java-app-ingress 

查看 Events 部分是否有错误。

5. 查看 Ingress Controller 日志

kubectl logs -n ingress-nginx <ingress-controller-pod-name>

观察是否有 404、502 等错误。


生产环境最佳实践 🏆

1. 使用健康检查

已在 Deployment 中配置 livenessProbereadinessProbe,确保流量只发送到就绪的 Pod。

2. 资源限制

为容器设置合理的 requestslimits,避免资源争抢。

3. 自动扩缩容(HPA)

根据 CPU 或自定义指标自动调整副本数:

apiVersion: autoscaling/v2 kind: HorizontalPodAutoscaler metadata:name: java-app-hpa spec:scaleTargetRef:apiVersion: apps/v1 kind: Deployment name: java-app-deployment minReplicas:2maxReplicas:10metrics:-type: Resource resource:name: cpu target:type: Utilization averageUtilization:70

4. 使用 NetworkPolicy 限制流量

默认情况下,Pod 可被任意访问。通过 NetworkPolicy 限制来源:

apiVersion: networking.k8s.io/v1 kind: NetworkPolicy metadata:name: allow-from-ingress spec:podSelector:matchLabels:app: java-app policyTypes:- Ingress ingress:-from:-namespaceSelector:matchLabels:kubernetes.io/metadata.name: ingress-nginx 

5. 监控与日志

集成 Prometheus + Grafana 监控应用指标,使用 EFK(Elasticsearch, Fluentd, Kibana)收集日志。


总结:选择合适的外部访问方式 🎯

方案适用场景优点缺点
NodePort开发/测试环境简单、无需额外组件端口不友好、无高级路由
LoadBalancer云环境、单一服务自动集成云 LB成本高、不支持多路由
Ingress生产环境、多服务统一入口、支持 HTTPS、灵活路由需部署 Ingress Controller

对于绝大多数 Java 应用,Ingress 是首选方案。它不仅满足基本访问需求,还为未来的微服务架构打下基础。


扩展阅读 📚


通过本文,你应该已经掌握了如何将 Java 应用部署到 Kubernetes,并通过 Service 和 Ingress 实现安全、高效的外部访问。从本地开发到生产上线,每一步都至关重要。希望这些知识能助你在云原生之旅中走得更远!💪

Happy coding! 💻✨


🙌 感谢你读到这里!
🔍 技术之路没有捷径,但每一次阅读、思考和实践,都在悄悄拉近你与目标的距离。
💡 如果本文对你有帮助,不妨 👍 点赞、📌 收藏、📤 分享 给更多需要的朋友!
💬 欢迎在评论区留下你的想法、疑问或建议,我会一一回复,我们一起交流、共同成长 🌿
🔔 关注我,不错过下一篇干货!我们下期再见!✨

Read more

[特殊字符]颠覆MCP!Open WebUI新技术mcpo横空出世!支持ollama!轻松支持各种MCP Server!Cline+Claude3.7轻松开发论文检索MCP Server!

[特殊字符]颠覆MCP!Open WebUI新技术mcpo横空出世!支持ollama!轻松支持各种MCP Server!Cline+Claude3.7轻松开发论文检索MCP Server!

🔥🔥🔥本篇笔记所对应的视频:🚀颠覆MCP!Open WebUI新技术mcpo横空出世!支持ollama!轻松支持各种MCP Server!Cline+Claude3.7轻松开发MCP服务_哔哩哔哩_bilibili Open WebUI 的 MCPo 项目:将 MCP 工具无缝集成到 OpenAPI 的创新解决方案 随着人工智能工具和模型的快速发展,如何高效、安全地将这些工具集成到标准化的 API 接口中成为了开发者面临的重要挑战。Open WebUI 的 MCPo 项目(Model Context Protocol-to-OpenAPI Proxy Server)正是为了解决这一问题而设计的。本文将带您深入了解 MCPo 的功能、优势及其对开发者生态的影响。 什么是 MCPo? MCPo 是一个简单、可靠的代理服务器,能够将任何基于 MCP 协议的工具转换为兼容

By Ne0inhk
Qwen3+Qwen Agent 智能体开发实战,打开大模型MCP工具新方式!(一)

Qwen3+Qwen Agent 智能体开发实战,打开大模型MCP工具新方式!(一)

系列文章目录 一、Qwen3+Qwen Agent 智能体开发实战,打开大模型MCP工具新方式!(一) 二、Qwen3+Qwen Agent +MCP智能体开发实战(二)—10分钟打造"MiniManus" 前言 要说最近人工智能界最火热的开源大模型,必定是阿里发布不久的Qwen3系列模型。Qwen3模型凭借赶超DeepSeek-V3/R1的优异性能,创新的混合推理模式,以及极强的MCP能力迅速成为AI Agent开发的主流基座模型。大家可参考我的文章一文解析Qwen3大模型详细了解Qwen3模型的核心能力。有读者私信我: “Qwen3官网特地强调增强了Agent和代码能力,同时加强了对MCP的支持,那么我该如何利用Qwen3快速开发MCP应用呢?” 这就就需要使用我们今天的主角——Qwen官方推荐的开发工具Qwen-Agent ,本期分享我们就一起学习快速使用Qwen3+QwenAgent 接入MCP服务端,快速开发AI Agent应用! 一、注册 Qwen3 API-Key 本次分享通过阿里云百炼大模型服务平台API Key请求方式调用Qwen3大模型,获取服务平台

By Ne0inhk