k8s 服务发现和负载均衡:Service

您所在的位置:网站首页 k8s的service负载均衡策略 k8s 服务发现和负载均衡:Service

k8s 服务发现和负载均衡:Service

2024-04-29 08:05| 来源: 网络整理| 查看: 265

四层负载均衡 Service 在 kubernetes 中,Pod 是有生命周期的,如果 Pod 重启它的 IP 很有可能会发生变化。如果我们的服务都是将 Pod 的 IP 地址写死,Pod 挂掉或者重启,和刚才重启的 pod 相关联的其他服务将会找不 到它所关联的 Pod,为了解决这个问题,在 kubernetes 中定义了 service 资源对象,Service 定义了 一个服务访问的入口,客户端通过这个入口即可访问服务背后的应用集群实例,service 是一组 Pod 的 逻辑集合,这一组 Pod 能够被 Service 访问到,通常是通过 Label Selector 实现的。

1、pod ip 经常变化,service 是 pod 的代理,我们客户端访问,只需要访问 service,就会把请求 代理到 Pod

2、pod ip 在 k8s 集群之外无法访问,所以需要创建 service,这个 service 可以在 k8s 集群外访 问的。

Service 概述

service 是一个固定接入层,客户端可以通过访问 service 的 ip 和端口访问到 service 关联的后端pod,这个 service 工作依赖于在 kubernetes 集群之上部署的一个附件,就是 kubernetes 的 dns 服 务(不同 kubernetes 版本的 dns 默认使用的也是不一样的,1.11 之前的版本使用的是 kubeDNs,较 新的版本使用的是 coredns),service 的名称解析是依赖于 dns 附件的,因此在部署完 k8s 之后需要再部署 dns 附件,kubernetes 要想给客户端提供网络功能,需要依赖第三方的网络插件(flannel, calico 等)。每个 K8s 节点上都有一个组件叫做 kube-proxy,kube-proxy 这个组件将始终监视着 apiserver 中有关 service 资源的变动信息,需要跟 master 之上的 apiserver 交互,随时连接到 apiserver 上获取任何一个与 service 资源相关的资源变动状态,这种是通过 kubernetes 中固有的一种 请求方法 watch(监视)来实现的,一旦有 service 资源的内容发生变动(如创建,删除),kube- proxy 都会将它转化成当前节点之上的能够实现 service 资源调度,把我们请求调度到后端特定的 pod 资源之上的规则,这个规则可能是 iptables,也可能是 ipvs,取决于 service 的实现方式。

Service 工作原理

k8s 在创建 Service 时,会根据标签选择器 selector(lable selector)来查找 Pod,据此创建与

Service 同名的 endpoint 对象,当 Pod 地址发生变化时,endpoint 也会随之发生变化,service 接 收前端 client 请求的时候,就会通过 endpoint,找到转发到哪个 Pod 进行访问的地址。(至于转发到哪 个节点的 Pod,由负载均衡 kube-proxy 决定)

kubernetes 集群中有三类 IP 地址

1、Node Network(节点网络):物理节点或者虚拟节点的网络,如 ens33 接口上的网路地址 

~]# ip addr

2: ens33:  mtu 1500 qdisc pfifo_fast state UP

link/ether 00:0c:29:87:60:d5 brd ff:ff:ff:ff:ff:ff

inet 192.168.1.63/24 brd 192.168.1.255 scope global noprefixroute ens33

2、Pod network(pod 网络),创建的 Pod 具有的 IP 地址

]# kubectl get pods -o wide

NAME READY STATUS IP NODE

frontend-h78gw 1/1 Running 

10.244.187.76   god62

Node Network 和 Pod network 这两种网络地址是我们实实在在配置的,其中节点网络地址是配

置在节点接口之上,而 pod 网络地址是配置在 pod 资源之上的,因此这些地址都是配置在某些设备之上 的,这些设备可能是硬件,也可能是软件模拟的

3、Cluster Network(集群地址,也称为 service network),这个地址是虚拟的地址(virtual ip),没有配置在某个接口上,只是出现在 service 的规则当中。

kubectl get svc

