天天看點

Kind Kubernetes 部署簡單應用 上篇

Kind Kubernetes 部署簡單應用 上篇

本文承接《代理環境下在 WSL2 中用 Kind 建立 Kubernetes 叢集》一文,主要講述如何在K8s中部署應用。

首先,我們先講述後續部署實戰中會用到的一些概念

  • Pod
  • Deployment
  • Service
  • Namespaces
  • DNS

然後,重建Kind K8s環境,并部署一個可以從本地通路的簡單網頁。

目錄

- 環境(配置)

- K8s 部署應用相關概念

  1. Workloads

      - Pod

  2. Workloads Resources

      - Deployment

  3. Service

  4. Namespaces

  5. DNS

- 實戰步驟

  1. 重建 K8s,暴露 80、443 端口

  2. 部署 Deployment、Service

      - 部署 Deployment

      - 部署 Service

      - 更改 Serivce(nodePort)

- 總結

- 引申

- 後記

環境(配置)

  • Win10 + WSL2
  • Docker desktop 3.3.3 或以上版本
  • kind

K8s 部署應用相關概念

1. Workloads

Workloads(工作負載)是運作在 K8s 上的應用,可以是單獨一個元件(比如一個 Job)也可以是多個元件協同運作(比如 deployment,service,ingress 等一起構成一個應用)。

無論是哪種形式,在 K8s 上負載最終都是以 Pod 為基本機關運作的。

Pod 本身有一個生命周期,比如當一個 node 出現故障當機了,則此 node 上運作的所有 Pod 會失敗,這時我們需要重新在其它節點建立 Pod。

一般情況下,我們不直接運作 Pod,我們通過 Workloads Resources 來幫我們管理 Pod。

每個 Workloads Resources 有不同的 controller 相對應,controller 按我們的要求維護 Pod 的狀态(比如在一個 node 失敗後,在其它節點重建 pod)。

Pod

Pod 是我們在 K8s 中可以建立使用的最小計算單元。每個 Pod 可以由一個或者多個容器組成。

比如,kube-system namespace 内運作的 pods

Kind Kubernetes 部署簡單應用 上篇

K8s 為每個 Pod 配置設定一個叢集内部的 IP 和 DNS。

多個容器組成的 Pods 中,容器之間共享 Pod 的存儲和網絡。一個 Pod 中的多個容器總是安排運作在相同的 node 上,并且同時啟動或者停止。

下圖展示了一個 Pod 中運作的兩個容器
  • Web Server: 網站伺服器,用來向使用者提供通路網頁
  • FilePuller: Job 服務,定期從另一個資料源下載下傳檔案到 Pod 内的存儲中
Kind Kubernetes 部署簡單應用 上篇

Pod 中多容器的常用應用例子還有

在 Pod 中運作應用容器之外,再運作一個 Filebeat 容器,用來把應用容器産生的日志輸出到 ElasticSearch。

下圖中,第一行backend pod 中就運作了兩個容器,READY 顯示2/2,代表這個pod中有兩個容器在運作

Kind Kubernetes 部署簡單應用 上篇

我們可以使用 kubectl describe 指令,檢視 backend pod中具體有哪兩個容器。

從下圖可以看到,其中一個是backend應用容器,還有一個是filebeat容器

kubectl describe pods/POD_NAME -n NAMESPACE_NAME可
      
Kind Kubernetes 部署簡單應用 上篇

另外,在 Pod 中我們還可以設定 init 容器,init 容器在其它容器(應用容器)運作之前啟動運作并終止,init 容器可以幫我們做一些初始化的工作。

2. Workloads Resources

