k8s | 深入理解资源对象 service
继续将 k8s 比喻成一个大公司,Service 就像是一名重要的客服代表,它的职责是帮助内部员工(Pods)提供服务,以满足外部客户(应用程序或用户)的需求。
出现原因
service 出现是为了解决什么问题呢?
Service 的主要目的是解决内部服务的稳定性和可访问性问题,为外部客户提供一个稳定的入口,使他们可以方便地访问到所需的服务。Service 为每个服务分配一个虚拟的固定 IP 地址,并通过这个 IP 地址代表后端的员工(Pods)。即使员工(Pods)发生变化,Service 会自动更新后端的员工列表,确保客户始终能够找到所需的服务。
Pod是不稳定的,IP是会变化的,所以需要一层抽象来屏蔽这种变化,这层抽象叫做Service
四种类型
-
Cluster IP: 默认类型,给集群内部每个
pod
分配一个虚拟ip -
NodePort:在
Cluster IP
的基础上为Service
在每个节点绑定一个端口,这样就可以通过NodeIP:NodePort
来访问服务apiVersion: v1 kind: Service metadata: name: test-service spec: selector: app: test type: NodePort # 指定service 类型 ports: - protocol: TCP port: 80 targetPort: 80 name: test-http nodePort: 30000 # 范围:30000-32767
master 将从给定的配置范围内(默认:30000-32767)分配端口, 每个 Node 将从该端口(每个 Node 上的同一端口)代理到 Service,如果不指定的话会自动生成一个端口。
-
LoadBalance:在
NodePort
的基础上,借助cloud provider
创建一个使用云提供商的负载局衡器,可以向外部暴露服务。并将请求转发到<NodeIP>:NodePort
-
ExternalName:将服务通过 DNS CNAME 记录方式转发到指定的域名(通过
spec.externlName
设定) 当一个 Service 的类型被设置为 ExternalName 时,它并不代表内部的员工(Pods),而是为一个外部服务提供一个别名。
这个别名就像是一个联系人名单,告诉公司的员工:如果需要特定的服务,可以通过这个别名来访问。ExternalName 类型的 Service 并不会分配外部 IP 地址,而是直接返回一个 CNAME 记录,指向外部服务的域名
假设有一个外部的数据库服务,它的域名是
external-db.example.com
,集群内部可以通过一个别名my-db
来访问这个外部服务。我们可以通过以下 YAML 配置文件来创建一个 ExternalName 类型的 Service
apiVersion: v1 kind: Service metadata: name: my-db spec: type: ExternalName externalName: external-db.example.com
对于运行在集群外部的服务,它通过返回该外部服务的别名这种方式来提供服务
Service的用法
定义
通过 yaml 或者 json 来定义。属性解释
apiVersion: v1 # 版本
kind: Service # 类型
metadata: #元数据 类型string
name: test #Service名称 类型string
namespace: test #命名空间,不指定时默认为default命名空间
labels: #自定义标签属性列表 类型string
- name: string
annotations: #自定义注解属性列表
- name: string
spec: #详细描述 类型list[]
selector: [] #Label Selector配置,选择具有指定label标签的pod作为管理范围
type: string #service的类型,指定service的访问方式,默认ClusterIP
#ClusterIP:虚拟的服务ip地址,用于k8s集群内部的pod访问,在Node上kube-porxy通过设置的iptables规则进行转发
#NodePort:使用宿主机端口,能够访问各Node的外部客户端通过Node的IP和端口就能访问服务器
#LoadBalancer:使用外部负载均衡器完成到服务器的负载分发,
#需要在spec.status.loadBalancer字段指定外部负载均衡服务器的IP,并同时定义nodePort和clusterIP用于公有云环境。
clusterIP: string #虚拟服务IP地址,当type=ClusterIP时,如不指定,则系统会自动进行分配,也可以手动指定。当type=loadBalancer,需要指定
sessionAffinity: string #是否支持session,可选值为ClietIP,默认值为空,ClientIP表示将同一个客户端(根据客户端IP地址决定)的访问请求都转发到同一个后端Pod
ports: #service需要暴露的端口列表
- name: string #端口名称 类型string
protocol: TCP #端口协议,支持TCP或UDP,默认TCP 类型string
port: 80 #服务监听的端口号 类型int
targetPort: 8080 #需要转发到后端的端口号 类型int
nodePort: 8080 #当type=NodePort时,指定映射到物理机的端口号 类型:int
status: #当type=LoadBalancer时,设置外部负载均衡的地址,用于公有云环境
loadBalancer: #外部负载均衡器
ingress: #外部负载均衡器
ip: string #外部负载均衡器的IP地址
hostname: string #外部负载均衡器的机主机
常用指令
-
创建service
通过配置文件
kubectl apply -f service.yaml
通过命令
kubectl create service <service-type> <service-name> --tcp=<port>
这个指令可以创建一个新的 Service,并将其与指定的 Deployment 或 Pod 关联
-
查看service 详情
# 列出当前命名空间中所有的 Service,并显示它们的名称、类型、Cluster IP、外部 IP 等信息 kubectl get services # 查看指定 Service 的详细信息,包括关联的 Pod、端口配置、Selector 等信息 kubectl describe service <service-name>
-
删除或者编辑service
kubectl delete service <service-name> kubectl edit service <service-name>
-
暴露 Deployment/Pod 为 Service
kubectl expose <resource-type> <resource-name> --type=<service-type> --port=<port> --target-port=<target-port>
这个指令可以将指定的 Deployment 或 Pod 暴露为一个新的 Service,需要指定 Service 的类型、要暴露的端口和目标端口。
例如:
kubectl expose deployment my-app --type=NodePort --port=80 --target-port=8080 # 这个命令将 my-app Deployment 暴露为一个类型为 NodePort 的 Service。这样,Kubernetes 就会在集群的每个节点上分配一个随机的端口(NodePort),并将这个端口映射到后端 Pod 的端口 8080。
-
端口转发
kubectl port-forward <pod-name> <local-port>:<pod-port>
将本地端口与指定 Pod 的端口进行转发,使得可以直接访问 Pod 的服务
例如:
# 这个命令将本地主机的端口 8888 绑定到 Pod my-pod 内部的端口 8080。现在,我们可以在本地浏览器中访问 http://localhost:8888,就可以直接访问 Pod 内部运行的 Web 应用程序 kubectl port-forward my-pod 8888:8080
评论区