NAME        TYPE        CLUSTER-IP      EXTERNAL-IP  PORT(S)          AGE

kubernetes  ClusterIP  10.96.0.1                443/TCP          21d

nginx        NodePort    10.105.245.139          3000:31003/TCP  7d23h

#查看定义 Service 资源需要的字段有哪些?

kubectl explain service

FIELDS:

  apiVersion  .         #service 资源使用的 api 组

kind                       #创建的资源类型

metadata           #定义元数据

spec

#查看 service 的 spec 字段如何定义?

clusterIP .   #动态分配的地址,也可以自己在创建的时候指定,创建之后就改不了了

ports  #定义 service 端口,用来和后端 pod 建立联系 

publishNotReadyAddresses

selector  #通过标签选择器选择关联的 pod 有哪些

sessionAffinity          

sessionAffinityConfig 

#service 在实现负载均衡的时候还支持 sessionAffinity,sessionAffinity 什么意思?会话联系,默认是 none,随机调度的(基于 iptables 规则调度的);如果我们定义sessionAffinity 的 client ip,那就表示把来自同一客户端的 IP 请求调度到同一个 pod 上

type  #定义 service 的类型 Service 的四种类型

kubectl explain service.spec.type

DESCRIPTION:

type determines how the Service is exposed. Defaults to 

ClusterIP. Valid options are ExternalName, ClusterIP, NodePort, and LoadBalancer.

1、ExternalName: 适用于 k8s 集群内部容器访问外部资源,它没有 selector,也没有定义任何的端口和Endpoint。

以下 Service 定义的是将 prod 名称空间中的 my-service 服务映射到 my.database.example.com

kind: Service 

apiVersion: v1 

metadata:

name: my-service

namespace: prod spec:

type: ExternalName

externalName: my.database.example.com

当查询主机 my-service.prod.svc.cluster.local 时,群集 DNS 将返回值为my.database.example.com 的 CNAME 记录。

2、ClusterIP: 通过 k8s 集群内部 IP 暴露服务,选择该值,服务只能够在集群内部访问,这也是默认的 ServiceType。

3、NodePort:

通过每个 Node 节点上的 IP 和静态端口暴露 k8s 集群内部的服务。通过请求 :可以把请求代理到内部的 pod。Client----->NodeIP:NodePort---- ->Service Ip:ServicePort----->PodIP:ContainerPort。

4、LoadBalancer:

使用云提供商的负载局衡器,可以向外部暴露服务。外部的负载均衡器可以路由到 NodePort 服务 和 ClusterIP 服务。

Service 的端口 kubectl explain service.spec.ports

name  #定义端口的名字 

nodePort

|#宿主机上映射的端口,比如一个 Web 应用需要被 k8s 集群之外的其他用户访问,那么需要配置 type=NodePort,若配置 nodePort=30001,那么其他机器就可以通过浏览器访问 scheme://k8s 集 群中的任何一个节点 ip:30001 即可访问到该服务,例如 http://192.168.1.63:30001。如果在 k8s 中 部署 MySQL 数据库,MySQL 可能不需要被外界访问,只需被内部服务访问,那么就不需要设置 NodePort

port -required- #service 的端口,这个是 k8s 集群内部服务可访问的端口 

protocol  

targetPort.  

# targetPort 是 pod 上的端口,从 port 和 nodePort 上来的流量,经过 kube-proxy 流入到后端 pod 的 targetPort 上,最后进入容器。与制作容器时暴露的端口一致(使用 DockerFile 中的 EXPOSE),例如官方的 nginx 暴露 80 端口。

创建 Service:type 类型是 ClusterIPdocker load -I nginx.tar.gz

cat pod_test.yaml

apiVersion: apps/v1

kind:  Deployment

metadata:

  name: my-nginx

spec:

  selector:

    matchLabels:

      run: my-nginx

  replicas: 2

  template:

    metadata:

      labels:

        run: my-nginx

    spec:

      containers:

      - image: nginx

        name: my-nginx

        ports:

        - containerPort: 80  #pod容器中暴露的端口

kubectl apply -f pod_test.yaml

kubectl get pods -l run=my-nginx -o wide

curl ip 看主页

