k8s-service

目录

 k8s网络通信

NodePort方式 

​headless service "无头服务"

LoadBalancer方式

ExternalName 方式


Service可以看作是一组提供相同服务的Pod对外的访问接口。

借助Service应用可以方便地实现服务发现和负载均衡。  service默认只支持4层负载均衡能力,没有7层功能。(可以通过Ingress实现)

k8s-service_第1张图片

Service 是由 kube-proxy 组件,加上 iptables 来共同实现的.  kube-proxy 通过 iptables 处理 Service 的过程,需要在宿主机上设置相当多的 iptables 规则,如果宿主机有大量的Pod,不断刷新iptables规则,会消耗大量的CPU资源。 

IPVS模式的service,可以使K8s集群支持更多量级的Pod

开启kube-proxy的ipvs模式

iptables -t nat -nL #查看iptable策略
kubectl get svc
yum install -y ipvsadm
 ipvsadm -ln #查看策略,目前为空
 kubectl get pod -n kube-system
kubectl get cm -n kube-system ##所有服务的配置都存在cm中
kubectl edit cm kube-proxy  -n kube-system #//修改IPVS模式,mode: "ipvs"
kubectl get pod -n kube-system |grep kube-proxy | awk '{system("kubectl delete pod "$1" -n kube-system")}' ##//更新kube-proxy pod(删除pod,控制器自动创建一份,类似于刷新)
kubectl get cm -n kube-system
kubectl get pod -n kube-system #运行可以看到已经生效
ipvsadm -ln #已经查看到策略
cd
 ip addr #系统中出现kube-ipvs0接口,策略内每个节点都有,出现相应vip

k8s-service_第2张图片

k8s-service_第3张图片

k8s-service_第4张图片

k8s-service_第5张图片

k8s-service_第6张图片

k8s-service_第7张图片

k8s-service_第8张图片

k8s-service_第9张图片

k8s-service_第10张图片

ls
cd init/
ls
cat svc.yaml
cd pod/
ls
vim deploy.yml #用deploy控制器创建3个pod
kubectl apply -f deploy.yml
kubectl get pod
kubectl get svc #可以看到创建的svc获得的集群地址10.108.242.106
kubectl describe svc myservice##service选择的后端是通过标签匹配的,endpoint有三个ip
ipvsadm -ln ##创建出相应的策略【10.108.242.106地址下面有三个pod】
kubectl get svc #ClusterIP仅限集群内部
kubectl get pod -o wide
 ip addr #PVS模式下,kube-proxy会在service创建后,在宿主机上添加一个虚拟网卡:kube-ipvs0,并分配service IP
curl 10.108.242.106 #访问集群地址
curl 10.108.242.106/hostname.html #可以看到负载均衡
ipvsadm -ln #可以看到调度次数
ls

k8s-service_第11张图片

k8s-service_第12张图片k8s-service_第13张图片

k8s-service_第14张图片

k8s-service_第15张图片

k8s-service_第16张图片

k8s-service_第17张图片

kube-proxy通过linux的IPVS模块,以rr轮询方式调度service中的Pod 

k8s-service_第18张图片

vim deploy.yml #设置副本数为6
kubectl apply -f deploy.yml
kubectl get pod
kubectl describe svc myservice ####endpoint有6个ip
 ipvsadm -ln

k8s-service_第19张图片

k8s-service_第20张图片

 k8s-service_第21张图片

 k8s网络通信

k8s通过CNI接口接入其他插件来实现网络通讯。目前比较流行的插件有flannel,calico等。 CNI插件存放位置:# cat  /etc/cni/net.d/10-flannel.conflist

容器间通信:同一个pod内的多个容器间的通信,通过lo即可实现; 

pod之间的通信: 同一节点的pod之间通过cni网桥转发数据包。

不同节点的pod之间的通信需要网络插件支持。  pod和service通信: 通过iptables或ipvs实现通信,ipvs取代不了iptables,因为ipvs只能做负载均衡,而做不了nat转换。

pod和外网通信:iptables的MASQUERADE。 

Service与集群外部客户端的通信;(ingress、nodeport、loadbalancer)  

Flannel vxlan模式跨主机通信原理 

k8s-service_第22张图片

flannel网络原理