我們通過 Workloads Resources 來管理 Pods,K8s 提供了一些定義好的 Workloads Resources 類型來滿足不同的業務要求。

  • Deployment and ReplicaSet:适合管理無狀态應用,Doployment 中任意 Pod 都是可随意替換的。
  • StatefulSet:有狀态的應用場景,我們可以運作一個或多個相關連的 Pods 并記錄其狀态。
  • DaemonSet:适合為 cluster node 提供服務的 Pod,比如管理叢集網絡或者插件。當在 K8s 叢集中新增 Node 時,由 Control Plane 根據 DaemonSet 中的定義安排在新的 Node 上運作 Pod
  • Job and CronJob:一次性任務的 Pod。

Deployment

我們後面實驗用的是 Deployment,是以我們再多介紹一下 Workloads Resources 中的 Deployment。

我們在 Deployment 中描述需要的狀态,然後 Deployment Controller 幫我們把 Pod 運作在指定狀态。

簡單點說就是,我們在 Deployment Yaml 檔案中定義自己的 Pod(容器)模闆、運作數量等,然後 Deployment Controller 幫我們維護這些 Pod。

這時如果 Pod 運作所在的 Node 當機了,Deployment Controller 會自動幫我們把 Pod 運作到其它可用的 Node 上。

Deployment 通過 selector(利用 labels)來選擇哪些 Pods 歸其管理。

下面就是一個 Deployment Yaml 檔案,後面我們會用 kubectl 指令運作這個 yaml 檔案,在 kind K8s 中部署。

apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx-deployment
  labels:
    app: nginx
spec:
  replicas: 3
  selector:
    matchLabels:
      app: nginx
  template:
    metadata:
      labels:
        app: nginx
    spec:
      containers:
      - name: nginx
        image: nginx:1.14.2
        ports:
        - containerPort: 80

      

說明:

  • .kind:定義這個 K8s 資源類型為 Deployment
  • .metadata.name:定義 Deployment 的名稱是“nginx-deployment”
  • .spec.replicas:指定運作三個同樣的 Pod
  • .spec.selector:定義哪些 Pod 由這個 Deployment 來管理,這裡選擇 Pod 标簽(labels)中帶有“app: nginx”的。
  • template:這裡就是 Pod 模闆
    • .metadata.labels:給 Pods 定義标簽“app: nginx”
    • .template.spec:定義容器鏡像的具體資訊,公共倉庫的 nginx 鏡像,開放端口 80

以後部署任何 K8s 應用,都會以這種 yaml 檔案的形式來做部署。

當然我們也可以使用 Helm 來做部署,但 Helm 最終也是生成上面這種 yaml 檔案來部署應用。

現在,我們觀察一下 Kind K8s 中 kube-system 空間内部署的 Deployment

Kind Kubernetes 部署簡單應用 上篇

檢視 Deployment 的詳細資訊

kubectl describe deployments/coredns -n kube-system

      
Kind Kubernetes 部署簡單應用 上篇

說明:這裡可以看到 selector,以及 Pod 模闆等資訊

3. Service

在用 Deployment 管理 Pod 時,Deployment 會幫助我們重新開機失敗的 Pod,維護 Pod 設定的狀态。

但是重新開機後的 Pod 會配置設定一個新的内部 IP 和 DNS,這就會造成一些問題。

比如,一個應用運作了兩組 Pod,一組做為前端,另一組做為後端。當後端的 Pod 重新開機并配置設定新 IP 之後,前端如何找到新的後端?(服務發現)

這就是 Service 提供的功能。

Service 用來把應用運作的 Pods 做為網絡服務暴露出來。

可以簡單了解為,Pods 沒有固定 IP,但 Service 有固定 IP,把 Pods 和 Service 關聯起來之後,我們就可以通過 Service 來找到需要的 Pods。

與 Deployment 一樣,Service 也用 yaml 檔案來定義,下面一個 Service 的例子

apiVersion: v1
kind: Service
metadata:
  name: my-service
spec:
  selector:
    app: nginx
  ports:
    - protocol: TCP
      port: 80
      targetPort: 80

      