Welcome to nginx!

kubectl exec -it my-nginx-5b56ccd65f-cwqbg -- /bin/bash

需要注意的是,pod 虽然定义了容器端口,但是不会使用调度到该节点上的 80 端口,也不会使用任 何特定的 NAT 规则去路由流量到 Pod 上。 这意味着可以在同一个节点上运行多个 Pod,使用相同的容 器端口,并且可以从集群中任何其他的 Pod 或节点上使用 IP 的方式访问到它们。

误删除其中一个 Pod:

kubectl delete pods my-nginx-5b56ccd65f-cwqbg

kubectl get pods -l run=my-nginx -o wide

kubectl get pods -l run=my-nginx -o wide

NAME                        READY  STATUS    RESTARTS  AGE  IP              NODE      NOMINATED NODE  READINESS GATES

my-nginx-5b56ccd65f-d7j7v  1/1    Running  0          21s  10.244.187.103  god62           

my-nginx-5b56ccd65f-h2kjl  1/1    Running  0          14m  10.244.209.135  god64           

通过上面可以看到重新生成了一个 pod :my-nginx-5b56ccd65f-7xzr4,ip 是 10.244.187.102,在 k8s 中创建 pod,如果 pod 被删除了,重新生成的 pod ip 地址会发生变化,所 以需要在 pod 前端加一个固定接入层。接下来创建 service:

创建 Service cat service_test.yaml

apiVersion: v1

kind: Service

metadata:

  name: my-nginx

  labels:

    run: my-nginx

spec:

  type: ClusterIP

  ports:

  - port: 80             #service 的端口,暴露给 k8s 集群内部服务访问

    protocol: TCP       #通过ip和端口代理

    targetPort: 80      #pod 容器中定义的端口

  selector:

    run: my-nginx       #选择拥有 run=my-nginx 标签的 pod

上述 yaml 文件将创建一个 Service,具有标签 run=my-nginx 的 Pod,目标 TCP 端口 80,并 且在一个抽象的 Service 端口(targetPort:容器接收流量的端口;port:抽象的 Service 端口,可 以使任何其它 Pod 访问该 Service 的端口)上暴露。

kubectl apply -f service_test.yaml

kubectl get svc -l run=my-nginx

NAME      TYPE        CLUSTER-IP      EXTERNAL-IP  PORT(S)  AGE

my-nginx  ClusterIP  10.102.215.115          80/TCP    3m34s

#在 k8s 控制节点访问 service 的 ip:端口就可以把请求代理到后端 pod 

curl 10.102.215.115:80

Welcome to nginx!

#通过上面可以看到请求 service IP:port 跟直接访问 pod ip:port 看到的结果一样,这就说明 service 可以把请求代理到它所关联的后端 pod

注意:上面的 10.102.215.115:80 地址只能是在 k8s 集群内部可以访问,在外部无法访问,比方说

我们想要通过浏览器访问,那么是访问不通的,如果想要在 k8s 集群之外访问,是需要把 service type 类型改成 nodePort 的

#通过上面可以看到请求 service IP:port 跟直接访问 pod ip:port 看到的结果一样,这就说明 service 可以把请求代理到它所关联的后端 pod

注意:上面的 10.102.215.115:80 地址只能是在 k8s 集群内部可以访问,在外部无法访问,比方说

我们想要通过浏览器访问,那么是访问不通的,如果想要在 k8s 集群之外访问,是需要把 service type 类型改成 nodePort 的

#查看 service 详细信息

kubectl describe svc my-nginx

kubectl get ep my-nginx

NAME      ENDPOINTS                            AGE

my-nginx  10.244.187.106:80,10.244.209.138:80  6m8s

service 可以对外提供统一固定的 ip 地址,并将请求重定向至集群中的 pod。其中“将请求重定向 至集群中的 pod”就是通过 endpoint 与 selector 协同工作实现。selector 是用于选择 pod,由 selector 选择出来的 pod 的 ip 地址和端口号,将会被记录在 endpoint 中。endpoint 便记录了所有 pod 的 ip 地址和端口号。当一个请求访问到 service 的 ip 地址时,就会从 endpoint 中选择出一个 ip地址和端口号,然后将请求重定向至 pod 中。具体把请求代理到哪个 pod,需要的就是 kube-proxy 的 轮询实现的。service 不会直接到 pod,service 是直接到 endpoint 资源,就是地址加端口,再由 endpoint 再关联到 pod。

