1、service簡介前端
- 我的理解:service相似於一個前端代理,全部的訪問經過代理分發,不管後端怎麼變化,用戶的訪問方式始終保持不變
- service是一種爲一組功能相同的pod提供單一不變的接入點的資源(如何保證service的高可用?service自己是否會成爲瓶頸?)
- service也經過標籤選擇器來選擇對應的pod
- service能夠將特定客戶端的請求每次都指向同一個pod(使用次屬性須要考慮負載均衡的影響)
- service工做在TCP與UDP層,所以沒法基於cookie來綁定pod
- service的服務發現:
1)全部的service都以環境變量的形式存放在pod中,pod經過環境變量獲取service的IP和端口
2)DNS發現服務:
a、k8s自身在kubesystem命名空間有運行dns服務
b、其餘全部在同一集羣的pod都配置成使用該dns(k8s經過修改每一個容器的/etc/resolv.conf文件實現)
c、pod是否使用dns由pod中sepcd dnsPolicy屬性決定
d、客戶端pod在知道service的名稱的狀況下能夠經過FQDN(全侷限定域名)訪問
訪問格式:web-test.default.svc.cluster.local #service名稱.命名空間名稱.集羣本地服務名稱中使用的可配置的集羣域後綴
在同一namespace的pod能夠省略集羣域後綴及命名空間,即只須要service_name
e、端口號依舊使用環境變量獲取
- service的IP是沒法ping的,由於service的clusterIP只是一個虛擬的IP,只有與service的port結合使用時纔有意義
- 經過service訪問服務沒法記錄客戶端IP,因爲node對數據包執行了SNAT(源網絡地址轉換),所以數據包的源IP會發生改變
2、endpoint(kubectl get svc svc_name #能夠查看到endpoint)node
- Endpoint就是暴露一個服務的IP地址和端口的列表
- service的標籤選擇器是用與構建endpoint的IP、端口列表,而後存入endpoint資源中
- 手動建立endpoint(用於給沒有標籤選擇器的service建立endpoint)
- 手動建立的endpoint須要與對應的service具備相同的名稱,幷包含該服務的目標IP和端口列表
- 建立完整的service後刪除seletor選擇器,service將不會自動更新endpoint列表,能夠人爲控制endpoint
3、使用service連接外部服務 web
- 使用endpoint寫入外部服務器的IP和端口連接外部服務(默認服務發現只能連接集羣內部的服務)
- 建立ExternalName類型的服務,經過externalname屬性和ports屬性指定外部服務器的IP和端口
- 經過service訪問外部服務能夠直接連接外部服務,隱藏了外部服務的名稱、端口等信息
4、將服務暴露給外部客戶端 後端
- 建立NodePort類型的service:每一個節0點都會打開一個相同的隨機端口,用於將流量重定向到節點上的pod,外部經過node_ip:port訪問(缺點:pod更換node節點會改變訪問方式,或弄得節點故障從而致使服務不可訪問)
- 建立LoadBalancer類型的service:經過一個專用的負載均衡器訪問,客戶端經過負載均衡器的IP鏈接到服務
(雲服務商的k8s集羣一般支撐從雲基礎架構自動提供負載均衡器,用戶僅需將類型修改成LoadBalance模式便可,以後根據查看到的負載均衡IP訪問服務)
實現須要負載均衡器+獨有的公網IP
- 建立一個Ingress資源,經過一個IP地址公佈多個service
一、Ingress須要一個公網IP
二、Ingress根據請求的主機名和路勁決定請求轉發的服務
三、Ingress在網絡棧(HTTP)的應用層操做,能夠實現基於cookie的回話親和性
四、只有Ingress控制器在集羣中運行,Ingress資源才能正常工做
五、雲供應商的Ingress控制器(例如:GKE)要求Ingress指向一個NodePort服務
六、ingress工做原理:客戶端——》DNS——》返回ingress_IP——》客戶端發出HTTP請求,並在Host頭中指定域名——》控制器經過域名肯定客戶端訪問的服務——》經過該服務的Endpoint查看pod IP——》並將客戶端的請求轉發給其中一個pod(一般狀況ingress只經過service選擇pod,而不是轉發給service)
七、一個Ingress能夠暴露多個服務:經過不一樣的域名指向不一樣的service,所以在實際應用場景中,須要將Ingress用到的域名在Ingress所在的node上所有解析
- 小結:
1)Ingress決定訪問的service(選擇須要訪問的服務)
2)service選擇響應用戶請求的pod
3)建立ingress的pod時注意使用replicas機制,(使用DNS解析到多個對應的Ingress節點,以避免當pod或node故障時,經過ingress的訪問所有失效:僅我的理解)
2、service的yaml示例api
apiVersion: v1服務器
kind: Servicecookie
metadata:網絡
name: svc-testsession
spec:架構
#type: ExternalName
#externalname: www.example.com #在externalname模式是的屬性,指定外部服務器的FQDN,同時也須要指定ports屬性
sessionAffinity: ClientIp #次屬性用於使同一客戶端的請求每次都指向同一個pod(有none和client兩中選擇,默認爲none)
externalTrafficPolicy: local #負載均衡器——》service——》node——》pod(選擇了node的時候可能響應的pod不在該node上(默認隨機),此選即開啓:接受到請求的node直接使用本地的pod直接響應;缺點,若此node上無pod響應,則該請求將被直接掛起,且node上的pod數量不一致的狀況下,可能致使pod的負載不均衡
selector:
app: web
ports:
- name: http #映射多個端口時須要指定name屬性,只須要映射一個端口時能夠省略
port: 8080 #映射的端口
targetPort: 80 #pod端口
#nodePort: 30080 #節點端口,使用nodeport模式時能夠指定的屬性(不指定則自動生成隨機端口)
- name: http
port: 8443
targetPort: 443 #pod端口在pod的yaml文件中也定義有name屬性,此處能夠直接引用,這樣即便pod的端口發生變化,此處也無需修改
Ingress的yaml文件
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
name: ingress-test
spec:
tls: #使用HTTPS方式訪問,將證書建立爲secret資源使用
- hosts:
- test.example.com #使用HTTPS訪問的域名
secretName: tls-secret #建立的secret名稱
rules:
- host: test.example.com #對外暴露的域名
http:
paths:
- path: /web1 #訪問的文件路徑
backend:
service:Name: test-svc #service的名稱
servicePort: 80 #service的端口
http:
paths:
- path: /web2 #在同一host下的不一樣路徑
backend:
service:Name: test-svc2
servicePort: 80
- host: test2.example.com
http:
paths:
- path: /web1
backend:
service:Name: test2-svc
servicePort: 80