Kubernetes中外部客戶端訪問Pod的幾種方式


kubernetes集群上運行的pod,在集群內訪問是很容易的,最簡單的,可以通過pod的ip來訪問,也可以通過對應的svc來訪問,但在集群外,由於kubernetes集群的pod ip地址是內部網絡地址,因此從集群外是訪問不到的。

為了解決這個問題,kubernetes提供了如下幾個方法。

  • hostNetwork
  • hostPort
  • service NodePort

hostNetwork: true
hostNetwork為true時,容器將使用宿主機node的網絡,因此,只要知道容器在哪個node上運行,從集群外以 node-ip + port 的方式就可以訪問容器的服務。

apiVersion: v1
kind: Pod
metadata:
  name: nginx
spec:
  hostNetwork: true
  containers:
    - name: nginx
      image: nginx

pod啟動后,如下,可以看到pod的ip地址與node節點的地址是一致的

[root@localhost ~]# kubectl get pods -o wide nginx
NAME    READY   STATUS    RESTARTS   AGE    IP              NODE       NOMINATED NODE
nginx   1/1     Running   0          8m2s   192.168.10.10   minikube   <none>

[root@localhost ~]# kubectl get nodes -o wide 
NAME       STATUS   ROLES    AGE   VERSION   INTERNAL-IP     EXTERNAL-IP   OS-IMAGE                KERNEL-VERSION          CONTAINER-RUNTIME
minikube   Ready    master   11d   v1.12.1   192.168.10.10   <none>        CentOS Linux 7 (Core)   3.10.0-957.el7.x86_64   docker://17.12.1-ce

可以通過curl或者瀏覽器直接訪問node節點的地址,即可以訪問到nginx的服務

[root@localhost ~]# curl http://192.168.10.10
<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
......
</html>
[root@localhost ~]# 

hostNetwork的優點是直接使用宿主機的網絡,只要宿主機能訪問,Pod就可以訪問;但缺點也是很明顯的:

  • 易用性:Pod漂移到其他node上,訪問時需要更換ip地址。解決方法是將Pod綁定在某幾個node上,並在這幾個node上運行keepalived以漂移vip,從而客戶端可以使用vip+port的方式來訪問。
  • 易用性:Pod間可能出現端口沖突,造成Pod無法調度成功。
  • 安全性:Pod可以直接觀察到宿主機的網絡。

hostPort
hostPort的效果與hostNetwork類似,hostPort是直接將容器的端口與所調度的節點上的端口進行映射,這樣用戶就可以通過宿主機的IP加上映射到綁定主機的端口來訪問Pod了

apiVersion: v1
kind: Pod
metadata:
  name: nginx
spec:
  containers:
    - name: nginx
      image: nginx
      ports:
        - containerPort: 80     #pod容器指定的端口
          hostPort: 9090        #映射到node主機的端口

pod啟動后如下,可以看到,pod的ip地址是內部網絡ip,與宿主機node的ip不同;與hostNetwork一樣,也可以通過node ip + pod port訪問,此處的訪問port地址為,pod容器端口映射到node主機的端口地址

[root@localhost ~]# kubectl get pods -o wide nginx
NAME    READY   STATUS    RESTARTS   AGE   IP           NODE       NOMINATED NODE
nginx   1/1     Running   0          57s   172.17.0.2   minikube   <none>
[root@localhost ~]# 

可以curl訪問,也可以瀏覽器訪問

[root@localhost ~]# curl -I http://192.168.10.10:9090
HTTP/1.1 200 OK
Server: nginx/1.19.2
Date: Tue, 01 Sep 2020 09:56:16 GMT
Content-Type: text/html
Content-Length: 612
Last-Modified: Tue, 11 Aug 2020 14:50:35 GMT
Connection: keep-alive
ETag: "5f32b03b-264"
Accept-Ranges: bytes

[root@localhost ~]# 

hostPort的優缺點與hostNetwork類似,因為它們都是使用了宿主機的網絡資源。hostPort相對hostNetwork的一個優點是,hostPort不需要提供宿主機的網絡信息,但其性能不如hostNetwork,因為需要經過iptables的轉發才能到達Pod。