service 只要创建完成,我们就可以直接解析它的服务名,每一个服务创建完成后都会在集群 dns 中 动态添加一个资源记录,添加完成后我们就可以解析了,资源记录格式是:

SVC_NAME.NS_NAME.DOMAIN.LTD. 服务名.命名空间.域名后缀

集群默认的域名后缀是 

svc.cluster.local.

就像我们上面创建的 my-nginx 这个服务,它的完整名称解析就是 my-nginx.default.svc.cluster.local

# kubectl exec -it my-nginx-5b56ccd65f-7xzr4 -- /bin/bash 

root@my-nginx-5b56ccd65f-7xzr4:/# curl my-nginx.default.svc.cluster.local

Welcome to nginx!

创建 Service:type 类型是 NodePort cat pod_nodeport.yaml

apiVersion: apps/v1

kind: Deployment

metadata:

  name: my-nginx-nodeport

spec:

  selector:

    matchLabels:

      run: my-nginx-nodeport

  replicas: 2

  template:

    metadata:

      labels:

        run: my-nginx-nodeport

    spec:

      containers:

      - name: my-nginx-nodeport-contauber

        image: nginx

        ports:

        - containerPort: 80

kubectl apply -f pod_nodeport.yaml

#查看 pod 是否创建成功

kubectl get pods -l run=my-nginx-nodeport

NAME                                READY  STATUS    RESTARTS  AGE

my-nginx-nodeport-6cb5fff859-9c4lm  1/1    Running  0          54s

my-nginx-nodeport-6cb5fff859-lqdnc  1/1    Running  0          54s

创建 service,代理 pod

cat service_nodeport.yaml

apiVersion: v1

kind: Service

metadata:

  name: my-nginx-nodeport

  labels:

    run: my-nginx-nodeport

spec:

  type: NodePort

  ports:

  - port: 80

    protocol: TCP

    targetPort: 80

  selector: 30380

    run: my-nginx-nodeport

kubectl apply -f service_nodeport.yaml

#查看刚才创建的 service

kubectl get svc -l run=my-nginx-nodeport

NAME                TYPE      CLUSTER-IP      EXTERNAL-IP  PORT(S)        AGE

my-nginx-nodeport  NodePort  10.100.132.187          80:30380/TCP  2m36s

curl 10.100.132.187

Welcome to nginx!

10.100.132.187是 k8s 集群内部的 service ip 地址,只能在 k8s 集群内部访问,在集群外无法访问。

#在集群外访问 service

curl 192.168.172.163:30380

过程就是192.168.172.163:30380。---> 10.100.132.187:80(kubectl get svc -l run=my-nginx-nodeport)----> pod ip:container port   随机生成的如下

创建 Service:type 类型是 ExternalName

应用场景:跨名称空间访问

需求:default 名称空间下的 client 服务想要访问 nginx-ns 名称空间下的 nginx-svc 服务

docker load -I busybox.tar.gz.   工作节点

cat client.yaml

apiVersion: apps/v1

kind: Deployment

metadata:

  name: client

spec:

  replicas: 1

  selector:

    matchLabels:

      app: busybox

  template:

    metadata:

      labels:

        app: busybox

    spec:

      containers:

      - name: busybox

        image: busybox

        command: ["/bin/sh","-c","sleep 36000"]

kubectl apply -f client.yaml

 #. cat client_svc.yaml

apiVersion: v1

kind: Service

metadata:

  name: client-svc

spec:

  type: ExternalName

  externalName: nginx-svc.nginx-ns.svc.cluster.local

  ports:

  - name: http

    port: 80

    targetPort: 80

#该文件中指定了到 nginx-svc 的软链,让使用者感觉就好像调用自己命名空间的服务一样。 #查看 pod 是否正常运行

kubectl get pods | grep client-76b6556d97-xqkzk

