k8s入門-使用Service管理Pod訪問

我們通過Deployment可以爲一個應用創建多個Pod,而且可以動態的進行增加、或者刪除多餘的Pod,Kubernetes Pod 是有生命週期的,它們可以被創建,也可以被銷燬,但是每次Pod的IP地址就會發生變化,外面如何訪問到該Pod呢?總不能每次Pod重啓就修改訪問的IP地址吧。 每個 Pod 都會獲取它自己的 IP 地址,但是每次即使這些 IP 地址不總是穩定可依賴的。 這會導致一個問題:在 Kubernetes 集羣中,如果一組 Pod(稱爲 backend)爲其它 Pod (稱爲 frontend)提供服務,那麼那些 frontend 該如何發現,並連接到這組 Pod 中的哪些 backend 呢?

這個時候就要用到Service了。

一、Service概念

Service定義了一個服務的訪問入口地址,前端的應用(Pod)通過這個入口地址訪問其背後的一組由Pod副本組成的集羣實例。 Service與其後端Pod副本集羣之間則是通過Label Selector來實現"無縫對接"

既然每個Pod都會被分配一個單獨的IP地址,而且每個Pod都提供了一個獨立的Endpoint**(Pod IP+ContainerPort)**以被客戶端訪問,現在多個Pod副本組成了一個集羣來提供訪問。

Kubernetes 需要在每個Node上安裝kube-proxy,kube-proxy進程其實就是一個智能的軟件負載均衡器,它負責把對Service的請求轉發到後端的某個Pod實例上,並在內部實現服務的負載均衡與會話保持機制。

Kubernetes發明了一個很巧明的設計,Service不是共用一個負載均衡器的IP地址,而是每個Service分配了一個全局唯一的虛擬IP地址,這個虛擬IP被稱爲Cluster IP。這樣每個服務就變成了具備唯一IP地址的"通信節點",服務調用就變成了最基礎的TCP網絡通信問題。而且在Service的整個聲明週期內,它的Cluster IP不會發生改變

二、Service的幾種類型

在Serive定義時,我們需要指定spec.type字段,這個字段擁有四個選項:

ClusterIP。默認值。給這個Service分配一個Cluster IP,它是Kubernetes系統自動分配的虛擬IP,因此只能在集羣內部訪問。

NodePort。將Service通過指定的Node上的端口暴露給外部。通過此方法,訪問任意一個NodeIP:nodePort都將路由到ClusterIP,從而成功獲得該服務。

LoadBalancer。在 NodePort 的基礎上,利用其他第三方的LB暴露服務的,谷歌或者亞馬遜的LB等等。

ExternalName。將服務通過 DNS CNAME 記錄方式轉發到指定的域名(通過 spec.externlName 設定)。需要 kube-dns 版本在 1.7 以上。

三、Service示例

1、ClusterIP

繼續我們Nginx的案例,之前用DaemonSet創建了nginx應用,現在爲這些應用創建一個Service

[root@k8s-01 ~]# cat nginx-service.yaml 
kind: Service
apiVersion: v1
metadata:
  name: nginx-service
spec:
  selector:
    app: nginx
  ports:
  - protocol: TCP
    port: 80
    targetPort: 80
  • 第1行:定義資源類型爲Service
  • 第2行:定義當前Service API的版本
  • 第3行:metadata設置
  • 第4行:設置Service的名稱爲nginx-service
  • 第5行:spec: 開始設置Service的內容
  • 第6行:selector: 爲該Service指定一個匹配的標籤
  • 第7行:app: nginx 所有帶有標籤app:nginx的Pod將使用該Service
  • 第8行:ports: 指定Service需要對外的端口
  • 第9行:設置端口協議:支持TCP和UDP
  • 第10行:設置Service的端口
  • 第11行:設置Pod的端口,Kubernetes會將發送給Service端口的連接,轉發到Pod的端口上。

創建Nginx Service

[root@k8s-01 ~]# kubectl create -f nginx-service.yaml
service/nginx-service created

查看Nginx Service

[root@k8s-01 ~]# kubectl get service
NAME            TYPE        CLUSTER-IP       EXTERNAL-IP   PORT(S)        AGE
kubernetes      ClusterIP   10.254.0.1       <none>        443/TCP        18d
nginx-service   ClusterIP   10.254.247.47    <none>        80/TCP         10s

訪問Servce IP

