Service 的实现

服务(Service)

将在集群中运行的应用通过同一个面向外界的端点公开出去,即使工作负载分散于多个后端也完全可行。
Kubernetes 中 Service 是 将运行在一个或一组 Pod 上的网络应用程序公开为网络服务的方法。

Kubernetes 中 Service 的一个关键目标是无需修改现有应用以使用某种不熟悉的服务发现机制。 可以在 Pod 集合中运行代码,无论该代码是为云原生环境设计的,还是被容器化的老应用。可以使用 Service 让一组 Pod 可在网络上访问,这样客户端就能与之交互。

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

每个 Pod 会获得属于自己的 IP 地址(Kubernetes 期待网络插件来保证这一点)。 对于集群中给定的某个 Deployment,这一刻运行的 Pod 集合可能不同于下一刻运行该应用的 Pod 集合。

Kubernetes 中的 Service

Service API 是 Kubernetes 的组成部分,它是一种抽象,帮助你将 Pod 集合在网络上公开出去。 每个 Service 对象定义端点的一个逻辑集合(通常这些端点就是 Pod)以及如何访问到这些 Pod 的策略。

考虑一个无状态的图像处理后端,其中运行 3 个副本(Replicas)。 这些副本是可互换的 —— 前端不需要关心它们调用的是哪个后端。 即便构成后端集合的实际 Pod 可能会发生变化,前端客户端不应该也没必要知道这些, 而且它们也不必亲自跟踪后端的状态变化。Service 抽象使这种解耦成为可能。

如果你的工作负载使用 HTTP 通信,你可能会选择使用 Ingress 来控制 Web 流量如何到达该工作负载。Ingress 不是一种 Service,但它可用作集群的入口点。 Ingress 能让你将路由规则整合到同一个资源内,这样你就能将工作负载的多个组件公开出去, 这些组件使用同一个侦听器,但各自独立地运行在集群中。

用于 Kubernetes 的 Gateway API 能够提供 Ingress 和 Service 所不具备的一些额外能力。 Gateway 是使用 CustomResourceDefinitions 实现的一系列扩展 API。 你可以添加 Gateway 到你的集群中,之后就可以使用它们配置如何访问集群中运行的网络服务

云原生服务发现

如果你想要在自己的应用中使用 Kubernetes API 进行服务发现,可以查询 API 服务器, 寻找匹配的 EndpointSlice 对象。 只要 Service 中的 Pod 集合发生变化,Kubernetes 就会为其更新 EndpointSlice。

对于非本地应用,Kubernetes 提供了在应用和后端 Pod 之间放置网络端口或负载均衡器的方法。

无论采用那种方式,你的负载都可以使用这里的服务发现机制找到希望连接的目标。

服务类型

对一些应用的某些部分(如前端),你可能希望将其公开于某外部 IP 地址, 也就是可以从集群外部访问的某个地址。

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

可用的 type 值及其行为有:

ClusterIP
通过集群的内部 IP 公开 Service,选择该值时 Service 只能够在集群内部访问。 这也是你没有为 Service 显式指定 type 时使用的默认值。 你可以使用 Ingress 或者 Gateway API 向公共互联网公开服务。
NodePort
通过每个节点上的 IP 和静态端口(NodePort)公开 Service。 为了让 Service 可通过节点端口访问,Kubernetes 会为 Service 配置集群 IP 地址, 相当于你请求了 type: ClusterIP 的 Service。
LoadBalancer
使用云平台的负载均衡器向外部公开 Service。Kubernetes 不直接提供负载均衡组件; 你必须提供一个,或者将你的 Kubernetes 集群与某个云平台集成。
ExternalName
将服务映射到 externalName 字段的内容(例如,映射到主机名 api.foo.bar.example)。 该映射将集群的 DNS 服务器配置为返回具有该外部主机名值的 CNAME 记录。 集群不会为之创建任何类型代理。

