k8s-Service

一 service概念

Kubernetes  Service 定义了这样一种抽象:一个 Pod 的逻辑分组,一种可以访问它们的策略 —— 通常称为微

服务。 这一组 Pod 能够被 Service 访问到,通常是通过 Label Selecto

 

Service能够提供负载均衡的能力,但是在使用上有以下限制:

只提供 4 层负载均衡能力,而没有 7 层功能,但有时我们可能需要更多的匹配规则来转发请求,这点上 4 层

负载均衡是不支持的

二 servce类型

Service 在 K8s 中有以下四种类型

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

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

  • LoadBalancer:在 NodePort 的基础上,借助 cloud provider(云供应商,收费的) 创建一个外部负载均衡器,并将请求转发到: NodePort

 

  • ExternalName:把集群外部的服务引入到集群内部来,在集群内部直接使用。没有任何类型代理被创建,这只有 kubernetes 1.7 或更高版本的 kube-dns 才支持

2.1 clusterip

2.1.1 概念

clusterIP 主要在每个 node 节点使用 iptables,将发向 clusterIP 对应端口的数据,转发到 kube-proxy 中。然后 kube-proxy 自己内部实现有负载均衡的方法,并可以查询到这个 service 下对应 pod 的地址和端口,进而把数据转发给对应的 pod 的地址和端口

大致架构:

svc如何和后端pod通信,是通过后端pod的标签等信息

2.2.2 实例

创建三个pod

 

apiVersion: apps/v1
kind: Deployment
metadata:
  name: myapp-deploy
  namespace: default
spec:
  replicas: 3
  selector:
    matchLabels:
      app: myapp
      release: stabel
  template:
    metadata:
      labels:
        app: myapp
        release: stabel
        env: test
    spec:
      containers:
      - name: myapp
        image: wangyanglinux/myapp:v2
        imagePullPolicy: IfNotPresent
        ports:
        - name: http
          containerPort: 80

开启svc clusterip

 

apiVersion: v1
kind: Service
metadata:
  name: myapp
  namespace: default
spec:
  type: ClusterIP
  selector:
    app: myapp
    release: stabel
  ports:
  - name: http
    port: 80
    targetPort: 80

 

查看cluseterip

 

[[email protected] yaml]# kubectl get svc
NAME         TYPE        CLUSTER-IP     EXTERNAL-IP   PORT(S)   AGE
kubernetes   ClusterIP   10.96.0.1      <none>        443/TCP   7h8m
myapp        ClusterIP   10.99.48.182   <none>        80/TCP    8m14s

 

访问 10.99.48.182 下面绑定了三个pod的ip

2.2.3 无头服务(headless service)

headless service也属于clausterip的一种,不会分配clusterip,也不会进行负载和路由

apiVersion: v1
kind: Service
metadata:
  name: nginx-service 
  labels:
    app: nginx
spec:
  selector:
    app: nginx
  clusterIP: "None"
  ports:
  - port: 80
    targetPort: 80

 

 

2.2 nodeport

nodePort 的原理在于在 node 上开了一个端口,将向该端口的流量导入到 kube-proxy,然后由 kube-proxy 进一步到给对应的 pod

实例:

 

apiVersion: v1
kind: Service
metadata:
  name: myapp
  namespace: default
spec:
  type: NodePort
  selector:
    app: myapp
    release: stabel
  ports:
  - name: http
    port: 80
    targetPort: 80

2.3 ExternalName

这种类型的 Service 通过返回 CNAME 和它的值,可以将服务映射到 externalName 字段的内容( 例如:

hub.atguigu.com )。ExternalName Service 是 Service 的特例,它没有 selector,也没有定义任何的端口和

Endpoint。相反的,对于运行在集群外部的服务,它通过返回该外部服务的别名这种方式来提供服务

实例;

 

apiVersion: v1
kind: Service
metadata:
  name: myapp-headless
  namespace: default
spec:
  selector:
    app: myapp
  clusterIP: "None"
  ports:
  - port: 80
    targetPort: 80

查看:

验证:

dig -t A my-service-1.default.svc.cluster.local. @10.244.2.9

 

dig -t A my-service-1.default.svc.cluster.local. @10.244.2.9
; <<>> DiG 9.11.4-P2-RedHat-9.11.4-9.P2.el7 <<>> -t A my-service-1.default.svc.cluster.local. @10.244.2.9
;; global options: +cmd
;; Got answer:
;; WARNING: .local is reserved for Multicast DNS
;; You are currently testing what happens when an mDNS query is leaked to DNS
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 36528
;; flags: qr aa rd; QUERY: 1, ANSWER: 1, AUTHORITY: 0, ADDITIONAL: 1
;; WARNING: recursion requested but not available
;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags:; udp: 4096
;; QUESTION SECTION:
;my-service-1.default.svc.cluster.local. IN A
;; ANSWER SECTION:
my-service-1.default.svc.cluster.local. 30 IN CNAME hub.atguigu.com.
;; Query time: 36 msec
;; SERVER: 10.244.2.9#53(10.244.2.9)
;; WHEN: 二 3月 17 21:13:47 CST 2020
;; MSG SIZE  rcvd: 134

 

 

三 注意

svc必须和pod在同一个命名空间里面,否则不会自动绑定