[root@k8s-01 ~]# curl --head 10.254.247.47
HTTP/1.1 200 OK
Server: nginx/1.13.12
Date: Tue, 12 May 2020 07:26:00 GMT
Content-Type: text/html
Content-Length: 612
Last-Modified: Mon, 09 Apr 2018 16:01:09 GMT
Connection: keep-alive
ETag: "5acb8e45-264"
Accept-Ranges: bytes

2、NodePort

在開始之前,將之前創建的pod和service清理下。

1)通過指令創建NodePort

nginx的yaml文件:

[root@k8s-01 ~]# cat nginx-pod.yaml 
apiVersion: v1
kind: Pod
metadata:
  name: nginx-pod
  labels:
    app: nginx
spec:
  containers:
  - name: nginx
    image: nginx
    ports:
    - containerPort: 80

創建並查看Pod

[root@k8s-01 ~]# kubectl create -f nginx-pod.yaml 
pod/nginx-pod created


[root@k8s-01 ~]# kubectl get pod
NAME                        READY   STATUS    RESTARTS   AGE
nginx-pod                   1/1     Running   0          26s

[root@k8s-01 ~]# kubectl get pod -o wide
NAME                        READY   STATUS    RESTARTS   AGE   IP              NODE     NOMINATED NODE   READINESS GATES
nginx-pod                   1/1     Running   0          32s   172.30.64.4     k8s-01   <none>           <none>

現在用命令將其配置爲NodePort的形式:

[root@k8s-01 ~]# kubectl expose pod nginx-pod --type=NodePort
service/nginx-pod exposed

[root@k8s-01 ~]# kubectl get svc
NAME            TYPE        CLUSTER-IP       EXTERNAL-IP   PORT(S)        AGE
kubernetes      ClusterIP   10.254.0.1       <none>        443/TCP        18d
nginx-pod       NodePort    10.254.199.142   <none>        80:30248/TCP   29s

這個時候可以看到nginx-pod的類型變成了NodePort,而且後面也寫明瞭端口的映射關係:將pod中的80端口映射到node的30248端口。

現在就直接訪問node的30248端口:

master:
在這裏插入圖片描述

node:
在這裏插入圖片描述

2)通過yaml形式創建NodePort

在開始之前,先刪除剛剛的service

[root@k8s-01 ~]# kubectl delete svc nginx-pod
service "nginx-pod" deleted

然後編寫yaml文件

[root@k8s-01 ~]# cat service-nginx.yml 
kind: Service
apiVersion: v1
metadata:
  name: nginx-service
spec:
  selector:
    app: nginx
  type: NodePort
  ports:
    - protocol: TCP
      port: 32001
      targetPort: 80
      nodePort: 32111
  • port:service暴露在cluster ip(Seriver ip )上的端口,:port 是提供給集羣內部客戶訪問service的入口。
  • nodePort:kubernetes提供給集羣外部客戶訪問service入口的一種方式(另一種方式是[LoadBalancer]),是提供給集羣外部客戶訪問service的入口。
  • targetPort:targetPort很好理解,targetPort是pod上的端口,從port和nodePort上到來的數據最終經過kube-proxy流入到後端pod的targetPort上進入容器。

創建:

[root@k8s-01 ~]# kubectl create -f service-nginx.yml
service/nginx-service created

訪問:
在這裏插入圖片描述

四、外部系統訪問Service問題

我們需要掌握kubernetes中的三種IP

  • Node IP:Node節點IP地址
  • Pod IP:Pod的IP地址
  • Cluster IP:Service的IP地址

NodePort的實現方式是在Kubernetes集羣裏的每個Node上爲需要外部訪問的Service開啓一個對應的TCP請求,外部系統只要用任意Node的IP地址+具體的NodePort端口即可訪問服務,在任意node上運行netstat服務,我們可以看到NodePort端口被監聽。

但NodePort還沒有完全解決外部訪問Service的所有問題,比如負載均衡的問題,假如說我們集羣中有10個Node,則此時最好有一個負載均衡,外部的請求只需要訪問此負載均衡器的IP地址,由負載均衡負責轉發流量到後面的node上。
在這裏插入圖片描述

上圖中Load balancer組件獨立於Kubernetes集羣之外,通常是一個硬件的負載均衡器,或者是以軟件方式實現的,例如Haproxy或者Nginx。對於每個Service,我們通常配置一個對應的Load balancer實例來轉發流量到後端的Node。

參考文章:
https://k.i4t.com/kubernetes_service.html
http://k8s.unixhot.com/kubernetes/service-admin.html
http://www.eryajf.net/2127.html

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章