Kubernetes(K8S)是一個可以幫助我們管理微服務(microservices)的系統,他可以自動化地部署及管理多台機器上的多個容器(Container)。簡單來說,他可以做到:
- 同時部署多個容器到多台機器上(Deployment)
- 服務的乘載量有變化時,可以對容器做自動擴展(Scaling)
- 管理多個容器的狀態,自動偵測並重啟故障的容器(Management)
系列文目錄
- Kubernetes 四元件
- 基本運作與安裝
- 如何建立一個 Pod
- Kubernetes 進階三元件
- Helm
- kubectl 額外補充 在系列文的第一篇文章中,我們了解了構成 Kubernetes 的四個重要元素:Pod、Node、Master、Cluster,並安裝好了我們要實際動手玩 Kubernetes 前需要的套件與工具。而在第二篇文章中,我們實際動手操作了 Kubernetes 中的 Pod、Service、Deployment、Ingress。
接下來在這篇文章中,我們會介紹一個建立 Kubernetes 應用變得輕鬆簡單的好幫手:Helm。並且一如往常地,我們一樣可以在這篇文章中動手實際操作它!
Helm
在如何建立一個 Pod 以及 Kubernetes 進階三元件我們介紹了多個 Kubernetes 的元件與他們所對應到的 yaml
設定檔。假設我們今天有一個複雜的服務,裡面同時包含了很多種設定檔時,如何同時做好版本控制、管理、更新這些設定檔就變得不太容易,且要快速部署這個含有多個設定檔的服務也變得困難。因此 Helm 就是一個用來解決上述問題的工具。
簡單來說,Helm 就是一個管理設定檔的工具。他會把 Kubernetes 一個服務中各種元件裡的 yaml
檔統一打包成一個叫做 chart
的集合,然後透過給參數的方式,去同時管理與設定這些 yaml
檔案。
使用一個現有 Helm Chart
接下來我們要來示範用一個現有的 Helm Chart 來嘗試部署一個 Wordpress 的服務。首先,我們的第一步當然就是要下載 Helm。MacOS 中我們可以直接使用 Homebrew
安裝,其他環境可以參考 Helm 的 Github。
brew install kubernetes-helm
下載完後,我們記得要 Helm 把 Cluster 配置初始化
helm init
接下來讓我們安裝 Wordpress 的 Chart,我們可以直接透過指令
helm install stable/wordpress
這個指令會讓我們直接到 Chart Repository 去載入 Chart 檔並將它部署到我們的 Kubernetes Cluster 上,我們現在可以透過指令檢查我們的 Cluster
kubectl get all
NAME READY STATUS RESTARTS
pod/peddling-hog-mariadb-0 1/1 Running 0
pod/peddling-hog-wordpress-7bf6d69c8b 1/1 Running 1
NAME TYPE CLUSTER-IP
service/peddling-hog-mariadb ClusterIP 10.109.96.113
service/peddling-hog-wordpress LoadBalancer 10.101.157.184
EXTERNAL-IP PORT(S)
<none> 3306/TCP
<pending> 80:30439/TCP,443:31824/TCP
NAME READY UP-TO-DATE AVAILABLE
deployment.apps/peddling-hog-wordpress 1/1 1 1
NAME DESIRED
replicaset.apps/peddling-hog-wordpress-7bf6d69c8b 1
NAME READY AGE
statefulset.apps/peddling-hog-mariadb 1/1 60s
可以看到我們透過 Chart 一次就安裝與部署了兩個 Pod、兩個 Service 以及其他各種元件。如果要一次把所有 Chart 所安裝的元件刪除,我們可以先透過 helm list
列出我們所有的 Chart。
NAME REVISION UPDATED STATUS CHART
peddling-hog 1 Fri Apr 26 16:08:30 2019 DEPLOYED wordpress
然後輸入 helm delete peddling-hog
就可以一次把所有元件刪除。
Chart 的運作方式
嘗試完從 Chart 部署元件後,我們可以進一步來暸解 Chart 是如何運作的。我們可以到 Wordpress chart 的 Github 上觀察這個 Chart 的檔案結構,或是透過指令來建立一個最簡單的 Chart
helm create helm-demo
接下來我們來看看 ./helm-demo
的資料夾
.
├── Chart.yaml
├── charts
├── templates
│ ├── deployment.yaml
│ ├── ingress.yaml
│ └── service.yaml
└── values.yaml
把這個 Chart 的檔案結構化簡後就如上所見。
Chart.yaml
- 定義了這個 Chart 的 Metadata,包括 Chart 的版本、名稱、敘述等
charts
- 在這個資料夾裡可以放其他的 Chart,這裡稱作 SubCharts
templates
- 定義這個 Chart 服務需要的 Kubernetes 元件。但我們並不會把各元件的參數寫死在裡面,而是會用參數的方式代入
values.yaml
- 定義這個 Chart 的所有參數,這些參數都會被代入在 templates 中的元件。例如我們會在這邊定義
nodePorts
給service.yaml
、定義replicaCount
給deployment.yaml
、定義hosts
給ingress.yaml
等等
從上面的檔案結構可以看到,我們透過編輯 values.yaml
,就可以對所有的 yaml
設定檔做到版本控制與管理。並透過 install / delete 的方式一鍵部署 / 刪除。
如何建立自己的 Chart
了解了 Chart 大致上是如何運作後,我們就可以來實際建立一個簡單的 Chart。我們的目標是要透過 deployment
、service
、ingress
來讓使用者在輸入 blue.demo.com
時可以得到一隻小鯨魚。而首先,我們一樣輸入指令
helm create helm-demo
之後我們就先借看一下在 ingress
章節有使用過的 yaml
檔們。
deployment.yaml
apiVersion: extensions/v1beta1
kind: Deployment
metadata:
name: blue-nginx
spec:
replicas: 2
template:
metadata:
labels:
app: blue-nginx
spec:
containers:
- name: nginx
image: hcwxd/blue-whale
ports:
- containerPort: 3000
service.yaml
apiVersion: v1
kind: Service
metadata:
name: blue-service
spec:
type: NodePort
selector:
app: blue-nginx
ports:
- protocol: TCP
port: 80
targetPort: 3000
ingress.yaml
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
name: web
spec:
rules:
- host: blue.demo.com
http:
paths:
- backend:
serviceName: blue-service
servicePort: 80
然後我們就可以嘗試來把上述 yaml
檔中可以作為參數的部分抽取出來,在這邊為了降低複雜度,我們只簡單挑幾個參數出來,然後我們就可以把這些參數寫到 values.yaml
中。
values.yaml
replicaCount: 2
image:
repository: hcwxd/blue-whale
service:
type: NodePort
port: 80
ingress:
enabled: true
hosts:
- host: blue.demo.com
paths: [/]
把參數提取出來後,我們就來依樣畫葫蘆地把 template
中其他三個 yaml
檔寫成可以接受參數的方式:
deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: {{ include "value-helm-demo.fullname" . }}
spec:
replicas: {{ .Values.replicaCount }}
selector:
matchLabels:
app: {{ include "value-helm-demo.fullname" . }}
template:
metadata:
labels:
app: {{ include "value-helm-demo.fullname" . }}
spec:
containers:
- name: {{ .Chart.Name }}
image: '{{ .Values.image.repository }}'
ports:
- containerPort: 3000
service.yaml
apiVersion: v1
kind: Service
metadata:
name: {{ include "value-helm-demo.fullname" . }}
spec:
type: {{ .Values.service.type }}
ports:
- port: {{ .Values.service.port }}
targetPort: 3000
protocol: TCP
selector:
app: {{ include "value-helm-demo.fullname" . }}
ingress.yaml
{{- if .Values.ingress.enabled -}}
{{- $fullName := include "value-helm-demo.fullname" . -}}
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
name: {{ $fullName }}
spec:
rules:
{{- range .Values.ingress.hosts }}
- host: {{ .host | quote }}
http:
paths:
{{- range .paths }}
- backend:
serviceName: {{ $fullName }}
servicePort: 80
{{- end }}
{{- end }}
{{- end }}
寫好後,我們就可以來一鍵部署我們的這三份檔案囉。我們可以直接在 /helm-demo
資料夾下輸入指令
helm install .
NAME: gilded-peacock
LAST DEPLOYED: Mon May 6 16:31:27 2019
NAMESPACE: default
STATUS: DEPLOYED
RESOURCES:
==> v1/Deployment
NAME READY UP-TO-DATE AVAILABLE AGE
gilded-peacock-helm-demo 0/2 2 0 0s
==> v1/Pod(related)
NAME READY STATUS RESTARTS
gilded-peacock-helm-demo-5fc5964759 0/1 ContainerCreating 0
gilded-peacock-helm-demo-5fc5964759 0/1 ContainerCreating 0
==> v1/Service
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S)
gilded-peacock-helm-demo NodePort 10.106.164.53 <none> 80:30333/TCP
==> v1beta1/Ingress
NAME HOSTS ADDRESS PORTS
gilded-peacock-helm-demo blue.demo.com 80 0s
NOTES:
1. Get the application URL by running these commands:
http://blue.demo.com/
部署成功後顯示的 NAME: gilded-peacock
就是這個 Chart 部署後的名稱囉(在 Helm 中稱部署出去的這個實體為 release
)。我們可以再透過指令
helm list
列出我們目前所有的 releases
。接下來我們可以用 kubectl get all
來看到我們目前的 kubernetes 狀況
NAME READY STATUS RESTARTS
pod/gilded-peacock-helm-demo-5fc5964759 1/1 Running 0
pod/gilded-peacock-helm-demo-5fc5964759 1/1 Running 0
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S)
service/gilded-peacock-helm-demo NodePort 10.106.164.53 <none> 80:30333/TCP
NAME READY UP-TO-DATE AVAILABLE
deployment.apps/gilded-peacock-helm-demo 2/2 2 2
NAME DESIRED CURRENT
replicaset.apps/gilded-peacock-helm-demo-5fc5964759 2 2
這邊就可以看到我們所指定的資源都有按照 chart 的配置建立起來囉,所以打開 blue.demo.com
就可以看到一隻我們透過 Helm 實際部署出的小鯨魚。
以上,我們就完成 Helm 的實際部署囉!
而其他常用的 Helm 指令還有:
helm delete --purge RELEASE_NAME
刪除一個 release(--purge
這個 flag 可以把該 RELEASE_NAME
釋放出來供之後重複使用)。
helm upgrade RELEASE_NAME CHART_PATH
如果有更新 Chart 的檔案時,可以透過 upgrade 去更新對應的 Release。
helm lint CHART_PATH
檢查你的 Chart 檔案有沒有錯誤的語法。
helm package CHART_PATH
打包並壓縮整個 Chart 資料夾的檔案。
kubectl 額外補充
簡寫
覺得每次下指令都要打 kubectl
很花時間的話,可以透過 alias 來節省時間,例如設定 alias kbs=kubectl
。
kubectl 中的各項資源的名稱其實也都有內建的簡寫,可以透過指令
kubectl api-resources
去看到各個資源的簡寫,例如 deployments 可以簡寫成 deploy
、services 簡寫成 svc
等。
auto-complete
覺得 kubectl 的指令沒有 auto-complete 很痛苦的話可以參考官網的教學。像是如果使用 zsh 的話,就可以透過指令
echo "if [ $commands[kubectl] ]; then source <(kubectl completion zsh); fi" >> ~/.zshrc
來啟用 kubectl 的 auto-complete
create vs apply
在之前提到透過 yaml
建立資源時,我們都用了 kubectl create -f
。但其實也可以使用 kubectl apply -f
達成建立與更新資源,雖然在單純建立的使用情景上沒有差別,但其它用法上的差別可見 kubectl apply vs kubectl create。
小結
呼!希望這三篇 Kubernetes 基礎教學能對你有幫助!再次溫故知新一下:
在系列文的第一篇文章中,我們了解了構成 Kubernetes 的四個重要元素:Pod、Node、Master、Cluster,並安裝好了我們要實際動手玩 Kubernetes 前需要的套件與工具。
而在第二篇文章中,我們實際動手操作了 Kubernetes 中的 Pod、Service、Deployment、Ingress。
在最後的這篇文章中,我們了解了讓 Kubernetes 部署變得好輕鬆好棒棒的工具 Helm,並實際透過 Helm 部署了一個 Helm。
在學會了上述的各個基礎後,如果想要實際在各個雲端服務上操作 Kubernetes 的話,歡迎接下來可以進一步去了解 Kops!
參考資料:
- Helm Official Document
- Kubernetes Official Document
- Kubernetes 30 天學習筆記 by zxcvbnius
- 五分鐘 Kubernetes 有感
- 十分鐘帶你理解 Kubernetes 核心概念
- Kubernetes 學習筆記
- [教學] 用 Drone, Kubernetes 跟 Helm,以及 RBAC 來建置你的 CI/CD 流程
嗨,我是程維,目前在美國 Google 擔任軟體工程師。如果你對入門機器學習、深度學習、人工智慧和大語言模型有興趣,我目前在準備一系列入門的文章。歡迎在這個網頁表單輸入你的電子信箱,我會在寫好的第一時間將文章寄送給你。