service NodePort
與hostPort、hostNetwork只是Pod的配置不同,NodePort是一種service,其使用的是宿主機node上的端口號,從集群外以 任意node的ip + nodePort 來訪問Pod的服務。

NodePort 在 kubenretes 里是一個廣泛應用的服務暴露方式。Kubernetes中的service默認情況下都是使用的ClusterIP這種類型,這樣的service會產生一個ClusterIP,這個IP只能在集群內部訪問,要想讓外部能夠直接訪問service,需要將service type修改為 nodePort。

apiVersion: v1
kind: Pod
metadata:
  name: nginx
  labels:
    name: nginx
spec:
  containers:
    - name: nginx
      image: nginx
      ports:
        - containerPort: 80
---
kind: Service
apiVersion: v1
metadata:
  name: nginx
spec:
  type: NodePort
  ports:
    - name: nginx
      port: 80
      nodePort: 30000
  selector:
    name: nginx

svc 配置中的nodePort,即為訪問服務時,宿主機的端口號。可以在配置文件中指定(當然不能與其他nodePort類型的svc沖突),也可以不配置,由k8s來分配。

創建上述Pod和service后,如下,查看pod和svc的相關信息,我們可以通過宿主機的ip地址+noePort來訪問pod的服務

[root@localhost ~]# kubectl get pods -o wide nginx
NAME    READY   STATUS    RESTARTS   AGE     IP           NODE       NOMINATED NODE
nginx   1/1     Running   0          5m47s   172.17.0.2   minikube   <none>
[root@localhost ~]# 
[root@localhost ~]# kubectl get svc -o wide nginx
NAME    TYPE       CLUSTER-IP      EXTERNAL-IP   PORT(S)        AGE     SELECTOR
nginx   NodePort   10.96.116.150   <none>        80:30000/TCP   5m58s   name=nginx
[root@localhost ~]# 
[root@localhost ~]# kubectl get nodes -o wide
NAME       STATUS   ROLES    AGE   VERSION   INTERNAL-IP     EXTERNAL-IP   OS-IMAGE                KERNEL-VERSION          CONTAINER-RUNTIME
minikube   Ready    master   11d   v1.12.1   192.168.10.10   <none>        CentOS Linux 7 (Core)   3.10.0-957.el7.x86_64   docker://17.12.1-ce
[root@localhost ~]# 
[root@localhost ~]# curl -I http://192.168.10.10:30000
HTTP/1.1 200 OK
Server: nginx/1.19.2
Date: Tue, 01 Sep 2020 10:14:12 GMT
Content-Type: text/html
Content-Length: 612
Last-Modified: Tue, 11 Aug 2020 14:50:35 GMT
Connection: keep-alive
ETag: "5f32b03b-264"
Accept-Ranges: bytes

[root@localhost ~]# 

集群外就可以使用kubernetes任意一個節點的IP加上30000端口訪問該服務了。kube-proxy會自動將流量以round-robin的方式轉發給該service的每一個pod。

這種服務暴露方式,無法讓你指定自己想要的應用常用端口,不過可以在集群上再部署一個反向代理作為流量入口

service的作用體現在兩個方面,對集群內部,它不斷跟蹤pod的變化,更新endpoint中對應pod的對象,提供了ip不斷變化的pod的服務發現機制,對集群外部,他類似負載均衡器,可以在集群內外部對pod進行訪問。但是,單獨用service暴露服務的方式,在實際生產環境中不太合適:
ClusterIP的方式只能在集群內部訪問。
NodePort方式的話,測試環境使用還行,當有幾十上百的服務在集群中運行時,NodePort的端口管理是災難。
LoadBalance方式受限於雲平台,且通常在雲平台部署ELB還需要額外的費用。
————————————————

LoadBalancer、Ingress可以實現pod的外網訪問,后續在做整理...

 

參考文檔:https://ieevee.com/tech/2020/01/06/access-pods.html


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM