k8s网络通信
一、通信模式
一 、k8s通過CNI接口接入其他插件來實現(xiàn)網(wǎng)絡通訊。目前比較流行的插件有flannel,calico等。
CNI插件存放位置:# cat /etc/cni/net.d/10-flannel.conflist
插件使用的解決方案如下:
- 虛擬網(wǎng)橋,虛擬網(wǎng)卡,多個容器共用一個虛擬網(wǎng)卡進行通信。
- 多路復用:MacVLAN,多個容器共用一個物理網(wǎng)卡進行通信。
- 硬件交換:SR-LOV,一個物理網(wǎng)卡可以虛擬出多個接口,這個性能最好。
二、容器間通信:同一個pod內的多個容器間的通信,通過lo即可實現(xiàn);
三、pod之間的通信:
- 同一節(jié)點的pod之間通過cni網(wǎng)橋轉發(fā)數(shù)據(jù)包。
- 不同節(jié)點的pod之間的通信需要網(wǎng)絡插件支持。
四、pod和service通信: 通過iptables或ipvs實現(xiàn)通信,ipvs取代不了iptables,因為ipvs只能做負載均衡,而做不了nat轉換。
五、pod和外網(wǎng)通信:iptables的MASQUERADE。
六、Service與集群外部客戶端的通信;(ingress、nodeport、loadbalancer)
二、service
1 k8s提供的dns服務插件
[root@server2 ~]# kubectl describe svc myservice [root@server2 ~]# kubectl run demo1 --image=busyboxplus -it If you don't see a command prompt, try pressing enter. / # nslookup myservice / # curl myservice [root@server2 ~]# kubectl get service kube-dns --namespace=kube-system [root@server2 ~]# dig myservice.default.svc.cluster.local. @10.96.0.102 Headless Service “無頭服務”
- Headless Service不需要分配一個VIP,而是直接以DNS記錄的方式解析出被代理Pod的IP地址。
- 域名格式:(servicename).(servicename).(servicename).(namespace).svc.cluster.local
從下圖看到?jīng)]有分配固定ip,而是直接以DNS記錄的方式解析出被代理Pod的IP地址。
3 創(chuàng)建service(NodePort方式)
[root@server2 ~]# vim demo.yml --- apiVersion: v1 kind: Service metadata:name: myservice spec:selector:app: myappports:- protocol: TCPport: 80targetPort: 80#clusterIP: Nonetype: NodePort---apiVersion: apps/v1 kind: Deployment metadata:name: demo2 spec:replicas: 3selector:matchLabels:app: myapptemplate:metadata:labels:app: myappspec:containers:- name: myappimage: myapp:v2 [root@server2 ~]# kubectl delete -f demo.yml [root@server2 ~]# kubectl apply -f demo.yml [root@server2 ~]# kubectl get svc在ip的基礎上又加了一個端口
4. LoadBalancer 類型的 Service
從外部訪問 Service 的第二種方式,適用于公有云上的 Kubernetes 服務。這時候,你可以指定一個 LoadBalancer 類型的 Service。
在service提交后,Kubernetes就會調用 CloudProvider 在公有云上為你創(chuàng)建一個負載均衡服務,并且把被代理的 Pod 的 IP地址配置給負載均衡服務做后端。
將剛才的demo.yml中的類型變成LoadBalancer即可
由于我們使用的不是共有云,所以暫時不能實現(xiàn),EXTERNAL-IP顯示的是pending等待分配ip狀態(tài)
5 service允許為其分配一個公有IP
在ClusterIP的基礎上,給綁定了一個外部地址,在外部可以直接訪問
[root@server2 ~]# vim demo.yml externalIPs:- 172.25.1.10
在外部主機可以通過這個ip進行訪問
6 ExternalName
從外部訪問的第三種方式叫做ExternalName
[root@server2 ~]# vim my-service.yml apiVersion: v1 kind: Service metadata:name: my-service spec:type: ExternalNameexternalName: www.baidu.com
兩種驗證方式:
三、(pod間通信)Flannel 網(wǎng)絡
Flannel vxlan模式跨主機通信原理
(1)VXLAN,即Virtual Extensible LAN(虛擬可擴展局域網(wǎng)),是Linux本身支持的一網(wǎng)種網(wǎng)絡虛擬化技術。VXLAN可以完全在內核態(tài)實現(xiàn)封裝和解封裝工作,從而通過“隧道”機制,構建出覆蓋網(wǎng)絡(Overlay Network)。
(2)VTEP:VXLAN Tunnel End Point(虛擬隧道端點),在Flannel中 VNI的默認值是1,這也是為什么宿主機的VTEP設備都叫flannel.1的原因。
(3)Cni0: 網(wǎng)橋設備,每創(chuàng)建一個pod都會創(chuàng)建一對 veth pair。其中一端是pod中的eth0,另一端是Cni0網(wǎng)橋中的端口(網(wǎng)卡)。
(4)Flannel.1: TUN設備(虛擬網(wǎng)卡),用來進行 vxlan 報文的處理(封包和解包)。不同node之間的pod數(shù)據(jù)流量都從overlay設備以隧道的形式發(fā)送到對端。
(5)Flanneld:flannel在每個主機中運行flanneld作為agent,它會為所在主機從集群的網(wǎng)絡地址空間中,獲取一個小的網(wǎng)段subnet,本主機內所有容器的IP地址都將從中分配。同時Flanneld監(jiān)聽K8s集群數(shù)據(jù)庫,為flannel.1設備提供封裝數(shù)據(jù)時必要的mac、ip等網(wǎng)絡數(shù)據(jù)信息。
flannel網(wǎng)絡原理
當容器發(fā)送IP包,通過veth pair 發(fā)往cni網(wǎng)橋,再路由到本機的flannel.1設備進行處理。
VTEP設備之間通過二層數(shù)據(jù)幀進行通信,源VTEP設備收到原始IP包后,在上面加上一個目的MAC地址,封裝成一個內部數(shù)據(jù)幀,發(fā)送給目的VTEP設備。
內部數(shù)據(jù)楨,并不能在宿主機的二層網(wǎng)絡傳輸,Linux內核還需要把它進一步封裝成為宿主機的一個普通的數(shù)據(jù)幀,承載著內部數(shù)據(jù)幀通過宿主機的eth0進行傳輸。
Linux會在內部數(shù)據(jù)幀前面,加上一個VXLAN頭,VXLAN頭里有一個重要的標志叫VNI,它是VTEP識別某個數(shù)據(jù)楨是不是應該歸自己處理的重要標識。
flannel.1設備只知道另一端flannel.1設備的MAC地址,卻不知道對應的宿主機地址是什么。在linux內核里面,網(wǎng)絡設備進行轉發(fā)的依據(jù),來自FDB的轉發(fā)數(shù)據(jù)庫,這個flannel.1網(wǎng)橋對應的FDB信息,是由flanneld進程維護的。
linux內核在IP包前面再加上二層數(shù)據(jù)幀頭,把目標節(jié)點的MAC地址填進去,MAC地址從宿主機的ARP表獲取。
此時flannel.1設備就可以把這個數(shù)據(jù)幀從eth0發(fā)出去,再經(jīng)過宿主機網(wǎng)絡來到目標節(jié)點的eth0設備。目標主機內核網(wǎng)絡棧會發(fā)現(xiàn)這個數(shù)據(jù)幀有VXLAN Header,并且VNI為1,Linux內核會對它進行拆包,拿到內部數(shù)據(jù)幀,根據(jù)VNI的值,交給本機flannel.1設備處理,flannel.1拆包,根據(jù)路由表發(fā)往cni網(wǎng)橋,最后到達目標容器。
相同主機之間的pod通過cni通信
在server3上要先知道目標主機(server4)eth0的IP和mac地址
arp -n 可以查看到有server4的ip信息。
flannel支持多種后端
Vxlan
- vxlan //報文封裝,默認
- Directrouting //直接路由,跨網(wǎng)段使用vxlan,同網(wǎng)段使用host-gw模式。
host-gw://主機網(wǎng)關,性能好,但只能在二層網(wǎng)絡中,不支持跨網(wǎng)絡,如果有成千上萬的Pod,容易產(chǎn)生廣播風暴,不推薦
UDP: //性能差,不推薦
host-gw主機網(wǎng)關
修改配置flannel:
[root@server2 ~]# kubectl -n kube-system edit cm kube-flannel-cfg
生效:
從下圖我們可以看出本地的話直接走cni,如果是1,0網(wǎng)段的直接走網(wǎng)關etho
vxlan
[root@server2 ~]# kubectl -n kube-system edit cm kube-flannel-cfg "Type": "vxlan","Directrouting": true [root@server2 ~]# kubectl get pod -n kube-system |grep flannel | awk '{system("kubectl delete pod "$1" -n kube-system")}'
并沒有經(jīng)過flannel.1
四、Service與集群外部客戶端的通信(Ingress 服務)
- 一種全局的、為了代理不同后端 Service 而設置的負載均衡服務,就是 Kubernetes 里的Ingress 服務。
- Ingress由兩部分組成:Ingress controller和Ingress服務。
- Ingress Controller 會根據(jù)你定義的 Ingress 對象,提供對應的代理能力。業(yè)界常用的各種反向代理項目,比如 Nginx、HAProxy、Envoy、Traefik 等,都已經(jīng)為Kubernetes 專門維護了對應的 Ingress Controller。
官網(wǎng):ingress-nginx
下載鏡像并上傳到本地倉庫,鏡像下載需要翻墻
所需的資源鏈接: yaml文件和鏡像 提取碼: nbvc
Ingress 服務部署:
[root@server1 ~]# docker load -i ingress-nginx.tar [root@server1 ~]# docker tag quay.io/kubernetes-ingress-controller/nginx-ingress-controller:0.33.0 reg.westos.org/library/nginx-ingress-controller:0.33.0 [root@server1 ~]# docker tag jettech/kube-webhook-certgen:v1.2.0 reg.westos.org/library/kube-webhook-certgen:v1.2.0 [root@server1 ~]# docker push reg.westos.org/library/nginx-ingress-controller:0.33.0 [root@server1 ~]# docker push reg.westos.org/library/kube-webhook-certgen:v1.2.0[root@server2 ~]# mkdir ingress-nginx/ [root@server2 ~]# cd ingress-nginx/ [root@server2 ingress-nginx]# kubectl apply -f deploy.yaml [root@server2 ingress-nginx]# kubectl get ns [root@server2 ingress-nginx]# kubectl get all -n ingress-nginx
創(chuàng)建Ingress服務
[root@server2 ~]# vim nginx.yml apiVersion: networking.k8s.io/v1beta1 kind: Ingress metadata:name: ingress-demo spec:rules:- host: www1.westos.orghttp:paths:- path: /backend:serviceName: myserviceservicePort: 80 [root@server2 ~]# kubectl apply -f nginx.yml
做好地址解析:
用DaemonSet結合nodeselector來部署ingress-controller到特定的node上,然后使用HostNetwork直接把該pod與宿主機node的網(wǎng)絡打通,直接使用宿主機的80/443端口就能訪問服務。
- 優(yōu)點是整個請求鏈路最簡單,性能相對NodePort模式更好。
- 缺點是由于直接利用宿主機節(jié)點的網(wǎng)絡和端口,一個node只能部署一個ingress-controller pod。
比較適合大并發(fā)的生產(chǎn)環(huán)境使用。
Ingress TLS 加密配置
生成證書: [root@server2 ingress-nginx]# openssl req -x509 -sha256 -nodes -days 365 -newkey rsa:2048 -keyout tls.key -out tls.crt -subj "/CN=nginxsvc/O=nginxsvc" 導入證書: [root@server2 ingress-nginx]# kubectl create secret tls tls-secret --key tls.key --cert tls.crt 查看證書: [root@server2 ingress-nginx]# kubectl get secrets
生效:
認證
[root@server2 ingress-nginx]# yum install httpd-tools.x86_64 -y [root@server2 ingress-nginx]# htpasswd -c auth sun [root@server2 ingress-nginx]# kubectl create secret generic basic-auth --from-file=auth [root@server2 ingress-nginx]# vim tls.ymlannotations:nginx.ingress.kubernetes.io/auth-type: basicnginx.ingress.kubernetes.io/auth-secret: basic-auth [root@server2 ingress-nginx]# kubectl apply -f tls.yml [root@server2 ingress-nginx]# kubectl apply -f nginx.yml
Ingress地址重寫
vim tls.yml apiVersion: networking.k8s.io/v1beta1 kind: Ingress metadata:name: nginx-testannotations:nginx.ingress.kubernetes.io/rewrite-target: /$2 spec:rules:- host: www1.westos.orghttp:paths:- backend:serviceName: myserviceservicePort: 80path: /westos(/|$)(.*)kubectl apply -f tls.yml curl www1.westos.org == curl www1.westos.org/westos- annotations參數(shù)
總結
- 上一篇: bind-utils.x86_64(di
- 下一篇: Django入门-项目创建与初识子应用