Kubernetes 120:網路基礎
如果你讀過該系列的前一篇文章,那麼在你的叢集裡應該已經成功執行著Gitea的deployment了。下一步是能夠通過web瀏覽器訪問它。本文會介紹一些Kubernetes的網路基礎知識,並且可以讓外部網路可以訪問Gitea容器。
開啟容器埠
Pod預設是和外部隔離的。為了能夠將流量匯入應用程式,我們需要開啟該容器計劃使用的一系列埠。
Gitea容器內的軟體會監聽3000埠上的http請求,以及22埠上的ssh連結。可以通過如下YAML檔案開啟這些埠:
apiVersion: extensions/v1beta1 kind: Deployment metadata: name: gitea-deployment spec: replicas: 1 selector: matchLabels: app: gitea template: metadata: labels: app: gitea spec: containers: - name: gitea-container image: gitea/gitea:1.4 ports:#+ - containerPort: 3000#+ name: http#+ - containerPort: 22#+ name: ssh
在叢集裡應用這個更新過的檔案:
$ kubectl apply -f gitea.yaml
這時,就可以執行命令kubectl describe deployment
來檢視新開啟的埠了。Pod應該已經打開了3000和22埠。
$ kubectl describe deployment | grep Ports Ports:3000/TCP, 22/TCP
使用埠轉發進行除錯
容器上的埠應該已經開啟了,但是我們仍然需要能夠和叢集裡的pod通訊。為了除錯的方便,我們可以使用kubectl port-forward
來連線pod。
# grab the name of your active pod $ PODNAME=$(kubectl get pods --output=template \ --template="{{with index .items 0}}{{.metadata.name}}{{end}}") # open a port-forward session to the pod $ kubectl port-forward $PODNAME 3000:3000
這樣,kubectl
就會將本機3000埠的所有連線轉發到雲上的pod裡。在瀏覽器開啟ofollow,noindex" target="_blank">http://localhost:3000
,你就可以和伺服器互動了,伺服器就像執行在本地一樣。


建立外部LoadBanlancer
既然已經驗證了pod工作正常,就可以暴露到公網上了。我們需要新增一個新的Kubernetes資源,它會預配一個公網IP地址並且將入站請求路由到pod上。可以使用稱為Service(服務)的Kubernetes資源來達到這一目的。可以使用好幾種不同型別的服務 ,但是這裡我們使用LoadBalancer。
apiVersion: extensions/v1beta1 kind: Deployment metadata: name: gitea-deployment spec: replicas: 1 selector: matchLabels: app: gitea template: metadata: labels: app: gitea spec: containers: - name: gitea-container image: gitea/gitea:1.4 ports: - containerPort: 3000 name: http - containerPort: 22 name: ssh --- kind: Service#+ apiVersion: v1#+ metadata:#+ name: gitea-service#+ spec:#+ selector:#+ app: gitea#+ ports:#+ - protocol: TCP#+ targetPort: 3000#+ port: 80#+ name: http#+ - protocol: TCP#+ targetPort: 22#+ port: 22#+ name: ssh#+ type: LoadBalancer#+
和Deployment一樣,Service使用選擇器(第29-30行)。這個選擇器告訴LoadBanlancer將流量路由到哪些pod裡。當LoadBanlancer收到請求時,它會智慧地將負載分發給匹配這個選擇器的所有pod。這裡,因為我們僅有一個pod,所以負載均衡很簡單。
LoadBanlancer管理的埠定義在31-39行。除了定義一個唯一名稱以及協議型別(TCP/UDP)之外,使用者還必須定義“port”和“targetPort”。這兩個欄位定義了外部IP的埠(port)和容器使用埠(targetPort)的對映。在33和34行裡,LoadBanlancer會監聽80埠的請求(web瀏覽器檢視網頁的預設埠),並且將請求轉發給pod的3000埠。
我們再次需要將更改應用到叢集裡
$ kubectl apply -f gitea.yaml
等待幾分鐘變更生效後,檢查服務
$ kubectl get service NAMETYPECLUSTER-IPEXTERNAL_IPAGE gitea-serviceLoadBalancer10.27.240.3435.192.x.x2m
幾分鐘後,就能看到一個外部IP自動新增到了服務上。在web瀏覽器裡開啟這個IP就可以和pod上的web伺服器互動了。

