当前位置: 首页 > news >正文

K8S(十一)—Service详解

目录

    • Service
      • 发布服务(服务类型)
        • type: ClusterIP
          • 选择自己的 IP 地址
          • 例子
        • type: NodePort
          • 选择你自己的端口
          • 为 `type: NodePort` 服务自定义 IP 地址配置
          • 例子
        • type: LoadBalancer
        • 混合协议类型的负载均衡器
        • 禁用负载均衡器节点端口分配
        • 设置负载均衡器实现的类别
        • 内部负载均衡器
      • 练习

Service

官网地址:https://kubernetes.io/zh-cn/docs/concepts/services-networking/service/

Kubernetes 中 Service 是 将运行在一个或一组 Pod 上的网络应用程序公开为网络服务的方法。

Kubernetes 中 Service 的一个关键目标是让你无需修改现有应用程序就能使用不熟悉的服务发现机制。 你可以在 Pod 中运行代码,无需顾虑这是为云原生世界设计的代码,还是为已容器化的老应用程序设计的代码。 你可以使用 Service 让一组 Pod 在网络上可用,让客户端能够与其交互。

如果你使用 Deployment 来运行你的应用, Deployment 可以动态地创建和销毁 Pod。不管是这一刻还是下一刻, 你不知道有多少个这样的 Pod 正在工作以及健康与否;你可能甚至不知道那些健康的 Pod 是如何命名的。 Kubernetes Pod 被创建和销毁以匹配集群的预期状态。 Pod 是临时资源(你不应该期待单个 Pod 既可靠又耐用)。

每个 Pod 获取其自己的 IP 地址(Kubernetes 期待网络插件确保 IP 地址分配)。 对于集群中给定的 Deployment,这一刻运行的这组 Pod 可能不同于下一刻运行应用程序的那组 Pod。

这导致了一个问题: 如果一组 Pod(称为“后端”)为集群内的其他 Pod(称为“前端”)提供功能, 那么前端如何找出并跟踪要连接的 IP 地址,以便前端可以使用提供工作负载的后端部分?

发布服务(服务类型)

对一些应用的某些部分(如前端),可能希望将其暴露给 Kubernetes 集群外部的 IP 地址。

Kubernetes ServiceTypes 允许指定你所需要的 Service 类型。

可用的 type 值及其行为有:

  • ClusterIP

    通过集群的内部 IP 暴露服务,选择该值时服务只能够在集群内部访问。 这也是你没有为服务显式指定 type 时使用的默认值。 你可以使用 Ingress 或者 Gateway API 向公众暴露服务。

  • NodePort

    通过每个节点上的 IP 和静态端口(NodePort)暴露服务。 为了让节点端口可用,Kubernetes 设置了集群 IP 地址,这等同于你请求 type: ClusterIP 的服务。

  • LoadBalancer

    使用云提供商的负载均衡器向外部暴露服务。 Kubernetes 不直接提供负载均衡组件;你必须提供一个,或者将你的 Kubernetes 集群与云提供商集成。

  • ExternalName

    将服务映射到 externalName 字段的内容(例如,映射到主机名 api.foo.bar.example)。 该映射将集群的 DNS 服务器配置为返回具有该外部主机名值的 CNAME 记录。 无需创建任何类型代理。

服务 API 中的 type 字段被设计为层层递进的形式 - 每个级别都建立在前一个级别基础上。 并不是所有云提供商都如此严格要求的,但 Kubernetes 的 Service API 设计要求满足这一逻辑。

type: ClusterIP

此默认服务类型从你的集群中有意预留的 IP 地址池中分配一个 IP 地址。

其他几种服务类型在 ClusterIP 类型的基础上进行构建。

如果你定义的服务将 .spec.clusterIP 设置为 "None",则 Kubernetes 不会分配 IP 地址。有关详细信息,请参阅 headless 服务。

选择自己的 IP 地址

Service 创建的请求中,可以通过设置 spec.clusterIP 字段来指定自己的集群 IP 地址。 比如,希望替换一个已经已存在的 DNS 条目,或者遗留系统已经配置了一个固定的 IP 且很难重新配置。