說明:

  • .kind: k8s 資源類型為 Service
  • .metadata.name: 定義 Service 的名稱,與 Deployment 類似
  • .spec.selector:定義哪些 Pod 會關聯到這個 Service,這裡選擇 Pod 标簽中帶有“app: nginx”的,是以上面定義的 Deployment 中的 Pods 會關聯到這個 Service
  • .spec.ports:這部分定義 Service 對外暴露的端口
    • port: 這裡 Service 會對外暴露 80 端口
    • targetPort: Pods 對 Service 暴露 80 端口port 和 targetPort 可以不同,也可以同時暴露多個端口

我們觀察 Kind K8s 中 kube-system 空間内部署的 Service,目前這個 Service 的類型是 Clsuter IP,隻能從内部通路

Kind Kubernetes 部署簡單應用 上篇

4. Namespaces

K8s 支援在 cluster 中建立 virtual cluster,這些 virtual cluster 就叫做 namespaces。

當一個 K8s 叢集有很多使用者或項目使用時,我們可以通過建立 namespace 來區分使用者和資源。

在一個 Cluster 中,一個 K8s 對象的名稱是不能重複的,但在 namespace 中,隻要對象名稱不在目前 namespace 中重複即可。

檢視 cluster 中所有 Namespaces

kubectl get namespaces

      
Kind Kubernetes 部署簡單應用 上篇

5. DNS

這裡的 DNS 是特指 K8s 内部的 DNS。K8s 會自動為每個 Pod 和 Service 建立 DNS,我們可以通過 DNS 或者 IP 來通路 Pod 和 Service。

實戰步驟

1. 重建 K8s,暴露 80、443 端口

在上一篇文章中,我們介紹過用 kind 建立 K8s 時,是相當于在本地運作了一個容器,而K8s Cluster 就運作在這個容器中。

是以,如果我們想從外部通路 kind K8s 的話,就需要把這個容器的端口(K8s 的端口)暴露出來。

目前可以看到隻有 38325 這個端口可以從外部通路

Kind Kubernetes 部署簡單應用 上篇

為了下一步測試,我們重新建立一個新的 K8s cluster 并且把 80 和 443 端口暴露出來。

運作下列指令删除現在的 k8s cluster

kind delete cluster --name tsk8s

      
Kind Kubernetes 部署簡單應用 上篇

運作下列指令建立新的 k8s cluster

cat <<EOF | kind create cluster --name tsk8s --config=-
kind: Cluster
apiVersion: kind.x-k8s.io/v1alpha4
nodes:
- role: control-plane
  kubeadmConfigPatches:
  - |
    kind: InitConfiguration
    nodeRegistration:
      kubeletExtraArgs:
        node-labels: "ingress-ready=true"
  extraPortMappings:
  - containerPort: 80
    hostPort: 80
    protocol: TCP
  - containerPort: 443
    hostPort: 443
    protocol: TCP
  - containerPort: 30000
    hostPort: 30000
    protocol: TCP
EOF

      

說明:

  • extraPortMappings:把 K8s 容器(相當于 K8s 所在的伺服器)端口暴露出來,這裡暴露了 80、443、30000
  • node-labels:隻允許 Ingress controller 運作在有"ingress-ready=true"标簽的 node 上

運作結果

Kind Kubernetes 部署簡單應用 上篇

這時可以看到 80、443、30000 端口已經暴露出來了

Kind Kubernetes 部署簡單應用 上篇

注意:如果是在公司代理環境下,我們要在 K8s 容器中設定代理,才可以正常進行下面的測試,設定代理請參考上一篇文章《代理環境下在 WSL2 中用 Kind 建立 Kubernetes 叢集》”

2. 部署 Deployment、Service

部署 Deployment

建立檔案 my-dep.yaml,添加以下内容

apiVersion: apps/v1
kind: Deployment
metadata:
  name: httpd-dep
spec:
  replicas: 1  # number of replicas of frontEnd application
  selector:
    matchLabels:
      app: httpd-app
  template:
    metadata:
      labels: # Must match 'Service' and 'Deployment' labels
        app: httpd-app
    spec:
      containers:
      - name: httpd
        image: httpd # docker image of frontend application
        ports:
        - containerPort: 80

      

