kubernetes 核心技术-Service

kubernetes 核心技术-Service

一、Service 概述

Service 是 Kubernetes 最核心概念,通过创建 Service,可以为一组具有相同功能的容器应用提供一个统一的入口地址,并且将请求负载分发到后端的各个容器应用上。
目前一致的service有两个要求:标签匹配,就绪,如果不满足这两个,则无法匹配。

二、service 类型

2.1、ClusterIp

默认类型,自动分配一个仅 Cluster 内部可以访问的虚拟 IP。

2.2、NodePort(节点端口)

在 ClusterIP 基础上为 Service 在每台机器上绑定一个端口,这样就可以通过 <NodeIP>: NodePort 来访问该服务。

2.3、LoadBalancer

在 NodePort 的基础上,借助 cloud provider 创建一个外部负载均衡器,并将请求转发到 <NodeIP>: NodePort

2.4、ExternalName(DNS别名)

把集群外部的服务引入到集群内部来,在集群内部直接使用。没有任何类型代理被创 建,这只有 kubernetes 1.7 或更高版本的 kube-dns 才支持。
DNS别名解析流程:
我们要创建一个 ExternalName 的 service(domain),当创建完 domain 以后,我们就会得到一个域名,tomcat 只要去访问到这个域名,这个域名就会经过 coredns 解析,解析到一个结果上,这个结果可能是一个域名,也可能是一个 IP,这个域名或 IP 可能指向这个 db。
当外部的 db 的 IP 发生变化时,只要修改 domain 的别名地址就好了,例如 db 数据库原来是 bbs.aaa.com,现在是 db.aaa.com,那么只需要将 domain 的别名地址写成 db.aaa.com 即可。

三、Service 的定义

yaml 格式的 Service 定义文件。

apiVersion: v1
kind: Service
metadata:
  name: string
  namespace: string
  labels:
    name: string
  annotations:
    name: string
spec:
  selector: {}  # 选择器,用于关联 Pod
  type: string  # 可选值:ClusterIP, NodePort, LoadBalancer, ExternalName
  clusterIP: string
  sessionAffinity: string  # 可选值:None, ClientIP
  ports:
    - name: string
      protocol: string     # 可选值:TCP, UDP, SCTP
      port: int           # Service 端口
      targetPort: int     # Pod 端口
      nodePort: int       # 节点端口(当 type: NodePort 时使用)
status:
  loadBalancer:
    ingress:
      - ip: string
        hostname: string



四、使用

4.1、ClusterIP 创建

ClusterIP.yaml

apiVersion: v1
kind: Service       #service类型
metadata:
  name: myapp       #当前service的名是myapp
  namespace: default        #放到default名称空间下
spec:       #期望
  type: ClusterIP   #ClusterIP的类型
  selector:         #标签选择器,匹配下面两个标签
    app: myapp  
    release: stabel
  ports:            #端口,
  - name: http      #端口名称为http
    port: 80        #端口是80,集群访问的VIP的端口。
    targetPort: 80  #后端目标80,真实服务器的端口
#IPVS是基于NAT工作模式运行的

创建

#基于yaml文件创建ClusterIP类型的svc
kubectl apply -f ClusterIP.yaml
    
#查看已经创建的svc
kubectl get svc  

4.2、NodePort 创建

NodePort.yaml

apiVersion: v1
kind: Service
metadata:
  name: myapp-nodeport
  namespace: default        #放在default名称空间下
spec:           #期望
  type: NodePort        #当前的工作模式是NodePort方式
  selector:
    app: myapp
    release: stabel
  ports:
  - name: http      #定义的别名为http
    port: 80        #集群的端口80
    targetPort: 80  #后端的端口80

创建

kubectl apply -f 6.nodeport.yaml

#这里映射的端口,必须大于三万以上。默认就可以,不用修改,防止冲突
#在外部访问物理机的31225端口即可映射到容器内部的80端口,达到访问容器的内目的
kubectl get svc

4.3、LoadBalancer 创建

与 nodeport 的区别在于,loadbalancer 会自动在外部创建一个调度器将当前的 nodeport 端口进行流量访问,实现高可用,但是必须得借助云平台创建 LB 来向节点导流。
loadBalancer 和 nodePort 其实是同一种方式。区别在于 loadBalancer 比 nodePort 多了一步,就是可以调用 cloud provider 去创建 LB 来向节点导流。

loadbalancer.yaml

