kubernetes之service

本文详细介绍了Kubernetes中Service的概念,包括Service的定义、类型、服务发现机制、基本用法,以及如何通过NodePort和Ingress实现集群外部访问。同时,讲解了Service与Pod、Deployment的关系,以及如何通过Service实现负载均衡。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

目录

1、Service定义详解

1.1、 yaml格式的Service定义文件的完整内容

1.2、Service定义文件中各属性的说明表

2、Service  服务类型

3、服务发现

3.1、环境变量

3.2、DNS

4、Service的基本用法

4.1 创建deployment

4.2 创建一个Service来提供服务

5、集群外部访问Service

5.1、将Service的端口号映射到物理机

6、Ingress


 

1、Service定义详解

1.1、 yaml格式的Service定义文件的完整内容

apiVersion: v1

kind: Service

metadata:

  name: string

  namespace: string

  labels:

  - name: string

  annotations:

  - name: string

spec:

  selector: []

  type: string

  clusterIP: string

  sessionAffinity: string

  ports:

  - name: string

    protocol: string

    port: int

    targetPort: int

    nodePort: int

1.2、Service定义文件中各属性的说明表

属性名称

取值类型

是否必选

取值说明

apiVersion
stringrequiredv1
kind
stringrequiredService
metadata
objectrequired元数据
metadata.namestringrequiredservice 名称
metadata.namespace
stringrequired命名空间,默认default
metadata.labels[]list 自定义标签属性列表
metadata.annotations[]list 自定义注解属性列表
specobjectrequired详细描述
spec.selector[]listrequiredLabel Selector配置,将选择具有指定Label标签的Pod作为管理范围
spec.typestringrequired

Service的类型,指定Service的访问方式,默认值为ClusterIP。取值范围如下:
ClusterIP: 虚拟服务的IP,用于k8s集群内部的pod访问,在Node上kube-proxy通过设置的Iptables规则进行转发。
NodePort:使用宿主机的端口,使用能够访问各Node的外部客户端通过Node的IP地址和端口就能访问服务。
 

spec.clusterIPstring 虚拟服务的IP地址,当type=clusterIP时,如果不指定,则系统进行自动分配。
spec.sessionAffinitystring 是否支持Session,可选值为ClientIP,表示将同一个源IP地址的客户端访问请求都转发到同一个后端Pod。默认值为空。
spec.ports[]list Service需要暴露的端口列表
spec.ports[].namestring 端口名称
spec.ports[].protocolstring 端口协议,支持TCP和UDP,默认值为TCP
spec.ports[].portint 服务监听的端口号
spec.ports[].targetPortint 需要转发到后端Pod的端口号
spec.ports[].nodePortint 当spec.type=NodePort时,指定映射到物理机的端口号

 

2、Service  服务类型

Kubernetes ServiceTypes 允许指定一个需要的类型的 Service,默认是 ClusterIP 类型。


Type 的取值以及行为如下:

  • ClusterIP:通过集群的内部 IP 暴露服务,选择该值,服务只能够在集群内部可以访问,这也是默认的 ServiceType。
     
  • NodePort:通过每个 Node 上的 IP 和静态端口(NodePort)暴露服务。NodePort 服务会路由到 ClusterIP 服务,这个 ClusterIP 服务会自动创建。通过请求 <NodeIP>:<NodePort>,可以从集群的外部访问一个 NodePort 服务。
     
  • LoadBalancer:使用云提供商的负载局衡器,可以向外部暴露服务。外部的负载均衡器可以路由到 NodePort 服务和 ClusterIP 服务。
     
  • ExternalName:通过返回 CNAME 和它的值,可以将服务映射到 externalName 字段的内容(例如, foo.bar.example.com)。 没有任何类型代理被创建,这只有 Kubernetes 1.7 或更高版

