注意:
- 本教學課程包含在 Oracle 提供的免費實驗室環境中。
- 它會使用 Oracle Cloud Infrastructure 證明資料、租用戶以及區間的範例值。完成實驗室之後,請將這些值取代為您雲端環境特有的值。
在 Oracle Linux 上執行 Kubernetes
簡介
Kubernetes 是歐式駕駛員或制服員的希臘文,換句話說,遵循指令並引導船邁向其終極目標 (而非船長供應訂單) 的人員。Kubernetes 是一個開源、可擴充的平台,可用於部署、管理及調整容器化應用系統。它使用多個命令行工具來達到此目的。此實驗室使用其中一個稱為 kubectl
的檔案及 YAML 檔案來定義組織部署應用程式的必要屬性,並瞭解在部署應用程式之後如何設定及維護應用程式。
Kubernetes 叢集上的所有部署都會以物件方式呈現。這些部署的物件使用文字型 YAML 檔案,提供部署到叢集之任何應用程式所需狀態的詳細資訊。這些 YAML 檔案可能描述下列:
- 要在哪個節點執行的容器化應用程式
- 應用程式所需的資源詳細資訊
- 詳述這些應用程式如何維持其狀態的所有原則,例如重新啟動原則、升級原則等。
這個第三點雖然很重要,但沒有瞭解基本知識就很複雜。因此,我們將在未來的教學課程中暫時關閉,並加以處理。
本教學課程適用於在 Oracle Linux 上的精簡 Oracle Cloud Native Environment 中執行的 Kubernetes。針對管理生產部署所需的一切,目的不是「一站式商店」。而是會介紹部署工作範例應用程式所需的技能。
目標
- 檢查不同的 Kubernetes 元件,例如 Pod、Deployment 及 Service
- 檢查不同的 Kubernetes 物件
- 部署並測試範例專案
必要條件
使用下列配置的 Oracle Linux 8 或更新版本系統:
- 具有
sudo
權限的非 root 使用者 - 安裝並設定 Oracle Cloud Native Environment
設定實驗室環境
注意:使用免費實驗室環境時,請參閱 Oracle Linux Lab Basics,瞭解連線和其他使用指示。
資訊:免費實驗室環境會在提供的節點上部署 Oracle Cloud Native Environment,以供建立環境使用。此部署在啟動後大約需要 8-10 分鐘完成。因此,您可能想要在執行此作業時離開,然後返回完成實驗室。
-
如果尚未連接,請開啟終端機並透過 ssh 連線至 ocne-node01 系統。
ssh oracle@<ip_address_of_ol_node>
-
確認環境已就緒。
kubectl get pods -A
範例輸出:
[oracle@ocne-node01 ~]$ kubectl get pods -A NAMESPACE NAME READY STATUS RESTARTS AGE externalip-validation-system externalip-validation-webhook-7988bff847-8ws2v 1/1 Running 0 3m18s kube-system coredns-7cbc77dbc7-qxqth 1/1 Running 0 3m18s kube-system coredns-7cbc77dbc7-r9bgj 1/1 Running 0 3m18s kube-system etcd-ocne-node01 1/1 Running 0 3m37s kube-system kube-apiserver-ocne-node01 1/1 Running 0 3m37s kube-system kube-controller-manager-ocne-node01 1/1 Running 0 3m37s kube-system kube-flannel-ds-vcwzn 1/1 Running 0 3m18s kube-system kube-proxy-7lx59 1/1 Running 0 3m18s kube-system kube-scheduler-ocne-node01 1/1 Running 0 3m37s kubernetes-dashboard kubernetes-dashboard-5d5d4947b5-7pffh 1/1 Running 0 3m18s
在 Pod 和要求詳細資訊上建立部署
在 Kubernetes 中,部署是一項技術術語,可用來管理 Pod 的行為與特性。管理員可以使用部署來指示應用程式該如何進行,而 Kubernetes 則會執行作業來達到該狀態。
這些範例使用的影像包含小型 nginx Web 伺服器,可回溯透過 HTTP 標頭接收之要求的來源 IP。
-
建立 echoserver 的部署。
kubectl create deployment test --image=k8s.gcr.io/echoserver:1.4
-
列出叢集中的所有 Pod。
kubectl get pods
範例輸出:
[oracle@ocne-node01 ~]$ kubectl get pods NAME READY STATUS RESTARTS AGE test-6c486b6d76-467p7 1/1 Running 0 53s
備註:Pod 名稱包含每次部署 Pod 時會變化的字尾值。
-
使用 JSONPath 將 Pod 名稱指派給變數。
TESTPOD=$(kubectl get pods -o jsonpath='{ $.items[*].metadata.name }')
-
測試變數指派。
kubectl get pods
指令也允許傳送 Pod 名稱作為參數,以僅顯示該 Pod 的資訊。kubectl get pods $TESTPOD
-
要求選取的 Pod 資訊。
kubectl get pod $TESTPOD --output custom-columns=NAME:metadata.name,NODE_IP:status.hostIP,POD_IP:status.podIP
範例輸出:
[oracle@ocne-node01 ~]$ kubectl get pod $TESTPOD --output custom-columns=NAME:metadata.name,NODE_IP:status.hostIP,POD_IP:status.podIP NAME NODE_IP POD_IP test-6c486b6d76-467p7 10.0.0.140 10.244.0.7
-
取得 Pod 詳細資訊。
kubectl describe pod $TESTPOD
範例輸出:
[oracle@ocne-node01 ~]$ kubectl describe pod test-6c486b6d76-467p7 Name: test-6c486b6d76-467p7 Namespace: default Priority: 0 Node: ocne-node01/10.0.0.140 Start Time: Tue, 28 Jun 2022 19:21:27 +0000 Labels: app=test pod-template-hash=6c486b6d76 Annotations: <none> Status: Running IP: 10.244.0.7 IPs: IP: 10.244.0.7 Controlled By: ReplicaSet/test-6c486b6d76 Containers: echoserver: Container ID: cri-o://5b7866a27722ec0998cd9fe74945fb82b4dd9ed4c5c80671d9e8aa239c7008a4 Image: k8s.gcr.io/echoserver:1.4 Image ID: k8s.gcr.io/echoserver@sha256:5d99aa1120524c801bc8c1a7077e8f5ec122ba16b6dda1a5d3826057f67b9bcb Port: <none> Host Port: <none> State: Running Started: Tue, 28 Jun 2022 19:21:30 +0000 Ready: True Restart Count: 0 Environment: <none> Mounts: /var/run/secrets/kubernetes.io/serviceaccount from kube-api-access-d67ph (ro) Conditions: Type Status Initialized True Ready True ContainersReady True PodScheduled True Volumes: kube-api-access-d67ph: Type: Projected (a volume that contains injected data from multiple sources) TokenExpirationSeconds: 3607 ConfigMapName: kube-root-ca.crt ConfigMapOptional: <nil> DownwardAPI: true QoS Class: BestEffort Node-Selectors: <none> Tolerations: node.kubernetes.io/not-ready:NoExecute op=Exists for 300s node.kubernetes.io/unreachable:NoExecute op=Exists for 300s Events: Type Reason Age From Message ---- ------ ---- ---- ------- Normal Scheduled 21m default-scheduler Successfully assigned default/test-6c486b6d76-467p7 to ocne-node01 Normal Pulling 21m kubelet Pulling image "k8s.gcr.io/echoserver:1.4" Normal Pulled 21m kubelet Successfully pulled image "k8s.gcr.io/echoserver:1.4" in 3.102843235s Normal Created 21m kubelet Created container echoserver Normal Started 21m kubelet Started container echoserver
使用 YAML 檔案建立部署
使用 Kubernetes 部署資訊清單可定義如何將應用程式部署至 Kubernetes 叢集,並提供存取其他 Kubernetes 功能 (例如自我修復、擴展性、版本控制及輪流更新)。此實驗室將不會解決 Kubernetes 中提供的更複雜功能。而是會說明如何使用非常基本的清單檔案來部署應用程式。
部署資訊清單檔案會以 JSON 或 YAML 撰寫。雖然可以使用 JSON,但因為 YAML 的彈性、可讀性以及具備描述性註解功能,能夠清楚說明最終部署層面的緣故,所以較為受歡迎。
執行部署時,會透過一系列宣告更新來更新 Pod,以達到執行之應用程式的所需狀態。
deployment.yaml 中的所有詳細資訊對於 Kubernetes 能夠確實執行部署要求,因此會重點介紹部分更重要的一部分:
- apiVersion 欄位指定要使用的 Kubernetes API 版本。如果使用最新版本的 Kubernetes,請將其設定為 apps/v1。
- 在此範例中,kind 欄位會通知 Kubernetes 參閱稱為部署的物件類型。
- 描述資料區段用於概述「部署」名稱和相關標籤的詳細資訊
- .spec 區段可能是任何部署資訊清單檔案的最重要區段。從此處開始的任何項目都與部署 Pod 相關。.spec.template 區段下方的任何內容說明 Pod 樣板,Kubernetes 用來管理部署 (在此範例中,是一個單一容器)。
- 此範例中未使用的其他欄位是 .spec.replicas 欄位 (它會告訴 Kubernetes 要部署的 Pod 複本數目),以及 .spec.strategy 欄位 (告訴 Kubernetes 如何執行部署的更新)。
如需這些其他欄位的詳細資訊,請參閱上游部署文件。
-
建立「部署」檔案。
cat << 'EOF' | tee mydeployment.yaml > /dev/null apiVersion: apps/v1 kind: Deployment metadata: name: echo1 spec: selector: matchLabels: app: echo1 template: metadata: labels: app: echo1 spec: containers: - name: echoserver image: k8s.gcr.io/echoserver:1.4 EOF
-
使用部署資訊清單檔案在 Pod 上部署應用程式。
kubectl apply -f mydeployment.yaml
範例輸出:
[[oracle@ocne-node01 ~]$ kubectl apply -f mydeployment.yaml deployment.apps/echo1 created
-
列出由部署管理的 Pod。
kubectl get pods -l app=echo1
範例輸出:
[oracle@ocne-node01 ~]$ kubectl get pods -l app=echo1 NAME READY STATUS RESTARTS AGE echo1-7cbf6dfb96-4cgq7 1/1 Running 0 24s
-l
或--selector=
選項提供要篩選的選取器 (標籤查詢)。此選項支援 '='、'==' 和 '!='。(例如-l key1=value1,key2=value2
)
備註:提示 Pod 名稱包含每次部署 Pod 時會變化的字尾值。
-
驗證部署成功。
kubectl get deploy echo1
範例輸出:
[oracle@ocne-node01 ~]$ kubectl get deploy echo1 NAME READY UP-TO-DATE AVAILABLE AGE echo1 1/1 1 1 16m
deploy
選項是deployments
的簡短手。kubectl
指令允許針對其許多選項使用縮寫語法。執行kubectl --help
可取得更多詳細資訊。
-
傳回更多部署詳細資訊。
kubectl describe deploy echo1
範例輸出:
[oracle@ocne-node01 ~]$ kubectl describe deploy echo1 Name: echo1 Namespace: default CreationTimestamp: Tue, 28 Jun 2022 20:20:40 +0000 Labels: <none> Annotations: deployment.kubernetes.io/revision: 1 Selector: app=echo1 Replicas: 1 desired | 1 updated | 1 total | 1 available | 0 unavailable StrategyType: RollingUpdate MinReadySeconds: 0 RollingUpdateStrategy: 25% max unavailable, 25% max surge Pod Template: Labels: app=echo1 Containers: echoserver: Image: k8s.gcr.io/echoserver:1.4 Port: <none> Host Port: <none> Environment: <none> Mounts: <none> Volumes: <none> Conditions: Type Status Reason ---- ------ ------ Available True MinimumReplicasAvailable Progressing True NewReplicaSetAvailable OldReplicaSets: <none> NewReplicaSet: echo1-7cbf6dfb96 (1/1 replicas created) Events: Type Reason Age From Message ---- ------ ---- ---- ------- Normal ScalingReplicaSet 23m deployment-controller Scaled up replica set echo1-7cbf6dfb96 to 1
使用 ClusterIP 服務
儘管成功將 echo1 部署部署至 Pod,但一般使用者無法在內部或網路上存取 Pod 時,仍無法使用。在服務公開到網路的部署時,該存取會方便。
預設的 Kubernetes 服務類型為 ClusterIP。不過,您無法從網際網路存取 ClusterIP 服務,但是可以使用 Kubernetes 代理主機。如需有關代理伺服器的詳細資訊,請參閱上游文件。
本節公開 echo1,並使用 Oracle Linux Pod 建立叢集內的服務間通訊,示範您 App 前端和後端元件之間的通訊。
-
取得節點清單。
kubectl get nodes
範例輸出:
[oracle@ocne-node01 ~]$ kubectl get nodes NAME STATUS ROLES AGE VERSION ocne-node01 Ready <none> 4h27m v1.22.8+1.el8
節點是部署 Pod 的實體系統或虛擬機器。
-
查詢 kube-proxy 模式。
以 iptables 模式執行 kube-proxy 會導致傳送至 ClusterIP 服務的封包永遠不會成為來源 NAT。
curl -w "\n" http://localhost:10249/proxyMode
- kube-proxy 會在執行所在節點的 10249 連接埠監聽。
-
建立 ClusterIP 服務。
kubectl expose deployment echo1 --name=clusterip-service --port=80 --target-port=8080
-
取得指定給叢集的 IP 位址。
kubectl get svc clusterip-service
範例輸出:
[oracle@ocne-node01 ~]$ kubectl get svc clusterip-service NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE clusterip-service ClusterIP 10.108.107.54 <none> 80/TCP 13s
記下輸出中的
CLUSTER-IP
位址。 -
在相同的叢集中建立 Pod 以存取 ClusterIP 服務。
kubectl run ol -it --image=oraclelinux:8 --restart=Never --rm
此命令會以 interactive 模式,建立執行 Oracle Linux 8 容器的 Pod,並出現命令提示符號。
範例輸出:
[oracle@ocne-node01 ~]$ kubectl run ol -it --image=oraclelinux:8 --restart=Never --rm If you don't see a command prompt, try pressing enter. [root@ol /]#
-
取得 Oracle Linux 容器的 IP 位址。
ip -br a
範例輸出:
[root@ol /]# ip -br a lo UNKNOWN 127.0.0.1/8 ::1/128 eth0@if12 UP 10.244.0.9/24 fe80::146f:2cff:fe73:b528/64
-
在 echo1 內測試 nginx Web 伺服器。
curl -w "\n" <CLUSTER-IP_ADDRESS>
使用前一個輸出的
CLUSTER-IP
位址。範例輸出:
[root@ol /]# curl -w "\n" 10.108.107.54 CLIENT VALUES: client_address=10.244.0.9 command=GET real path=/ query=nil request_version=1.1 request_uri=http://10.108.107.54:8080/ SERVER VALUES: server_version=nginx: 1.10.0 - lua: 10001 HEADERS RECEIVED: accept=*/* host=10.108.107.54 user-agent=curl/7.61.1 BODY: -no body in request-
輸出顯示來自 Oracle Linux 的要求,並使用 echo1 部署由 ClusterIP 服務處理。
-
結束容器。
exit
範例輸出:
[root@ol /]# exit exit pod "ol" deleted
使用 NodePort 服務搭配 YAML 檔案
先前的 echo1 部署是使用 kubectl expose
指令公開,並使用 ClusterIP 在內部存取。現在,我們將使用 NodePort 服務,這是開發者如何可透過網路從外部存取 echo1。
NodePort 服務會在所有節點上開啟特定連接埠,並將任何流量轉送至該連接埠至服務。
注意「標準實務」不建議在「生產」系統上使用 NodePort,因為下列幾個原因:
- 每個部署的服務都需要不同的連接埠
- 節點需要公開使用 - 不建議使用。
- 節點之間不會發生負載平衡 (在多節點 Kubernetes 叢集中)
-
定義服務檔案。
cat << 'EOF' | tee myservice.yaml > /dev/null apiVersion: v1 kind: Service metadata: name: echo1-nodeport namespace: default spec: ipFamilies: - IPv4 ipFamilyPolicy: SingleStack ports: - nodePort: 32387 port: 80 protocol: TCP targetPort: 8080 selector: app: echo1 sessionAffinity: None type: NodePort status: loadBalancer: {} EOF
- 類型: - 讓來自外部用戶端的網路要求能夠使用服務。有效值包括:nodePort、LooadBalancer。
- nodePort: - 用來存取服務的外部連接埠。
- 連接埠: - 顯示在叢集內的連接埠號碼。
- targetPort: - 容器監聽的連接埠。
-
建立服務。
kubectl apply -f myservice.yaml
範例輸出:
[oracle@ocne-node01 ~]$ kubectl apply -f myservice.yaml service/echo1 created
注意:在相同的 YAML 檔案內具有部署與服務定義,以簡化應用程式的管理。在這些步驟中使用個別檔案僅作為訓練用途。將它們合併成單一檔案時,請使用
---
YAML 語法來分隔它們。 -
顯示 Kubernetes 如何儲存新建立的服務。
kubectl get service echo1-nodeport -o yaml
範例輸出:
[oracle@ocne-node01 ~]$ kubectl get service echo1-nodeport -o yaml apiVersion: v1 kind: Service metadata: annotations: kubectl.kubernetes.io/last-applied-configuration: | {"apiVersion":"v1","kind":"Service","metadata":{"annotations":{},"name":"echo1-nodeport","namespace":"default"},"spec":{"ipFamilies":["IPv4"],"ipFamilyPolicy":"SingleStack","ports":[{"nodePort":32387,"port":80,"protocol":"TCP","targetPort":8080}],"selector":{"app":"echo1"},"sessionAffinity":"None","type":"NodePort"},"status":{"loadBalancer":{}}} creationTimestamp: "2022-06-29T00:14:30Z" name: echo1-nodeport namespace: default resourceVersion: "6242" uid: 3171dda6-05b8-45b8-a0ba-457eab6e4f71 spec: clusterIP: 10.100.17.53 clusterIPs: - 10.100.17.53 externalTrafficPolicy: Cluster internalTrafficPolicy: Cluster ipFamilies: - IPv4 ipFamilyPolicy: SingleStack ports: - nodePort: 32387 port: 80 protocol: TCP targetPort: 8080 selector: app: echo1 sessionAffinity: None type: NodePort status: loadBalancer: {}
-
描述 Pod 服務。
kubectl describe svc echo1-nodeport
範例輸出:
[oracle@ocne-node01 ~]$ kubectl describe svc echo1-nodeport Name: echo1-nodeport Namespace: default Labels: <none> Annotations: <none> Selector: app=echo1 Type: NodePort IP Family Policy: SingleStack IP Families: IPv4 IP: 10.100.17.53 IPs: 10.100.17.53 Port: <unset> 80/TCP TargetPort: 8080/TCP NodePort: <unset> 32387/TCP Endpoints: 10.244.0.7:8080 Session Affinity: None External Traffic Policy: Cluster Events: <none>
-
取得物件端點。
端點會追蹤服務傳送流量之 Pod 的 IP 位址。
kubectl get endpoints echo1-nodeport
範例輸出:
[oracle@ocne-node01 ~]$ kubectl get endpoints echo1-nodeport NAME ENDPOINTS AGE echo1-nodeport 10.244.0.7:8080 8m39s
-
列出執行應用程式的 Pod。
kubectl get pods --output=wide
範例輸出:
[oracle@ocne-node01 ~]$ kubectl get pods -o wide NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES echo1-7cbf6dfb96-mlds4 1/1 Running 0 80m 10.244.0.7 ocne-node01 <none> <none> test-6c486b6d76-v4htj 1/1 Running 0 83m 10.244.0.6 ocne-node01 <none> <none>
此清單中 echo1 的 IP 位址應該符合端點上一個步驟中顯示的值,即在指定節點上執行的 Pod IP 位址。
-
列出服務。
kubectl get svc -o wide
範例輸出:
[oracle@ocne-node01 ~]$ kubectl get svc -o wide NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE SELECTOR clusterip-service ClusterIP 10.107.31.75 <none> 80/TCP 78m app=echo1 echo1-nodeport NodePort 10.100.17.53 <none> 80:32387/TCP 10m app=echo1 kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 88m <none>
此指令使用
-o wide
的替代選項,而非--output=wide
。請記下 NodePort,echo1-nodeport 服務的設定為 32387。
-
取得節點的 IP 位址。
免費實驗室環境會在單一節點 ocne-node01 上執行。
ip -br a
在免費實驗室環境中,IP 位址應該會傳回指定給介面 ens3 的執行處理專用 IP 位址 10.0.0.140。
-
使用 JSONPath 來指派 NodePort 變數。
NODEPORT=$(kubectl get -o jsonpath="{.spec.ports[0].nodePort}" services echo1-nodeport)
-
使用 JSONPath 將節點 IP 指派給變數。
NODES=$(kubectl get nodes -o jsonpath='{ $.items[*].status.addresses[?(@.type=="InternalIP")].address }')
-
建立防火牆規則。
此規則允許
node:nodeport
上的流量,其中node
是執行 Pod 之系統或虛擬機器的主機 IP 位址。sudo firewall-cmd --permanent --add-port=$NODEPORT/tcp sudo firewall-cmd --reload
--reload
之後,firewalld 常駐程式會重新載入含有iptables
的配置。由於 kube-proxy 取決於iptables
,因此「服務」的回應會有所延遲。 -
使用節點位址和節點連接埠驗證應用程式。
curl -s $NODES:$NODEPORT
範例輸出:
[oracle@ocne-node01 ~]$ curl -s $NODES:NODEPORT CLIENT VALUES: client_address=10.244.0.1 command=GET real path=/ query=nil request_version=1.1 request_uri=http://10.0.0.140:8080/ SERVER VALUES: server_version=nginx: 1.10.0 - lua: 10001 HEADERS RECEIVED: accept=*/* host=10.0.0.140:32387 user-agent=curl/7.61.1 BODY:
輸出會從本機節點路由向 NodePort 服務、透過 kube-proxy 以及執行 echo1 部署的 Pod 顯示要求。
注意:如果輸出似乎停滯,這是因為前次重新載入防火牆所致。輸入
Ctrl-C
,然後再試一次。
移除部署和服務
完成服務或部署之後,請將這些服務從 Kubernetes 中移除。
-
移除服務。
kubectl delete svc clusterip-service echo1-nodeport
-
移除部署。
kubectl delete deployments echo1 kubectl delete deploy test
移除物件可個別執行或以群組方式完成。如需詳細資訊,請參閱 Kubernetes Reference Manual。
摘要
此實驗室只簡要介紹使用像 Kubernetes 等雲端原生協調器的功能,提供給使用 Kubernetes 管理容器部署的任何組織。這些練習提供使用 Kubernetes 提供彈性的首要步驟。
其他相關資訊
其他學習資源
探索 docs.oracle.com/learn 上的其他實驗室,或前往 Oracle Learning YouTube 通道存取更多免費學習內容。此外,請造訪 education.oracle.com/learning-explorer 以成為 Oracle Learning Explorer。
如需產品文件,請瀏覽 Oracle Help Center。