K8s新手系列之Service资源
概述
官方文档:https://kubernetes.io/zh-cn/docs/concepts/services-networking/service/
在kubernetes中,pod是应用程序的载体,我们可以通过pod的ip来访问应用程序,但是pod的ip地址不是固定的,这也就意味着不方便直接采用pod的ip对服务进行访问。
为了解决这个问题,kubernetes提供了Service资源,Service会对提供同一个服务的多个pod进行聚合,并且提供一个统一的入口地址。通过访问Service的入口地址就能访问到后面的pod服务。
Service在很多情况下只是一个概念,真正起作用的其实是kube-proxy服务进程,每个Node节点上都运行着一个kube-proxy服务进程。当创建Service的时候会通过api-server向etcd写入创建的service的信息,而kube-proxy会基于监听的机制发现这种Service的变动,然后它会将最新的Service信息转换成对应的访问规则。
简单点说就是:Service可以实现pod的负载均衡和服务发现功能,为访问Pod提供了统一的访问入口。
Service的类型
Service的类型有四类:分别是以下四类
ClusterIP
这是svc默认的类型,是k8s集群内部分配的虚拟IP,适用于集群内部进行访问,外部访问不到,但是可以使用 Ingress 或者 Gateway API 来公开服务。创建svc时会自动关联endpoints资源。
NodePort
在ClusterIP基础之上,多添加了对所有Worker节点实现端口映射的功能。NodePort的工作原理其实就是将service的端口映射到Node的一个端口上,然后就可以通过NodeIp:NodePort来访问service了。
LoadBalancer
实现负载均衡的服务,主要应用场景是云厂商环境,它能够为服务提供外部可访问的 IP 地址。这种类型的服务通过云服务提供商的负载均衡器实现,允许外部流量进入集群中的 Pod。
ExternalName
ExternalName类型的Service用于引入集群外部的服务,它通过ExternalName属性指定外部一个服务的地址,然后在集群内部访问此service就可以访问到外部的服务了。
Service的作用
服务发现与负载均衡
服务发现:Kubernetes 中的 Pod 是动态创建和销毁的,它们的 IP 地址也是动态分配的。Service 为一组具有相同功能的 Pod 提供了一个固定的虚拟 IP 地址和 DNS 名称。其他组件可以通过这个固定的地址来访问这些 Pod,而无需关心具体 Pod 的 IP 地址变化。
负载均衡:Service 可以将流量均匀地分发到后端的多个 Pod 上,实现负载均衡的功能。这样可以确保应用能够处理大量的并发请求,提高系统的性能和可靠性。例如,一个 Web 应用可能由多个 Pod 组成,通过 Service 可以将用户的请求均衡地分配到这些 Pod 上,避免单个 Pod 因负载过高而出现性能问题。
应用解耦
解耦客户端与服务端:Service 使得客户端与后端服务的 Pod 之间实现了解耦。客户端只需要知道 Service 的地址,而不需要了解后端具体有哪些 Pod 以及它们的状态。当后端 Pod 发生变化(如扩容、缩容或升级)时,客户端无需进行任何修改,仍然可以通过 Service 正常访问服务。
支持微服务架构:在微服务架构中,不同的微服务之间通常需要相互调用。Service 为每个微服务提供了独立的访问入口,使得各个微服务可以独立地进行部署、扩展和升级,而不会影响到其他微服务。这种解耦方式提高了整个系统的可维护性和可扩展性。
提供稳定的网络端点
外部访问入口:对于需要对外提供服务的应用,Service 可以作为外部访问的入口点。通过将 Service 设置为 NodePort 类型或 LoadBalancer 类型,可以将服务暴露到集群外部,让外部用户能够访问到 Kubernetes 集群中的应用。
内部网络隔离:在 Kubernetes 集群内部,Service 还可以用于实现网络隔离。通过定义不同的 Service 和相应的访问规则,可以限制哪些 Pod 能够访问特定的服务,从而提高集群的安全性和稳定性。
方便应用管理与维护
统一管理:通过 Service,可以对一组相关的 Pod 进行统一的管理和配置。例如,可以通过 Service 来设置访问策略、监控指标收集等,而无需对每个 Pod 单独进行配置。
简化运维操作:当需要对应用进行升级、回滚或其他运维操作时,只需要对 Service 进行相应的配置修改,Kubernetes 会自动根据 Service 的定义来调整后端 Pod 的状态,从而简化了运维操作的复杂度。
Service的工作原理
Service 通过 Label Selector
来选择对应的 Pods,当 Service 接收到请求时,它会根据负载均衡算法将请求转发到后端的某个 Pod 上。K8s 中的 kube - proxy
组件负责在节点上维护网络规则,确保 Service 能够正确地将流量路由到后端 Pods。
Service的资源配置文件
apiVersion: v1 # API版本,Service属于核心API组,固定使用v1
kind: Service # 资源类型为Service
metadata: # 元数据,定义Service的标识信息
name: my-service # Service名称,必须符合DNS标签规范
namespace: default # 命名空间,默认为default
labels: # 标签,用于组织和选择资源
app: my-app
tier: backend
annotations: # 注解,用于存储非标识性元数据(如配置信息)
service.beta.kubernetes.io/aws-load-balancer-type: nlb
spec: # 服务规范,定义Service的行为和关联的Pod
type: ClusterIP # Service类型(ClusterIP/NodePort/LoadBalancer/ExternalName)
selector: # 标签选择器,用于确定哪些Pod属于此服务
app: my-app
tier: backend
ports: # 端口配置,定义服务如何接收流量
- name: http # 端口名称,必须符合DNS标签规范
protocol: TCP # 协议类型,支持TCP/UDP/SCTP,默认为TCP
port: 80 # 服务暴露的端口(集群内部访问使用)
targetPort: 8080 # 后端Pod接收流量的端口
nodePort: 30080 # NodePort类型时,节点上暴露的端口(30000-32767)
externalIPs: # 外部IP列表,允许通过这些IP访问服务
- 80.11.12.10
sessionAffinity: None # 会话亲和性(None/ClientIP),默认为None
sessionAffinityConfig: # 会话亲和性配置(仅当sessionAffinity为ClientIP时有效)
clientIP:
timeoutSeconds: 10800 # 客户端IP会话保持时间(秒)
loadBalancerIP: 70.42.103.12 # LoadBalancer类型时,指定负载均衡器的IP
loadBalancerSourceRanges: # 限制访问LoadBalancer的客户端IP范围
- 10.0.0.0/8
externalName: my.database.example.com # ExternalName类型时,指定外部域名
publishNotReadyAddresses: false # 是否发布未就绪的端点,默认为false
Service之ClusterIP实战
这是svc默认的类型,是k8s集群内部分配的虚拟IP,适用于集群内部进行访问,外部访问不到,但是可以使用 Ingress 或者 Gateway API 来公开服务。创建svc时会自动关联endpoints资源。
创建一个Deployment
[root@master01 ~/deploy]# cat deploy-nginx.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: deployment-nginx
namespace: default
spec:
# 设置Pod的副本数量
replicas: 3
selector:
# 标签匹配规则
matchLabels:
app: nginx
template:
metadata:
name: pod-nginx
labels:
app: nginx
spec:
containers:
- name: container-nginx
image: nginx:1.14.1
restartPolicy: Always
# 创建deploy
[root@master01 ~/deploy]# kubectl apply -f deploy-nginx.yaml
deployment.apps/deployment-nginx created
创建Service
# 定义service
[root@master01 ~/service]# cat service-clusterip.yaml
apiVersion: v1
kind: Service
metadata:
# 需要和pod在一个命名空间内
namespace: default
name: nginx-svc-clusterip
spec:
# 定义service的类型
type: ClusterIP
# 标签选择器,选择pod的标签,而不是deploy的标签
selector:
app: nginx
# 定义端口映射
ports:
- name: clusterip-nginx
# 访问service的端口
port: 6789
# 容器的端口
targetPort: 80
protocol: TCP
# 创建service
[root@master01 ~/service]# kubectl apply -f service-clusterip.yaml
service/nginx-svc-clusterip created
查看service的详情
# 查看service
[root@master01 ~/service]# kubectl get svc -o wide
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE SELECTOR
nginx-svc-clusterip ClusterIP 10.96.3.77 <none> 6789/TCP 91s app=nginx
# 查看详情
[root@master01 ~/service]# kubectl describe svc nginx-svc-clusterip
Name: nginx-svc-clusterip
Namespace: default
Labels: <none>
Annotations: <none>
Selector: app=nginx
Type: ClusterIP
IP Family Policy: SingleStack
IP Families: IPv4
IP: 10.96.3.77
IPs: 10.96.3.77
Port: clusterip-nginx 6789/TCP
TargetPort: 80/TCP
Endpoints: 100.117.144.188:80,100.117.144.189:80,100.95.185.217:80
Session Affinity: None
Events: <none>
注意看Endpoints字段,该字段对应的是关联的所有的pod的IP:PORT
地址,service和pod之间的联系是通过endpoints实现的。
访问service
访问clusterip的service需要通过分配给service的IP和PORT进行访问
# 可以看到CLUSTER-IP字段分配的值是10.96.3.77,PORT(S)字段的值是6789(我们在资源配置文件中定义的)
[root@master01 ~/service]# kubectl get svc -o wide
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE SELECTOR
nginx-svc-clusterip ClusterIP 10.96.3.77 <none> 6789/TCP 91s app=nginx
# 访问service
[root@master01 ~/service]# curl 10.96.3.77:6789
<!DOCTYPE html>
<html>
<body>
<h1>Welcome to nginx!</h1>
# 省略部分内容
<p><em>Thank you for using nginx.</em></p>
</body>
</html>
Service之NodePort实战
ClusterIP只能在K8s集群内部访问,外部无法访问,而NodePort在ClusterIP基础之上,多添加了对所有Worker节点实现端口映射的功能。实现了外部访问Pod。
NodePort的工作原理其实就是将service的端口映射到Node的一个端口上,然后就可以通过NodeIp:NodePort来访问service了。
创建deployment
# 定义资源文件
[root@master01 ~/deploy]# cat deploy-tomcat.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: deployment-tomcat
namespace: default
spec:
# 定义更新策略
strategy:
type: RollingUpdate
rollingUpdate:
maxSurge: 1
maxUnavailable: 1
replicas: 3
selector:
matchLabels:
app: tomcat
template:
metadata:
name: pod-tomcat
labels:
app: tomcat
spec:
containers:
- name: container-tomcat
image: tomcat:9.0
restartPolicy: Always
# 创建deployment
[root@master01 ~/deploy]# kubectl apply -f deploy-tomcat.yaml
deployment.apps/deployment-tomcat created
创建service
# 定义资源文件
[root@master01 ~/service]# cat service-nodeport.yaml
apiVersion: v1
kind: Service
metadata:
# 需要和pod在一个命名空间内
namespace: default
name: tomcat-svc-nodeport
spec:
# 定义service的类型
type: NodePort
# 标签选择器,选择pod的标签,而不是deploy的标签
selector:
app: tomcat
# 定义端口映射
ports:
- name: nodeport-tomcat
# 访问service的端口
port: 16789
# 容器的端口
targetPort: 8080
# nodePort的取值是30000-32767,会随机生成,但建议配置
nodePort: 31180
protocol: TCP
# 创建service
[root@master01 ~/service]# kubectl apply -f service-nodeport.yaml
service/tomcat-svc-nodeport created
查看service
## 查看service
[root@master01 ~/service]# kubectl get svc -o wide
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE SELECTOR
tomcat-svc-nodeport NodePort 10.96.0.110 <none> 16789:31180/TCP 54s app=tomcat
# 查看详情
[root@master01 ~/service]# kubectl describe svc tomcat-svc-nodeport
Name: tomcat-svc-nodeport
Namespace: default
Labels: <none>
Annotations: <none>
Selector: app=tomcat
Type: NodePort
IP Family Policy: SingleStack
IP Families: IPv4
IP: 10.96.0.110
IPs: 10.96.0.110
Port: nodeport-tomcat 16789/TCP
TargetPort: 8080/TCP
NodePort: nodeport-tomcat 31180/TCP
Endpoints: <none>
Session Affinity: None
External Traffic Policy: Cluster
Events: <none>
访问service
访问nodeport的service可以通过集群内部的IP:PORT
进行访问,也可以通过node节点的IP:PORT
进行访问
通过所有node节点均可访问
## 查看service
[root@master01 ~/service]# kubectl get svc -o wide
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE SELECTOR
tomcat-svc-nodeport NodePort 10.96.0.110 <none> 16789:31180/TCP 54s app=tomcat
# 通过集群内部
curl 10.96.0.110:16789
# 通过node节点进行访问
curl 10.0.0.30:31180
curl 10.0.0.31:31180
curl 10.0.0.32:31180
Service之ExternalName实战
ExternalName类型的Service用于引入集群外部的服务,它通过ExternalName属性指定外部一个服务的地址,然后在集群内部访问此service就可以访问到外部的服务了。
创建service
# 定义配置文件
[root@master01 ~/service]# cat service-externalname.yaml
apiVersion: v1
kind: Service
metadata:
name: baidu-externalname
spec:
type: ExternalName
externalName: www.baidu.com
#ports:
#- name: baidu-name
# port: 443 # 服务端口(集群内部使用)
# targetPort: 443 # 外部服务实际端口
# protocol: TCP
# 创建service
[root@master01 ~/service]# kubectl apply -f service-externalname.yaml
service/baidu-externalname created
查看详情
# 查看service
[root@master01 ~/service]# kubectl get svc
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
baidu-externalname ExternalName <none> www.baidu.com <none> 47s
# 查看service详情
[root@master01 ~/service]# kubectl describe svc baidu-externalname
Name: baidu-externalname
Namespace: default
Labels: <none>
Annotations: <none>
Selector: <none>
Type: ExternalName
IP Families: <none>
IP:
IPs: <none>
External Name: www.baidu.com
Session Affinity: None
Events: <none>
验证集群内部访问
# 创建busybox容器进行访问测试
[root@master01 ~/service]# kubectl run -it --rm dns-test --image=busybox:1.28
If you don't see a command prompt, try pressing enter.
# nslookup 验证
/ # nslookup baidu-externalname
Server: 10.96.0.10
Address 1: 10.96.0.10 kube-dns.kube-system.svc.cluster.local
Name: baidu-externalname
Address 1: 2409:8c00:6c21:118b:0:ff:b0e8:f003
Address 2: 2409:8c00:6c21:11eb:0:ff:b0bf:59ca
Address 3: 39.156.70.239
Address 4: 39.156.70.46
# ping进行访问
/ # ping baidu-externalname
PING baidu-externalname (39.156.70.239): 56 data bytes
64 bytes from 39.156.70.239: seq=0 ttl=127 time=15.301 ms
64 bytes from 39.156.70.239: seq=1 ttl=127 time=14.258 ms
64 bytes from 39.156.70.239: seq=2 ttl=127 time=29.040 ms
Service之LoadBalancer(省略)
LoadBalancer目前没有云环境,在这儿先省略
Service的管理
查看Service
语法:
kubectl get svc <svc-name> -n <namespace>
示例:
[root@master01 ~/service]# kubectl get svc
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
baidu-externalname ExternalName <none> www.baidu.com <none> 23m
kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 13d
nginx-svc-clusterip ClusterIP 10.96.3.77 <none> 6789/TCP 4d20h
tomcat-svc-nodeport NodePort 10.96.0.110 <none> 16789:31180/TCP 49m
修改Service
有两种方式,一种是通过kubectl edit svc <svc-name>
来进行修改,会打开一个类似vim的界面,修改其对应的值即可,最后wq保存即可应用你的配置.
另一种方式则是修改对应的资源文件,最后使用kubectl apply -f <file>
即可。
删除Service
语法:
kubectl delete svc <svc-name> -n <namespace>
K8s新手系列之Service资源的更多相关文章
- kubernetes系列08—service资源详解
本文收录在容器技术学习系列文章总目录 1.认识service 1.1 为什么要使用service Kubernetes Pod 是有生命周期的,它们可以被创建,也可以被销毁,然而一旦被销毁生命就永远结 ...
- 容器编排系统k8s之Service资源
前文我们了解了k8s上的DemonSet.Job和CronJob控制器的相关话题,回顾请参考:https://www.cnblogs.com/qiuhom-1874/p/14157306.html:今 ...
- k8s 之service资源介绍(三)
kubernetes service资源 apiVersion: v1 kind: Service metadata: name: kubia spec: ports: - port: 80 targ ...
- k8s入门系列之guestbook快速部署
k8s集群以及一些扩展插件已经安装完毕,本篇文章介绍一下如何在k8s集群上快速部署guestbook应用. •实验环境为集群:master(1)+node(4),详细内容参考<k8s入门系列之集 ...
- k8s入门系列之扩展组件(一)DNS安装篇
DNS (domain name system),提供域名解析服务,解决了难于记忆的IP地址问题,以更人性可读可记忆可标识的方式映射对应IP地址. Cluster DNS扩展插件用于支持k8s集群系统 ...
- K8S入门系列之集群二进制部署-->master篇(二)
组件版本和配置策略 组件版本 Kubernetes 1.16.2 Docker 19.03-ce Etcd 3.3.17 https://github.com/etcd-io/etcd/release ...
- k8s~k8s里的服务Service
k8s用命名空间namespace把资源进行隔离,默认情况下,相同的命名空间里的服务可以相互通讯,反之进行隔离. 服务Service 1.1 Service Kubernetes中一个应用服务会有一个 ...
- k8s创建pod和service的过程
一.概念介绍 更详细的参见:https://www.kubernetes.org.cn/5335.html 1.K8s K8s 是一种用于在一组主机上运行和协同容器化应用程序的系统,提供应用部署.规划 ...
- Kubernetes 学习10 Service资源
一.Service对应组件关系 1.在kubernetes平台之上,pod是有生命周期的,所以为了能够给对应的客户端提供一个固定的访问端点,因此我们在客户端和服务Pod之间添加一个固定的中间层,这个中 ...
- 【转帖】k8s之Deployment与service
k8s之Deployment与service 2018年08月05日 18:11:00 xiyou_pen/pen 阅读数 5894 版权声明:本文为博主原创文章,遵循CC 4.0 by-sa版权 ...
随机推荐
- [SDOI2008] Sandy的卡片 题解
讲一种自认为最暴力的方法. 首先肯定还是用差分的思想,对于每一张卡片进行重新标号,在卡片串与卡片串中插入特殊字符,然后找重复了 \(n\) 次的子串. 这里我们对于每一个子串开一个大小为 \(n\) ...
- docker - [02] 安装部署
一.环境准备 1.需要会一点点Linux基础 2.CentOS 7+ 3.XShell连接服务器进行远程操作 Centos7.x 虚拟机环境 序号 主机名 IP 操作系统 1 ctos79-01 19 ...
- 如何构建多模态AI知识库?
转载:如何构建多模态AI知识库? 摘要 在科技飞速发展的当下,人工智能(AI)已成为推动各行业变革的关键力量.其中,多模态 AI 知识库作为 AI 领域的重要创新,正引领我们迈向一个全新的智能时代.它 ...
- 值得推荐的IT公司名单(成都篇)
成都,作为新一线城市中的科技强市,拥有众多优秀的 IT 公司,为广大 IT 从业者提供了丰富的就业机会和良好的职业发展环境.以下是一些值得推荐的 IT 公司(排名不分先后): 一.互联网巨头在成都 1 ...
- Selenium IDE 使用过程
这篇文章主要介绍如何成功搭建firefox与Selenium IDE环境及IDE使用过程,以登录功能介绍. Selenium IDE是Firefox浏览器的一款插件,实现网页的录制及回放,可以脚本导出 ...
- Selenium WebDriver上创建 WebDriver测试脚本
本文实现一个WebDriver测试脚本,介绍WebDrive的常用命令.UI元素定位的策略以及在脚本中的使用,还有Get命令. 你将学到: 脚本创建 代码走查 测试执行 定位Web元素 ...
- vue2打包部署到nginx,解决路由history模式下页面空白问题
项目使用的是vue2,脚手架vue-cli 4. 需求:之前项目路由使用的是hash,现在要求调整为history模式,但是整个过程非常坎坷,遇到了页面空白问题.现在就具体讲一下这个问题. 首先,直接 ...
- calico配置报错 kubelet.go:2855] "Container runtime network not ready"
前言 配置 calico 网络插件时,kubectl get node 报错: NoReady kubectl describe node node Name: node Roles: <non ...
- wordpress:nginx负载均衡+nignweb服务器+mysql数据库+nfs-lsync+rsync备份
目录 所有知识结合,注意正式环境慎用: mariadb服务器 NFS服务器配置 web服务器配置 Nginx负载均衡 backup备份服务器配置rsync NFS服务器安装lsync进行实时同步 所有 ...
- 鸿蒙NEXT开发案例:程序员计算器
[环境准备] • 操作系统:Windows 10 • 开发工具:DevEco Studio 5.0.1 Release Build Version: 5.0.5.306 • 目标设备:华为Mate60 ...