iT邦幫忙

2023 iThome 鐵人賽

DAY 29
0
Cloud Native

【하나, 둘, ready, get set, go】系列 第 29

【하나, 둘, ready, get set, go】Day 29 - 改用 Helm 來部署到 Kubernetes 上吧

  • 分享至 

  • xImage
  •  

前情提要

昨天我們成功將服務部署上 Kubernetes,但是在部署過程中,需要手動逐一部署每個元件

有沒有可以透過一鍵部署,就可以快速部署服務的方法呢?答案是有的!

今天要介紹的是 Helm,從下圖官網的斗大標題可以得知,Helm 是一套專為 Kubernetes 而生的 Kubernetes Package Manager

Helm 官網介紹

▲ 圖取自 Helm 官網

透過將服務所需的 yaml 描述檔打包成 chart (也就是 Package),讓開發人員可以一鍵快速部署

下面我們就來實際操作看看吧

實際操作

安裝 Helm Client

Helm 提供了多達 10 種以上的安裝方式

  1. Binary Release
  2. Script
  3. Homebrew (macOS)
  4. Chocolatey (Windows)
  5. Scoop (Windows)
  6. Apt (Debian/Ubuntu)
  7. dnf/yum (fedora)
  8. Snap
  9. pkg (FreeBSD)
  10. Source (Linux, macOS)
  11. Development Builds
  12. Canary Builds

這邊我們選擇使用 Homebrew 來安裝

brew install helm

透過 Homebrew 安裝 Helm Client

Helm 常用指令

指令 用途 指令 用途
helm create 在本地建立 Helm chart helm dependency 管理 Helm chart 依賴
helm install 安裝 Helm chart,安裝後會產生一個 release 版本 helm lint 驗證 Helm chart 語法、格式是否有誤
helm list 列出所有的 release helm package 將本地的 Helm chart 進行打包
helm repo 列出、新增、更新、刪除 Chart Repository helm rollback 將當前 release 版本回滾到先前版本
helm pull 從遠端拉取 Helm chart 到本地 helm search 搜尋 Helm chart
helm uninstall 刪除 release 版本 helm upgrade 更新 release 版本

建立 Helm chart

開啟 Terminal 並輸入以下指令

helm create <CHART_NAME>

# Example
helm create it15th

建立 Helm chart

建立好 Helm chart 後,就可以看到像下面一樣的 Chart 資料夾結構了

Helm chart 結構

下面就來說明每個檔案的用途

| it15th
-- 
  |
  -- charts // 用來存放依賴的 Sub Charts
  | 
  -- templates // 用來存放每個元件的 yaml 檔
    |
    -- 每個元件的 yaml...
  | 
  -- .helmignore // 用來定義 helm package 時,不會被打包進 Chart 內的東西
  | 
  -- Chart.yaml // 記載這個 Helm chart 的相關資訊
  | 
  -- values.yaml // 用來定義 templates 底下的各 yaml 檔的參數

Helm Official Documentation
https://helm.sh/docs/chart_template_guide/getting_started/

接下來我們可以先將昨天撰寫的各元件的 yaml 檔放到 templates 資料夾內

https://ithelp.ithome.com.tw/upload/images/20230917/20140363Fk5fEE08O6.png

接著就可以到 values.yaml 內開始定義參數

values.yaml 定義參數

Pod

pod:
  metadata:
    labels:
      app: it15th-pod
  spec:
    containers:
      name: it15th-container
      image: leoho0722/it15th:k8s
      ports:
        containerPort: 8080
      args: ["./it15th"]
      resources:
        limits:
          cpu: 200m
          memory: 256Mi
        requests:
          cpu: 100m
          memory: 128Mi

Deployment

deployment:
  metadata:
    name: it15th-deployment
  spec:
    replicas: 2
    strategy:
      type: RollingUpdate
      rollingUpdate:
        maxSurge: 2
        maxUnavailable: 2
    minReadySeconds: 60
    revisionHistoryLimit: 10

Service

service:
  metadata:
    name: it15th-service
  spec:
    type: NodePort
    ports:
      protocol: TCP
      port: 8080
      targetPort: 8080
      nodePort: 32000
    selector:
      app: it15th-pod

PersistentVolume

pv:
  metadata:
    name: it15th-pv
  spec:
    capacity:
      storage: 1Gi
    volumeMode: Filesystem
    accessModes:
      - ReadWriteOnce
    storageClassName: it15th-pv
    hostPath:
      path: /mnt/data
      type: DirectoryOrCreate

PersistentVolumeClaim

pvc:
  metadata:
    name: it15th-pvc
  spec:
    volumeMode: Filesystem
    accessModes:
      - ReadWriteOnce
    resources:
      requests:
        storage: 256Mi
    storageClassName: it15th-pv

用 values.yaml 來改寫每個元件的 yaml 檔

Deployment

# Kubernetes 中 Deployment 元件的版本
apiVersion: apps/v1

# 該元件的類型
kind: Deployment

