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