client-76b6556d97-xqkzk              1/1    Running    0          64m

kubectl apply -f client_svc.yaml

kubectl apply -f client_svc.yaml

#创建名称空间

kubectl create ns nginx-ns

cat server_nginx.yaml

apiVersion: apps/v1

kind: Deployment

metadata:

  name: nginx

  namespace: nginx-ns

spec:

  replicas: 1

  selector:

    matchLabels:

      app: nginx

  template:

    metadata:

      labels:

        app: nginx

    spec:

      containers:

      - name: nginx

        image: nginx

        imagePullPolicy: IfNotPresent

kubectl apply -f server_nginx.yaml

#查看 pod 是否创建成功

kubectl get pods -n nginx-ns

NAME                    READY  STATUS    RESTARTS  AGE

nginx-7cf7d6dbc8-glps2  1/1    Running  0          79m

cat nginx_svc.yaml

apiVersion: v1

kind: Service

metadata:

  name: nginx-svc

  namespace: nginx-ns

spec:

  selector:

    app: nginx

  ports:

    - name: http

      protocol: TCP

      port: 80

      targetPort: 80

kubectl apply -f nginx_svc.yaml

#登录到 client pod

kubectl exec -it client-76b6556d97-xqkzk -- /bin/sh

wget -q -O - client-svc.default.svc.cluster.local

wget -q -O - nginx-svc.nginx-ns.svc.cluster.local

k8s 映射外部服务分享

场景 1:k8s 集群引用外部的 mysql 数据库

在 god62 上安装 mysql 数据库:

yum install mariadb-server.x86_64 -y

systemctl start mariadb

cat mysql_service.yaml

apiVersion: v1

kind:  Service

metadata:

  name: mysql

pec:kubectl apply -f mysql_service.yaml

  type: ClusterIP

  ports:

  - port: 3306

kubectl apply -f mysql_service.yaml

kubectl get svc | grep mysql

mysql              ClusterIP      10.109.176.8                                    3306/TCP        49s

kubectl describe svc mysql

Name: mysql

Namespace:        default

Labels:           

Annotations:     

Selector:         

Type:              ClusterIP

IP Families:     

IP:                10.109.176.8

IPs:              10.109.176.8

Port:                3306/TCP

TargetPort:        3306/TCP

Endpoints:           #还没有endpoint

Session Affinity:  None

Events:           

cat mysql_endpoint.yaml

apiVersion: v1

kind: Endpoints

metadata:

  name: mysql

subsets:

- addresses:

    - ip: 192.168.172.162

  ports:

    - protocol: TCP

      port: 3306

kubectl describe svc mysql

Name:              mysql

Namespace:        default

Labels:           

Annotations:     

Selector:         

Type:              ClusterIP

IP Families:     

IP:                10.109.176.8

IPs:              10.109.176.8

Port:                3306/TCP

TargetPort:        3306/TCP

Endpoints:        192.168.172.162:3306     #这个 定义的外部数据库,name与之对应

Session Affinity:  None

Events:           

上面配置就是将外部 IP 地址和服务引入到 k8s 集群内部,由 service 作为一个代理来达到能够访问

外部服务的目的。

Service 代理:kube-proxy 组件详解

Kubernetes service 只是把应用对外提供服务的方式做了抽象,真正的应用跑在 Pod 中的container 里,我们的请求转到 kubernetes nodes 对应的 nodePort 上,那么 nodePort 上的请求是如何进一步转到提供后台服务的 Pod 的呢? 就是通过 kube-proxy 实现的:

kube-proxy 部署在 k8s 的每一个 Node 节点上,是 Kubernetes 的核心组件,我们创建一个 service 的时候,kube-proxy 会在 iptables 中追加一些规则,为我们实现路由与负载均衡的功能。在 k8s1.8 之前,kube-proxy 默认使用的是 iptables 模式,通过各个 node 节点上的 iptables 规则来实 现 service 的负载均衡,但是随着 service 数量的增大,iptables 模式由于线性查找匹配、全量更新等 特点,其性能会显著下降。从 k8s 的 1.8 版本开始,kube-proxy 引入了 IPVS 模式,IPVS 模式与 iptables 同样基于 Netfilter,但是采用的 hash 表,因此当 service 数量达到一定规模时,hash 查表 的速度优势就会显现出来,从而提高 service 的服务性能。

