注意:

在 Oracle Linux 上執行 Kubernetes

簡介

Kubernetes 是歐式駕駛員或制服員的希臘文,換句話說,遵循指令並引導船邁向其終極目標 (而非船長供應訂單) 的人員。Kubernetes 是一個開源、可擴充的平台,可用於部署、管理及調整容器化應用系統。它使用多個命令行工具來達到此目的。此實驗室使用其中一個稱為 kubectl 的檔案及 YAML 檔案來定義組織部署應用程式的必要屬性,並瞭解在部署應用程式之後如何設定及維護應用程式。

Kubernetes 叢集上的所有部署都會以物件方式呈現。這些部署的物件使用文字型 YAML 檔案,提供部署到叢集之任何應用程式所需狀態的詳細資訊。這些 YAML 檔案可能描述下列:

這個第三點雖然很重要,但沒有瞭解基本知識就很複雜。因此,我們將在未來的教學課程中暫時關閉,並加以處理。

本教學課程適用於在 Oracle Linux 上的精簡 Oracle Cloud Native Environment 中執行的 Kubernetes。針對管理生產部署所需的一切,目的不是「一站式商店」。而是會介紹部署工作範例應用程式所需的技能。

目標

必要條件

使用下列配置的 Oracle Linux 8 或更新版本系統:

設定實驗室環境

注意:使用免費實驗室環境時,請參閱 Oracle Linux Lab Basics,瞭解連線和其他使用指示。

資訊:免費實驗室環境會在提供的節點上部署 Oracle Cloud Native Environment,以供建立環境使用。此部署在啟動後大約需要 8-10 分鐘完成。因此,您可能想要在執行此作業時離開,然後返回完成實驗室。

  1. 如果尚未連接,請開啟終端機並透過 ssh 連線至 ocne-node01 系統。

    ssh oracle@<ip_address_of_ol_node>
    
  2. 確認環境已就緒。

    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。

  1. 建立 echoserver 的部署。

    kubectl create deployment test --image=k8s.gcr.io/echoserver:1.4
    
  2. 列出叢集中的所有 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 時會變化的字尾值。

  3. 使用 JSONPath 將 Pod 名稱指派給變數。

    TESTPOD=$(kubectl get pods -o jsonpath='{ $.items[*].metadata.name }')
    
  4. 測試變數指派。

    kubectl get pods 指令也允許傳送 Pod 名稱作為參數,以僅顯示該 Pod 的資訊。

    kubectl get pods $TESTPOD
    
  5. 要求選取的 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
    
  6. 取得 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 能夠確實執行部署要求,因此會重點介紹部分更重要的一部分:

如需這些其他欄位的詳細資訊,請參閱上游部署文件。

  1. 建立「部署」檔案。

    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
    
  2. 使用部署資訊清單檔案在 Pod 上部署應用程式。

    kubectl apply -f mydeployment.yaml
    

    範例輸出:

    [[oracle@ocne-node01 ~]$ kubectl apply -f mydeployment.yaml
    deployment.apps/echo1 created
    
  3. 列出由部署管理的 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 時會變化的字尾值。

  4. 驗證部署成功。

    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 可取得更多詳細資訊。
  5. 傳回更多部署詳細資訊。

    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 前端和後端元件之間的通訊。

  1. 取得節點清單。

    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 的實體系統或虛擬機器。

  2. 查詢 kube-proxy 模式。

    iptables 模式執行 kube-proxy 會導致傳送至 ClusterIP 服務的封包永遠不會成為來源 NAT。

    curl -w "\n" http://localhost:10249/proxyMode
    
    • kube-proxy 會在執行所在節點的 10249 連接埠監聽。
  3. 建立 ClusterIP 服務。

    kubectl expose deployment echo1 --name=clusterip-service --port=80 --target-port=8080
    
  4. 取得指定給叢集的 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 位址。

  5. 在相同的叢集中建立 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 /]#
    
  6. 取得 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
    
  7. 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 服務處理。

  8. 結束容器。

    exit
    

    範例輸出:

    [root@ol /]# exit
    exit
    pod "ol" deleted
    

使用 NodePort 服務搭配 YAML 檔案

先前的 echo1 部署是使用 kubectl expose 指令公開,並使用 ClusterIP 在內部存取。現在,我們將使用 NodePort 服務,這是開發者如何可透過網路從外部存取 echo1

NodePort 服務會在所有節點上開啟特定連接埠,並將任何流量轉送至該連接埠至服務。

注意「標準實務」不建議在「生產」系統上使用 NodePort,因為下列幾個原因:

  1. 定義服務檔案。

    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: - 容器監聽的連接埠。
  2. 建立服務。

    kubectl apply -f myservice.yaml
    

    範例輸出:

    [oracle@ocne-node01 ~]$ kubectl apply -f myservice.yaml 
    service/echo1 created
    

    注意:在相同的 YAML 檔案內具有部署與服務定義,以簡化應用程式的管理。在這些步驟中使用個別檔案僅作為訓練用途。將它們合併成單一檔案時,請使用 --- YAML 語法來分隔它們。

  3. 顯示 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: {}
    
  4. 描述 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>
    
  5. 取得物件端點。

    端點會追蹤服務傳送流量之 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
    
  6. 列出執行應用程式的 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>
    

    此清單中 echo1IP 位址應該符合端點上一個步驟中顯示的值,即在指定節點上執行的 Pod IP 位址。

  7. 列出服務。

    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

    請記下 NodePortecho1-nodeport 服務的設定為 32387

  8. 取得節點的 IP 位址。

    免費實驗室環境會在單一節點 ocne-node01 上執行。

    ip -br a
    

    在免費實驗室環境中,IP 位址應該會傳回指定給介面 ens3 的執行處理專用 IP 位址 10.0.0.140

  9. 使用 JSONPath 來指派 NodePort 變數。

    NODEPORT=$(kubectl get -o jsonpath="{.spec.ports[0].nodePort}" services echo1-nodeport)
    
  10. 使用 JSONPath 將節點 IP 指派給變數。

    NODES=$(kubectl get nodes -o jsonpath='{ $.items[*].status.addresses[?(@.type=="InternalIP")].address }')
    
  11. 建立防火牆規則。

    此規則允許 node:nodeport 上的流量,其中 node 是執行 Pod 之系統或虛擬機器的主機 IP 位址。

    sudo firewall-cmd --permanent --add-port=$NODEPORT/tcp
    sudo firewall-cmd --reload
    

    --reload 之後,firewalld 常駐程式會重新載入含有 iptables 的配置。由於 kube-proxy 取決於 iptables,因此「服務」的回應會有所延遲。

  12. 使用節點位址和節點連接埠驗證應用程式。

    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 中移除。

  1. 移除服務。

    kubectl delete svc clusterip-service echo1-nodeport
    
  2. 移除部署。

    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