Service 存在的意义
• 防止Pod失联(服务发现)
• 定义一组Pod的访问策略(负载均衡)
Pod与Service的关系
• 通过label-selector相关联
• 通过Service实现Pod的负载均衡( TCP/UDP 4层)

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

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

如果不指定type 默认创建的是 ClusterIp
clusterip 类型只能在集群内部访问 在node节点 curl 10.0.0.169:80
NodePort:
分配一个内部集群IP地址,并在每个节点上启用一个端口来暴露服务,可以在集群外部访问。 访问地址:<NodeIp>:<NodePort>

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

curl k8s-node1:30008

通过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])作为后端添加进去。

Service代理模式

默认启用的时 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

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

重启kube-proxy服务才能生效
systemctl restart kube-proxy
验证
在node节点安装 ipvsadm 工具
yum install ipvsadm -y

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


此时 curl 10.0.0.203:80 相当于请求了 这个endpoint 10.244.0.31:80
如果pod 重建了 endpoint 发生变化,ipvs能自动更新后端的 server 嘛?

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

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"

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

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

tips:
k8s-master watch svc if svc have new ? add A record into dns
来源:https://www.cnblogs.com/benjamin77/p/12446752.html