服务 API 中的 type 字段被设计为层层递进的形式 - 每层都建立在前一层的基础上。 但是,这种层层递进的形式有一个例外。 你可以在定义 LoadBalancer Service 时禁止负载均衡器分配 NodePort

ClusterIP

[root@master svc]# kubectl get po -l app=nginx-cx -owide 
NAME                         READY   STATUS    RESTARTS   AGE    IP               NODE     NOMINATED NODE   READINESS GATES
nginx-cx1-5c86fddfc5-4wdvg   1/1     Running   0          4h4m   172.16.84.190    node-1   <none>           <none>
nginx-cx1-5c86fddfc5-8qgqb   1/1     Running   0          4h4m   172.16.167.141   node     <none>           <none>
nginx-cx1-5c86fddfc5-jgtt5   1/1     Running   0          4h4m   172.16.247.37    node-2   <none>           <none>


[root@master svc]# cat svc.yaml 
apiVersion: v1
kind: Service
metadata: 
  name: nginx-cx1
spec:
  type: ClusterIP
  #sessionAffinity: ClientIP
  ports:
  - port: 80
    targetPort: 80
  selector:
    app: nginx-cx
[root@master svc]# kubectl apply -f svc.yaml 
service/nginx-cx1 created
[root@master svc]# kubectl describe svc nginx-cx1 
Name:              nginx-cx1
Namespace:         default
Labels:            <none>
Annotations:       <none>
Selector:          app=nginx-cx
Type:              ClusterIP
IP Family Policy:  SingleStack
IP Families:       IPv4
IP:                10.107.129.30
IPs:               10.107.129.30
Port:              <unset>  80/TCP
TargetPort:        80/TCP
Endpoints:         172.16.167.141:80,172.16.247.37:80,172.16.84.190:80
Session Affinity:  None
Events:            <none>

  NodePort

[root@master svc]# cat  svc-1.yaml 
apiVersion: v1
kind: Service
metadata: 
  name: nginx-ro
spec:
  type: NodePort
  #sessionAffinity: ClientIP
  ports:
  - port: 80
    targetPort: 80
    nodePort: 30080
  selector:
    app: nginx-ro
[root@master svc]# kubectl get po -l app=nginx-ro -owide 
NAME                                   READY   STATUS    RESTARTS   AGE     IP              NODE     NOMINATED NODE   READINESS GATES
nginx-deployment-ro-56d78cc78d-5sskn   1/1     Running   0          5h32m   172.16.84.188   node-1   <none>           <none>
nginx-deployment-ro-56d78cc78d-77m8k   1/1     Running   0          5h32m   172.16.247.35   node-2   <none>           <none>
nginx-deployment-ro-56d78cc78d-kvhsw   1/1     Running   0          5h32m   172.16.84.187   node-1   <none>           <none>
[root@master svc]# kubectl apply -f svc-1.yaml 
service/nginx-ro created
[root@master svc]# kubectl describe svc 
kubernetes          nginx-cx1           nginx-ro            riodseconds-exec    riodseconds-exec-1  
[root@master svc]# kubectl describe svc nginx-ro 
Name:                     nginx-ro
Namespace:                default
Labels:                   <none>
Annotations:              <none>
Selector:                 app=nginx-ro
Type:                     NodePort
IP Family Policy:         SingleStack
IP Families:              IPv4
IP:                       10.107.71.223
IPs:                      10.107.71.223
Port:                     <unset>  80/TCP
TargetPort:               80/TCP
NodePort:                 <unset>  30080/TCP
Endpoints:                172.16.247.35:80,172.16.84.187:80,172.16.84.188:80
Session Affinity:         None
External Traffic Policy:  Cluster
Events:                   <none>

  externalName 

[root@master dpment]# cat dpment.yaml 
apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx-deployment
  namespace: qa
  labels:
    app: nginx
spec:
  replicas: 3
  selector:
    matchLabels:
      app: nginx
  template:
    metadata:
      labels:
        app: nginx
    spec:
      containers:
      - name: nginx
        image: nginx:1.14.2
        ports:
        - containerPort: 80