当容器发送IP包,通过veth pair 发往cni网桥,再路由到本机的flannel.1设备进行处理。 VTEP设备之间通过二层数据帧进行通信,源VTEP设备收到原始IP包后,在上面加上一个目的MAC地址,封装成一个内部数据帧,发送给目的VTEP设备。 内部数据桢,并不能在宿主机的二层网络传输,Linux内核还需要把它进一步封装成为宿主机的一个普通的数据帧,承载着内部数据帧通过宿主机的eth0进行传输。 Linux会在内部数据帧前面,加上一个VXLAN头,VXLAN头里有一个重要的标志叫VNI,它是VTEP识别某个数据桢是不是应该归自己处理的重要标识。 flannel.1设备只知道另一端flannel.1设备的MAC地址,却不知道对应的宿主机地址是什么。在linux内核里面,网络设备进行转发的依据,来自FDB的转发数据库,这个flannel.1网桥对应的FDB信息,是由flanneld进程维护的。 linux内核在IP包前面再加上二层数据帧头,把目标节点的MAC地址填进去,MAC地址从宿主机的ARP表获取。 此时flannel.1设备就可以把这个数据帧从eth0发出去,再经过宿主机网络来到目标节点的eth0设备。目标主机内核网络栈会发现这个数据帧有VXLAN Header,并且VNI为1,Linux内核会对它进行拆包,拿到内部数据帧,根据VNI的值,交给本机flannel.1设备处理,flannel.1拆包,根据路由表发往cni网桥,最后到达目标容器。 

 k8s-service_第23张图片

使用cni0接口通信

查看路由

k8s-service_第24张图片

Cni0: 网桥设备,每创建一个pod都会创建一对 veth pair。其中一端是pod中的eth0,另一端是Cni0网桥中的端口(网卡)在server3上也是通过cni0,分配的ip10.244.1.1

k8s-service_第25张图片在后台运行flanneld服务

k8s-service_第26张图片Flanneld:flannel在每个主机中运行flanneld作为agent,它会为所在主机从集群的网络地址空间中,获取一个小的网段subnet,本主机内所有容器的IP地址都将从中分配。同时Flanneld监听K8s集群数据库,为flannel.1设备提供封装数据时必要的mac、ip等网络数据信息。 

k8s-service_第27张图片

k8s-service_第28张图片在fdb的转发数据库中查找对应的mac地址

k8s-service_第29张图片

k8s-service_第30张图片 flannel支持多种后端Vxlan

VXLAN,即Virtual Extensible LAN(虚拟可扩展局域网),是Linux本身支持的一网种网络虚拟化技术。VXLAN可以完全在内核态实现封装和解封装工作,从而通过“隧道”机制,构建出覆盖网络(Overlay Network)。 

vxlan            //报文封装,默认

Directrouting        //直接路由,跨网段使用vxlan,同网段使用host-gw模式。

host-gw:        //主机网关,性能好,但只能在二层网络中,不支持跨网络,                如果有成千上万的Pod,容易产生广播风暴,不推荐

UDP:            //性能差,不推荐  配置flannel

kubectl -n kube-system get cm
kubectl -n kube-system edit cm kube-flannel-cfg #配置flannel
kubectl get pod -n kube-system |grep flannel | awk '{system("kubectl delete pod "$1" -n kube-system")}' ##加载
kubectl -n kube-system get pod
 kubectl -n kube-system get all ##有daemonset控制器在后台自动创建
route -n #查看路由。已经无flannel接口

k8s-service_第31张图片

k8s-service_第32张图片

k8s-service_第33张图片

k8s-service_第34张图片

NodePort方式 

kubectl get pod
kubectl get svc
kubectl describe  svc myservice
curl 10.108.242.106
curl 10.108.242.106/hostname.html #改变网络类型后可以访问,实现负载均衡,同一个vlan更加方便
kubectl edit svc myservice #编辑改为nodeport方式
kubectl get svc #NodePort实际上是cluster ip基础之上绑定了一个端口
kubectl describe  svc myservice #可以看到暴露的端口
dig -t A myservice.default.svc.cluster.local. @10.96.0.10 #服务的A记录。service是10.96.0.10
kubectl -n kube-system get svc
kubectl -n kube-system describe svc kube-dns #可以看到dns解析服务
kubectl -n kube-system get pod -o wide
dig -t A myservice.default.svc.cluster.local. @10.244.0.6 #访问的svc实际上负载到后端的pod上
dig -t A myservice.default.svc.cluster.local. @10.96.0.10

k8s-service_第35张图片

k8s-service_第36张图片

可以让外网访问

k8s-service_第37张图片

k8s-service_第38张图片

k8s-service_第39张图片

k8s-service_第40张图片

k8s-service_第41张图片

k8s-service_第42张图片headless service "无头服务"

vim headless.yml
kubectl apply -f headless.yml
kubectl get svc #可以看到服务没有ip
kubectl -n kube-system describe svc nginx-svc #但是后端还有pod
kubectl describe svc nginx-svc #有标签
kubectl get pod --show-labels
dig -t A nginx-svc.default.svc.cluster.local. @10.96.0.10 #有解析记录

k8s-service_第43张图片

k8s-service_第44张图片

k8s-service_第45张图片

k8s-service_第46张图片

vim deploy.yml #修改副本数为3
 kubectl apply -f deploy.yml
 kubectl get svc
dig -t A nginx-svc.default.svc.cluster.local. @10.96.0.10 #解析的ip发生变化
 kubectl run -it demo --image=busyboxplus --restart=Never #直接可以访问svc名称做到负载均衡
 kubectl delete pod demo 