# 該元件的元資料
metadata:
  # 這個 Deployment 的名稱
  name: {{ .Values.deployment.metadata.name }}

# 這個 Deployment 的 DeploymentSpec
spec:
  # 要建立的 Pod 數量
  # 當現有 Pod 數量小於這邊 replica 設定的數值時,就會自動產生對應數量的 Pod 來補齊
  replicas: {{ .Values.deployment.spec.replicas }}

  # 將更新 Pod 取代舊有 Pod 的政策/策略
  strategy:
    # 這邊的 type 可以設定為 RollingUpdate 或 Recreate
    # RollingUpdate 會逐一更新 Pod,不會將所有 Pod 都停止
    # Recreate 會將所有 Pod 都停止,再重新建立新的 Pod
    type: {{ .Values.deployment.spec.strategy.type }}

    # 這邊的 maxSurge 設定為 1,表示在更新 Pod 時,最多可以多出 1 個 Pod
    # 這邊的 maxUnavailable 設定為 0,表示在更新 Pod 時,最多可以少 0 個 Pod
    rollingUpdate:
      # 在 RollingUpdate 過程中,要多比 `replica` 設定的數量生幾個 Pod 出來
      # 好處是,可以降低在 RollingUpdate 過程中,舊 Pod 內容出現的機率
      maxSurge: {{ .Values.deployment.spec.strategy.rollingUpdate.maxSurge }}

      # 在 RollingUpdate 過程中,可以允許多少數量的 Pod 無法使用
      # 若 maxSurge 不為 0,maxUnavailable 也不得為 0
      maxUnavailable: {{ .Values.deployment.spec.strategy.rollingUpdate.maxUnavailable }}

  # 新建立出來的 Pod 如果沒有任何 Container Crash 的情形發生,
  # 應準備就緒的最小秒數,預設為 0 (即 Pod 準備就緒後就可視為可用)
  minReadySeconds: {{ .Values.deployment.spec.minReadySeconds }}

  # 要保留多少數量可以 RollBack 的舊有 ReplicaSet,預設為 10
  revisionHistoryLimit: {{ .Values.deployment.spec.revisionHistoryLimit }}

  # 要選取的 Pod
  selector:
    matchLabels:
      app: {{ .Values.pod.metadata.labels.app }}

  # 選到的 Pod 的 PodTemplateSpec
  template:
    # Pod 的元資料
    metadata:
      # Pod 的標籤
      labels:
        app: {{ .Values.pod.metadata.labels.app }}

    # 選取到的 Pod 的 PodSpec,用來定義 Pod 中的 Containers
    spec:
      # Pod 要執行的 Container
      containers:
        # 選取到的 Pod 內的 Container 名稱
        - name: {{ .Values.pod.spec.containers.name }}

          # 這個 Container 要用的 Image,預設從 DockerHub 取得
          image: {{ .Values.pod.spec.containers.image }}

          # 宣告這個 Container 要對外開放的 port 類型
          ports:
            # 宣告這個 Container 要對外開放的 port 號
            - containerPort: {{ .Values.pod.spec.containers.ports.containerPort }}

          # 宣告這個 Container 要執行的指令
          args: {{ .Values.pod.spec.containers.args }}

          # 宣告這個 Container 要用的資源
          resources:
            # 這個 Container 最多可以用到的資源
            limits:
              cpu: {{ .Values.pod.spec.containers.resources.limits.cpu }}
              memory: {{ .Values.pod.spec.containers.resources.limits.memory }}

            # 這個 Container 最少要用到的資源
            requests:
              cpu: {{ .Values.pod.spec.containers.resources.requests.cpu }}
              memory: {{ .Values.pod.spec.containers.resources.requests.memory }}

          # 宣告這個 Container 要用的 Volume
          volumeMounts:
            - name: {{ .Values.pv.metadata.name }}
              mountPath: {{ .Values.pv.spec.hostPath.path }}

      volumes:
        - name: {{ .Values.pv.metadata.name }}
          persistentVolumeClaim:
            claimName: {{ .Values.pvc.metadata.name }}

Service

# Kubernetes 中 Service 元件的版本號
apiVersion: v1

# 該元件的種類
kind: Service

# 該元件的元資料
metadata:
  # 這個 Service 的名稱
  name: {{ .Values.service.metadata.name }}

# 這個 Service 的 ServiceSpec
spec:
  # Service 要以哪種模式運作
  # Kubernetes 提供 ClusterIP、NodePort、ExternalName、LoadBalancer
  # 預設為 ClusterIP
  type: {{ .Values.service.spec.type }}

  # 要選取的 Pod
  selector:
    app: {{ .Values.pod.metadata.labels.app }}

  # 設定 Service 要連接的相關 port 號
  ports:
    - name: {{ .Values.pod.spec.containers.name}}

      # 決定要以哪種網路協議來進行連線,TCP、UDP、SCTP
      # 預設為 TCP
      protocol: {{ .Values.service.spec.ports.protocol }}

      # Service 要用哪個 port 號來連到 Pod
      # 通常 port 會跟 targetPort 設定為相同的 port 號
      port: {{ .Values.service.spec.ports.port }}

      # Pod 對外開放的 port 號
      # 沒設定 targetPort 的話,Kubernetes 預設會設為與 port 相同的 port 號
      targetPort: {{ .Values.service.spec.ports.targetPort }}

      # 指定外部連進 Service 的 port 號,範圍為 30000~32767
      # 沒設定 nodePort 的話,Kubernetes 會自動指派一個範圍內的 port 號作為 nodePort
      nodePort: {{ .Values.service.spec.ports.nodePort }}