service 是一组 pod 的服务抽象,相当于一组 pod 的 LB,负责将请求分发给对应的 pod。service 会为这个 LB 提供一个 IP,一般称为 cluster IP。kube-proxy 的作用主要是负责 service 的实现,具体 来说,就是实现了内部从 pod 到 service 和外部的从 node port 向 service 的访问。

1、kube-proxy 其实就是管理 service 的访问入口,包括集群内 Pod 到 Service 的访问和集群外访问 service。

2、kube-proxy 管理 sevice 的 Endpoints,该 service 对外暴露一个 Virtual IP,也可以称为是 Cluster IP, 集群内通过访问这个 Cluster IP:Port 就能访问到集群内对应的 serivce 下的 Pod。

kube-proxy 三种工作模式 1、Userspace 方式:

Client Pod 要访问 Server Pod 时,它先将请求发给内核空间中的 service iptables 规则,由它再将请求转给监听在指定套接字上的 kube-proxy 的端口,kube-proxy 处理完请求,并分发请求到指定 Server Pod 后,再将请求转发给内核空间中的 service ip,由 service iptables 将请求转给各个节点中 的 Server Pod。

这个模式有很大的问题,客户端请求先进入内核空间的,又进去用户空间访问 kube-proxy,由 kube-proxy 封装完成后再进去内核空间的 iptables,再根据 iptables 的规则分发给各节点的用户空间 的 pod。由于其需要来回在用户空间和内核空间交互通信,因此效率很差。在 Kubernetes 1.1 版本之 前,userspace 是默认的代理模型。

2、iptables 方式:

客户端 IP 请求时,直接请求本地内核 service ip,根据 iptables 的规则直接将请求转发到到各 pod 上,因为使用 iptable NAT 来完成转发,也存在不可忽视的性能损耗。另外,如果集群中存上万的 Service/Endpoint,那么 Node 上的 iptables rules 将会非常庞大,性能还会再打折

iptables 代理模式由 Kubernetes 1.1 版本引入,自 1.2 版本开始成为默认类型。

3、ipvs 方式:

Kubernetes 自 1.9-alpha 版本引入了 ipvs 代理模式,自 1.11 版本开始成为默认设置。客户端

请求时到达内核空间时,根据 ipvs 的规则直接分发到各 pod 上。kube-proxy 会监视 KubernetesService 对象和 Endpoints,调用 netlink 接口以相应地创建 ipvs 规则并定期与 KubernetesService 对象和 Endpoints 对象同步 ipvs 规则,以确保 ipvs 状态与期望一致。访问服务 时,流量将被重定向到其中一个后端 Pod。与 iptables 类似,ipvs 基于 netfilter 的 hook 功能,但 使用哈希表作为底层数据结构并在内核空间中工作。这意味着 ipvs 可以更快地重定向流量,并且在同步 代理规则时具有更好的性能。此外,ipvs 为负载均衡算法提供了更多选项,例如:

rr:轮询调度 

lc:最小连接数 

dh:目标哈希 

sh:源哈希 

sed:最短期望延迟 

nq:不排队调度

如果某个服务后端 pod 发生变化,标签选择器适应的 pod 又多一个,适应的信息会立即反映到 apiserver 上,而 kube-proxy 一定可以 watch 到 etc 中的信息变化,而将它立即转为 ipvs 或者 iptables 中的规则,这一切都是动态和实时的,删除一个 pod 也是同样的原理。如图:

注:

以上不论哪种,kube-proxy 都通过 watch 的方式监控着 apiserver 写入 etcd 中关于 Pod 的最 新状态信息,它一旦检查到一个 Pod 资源被删除了或新建了,它将立即将这些变化,反应再 iptables 或 ipvs 规则中,以便 iptables 和 ipvs 在调度 Clinet Pod 请求到 Server Pod 时,不会出现 Server Pod 不存在的情况。自 k8s1.1 以后,service 默认使用 ipvs 规则,若 ipvs 没有被激活,则降级使用 iptables 规则. 但在 1.1 以前,service 使用的模式默认为 userspace。Service 是由 kube-proxy 组件,加上 iptables 来共同实现的。kube-proxy 通过 iptables 处理 Service 的过程,需要在宿主机上设置相 当多的 iptables 规则,如果宿主机有大量的 Pod,不断刷新 iptables 规则,会消耗大量的 CPU 资源。