k8s-service_第47张图片

k8s-service_第48张图片

k8s-service_第49张图片

LoadBalancer方式

 从外部访问 Service 的第二种方式,适用于公有云上的 Kubernetes 服务。这时候,你可以指定一个 LoadBalancer 类型的 Service

kubectl get node
kubectl get pod
cd
cd service/
ls
 vim lb.yml
kubectl apply -f lb.yml
kubectl get svc #发现lb-nginx 一直处于pending状态

k8s-service_第50张图片

k8s-service_第51张图片在service提交后,Kubernetes就会调用 CloudProvider 在公有云上为你创建一个负载均衡服务,并且把被代理的 Pod 的 IP地址配置给负载均衡服务做后端。 

vim lb.yml
kubectl apply -f lb.yml
kubectl get pod
kubectl describe svc lb-nginx
cd
 ls
kubectl edit configmap -n kube-system kube-proxy #编辑strictARP: true
kubectl get pod -n kube-system |grep kube-proxy | awk '{system("kubectl delete pod "$1" -n kube-system")}' #加载使之生效
kubectl get pod -n kube-system #重新自动创建

k8s-service_第52张图片可以访问

k8s-service_第53张图片 k8s-service_第54张图片

k8s-service_第55张图片

mkdir metallb
cd metallb/
wget https://raw.githubusercontent.com/metallb/metallb/v0.10.2/manifests/namespace.yaml
cat namespace.yaml
kubectl apply -f namespace.yaml
kubectl get ns
wget https://raw.githubusercontent.com/metallb/metallb/v0.10.2/manifests/metallb.yaml
ls
vim metallb.yaml #修改镜像的路径
kubectl apply -f metallb.yaml
kubectl -n metallb-system get all #查看状态是否就绪
kubectl get svc #

k8s-service_第56张图片

k8s-service_第57张图片

k8s-service_第58张图片

k8s-service_第59张图片server1拉取镜像上传到私有仓库中

 k8s-service_第60张图片

 k8s-service_第61张图片

k8s-service_第62张图片

vim config.yaml #设置IP池
kubectl apply -f config.yaml
kubectl get svc
cd
cd service/
ls
cp lb.yml lb-2.yml
vim lb-2.yml
kubectl apply -f lb-2.yml
kubectl get svc #会看到分配的ip

这个 IP 池必须专供 MetalLB 使用,不能重复使用 Kubernetes 节点 IP 或 DHCP 服务器分发的 IP。 

k8s-service_第63张图片  k8s-service_第64张图片

k8s-service_第65张图片

k8s-service_第66张图片

k8s-service_第67张图片

kubectl delete -f lb-2.yml
kubectl get svc

k8s-service_第68张图片

ExternalName 方式

从外部访问的第三种方式叫做ExternalName,这种方式也可以使pod能够访问外部的地址

vim ex-svc.yaml
kubectl apply -f ex-svc.yaml 创建service
kubectl get svc
dig -t A my-service.default.svc.cluster.local. @10.96.0.10 #可以看出并没有分配ip地址,只是在dns里面更新了以下CNAME

externalName: test.westos.org		#指定外部有效地址

k8s-service_第69张图片

k8s-service_第70张图片

k8s-service_第71张图片

 这样的做法有一个好处,即使需要访问的外部地址变了,也只需要更改service的yaml文件即可,依然可以通过访问myservice.default.svc.cluster.local来访问外部地址,如下变动外部网站

vim ex-svc.yaml
kubectl apply -f ex-svc.yaml
dig -t A my-service.default.svc.cluster.local. @10.96.0.10

k8s-service_第72张图片

k8s-service_第73张图片

kubectl get ns
kubectl create namespace demo
kubectl get ns
vim ex-svc.yaml
kubectl apply -f ex-svc.yaml
kubectl get svc
kubectl get svc -n demo
dig -t A my-service.demo.svc.cluster.local. @10.96.0.10
kubectl delete -f ex-svc.yaml
kubectl delete namespaces demo
kubectl get ns
ls

k8s-service_第74张图片

k8s-service_第75张图片

k8s-service_第76张图片

k8s-service_第77张图片

k8s-service_第78张图片 ExternalName方式的service允许为其分配一个公有IP

vim ex-ip.yaml
kubectl apply-f  ex-ip.yaml
kubectl apply -f ex-ip.yaml
kubectl get svc #查看svc的状态说明指定成功
kubectl describe svc ex-service
ip addr add 172.25.254.200/24 dev eth0 #集群外访问时需要添加ip
ip addr del 172.25.254.200/24 dev eth0
kubectl get svc
kubectl delete -f ex-ip.yaml
kubectl get all
kubectl get svc
kubectl delete svc my-service

k8s-service_第79张图片 

k8s-service_第80张图片集群外不能访问

k8s-service_第81张图片 

 

你可能感兴趣的:(docker,运维)