k8s-service

1、service簡介前端

  1. 我的理解:service相似於一個前端代理,全部的訪問經過代理分發,不管後端怎麼變化,用戶的訪問方式始終保持不變
  2. service是一種爲一組功能相同的pod提供單一不變的接入點的資源(如何保證service的高可用?service自己是否會成爲瓶頸?) 
  3. service也經過標籤選擇器來選擇對應的pod
  4. service能夠將特定客戶端的請求每次都指向同一個pod(使用次屬性須要考慮負載均衡的影響)
  5. service工做在TCP與UDP層,所以沒法基於cookie來綁定pod
  6. 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、端口號依舊使用環境變量獲取
  7. service的IP是沒法ping的,由於service的clusterIP只是一個虛擬的IP,只有與service的port結合使用時纔有意義
  8. 經過service訪問服務沒法記錄客戶端IP,因爲node對數據包執行了SNAT(源網絡地址轉換),所以數據包的源IP會發生改變

 

2、endpoint(kubectl get svc svc_name  #能夠查看到endpoint)node

  1. Endpoint就是暴露一個服務的IP地址和端口的列表
  2. service的標籤選擇器是用與構建endpoint的IP、端口列表,而後存入endpoint資源中
  3. 手動建立endpoint(用於給沒有標籤選擇器的service建立endpoint)
  4. 手動建立的endpoint須要與對應的service具備相同的名稱,幷包含該服務的目標IP和端口列表
  5. 建立完整的service後刪除seletor選擇器,service將不會自動更新endpoint列表,能夠人爲控制endpoint

 

 

3、使用service連接外部服務 web

  1. 使用endpoint寫入外部服務器的IP和端口連接外部服務(默認服務發現只能連接集羣內部的服務)
  2. 建立ExternalName類型的服務,經過externalname屬性和ports屬性指定外部服務器的IP和端口
  3. 經過service訪問外部服務能夠直接連接外部服務,隱藏了外部服務的名稱、端口等信息

 

4、將服務暴露給外部客戶端 後端

  1. 建立NodePort類型的service:每一個節0點都會打開一個相同的隨機端口,用於將流量重定向到節點上的pod,外部經過node_ip:port訪問(缺點:pod更換node節點會改變訪問方式,或弄得節點故障從而致使服務不可訪問)
  2. 建立LoadBalancer類型的service:經過一個專用的負載均衡器訪問,客戶端經過負載均衡器的IP鏈接到服務
    (雲服務商的k8s集羣一般支撐從雲基礎架構自動提供負載均衡器,用戶僅需將類型修改成LoadBalance模式便可,以後根據查看到的負載均衡IP訪問服務)
    實現須要負載均衡器+獨有的公網IP
  3. 建立一個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上所有解析
  4. 小結:
    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 

本站公眾號
   歡迎關注本站公眾號,獲取更多信息