Kubernetes 初體驗 By minikube
前言
本篇文章是初學者(我)對於探索 Kubernetes 的記錄,包含相關名詞的認識、如何與 Kuberentes 互動,過程中查詢了許多的相關知識,都附在文末的 Reference 部分。文章內容若有任何的(理解)錯誤,請麻煩告知我改正,謝謝!🙏🏻
文章內容稍長,一開始會先介紹如何安裝 Kubernetes 叢集,接著再介紹 Kubernetes 一些常見的名詞,文章最後再透過指令簡單的與 Kubernetes 互動。
🐳 minikube 安裝
minikube 是 Kubernetes 輕量化的實作,它會在你本機的 VM 內建立並且執行一個單一節點的 Kubernetes 叢集。
請按照以下說明,安裝所需要的相關軟體
📝 minikube 支援 macOS、Linux、Windows 平台,使用 minikube 之前你必須安裝好 VM 環境,若你的電腦沒有安裝任何的 VM 環境,可以使用 VirtualBox 作為你的 VM 環境,請根據你的作業系統下載對應的版本。
📝 kubectl 可以用來方便操作 Kubernets 的 API,若是使用 macOS 可以直接透過 Homebrew 安裝:
$ brew install kubernetes-cli$ kubectl version
或者可以透過 curl
來安裝 kubectl 的 binary 執行檔:
# latest release$ curl -LO https://storage.googleapis.com/kubernetes-release/release/$(curl -s https://storage.googleapis.com/kubernetes-release/release/stable.txt)/bin/darwin/amd64/kubectl$ chmod +x ./kubectl$ sudo mv ./kubectl /usr/local/bin/kubectl
kubectl 其他安裝方式,請參考此連結。
- 📝 minikube 安裝(macOS 作為範例):
$ brew cask install minikube
其他作業系統安裝 minikube 方式,請參考官方文件。
以上三個步驟 📝 做完後,就完成了 minikube 的安裝,可以在終端機執行 kubectl
和 minikube
測試一下是否安裝完成:
- kubectl
- minikube
使用 minikube
執行以下指令把叢集跑起來:
$ minikube start
可以打開 Dashboard GUI 讓你可以概觀目前整個叢集的狀況:
$ minikube dashboard
到這邊我們就完成 minikube 的安裝,同時也在本機電腦上執行了一個叢集。
📖 名詞解釋
當我在讀 Kubernetes 相關文章的時候,對於那些新名詞總是感到疑問,所以覺得在開始之前,先對幾個常用的名詞做些簡單的解釋:
- Pod
在 Kubernetes 的世界中,Pod 是最小的單位。在 Pod 內,可以有一個或者是多個 Container,這些 Container 共享相同的資源,例如:Storage、Network,因為使用相同的資源,所以 Container 之間彼此可以方便溝通,但同時也可以保持與其他 Container 的隔離。
- Node
Node 在 Kubernetes 上代表工作機器(Worker Machine),它可能是一個虛擬或是實體機器,而 Pod 是執行在 Node 上的,所以一個 Node 可能有一個或者是多個 Pod。
- Deployment
Deployment 是描述如何在 Kubernetes 上建立或者是更新你的應用程式,它是一個抽象的概念。透過 Deployment 可以管理 Pod 的 replicas、應用程式的滾動升級(rolling update)、回滾(rollback)。
- Service
Kubernetes 的 Service 是一個抽象化的概念,它主要定義一組邏輯(相同)的 Pod 以及存取它們的方針。
- Kubernetes Object
在 Kubernetes 中,Kubernetes Object 是一個持久化的實體(persistent entities),Kubernetes 使用這些實體來表示目前整個叢集的狀態。Kubernetes 的 Object 都可以透過
yaml
格式的檔案來描述要如何建立 Object 以及狀態。
來個 Hello Kubernetes
在學習任何新事物前,都不免俗來要個 Hello World 😂,Google 提供了一個簡單的 echoserver
Container,接著將這個 Container 服務執行在 minikube
上:
$ kubectl run hello-minikube --image=gcr.io/google_containers/echoserver:1.8 --port=8080deployment "hello-minikube" created$ kubectl expose deployment hello-minikube --type=NodePortservice "hello-minikube" exposed$ kubectl get servicesNAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGEhello-minikube NodePort 10.104.163.46 <none> 8080:32101/TCP 13skubernetes ClusterIP 10.96.0.1 <none> 443/TCP 19h
解釋一下上面指令所代表的意思:
run
:建立一個 Deployment 或是 Job 來管理被建立的 Container--image
:提供 Image 的來源,例如 Docker Hub 上的 nginx- 💡 nginx 是由官方所提供的 Image ,如果要使用自己或是他人的 Image 請使用
user/image
格式
- 💡 nginx 是由官方所提供的 Image ,如果要使用自己或是他人的 Image 請使用
--port
:指定埠號expose
:讓存取hello-minikube
服務可以被存取get services
:取得叢集上的 Service 列表
透過 kubectl get services
可以看到 hello-minikube
已經被建立,接著使用 minikube
來取得網站的 URL:
$ minikube service hello-minikube --urlhttp://192.168.99.100:32101
打開瀏覽器輸入網址後可以看到一些資訊:
🤟🏻 動手操作
接下來的內容會根據上面名詞解釋來建立對應的 Kubernetes Object。
📦 Pod
- Pod 是由一個或者是多個 Container 所組成
- 在 Pod 內會共享 Storage、Network 資源以及配置設定
- Pod 內的 Container 就像是生命共同體,一旦 Pod 被調度,所有 Pod 內的 Container 也會一起被調度
- Pod 具有生命週期
- Pod 在建立後,會擁有一個 Unique ID
- 每個 Pod 都會與調度它的 Node 綁定,並維持期望的狀態直到終止(根據重啟策略)或刪除,若 Node 發生故障,Pod 會被調度到其他的可用的 Node 上
- 一個給定的 Pod(UID 被定義)不會被調度到新的 Node 上,而是由一個全新相同而且帶著不同的 UID Pod 取代
建立 Pod YAML 檔案
建立一個資料夾,並建立一個 my-first-pod.yaml
:
apiVersion: v1kind: Podmetadata:name: echo-serverlabels:app: echo-serverspec:containers:- name: echo-serverimage: inanimate/echo-serverports:- containerPort: 8080
稍微說明 YAML 檔案的內容:
kind
:說明 Kubernetes Object 是什麼類別metadata
:一些詮釋資料name
表示 Pod 名稱labels
實際上是一個 key/value,標籤可以有效的劃分 Pod,未來可以將不同種類的標籤 Pod 做管理
spec
:定義 Container 的內容
使用 kubectl
來建立 Pod:
$ kubect apply -f my-pod.yamlpod/echo-server created$ kubectl get pods -o wideNAME READY STATUS RESTARTS AGE IP NODEecho-server 0/1 ContainerCreating 0 6s <none> minikubehello-deployment-7f97bc8897-qzfn2 1/1 Running 4 1d 172.17.0.5 minikubehello-minikube-5b8fc68cc9-qvpxj 1/1 Running 5 2d 172.17.0.4 minikube
這時候可以看到 Pod 的狀態是正在被建立當中,過一下可以看到已經建立完成:
$ kubectl get pods -o wideNAME READY STATUS RESTARTS AGE IP NODEecho-server 1/1 Running 0 46s 172.17.0.6 minikubehello-deployment-7f97bc8897-qzfn2 1/1 Running 4 1d 172.17.0.5 minikubehello-minikube-5b8fc68cc9-qvpxj 1/1 Running 5 2d 172.17.0.4 minikube
minikube 是單節點的叢集,所以在相同叢集內的 Pod 彼此可以存取。從上面的結果可以看到目前 echo-server
的 IP 是 172.17.0.6
,我們再開一個測試的 Pod 來測試 echo-server
是否正常運作:
$ kubectl -n default run curl-pod --image=radial/busyboxplus:curl -i --tty --rm
我們開另外一個 Terminal tab 視窗看一下 Pod 的狀態:
$ kubectl get pods -o wideNAME READY STATUS RESTARTS AGE IP NODEcurl-pod-6f979c484f-hx7gn 1/1 Running 0 1m 172.17.0.7 minikubeecho-server 1/1 Running 0 2h 172.17.0.6 minikubehello-deployment-7f97bc8897-qzfn2 1/1 Running 4 1d 172.17.0.5 minikubehello-minikube-5b8fc68cc9-qvpxj 1/1 Running 5 2d 172.17.0.4 minikube
可以看到剛剛建立的 curl-pod
已經好了,接著再切回原本執行 curl-pod
的視窗執行:
Welcome to echo-server! Here's what I know.> Head to /ws for interactive websocket echo!-> My hostname is: echo-server-> Requesting IP: 172.17.0.7:55678-> Request Headers |HTTP/1.1 GET /Host: 172.17.0.6:8080Accept: */*User-Agent: curl/7.35.0-> Response Headers |Content-Type: text/plainX-Real-Server: echo-server> Note that you may also see "Transfer-Encoding" and "Date"!-> ...
由輸出結果可以看到:
Requesting IP: 172.17.0.7:55678 ...
echo-server
收到了來自 curl-pod
所發出的請求,以上就是建立一個簡單 Pod 的範例。
💠 Node
- 在 Kubernetes 叢集中,Node 可能是一個虛擬或是實體的主機
- 每個 Node 上都會有
kubelet
,它是一個管理機器上的 Pod 並負責與 Kubernetes Master 溝通的代理 - 每個 Node 都會執行一個 Container 的 Runtime,主要是拉取 Image 並執行 Container
- 每個 Node 都會執行一個
kube-proxy
,它是對 iptables 的規則進行規劃來取得對 Service IP 的存取,並且將它們重導(Redirect)到正確的後端位置
📍 Replication Controller 和 ReplicaSet
Replication Controller(簡稱 rc),主要是用來確保 Pod 的 replicas(副本)維持在使用者所定義的副本數,透過 Replication Controller 可以一次建立多個相同的 Pod,若 Pod 出現 Crash 或 Failure 而無法提供服務時,Replication Controller 會自動的砍掉無法正常執行的 Pod,並且重新建立一個新的 Pod 來維持 replicas 的數量
ReplicaSet 和 Replication Controller 本質上是相同的,差別在於 ReplicaSet 支援集合式的 selector,而 Replication Controller 只支援等式的 selector
建立 Replication Controller YAML 檔案
接下來以 nginx 作為範例,請建立一個 my-first-rc.yaml
檔案內容如下:
apiVersion: v1kind: ReplicationControllermetadata:name: nginxspec:replicas: 3selector:app: nginxtemplate:metadata:name: nginxlabels:app: nginxspec:containers:- name: nginximage: nginxports:- containerPort: 80
使用 kubectl
來建立 Replication Controller:
$ kubectl apply -f my-first-rc.yamlreplicationcontroller/nginx created
確認 Replication Controller:
$ kubectl get rcNAME DESIRED CURRENT READY AGEnginx 3 3 3 1m
使用 kubectl get pods -o wide
可以看到三個 nginx 的 Pod:
NAME READY STATUS RESTARTS AGE IP NODEcurl-pod-6f979c484f-hx7gn 1/1 Running 7 3d 172.17.0.3 minikubehello-minikube-5b8fc68cc9-qvpxj 1/1 Running 11 5d 172.17.0.5 minikubenginx-2hb8r 1/1 Running 0 1m 172.17.0.8 minikubenginx-4rwv5 1/1 Running 0 1m 172.17.0.7 minikubenginx-7fjvs 1/1 Running 0 1m 172.17.0.6 minikube
在前面我們建立了 curl-pod
,我們使用它來檢查 nginx 服務是否正常,首先:
$ kubectl attach curl-pod-6f979c484f-hx7gn -c curl-pod -i -tIf you don't see a command prompt, try pressing enter.
接著請選擇其中一個 nginx 的 Pod 來測試:
<!DOCTYPE html><html><head><title>Welcome to nginx!</title><style>body {width: 35em;margin: 0 auto;font-family: Tahoma, Verdana, Arial, sans-serif;}</style></head><body><h1>Welcome to nginx!</h1><p>If you see this page, the nginx web server is successfully installed andworking. Further configuration is required.</p><p>For online documentation and support please refer to<a href="http://nginx.org/">nginx.org</a>.<br/>Commercial support is available at<a href="http://nginx.com/">nginx.com</a>.</p><p><em>Thank you for using nginx.</em></p></body></html>
啊!是熟悉的畫面內容呀(當然在 Terminal 上是看不到的啊! 😂)
擴展和刪除
擴展(Scale)
若要擴展 Replication Controller 物件的副本的數量,可以透過以下指令:
$ kubectl scale --replicas=5 rc/nginxreplicationcontroller/nginx scaled
現在 nginx 的副本數量為 5:
$ kubectl get pods -o wideNAME READY STATUS RESTARTS AGE IP NODEcurl-pod-6f979c484f-hx7gn 1/1 Running 7 3d 172.17.0.3 minikubehello-minikube-5b8fc68cc9-qvpxj 1/1 Running 11 5d 172.17.0.5 minikubenginx-2hb8r 1/1 Running 0 3m 172.17.0.8 minikubenginx-4rwv5 1/1 Running 0 3m 172.17.0.7 minikubenginx-7fjvs 1/1 Running 0 3m 172.17.0.6 minikubenginx-m8hqv 1/1 Running 0 11s 172.17.0.10 minikubenginx-wdk7p 1/1 Running 0 11s 172.17.0.9 minikube
可以看到 nginx 的 Pod 已經 scale 到我們所指定的數量了,透過 scale
指令可以彈性的調整 Pod 的數量。
刪除(Delete)
刪除 Replication Controller 時,請注意你的 Pod 也會隨著 rc 的刪除跟著被刪除,延續上面範例,將剛剛建立的 rc 刪除:
$ kubectl delete rc nginxreplicationcontroller "nginx" deleted
$ kubectl get pods -o wideNAME READY STATUS RESTARTS AGE IP NODEcurl-pod-6f979c484f-hx7gn 1/1 Running 7 3d 172.17.0.3 minikubehello-minikube-5b8fc68cc9-qvpxj 1/1 Running 11 6d 172.17.0.5 minikubenginx-2hb8r 0/1 Terminating 0 14m 172.17.0.8 minikubenginx-4rwv5 0/1 Terminating 0 14m 172.17.0.7 minikubenginx-7fjvs 0/1 Terminating 0 14m 172.17.0.6 minikubenginx-m8hqv 0/1 Terminating 0 11m 172.17.0.10 minikubenginx-wdk7p 0/1 Terminating 0 11m 172.17.0.9 minikube
可以注意到 nginx 的 Pod 狀態變成 Terminating,最後會被完全刪除。
Replication Controller 雖然可以容易的擴展和刪除 Pod,但實務上還是有些不方便的地方,以上面範例來說,如果要升級 nginx 的版本,就需要額外再建立新的設定檔案來進行升級,更多詳細資訊可以參考 Perform Rolling Update Using a Replication Controller,而官方推薦的做法是使用 Deployment,除了具備原先 Replication Controller 的功能,也可以更容易的完成滾動升級。
🛠 Deployment
- Deployment 提供了宣告式的方式來更新 Pod 和 ReplicaSet
- 使用 Deployment 會建立 ReplicaSet,而 ReplicaSet 會在背景繼續建立所需的 Pod,所以你不應該手動的去管理由 Deployment 所建立的 ReplicaSet
- 可以把 Deployment 是新一代的 Replication Controller,它除了具備 Replication Controller 的功能外,還多了以下的功能:
- 版本記錄:每次對於 Deployment 的操作都會被記錄下來(ReplicaSet)
- 回滾:若升級後遇到問題可以 rollback 到先前的版本
- 暫停和啟動:更新 Deployment 時,可以隨時地暫停和恢復
- 狀態查詢:查詢 Deployment 的升級狀態與詳細進度
建立 Deployment YAML 檔案
這裡使用我自己寫的 docker-fiveN1 作為範例,docker-fiveN1 是一個簡單的 591 租屋網的爬蟲 API。
請建立一個 my-first-deployment.yaml
檔案:
apiVersion: apps/v1kind: Deploymentmetadata:name: fiven1-deploymentspec:replicas: 3selector:matchLabels:app: fiven1-backendtemplate:metadata:labels:app: fiven1-backendspec:containers:- name: fiven1-podimage: neighborhood999/fiven1-backend:1.2.0ports:- containerPort: 8000
從上面 spec
部分說明建立了一個 ReplicaSet,而這個 ReplicaSet 會建立三個 fiven1-backend
副本。
使用 kubectl
來建立 Deployment:
$ kubectl apply -f my-first-deployment.yamldeployment.apps/fiven1-deployment created
$ kubectl get deploymentsNAME DESIRED CURRENT UP-TO-DATE AVAILABLE AGEcurl-pod 1 1 1 1 4dfiven1-deployment 3 3 3 3 4shello-minikube 1 1 1 1 7d
接著查看 ReplicaSet 的狀態:
$ kubectl get rsNAME DESIRED CURRENT READY AGEcurl-pod-6f979c484f 1 1 1 4dfiven1-deployment-68c48d6664 3 3 3 16shello-minikube-5b8fc68cc9 1 1 1 7d
最後查看 Pod 的狀態:
$ kubectl get pods --show-labelsNAME READY STATUS RESTARTS AGE LABELScurl-pod-6f979c484f-hx7gn 1/1 Running 10 4d pod-template-hash=2953570409,run=curl-podfiven1-deployment-68c48d6664-5wm45 1/1 Running 0 29s app=fiven1-backend,pod-template-hash=2470482220fiven1-deployment-68c48d6664-gpvnq 1/1 Running 0 29s app=fiven1-backend,pod-template-hash=2470482220fiven1-deployment-68c48d6664-s7s78 1/1 Running 0 29s app=fiven1-backend,pod-template-hash=2470482220hello-minikube-5b8fc68cc9-qvpxj 1/1 Running 13 7d pod-template-hash=1649724775,run=hello-minikube
透過 kubectl get pods --show-labels
可以看到有 3 個 Pod 都帶有 fiven1-backend
的 Label。
使用 curl-pod
來測試一下服務是否正常,如果先前有安裝過 curl-pod
可以查看你的 curl-pod
完整名稱並執行:
$ kubectl attach curl-pod-6f979c484f-hx7gn -c curl-pod -i -t
若沒有安裝該 Pod 請輸入下面指令:
$ kubectl -n default run curl-pod --image=radial/busyboxplus:curl -i --tty --rm
查看一下 Pod 的 IP 位置:
$ kubectl get pods -o wideNAME READY STATUS RESTARTS AGE IP NODEcurl-pod-6f979c484f-hx7gn 1/1 Running 10 4d 172.17.0.4 minikubefiven1-deployment-68c48d6664-5wm45 1/1 Running 0 56s 172.17.0.6 minikubefiven1-deployment-68c48d6664-gpvnq 1/1 Running 0 56s 172.17.0.8 minikubefiven1-deployment-68c48d6664-s7s78 1/1 Running 0 56s 172.17.0.7 minikubehello-minikube-5b8fc68cc9-qvpxj 1/1 Running 13 7d 172.17.0.2 minikube
以 172.17.0.7
作為範例來測試,直接使用以下指令測試:
$ curl 172.17.0.7:8000{"1": [{"preview": "https://hp2.591.com.tw/house/active/2016/06/15/146597739918187302_765x517.water3.jpg","title": "南軟優質大套房!(雙捷運旁) 特價中!","url": "https://rent.591.com.tw/rent-detail-6739629.html","address": "南港區 - 中南街","rentType": "沒有格局說明","optionType": "分租套房","ping": "15","floor": "樓層:頂樓加蓋","price": "17,500 元 / 月","isNew": false},{"preview": "https://hp1.591.com.tw/house/active/2018/08/10/153388789733221608_765x517.water3.jpg","title": "兩房一廳忠孝信義松山松德林口福德永春站","url": "https://rent.591.com.tw/rent-detail-6679039.html","address": "信義區 - 虎林街 242 巷","rentType": "2","optionType": "整層住家","ping": "23","floor": "樓層:2/4","price": "23,012 元 / 月","isNew": false}...}
滾動升級(Rolling Update)
這裡使用指令的方式作為範例來滾動升級 docker Image 的版本,我們把 fiven1-backend
的 Image 升級到 latest
版本,而在指令最後加上 --record
可以記錄每次操作的指令,這樣可以清楚了解 Deployment 不同的版本(revision)之間的操作:
$ kubectl set image deployment/fiven1-deployment fiven1-pod=neighborhood999/fiven1-backend:latest --recorddeployment.extensions/fiven1-deployment image updated
查看升級的狀況:
$ kubectl rollout status deployment fiven1-deploymentdeployment "fiven1-deployment" successfully rolled out
接著查看一下 Pod 的狀態:
$ kubectl get pods -o wideNAME READY STATUS RESTARTS AGE IP NODEcurl-pod-6f979c484f-hx7gn 1/1 Running 10 4d 172.17.0.4 minikubefiven1-deployment-54cc9d7954-2qgvx 1/1 Running 0 7m 172.17.0.6 minikubefiven1-deployment-54cc9d7954-rdfvg 1/1 Running 0 7m 172.17.0.9 minikubefiven1-deployment-54cc9d7954-xfkn8 1/1 Running 0 7m 172.17.0.8 minikubehello-minikube-5b8fc68cc9-qvpxj 1/1 Running 13 7d 172.17.0.2 minikube
這邊請注意到 IP 的部分,在上面範例中,我使用 172.17.0.7
作為測試,但是發現 172.17.0.7
不存在了,這裡主要的原因是,在滾動升級時,並不會馬上把舊的 Pod 砍掉,而是建立新的 Pod 來取代舊版本的 Pod。
查看 ReplicaSet 的狀態:
$ kubectl get rsNAME DESIRED CURRENT READY AGEcurl-pod-6f979c484f 1 1 1 4dfiven1-deployment-54cc9d7954 3 3 3 10mfiven1-deployment-68c48d6664 0 0 0 15mhello-minikube-5b8fc68cc9 1 1 1 7d
可以看到有兩個 fiven1-deployment
,其中 fiven1-deployment-68c48d6664
是沒有在執行的,每次在進行滾動升級時,都會保留舊的 ReplicaSet,未來可以方便的 rollback 到舊的版本。
在進行滾動升級時,除了透過以上的方式,也可以加入一些升級策略,像是 minReadySeconds
、maxSurge
、maxUnavailable
,詳細可以參考這篇文章。
回滾(Roll Back)
若當發現升級完之後有些問題,可以透過回滾的方式將應用程式回復到先前的狀態,可以透過以下指令來查詢升級的歷史紀錄:
$ kubectl rollout history deploy fiven1-deploymentdeployments "fiven1-deployment"REVISION CHANGE-CAUSE1 <none>2 kubectl set image deployment/fiven1-deployment fiven1-pod=neighborhood999/fiven1-backend:latest --record=true
第一筆是建立 Deployment 的時候,第二個則是在升級時,因為有加入的 --record
參數,在 CHANGE-CAUSE
部分就可以清楚看到升級時所下的指定。
接著我們來測試 rollback 到上一筆(剛建立)的狀態:
$ kubectl rollout undo deployment fiven1-deploymentdeployment.extensions/fiven1-deployment
查看 ReplicaSet 的狀態:
$ kubectl get rsNAME DESIRED CURRENT READY AGEcurl-pod-6f979c484f 1 1 1 4dfiven1-deployment-54cc9d7954 0 0 0 48mfiven1-deployment-68c48d6664 3 3 3 53mhello-minikube-5b8fc68cc9 1 1 1 7d
對照上面滾動升級的部分,可以看到 54cc9d7954
已經被停止,已經成功回滾到 68c48d6664
的 ReplicaSet。
若要 rollback 到特定版本:
$ kubectl rollout undo deploy <deployment> --to-revision=<revision>
最後查詢歷史紀錄會發現多一筆:
$ kubectl rollout history deploy fiven1-deploymentdeployments "fiven1-deployment"REVISION CHANGE-CAUSE2 kubectl set image deployment/fiven1-deployment fiven1-pod=neighborhood999/fiven1-backend:latest --record=true3 <none>
🚥 Service
- Service 是一個抽象化的概念,它定義一組邏輯的 Pod 和存取它們的方針
- Pod 本身可能帶有一個或多個不同的標籤,Service 通常透過 LabelSelector 來選取對應的 Pod 集合
- Service 有四種 Type:
ClusterIP
、NodePort
、LoadBalancer
、ExternalName
,不同 Type 有各自不同的行為 - Service 支援 TCP 和 UDF 協定
建立 Service YAML 檔案
這裡將會延續前面 Deployment 的範例,在 Deployment 範例中建立了 fiven1-deployment
,這個 Deployment 有三個 fiven1-backend
的副本。
以下將會使用 NodePort
type 的 Service 作為範例:
apiVersion: v1kind: Servicemetadata:name: fiven1-servicelabels:app: fiven1-servicespec:type: NodePortselector:app: fiven1-backendports:- port: 8000protocol: TCP
在 spec
部分我們設定 type
為 NodePort
而且 selector
部分我們選擇了 app=fiven1-backend
的 Pod:
$ kubectl get pods --show-labelsNAME READY STATUS RESTARTS AGE LABELScurl-pod-6f979c484f-hx7gn 1/1 Running 24 8d pod-template-hash=2953570409,run=curl-podfiven1-deployment-68c48d6664-jsnjd 1/1 Running 3 3d app=fiven1-backend,pod-template-hash=2470482220fiven1-deployment-68c48d6664-kcsrp 1/1 Running 3 3d app=fiven1-backend,pod-template-hash=2470482220fiven1-deployment-68c48d6664-kxtp7 1/1 Running 3 3d app=fiven1-backend,pod-template-hash=2470482220hello-minikube-5b8fc68cc9-qvpxj 1/1 Running 16 10d pod-template-hash=1649724775,run=hello-minikube
接著使用 kubectl
來建立 Service:
$ kubectl apply -f my-first-service.yamlservice/fiven1-service created
確認 Service 的狀態:
$ kubectl get servicesNAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGEfiven1-service NodePort 10.110.35.60 <none> 8000:30554/TCP 5mhello-minikube NodePort 10.104.163.46 <none> 8080:32101/TCP 9dkubernetes ClusterIP 10.96.0.1 <none> 443/TCP 10d
fiven1-service
的 CLUSTER-IP
為 10.110.35.60
,我們可以使用 curl-pod
來測試 Service 運作是否正常:
{"1": [{"preview": "https://hp2.591.com.tw/house/active/2017/08/04/150183382555696109_765x517.water3.jpg","title": "雙捷運 * 近馬偕 - 鬧中取靜的舒適套房","url": "https://rent.591.com.tw/rent-detail-6007811.html","address": "中山區 - 中山北路二段 72 巷 12-1 號","rentType": "沒有格局說明","optionType": "獨立套房","ping": "6","floor": "樓層:2/5","price": "17,000 元 / 月","isNew": false}...}
CLUSTER-IP
是 Service 在叢集內的 IP,curl-pod
與 fiven1-service
位在同個叢集上,所以可以透過內部網路去存取該服務,若想要從外部(叢集外)存取該服務該怎麼做?
我們先使用以下指令來查看 fiven1-service
Service 的詳細資訊:
$ kubectl describe service fiven1-serviceName: fiven1-serviceNamespace: defaultLabels: app=fiven1-serviceAnnotations: kubectl.kubernetes.io/last-applied-configuration={"apiVersion":"v1","kind":"Service","metadata":{"annotations":{},"labels":{"app":"fiven1-service"},"name":"fiven1-service","namespace":"default"},"spec...Selector: app=fiven1-backendType: NodePortIP: 10.110.35.60Port: <unset> 8000/TCPTargetPort: 8000/TCPNodePort: <unset> 30554/TCPEndpoints: 172.17.0.5:8000,172.17.0.6:8000,172.17.0.7:8000Session Affinity: NoneExternal Traffic Policy: ClusterEvents: <none>
可以注意到 NodePort
的部分,它的 Port 為 30554
,若要在叢集外存取 Service 服務,可以透過 <NodeIP>:<NodePort>
的方式,而這些請求透過 Service 會被自動地分配至 Endpoints
,也就是我們的 Pod。
查詢 minikube 在我們本機上的 IP 位置:
$ minikube ip192.168.99.100
可以看到 IP 位置為 192.168.99.100
,所以可以透過 192.168.99.100:30554
來存取 fiven1-service
:
$ curl 192.168.99.100:30554
或者可以透過瀏覽器:
🤯 結語
學習 Kubernetes 才發現到它涵蓋的知識真的非常的廣,寫到這其實已經花了我不少時間,除了理解 Kubernetes 一些基本的架構和機制外,還有一些比較底層的東西,當然懂的也都還是皮毛,真的是不容易啊!
雖然現在不太有機會用到 Kubernetes,但是多學一些東西也不是壞處啦,希望未來可以把一些還不懂的地方給補起來(多到哭出來)。
🔗 Reference
- 🔗 Kubernetes - Concepts
- 🔗 Kubernetes Design and Architecture
- 🔗 GitHub - minikube
- 🔗 Kubernetes 101: Pods, Nodes, Containers, and Clusters
- 🔗 Kubernetes 30 天學習筆記系列
- 🔗 透過 Kubernetes Deployments 實現滾動升級
- 🔗 Kubernetes 最小部署單位 Pod
- 🔗 Kubernetes Service 概念詳解
- 🔗 Kubernetes Service 深度剖析 - 存取路徑差異
- 🔗 [Kubernetes] What Is Service?
- 🔗 [Kubernetes] How To Implemete Kubernetes Service - ClusterIP
- 🔗 Kubernetes Handbook (Kubernetes 指南)
- 🔗 Kubernetes 中文指南/云原生应用架构实践手册