---
apiVersion: v1
kind: Service
metadata:
  name: nginx-svc
  namespace: qa
spec:
  selector:
    app: nginx
  ports:
  - port: 80
    targetPort: 80
[root@master dpment]# kubectl apply -f dpment.yaml 
deployment.apps/nginx-deployment created
service/nginx-svc created
[root@master dpment]# kubectl get po -n qa
NAME                                READY   STATUS    RESTARTS   AGE
nginx-deployment-86dcfdf4c6-2lj7t   1/1     Running   0          14s
nginx-deployment-86dcfdf4c6-bbnbm   1/1     Running   0          14s
nginx-deployment-86dcfdf4c6-k6w7l   1/1     Running   0          14s
[root@master dpment]# kubectl get svc -n qa
NAME        TYPE        CLUSTER-IP      EXTERNAL-IP   PORT(S)   AGE
nginx-svc   ClusterIP   10.108.11.102   <none>        80/TCP    20s
[root@master dpment]# kubectl describe svc -n qa
Name:              nginx-svc
Namespace:         qa
Labels:            <none>
Annotations:       <none>
Selector:          app=nginx
Type:              ClusterIP
IP Family Policy:  SingleStack
IP Families:       IPv4
IP:                10.108.11.102
IPs:               10.108.11.102
Port:              <unset>  80/TCP
TargetPort:        80/TCP
Endpoints:         172.16.247.38:80,172.16.84.129:80,172.16.84.191:80
Session Affinity:  None
Events:            <none>
[root@master svc]# cat svc-2.yaml 
apiVersion: v1
kind: Service
metadata: 
  name: nginx-ro
spec:
  type: ExternalName
  externalName: nginx-svc.qa.svc.cluster.local
  #sessionAffinity: ClientIP
  ports:
  - port: 80
    targetPort: 80
    nodePort: 30080
  selector:
    app: nginx-ro
[root@master svc]# kubectl apply -f svc-2.yaml 
service/nginx-ro configured
[root@master svc]# kubectl describe svc nginx-ro 
Name:              nginx-ro
Namespace:         default
Labels:            <none>
Annotations:       <none>
Selector:          app=nginx-ro
Type:              ExternalName
IP Families:       <none>
IP:                
IPs:               <none>
External Name:     nginx-svc.qa.svc.cluster.local
Port:              <unset>  80/TCP
TargetPort:        80/TCP
Endpoints:         172.16.247.35:80,172.16.84.187:80,172.16.84.188:80
Session Affinity:  None
Events:            <none>
[root@master ~]# kubectl run -it  test --image=busybox --restart=Never -- /bin/sh
If you don't see a command prompt, try pressing enter.
/ # nslookup nginx-svc.qa.svc.cluster.local
Server:		10.96.0.10
Address:	10.96.0.10:53


Name:	nginx-svc.qa.svc.cluster.local
Address: 10.108.11.102

/ # curl nginx-svc.qa.svc.cluster.local
/bin/sh: curl: not found
/ # wget nginx-svc.qa.svc.cluster.local
Connecting to nginx-svc.qa.svc.cluster.local (10.108.11.102:80)
saving to 'index.html'
index.html           100% |**********************************************************************|   612  0:00:00 ETA
'index.html' saved
/ # exit
[root@master ~]# kubectl delete po test 
pod "test" deleted
[root@master ~]# kubectl run -it  test --image=busybox --restart=Never -- /bin/sh
If you don't see a command prompt, try pressing enter.
/ # wget nginx-cx2
Connecting to nginx-cx2 (10.108.11.102:80)
saving to 'index.html'
index.html           100% |**********************************************************************|   612  0:00:00 ETA
'index.html' saved

  

 

posted @ 2024-10-17 18:38  烟雨楼台,行云流水  阅读(9)  评论(0编辑  收藏  举报