云原生之容器编排实践-以k8s的Service方式暴露SpringBoot服务

本文涉及的产品
容器服务 Serverless 版 ACK Serverless,952元额度 多规格
容器服务 Serverless 版 ACK Serverless,317元额度 多规格
简介: 云原生之容器编排实践-以k8s的Service方式暴露SpringBoot服务

8MQ%5[XONO$6[}FB3RUQOMA.png


背景


上一篇文章云原生之容器编排实践-SpringBoot应用以Deployment方式部署到minikube以及弹性伸缩中,我们通过 Deployment 完成了将 SpringBoot 应用部署到 minikube 并测试了其弹性伸缩的丝滑体验。但是 Deployment 部署后我们还面临以下问题:


  • 访问时需要先进行端口转发
  • 每次只能访问一个Pod,不支持负载均衡将请求路由至不同的Pod
  • Pod重新创建后IP地址与名称均发生变化,显然这在实际生产环境下是无法容忍的

这次我们使用 KubernetesService 来解决上述问题, Service 为我们带来了以下特性:


  • Service通过Label标签选择器关联对应的Pod
  • Service生命周期不跟Pod绑定,不会因为Pod重新创建改变IP
  • 提供了负载均衡功能,自动转发流量到不同Pod
  • 集群内部可通过服务名字访问(ClusterIP)
  • 可对集群外部提供访问端口(NodePort)

今天我们体验下两种类型的 Service :分别为 ClusterIPNodePort

创建服务最简单的 方式是通过 kubectl expose 命令,结合标签选择器来创建服务资源,实现通过单个 IP 和端口来访问所有的 Pod 。与 Deployment 一样,我们同样可以通过 YAML 描述文件调用 Kubernetes  API 服务来创建 Service


ClusterIP


ClusterIP 类型的 Service 只能在集群内部可以被访问。可以通过端口转发的方式可以在外面访问到集群里的服务。

H4KB)}M``$N[XFIQTS6}442.png

YAML


重点关注类型 kind: Service ,以及选择器 selector.app: cloud-native

[root@k8s0 service]# vi cloud-native-service.yaml 
apiVersion: v1
kind: Service
metadata:
  name: cloud-native-svc
spec:
  # 用来查找关联的Pod,所有标签都匹配才行
  selector:
    app: cloud-native
  # 默认 ClusterIP 集群内可访问
  type: ClusterIP
  ports:
    - port: 8080
      targetPort: 8080
# 应用配置
[root@k8s0 service]# kubectl apply -f cloud-native-service.yaml 
service/cloud-native-svc created

获取服务


service 可以简写为 svc

Note: 关于简写,在 Kubernetes 中通常会用到以下简写。


namespaces ns
nodes no
pods po
services svc
deployments deploy
replicationcontrollers rc
replicasets rs
configmaps cm
endpoints ep
events ev
cronjobs cj
persistentvolumeclaims pvc
persistentvolumes pv


[root@k8s0 service]# kubectl get service
NAME               TYPE        CLUSTER-IP       EXTERNAL-IP   PORT(S)          AGE
cloud-native-svc   ClusterIP   10.105.254.130   <none>        8080/TCP         9s
hello-minikube     NodePort    10.107.201.188   <none>        8080:31061/TCP   35d
kubernetes         ClusterIP   10.96.0.1        <none>        443/TCP          35d
[root@k8s0 service]# kubectl get svc
NAME               TYPE        CLUSTER-IP       EXTERNAL-IP   PORT(S)          AGE
cloud-native-svc   ClusterIP   10.105.254.130   <none>        8080/TCP         43s
hello-minikube     NodePort    10.107.201.188   <none>        8080:31061/TCP   35d
kubernetes         ClusterIP   10.96.0.1        <none>        443/TCP          35d

Service 服务的默认类型是 ClusterIP ,只能在集群内部访问。


可以进入 Pod 内访问或者通过端口转发,并且可以通过服务名称或者IP来访问。我的镜像内部没有 curl 命令(那么问题来了,镜像里面没有curl命令,怎么破?),就不测试了。


转发端口


[root@k8s0 service]# kubectl port-forward service/cloud-native-svc 8000:8080
Forwarding from 127.0.0.1:8000 -> 8080
Forwarding from [::1]:8000 -> 8080
Handling connection for 8000

测试接口


完成端口测试后,新开一个 Tab ,使用 Curl 进行接口测试。


[root@k8s0 ~]# curl http://localhost:8000/hi
Hi 127.0.0.1, I am 172.17.0.6

NodePort


