本次目標
在執行之前本機端也需要安裝 kubectl
工具。K3d 安裝這邊不贅述,可以參考官方安裝部分。使用 K3d 原因是,建立起來的環境包含了 Ingress controller、Metric Server 等資源,因此可以作快速驗證。
透過 K3d 的 API 可以配置 Kubernetes 相關的資訊。
apiVersion: k3d.io/v1alpha4 # this will change in the future as we make everything more stable
kind: Simple # internally, we also have a Cluster config, which is not yet available externally
metadata:
name: ithome-lab-cluster # name that you want to give to your cluster (will still be prefixed with `k3d-`)
servers: 1 # same as `--servers 1`
agents: 2 # same as `--agents 2`
kubeAPI: # same as `--api-port myhost.my.domain:6445` (where the name would resolve to 127.0.0.1)
host: "ithome.cch.com" # important for the `server` setting in the kubeconfig
hostIP: "127.0.0.1" # where the Kubernetes API will be listening on
hostPort: "6500"
image: rancher/k3s:v1.27.7-k3s1
ports:
- port: 8580:80
nodeFilters:
- loadbalancer
- port: 8543:443
nodeFilters:
- loadbalancer
注意,上述配置 ithome.cch.com
此值要映射至 /etc/hosts
檔案,讓地端的 dns 可以解析到。
透過以下指令建置,Kubernetes 並限制其記憶體。
$ k3d cluster create -c infra/config.yaml --servers-memory 2G --agents-memory 2G
成功安裝後,透過 kubectl
方式可以檢查是否存在,如下,應當要看到 k3d-ithome-lab-cluster
。K3d 建置完 Kubernetes 環境後會將其 API 位置、憑證等資訊加至 .kube/config
檔案中。
$ kubectl config get-clusters
k3d-ithome-lab-cluster
切換至 k3d-ithome-lab-cluster 的資源。接著使用 kubectl cluster-info
可獲取相對應的資訊有 API 位置和一些資源部署資訊。
$ kubectl config use-context k3d-ithome-lab-cluster
$ kubectl cluster-info
Kubernetes control plane is running at https://ithome.cch.com:6500
CoreDNS is running at https://ithome.cch.com:6500/api/v1/namespaces/kube-system/services/kube-dns:dns/proxy
Metrics-server is running at https://ithome.cch.com:6500/api/v1/namespaces/kube-system/services/https:metrics-server:https/proxy
To further debug and diagnose cluster problems, use 'kubectl cluster-info dump'.
到這邊已經建置一個可以使用的 Kubernetes 環境。接著要將 Quarkus API 給部署至這環境中。
上一章節,藉由 quarkus-kubernetes
自動產生 kubernetes YAML 資源。此章節透過 kubectl apply
部署該資源。
kubectl apply -f kubernetes/kubernetes.yml
部署完後,可以看到以下資源 Service、Deployment、ReplicaSet 和 Pod。
$ kubectl get all
NAME READY STATUS RESTARTS AGE
pod/ithome2024lab-77468c897c-rgrqv 1/1 Running 0 39m
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
service/kubernetes ClusterIP 10.43.0.1 <none> 443/TCP 113m
service/ithome2024lab ClusterIP 10.43.107.205 <none> 80/TCP 39m
NAME READY UP-TO-DATE AVAILABLE AGE
deployment.apps/ithome2024lab 1/1 1 1 39m
NAME DESIRED CURRENT READY AGE
replicaset.apps/ithome2024lab-77468c897c 1 1 1 39m
由於 Quarkus 專案沒有定義 Ingress 資源暴露服務,因此我們透過 port-forward 來驗證 API,其格式是:
kubectl port-forward TYPE/NAME [options] [LOCAL_PORT:]REMOTE_PORT [...[LOCAL_PORT_N:]REMOTE_PORT_N]
期可以針對 Pod
或是 Server
資源,將服務流量透過本機進行轉發。下面的指令可以看到最後成功驗證服務是正常運行。
$ kubectl port-forward service/ithome2024lab 8080:80
$ curl http://localhost:8080/hello
Hello RESTEasy hello
但,Quarkus 能作的事情不只是這樣。如果在地端可以省去 kubectl apply
的話更好,沒錯就是使用 quarkus.kubernetes.deploy
和 quarkus.kubernetes.deployment-target
預設上前者為 false
後者為 kubernetes
。這過程會需要與 Kubernetes API 進行溝通所以需要新增以下的依賴
implementation 'io.quarkus:quarkus-kubernetes-client'
下面來試試,首先在定義新的 API
// GreetingResource.java
@GET
@Path("/day03")
@Produces(MediaType.APPLICATION_JSON)
public String day03() {
return "Hello RESTEasy %s".formatted("day03");
}
定義好後重新打包 Image,相較於上一篇,這次把 quarkus.kubernetes.deploy
設定為 true
,並指定要部署到的 namespace。因此會達到打包 Image 後順便部署的好處。
gradle build -Dquarkus.package.type=native -Dquarkus.native.container-build=true -Dquarkus.kubernetes.deploy=true -Dquarkus.container-image.push=true -Dquarkus.container-image.build=true -Dquarkus.container-image.additional-tags=day03 -Dquarkus.container-image.username=${USER} -Dquarkus.container-image.password=${PASSWORD} -Dquarkus.kubernetes.namespace=default
最後,確實也多新增了一個 ithome2024lab-cccd555bd 的 ReplicaSet
資源,注意第一次部署的 ithome2024lab-77468c897c ReplicaSet
資源還在,也表示隨時都可以回滾到之前的版本。
$ kubectl get all
NAME READY STATUS RESTARTS AGE
pod/ithome2024lab-cccd555bd-qlcl5 1/1 Running 0 54s
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
service/kubernetes ClusterIP 10.43.0.1 <none> 443/TCP 3h26m
service/ithome2024lab ClusterIP 10.43.73.110 <none> 80/TCP 54s
NAME READY UP-TO-DATE AVAILABLE AGE
deployment.apps/ithome2024lab 1/1 1 1 2m15s
NAME DESIRED CURRENT READY AGE
replicaset.apps/ithome2024lab-cccd555bd 1 1 1 54s
replicaset.apps/ithome2024lab-77468c897c 0 0 0 39m15s
驗證,新 API /hello/day03
確實被部署了。
$ kubectl port-forward service/ithome2024lab 8080:80
$ curl http://localhost:8080/hello/day03
Hello RESTEasy day03
如果要嘗試回滾,可以如下操作
$ kubectl rollout history deployment ithome2024lab # 查看歷史版本紀錄
deployment.apps/ithome2024lab
REVISION CHANGE-CAUSE
1 <none>
2 <none>
$ kubectl rollout undo deployment ithome2024lab --to-revision 1 # 回滾至版本 1
deployment.apps/ithome2024lab rolled back
Quarkus 提供了一個讓開發者簡易整合 Kubernetes 的依賴套件,作為開發端如果要在地端驗證某些功能其實是滿方便也夠用,該套件如果注意看,預設上所提供的 Labels 和 Annotations 欄位資訊滿豐富,對於時常上版的 DEV 環境可以清楚知道該版本的 commit 和建置時間與版本。壞處是如果真的要上 QAS 等以上環境其實要定義的資源滿多,反到會開始用 Helm Charts 或是 Kustomzie 等工具進行 YAML 管理。
itachi@DESKTOP-5L93DSL:~/github/ithome2024/ithome2024lab$ kubectl describe pod ithome2024lab-74959699f7-zq5gx
Name: ithome2024lab-74959699f7-zq5gx
Namespace: default
Priority: 0
Service Account: ithome2024lab
Node: k3d-ithome-lab-cluster-agent-1/172.24.0.3
Start Time: Sat, 24 Aug 2024 18:23:51 +0800
Labels: app.kubernetes.io/managed-by=quarkus
app.kubernetes.io/name=ithome2024lab
app.kubernetes.io/version=1.0.0-SNAPSHOT
pod-template-hash=74959699f7
Annotations: app.quarkus.io/build-timestamp: 2024-08-24 - 10:06:23 +0000
app.quarkus.io/commit-id: 1935a62ca5ef3e7242ba80b9ee3f27ed08d875b4
app.quarkus.io/quarkus-version: 3.13.3
app.quarkus.io/vcs-uri: https://xxxxxxxxx/quarkus-sandbox.git
....
這邊探討一下 Labels(標籤) 和 Annotations(註釋)。
apiVersion: v1
kind: Service
metadata:
labels:
app.kubernetes.io/name: ithome2024lab
app.kubernetes.io/version: v1.0.0
apiVersion: v1
kind: Service
metadata:
annotations:
app.quarkus.io/quarkus-version: 3.13.3
app.quarkus.io/commit-id: 1935a62ca5ef3e7242ba80b9ee3f27ed08d875b4
app.quarkus.io/vcs-uri: https://xxxxx/quarkus-sandbox.git
app.quarkus.io/build-timestamp: 2024-08-24 - 10:11:15 +0000
定義這些鍵值時會希望是 prefix/name
這樣規範定義。這由助於團隊溝通、識別服務(可能像是屬於哪個團隊、業務是什麼類型之類)或是管理者進行除錯都很有幫助。
app.kubernetes.io/
它們兩之間的主要區別在於它們是否是可識別的。可以根據這些標籤值來篩選和分組資源,則應將數據映射為標籤。如果元數據不是標識碼,而是與 Kubernetes 資源相關的其他數據,則考慮用註釋。