說明:

  • Deployment 的名稱為“httpd-dep”
  • 管理的 Pods 需要帶有“app: httpd-app”标簽
  • Pod 模闆中指定運作的鏡像為 Docker 公共倉庫中的 httpd

運作以下指令建立 Deployment

kubectl apply -f my-dep.yaml

      

建立 Deployment 結果

Kind Kubernetes 部署簡單應用 上篇

檢視建立的 Pod,-o wide 可以看到更多的資訊

kubectl get pods -o wide

      
Kind Kubernetes 部署簡單應用 上篇

說明:可以看到 Pod 被配置設定了一個 K8s 内部 IP,這個 IP 不能從 K8s 外部通路到,而且這個 IP 在 Pod 重建後會變化

部署 Service

建立檔案 my-svc.yaml,添加以下内容

kind: Service
apiVersion: v1
metadata:
  name: httpd-svc
spec:
  selector:
      app: httpd-app
  ports:
  - port: 80

      

運作以下指令建立 Service

kubectl apply -f my-svc.yaml

      

建立 Service 結果

Kind Kubernetes 部署簡單應用 上篇

檢視 Service 資訊

kubectl get svc/httpd-svc

      
Kind Kubernetes 部署簡單應用 上篇

說明:Service 的 IP 是不會變化的(除非重建 Service)

檢視 Service 詳細資訊

kubectl describe svc/httpd-svc

      
Kind Kubernetes 部署簡單應用 上篇

說明:

可以看到這裡 Service 關聯的 Endpoint 的 IP 和端口就是上面 Pod 的 IP 和端口。每次 Pod 重建後這裡的 Endpoint 就會重新整理為新的 IP。

目前這個 Service 隻有内部 IP 和端口,是以這個 Service 還隻能用在 K8s 内部暴露 Pods。

下面我們修改 Service 配置,使用 K8s 外部也可以通路到這個 Service

更改 Serivce(nodePort)

修改 my-svc.yaml,添加以下内容

kind: Service
apiVersion: v1
metadata:
  name: httpd-svc
spec:
  selector:
      app: httpd-app
  type: NodePort #1
  ports:
  - port: 80
    nodePort: 30000 #2

      

說明:

  • #1 Service type 預設為 ClusterIP,即隻有内部 IP。改為 NodePort 後,Service 會把 K8s 内部的端口映射到叢集所在的伺服器上
  • #2 指定 Service 映射到伺服器上的端口為 30000

再次運作 kubectl apply 指令

運作結果

Kind Kubernetes 部署簡單應用 上篇

再次檢視 Service 資訊,可以看到端口中多了一個 30000

Kind Kubernetes 部署簡單應用 上篇

30000 這個端口被映射到了 K8s 叢集所在的伺服器上(即 K8s 運作的容器),而我們在建立 kind K8s 時把容器的 30000 端口又映射到本地,是以現在我們可以在本地用浏覽器通路 30000 端口。

在本地可以通路到 30000 端口上的 httpd 應用

Kind Kubernetes 部署簡單應用 上篇

引申

除了用 NodePort 暴露服務,我們還可以用 ingress/ingress controller 實作相同的功能。我們将在下一篇文章中測試 ingress/ingress controller

後記

K8s 的内容多且雜,估計因為 K8s 是一個開源架構而非産品,是以官網上基本沒有實操的例子,都是大段的概念介紹。

當年開始學習 K8s 時,就是感覺無從下手。後來搭建起來 K8s 環境後,邊學邊試才好了很多。

這篇及下一篇文章挑了一些最常用的 K8s 對象來講解,然後加上實際操作,應該能讓 K8s 初學者找到點門道兒。

喜歡請點贊,禁止轉載,轉發請标明出處

關注 B 站 UP 主“我是手拉面” 觀看更多視訊

微信公衆号“全是 AWS 幹貨”

繼續閱讀