步步驚心:從頭部署服務到 Kubernetes (二)

幫自己的應用程式部署和設計 Service 和 Ingress

Duan Li
Brobridge - 寬橋微服務
8 min readMar 14, 2020

--

Photo by Christopher Burns on Unsplash

前一篇如果都沒有問題的話,接下來會調整其中一些細節,讓開發流程更符合實際環境與需求。

這篇會提到的調整內容有:

  • 將 image 推送到 image repository,讓部署的流程更接近真實環境。
  • 替 app 建立 service 以方便測試。
  • 替 app 建立 ingress 以方便測試。

註冊一個自己的 DockerHub 帳號

簡單來說,image repository 就是一個管理 container image 的服務,可以讓使用者上傳或下載 container image 。有公開的 image repository 如 DockerHub,也可以架設在自有環境裡如 Harbor。

對開發人員來說,公開的或自己架設的,在使用方式上沒什麼差異,因此這邊使用 dockerhub 的服務。請先至 https://hub.docker.com/ 註冊一個帳號,註冊完成後,可以試看看是否可以用 docker 指令做登入:

$ docker login
Username: duanli # 輸入註冊時設定的帳號
Password: xxxxxx # 輸入註冊時設定的密碼

嘗試上傳自己的容器映像檔

使用 docker 指令登入,是為了可以上傳自己做的 container image。而上傳後的 image 預設是 public 的,也就是所有人只要知道路徑,都可以下載,這部分請留意。我們來嘗試把前一篇的 image 上傳看看:

$ docker push duanli/hello-node # 請自行把 duanli 換成在 dockerhub 註冊的帳號

沒有錯誤訊息的話,可以從 dockerhub 官網上確認。因為 image 權限是 public ,所以 kubernetes 建立 Pod 要取回 image 時,不會有權限問題,所以我們調整一下指令重新部署看看,先刪除之前已經部署的 Pod。

$ kubectl delete pods hellonode
$ kubectl run hellonode --image=duanli/hello-node --restart=Never

到這邊,往真實環境又邁進一步了。

在 Kubernetes 上部署你的 Service 元件

在 kubernetes 裡建立的 Pod,是實際處理回應的 app。然而 Pod 使用的是 Kubernetes 內部的 IP,沒辦法從外部直接連線,所以在前一篇中,是透過 minikube 的 ssh 參數來執行測試的指令。

除了 IP 無法直接存取的問題外,另一個問題就是如果 Pod 刪除後重新建立,Pod IP 也會改變,因此每次測試時都要重新取得一次 Pod IP ,也是非常不方便的事情。因此我們可以用 Kubernetes 裡的另一種資源,來 (部分)解決上述的問題,這種資源叫 Service。

我們可以快速透過指令來建立 Service,並且在建立時可以調整一下測試使用的 Port,原本是 3000 ,我們改成 80 看看:

# 建立一個 Service 來監聽 80 port,然後把連線要求導向 Pod 的 3000 port
$ kubectl expose pod hellonode --port=80 --target-port=3000
# 取得 Service 的連線位置
$ SVC=$(kubectl get svc hellonode -o jsonpath='{.spec.clusterIP}'
# 呼叫測試
$ minikube ssh curl $SVC
Hello World!

測試成功。不過這只有解決上面第二個問題(可以自行刪除 Pod 重新建立來測試看看~),但測試還是要透過 minikube ssh ?原則上這部分要靠之後介紹的 Ingress 來處理,但使用 Ingress 前,必須要先建立 service,所以這節的內容還是需要先進行的。

NodePort 模式的 Service

在使用 Ingress 之前,還有一種變通的方式,可以讓我們不需要透過 minikube ssh 來進行測試。

Service 有幾種模式,這邊不討論細節,直接提供方式。在建立 service 時,指定 service 的模式為 NodePort,然後 minikube 提供指令可以快速的查看瀏覽 service 的 URL。所以我們先以指令刪除 service 然後重新建立:

# 先刪除前一節建立的 Service
$ kubectl delete svc hellonode
# 建立一個新的 Service,port 的設定和前一節一樣,但模式採用 NodePort
$ kubectl expose pod hellonode --port=80 --target-port=3000 --type=NodePort
# 取得 service 的對外位置和 Port
$ minikube service hellonode --url
http://192.168.64.2:30270
# 呼叫測試
$ curl http://192.168.64.2:30270
Hello World!

這個方式作為臨時測試很方便,但是 app 數量較多的時候,管理或使用上就沒有 ingress 方便。而且如果要搭配前端程式打 API 時,用 ingress 會比較接近真實的使用方式。

NodePort 模式下,Service 上的對外埠,會對應到 Kubernetes 節點上的埠號,所以只要得到節點的 IP 位置和對應的埠號,就可以從節點外部直接連線到 Service。

在 Kubernetes 啟用 Ingress 元件

如果說 Service 的角色像是 proxy 的話,那 Ingress 的角色就像是 API Gateway,可以依據不同的 Domain 或是路徑,轉流量到指定的 API,或者是說轉流量到指定 API 所負責的 app ,也就是 Pod。

在標準的 Kubernetes 上要安裝 Ingress Controller 稍微比較複雜些,不過我們這邊用 minikube 的話,可以很快的有 Ingress 可以使用:

$ minikube addons enable ingress

Ingress Controller 是可以自己客製化的,許多 API Gateway 或是 Service Mesh 的解決方案,都有自己的 Ingress Controller 可使用。隨著你裝的解決方案不同,你將有不同的 Ingress Controller 可選擇,但無論是哪一種,基本功能大同小異。

在本系列文中,會以 minikube 內建的 Nginx Ingress 做為範例說明。

部署你的 Ingress

Ingress 就沒辦法直接用指令來設定了,需要寫個 yaml 檔來提供設定內容,然後用指令來建立。

所以撰寫一個 ingress.yaml 如下:

apiVersion: networking.k8s.io/v1beta1
kind: Ingress
metadata:
name: example
annotations:
nginx.ingress.kubernetes.io/rewrite-target: /$1
spec:
rules:
- host: hello.node.minikube
http:
paths:
- path: /(.*|$)
backend:
serviceName: hellonode
servicePort: 80

host 的「hello.node.minikube」可以隨便定,若 Ingress 要直接對外提供服務,這其實是對應到實際對外的 Domain Name。你可以想像是過去在 Nginx 裡面設定 Server Name、 Virtual Host 的功能。

然後用指令讀入 ingress.yaml 來建立 Ingress

$ kubectl apply -f ingress.yaml
$ kubectl get ing
NAME HOSTS ADDRESS PORTS AGE
example hello.node.minikube 192.168.64.2 80 37s

可以看到一個 IP 出現(可能需要一點時間,不會馬上取得 IP),然後就可以測試看看了:

$ curl --resolve hello.node.minikube:80:192.168.64.2  http://hello.node.minikubeHello World!

如果覺得每次加 resolve 參數很麻煩的話,可以在 /etc/hosts 裡設定好,這樣就更方便了。

整理一下到目前的流程

  • 開發程式
  • 撰寫 Dockerfile 並打包成 container image
  • 將 image 上傳至 DockerHub
  • 用指令在 minikube 建立 Pod
  • 用指令在 minikube 建立 Service
  • 撰寫 yaml 來建立 Ingress

當上述流程完成後,就可以用很簡單的方式測試自己開發的程式跑在 Kubernetes 上的情況。

下一篇會繼續做一些調整改進,可以應付再更複雜一些的開發需求。

<<上一篇 | 下一篇>>

--

--

Duan Li
Brobridge - 寬橋微服務

All we do crumbles to the ground, though we refuse to see, dust in the wind, all we are is dust in the wind