一、service
service作用
1.通過service為pod用戶端提供通路pod方法,即可用戶端通路pod入口 通過标簽動态感覺pod IP位址變化等
2.防止pod失聯
3.定義通路pod通路政策
4.通過label-selector相關聯
5.通過Service實作Pod的負載均衡(TCP/UDP 4層)
6.底層實作主要通過iptables和IPVS二種網絡模式
service底層實作原理
底層流量轉發與負載均衡實作均可以通過iptables或ipvs實作
iptables實作
ipvs實作
對比:
Iptables:
靈活,功能強大(可以在資料包不同階段對包進行操作) 規則周遊比對和更新,呈線性時延
IPVS:
工作在核心态,有更好的性能
排程算法豐富:rr,wrr,lc,wlc,ip hash...
service類型
service類型分為:
ClusterIP
預設,配置設定一個叢集内部可以通路的虛拟IP
NodePort
在每個Node上配置設定一個端口作為外部通路入口
LoadBalancer
工作在特定的Cloud Provider上,例如Google Cloud,AWS, OpenStack
ExternalName
表示把叢集外部的服務引入到叢集内部中來,即實作了叢集内部
pod和叢集外部的服務進行通信
二、ClusterIP類型
普通ClusterIP類型
ClusterIP根據是否生成ClusterIP又可分為普通Service和Headless Service 兩類:
普通Service:
為Kubernetes的Service配置設定一個叢集内部可通路的固定虛拟
IP(Cluster IP), 通過iptables或ipvs實作負載均衡通路pod。
Headless Service:
該服務不會配置設定Cluster IP, 也不通過kube-proxy做反向代理和負載均 衡。而是通過DNS提供穩定的網絡ID來通路,DNS會将headless service的後端直接解析為pod IP清單。
指令建立普通service
1.準備YAML并建立deployment
vim deployment-nginx.yml
apiVersion: apps/v1
kind: Deployment
metadata:
name: deploy-nginx
spec:
replicas: 2
selector:
matchLabels:
app: nginx
template:
metadata:
labels:
app: nginx
spec:
containers:
- name: nginx
image: nginx:1.15-alpine
imagePullPolicy: IfNotPresent
ports:
- containerPort: 80
kubectl apply -f deployment-nginx.yml
2.檢視目前的service
kubectl get services # 或者 使用svc簡寫
預設隻有kubernetes本身自己的services
3.将名為nginx1的deployment映射端口
kubectl expose deployment deploy-nginx --port=80 --target-port=80 --protocol=TCP
說明:
預設是--type=ClusterIP,也可以使用--type="NodePort"
或 --type="ClusterIP"
4.驗證
kubectl get svc
kubectl get endpoints # endpoints可簡寫為ep
5.通路(叢集内部任意節點可通路), 叢集外部不可通路
curl 10.68.101.47
YAML建立普通service
1.直接使用上節内容建立的deployment,确認pod的标簽為app=nginx
kubectl get pods -l app=nginx
2.YAML編寫ClusterIP類型service
vim nginx_service.yml
apiVersion: v1
kind: Service
metadata:
name: my-service
namespace: default
spec:
type: ClusterIP # ClusterIP類型,也是預設類型
ports: # 指定service 端口及容器端口
- port: 80
protocol: TCP
targetPort: 80 # pod中的端口
selector: # 指定後端pod标簽(不是deployment 的标簽)
app: nginx
解釋如下:
apiVersion: v1
kind: Service
metadata:
name: my-service
namespace: default
spec:
clusterIP: 10.2.11.22 # 這個ip可以不指定,讓它自動配置設定,需 要與叢集配置設定的網絡對應
type: ClusterIP # ClusterIP類型,也是預設類型
ports: # 指定service 端口及容器端口
- port: 80
protocol: TCP
targetPort: 80 # pod中的端口
selector: # 指定後端pod标簽(不是deployment 的标簽)
app: nginx # 表示此service關聯app:nginx标簽 的pod
3, 應用YAML建立service
kubectl apply -f nginx_service.yml
4, 驗證檢視
5.叢集内節點通路驗證
curl 10.68.23.55
注意:叢集内節點都可通路,叢集外不可通路
驗證負載均衡
問題: 一共2個pod,那麼通路的到底是哪一個呢?
答案: 2個pod會負載均衡。
1.兩個pod裡做成不同的首頁友善測試負載均衡
kubectl exec -it deploy-nginx-6c9764bb69-jrnbh -- /bin/sh
cd /usr/share/nginx/html/
echo web1 > index.html
exit
kubectl exec -it deploy-nginx-6c9764bb69-vswlq -- /bin/sh
cd /usr/share/nginx/html/
echo web2 > index.html
exit
2.測試
curl 10.68.23.55 # 多次通路有負載均衡
curl 10.68.101.47 # 多次通路也有負載均衡,因為我兩個service關聯的是相同的兩個pod
sessionAffinity(會話連接配接)
設定sessionAffinity為Clientip (類似nginx的ip_hash算法,lvs的source hash算法)
kubectl patch svc my-service -p '{"spec":{"sessionAffinity":"ClientIP"}}'
測試
curl 10.68.23.55 # 多次通路,會話粘貼
設定回sessionAffinity為None
kubectl patch svc my-service -p '{"spec":{"sessionAffinity":"None"}}'
curl 10.68.23.55 # 多次通路, 回到負載均衡
普通service的DNS解析
DNS服務監視Kubernetes API,為每一個Service建立DNS記錄用于域名解
析
DNS記錄格式為: ..svc.cluster.local
1, 檢視k8s的dns服務的IP
kubectl get svc -n kube-system |grep dns
2.查詢得到dns服務的IP為10.68.0.2, 查詢服務的endpoints
kubectl get endpoints
3.在node上驗證dns解析
yum -y install bind-utils
nslookup deploy-nginx.default.svc.cluster.local 10.68.0.2
nslookup my-service.default.svc.cluster.local 10.68.0.2
注意:
在node上驗證不能直接curl my-service.default.svc.cluster.local去通路,因為在node上操 作,會預設走/etc/resolv.conf 裡的DNS,而不是走k8s自己的DNS 伺服器,是以上面驗證指令nslookup需要後面加上k8s自己的DNS服 務器IP
在pod裡就可以直接對service的域名進行操作了
4.在pod裡驗證dns解析
kubectl run busybox sleep 1000000 --image=busybox
kubectl get pods
kubectl exec -it busybox -- /bin/sh
/ # ping my-service.default.svc.cluster.local.
#直接可以通過域名解析到service-IP
因為busybox鏡像裡沒有curl和yum指令,是以用wget通過域名下載下傳pod 的首頁,也是OK的
/ # wget my-service.default.svc.cluster.local./index.html
cat index.html
rm index.html -rf
wget my-service.default.svc.cluster.local./index.html
結論:
dns傳回的結果為service的IP,而不是pod的IP
也就是說客戶通路dns,解析為service的IP,再通過iptables或ipvs負載均衡到pod
iptables與ipvs排程方式修改
在kubeasz安裝時,預設現在指定為ipvs排程模式了,如果要改成 iptables模式,操作如下
systemctl cat kube-proxy |grep proxy-mode
vim /etc/systemd/system/kube-proxy.service
--proxy-mode=iptables # k8s叢集所有節點都将此參數由 ipvs改成iptables
改完之後,重新開機kube-proxy服務無法直接生效,需要把整個k8s叢集重 啟。
systemctl restart kube-proxy
systemctl daemon-reload
注意: 測試完後,請再改回成ipvs模式,重新開機叢集生效。(不建議使用iptables排程)
如果是kubeadm安裝,那麼預設為iptables排程模式,則可使用下面的方式修改
1, 修改kube-proxy的配置檔案
kubectl edit configmap kube-proxy -n kube-system
2, 檢視kube-system的namespace中kube-proxy有關的pod
kubectl get pods -n kube-system |grep kube-proxy
3, 驗證kube-proxy-xxx的pod中的資訊
4, 删除kube-proxy-xxx的所有pod,讓它重新拉取新的kube-proxy-xxx的 pod
kubectl delete pod kube-proxy-22x22 -n kube-system
kubectl delete pod kube-proxy-wk77n -n kube-system
kubectl delete pod kube-proxy-wnrmr -n kube-system
5, 随意檢視其中1個或3個kube-proxy-xxx的pod,驗證是否為IPVS方式了
6, 安裝ipvsadm檢視規則
yum install ipvsadm -y
ipvsadm -Ln
7, 再次驗證,就是标準的rr算法了
curl 10.2.11.22 # 多次通路,rr輪循
headless service
普通的ClusterIP service是service name解析為cluster ip,然後cluster ip對 應到後面的pod ip
而無頭service是指service name 直接解析為後面的pod ip
建立headless service
1.編寫YAML檔案
vim headless-service.yml
apiVersion: v1
kind: Service
metadata:
name: headless-service
namespace: default
spec:
clusterIP: None # None就代表是無頭 service
type: ClusterIP # ClusterIP類型,也 是預設類型
ports: # 指定service 端口 及容器端口
- port: 80 # service ip中的端 口
protocol: TCP
targetPort: 80 # pod中的端口
selector: # 指定後端pod标簽
app: nginx # 表示此service關聯 app:nginx标簽的pod
2.應用YAML檔案建立無頭服務
kubectl apply -f headless-service.yml
3.驗證
可以看到headless-service沒有CLUSTER-IP,用None表示
headless service的DNS解析
1. 檢視kube-dns服務的IP
2.能過DNS服務位址查找無頭服務的dns解析
nslookup headless-service.default.svc.cluster.local 10.68.0.2
3.驗證pod的IP
kubectl get pods -o wide