用户选择的 IP 地址必须合法,并且这个 IP 地址在 service-cluster-ip-range CIDR 范围内, 这对 API 服务器来说是通过一个标识来指定的。 如果 IP 地址不合法,API 服务器会返回 HTTP 状态码 422,表示值不合法。

阅读避免冲突, 了解 Kubernetes 如何协助降低两种不同服务试图使用相同 IP 地址的风险和影响。

例子
[root@k8smaster service]# cat nginx.yaml 
apiVersion: v1
kind: Pod
metadata:name: nginxlabels:app.kubernetes.io/name: proxy
spec:containers:- name: nginximage: nginx:stableports:- containerPort: 80name: http-web-svc---
apiVersion: v1
kind: Service
metadata:name: nginx-service
spec:selector:app.kubernetes.io/name: proxyports:- name: name-of-service-portprotocol: TCPport: 80targetPort: http-web-svc
[root@k8smaster service]# kubectl get pod -o wide
NAME    READY   STATUS    RESTARTS   AGE     IP               NODE       NOMINATED NODE   READINESS GATES
nginx   1/1     Running   0          4m44s   10.244.185.193   k8snode2   <none>           <none>
[root@k8smaster service]#  kubectl get service
NAME            TYPE        CLUSTER-IP     EXTERNAL-IP   PORT(S)   AGE
kubernetes      ClusterIP   10.96.0.1      <none>        443/TCP   172m
nginx-service   ClusterIP   10.98.127.82   <none>        80/TCP    4m55s
[root@k8smaster service]# 
[root@k8smaster service]# curl 10.98.127.82
<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
<style>
type: NodePort

如果你将 type 字段设置为 NodePort,则 Kubernetes 控制平面将在 --service-node-port-range 标志指定的范围内分配端口(默认值:30000-32767)。 每个节点将那个端口(每个节点上的相同端口号)代理到你的服务中。 你的服务在其 .spec.ports[*].nodePort 字段中报告已分配的端口。

使用 NodePort 可以让你自由设置自己的负载均衡解决方案, 配置 Kubernetes 不完全支持的环境, 甚至直接暴露一个或多个节点的 IP 地址。

对于 NodePort 服务,Kubernetes 额外分配一个端口(TCP、UDP 或 SCTP 以匹配服务的协议)。 集群中的每个节点都将自己配置为监听分配的端口并将流量转发到与该服务关联的某个就绪端点。 通过使用适当的协议(例如 TCP)和适当的端口(分配给该服务)连接到所有节点, 你将能够从集群外部使用 type: NodePort 服务。

选择你自己的端口

如果需要特定的端口号,你可以在 nodePort 字段中指定一个值。 控制平面将为你分配该端口或报告 API 事务失败。 这意味着你需要自己注意可能发生的端口冲突。 你还必须使用有效的端口号,该端口号在配置用于 NodePort 的范围内。

以下是 type: NodePort 服务的一个示例清单,它指定了一个 NodePort 值(在本例中为 30007):

apiVersion: v1
kind: Service
metadata:name: my-service
spec:type: NodePortselector:app.kubernetes.io/name: MyAppports:# 默认情况下,为了方便起见,`targetPort` 被设置为与 `port` 字段相同的值。- port: 80targetPort: 80# 可选字段# 默认情况下,为了方便起见,Kubernetes 控制平面会从某个范围内分配一个端口号(默认:30000-32767)nodePort: 30007
type: NodePort 服务自定义 IP 地址配置

你可以在集群中设置节点以使用特定 IP 地址来提供 NodePort 服务。 如果每个节点都连接到多个网络(例如:一个网络用于应用程序流量,另一个网络用于节点和控制平面之间的流量), 你可能需要执行此操作。

如果你要指定特定的 IP 地址来代理端口,可以将 kube-proxy 的 --nodeport-addresses 标志或 kube-proxy 配置文件的等效 nodePortAddresses 字段设置为特定的 IP 段。

此标志采用逗号分隔的 IP 段列表(例如 10.0.0.0/8192.0.2.0/25)来指定 kube-proxy 应视为该节点本地的 IP 地址范围。

