深入理解Service

Service 存在的意义

• 防止Pod失联(服务发现)

• 定义一组Pod的访问策略(负载均衡)

Pod与Service的关系

• 通过label-selector相关联

• 通过Service实现Pod的负载均衡( TCP/UDP 4层)

image.png

Service三种类型

ClusterIP:

分配一个内部集群IP地址,只能在集群内部访问(同Namespace内的Pod),默认ServiceType。 ClusterIP 模式的 Service 为你提供的,就是一个 Pod 的稳定的 IP 地址,即 VIP。

image.png

web-deployment.yaml

apiVersion: apps/v1
kind: Deployment
metadata:
  labels:
    app: web
  name: web
spec:
  replicas: 1
  selector:
    matchLabels:
      app: web
  template:
    metadata:
      labels:
        app: web
    spec:
      containers:
      - image: nginx
        name: nginx

service-clusterip.yaml

apiVersion: v1
kind: Service
metadata:
  labels: 
    app: web
  name: web
spec:
  ports:
  - port: 80
    protocol: TCP
    targetPort: 80
  selector:
    app: web

image.png

如果不指定type  默认创建的是 ClusterIp

clusterip 类型只能在集群内部访问 在node节点  curl  10.0.0.169:80

NodePort:

分配一个内部集群IP地址,并在每个节点上启用一个端口来暴露服务,可以在集群外部访问。 访问地址:<NodeIp>:<NodePort>

image.png

apiVersion: v1
kind: Service
metadata:
  labels:
    app: web
  name: web
spec:
  ports:
  - port: 80
    protocol: TCP
    targetPort: 80
    nodePort: 30008    #如果nodePort未指定将随机分配一个端口范围30000-32767
  selector:
    app: web
  type: NodePort

nodeport的默认范围30000-32767,如果需要修改这个范围

比如像把端口范围改成1-65535,则在apiserver的启动命令里面添加如下参数:

–service-node-port-range=1-65535

image.png

curl k8s-node1:30008

image.png

通过nodeport暴露服务可以在集群外部访问,nodeport类型会在每个node上开启对应的端口(30008)服务

需要注意的问题:

指定的port 首先不能被占用。

如果某个node挂了,前端访问时却不能感知,导致访问落空,node挂了没法通知到前端,这时候假如有个lb来记录可用的后端服务,这样才显得灵活,传统使用 nginx haproxy lvs 来充当这样的lb,但是每次需要手动更新后端可用节点ip和端口。

如果采用公有云的loadbalancer ,每次创建新的service会自动调用loadbalancer的api更新后端的<nodeip>:<nodeport>

LoadBalancer:

分配一个内部集群IP地址,并在每个节点上启用一个端口来暴露服务。 除此之外,Kubernetes会请求底层云平台上的负载均衡器,将每个Node([NodeIP]:[NodePort])作为后端添加进去。

image.png

Service代理模式

image.png

默认启用的时 iptables 来创建转发规则。

ipvs转发性能 明显优于iptables,但是iptables是kubernetes默认的转发工具比较稳定可靠。

修改默认转发工具为ipvs

查看是否加载ipvs模块

集群内所有节点都需要加载

lsmod |grep ip_vs  #如果没有返回 需要加载以下模块
modprobe -- ip_vs
modprobe -- ip_vs_rr
modprobe -- ip_vs_wrr
modprobe -- ip_vs_sh
modprobe -- nf_conntrack_ipv4

image.png

kubeadmin方式部署(ipvs)

kube-proxy的配置 是保存在一个configmap中

kubectl edit configmap kube-proxy -n kube-system

找到 mode 字段,默认是为空的,为空的时候使用iptables,此时将mode字段对应的值改为ipvs 

mode:"ipvs"

重启kube-proxy  pod 方能生效

kubectl delete pod kube-proxy-xxx -n kube-system

二进制部署方式 (ipvs)

修改kube-proxy配置文件指定模式为ipvs

image.png

重启kube-proxy服务才能生效

systemctl restart kube-proxy

验证

在node节点安装 ipvsadm 工具

yum install ipvsadm -y

image.png

通过 10.0.0.203 这个ip的80端口 来转发 到后端的 服务,后端的服务为这个service的endpoint

image.png

image.png

此时  curl 10.0.0.203:80  相当于请求了 这个endpoint 10.244.0.31:80

如果pod 重建了 endpoint 发生变化,ipvs能自动更新后端的 server 嘛?

image.png

当我们重建pod后  endpoint 由 10.244.0.31:80 变成 10.244.1.43:80, ipvs自动更新了 后端的server

image.png

Iptables VS IPVS 对比

Iptables:

• 灵活,功能强大

• 规则遍历匹配和更新,呈线性时延

• 可扩展性

IPVS:

• 工作在内核态,有更好的性能

• 调度算法丰富:rr,wrr,lc,wlc,ip hash...

Service DNS名称

DNS服务监视Kubernetes API,为每一个Service创建DNS记录用于域名解析。

ClusterIP A记录格式:<service-name>.<namespace-name>.svc.cluster.local 示例:my-svc.my-namespace.svc.cluster.local

k8s默认使用coredns 用来集群内部 域名解析,将service的名称和 clusterip 做一个A记录

创建一个测试pod

nslookup.yaml

apiVersion: v1
kind: Pod
metadata:
  labels:
    run: busybox 
  name: dns-test
  namespace: default
spec:
  containers:
  - image: busybox:1.28.4
    name: b1
    command:
      - "ping"
      - "baidu.com"

image.png

由于web是default 名称空间下的所有不需要指定namespace

image.png

如果解析 kube-system 名称空间下kube-dns service 需要指定kube-system名称空间

image.png

tips:

k8s-master  watch svc   if  svc  have new ?  add A record into dns

原文地址:https://www.cnblogs.com/benjamin77/p/12446752.html