認識Helm
-
為什么有helm?
-
Helm是什么?
kubernetes的包管理器,“可以將Helm看作Linux系統下的apt-get/yum”。
-
對於應用發布者而言,可以通過Helm打包應用,管理應用依賴關系,管理應用版本並發布應用到軟件倉庫。
-
對於使用者而言,使用Helm后不用需要了解Kubernetes的Yaml語法並編寫應用部署文件,可以通過Helm下載並在kubernetes上安裝需要的應用。
除此以外,Helm還提供了kubernetes上的軟件部署,刪除,升級,回滾應用的強大功能。
-
-
Helm的版本
-
helm2
C/S架構,helm通過Tiller與k8s交互 -
helm3
-
從安全性和易用性方面考慮,移除了Tiller服務端,helm3直接使用kubeconfig文件鑒權訪問APIServer服務器
-
由二路合並升級成為三路合並補丁策略( 舊的配置,線上狀態,新的配置 )
helm install very_important_app ./very_important_app
這個應用的副本數量設置為 3 。現在,如果有人不小心執行了
kubectl edit
或:kubectl scale -replicas=0 deployment/very_important_app
然后,團隊中的某個人發現 very_important_app 莫名其妙宕機了,嘗試執行命令:
helm rollback very_important_app
在 Helm 2 中,這個操作將比較舊的配置與新的配置,然后生成一個更新補丁。由於,誤操作的人僅修改了應用的線上狀態(舊的配置並未更新)。Helm 在回滾時,什么事情也不會做。因為舊的配置與新的配置沒有差別(都是 3 個副本)。然后,Helm 不執行回滾,副本數繼續保持為 0
-
移除了helm serve本地repo倉庫
-
創建應用時必須指定名字(或者--generate-name隨機生成)
-
-
-
Helm的重要概念
- chart,應用的信息集合,包括各種對象的配置模板、參數定義、依賴關系、文檔說明等
- Repoistory,chart倉庫,存儲chart的地方,並且提供了一個該 Repository 的 Chart 包的清單文件以供查詢。Helm 可以同時管理多個不同的 Repository。
- release, 當 chart 被安裝到 kubernetes 集群,就生成了一個 release , 是 chart 的運行實例,代表了一個正在運行的應用
helm 是包管理工具,包就是指 chart,helm 能夠:
- 從零創建chart
- 與倉庫交互,拉取、保存、更新 chart
- 在kubernetes集群中安裝、卸載 release
- 更新、回滾、測試 release
安裝與快速入門實踐
下載最新的穩定版本:https://get.helm.sh/helm-v3.2.4-linux-amd64.tar.gz
更多版本可以參考: https://github.com/helm/helm/releases
# k8s-master節點
$ wget https://get.helm.sh/helm-v3.2.4-linux-amd64.tar.gz
$ tar -zxf helm-v3.2.4-linux-amd64.tar.gz
$ cp linux-amd64/helm /usr/local/bin/
# 驗證安裝
$ helm version
version.BuildInfo{Version:"v3.2.4", GitCommit:"0ad800ef43d3b826f31a5ad8dfbb4fe05d143688", GitTreeState:"clean", GoVersion:"go1.13.12"}
$ helm env
# 添加倉庫
$ helm repo add stable http://mirror.azure.cn/kubernetes/charts/
# 同步最新charts信息到本地
$ helm repo update
快速入門實踐:
示例一:使用helm安裝mysql應用
# helm 搜索chart包
$ helm search repo mysql
# 從倉庫安裝
$ helm install mysql stable/mysql
$ helm ls
$ kubectl get all
# 從chart倉庫中把chart包下載到本地
$ helm pull stable/mysql
$ tree mysql
示例二:新建nginx的chart並安裝
$ helm create nginx
# 從本地安裝
$ helm install nginx ./nginx
# 安裝到別的命名空間luffy
$ helm -n luffy install ./nginx
# 查看
$ helm ls
$ helm -n luffy ls
#
$ kubectl get all
$ kubectl -n luffy get all
Chart的模板語法及開發
nginx的chart實現分析
格式:
$ tree nginx/
nginx/
├── charts # 存放子chart
├── Chart.yaml # 該chart的全局定義信息
├── templates # chart運行所需的資源清單模板,用於和values做渲染
│ ├── deployment.yaml
│ ├── _helpers.tpl # 定義全局的命名模板,方便在其他模板中引入使用
│ ├── hpa.yaml
│ ├── ingress.yaml
│ ├── NOTES.txt # helm安裝完成后終端的提示信息
│ ├── serviceaccount.yaml
│ ├── service.yaml
│ └── tests
│ └── test-connection.yaml
└── values.yaml # 模板使用的默認值信息
很明顯,資源清單都在templates中,數據來源於values.yaml,安裝的過程就是將模板與數據融合成k8s可識別的資源清單,然后部署到k8s環境中。
分析模板文件的實現:
-
引用命名模板並傳遞作用域
{{ include "nginx.fullname" . }}
include從_helpers.tpl中引用命名模板,並傳遞頂級作用域.
-
內置對象
.Values .Release.Name
Release
:該對象描述了 release 本身的相關信息,它內部有幾個對象:Release.Name
:release 名稱Release.Namespace
:release 安裝到的命名空間Release.IsUpgrade
:如果當前操作是升級或回滾,則該值為 trueRelease.IsInstall
:如果當前操作是安裝,則將其設置為 trueRelease.Revision
:release 的 revision 版本號,在安裝的時候,值為1,每次升級或回滾都會增加Reelase.Service
:渲染當前模板的服務,在 Helm 上,實際上該值始終為 Helm
Values
:從values.yaml
文件和用戶提供的 values 文件傳遞到模板的 Values 值Chart
:獲取Chart.yaml
文件的內容,該文件中的任何數據都可以訪問,例如{{ .Chart.Name }}-{{ .Chart.Version}}
可以渲染成mychart-0.1.0
-
模板定義
{{- define "nginx.fullname" -}} {{- if .Values.fullnameOverride }} {{- .Values.fullnameOverride | trunc 63 | trimSuffix "-" }} {{- else }} {{- $name := default .Chart.Name .Values.nameOverride }} {{- if contains $name .Release.Name }} {{- .Release.Name | trunc 63 | trimSuffix "-" }} {{- else }} {{- printf "%s-%s" .Release.Name $name | trunc 63 | trimSuffix "-" }} {{- end }} {{- end }} {{- end }}
-
{{- 去掉左邊的空格及換行,-}} 去掉右側的空格及換行
-
示例
apiVersion: v1 kind: ConfigMap metadata: name: {{ .Release.Name }}-configmap data: myvalue: "Hello World" drink: {{ .Values.favorite.drink | default "tea" | quote }} food: {{ .Values.favorite.food | upper | quote }} {{ if eq .Values.favorite.drink "coffee" }} mug: true {{ end }}
渲染完后是:
apiVersion: v1 kind: ConfigMap metadata: name: mychart-1575971172-configmap data: myvalue: "Hello World" drink: "coffee" food: "PIZZA" mug: true
-
-
管道及方法
-
trunc表示字符串截取,63作為參數傳遞給trunc方法,trimSuffix表示去掉
-
后綴{{- .Values.fullnameOverride | trunc 63 | trimSuffix "-" }}
-
nindent表示前面的空格數
selector: matchLabels: {{- include "nginx.selectorLabels" . | nindent 6 }}
-
lower表示將內容小寫,quote表示用雙引號引起來
value: {{ include "mytpl" . | lower | quote }}
-
-
條件判斷語句每個if對應一個end
{{- if .Values.fullnameOverride }} ... {{- else }} ... {{- end }}
通常用來根據values.yaml中定義的開關來控制模板中的顯示:
{{- if not .Values.autoscaling.enabled }} replicas: {{ .Values.replicaCount }} {{- end }}
-
定義變量,模板中可以通過變量名字去引用
{{- $name := default .Chart.Name .Values.nameOverride }}
-
遍歷values的數據
{{- with .Values.nodeSelector }} nodeSelector: {{- toYaml . | nindent 8 }} {{- end }}
toYaml處理值中的轉義及特殊字符, "kubernetes.io/role"=master , name="value1,value2" 類似的情況
-
default設置默認值
image: "{{ .Values.image.repository }}:{{ .Values.image.tag | default .Chart.AppVersion }}"
hpa.yaml
{{- if .Values.autoscaling.enabled }}
apiVersion: autoscaling/v2beta1
kind: HorizontalPodAutoscaler
metadata:
name: {{ include "nginx.fullname" . }}
labels:
{{- include "nginx.labels" . | nindent 4 }}
spec:
scaleTargetRef:
apiVersion: apps/v1
kind: Deployment
name: {{ include "nginx.fullname" . }}
minReplicas: {{ .Values.autoscaling.minReplicas }}
maxReplicas: {{ .Values.autoscaling.maxReplicas }}
metrics:
{{- if .Values.autoscaling.targetCPUUtilizationPercentage }}
- type: Resource
resource:
name: cpu
targetAverageUtilization: {{ .Values.autoscaling.targetCPUUtilizationPercentage }}
{{- end }}
{{- if .Values.autoscaling.targetMemoryUtilizationPercentage }}
- type: Resource
resource:
name: memory
targetAverageUtilization: {{ .Values.autoscaling.targetMemoryUtilizationPercentage }}
{{- end }}
{{- end }}
創建應用的時候賦值
- set的方式
# 改變副本數和resource值
$ helm install nginx-2 ./nginx --set replicaCount=2 --set resources.limits.cpu=200m --set resources.limits.memory=256Mi
-
value文件的方式
$ cat nginx-values.yaml resources: limits: cpu: 100m memory: 128Mi requests: cpu: 100m memory: 128Mi autoscaling: enabled: true minReplicas: 1 maxReplicas: 3 targetCPUUtilizationPercentage: 80 ingress: enabled: true hosts: - host: chart-example.luffy.com paths: - / $ helm install -f nginx-values.yaml nginx-3 ./nginx
更多語法參考:
https://helm.sh/docs/topics/charts/
部署mysql失敗的問題
使用Helm部署Harbor鏡像及chart倉庫
harbor踩坑部署
架構 https://github.com/goharbor/harbor/wiki/Architecture-Overview-of-Harbor
- Core,核心組件
- API Server,接收處理用戶請求
- Config Manager :所有系統的配置,比如認證、郵件、證書配置等
- Project Manager:項目管理
- Quota Manager :配額管理
- Chart Controller:chart管理
- Replication Controller :鏡像副本控制器,可以與不同類型的倉庫實現鏡像同步
- Distribution (docker registry)
- Docker Hub
- ...
- Scan Manager :掃描管理,引入第三方組件,進行鏡像安全掃描
- Registry Driver :鏡像倉庫驅動,目前使用docker registry
- Job Service,執行異步任務,如同步鏡像信息
- Log Collector,統一日志收集器,收集各模塊日志
- GC Controller
- Chart Museum,chart倉庫服務,第三方
- Docker Registry,鏡像倉庫服務
- kv-storage,redis緩存服務,job service使用,存儲job metadata
- local/remote storage,存儲服務,比較鏡像存儲
- SQL Database,postgresl,存儲用戶、項目等元數據
通常用作企業級鏡像倉庫服務,實際功能強大很多。
組件眾多,因此使用helm部署
# 添加harbor chart倉庫
$ helm repo add harbor https://helm.goharbor.io
# 搜索harbor的chart
$ helm search repo harbor
# 不知道如何部署,因此拉到本地
$ helm pull harbor/harbor --version 1.4.1
創建pvc
$ kubectl create namespace harbor
$ cat harbor-pvc.yaml
kind: PersistentVolumeClaim
apiVersion: v1
metadata:
name: harbor-pvc
namespace: harbor
spec:
accessModes:
- ReadWriteOnce
storageClassName: dynamic-cephfs
resources:
requests:
storage: 20Gi
修改harbor配置:
- 開啟ingress訪問
- externalURL,web訪問入口,和ingress的域名相同
- 持久化,使用PVC對接的cephfs
- harborAdminPassword: "Harbor12345",管理員默認賬戶 admin/Harbor12345
- 開啟chartmuseum
- clair和trivy漏洞掃描組件,暫不啟用
helm創建:
# 使用本地chart安裝
$ helm install harbor ./harbor -n harbor
踩坑一:redis持久化數據目錄權限導致無法登錄
redis數據目錄,/var/lib/redis,需要設置redis的用戶及用戶組權限
initContainers:
- name: "change-permission-of-directory"
image: {{ .Values.database.internal.initContainerImage.repository }}:{{ .Values.database.internal.initContainerImage.tag }}
imagePullPolicy: {{ .Values.imagePullPolicy }}
command: ["/bin/sh"]
args: ["-c", "chown -R 999:999 /var/lib/redis"]
volumeMounts:
- name: data
mountPath: /var/lib/redis
subPath: {{ $redis.subPath }}
踩坑二:registry組件的鏡像存儲目錄權限導致鏡像推送失敗
registry的鏡像存儲目錄,需要設置registry用戶的用戶及用戶組,不然鏡像推送失敗
initContainers:
- name: "change-permission-of-directory"
image: {{ .Values.database.internal.initContainerImage.repository }}:{{ .Values.database.internal.initContainerImage.tag }}
imagePullPolicy: {{ .Values.imagePullPolicy }}
command: ["/bin/sh"]
args: ["-c", "chown -R 10000:10000 {{ .Values.persistence.imageChartStorage.filesystem.rootdirectory }}"]
volumeMounts:
- name: registry-data
mountPath: {{ .Values.persistence.imageChartStorage.filesystem.rootdirectory }}
subPath: {{ .Values.persistence.persistentVolumeClaim.registry.subPath }}
踩坑三:chartmuseum存儲目錄權限,導致chart推送失敗
initContainers:
- name: "change-permission-of-directory"
image: {{ .Values.database.internal.initContainerImage.repository }}:{{ .Values.database.internal.initContainerImage.tag }}
imagePullPolicy: {{ .Values.imagePullPolicy }}
command: ["/bin/sh"]
args: ["-c", "chown -R 10000:10000 /chart_storage"]
volumeMounts:
- name: chartmuseum-data
mountPath: /chart_storage
subPath: {{ .Values.persistence.persistentVolumeClaim.chartmuseum.subPath }}
更新內容后,執行更新release
$ helm upgrade harbor -n harbor ./
推送鏡像到Harbor倉庫
配置hosts及docker非安全倉庫:
$ cat /etc/hosts
...
192.168.136.10 k8s-master core.harbor.domain
...
$ cat /etc/docker/daemon.json
{
"insecure-registries": [
"192.168.136.10:5000",
"core.harbor.domain"
],
"registry-mirrors" : [
"https://8xpk5wnt.mirror.aliyuncs.com"
]
}
#
$ systemctl restart docker
# 使用賬戶密碼登錄admin/Harbor12345
$ docker login core.harbor.domain
$ docker tag nginx:alpine core.harbor.domain/library/nginx:alpine
$ docker push core.harbor.domain/library/nginx:alpine
推送chart到Harbor倉庫
helm3默認沒有安裝helm push插件,需要手動安裝。插件地址 https://github.com/chartmuseum/helm-push
安裝插件:
$ helm plugin install https://github.com/chartmuseum/helm-push
離線安裝:
$ helm plugin install ./helm-push
添加repo
$ helm repo add myharbor https://core.harbor.domain/chartrepo/library
# x509錯誤
# 添加證書信任,根證書為配置給ingress使用的證書
$ kubectl get secret harbor-harbor-ingress -n harbor -o jsonpath="{.data.ca\.crt}" | base64 -d >harbor.ca.crt
$ cp harbor.ca.crt /etc/pki/ca-trust/source/anchors
$ update-ca-trust enable; update-ca-trust extract
# 再次添加
$ helm repo add myharbor https://core.harbor.domain/chartrepo/library --ca-file=harbor.ca.crt
$ helm repo ls
推送chart到倉庫:
$ helm push harbor myharbor --ca-file=harbor.ca.crt -u admin -p Harbor12345
查看harbor倉庫的chart