例如,如果你使用 --nodeport-addresses=127.0.0.0/8 标志启动 kube-proxy, 则 kube-proxy 仅选择 NodePort 服务的环回接口。 --nodeport-addresses 的默认值是一个空列表。 这意味着 kube-proxy 应考虑 NodePort 的所有可用网络接口。 (这也与早期的 Kubernetes 版本兼容。)

说明:

此服务呈现为 <NodeIP>:spec.ports[*].nodePort.spec.clusterIP:spec.ports[*].port。 如果设置了 kube-proxy 的 --nodeport-addresses 标志或 kube-proxy 配置文件中的等效字段, 则 <NodeIP> 将是过滤的节点 IP 地址(或可能的 IP 地址)。

例子
[root@k8smaster service]# cat nginx2.yaml 
apiVersion: v1
kind: Pod
metadata:name: nginx-2labels:app.kubernetes.io/name: proxy2
spec:containers:- name: nginximage: nginx:stableports:- containerPort: 80name: http-web-svc---
apiVersion: v1
kind: Service
metadata:name: nginx-service2
spec:type: NodePortselector:app.kubernetes.io/name: proxy2ports:- name: name-of-service-portprotocol: TCPport: 80targetPort: http-web-svcnodePort: 30007

nginx

type: LoadBalancer

在使用支持外部负载均衡器的云提供商的服务时,设置 type 的值为 "LoadBalancer", 将为 Service 提供负载均衡器。 负载均衡器是异步创建的,关于被提供的负载均衡器的信息将会通过 Service 的 status.loadBalancer 字段发布出去。

实例:

apiVersion: v1
kind: Service
metadata:name: my-service
spec:selector:app.kubernetes.io/name: MyAppports:- protocol: TCPport: 80targetPort: 9376clusterIP: 10.0.171.239type: LoadBalancer
status:loadBalancer:ingress:- ip: 192.0.2.127

来自外部负载均衡器的流量将直接重定向到后端 Pod 上,由云提供商决定如何进行负载平衡。

要实现 type: LoadBalancer 的服务,Kubernetes 通常首先进行与请求 type: NodePort 服务等效的更改。 cloud-controller-manager 组件随后配置外部负载均衡器以将流量转发到已分配的节点端口。

你可以将负载均衡服务配置为忽略分配节点端口, 前提是云提供商实现支持这点。

某些云提供商允许设置 loadBalancerIP。 在这些情况下,将根据用户设置的 loadBalancerIP 来创建负载均衡器。 如果没有设置 loadBalancerIP 字段,将会给负载均衡器指派一个临时 IP。 如果设置了 loadBalancerIP,但云提供商并不支持这种特性,那么设置的 loadBalancerIP 值将会被忽略掉。

说明:

针对 Service 的 .spec.loadBalancerIP 字段已在 Kubernetes v1.24 中被弃用。

此字段的定义模糊,其含义因实现而异。它也不支持双协议栈联网。 此字段可能会在未来的 API 版本中被移除。

如果你正在集成某云平台,该平台通过(特定于提供商的)注解为 Service 指定负载均衡器 IP 地址, 你应该切换到这样做。

如果你正在为集成到 Kubernetes 的负载均衡器编写代码,请避免使用此字段。 你可以与 Gateway 而不是 Service 集成, 或者你可以在 Service 上定义自己的(特定于提供商的)注解,以指定等效的细节。

混合协议类型的负载均衡器

特性状态: Kubernetes v1.26 [stable]

默认情况下,对于 LoadBalancer 类型的服务,当定义了多个端口时, 所有端口必须具有相同的协议,并且该协议必须是受云提供商支持的协议。

当服务中定义了多个端口时,特性门控 MixedProtocolLBService (在 kube-apiserver 1.24 版本默认为启用) 允许 LoadBalancer 类型的服务使用不同的协议。

说明:

可用于负载均衡服务的协议集由你的云提供商决定,他们可能在 Kubernetes API 强制执行的限制之外另加一些约束。

禁用负载均衡器节点端口分配

特性状态: Kubernetes v1.24 [stable]