使用 NodePort 类型的 Service ,可以做到直接将集群服务暴露出来。

}FG@IX(L%S[7${N)_PGTV@G.png

YAML


重点关注类型 spec.type: NodePort ,以及节点端口 spec.ports.nodePort: 30000


[root@k8s0 service]# vi cloud-native-service.yaml 
apiVersion: v1
kind: Service
metadata:
  name: cloud-native-svc
spec:
  # 用来查找关联的Pod,所有标签都匹配才行
  selector:
    app: cloud-native
  # NodePort节点可访问
  type: NodePort
  ports: 
    - port: 8080 # 本Service端口
      targetPort: 8080 # 容器端口
      nodePort: 30000   # 节点端口,范围固定30000 ~ 32767
# 应用配置
[root@k8s0 service]# kubectl apply -f cloud-native-service-nodeport.yaml 
service/cloud-native-svc configured

获取服务


cloud-native-svcNodePort 类型。当使用 kubectl describe service 命令时,我们可以观察到结果中的 Endpoints 有两个:172.17.0.5:8080, 172.17.0.6:8080,这便是我们的两个 Deployment 副本。

通过 kubectl get pods -o wide 我们可以再次验证:两个 Endpoints 正是我们的两个 Pod

[root@k8s0 service]# kubectl get svc
NAME               TYPE        CLUSTER-IP       EXTERNAL-IP   PORT(S)          AGE
cloud-native-svc   NodePort    10.105.254.130   <none>        8080:30000/TCP   24m
hello-minikube     NodePort    10.107.201.188   <none>        8080:31061/TCP   35d
kubernetes         ClusterIP   10.96.0.1        <none>        443/TCP          35d
# Endpoints有两个
[root@k8s0 service]# kubectl describe service cloud-native-svc
Name:                     cloud-native-svc
Namespace:                default
Labels:                   <none>
Annotations:              <none>
Selector:                 app=cloud-native
Type:                     NodePort
IP Family Policy:         SingleStack
IP Families:              IPv4
IP:                       10.105.254.130
IPs:                      10.105.254.130
Port:                     <unset>  8080/TCP
TargetPort:               8080/TCP
NodePort:                 <unset>  30000/TCP
Endpoints:                172.17.0.5:8080,172.17.0.6:8080
Session Affinity:         None
External Traffic Policy:  Cluster
Events:                   <none>
# 两个Endpoints正是我们的两个Pod
[root@k8s0 service]# kubectl get pods -o wide
NAME                              READY   STATUS    RESTARTS       AGE     IP           NODE       NOMINATED NODE   READINESS GATES
cloud-native                      1/1     Running   3 (117m ago)   4d12h   172.17.0.4   minikube   <none>           <none>
cloud-native-7bc75f4c94-47zg7     1/1     Running   2 (117m ago)   2d4h    172.17.0.6   minikube   <none>           <none>
cloud-native-7bc75f4c94-c2php     1/1     Running   2 (117m ago)   2d4h    172.17.0.5   minikube   <none>           <none>
hello-minikube-58647b77b8-srpbq   1/1     Running   9 (117m ago)   35d     172.17.0.8   minikub

同样,可以桶过 Dashboard 以可视化的方式观测我们运行的 KubernetesService 信息。

G}9WGWH(4@IV{[EB7LPSO6J.png

进入节点


这里所谓的 节点 ,是指 Kubernetes 节点;显然,这时候我们只有一个 minikube 节点。


[root@k8s0 service]# docker ps
CONTAINER ID   IMAGE                    COMMAND                  CREATED       STATUS       PORTS  NAMES
421832f7e7c9   kicbase/stable:v0.0.32   "/usr/local/bin/entr…"   5 weeks ago   Up 2 hours   127.0.0.1:49157->22/tcp, 127.0.0.1:49156->2376/tcp, 127.0.0.1:49155->5000/tcp, 127.0.0.1:49154->8443/tcp, 127.0.0.1:49153->32443/tcp   minikube
# 进入节点内部
[root@k8s0 service]# docker exec -it 421832f7e7c9 /bin/bash

测试接口


Kubernetes 节点( minikube )内部测试接口,哇哦,我们体验到了 Service 提供的负载均衡效果。

bash

复制代码

root@minikube:/# curl http://localhost:30000/hi
Hi 172.17.0.1, I am 172.17.0.5root@minikube:/# curl http://localhost:30000/hi
Hi 172.17.0.1, I am 172.17.0.6root@minikube:/# curl http://localhost:30000/hi
Hi 172.17.0.1, I am 172.17.0.5root@minikube:/# curl http://localhost:30000/hi
Hi 172.17.0.1, I am 172.17.0.6root@minikube:/# curl http://localhost:30000/hi
Hi 172.17.0.1, I am 172.17.0.5root@minikube:/# curl http://localhost:30000/hi
Hi 172.17.0.1, I am 172.17.0.6root@minikube:/# curl http://localhost:30000/hi
Hi 172.17.0.1, I am 172.17.0.5root@minikube:/#

小总结


Kubemetes 服务是一种为一组功能相同的 Pod 提供单一不变的接入点的资源。当服务存在时,它的IP地址和端口不会改变。客户端通过IP地址和端口号建立连接,这些连接会被路由到提供该服务的任意一个 Pod 上。通过这种方式,客户端不需要知道每个单独的提供服务的 Pod 的地址,这样这些 Pod 就可以在集群中随时被创建或移除。


If you have any questions or any bugs are found, please feel free to contact me.

Your comments and suggestions are welcome!

相关实践学习
容器服务Serverless版ACK Serverless 快速入门:在线魔方应用部署和监控
通过本实验,您将了解到容器服务Serverless版ACK Serverless 的基本产品能力,即可以实现快速部署一个在线魔方应用,并借助阿里云容器服务成熟的产品生态,实现在线应用的企业级监控,提升应用稳定性。
容器应用与集群管理
欢迎来到《容器应用与集群管理》课程,本课程是“云原生容器Clouder认证“系列中的第二阶段。课程将向您介绍与容器集群相关的概念和技术,这些概念和技术可以帮助您了解阿里云容器服务ACK/ACK Serverless的使用。同时,本课程也会向您介绍可以采取的工具、方法和可操作步骤,以帮助您了解如何基于容器服务ACK Serverless构建和管理企业级应用。 学习完本课程后,您将能够: 掌握容器集群、容器编排的基本概念 掌握Kubernetes的基础概念及核心思想 掌握阿里云容器服务ACK/ACK Serverless概念及使用方法 基于容器服务ACK Serverless搭建和管理企业级网站应用
目录
相关文章
|
7天前
|
弹性计算 运维 Kubernetes
实践篇:灵活调度,高效编排,容器化管理云上应用
【7月更文第8天】阿里云容器服务Kubernetes版(ACK)作为业界领先的容器管理和编排服务,凭借其强大的技术实力和丰富的云服务生态,为企业级用户提供了一系列卓越的优势,助力现代化应用的快速构建、部署与运维。
16 1
|
12天前
|
Prometheus Kubernetes Cloud Native
云原生周刊:Argo Rollouts 支持 Kubernetes Gateway API 1.0 | 2024.7.1
探索开源世界:Kubetools的推荐系统[Krs](https://github.com/kubetoolsca/krs)助力K8s优化,追踪K8s组件清单,指引IAC集成。阅读建议: Prometheus与Thanos的进化故事,Adidas容器平台管理经验,K8s请求实现详解。关注云原生:Argo Rollouts支持Gateway API 1.0,Kubewarden v1.14强化策略与镜像安全。
|
7天前
|
Kubernetes Cloud Native 微服务
企业级容器部署实战:基于ACK与ALB灵活构建云原生应用架构
这篇内容概述了云原生架构的优势,特别是通过阿里云容器服务Kubernetes版(ACK)和应用负载均衡器(ALB)实现的解决方案。它强调了ACK相对于自建Kubernetes的便利性,包括优化的云服务集成、自动化管理和更强的生态系统支持。文章提供了部署云原生应用的步骤,包括一键部署和手动部署的流程,并指出手动部署更适合有技术背景的用户。作者建议在预算允许的情况下使用ACK,因为它能提供高效、便捷的管理体验。同时,文章也提出了对文档改进的建议,如添加更多技术细节和解释,以帮助用户更好地理解和实施解决方案。最后,展望了ACK未来在智能化、安全性与边缘计算等方面的潜在发展。水文一篇,太忙了,见谅!
|
16天前
|
弹性计算 Serverless 调度
《阿里云产品四月刊》—享道出行:容器弹性技术驱动下的智慧出行稳定性实践(3)
阿里云瑶池数据库云原生化和一体化产品能力升级,多款产品更新迭代
|
18天前
|
Prometheus 监控 Kubernetes
深入理解Prometheus: Kubernetes环境中的监控实践
Kubernetes简介 在深入Prometheus与Kubernetes的集成之前,首先简要回顾一下Kubernetes的核心概念。Kubernetes是一个开源的容器编排平台,用于自动化容器的部署、扩展和管理。它提供了高度的可扩展性和灵活性,使得它成为微服务和云原生应用的理想选择。 核心组件 • 控制平面(Control Plane):集群管理相关的组件,如API服务器、调度器等。 • 工作节点(Nodes):运行应用容器的机器。 • Pods:Kubernetes的基本运行单位,可以容纳一个或多个容器。
|
3天前
|
前端开发 Java 应用服务中间件
Spring Boot 2.x 嵌入式 Servlet 容器
Spring Boot使用内嵌Tomcat,默认端口8080,可通过`application.properties`配置端口、上下文路径等。配置方式有两种:1) 直接在配置文件中添加`server.port`和`server.servlet.context-path`;2) 创建`WebServerFactoryCustomizer` Bean来自定义配置,如设置端口`factory.setPort(8083)`,这种方式优先级更高。
|
8天前
|
Java Spring 容器
深入理解Spring Boot中的容器与依赖注入
深入理解Spring Boot中的容器与依赖注入
|
17天前
|
Java API Docker
使用Spring Boot和Docker进行容器化部署
使用Spring Boot和Docker进行容器化部署
|
19天前
|
Java 应用服务中间件 Maven
SpringBoot(六)之内嵌容器
需要用哪个容器,就把其他两个容器注释掉。(
14 0
|
20天前
|
Java 应用服务中间件 容器
手写SpringBoot(二)之动态切换Servlet容器
我们在切换serlvet容器的时候,会将SpringBoot默认的tomcat jar包给排除掉,换上我们需要的jar包,比如jetty。
16 0

推荐镜像

更多