k8s通过CNI接口接入其他插件来实现网络通讯。目前比较流行的插件有flannel,calico等。CNI插件存放位置:# cat /etc/cni/net.d/10-flannel.conflist 插件使用的解决方案如下:虚拟网桥,虚拟网卡,多个容器共用一个虚拟网卡进行通信。多路复用:MacVLAN,多个容器共用一个物理网卡进行通信。硬件交换:SR-LOV,一个物理网卡可以虚拟出多个接口,这个性能最好。容器间通信:同一个pod内的多个容器间的通信,通过lo即可实现;pod之间的通信:同一节点的pod之间通过cni网桥转发数据包。(brctl show可以查看)不同节点的pod之间的通信需要网络插件支持。pod和service通信: 通过iptables或ipvs实现通信,ipvs取代不了iptables,因为ipvs只能做负载均衡,而做不了nat转换。pod和外网通信:iptables的MASQUERADE。Service与集群外部客户端的通信;(ingress、nodeport、loadbalancer)
Service可以看作是一组提供相同服务的Pod对外的访问接口。借助Service,应用可以方便地实现服务发现和负载均衡。
service默认只支持4层负载均衡能力,没有7层功能。(可以通过Ingress实现)
service的类型:(前三种是集群外部访问内部资源)ClusterIP:默认值,k8s系统给service自动分配的虚拟IP,只能在集群内部访问。NodePort:将Service通过指定的Node上的端口暴露给外部,访问任意一个NodeIP:nodePort都将路由到ClusterIP。LoadBalancer:在 NodePort 的基础上,借助 cloud provider 创建一个外部的负载均衡器,并将请求转发到 :NodePort,此模式只能在云服务器上使用。ExternalName:将服务通过 DNS CNAME 记录方式转发到指定的域名(通过 spec.externlName 设定)。[集群内部访问外部,通过内部调用外部资源]
创建测试示例
[root@k8s2 service]# vim myapp.yml
apiVersion: apps/v1
kind: Deployment
metadata:labels:app: myappname: myapp
spec:replicas: 6selector:matchLabels:app: myapptemplate:metadata:labels:app: myappspec:containers:- image: myapp:v1name: myapp---apiVersion: v1
kind: Service
metadata:labels:app: myappname: myapp
spec:ports:- port: 80protocol: TCPtargetPort: 80selector:app: myapptype: ClusterIP[root@k8s2 service]# kubectl apply -f myapp.yml[root@k8s2 service]# kubectl get svc
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
kubernetes ClusterIP 10.96.0.1 443/TCP 4d1h
myapp ClusterIP 10.107.249.53 80/TCP 7s
默认使用iptables调度
Service 是由 kube-proxy 组件,加上 iptables 来共同实现的
kube-proxy 通过 iptables 处理 Service 的过程,需要在宿主机上设置相当多的 iptables 规则,如果宿主机有大量的Pod,不断刷新iptables规则,会消耗大量的CPU资源。
IPVS模式的service,可以使K8s集群支持更多量级的Pod。
查看没有设置ipvs模式时候的ipvs
[root@server2 ~]# lsmod | grep ip ##可以查看对应的ipvs是没有使用的,还是使用的iptables
ip6_udp_tunnel 12755 1 vxlan
ip_vs_sh 12688 0
ip_vs_wrr 12697 0
ip_vs_rr 12600 0
ip_vs 145497 6 ip_vs_rr,ip_vs_sh,ip_vs_wrr
部署ipvs模式
[root@server2 ~]# yum install -y ipvsadm ##安装ipvsadm[root@server2 ~]# kubectl get pod -n kube-system | grep kube-proxy ##部署之前查看一下
[root@server2 ~]# kubectl -n kube-system edit cm kube-proxy
...
mode: "ipvs" ##进入修改mode为ipvs重启pod:
[root@server2 ~]# kubectl -n kube-system get pod|grep kube-proxy | awk '{system("kubectl -n kube-system delete pod "$1"")}' ##更新kube-proxy pod
[root@server2 ~]# kubectl get pod -n kube-system | grep kube-proxy ##部署之后查看是否发生变化
[root@server2 ~]# ipvasdm -ln#IPVS模式下,kube-proxy会在service创建后,在宿主机上添加一个虚拟网卡:kube-ipvs0,并分配service IP
切换ipvs模式后,kube-proxy会在宿主机上添加一个虚拟网卡:kube-ipvs0,并分配service IP
测试:轮循机制
clusterip模式只能在集群内访问
[root@k8s2 service]# vim myapp.yml
---
apiVersion: v1
kind: Service
metadata:labels:app: myappname: myapp
spec:ports:- port: 80protocol: TCPtargetPort: 80selector:app: myapptype: ClusterIP ##模式
service创建后集群DNS提供解析
通过dig进行测试
Headless Service不需要分配一个VIP,而是直接以DNS记录的方式解析出被代理Pod的IP地址。
域名格式:(servicename).(servicename).(servicename).(namespace).svc.cluster.local
[root@k8s2 service]# vim myapp.yml...
---
apiVersion: v1
kind: Service
metadata:labels:app: myappname: myapp
spec:ports:- port: 80protocol: TCPtargetPort: 80selector:app: myapp type: ClusterIP ##clusterIP: None ##[root@k8s2 service]# kubectl delete svc myapp
[root@k8s2 service]# kubectl apply -f myapp.yml
headless模式不分配vip
headless通过svc名称访问,由集群内dns提供解析
集群内直接使用service名称访问
[root@k8s2 service]# vim myapp.yml
---
apiVersion: v1
kind: Service
metadata:labels:app: myappname: myapp
spec:ports:- port: 80protocol: TCPtargetPort: 80selector:app: myapptype: NodePort[root@k8s2 service]# kubectl apply -f myapp.yml[root@k8s2 service]# kubectl get svc
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
kubernetes ClusterIP 10.96.0.1 443/TCP 4d1h
myapp NodePort 10.107.249.53 80:32199/TCP 12m
nodeport在集群节点上绑定端口,一个端口对应一个服务
[root@k8s1 harbor]# curl 192.168.56.12:32199
Hello MyApp | Version: v1 | Pod Name
[root@k8s2 service]# vim myapp.yml
---
apiVersion: v1
kind: Service
metadata:labels:app: myappname: myapp
spec:ports:- port: 80protocol: TCPtargetPort: 80selector:app: myapptype: LoadBalancer ##[root@k8s2 service]# kubectl apply -f myapp.yml
默认无法分配外部访问IP
[root@k8s2 service]# kubectl get svc
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
kubernetes ClusterIP 10.96.0.1 443/TCP 4d1h
myapp LoadBalancer 10.107.23.134 80:32537/TCP 4sLoadBalancer模式适用云平台,裸金属环境需要安装metallb提供支持
官网:https://metallb.universe.tf/installation/
[root@k8s2 service]# kubectl edit configmap -n kube-system kube-proxy
apiVersion: kubeproxy.config.k8s.io/v1alpha1
kind: KubeProxyConfiguration
mode: "ipvs" ##
ipvs: ##strictARP: true ##[root@k8s2 service]# kubectl -n kube-system get pod|grep kube-proxy | awk '{system("kubectl -n kube-system delete pod "$1"")}'下载部署文件
[root@k8s2 metallb]# wget https://raw.githubusercontent.com/metallb/metallb/v0.13.9/config/manifests/metallb-native.yaml修改文件中镜像地址,与harbor仓库路径保持一致
[root@k8s2 metallb]# vim metallb-native.yaml
...
image: metallb/speaker:v0.13.9
image: metallb/controller:v0.13.9
上传镜像到harbor
[root@k8s1 ~]# docker pull quay.io/metallb/controller:v0.13.9
[root@k8s1 ~]# docker pull quay.io/metallb/speaker:v0.13.9[root@k8s1 ~]# docker tag quay.io/metallb/controller:v0.13.9 reg.westos.org/metallb/controller:v0.13.9
[root@k8s1 ~]# docker tag quay.io/metallb/speaker:v0.13.9 reg.westos.org/metallb/speaker:v0.13.9[root@k8s1 ~]# docker push reg.westos.org/metallb/controller:v0.13.9
[root@k8s1 ~]# docker push reg.westos.org/metallb/speaker:v0.13.9
部署服务
[root@k8s2 metallb]# kubectl apply -f metallb-native.yaml
[root@k8s2 metallb]# kubectl -n metallb-system get pod
NAME READY STATUS RESTARTS AGE
controller-74f844c699-gz9pt 1/1 Running 0 51s
speaker-crr2r 1/1 Running 0 51s
speaker-kcv84 1/1 Running 0 51s
speaker-zxc6j 1/1 Running 0 51s
配置分配地址段
[root@k8s2 metallb]# vim config.yaml
apiVersion: metallb.io/v1beta1
kind: IPAddressPool
metadata:name: first-poolnamespace: metallb-system
spec:addresses:- 192.168.117.100-192.168.117.110 #修改为自己本地地址段---
apiVersion: metallb.io/v1beta1
kind: L2Advertisement
metadata:name: examplenamespace: metallb-system
spec:ipAddressPools:- first-pool[root@k8s2 metallb]# kubectl apply -f config.yaml[root@k8s2 metallb]# kubectl get svc
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
kubernetes ClusterIP 10.96.0.1 443/TCP 4d1h
myapp LoadBalancer 10.107.23.134 192.168.117.100 80:32537/TCP 19m