開發應用程式
建立一組設定,將您的應用程式工作負載部署至 IBM Cloud® Kubernetes Service. 因為 Kubernetes 是一個可延伸的容器編排平台,並沒有規定特定的語言或應用程式,所以您可以執行各種工作負載,例如,無狀態、有狀態及資料處理應用程式,它們以您選擇的語言來撰寫。
在 YAML 檔案中指定應用程式需求
在 Kubernetes 中,您可在宣告 Kubernetes 物件配置的 YAML 檔案中說明應用程式。 然後,Kubernetes API 伺服器會處理 YAML 檔案,並將該物件的配置和所需狀態儲存在 etcd 資料儲存庫中。 Kubernetes 排程器會將您的工作負載排定至叢集內的工作者節點,同時考慮 YAML 檔案中的規格、管理者所設定的所有叢集原則,以及可用的叢集容量。
請檢視 完整的 YAML 檔案副本。 然後,檢閱下列各節以瞭解如何加強您的應用程式部署。
想了解更多關於物件 Kubernetes 如何協同運作以實現您的部署嗎? 請參閱 《理解應用程式的 Kubernetes 物件》。
基本部署 meta 資料
將適當的 API 版本用於您部署的 Kubernetes 物件類型。 API 版本會判定 Kubernetes 物件支援的特性,有哪些可供您使用。 您在 meta 資料中提供的名稱是物件的名稱,不是其標籤。 您在與物件互動時會使用該名稱,例如:kubectl get deployment <name>。
apiVersion: apps/v1
kind: Deployment
metadata:
name: wasliberty
抄本集
若要增加應用程式的可用性,您可以在部署中指定抄本集。 在抄本集中,您可以定義要部署多少個應用程式實例。 抄本集是由您的 Kubernetes 部署所管理及監視。 如果有一個應用程式實例關閉,Kubernetes 會自動啟動新的應用程式實例,以維持指定數目的應用程式實例。
spec:
replicas: 3
標籤
搭配標籤,您可以使用相同的 key: value 配對,標示叢集裡不同類型的資源。 然後,您可以指定要符合標籤的選取器,讓您可以針對這些其他資源進行建置。 如果您計劃公開應用程式,則必須使用一個符合您在服務中指定之選取器的標籤。 在此範例中,部署規格使用與該標籤相符的範本 app: wasliberty.
您可以擷取叢集裡標示的物件,例如查看 staging 或 production 元件。 例如,列出叢集裡所有名稱空間內具有 env: production 標籤的所有資源。 注意: 您必須具備所有命名空間的存取權限,才能執行此指令。
kubectl get all -l env=production --all-namespaces
- 有關標籤的更多資訊,請參閱 Kubernetes 的文件。
- 將標籤套用至工作者節點。
- 如需更詳細的範例,請參閱使用標籤將應用程式部署至特定工作者節點。
selector:
matchLabels:
app: wasliberty
template:
metadata:
labels:
app: wasliberty
親緣性
若要更精確地控制 Pod 應排程至哪些工作節點,請指定親和性(共置)。 親緣性僅在排定時影響 Pod。 例如,若要將部署分散至各工作節點,而非允許 Pod 排程在同一節點上,請在標準叢集中使用 podAntiAffinity 選項。 您可以定義兩種類型的 Pod 反親緣性:偏好或必要。
如需更多資訊,請參閱 Kubernetes 網站上關於「將 Pod 指派至節點」的文件。
- 需要反親緣性
- 您只能部署與您擁有的工作節點數量相等的複本。 例如,如果叢集裡有 3 個工作者節點,但在 YAML 檔案中定義了 5 個抄本,則僅部署 3 個抄本。 每一個抄本都位於不同的工作者節點上。 剩餘的 2 個抄本保持擱置狀態。 如果您新增另一個工作者節點至叢集,則其中一個剩餘的抄本會自動部署至新的工作者節點。 如果工作者節點失敗,則 Pod 不會重新排程,因為需要親緣性原則。 如需包含「required」設定的 YAML 範例,請參閱 《 Liberty 應用程式中的 Pod 反親和性設定(使用 required )》。
- 偏好的反親緣性
- 您可以將 Pod 部署至具有可用容量的節點上,這能為您的工作負載提供更大的靈活性。 可能的話,這些 Pod 會排定在不同的工作者節點上。 例如,如果叢集裡有 3 個工作者節點具有足夠的容量,則可以在這些節點上排定 5 個抄本 Pod。 然而,若您在叢集中新增兩個工作節點,親和性規則並不會強制將原本在現有節點上運行的那兩個額外 Pod 重新排程至可用節點上。
- 工作者節點親緣性
- 您可以將部署設定為僅在特定的工作節點(例如裸機)上執行。 如需相關資訊,請參閱使用標籤將應用程式部署至特定的工作者節點。
偏好的反親緣性的範例
spec:
affinity:
podAntiAffinity:
preferredDuringSchedulingIgnoredDuringExecution:
- weight: 100
podAffinityTerm:
labelSelector:
matchExpressions:
- key: app
operator: In
values:
- wasliberty
topologyKey: kubernetes.io/hostname
容器映像檔
指定您要用於容器的映像檔、映像檔的位置,以及影像取回原則。 若未指定圖片標籤,系統預設會載入標記為 latest 的圖片。
請避免在生產環境的工作負載中使用最新標籤。 如果您是使用公用或共用儲存庫(例如 Docker Hub 或 IBM Cloud Container Registry),則可能尚未測試具有最新映像檔的工作負載。
例如,若要列出公用 IBM 映像檔的標籤,請執行下列動作:
- 切換至全球登錄地區。
ibmcloud cr region-set global - 列出 IBM 映像檔。
ibmcloud cr images --include-ibm
預設 imagePullPolicy 設定為 IfNotPresent,僅當映像檔在本端不存在時才會取回該映像檔。 如果您要在每次容器啟動時都取回映像檔,請指定 imagePullPolicy: Always。
containers:
- name: wasliberty
image: icr.io/ibm/liberty:webProfile8
imagePullPolicy: Always
應用程式服務的埠
選取要在其上開啟應用程式服務的容器埠。 若要查看需要開啟的埠,請參閱您的應用程式規格或 Dockerfile。 此埠可從專用網路存取,但不能從公用網路連線存取。 若要公開應用程式,您必須建立 NodePort、負載平衡器或 Ingress 服務。 建立 Service 物件時,您可以使用這個相同的埠號。
所有服務的 25 號埠均遭封鎖。IBM Cloud
ports:
- containerPort: 9080
資源要求及限制
叢集管理員會為叢集中的每個 Kubernetes 命名空間建立一個 ResourceQuota 物件, 藉此確保共用同一叢集的團隊所佔用的運算資源(記憶體和 CPU)不會超過其應得的公平份額。 如果叢集管理者設定運算資源配額,則部署範本內的每一個容器都必須指定記憶體及
CPU 的資源要求與限制,否則無法建立 Pod。
- 檢查是否為名稱空間設定了資源配額。
kubectl get quota --namespace=<namespace> - 請參閱何謂配額限制。
kubectl describe quota <quota_name> --namespace=<namespace>
即使未設定任何資源配額,您也可以將資源要求及限制包括在部署中,以改善工作者節點資源的管理。
如果容器超出其限制,則容器可能會重新啟動或失敗。 如果容器超出要求,則在工作者節點用光超出的資源時,可能會收回其 Pod。 如需疑難排解的相關資訊,請參閱 Pod 重新啟動一再失敗或 Pod 被非預期移除。
- 要求
- 排程器為容器預留供其使用的資源最低數量。 如果數量等於限制,則保證要求。 如果資源數量小於限制,則仍會保證要求,但排程器可以使用要求和限制之間的差異來利用其他容器的資源。
- 限制
- 容器可消耗的資源最大量。 如果跨容器使用的資源總數量超過工作者節點上可用的數量,則可以收回容器以釋放空間。 若要防止收回,請將資源要求設為等於容器的限制。 如果未指定任何限制,則預設值為工作者節點的容量。
如需更多資訊,請參閱 Kubernetes 的文件。
resources:
requests:
memory: "512Mi"
cpu: "500m"
limits:
memory: "1024Mi"
cpu: "1000m"
存活性及就緒探測
依預設,Kubernetes 會在 Pod 中的所有容器啟動之後,將資料流量傳送至您的應用程式 Pod,並在容器當機後重新啟動它們。 不過,您可以設定性能檢查,以提高服務資料流量遞送的穩健性。
例如,您的應用程式可能會有啟動延遲的情形。 應用程式處理程序可能會在整個應用程式完全就緒之前就開始,此舉特別在跨多個實例擴增時可能會影響回應。 使用性能檢查,您可以讓系統得知您的應用程式是否在執行中,以及是否可以接收要求。 藉由設定這些探測,您也可以在執行應用程式的漸進式更新時,協助防止應用程式運作中斷時間。 您可以設定兩種類型的性能檢查:存活性及就緒探測。
- 活性探測
- 設定一個存活偵測機制,以檢查容器是否正在執行。 如果探測失敗,則容器會重新啟動。 如果容器未指定存活性探測,則探測會順利,因為它假設當容器處於執行中狀態時,表示容器作用中。
- 就緒探測
- 設定一個就緒探針,以檢查容器是否已準備好接收請求和外部流量。 如果探測失敗,則會移除 Pod 的 IP 位址,作為符合 Pod 之服務的可用 IP 位址,但容器不會重新啟動。 如果您的應用程式需要一段時間才能啟動,設定具有初始延遲的就緒探針就顯得格外重要。 在起始延遲之前,探測器不會啟動,讓容器有時間啟動。 如果容器未提供就緒探測,則探測會順利,因為它假設當容器處於執行中狀態時,表示容器作用中。
您可以將探測設為指令、HTTP 要求或 TCP Socket。 此範例使用 HTTP 要求。 讓存活性探測比就緒探測具有更多的時間。 如需更多資訊,請參閱 Kubernetes 的文件。
livenessProbe:
httpGet:
path: /
port: 9080
initialDelaySeconds: 300
periodSeconds: 15
readinessProbe:
httpGet:
path: /
port: 9080
initialDelaySeconds: 45
periodSeconds: 5
Pod 中斷預算
若要增加應用程式的可用性,您可以根據您想要使用 PodDisruptionBudget 物件的可用性類型,控制應用程式如何對 中斷 做出反應。
Pod 中斷預算可協助您規劃應用程式在自願中斷期間的行為方式,例如當您透過更新應用程式部署來起始直接重新啟動時,或非自願中斷時,例如核心恐慌。
minAvailable : 您可以指定在發生毀壞之後必須仍然可用的 Pod 數目或百分比。
maxUnavailable- 您可以指定發生中斷之後可能無法使用的 Pod 數目或百分比。 範例使用
maxUnavailable: 1。 selector- 輸入標籤以選擇
PodDisruptionBudget適用的 pod 集。 請注意,如果您在其他 Pod 部署中使用此相同標籤,則 Pod 也會套用至那些標籤。
如需更多資訊,請參閱 Kubernetes 的文件。
apiVersion: policy/v1beta1
kind: PodDisruptionBudget
metadata:
name: wasliberty
spec:
maxUnavailable: 1
selector:
matchLabels:
app: wasliberty
公開應用程式服務
您可以建立一個公開應用程式的服務。 在 spec 區段中,確定 port 及標籤值與您在部署中使用的值相符。 服務會在下列範例中公開符合標籤(例如 app: wasliberty)的物件。
- 預設情況下,服務會使用
ClusterIP,這使得該服務僅能在叢集內部存取,而無法從叢集外部存取。 - 您可以建立 NodePort、負載平衡器或 Ingress 服務,以公開應用程式。 這些服務有兩個 IP,一個外部及一個內部。 在外部 IP 收到資料流量時,會將其轉遞至內部叢集 IP。 然後,從內部叢集 IP 中,資料流量會遞送至應用程式的容器 IP。
- 範例會使用
NodePort,在叢集外公開服務。 如需如何設定外部存取權的相關資訊,請參閱選擇 NodePort、負載平衡器或 Ingress 服務。
apiVersion: v1
kind: Service
metadata:
name: wasliberty
labels:
app: wasliberty
spec:
ports:
- port: 9080
selector:
app: wasliberty
type: NodePort
若需部署 hostNetwork Pod 監聽特定端口,或使用 hostPort 將應用 Pod 暴露於工作節點的特定端口,請使用 範圍 11000-11200 內的端口。此範圍專為工作 IBM Cloud Kubernetes Service 節點端口 11000-11200 分配而設,可避免與本地端口及 使用的 IBM Cloud Kubernetes Service
其他端口產生衝突。 因為 hostNetwork Pod 及 hostPorts 參照特定工作者節點 IP 位址,所以會將 Pod 限制為只在該工作者節點上執行。 若發生任何意外情況,例如工作節點被移除或資源耗盡,您的 Pod 將無法重新排程。 如果您要在工作者節點上公開 Pod 的埠,請改為考慮使用 NodePort 服務。
如需更多資訊,請參閱 最佳實務 Kubernetes 文件。
容器環境變數的 ConfigMap
ConfigMap 會將非機密配置資訊提供給您的部署工作負載。
下列範例顯示如何在部署 YAML 的容器規格區段中,將您 ConfigMap 中的值參照為環境變數。 藉由參照 ConfigMap 中的值,您可以取消此配置資訊與部署的連結,以將您的容器化應用程式保持可攜狀態。
- 協助我判定要將 Kubernetes
ConfigMap還是Secret物件用於變數。 - 如需了解 configmaps 的更多使用方式,請參閱 Kubernetes 文件。
apiVersion: apps/v1
kind: Deployment
metadata:
name: wasliberty
spec:
replicas: 3
template:
...
spec:
...
containers:
- name: wasliberty
...
env:
- name: VERSION
valueFrom:
configMapKeyRef:
name: wasliberty
key: VERSION
- name: LANGUAGE
valueFrom:
configMapKeyRef:
name: wasliberty
key: LANGUAGE
...
---
apiVersion: v1
kind: ConfigMap
metadata:
name: wasliberty
labels:
app: wasliberty
data:
VERSION: "1.0"
LANGUAGE: en
容器環境變數的密碼
密碼可將機密配置資訊(例如密碼)提供給您的部署工作負載。
下列範例顯示如何在部署 YAML 的容器規格區段中,將密碼中的值作為環境變數參照。 您也可以將密碼裝載為磁區。 藉由參照密碼中的值,您可以取消此配置資訊與部署的連結,以將您的容器化應用程式保持可攜狀態。
要集中管理跨叢集的所有機密,並在應用程式執行時進行注入,請嘗試使用 IBM Cloud Secrets Manager.
apiVersion: apps/v1
kind: Deployment
metadata:
name: wasliberty
spec:
replicas: 3
template:
...
spec:
...
containers:
- name: wasliberty
...
env:
- name: username
valueFrom:
secretKeyRef:
name: wasliberty
key: username
- name: password
valueFrom:
secretKeyRef:
name: wasliberty
key: password
...
---
apiVersion: v1
kind: Secret
metadata:
name: wasliberty
labels:
app: wasliberty
type: Opaque
data:
username: dXNlcm5hbWU=
password: cGFzc3dvcmQ=
容器儲存空間的持續性磁區
具有實體儲存空間的持續性磁區 (PV) 介面,用來為您的容器工作負載提供持續性資料儲存空間。
下列範例顯示如何將持續性儲存空間新增至應用程式。 若要佈建持續性儲存空間,請建立持續性磁區要求 (PVC),以說明您要擁有之檔案儲存空間的類型及大小。 建立 PVC 後,系統會透過動態配置自動建立持久化卷和實體儲存空間。 藉由參照部署 YAML 中的 PVC,儲存空間會自動裝載至您的應用程式 Pod。 當 Pod 中的容器將資料寫入 /test 裝載路徑目錄時,資料會儲存在 NFS 檔案儲存空間實例上。 如需您可以佈建之其他儲存空間類型的相關選項,請參閱
規劃高度可用的持續性儲存空間。
apiVersion: apps/v1
kind: Deployment
metadata:
name: wasliberty
spec:
replicas: 3
template:
...
spec:
...
containers:
- name: wasliberty
...
volumeMounts:
- name: pvmount
mountPath: /test
volumes:
- name: pvmount
persistentVolumeClaim:
claimName: wasliberty
...
---
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: wasliberty
annotations:
volume.beta.kubernetes.io/storage-class: "ibmc-file-bronze"
labels:
billingType: "hourly"
app: wasliberty
spec:
accessModes:
- ReadWriteMany
resources:
requests:
storage: 24Gi
完整範例部署 YAML
下列範例是先前逐個部分討論的部署 YAML 的副本。 您也可以 從 GitHub 下載該 YAML 檔案。
若要套用 YAML,
kubectl apply -f file.yaml [-n <namespace>]
範例 YAML
apiVersion: apps/v1
kind: Deployment
metadata:
name: wasliberty
spec:
replicas: 3
selector:
matchLabels:
app: wasliberty
template:
metadata:
labels:
app: wasliberty
spec:
affinity:
podAntiAffinity:
preferredDuringSchedulingIgnoredDuringExecution:
- weight: 100
podAffinityTerm:
labelSelector:
matchExpressions:
- key: app
operator: In
values:
- wasliberty
topologyKey: kubernetes.io/hostname
containers:
- name: wasliberty
image: icr.io/ibm/liberty:latest
env:
- name: VERSION
valueFrom:
configMapKeyRef:
name: wasliberty
key: VERSION
- name: LANGUAGE
valueFrom:
configMapKeyRef:
name: wasliberty
key: LANGUAGE
- name: username
valueFrom:
secretKeyRef:
name: wasliberty
key: username
- name: password
valueFrom:
secretKeyRef:
name: wasliberty
key: password
ports:
- containerPort: 9080
resources:
requests:
memory: "512Mi"
cpu: "500m"
limits:
memory: "1024Mi"
cpu: "1000m"
livenessProbe:
httpGet:
path: /
port: 9080
initialDelaySeconds: 300
periodSeconds: 15
readinessProbe:
httpGet:
path: /
port: 9080
initialDelaySeconds: 45
periodSeconds: 5
volumeMounts:
- name: pvmount
mountPath: /test
volumes:
- name: pvmount
persistentVolumeClaim:
claimName: wasliberty
---
apiVersion: policy/v1beta1
kind: PodDisruptionBudget
metadata:
name: wasliberty
spec:
maxUnavailable: 1
selector:
matchLabels:
app: wasliberty
---
apiVersion: v1
kind: Service
metadata:
name: wasliberty
labels:
app: wasliberty
spec:
ports:
- port: 9080
selector:
app: wasliberty
type: NodePort
---
apiVersion: v1
kind: ConfigMap
metadata:
name: wasliberty
labels:
app: wasliberty
data:
VERSION: "1.0"
LANGUAGE: en
---
apiVersion: v1
kind: Secret
metadata:
name: wasliberty
labels:
app: wasliberty
type: Opaque
data:
username: dXNlcm5hbWU=
password: cGFzc3dvcmQ=
---
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: wasliberty
annotations:
volume.beta.kubernetes.io/storage-class: "ibmc-file-bronze"
labels:
billingType: "hourly"
app: wasliberty
spec:
accessModes:
- ReadWriteMany
resources:
requests:
storage: 24Gi