apiVersion: v1
kind: Service
metadata:
  name: myapp-loadbalancer    #服务的名称,这里是 myapp-loadbalancer。
spec:
  selector:
    app: myapp # 匹配带有相应标签的 Pods。在这个例子中,它匹配所有标签为 app: myapp 的 Pods。
  type: LoadBalancer    #为 LoadBalancer,表明我们想要的服务类型是负载均衡器。
  ports:                #服务的端口配置;
  - protocol: TCP
    port: 80            #服务内部端口,外部请求会到这个端口;
    targetPort: 8080    #Pods 上的端口,服务会将流量从内部端口转发到此端口;
    # 如果云提供商支持,也可以指定一个负载均衡器的外部端口,例如:
    # nodePort: 30000    #(可选)如果指定,这是节点上用来接收外部流量的端口

创建

kubectl apply -f loadbalancer.yaml
kubectl get svc myapp-loadbalancer

4.4、ExternalName 创建

这种类型的 Service 通过返回 CNAME 和它的值,可以将服务映射到 externalName 字段的内容( 例如:hub.aaa.com )。ExternalName Service 是 Service 的特例,它没有 selector,也没有定义任何的端口和 Endpoint。相反的,对于运行在集群外部的服务,它通过返回该外部服务的别名这种方式来提供服务。

kind: Service
apiVersion: v1
metadata:           #元数据
  name: my-service  #当前service名为my-service
  namespace: default    #放在default名称空间下
spec:
  type: ExternalName    #当前的类型为ExternalName类型
  externalName: hub.aaa.com # ExternalName的值为hub.hongfu.com

my-service.defalut.svc.cluster.local 这是在集群内可以访问到的域名,如果将他的值找dns解析,解析的应该是hub.aaa.com。
例如:
我有一个 pod,我去访问一个 web 服务,web 服务就是 hub.hongfu.com,就可以靠这个 svc 指向这个 hub.aaa.com,如果有一天我想指向 harbor,那只要 dit 将这个值指向 haobor,他就指过来了,对于 pod 来说,不需要做任何改变。
当查询主机 my-service.defalut.svc.cluster.local ( SVC_NAME.NAMESPACE.svc.cluster.local )时,集群的 DNS 服务将返回一个值 my.database.example.com 的 CNAME 记录。访问这个服务的工作方式和其他的相同,唯一不同的是重定向发生在 DNS 层,而且不会进行代理或转发。

五、Service 示例

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

apiVersion: v1
kind: ReplicationController
metadata:
  name: mywebapp
spec:
  replicas: 2
  template:
    metadata:
      name: mywebapp
      labels:
        app: mywebapp
    spec:
      containers:
        - name: mywebapp
          image: tomcat
          ports:
            - containerPort: 8080

我们可以通过 kubectl get pods -l app=mywebapp -o yaml | grep podIP 来获取 Pod 的 IP 地址和端口号来访问 Tomcat 服务,但是直接通过 Pod 的 IP 地址和端口访问应用 服务是不可靠的,因为当 Pod 所在的 Node 发生故障时, Pod 将被 kubernetes 重新调度到另一台 Node,Pod 的地址会发生改变。我们可以通过配置文件来定义 Service,再通过 kubectl create 来创建,这样可以通过 Service 地址来访问后端的 Pod.

apiVersion: v1
kind: Service
metadata:
  name: mywebAppService
spec:
  ports:
    - port: 8081
      targetPort: 8080
  selector:
    app: mywebapp

六、多端口 Service

有时一个容器应用也可能需要提供多个端口的服务,那么在 Service 的定义中也可以相应地设置为将多个端口对应到多个应用服务。

apiVersion: v1
kind: Service
metadata:
  name: mywebAppService
spec:
  ports:
    - port: 8080
      targetPort: 8080
      name: web
    - port: 8005
      targetPort: 8005
      name: management
  selector:
    app: mywebapp

七、外部服务 Service

在某些特殊环境中,应用系统需要将一个外部数据库作为后端服务进行连接,或将另一个集群或 Namespace 中的服务作为服务的后端,这时可以通过创建一个无 Label Selector 的 Service 来实现。

apiVersion: v1
kind: Service
metadata:
  name: my-service
spec:
  ports:
    - protocol: TCP
      port: 80
      targetPort: 80
---
apiVersion: v1
kind: Endpoints
metadata:
  name: my-service    # 必须与 Service 名称相同
subsets:
  - addresses:
      - ip: 10.254.74.3
    ports:
      - port: 8080

评论

暂无

添加新评论