Pod間通訊:ClusterIP服務
如果你嘗試開啟Gitea的註冊頁面,會看到還缺了一些東西:Gitea要求一個資料庫才能提供這個功能。要解決這個問題,我們可以選擇在Gitea pod裡以side-car 的形式新增一個SQL/">MySQL容器,或者單獨建立一個MySQL的pod。這兩種方法都有各自的優勢和缺點,選擇哪一個取決於具體的需求。本文我們建立一個新的pod。
我們建立一個名為mysql.yaml 的新YAML檔案來管理資料庫:
apiVersion: extensions/v1beta1 kind: Deployment metadata: name: mysql-deployment spec: replicas: 1 selector: matchLabels: app: mysql template: metadata: labels: app: mysql spec: containers: - name: mysql image: mysql:5.6 ports: - containerPort: 3306 # Ignore this for now. It will be explained in the next article env: - name: MYSQL_ALLOW_EMPTY_PASSWORD value: "true" --- kind: Service apiVersion: v1 metadata: name: mysql-service spec: selector: app: mysql ports: - protocol: TCP port: 3306 type: ClusterIP
大部分內容很類似。我們聲明瞭一個Deployment來管理這個pod,通過Service管理網路連線。這裡,service的型別是“ClusterIP”;這意味著這個IP僅僅暴露在叢集內部,這和之前使用LoadBanlancer將Gitea服務暴露到外部不一樣。
在叢集裡應用這個新YAML檔案:
$ kubectl apply -f mysql.yaml
這時你可以看到叢集裡新加了一個pod,deployment和service。
$ kubectl get pods NAMEREADYSTATUSRESTARTSAGE gitea-pod1/1Running09m mysql-pod1/1Running09s $ kubectl get deployments NAMEDESIREDCURRENTUP-TO-DATEAVAILABLEAGE gitea-deployment111111m mysql-deployment11115m $ kubectl get services NAMETYPECLUSTER-IPEXTERNAL_IPAGE gitea-serviceLoadBalancer10.27.240.3435.192.x.x2m mysql-serviceClusterIP10.27.254.69<none>6m
ClusterIP服務會自動生成一個內部IP地址,顯示在上面控制檯輸出的“CLUSTER-IP”一欄。叢集內的任何容器都可以使用這一地址訪問MySQL pod。但是,並不推薦直接使用內部IP地址。Kubernetes提供了更為簡單的方式來訪問這個新服務:可以在地址欄位輸入“mysql-service”即可。這是因為內建了“kube-dns ”pod,它為所有服務管理內部的DNS解析。這樣,使用者可以忽略隨機生成的內部IP地址,僅僅使用靜態的,可讀的服務名稱就可以了。
要讓Gitea能夠和MySQL pod通訊,僅僅需要在web UI的“host”欄位輸入服務的名稱和埠就可以了。如果一切和預期一樣,就會看到“access denied”的錯誤。這意味著pod可以成功通訊了,但是它們需要更多的配置資訊才能完成認證。下一篇部落格會繼續介紹如何完成認證。
下一步
本文介紹了Kubernetes網路的基礎知識,包括容器埠,埠轉發,LoadBanlancer以及ClusterIP服務和kube-dns。當然,網路是一個很大的領域,沒有討論的還有很多。如果你想了解Kubernetes的底層網路實現,可以參考這個系列 。如果你對控制叢集裡的哪些pod可以通訊感興趣,可以閱讀網路策略 。如果你想更好地控制服務間的相互通訊,可以研究服務網格產品,比如Istio .
備註
kubectl get pods --namespace=kube-system原文連結:Kubernetes 120: Networking Basics (翻譯:崔婧雯)
===========================
譯者介紹
崔婧雯,現就職於IBM,高階軟體工程師,負責IBM WebSphere業務流程管理軟體的系統測試工作。曾就職於VMware從事桌面虛擬化產品的質量保證工作。對虛擬化,中介軟體技術,業務流程管理有濃厚的興趣。