Helm3 使用Harbor仓库存储Chart

简介

本文讲述的是使用Helm3Harbor v2.3.1的经验,使用Harbor作为Chart仓库服务。来实现更高效、便捷的DevOps运维管理,学习如何撰写自己的Chart应用。文中如有错误的地方,还望各位大佬在评论区指正。

开发自己的Chart:Java应用为例

先创建模板

1
helm create demo

修改默认Chart.yaml

1
2
3
4
5
6
7
8
# cat > Chart.yaml <<EOF
apiVersion: v2
appVersion: 0.1.0
description: wangxiansen demo
name: demo
type: application
version: 1.16.0
EOF

删除默认配置文件

1
2
3
4
[root@k8s-master demo]# cd templates/
[root@k8s-master templates]# ls
deployment.yaml _helpers.tpl ingress.yaml NOTES.txt serviceaccount.yaml service.yaml tests
[root@k8s-master templates]# rm -rf tests serviceaccount.yaml

创建自定义ingress

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
cat > ingress.yaml <<EOF
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
labels:
release: dubbo-web
name: dubbo-dubbo-web
namespace: app
spec:
rules:
- host: demo.boysec.cn
http:
paths:
- backend:
service:
name: dubbo-dubbo-web
port:
number: 8080
path: /
pathType: Prefix
EOF

现在开始制作

编辑公共模板

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
cat > templates/_helpers.tpl <<EOF
{{/*
资源名称
Chart是表示Chart.yaml文件中内容
*/}}
{{- define "demo.fullname" -}}
{{- .Chart.Name -}}-{{ .Release.Name }}
{{- end -}}

{{/*
资源标签
*/}}
{{- define "demo.labels" -}}
app: {{ template "demo.fullname" . }}
chart: "{{ .Chart.Name }}-{{ .Chart.Version }}"
release: "{{ .Release.Name }}"
{{- end -}}

{{/*
pod标签
*/}}
{{- define "demo.selectorLabels" -}}
app: {{ template "demo.fullname" . }}
release: "{{ .Release.Name }}"
{{- end -}}
EOF

修改默认的values.yaml

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
cat > values.yaml <<EOF
image:
pullPolicy: IfNotPresent
repository: wangxiansen/java-demo
tag: latest
imagePullSecrets: []
ingress:
annotations:
kubernetes.io/ingress.class: traefik
enabled: true
host: example.boysec.cn
tls:
secretName: example-boysec-cn-tls
nodeSelector: {}
replicaCount: 3
resources:
limits:
cpu: 1000m
memory: 1Gi
requests:
cpu: 100m
memory: 128Mi
service:
port: 80
type: ClusterIP
tolerations: []
EOF

修改deployment.yaml

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
demo]# cat > templates/deployment.yaml <<EOF
apiVersion: apps/v1
kind: Deployment
metadata:
name: {{ include "demo.fullname" . }}
labels:
{{- include "demo.labels" . | nindent 4 }}
spec:
replicas: {{ .Values.replicaCount }}
selector:
matchLabels:
{{- include "demo.selectorLabels" . | nindent 6 }}
template:
metadata:
labels:
{{- include "demo.selectorLabels" . | nindent 8 }}
spec:
{{- with .Values.imagePullSecrets }}
imagePullSecrets:
{{- toYaml . | nindent 8 }}
{{- end }}
containers:
- name: {{ .Chart.Name }}
image: "{{ .Values.image.repository }}:{{ .Values.image.tag }}"
imagePullPolicy: {{ .Values.image.pullPolicy }}
ports:
- name: http
containerPort: 8080
protocol: TCP
livenessProbe:
httpGet:
path: /
port: http
readinessProbe:
httpGet:
path: /
port: http
resources:
{{- toYaml .Values.resources | nindent 12 }}
{{- with .Values.nodeSelector }}
nodeSelector:
{{- toYaml . | nindent 8 }}
{{- end }}
{{- with .Values.tolerations }}
tolerations:
{{- toYaml . | nindent 8 }}
{{- end }}
EOF

修改service

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
demo]# cat > templates/service.yaml <<EOF
apiVersion: v1
kind: Service
metadata:
name: {{ include "demo.fullname" . }}
labels:
{{- include "demo.labels" . | nindent 4 }}
spec:
type: {{ .Values.service.type }}
ports:
- port: {{ .Values.service.port }}
targetPort: http
protocol: TCP
name: http
selector:
{{- include "demo.selectorLabels" . | nindent 4 }}
EOF

修改ingress

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
demo]# cat > templates/ingress.yaml <<EOF
{{- if .Values.ingress.enabled -}}
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: {{ include "demo.fullname" . }}
labels:
{{- include "demo.labels" . | nindent 4 }}
{{- with .Values.ingress.annotations }}
annotations:
{{- toYaml . | nindent 4 }}
{{- end }}
spec:
{{- if .Values.ingress.tls }}
tls:
- hosts:
- {{ .Values.ingress.host }}
secretName: {{ .Values.ingress.tls.secretName }}
{{- end }}
rules:
- host: {{ .Values.ingress.host }}
http:
paths:
- pathType: Prefix
path: /
backend:
service:
name: {{ include "demo.fullname" . }}
port:
number: {{ .Values.service.port }}
{{- end }}
EOF