你可以通过设置 spec.allocateLoadBalancerNodePortsfalse 对类型为 LoadBalancer 的服务禁用节点端口分配。 这仅适用于直接将流量路由到 Pod 而不是使用节点端口的负载均衡器实现。 默认情况下,spec.allocateLoadBalancerNodePortstrue, LoadBalancer 类型的服务继续分配节点端口。 如果现有服务已被分配节点端口,将参数 spec.allocateLoadBalancerNodePorts 设置为 false 时,这些服务上已分配置的节点端口不会被自动释放。 你必须显式地在每个服务端口中删除 nodePorts 项以释放对应端口。

设置负载均衡器实现的类别

特性状态: Kubernetes v1.24 [stable]

对于 type 设置为 LoadBalancer 的 Service, spec.loadBalancerClass 字段允许你不使用云提供商的默认负载均衡器实现, 转而使用指定的负载均衡器实现。

默认情况下,.spec.loadBalancerClass 未设置,如果集群使用 --cloud-provider 配置了云提供商, LoadBalancer 类型服务会使用云提供商的默认负载均衡器实现。

如果设置了 .spec.loadBalancerClass,则假定存在某个与所指定的类相匹配的负载均衡器实现在监视服务变化。 所有默认的负载均衡器实现(例如,由云提供商所提供的)都会忽略设置了此字段的服务。.spec.loadBalancerClass 只能设置到类型为 LoadBalancer 的 Service 之上,而且一旦设置之后不可变更。

.spec.loadBalancerClass 的值必须是一个标签风格的标识符, 可以有选择地带有类似 “internal-vip” 或 “example.com/internal-vip” 这类前缀。 没有前缀的名字是保留给最终用户的。

内部负载均衡器

在混合环境中,有时有必要在同一(虚拟)网络地址块内路由来自服务的流量。

在水平分割 DNS 环境中,你需要两个服务才能将内部和外部流量都路由到你的端点(Endpoints)。

如要设置内部负载均衡器,请根据你所使用的云运营商,为服务添加以下注解之一:

  • Default
  • GCP
  • AWS
  • Azure
  • IBM Cloud
  • OpenStack
  • 百度云
  • 腾讯云
  • 阿里云
  • OCI

选择一个标签。

练习

  • 编写一个yaml文件mysql.yaml,启动一个MySQL的pod,一个副本,然后创建一个service-mysql,发布Mysql标准的方式,启动pod
apiVersion: v1
kind: Pod
metadata:name: mysqllabels:app.kubernetes.io/name: mysqlproxy
spec:containers:- name: mysqlimage: mysqlports:- containerPort: 3306name: http-mysql-svcenv:-name: MYSQL_ROOT_PASSWORDvalue: "123456"---
apiVersion: v1
kind: Service
metadata:name: mysql-service
spec:type: NodePortselector:app.kubernetes.io/name: mysqlproxyports:- name: name-of-service-portprotocol: TCPport: 3360targetPort: http-mysql-svcnodePort: 30008
[root@k8smaster service]# kubectl get pod -o wide
NAME      READY   STATUS    RESTARTS   AGE   IP               NODE       NOMINATED NODE   READINESS GATES
mysql     1/1     Running   0          71s   10.244.185.194   k8snode2   <none>           <none>
nginx     1/1     Running   0          33m   10.244.185.193   k8snode2   <none>           <none>
nginx-2   1/1     Running   0          22m   10.244.249.1     k8snode1   <none>           <none>[root@k8smaster service]# kubectl exec -it mysql -- bash
root@mysql:/# mysql -uroot -p123456
mysql: [Warning] Using a password on the command line interface can be insecure.
Welcome to the MySQL monitor.  Commands end with ; or \g.
Your MySQL connection id is 8
Server version: 8.0.27 MySQL Community Server - GPLCopyright (c) 2000, 2021, Oracle and/or its affiliates.Oracle is a registered trademark of Oracle Corporation and/or its
affiliates. Other names may be trademarks of their respective
owners.Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.mysql> 

在Window的sqlyog进行连接

  • 编写一个yaml文件nginx.yaml,使用deployment控制器,启动一个nginx的pod,三个副本,然后创建一个服务service-nginx,发布nginx集群