k8s中有3种IP地址:

  • Node IP: Node节点的IP地址,这是集群中每个节点的物理网卡的IP地址;
     
  • Pod IP: Pod的IP地址,这是Docker Engine根据docker0网桥的IP地址段进行分配的,通常是一个虚拟的二层网络;
     
  • Cluster IP:Service 的IP地址,这也是一个虚拟的IP,但它更像是一个“伪造”的IP地址,因为它没有一个实体网络对象,所以无法响应ping命令。它只能结合Service Port组成一个具体的通信服务端口,单独的Cluster IP不具备TCP/IP通信的基础。在k8s集群之内,Node IP网、Pod IP网与Cluster IP网之间的通信采用的是k8s自己设计的一种编程实现的特殊的路由规则,不同于常见的IP路由实现。
     

3、服务发现

Kubernetes 支持2种基本的服务发现模式 —— 环境变量和 DNS。

3.1、环境变量

当 Pod 运行在 Node 上,kubelet 会为每个活跃的 Service 添加一组环境变量。 它同时支持 Docker links兼容 变量、简单的 {SVCNAME}_SERVICE_HOST 和 {SVCNAME}_SERVICE_PORT 变量,这里 Service 的名称需大写,横线被转换成下划线。

3.2、DNS

        一个强烈推荐的集群插件 是 DNS 服务器。 DNS 服务器监视着创建新 Service 的 Kubernetes API,从而为每一个 Service 创建一组 DNS 记录。 如果整个集群的 DNS 一直被启用,那么所有的 Pod 应该能够自动对 Service 进行名称解析。
例如,有一个名称为 "my-service" 的 Service,它在 Kubernetes 集群中名为 "my-ns" 的 Namespace 中,为 "my-service.my-ns" 创建了一条 DNS 记录。 在名称为 "my-ns" 的 Namespace 中的 Pod 应该能够简单地通过名称查询找到 "my-service"。 在另一个 Namespace 中的 Pod 必须限定名称为 "my-service.my-ns"。 这些名称查询的结果是 Cluster IP。
Kubernetes 也支持对端口名称的 DNS SRV(Service)记录。 如果名称为 "my-service.my-ns" 的 Service 有一个名为 "http" 的 TCP 端口,可以对 "_http._tcp.my-service.my-ns" 执行 DNS SRV 查询,得到 "http" 的端口号。
Kubernetes DNS 服务器是唯一的一种能够访问 ExternalName 类型的 Service 的方式。 更多信息可以查看DNS Pod 和 Service。
Kubernetes 从 1.3 版本起, DNS 是内置的服务,通过插件管理器 集群插件 自动被启动。Kubernetes DNS 在集群中调度 DNS Pod 和 Service ,配置 kubelet 以通知个别容器使用 DNS Service 的 IP 解析 DNS 名字。
 

4、Service的基本用法

       一般来说,对外提供服务的应用程序需要通过某种机制来实现,对于容器应用最简便的方式就是通过TCP/IP机制及监听IP和端口号来实现。
创建一个基本功能的Service。

4.1 创建deployment

我们定义一个提供web服务的Deploy,由两个tomcat容器副本组成,每个容器通过containerPort设置提供服务号为8080:
 webapp-deploy.yaml

apiVersion: apps/v1

kind: Deployment

metadata:

  name: webapp

spec:

  selector:

    matchLabels:

      app: webapp

  replicas: 2

  template:

    metadata:

      name: webapp

      labels:

        app: webapp

    spec:

      containers:

      - name: webapp

        image: tomcat

        ports:

        - containerPort: 8080

创建该Deploy

kubectl apply -f webapp-deploy.yaml

获取pod的IP地址

[root@docker ~]# kubectl get pods -l app=webapp -o yaml|grep podIP
podIP: 172.20.1.157
podIP: 172.20.2.219

直接通过这两个Pod的IP地址和端口号访问Tomcat服务:

#curl 172.20.2.219:8080

直接通过Pod的IP地址和端口号可以访问容器内的应用服务,但是Pod的IP地址是不可靠的,例如Pod所在的Node发生故障,Pod将被k8s重新调度到另一台Node。Pod的IP地址将发生变化,更重要的是,如果容器应用本身是分布式的部署方式,通过多个实例共同提供服务,就需要在这些实例的前端设置一个负载均衡器来实现请求的分发。kubernetes中的Service就是设计出来用于解决这些问题的核心组件。

 

4.2 创建一个Service来提供服务

      webapp-svc.yaml

apiVersion: v1

kind: Service

metadata:

  name: webapp