再加个说明

1
2
3
4
5
6
7
8
9
10
11
demo]# cat > templates/NOTES.txt <<EOF
访问地址:
{{- if .Values.ingress.enabled }}
http{{ if $.Values.ingress.tls }}s{{ end }}://{{ .Values.ingress.host }}
{{- end }}
{{- if contains "NodePort" .Values.service.type }}
export NODE_PORT=$(kubectl get --namespace {{ .Release.Namespace }} -o jsonpath="{.spec.ports[0].nodePort}" services {{ include "demo.fullname" . }})
export NODE_IP=$(kubectl get nodes --namespace {{ .Release.Namespace }} -o jsonpath="{.items[0].status.addresses[0].address}")
echo http://$NODE_IP:$NODE_PORT
{{- end }}
EOF

查看项目编写的有没有问题

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
demo]# helm install java-demo --dry-run ../demo/
NAME: java-demo
LAST DEPLOYED: Tue May 5 12:43:34 2022
NAMESPACE: default
STATUS: pending-install
REVISION: 1
TEST SUITE: None
HOOKS:
MANIFEST:
---
# Source: demo/templates/service.yaml
apiVersion: v1
kind: Service
metadata:
name: demo-java-demo
labels:
app: demo-java-demo
chart: "demo-0.1.0"
release: "java-demo"
spec:
type: ClusterIP
ports:
- port: 80
targetPort: http
protocol: TCP
name: http
selector:
app: demo-java-demo
release: "java-demo"
---
# Source: demo/templates/deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: demo-java-demo
labels:
app: demo-java-demo
chart: "demo-0.1.0"
release: "java-demo"
spec:
replicas: 3
selector:
matchLabels:
app: demo-java-demo
release: "java-demo"
template:
metadata:
labels:
app: demo-java-demo
release: "java-demo"
spec:
containers:
- name: demo
image: "lizhenliang/java-demo:latest"
imagePullPolicy: IfNotPresent
ports:
- name: http
containerPort: 8080
protocol: TCP
livenessProbe:
httpGet:
path: /
port: http
readinessProbe:
httpGet:
path: /
port: http
resources:
limits:
cpu: 1000m
memory: 1Gi
requests:
cpu: 100m
memory: 128Mi
---
# Source: demo/templates/ingress.yaml
apiVersion: networking.k8s.io/v1beta1
kind: Ingress
metadata:
name: demo-java-demo
labels:
app: demo-java-demo
chart: "demo-0.1.0"
release: "java-demo"
annotations:
kubernetes.io/ingress.class: traefik
spec:
tls:
- hosts:
- example.boysec.cn
secretName: example-boysec-cn-tls
rules:
- host: example.boysec.cn
http:
paths:
- path: /
backend:
serviceName: demo-java-demo
servicePort: 80

NOTES:
访问地址:
https://example.boysec.cn

运行项目,默认是没有暴露service 应用的

1
2
3
4
5
6
7
8
9
10
helm install java-demo  ../demo/
NAME: java-demo
LAST DEPLOYED: Tue May 5 13:03:02 2022
NAMESPACE: default
STATUS: deployed
REVISION: 1
TEST SUITE: None
NOTES:
访问地址:
https://example.boysec.cn

更新,暴露该应用

1
demo]# helm upgrade java-demo --set service.type=NodePort   ../demo/

修改副本数

1
helm upgrade java-demo --set replicaCount=2 ../demo/

用模板创建nginx应用

1
2
3
4
5
6
7
8
9
10
demo]# helm install  nginx --set image.repository=nginx,service.targetport=80 ../demo/ -n test
NAME: nginx
LAST DEPLOYED: Tue May 5 13:28:46 2022
NAMESPACE: test
STATUS: deployed
REVISION: 1
TEST SUITE: None
NOTES:
访问地址:
https://example.boysec.cn

使用Harbor作为Chart仓库

1、启用Harbor的Chart仓库服务

1
# ./install.sh --with-chartmuseum

启用后,默认创建的项目就带有helm charts功能了。

2、安装push插件

https://github.com/chartmuseum/helm-push

1
helm plugin install https://github.com/chartmuseum/helm-push

3、添加repo

1
helm repo add  --username admin --password Harbor12345 myrepo http://harbor.od.com/chartrepo/library

4、推送与安装Chart

1
2
3
4
# helm package demo/
# helm cm-push demo-0.1.0.tgz --username=admin --password=Harbor12345 http://harbor.od.com/chartrepo/library
# helm install web --version 0.1.0 myrepo/demo
# helm list