apiVersion: apps/v1
kind: Deployment
metadata:name: nginx-deploymentlabels:app: mynginx
spec:replicas: 3selector:matchLabels:app: mynginxtemplate:metadata:labels:app: mynginxspec:containers:- name: nginximage: nginximagePullPolicy: IfNotPresentports:- containerPort: 80
---
apiVersion: v1
kind: Service
metadata:name: mynginx
spec:type: NodePortselector:app: mynginxports:- name: name-of-service-portprotocol: TCPport: 80targetPort: 80nodePort: 30009
[root@k8smaster service]# kubectl get pod -o wide
NAME                                READY   STATUS    RESTARTS   AGE   IP               NODE       NOMINATED NODE   READINESS GATES
mysql                               1/1     Running   0          14m   10.244.185.194   k8snode2   <none>           <none>
nginx                               1/1     Running   0          46m   10.244.185.193   k8snode2   <none>           <none>
nginx-2                             1/1     Running   0          36m   10.244.249.1     k8snode1   <none>           <none>
nginx-deployment-6dcb8ffbc7-bjdth   1/1     Running   0          27s   10.244.249.3     k8snode1   <none>           <none>
nginx-deployment-6dcb8ffbc7-gg4v9   1/1     Running   0          27s   10.244.185.195   k8snode2   <none>           <none>
nginx-deployment-6dcb8ffbc7-wtkhq   1/1     Running   0          27s   10.244.249.2     k8snode1   <none>           <none>

相关文章:

  • C#中的协变和逆变
  • 【MYSQL】-库的操作
  • JVM- 为什么G1垃圾回收器需要有大对象区
  • 物业该如何处理物业报修问题?工单管理系统如何统一管理报修需求?
  • 0089__一条普遍存在于嵌入式实时系统(RTOS)中的嵌套使用互斥量的bug分析
  • Apollo Planning——换道:LANE_CHANGE_DECIDER
  • 2312d,D语言单元测试等
  • 超级计算机与天气预报:精准预测的科技革命
  • x3::forward_ast
  • 七大主流的HttpClient程序比较
  • 国内外网络安全现状与存在的问题。应该如何缓解或解决这些问题
  • 51单片机应用从零开始(十一)·数组函数、指针函数
  • 龙芯loongarch64服务器编译安装gcc-8.3.0
  • 虚拟化之问答
  • html css概念
  • ERLANG 网工修炼笔记 ---- UDP
  • extjs4学习之配置
  • HTTP中的ETag在移动客户端的应用
  • java中具有继承关系的类及其对象初始化顺序
  • LintCode 31. partitionArray 数组划分
  • Linux各目录及每个目录的详细介绍
  • Puppeteer:浏览器控制器
  • Theano - 导数
  • 工作踩坑系列——https访问遇到“已阻止载入混合活动内容”
  • 基于 Babel 的 npm 包最小化设置
  • 基于Mobx的多页面小程序的全局共享状态管理实践
  • 京东美团研发面经
  • 跨域
  • 前端临床手札——文件上传
  • 容器化应用: 在阿里云搭建多节点 Openshift 集群
  • 它承受着该等级不该有的简单, leetcode 564 寻找最近的回文数
  • 小程序开发中的那些坑
  • 一个6年java程序员的工作感悟,写给还在迷茫的你
  • HanLP分词命名实体提取详解
  • ionic入门之数据绑定显示-1
  • 关于Kubernetes Dashboard漏洞CVE-2018-18264的修复公告
  • ​Python 3 新特性:类型注解
  • ​Spring Boot 分片上传文件
  • #ifdef 的技巧用法
  • $L^p$ 调和函数恒为零
  • (2)MFC+openGL单文档框架glFrame
  • (剑指Offer)面试题41:和为s的连续正数序列
  • (力扣记录)235. 二叉搜索树的最近公共祖先
  • (十八)SpringBoot之发送QQ邮件
  • (十一)c52学习之旅-动态数码管
  • (转) SpringBoot:使用spring-boot-devtools进行热部署以及不生效的问题解决
  • (转)ABI是什么
  • (转)关于pipe()的详细解析
  • (转载)虚函数剖析
  • (转载)虚幻引擎3--【UnrealScript教程】章节一:20.location和rotation
  • .[backups@airmail.cc].faust勒索病毒的最新威胁:如何恢复您的数据?
  • .net mvc 获取url中controller和action
  • .net(C#)中String.Format如何使用
  • .net程序集学习心得
  • .Net接口调试与案例