本文為作者的 Kubernetes 系列電子書的一部分,電子書已經開源,歡迎關注,電子書瀏覽地址:
https://k8s.whuanle.cn【適合國內訪問】
https://ek8s.whuanle.cn 【gitbook】
在 3.1,3.2 中,我們部署過了 Nginx 容器,使用了 --port=8080
或 containerPort: 8080
為 Pod 暴露一個端口,本章只是簡單地為 Pod 創建 Service,並且介紹 Pod 的一些網絡知識,在第四章中會詳細講解網絡方面的知識。
containerPort
這個字段用於規范化聲明容器對外暴露的端口,但這個端口並不是容器映射到主機的端口,它是一個聲明式的字段,屬於容器端口規范。
在很多情況下,我們不需要設置此 containerPort 也可以直接訪問 Pod。
讀者可以把上一章中創建的 deployment 刪除,然后重新創建。
kubectl create deployment nginx --image=nginx:latest
然后獲取 Pod 的 IP:
root@master:~# kubectl get pods -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
nginx-55649fd747-zndzx 1/1 Running 0 7m57s 10.32.0.2 slave1 <none> <none>
然后訪問 10.32.0.2 ,會發現正常打開。
加不加端口映射都可以訪問 80 ,它是一個容器端口規范,跟 Dockerfile 的 port 一樣,不具有強制開放的功能,在創建 Service 時有用處。
[Error] 提示
如果你沒有配置過 CNI 網絡插件,則創建的 Pod IP,只能在所在的節點中訪問,要跨節點訪問,請按照 2.2 的初始化網絡,或 2.3 中的 Calico 一節,安裝好網絡插件。
另外,如果 Calico 配置錯誤,會導致一直無法創建 Pod。
我們在創建 Pod 時,如果指定了 --port
,那么這個端口便會生成 containerPort
,可以使用下面的命令查看創建的 Deployment YAML 的定義:
kubectl create deployment nginx --image=nginx:latest --port=80 --dry-run=client -o yaml
containers:
- image: nginx:latest
name: nginx
ports:
- containerPort: 80
resources: {}
網絡端口映射
對於 docker,我們要映射端口時,可以使用 docker ... -p 6666:80
,那么對於 直接創建或使用 Deployment 等方式部署的 Pod,都有一個 Pod IP 可以在集群中的所有節點中訪問,但是這個 IP 是虛擬 IP,不能在集群外中訪問,即使都是內網機器,沒有加入 Kubernetes 集群,一樣不能訪問。如果我們要把端口暴露出去,供外網訪問,則可以使用 Service。
關於 Service 的知識,在第四章中會詳細講解,這里僅說明如何創建 Service,以及 containerPort 的作用。
在上一小節中,我們創建的 Pod 沒有聲明過 containerPort,因此我們創建 Service 的時候,需要指定映射的端口。
查看上一節創建的 Deployment、Pod:
kubectl get deployments
kubectl get pods
NAME READY UP-TO-DATE AVAILABLE AGE
nginx 1/1 1 1 5m44s
NAME READY STATUS RESTARTS AGE
nginx-55649fd747-9vfrx 1/1 Running 0 5m44s
通過 kubectl expose
可以快速創建 Service,並為 Deployment 部署的多個 Pod 暴露一個相同的端口。
由於 Pod 中的 nginx 訪問端口是 80,我們想在外網中訪問時使用 6666 端口,則命令如下;
kubectl expose deployment nginx --port=6666 --target-port=80
# 指定源端口為 80,要映射到 6666 端口
kubectl expose deployment nginx --port=80
# 如果沒有指定源端口,則表示其端口也是 80
如果對象直接是 Pod 或者 DaemonSet 等對象,則
kubectl expose {對象} ...
,會自動為此對象中的 Pod 創建端口映射。
查看 Service:
kubectl get services
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 13d
nginx ClusterIP 10.105.13.163 <none> 6666/TCP 6s
由於我們只是簡單地創建 Service,並沒有指定 Service 的公開程度,可以看到 TYPE
中,其類型為 ClusterIP
,表示只能在 Pod 所在的節點上通過此 IP 和端口訪問 Pod(如果安裝了 CNI 網絡插件,則任意節點皆可訪問)。
可以使用 10.105.13.163
和 6666 端口訪問 Pod 中的 Nginx 服務。
這里介紹了如何創建 Service,暴露端口,而在后面的章節中,會詳細介紹 Service。
[Info] 提示
如果已經指定過 containerPort,可以使用
kubectl expose deployment nginx
快速映射 containerPort 中指定的端口。
本地端口
每個 Pod 都有自己的唯一 IP 地址,Pod 所在的服務器上,通過 IP 地址可以直接訪問 Pod。
除了 Service,我們還可以使用 port-forward
在服務器上直接映射本地端口到 Pod。
root@instance-2:~# kubectl port-forward nginx-55649fd747-s4824 666:80
Forwarding from 127.0.0.1:666 -> 80
Forwarding from [::1]:666 -> 80
此方式具有很大限制,首先如果 Pod 在 instance-2
節點中,那么此命令在 instance-2
節點上運行才能生效,在其它節點上運行無效。
此方式只能映射本地端口,如 127.0.0.1
,不能通過外網訪問。
原本只能通過 具體的 Pod IP 才能訪問 Pod,現在在服務器上通過 127.0.0.1 也可以直接訪問服務。