spec:

  ports:

  - port: 8081

    targetPort: 8080

  selector:

    app: webapp

 

Service定义中的关键字段是ports和selector。
本例中ports定义部分指定了Service所需的虚拟端口号为8081,由于与Pod容器端口号8080不一样,所以需要在通过targetPort来指定后端Pod的端口。
selector定义部分设置的是后端Pod所拥有的label: app=webapp

 

创建svc

kubectl apply -f webapp-svc.yaml

获取clusterIP

# kubectl get svc

webapp                ClusterIP   10.68.250.97    <none>        8081/TCP        5m

 

 

//访问tomcat

curl 10.68.250.97:8081

查看Endpoints

# kubectl get endpoints webapp -o yaml

 

 

apiVersion: v1

kind: Endpoints

metadata:

  name: webapp

  namespace: default

subsets:

- addresses:

  - ip: 172.20.1.157

    nodeName: 172.18.10.43

    targetRef:

      kind: Pod

      name: webapp-548444c78c-8qv24

      namespace: default

      resourceVersion: "6313006"

      uid: 7b6cf000-6728-11e9-8850-0050569a9255

  - ip: 172.20.2.219

    nodeName: 172.18.10.42

    targetRef:

      kind: Pod

      name: webapp-548444c78c-nsb2t

      namespace: default

      resourceVersion: "6313016"

      uid: 7b6d942d-6728-11e9-8850-0050569a9255

  ports:

  - port: 8080

    protocol: TCP

 

5、集群外部访问Service

5.1、将Service的端口号映射到物理机

通过设置nodePort映射到物理机,同时设置Service的类型为NodePort

     webapp-svc-nodeport.yaml

apiVersion: v1

kind: Service

metadata:

  name: webapp-nodeport

spec:

  type: NodePort

  ports:

  - port: 8090

    targetPort: 8080

    nodePort: 30090

  selector:

    app: webapp

创建这个Service

kubectl apply -f webapp-svc-nodeport.yaml

[root@docker ~]# kubectl get svc

webapp-nodeport       NodePort    10.68.156.91    <none>        8090:30090/TCP   6s

通过物理机的IP和端口访问:

http://172.18.10.41:30090/

 

6、Ingress

      我们知道Service的表现形式为IP:Port,即工作在TCP/IP层,而对于基于HTTP的服务来说,不同的URL地址经常对应到不同的后端服务或者虚拟服务器,这些应用层的转发机制仅通过kubernetes的Service机制是无法实现的。kubernetes v1.1版本中新增的Ingress资源对象将不同URL的访问请求转发到后端不同的Service,以实现HTTP层的业务路由机制。   

      使用 Ingress 进行负载分发时,Ingress Controller 将基于 Ingress 规则将客户端请求直接转发到 Service 对应的后端 Endpoint(即 Pod)上,这样会跳过 kube-proxy 的转发功能,kuber-proxy 不在起作用。如果 Ingress Controller 提供的是对外服务,则实际上实现的是边缘路由器的功能。

 

为使用Ingress,需要创建Ingress Controller(带一个默认backend服务)和Ingress策略设置来共同完成。

 

nginx-ingress.yaml文件

nginx-ingress.yaml

查看 nginx-ingress-controller

[root@docker ~]# kubectl get ds -n kube-system

NAME                       DESIRED   CURRENT   READY     UP-TO-DATE   AVAILABLE   NODE SELECTOR                   AGE

nginx-ingress-controller   3         3         0         3            0           <none>                          19m

 

Ingress的策略配置

my-web-ingress.yaml

---

apiVersion: v1

kind: Service

metadata:

  name: webapp

spec:

  type: ClusterIP

  ports:

  - port: 8081

    targetPort: 8080

  selector:

    app: webapp

---

apiVersion: extensions/v1beta1

kind: Ingress

metadata:

  name: myweb-ingress

spec:

  rules:

  - host: zly.com.cn

    http:

      paths:

      - path: /

        backend:

          serviceName: webapp

          servicePort: 8081


本地电脑C:\Windows\System32\drivers\etc  修改hosts文件,添加 : 172.18.10.41  zly.com.cn

浏览器地址输入:zly.com.cn

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值