kube-proxy 生成的 iptables 规则分析

在 k8s 创建的 service,虽然有 ip 地址,但是 service 的 ip 是虚拟的,不存在物理机上的,是在

iptables 或者 ipvs 规则里的。

]# kubectl get svc | grep my-nginx

my-nginx ClusterIP 10.99.198.177 80/TCP 

10.99.198.177 是 kubernetes 的 service ip,这个 ip 我们在物理机上看不到,它是在 iptables 规则里。

iptables -t nat -L |grep 10.99.198.177

KUBE-MARK-MASQ tcp -- !10.244.0.0/16 10.99.198.177 /*

default/my-nginx cluster IP */ tcp dpt:http

KUBE-SVC-L65ENXXZWWSAPRCR tcp -- anywhere 10.99.198.177 /* 

default/my-nginx cluster IP */ tcp dpt:http

#通过上面可以看到之前创建的 service,会通过 kube-proxy 在 iptables 中生成一个规则,来实现流量路由,有一系列目标为 KUBE-SVC-xxx 链的规则,每条规则都会匹配某个目标 ip 与端口。也 就是说访问某个 ip:port 的请求会由 KUBE-SVC-xxx 链来处理。这个目标 IP 其实就是 service ip。

Service 服务发现:coredns 组件详解

DNS 全称是 Domain Name System:域名系统,是整个互联网的电话簿,它能够将可被人理解的 域名翻译成可被机器理解 IP 地址,使得互联网的使用者不再需要直接接触很难阅读和理解的 IP 地址。域 名系统在现在的互联网中非常重要,因为服务器的 IP 地址可能会经常变动,如果没有了 DNS,那么可 能 IP 地址一旦发生了更改,当前服务器的客户端就没有办法连接到目标的服务器了,如果我们为 IP 地 址提供一个『别名』并在其发生变动时修改别名和 IP 地址的关系,那么我们就可以保证集群对外提供的 服务能够相对稳定地被其他客户端访。DNS 其实就是一个分布式的树状命名系统,它就像一个去中心化 的分布式数据库,存储着从域名到 IP 地址的映射。

CoreDNS 其实就是一个 DNS 服务,而 DNS 作为一种常见的服务发现手段,所以很多开源项目 以及工程师都会使用 CoreDNS 为集群提供服务发现的功能,Kubernetes 就在集群中使用 CoreDNS 解决服务发现的问题。 作为一个加入 CNCF(Cloud Native Computing Foundation)的服务, CoreDNS 的实现非常简单。

验证 coredns

docker load -I dig.tar.gz      工作节点解压

cat dig.yaml

apiVersion: v1

kind: Pod

metadata:

  name: dig

  namespace: default

spec:

  containers:

  - name: dig

    image: god/xianchao/dig:latest

    command:

    - sleep

    - "3600"

    imagePullPolicy: IfNotPresent

  restartPolicy: Always

kubectl apply -f dig.yaml

#查看默认名称空间的 kubernetes 服务

# kubectl get svc | grep kubernetes

kubectl get svc | grep kubernetes

kubernetes          ClusterIP      10.96.0.1                                        443/TCP          23

#解析 dns,如有以下返回说明 dns 安装成功

kubectl exec -it dig -- nslookup kubernetes

Server: 10.96.0.10

Address: 10.96.0.10#53

Name: kubernetes.default.svc.cluster.local Address: 10.96.0.1

kubernetes.default.svc.cluster.local 

服务名.名称空间.默认后缀

在 k8s 中创建 service 之后,service 默认的 FQDN 是..svc.cluster.local,那么 k8s 集群内部的服务就可以通过 FQDN 访问



【本文地址】


今日新闻


推荐新闻


    CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3