service使用与网络原理
1. Service
- ipvs负载均衡
Service 的负载均衡是由 kube-proxy 加上 iptables 来共同实现的.
kube-proxy 通过 iptables 处理 Service 的过程,需要在宿主机上设置相当多的 iptables 规则,如果宿主机有大量的Pod,不断刷新iptables规则,会消耗大量的CPU资源。
IPVS模式的service,可以使K8s集群支持更多量级的Pod。
yum install -y ipvsadm
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
IPVS模式下,kube-proxy会在service创建后,在宿主机上添加一个虚拟网卡:kube-ipvs0,并分配service IP.kube-proxy通过linux的IPVS模块,以rr轮询方式调度service中的Pod。
- 创建service(ClusterIP模式)
此模式下,service会被分配一个ClusterIP,此IP默认会通过RR策略轮询后端POD。效果参考POD管理文中的暴露端口后。
vim service-example.yaml
apiVersion: v1
kind: Service
metadata:
name: web-service
spec:
ports:
- name: http
port: 80
targetPort: 80
selector:
app: myapp
type: ClusterIP
- 创建service (NodePort方式)
此方式会将节点主机的端口绑定至Service,通过节点主机的指定端口可以访问pod,提供负载均衡策略。
vim svc.yaml
apiVersion: v1
kind: Service
metadata:
name: mysvc
spec:
ports:
- name: http
port: 80
targetPort: 80
selector:
app: nginx
type: NodePort
访问节点指定端口时可以负载均衡
- 创建service (LoadBalance方式)
从外部访问 Service 的第二种方式,适用于公有云上的 Kubernetes 服务。
导入metallb镜像,在私有仓库创建metallb
docker load -i metallb-v0.10.2.tar
docker push reg.westos.org/metallb/controller:v0.10.2
docker push reg.westos.org/metallb/speaker:v0.10.2
修改proxy策略
kubectl edit cm kube-proxy -n kube-system
strictARP: true
mode: "ipvs"
部署应用metallb.yaml,内容见官网:
kubectl apply -f metallb.yaml
编辑IP池配置文件
vim configmap.yaml
apiVersion: v1
kind: ConfigMap
metadata:
namespace: metallb-system
name: config
data:
config: |
address-pools:
- name: default
protocol: layer2
addresses:
- 172.25.52.100-172.25.52.200
应用配置文件:
kubectl apply -f configmap.yaml
编辑svc文件选中后端pod标签app: myapp ,应用svc文件
vim lb-svc.yaml
kubectl apply -f lb-svc.yaml
apiVersion: v1
kind: Service
metadata:
name: lb-svc
spec:
ports:
- name: http
protocol: TCP
port: 80
targetPort: 80
selector:
app: myapp
type: LoadBalancer
已经分配到IP
在其他主机访问分配的外部端口
- 创建service (External)
- ExternalName
可以为svc设定地址名称,并且可以在svc上变动。检验时无需为svc分配pod资源。
vim ex-svc.yaml
kubectl apply -f ex-svc.yaml
apiVersion: v1
kind: Service
metadata:
name: my-service
spec:
type: ExternalName
externalName: www.westos.org
dig -t A my-service.default.svc.cluster.local. @10.244.2.59
- ExternalIP
service允许为其分配一个公有IP
vim ex-svc.yaml
kubectl apply -f ex-svc.yaml
apiVersion: v1
kind: Service
metadata:
name: my-service
spec:
selector:
app: myapp
ports:
- name: http
protocol: TCP
port: 80
targetPort: 80
externalIPs:
- 172.25.52.123
此IP不纳入Kubectl管理,无法通过外部节点访问,若需访问则要将其设置在节点的真实网卡上。
2. 网络原理
- fannel
flannel支持多种后端:
Vxlan:
vxlan //报文封装,默认
Directrouting //直接路由,跨网段使用vxlan,同网段使用host-gw模式。
host-gw: //主机网关,性能好,不支持跨网络,节点多时容易形成广播风暴
UDP: //性能差,不推荐
默认为vxlan模式,路由表中存在fannel设备接口。
修改fannnel配置文件
kubectl -n kube-system edit cm kube-flannel-cfg
net-conf.json: |
{
"Network": "10.244.0.0/16",
"Backend": {
"Type": "vxlan",
"Directrouting": true #vxlan模式2 途中为直连网关模式
}
}
重启后应用更改
kubectl get pod -n kube-system |grep kube-flannel | awk '{system("kubectl delete pod "$1" -n kube-system")}'
路由表中fannel消失,直接转发至节点的主机eth0网卡
- calico
原理
- flannel实现的是网络通信,calico的特性是在pod之间的隔离。
- 通过BGP路由,但大规模端点的拓扑计算和收敛往往需要一定的时间和计算资源。
- 纯三层的转发,中间没有任何的NAT和overlay,转发效率最好。Calico 仅依赖三层路由可达。
提供两种工作模式:
部署
删除原有的fannel网络插件
下载导入镜像至本地私有仓库:
docker load -i calico-v3.19.1.tar
下载配置文件:
curl https://docs.projectcalico.org/manifests/calico.yaml -o calico.yaml #导入
docker images | grep calico | awk '{system("docker push "$1":"$2"")}' #上传至仓库
修改安装calico的yml文件,将镜像地址改为本地仓库,并且关闭IPIP隧道:
- name: CALICO_IPV4POOL_IPIP
value: "off"
应用配置文件,拉取calico
kubectl apply -f calico.yaml
查看calico pod
策略
NetworkPolicy策略模型:控制某个namespace下的pod的网络出入站规则
官网:https://kubernetes.io/zh/docs/concepts/services-networking/network-policies/
案例:限制访问指定标签pod
vim deny-nginx.yaml
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: deny-nginx
spec:
podSelector:
matchLabels:
app: myapp
应用策略
kubectl apply -f deny-nginx.yaml
测试,无论在pod内还是宿主机都无法访问pod中的内容
案例:禁止访问指定namespace
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: default-deny
namespace: default
spec:
podSelector: {}
来自default与test ns的pod均无法访问服务
案例:只允许指定namespace访问服务
kind: NetworkPolicy
apiVersion: networking.k8s.io/v1
metadata:
name: access-namespace
spec:
podSelector:
matchLabels:
app: myapp
ingress:
- from:
- namespaceSelector:
matchLabels:
role: prod
只允许role=prod 的ns中pod 访问 app=myapp的pod
其余标签的ns无法访问myapp
示例:
#允许指定pod访问服务:
kind: NetworkPolicy
apiVersion: networking.k8s.io/v1
metadata:
name: access-nginx
spec:
podSelector:
matchLabels:
app: nginx
ingress:
- from:
- podSelector:
matchLabels:
app: demo
#禁止其他 namespace 访问服务
kind: NetworkPolicy
apiVersion: networking.k8s.io/v1
metadata:
name: deny-namespace
spec:
podSelector:
matchLabels:
ingress:
- from:
- podSelector: {}
#允许外网访问服务
kind: NetworkPolicy
apiVersion: networking.k8s.io/v1
metadata:
name: web-allow-external
spec:
podSelector:
matchLabels:
app: web
ingress:
- ports:
- port: 80
from: []