PersistentVolume

# Kubernetes 中 PersistentVolume 元件的版本號
apiVersion: v1

# 該元件的種類
kind: PersistentVolume

# 該元件的元資料
metadata:
  # 這個 PersistentVolume 的名稱
  name: {{ .Values.pv.metadata.name }}

# 這個 PersistentVolume 的 PersistentVolumeSpec
spec:
  # 該 PersistentVolume 的容量大小
  capacity:
    # 該 PersistentVolume 的容量大小單位
    storage: {{ .Values.pv.spec.capacity.storage }}

  # 該 PersistentVolume 的卷模式
  volumeMode: {{ .Values.pv.spec.volumeMode }}

  # 該 PersistentVolume 的存取模式
  accessModes: {{ .Values.pv.spec.accessModes }}

  # 該 PersistentVolume 的儲存類型
  # 若不指定,則預設為 default 儲存類型
  storageClassName: {{ .Values.pv.spec.storageClassName }}

  # 該 PersistentVolume 位於主機上的儲存路徑
  # 僅供單節點的 Kubernetes Cluster 使用
  hostPath:
    # 該 PersistentVolume 的儲存路徑
    path: {{ .Values.pv.spec.hostPath.path }}

    # 該 PersistentVolume 的儲存路徑的類型
    type: {{ .Values.pv.spec.hostPath.type }}

PersistentVolumeClaim

# Kubernetes 中 PersistentVolumeClaim 元件的版本號
apiVersion: v1

# 該元件的種類
kind: PersistentVolumeClaim

# 該元件的元資料
metadata:
  # 這個 PersistentVolumeClaim 的名稱
  name: {{ .Values.pvc.metadata.name }}

# 這個 PersistentVolumeClaim 的 PersistentVolumeClaimSpec
spec:
  # 要求的儲存空間大小
  resources:
    requests:
      storage: {{ .Values.pvc.spec.resources.requests.storage }}

  # 要求的儲存空間的卷模式
  volumeMode: {{ .Values.pvc.spec.volumeMode }}

  # 要求的儲存空間的存取模式
  accessModes: {{ .Values.pvc.spec.accessModes }}

  # 要求的儲存空間的儲存類型
  storageClassName: {{ .Values.pvc.spec.storageClassName }}

打包 Helm chart

用 values.yaml 改寫完原先的元件後,接下來就要來打包成 Helm chart 啦

在打包前,記得先進行 values.yaml 的語法/格式驗證

# 記得先切到 Chart 的目錄底下...
helm lint .

看到「0 chart(s) failed」就表示驗證成功啦,可以開始來打包了

https://ithelp.ithome.com.tw/upload/images/20230917/20140363UGaSDOQX34.png

# 記得先切到 Chart 的目錄底下...
helm package .

https://ithelp.ithome.com.tw/upload/images/20230917/20140363z3fWQ0hlZj.png

可以看到打包好的 Helm chart 以 tgz 壓縮檔的形式呈現

https://ithelp.ithome.com.tw/upload/images/20230917/20140363hGs6JWW16y.png

透過 Helm 來部署到 Kubernetes 上

在 Terminal 輸入下面的 helm 指令

helm install it15th /Users/leoho/Desktop/it15th/kubernetes/it15th/it15th-1.0.0.tgz

如果覺得每次都要輸入這麼長的安裝指令,可以將 Helm chart 上傳到 Chart Repository,這樣就可以不用輸入這麼長了,這部分就交給大家自行實作了,官方文件連結在下方

Create Chart Repository - Helm Official Documentation
https://helm.sh/docs/topics/chart_repository/

像是下面這樣

helm repo add {CHART_REPOSITORY_NAME} {CHART_REPOSITORY_URL}
helm repo update
helm install it15th {CHART_REPOSITORY_NAME}/it15th

接著輸入 kubectl get all,就可以看到服務一樣正常執行

總結

今天我們透過 Helm 這套專為 Kubernetes 應用而生的 Package Manager 將服務部署上 Kubernetes 上

只需要透過一個指令就能快速將整個 Kubernetes 應用部署到 Kubernetes 叢集內

明天就是最後一天了,來點輕鬆的,分享一下過去開始接觸「雲」這個東西的心得

我們明天見~


上一篇
【하나, 둘, ready, get set, go】Day 28 - 將服務部署上 Kubernetes 上吧 feat. minikube
下一篇
【하나, 둘, ready, get set, go】Day 30 - 我終於完賽了~
系列文
【하나, 둘, ready, get set, go】30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言