
नमस्कार, हेब्र!
लेखों की एक श्रृंखला में यह तीसरा भाग है, "लर्निंग टू डिप्लॉय माइक्रोसर्विस ", और आज हम हेल्म 3 के बारे में बात करेंगे। पिछले भाग में, हमने 2 माइक्रोसर्विसेस (बैकएंड और गेटवे) के एक प्रशिक्षण प्रोजेक्ट के लिए कुबेरनेट्स कॉन्फ़िगरेशन बनाया और यह सब Google कुबेरनेट इंजन में तैनात किया। इस लेख में, हम अपने सिस्टम के लिए एक हेलम चार्ट लिखेंगे, इसके लिए GitHub Pages के आधार पर एक रिपॉजिटरी बनाएंगे, और Helm का उपयोग करके GKE में एक प्रोजेक्ट को तैनात करेंगे।
:
Spring Boot, Docker
: Java 11, Spring Boot, Docker, image optimization
Kubernetes Google Kubernetes Engine
: Kubernetes, GKE, resource management, autoscaling, secrets
Helm 3
: Helm 3, chart deployment
Jenkins
: Jenkins configuration, plugins, separate configs repository
Helm — , , Kubernetes. Helm — yaml- , . Helm-. .
Helm Kubernetes , . values.yaml, Kubernetes-. , .
GitHub .
:
helm create <chart-name>
Helm. msvc-chart :
.
└── msvc-chart
├── charts
├── Chart.yaml
├── templates
│ ├── backend.yaml
│ ├── gateway.yaml
│ ├── _helpers.tpl
│ ├── NOTES.txt
│ ├── secrets.yaml
│ ├── service-account.yaml
│ ├── tests
│ │ └── interaction-test.yaml
│ └── urls-config.yaml
├── values.schema.json
└── values.yaml
charts/ — . , .
Chart.yaml — , .
*templates/*.yaml* — Kuberenetes.
templates/NOTES.txt — , .
*templates/tests/*.yaml* — Helm.
templates/_helpers.tpl — , . tpl.
values.yaml — .
values.schema.json — JSON- values.yaml.
values.yaml
— values.yaml. . .
backend:
deployment:
name:
replicas: 2
container:
name:
resources: {}
# limits:
# memory: 1024Mi
# cpu: 500m
# requests:
# memory: 512Mi
# cpu: 100m
service:
name:
port: 8080
image:
name: anshelen/microservices-backend
tag: latest
pullPolicy: IfNotPresent
hpa:
enabled: false
name:
minReplicas: 1
maxReplicas: 3
targetCPUUtilizationPercentage: 50
gateway:
deployment:
name:
replicas: 2
container:
name:
resources: {}
# limits:
# memory: 1024Mi
# cpu: 500m
# requests:
# memory: 512Mi
# cpu: 100m
service:
name:
port: 80
# Can be one of ClusterIP, NodePort or LoadBalancer
type: LoadBalancer
image:
name: anshelen/microservices-gateway
tag: latest
pullPolicy: IfNotPresent
hpa:
enabled: false
name:
minReplicas: 1
maxReplicas: 3
targetCPUUtilizationPercentage: 50
secrets:
secret: default-secret
serviceAccount:
# Specifies whether a service account should be created
create: true
# The name of the service account to use.
# If not set and create is true, a name is generated using the release and
# chart names
name:
, . , (№ gateway.service.type). , Kubernetes- (№ gateway.container.resources).
values.schema.json JSON-, . , , .
values.schema.json{
"$schema": "https://json-schema.org/draft-07/schema#",
"properties": {
"backend": {
"properties": {
"deployment": {
"properties": {
"name": {
"type": ["string", "null"]
},
"replicas": {
"minimum": 1,
"type": "integer"
}
},
"type": "object"
},
"container": {
"properties": {
"name": {
"type": ["string", "null"]
},
"resources": {
"properties": {
"limits": {
"properties": {
"memory": {
"type": ["string", "number"]
},
"cpu": {
"type": ["string", "number"]
}
},
"type": "object"
},
"requests": {
"properties": {
"memory": {
"type": ["string", "null"]
},
"cpu": {
"type": ["string", "null"]
}
},
"type": "object"
}
},
"type": "object"
}
},
"type": "object"
},
"service": {
"properties": {
"name": {
"type": ["string", "null"]
},
"port": {
"minimum": 1,
"type": "integer"
}
},
"type": "object"
},
"image": {
"properties": {
"name": {
"type": "string"
},
"tag": {
"type": "string"
},
"pullPolicy": {
"enum": ["IfNotPresent", "Always", "Never"]
}
},
"type": "object"
},
"hpa": {
"properties": {
"enabled": {
"type": "boolean"
},
"name": {
"type": ["string", "null"]
},
"minReplicas": {
"minimum": 1,
"type": "integer"
},
"maxReplicas": {
"minimum": 1,
"type": "integer"
},
"targetCPUUtilizationPercentage": {
"minimum": 1,
"maximum": 99,
"type": "integer"
}
},
"type": "object"
}
},
"type": "object"
},
"gateway": {
"properties": {
"deployment": {
"properties": {
"name": {
"type": ["string", "null"]
},
"replicas": {
"minimum": 1,
"type": "integer"
}
},
"type": "object"
},
"container": {
"properties": {
"name": {
"type": ["string", "null"]
},
"resources": {
"properties": {
"limits": {
"properties": {
"memory": {
"type": ["string", "number"]
},
"cpu": {
"type": ["string", "number"]
}
},
"type": "object"
},
"requests": {
"properties": {
"memory": {
"type": ["string", "null"]
},
"cpu": {
"type": ["string", "null"]
}
},
"type": "object"
}
},
"type": "object"
}
},
"type": "object"
},
"service": {
"properties": {
"name": {
"type": ["string", "null"]
},
"port": {
"minimum": 1,
"type": "integer"
},
"type": {
"enum": ["ClusterIP", "NodePort", "LoadBalancer"]
}
},
"type": "object"
},
"image": {
"properties": {
"name": {
"type": "string"
},
"tag": {
"type": "string"
},
"pullPolicy": {
"enum": ["IfNotPresent", "Always", "Never"]
}
},
"type": "object"
},
"hpa": {
"properties": {
"enabled": {
"type": "boolean"
},
"name": {
"type": ["string", "null"]
},
"minReplicas": {
"minimum": 1,
"type": "integer"
},
"maxReplicas": {
"minimum": 1,
"type": "integer"
},
"targetCPUUtilizationPercentage": {
"minimum": 1,
"maximum": 99,
"type": "integer"
}
},
"type": "object"
}
},
"type": "object"
},
"secrets": {
"properties": {
"secret": {
"type": ["number", "string"]
}
},
"type": "object"
},
"createAccount": {
"properties": {
"create": {
"type": "boolean"
},
"name": {
"type": ["string", "null"]
}
},
"type": "object"
}
},
"title": "Values",
"type": "object"
}
Helm , Kubernetes.
— . Helm , (Release
), (Values
) (Chart
). , secrets.secret {{ .Values.secrets.secret }}
.
, "" ("pipeline") — . , : {{ .Chart.AppVersion | quote }}
. .
, . define
:
{{- define "msvc-chart.someFragment" -}}
...
{{- end -}}
include
:
{{ include "msvc-chart.someFragment" . }}
{{-
{{
, . . , {{- include "msvc-chart.someFragment" . | nindent 4 }}
4 .
.
_helpers.tpl
Helm . Kubernetes , . , . , , . — , , . Release.Name
.
:
{{- define "msvc-chart.selectorLabels" -}}
app.kubernetes.io/name: {{ .Chart.Name }}
app.kubernetes.io/instance: {{ .Release.Name }}
{{- end -}}
.Chart.Name
('msvc-chart' ). , Helm.
:
{{- define "msvc-chart.chart" -}}
{{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" -}}
{{- end -}}
, , 63 ( Kubernetes) . Helm. Kubernetes- ( DNS ).
, -Kubernetes:
{{- define "msvc-chart.labels" -}}
helm.sh/chart: {{ include "msvc-chart.chart" . }}
{{ include "msvc-chart.selectorLabels" . }}
{{- if .Chart.AppVersion }}
app.kubernetes.io/version: {{ .Chart.AppVersion | quote }}
{{- end }}
app.kubernetes.io/managed-by: {{ .Release.Service }}
{{- end -}}
, 'msvc-project', :
helm.sh/chart: msvc-chart-1.0.0
app.kubernetes.io/name: msvc-chart
app.kubernetes.io/instance: msvc-project
app.kubernetes.io/version: 1.0.0
app.kubernetes.io/managed-by: Helm
Kubernetes
Kubernetes ServiceAccount. . , , . ServiceAccount . ServiceAccount , Jenkins .
:
- serviceAccount.create=true, serviceAccount.name. .
- serviceAccount.create=false, serviceAccount.name 'default', .
{{- define "msvc-chart.serviceAccountName" -}}
{{- if .Values.serviceAccount.create -}}
{{ default (printf "%s-%s" .Release.Name .Chart.Name | trunc 63 | trimSuffix "-") .Values.serviceAccount.name }}
{{- else -}}
{{ default "default" .Values.serviceAccount.name }}
{{- end -}}
{{- end -}}
if
default
, , null
.
Kubernetes , .
:
{{- define "msvc-chart.gateway.defaultName" -}}
{{- printf "gateway-%s" .Release.Name -}}
{{- end -}}
{{- define "msvc-chart.gateway.deployment.name" -}}
{{- default (include "msvc-chart.gateway.defaultName" .) .Values.gateway.deployment.name | trunc 63 | trimSuffix "-" -}}
{{- end -}}
, . , , Helm Kubernetes- . , . . Helm checksum/config, , . Helm , , .
:
{{- define "msvc-chart.propertiesHash" -}}
{{- $secrets := include (print $.Template.BasePath "/secrets.yaml") . | sha256sum -}}
{{- $urlConfig := include (print $.Template.BasePath "/urls-config.yaml") . | sha256sum -}}
{{ print $secrets $urlConfig | sha256sum }}
{{- end -}}
print
, $.Template.BasePath
(_helpers.tpl). include
, - $secrets
. ConfigMap, .
, include
'. ', '\$' Template. Helm '. ' (scope), '\$' — , . , . . .
Secret (secrets.yaml)
apiVersion: v1
kind: Secret
metadata:
name: {{ include "msvc-chart.secrets.defaultName" . }}
labels:
{{- include "msvc-chart.labels" . | nindent 4 }}
type: Opaque
stringData:
secret: {{ .Values.secrets.secret }}
ConfigMap (urls-config.yaml)
apiVersion: v1
kind: ConfigMap
metadata:
name: {{ include "msvc-chart.urlConfig.defaultName" . }}
labels:
{{- include "msvc-chart.labels" . | nindent 4 }}
data:
BACKEND_URL: "http://{{ include "msvc-chart.backend.service.name" . }}:{{ .Values.backend.service.port }}/"
ServiceAccount (service-account.yaml)
{{- if .Values.serviceAccount.create -}}
apiVersion: v1
kind: ServiceAccount
metadata:
name: {{ include "msvc-chart.serviceAccountName" . }}
labels:
{{- include "msvc-chart.labels" . | nindent 4 }}
---
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
name: "{{ include "msvc-chart.serviceAccountName" . }}-binding"
labels:
{{- include "msvc-chart.labels" . | nindent 4 }}
subjects:
- kind: ServiceAccount
name: {{ include "msvc-chart.serviceAccountName" . }}
namespace: {{ .Release.Namespace }}
roleRef:
kind: ClusterRole
name: admin
apiGroup: rbac.authorization.k8s.io
{{- end -}}
serviceAccount.create=true, .
Deployments (backend.yaml gateway.yaml)
gateway.yaml , , backend.yaml — . , HorizontalPodAutoscaler', . , gateway.container.resources.requests.cpu — . Kubernetes .
gateway.yaml:
apiVersion: apps/v1
kind: Deployment
metadata:
name: {{ include "msvc-chart.gateway.deployment.name" . }}
labels:
{{- include "msvc-chart.labels" . | nindent 4 }}
tier: gateway
spec:
replicas: {{ .Values.gateway.deployment.replicas }}
selector:
matchLabels:
{{- include "msvc-chart.selectorLabels" . | nindent 6 }}
tier: gateway
strategy:
rollingUpdate:
maxSurge: 25%
maxUnavailable: 25%
type: RollingUpdate
template:
metadata:
annotations:
checksum/config: {{ include "msvc-chart.propertiesHash" . }}
labels:
{{- include "msvc-chart.selectorLabels" . | nindent 8 }}
tier: gateway
spec:
serviceAccountName: {{ include "msvc-chart.serviceAccountName" . }}
containers:
- name: {{ include "msvc-chart.gateway.container.name" . }}
image: "{{ .Values.gateway.image.name }}:{{ .Values.gateway.image.tag }}"
imagePullPolicy: {{ .Values.gateway.image.pullPolicy }}
envFrom:
- configMapRef:
name: {{ include "msvc-chart.urlConfig.defaultName" . }}
env:
- name: SECRET
valueFrom:
secretKeyRef:
name: {{ include "msvc-chart.secrets.defaultName" . }}
key: secret
readinessProbe:
httpGet:
path: /actuator/health
port: 8080
initialDelaySeconds: 5
periodSeconds: 3
ports:
- containerPort: 8080
protocol: TCP
resources:
{{- toYaml .Values.gateway.container.resources | nindent 12 }}
---
apiVersion: v1
kind: Service
metadata:
name: {{ include "msvc-chart.gateway.service.name" . }}
labels:
{{- include "msvc-chart.labels" . | nindent 4 }}
tier: gateway
spec:
type: {{ .Values.gateway.service.type }}
ports:
- port: {{ .Values.gateway.service.port }}
protocol: TCP
targetPort: 8080
name: http
selector:
{{- include "msvc-chart.selectorLabels" . | nindent 4 }}
tier: gateway
---
{{- if .Values.gateway.hpa.enabled -}}
apiVersion: autoscaling/v1
kind: HorizontalPodAutoscaler
metadata:
name: {{ include "msvc-chart.gateway.hpa.name" . }}
labels:
{{- include "msvc-chart.labels" . | nindent 4 }}
tier: gateway
spec:
scaleTargetRef:
apiVersion: apps/v1
kind: Deployment
name: {{ include "msvc-chart.gateway.deployment.name" . }}
minReplicas: {{ .Values.gateway.hpa.minReplicas }}
maxReplicas: {{ .Values.gateway.hpa.maxReplicas }}
targetCPUUtilizationPercentage: {{ .Values.gateway.hpa.targetCPUUtilizationPercentage }}
{{- end -}}
"checksum/config", , ServiceAccount (spec.template.spec.serviceAccountName). toYaml backend.container.resources values.yaml .
.
backend.yamlapiVersion: apps/v1
kind: Deployment
metadata:
name: {{ include "msvc-chart.backend.deployment.name" . }}
labels:
{{- include "msvc-chart.labels" . | nindent 4 }}
tier: backend
spec:
replicas: {{ .Values.backend.deployment.replicas }}
selector:
matchLabels:
{{- include "msvc-chart.selectorLabels" . | nindent 6 }}
tier: backend
strategy:
rollingUpdate:
maxSurge: 25%
maxUnavailable: 25%
type: RollingUpdate
template:
metadata:
labels:
{{- include "msvc-chart.selectorLabels" . | nindent 8 }}
tier: backend
spec:
serviceAccountName: {{ include "msvc-chart.serviceAccountName" . }}
containers:
- name: {{ include "msvc-chart.backend.container.name" . }}
image: "{{ .Values.backend.image.name }}:{{ .Values.backend.image.tag }}"
imagePullPolicy: {{ .Values.backend.image.pullPolicy }}
ports:
- containerPort: 8080
protocol: TCP
readinessProbe:
httpGet:
path: /actuator/health
port: 8080
initialDelaySeconds: 5
periodSeconds: 3
resources:
{{- toYaml .Values.backend.container.resources | nindent 12 }}
---
apiVersion: v1
kind: Service
metadata:
name: {{ include "msvc-chart.backend.service.name" . }}
labels:
{{- include "msvc-chart.labels" . | nindent 4 }}
tier: backend
spec:
ports:
- port: {{ .Values.backend.service.port }}
protocol: TCP
targetPort: 8080
name: http
selector:
{{- include "msvc-chart.selectorLabels" . | nindent 4 }}
tier: backend
---
{{- if .Values.backend.hpa.enabled -}}
apiVersion: autoscaling/v1
kind: HorizontalPodAutoscaler
metadata:
name: {{ include "msvc-chart.backend.hpa.name" . }}
labels:
{{- include "msvc-chart.labels" . | nindent 4 }}
tier: backend
spec:
scaleTargetRef:
apiVersion: apps/v1
kind: Deployment
name: {{ include "msvc-chart.backend.deployment.name" . }}
minReplicas: {{ .Values.backend.hpa.minReplicas }}
maxReplicas: {{ .Values.backend.hpa.maxReplicas }}
targetCPUUtilizationPercentage: {{ .Values.backend.hpa.targetCPUUtilizationPercentage }}
{{- end -}}
NOTES.txt
NOTES.txt , , (helm status <name>
).
URL- . , , . , .
1. Get the application URL by running these commands:
{{- if contains "NodePort" .Values.gateway.service.type }}
export NODE_PORT=$(kubectl get --namespace {{ .Release.Namespace }} -o jsonpath="{.spec.ports[0].nodePort}" services {{ include "msvc-chart.gateway.service.name" . }})
export NODE_IP=$(kubectl get nodes --namespace {{ .Release.Namespace }} -o jsonpath="{.items[0].status.addresses[0].address}")
echo http://$NODE_IP:$NODE_PORT
{{- else if contains "LoadBalancer" .Values.gateway.service.type }}
NOTE: It may take a few minutes for the LoadBalancer IP to be available.
You can watch the status of by running 'kubectl get --namespace {{ .Release.Namespace }} svc -w {{ include "msvc-chart.gateway.service.name" . }}'
export SERVICE_IP=$(kubectl get svc --namespace {{ .Release.Namespace }} {{ include "msvc-chart.gateway.service.name" . }} -o jsonpath="{.status.loadBalancer.ingress[0].ip}")
echo http://$SERVICE_IP:{{ .Values.gateway.service.port }}
{{- else if contains "ClusterIP" .Values.gateway.service.type }}
export POD_NAME=$(kubectl get pods --namespace {{ .Release.Namespace }} -l "app.kubernetes.io/name= {{ .Chart.Name }},app.kubernetes.io/instance={{ .Release.Name }},tier=gateway" -o jsonpath="{.items[0].metadata.name}")
echo "Visit http://127.0.0.1:8080 to use your application"
kubectl --namespace {{ .Release.Namespace }} port-forward $POD_NAME 8080:8080
{{- end }}
2. Get service account token:
export TOKEN=$(kubectl get serviceaccount {{ include "msvc-chart.serviceAccountName" . }} -n {{ .Release.Namespace }} -o go-template --template='{{`{{range .secrets}}{{.name}}{{"\n"}}{{end}}`}}')
export TOKEN_DECODED=$(kubectl get secrets "$TOKEN" -n {{ .Release.Namespace }} -o go-template --template '{{`{{index .data "token"}}`}}' | base64 -d)
echo $TOKEN_DECODED
Chart.yaml
. — version appVersion. version — , . appVersion — . type 'application' 'library' — .
apiVersion: v2
name: msvc-chart
version: 1.0.0
description: Microservices project
type: application
sources:
- https://github.com/Anshelen/microservices-backend
- https://github.com/Anshelen/microservices-gateway
- https://github.com/Anshelen/microservices-deploy
maintainers:
- name: Anton Shelenkov
email: anshelen@yandex.ru
url: https://shelenkov.herokuapp.com
appVersion: 1.0.0
Helm . helm test <name>
(№ ). Kubernetes-, , http-. , .
, . Kubernetes- Job — , . , Job 3 ( backoffLimit). helm.sh/hook helm.sh/hook-delete-policy. Helm, , .
interaction-test.yaml:
apiVersion: batch/v1
kind: Job
metadata:
name: "{{ .Release.Name }}-interaction-test"
labels:
{{- include "msvc-chart.labels" . | nindent 4 }}
annotations:
"helm.sh/hook": test
"helm.sh/hook-delete-policy": hook-succeeded,hook-failed
spec:
template:
spec:
containers:
- name: test
image: busybox
command: ['wget']
args: ['{{ include "msvc-chart.gateway.service.name" . }}:{{ .Values.gateway.service.port }}/']
restartPolicy: Never
backoffLimit: 3
Helm
Helm : , , Helm, kubectl. Helm , . kubectl, Helm , .
, Kubernetes-:
helm install --dry-run --debug <name> <chart-folder>
, , , <name>
:
helm install <name> <chart-folder>
values.yaml, --set <key>=<value>
. . , yaml- -f <overriden-values.yaml>
. -n <namespace>
, .
:
helm upgrade <name> <chart-folder>
-f <file>
--set <key>=<value>
. Helm , . , --reuse-values
. , Helm , --set
--reuse-values
, - . :
helm install <name> <chart-folder>
helm upgrade <name> <chart-folder> --set key=value --reuse-values
, , - , , :
helm install <name> <chart-folder> --set _=null
helm list
— Helm' .
helm status <name>
— .
helm history <name>
— . . .
helm get values <name>
— . --revision n
, n- .
helm show values <chart-folder>
— . values.yaml.
helm get manifest <name>
— Helm' .
helm rollback <name> <revision-num>
— .
helm uninstall <name>
— .
Helm- . HTTP- S3-. GitHub Pages.
index.yaml , . — .
GitHub docs :
helm package msvc-chart/ -d docs/
helm repo index docs/ --url https://<github-username>.imtqy.com/<github-repo-name>/
docs. index.yaml . url URL- . , . , GitHub Pages, 'Source' 'master branch /docs folder'.
, GKE, Helm.
:
kubectl create namespace msvc-ns
kubectl config set-context --current --namespace=msvc-ns
. Helm msvc-repo (URL , Helm-):
helm repo add msvc-repo https://anshelen.imtqy.com/microservices-deploy/
helm repo update
:
helm install msvc-project msvc-repo/msvc-chart \
--set backend.container.resources.requests.cpu=50m \
--set backend.hpa.enabled=true \
--set gateway.container.resources.requests.cpu=50m \
--set gateway.hpa.enabled=true \
--set secrets.secret=secret
URL- . , , .
:
helm test msvc-project
:
helm upgrade msvc-project msvc-repo/msvc-chart \
--set secrets.secret=new-secret \
--reuse-values
- , .
Helm- , GKE. Helm , Git — , Docker, Helm.
क्लस्टर में कोड पहुंचाने की प्रक्रिया को स्वचालित करने के लिए, अगले लेख में हम जेनकिंस निरंतर एकीकरण सर्वर को कॉन्फ़िगर करेंगे और अपनी परियोजना के लिए एक पाइपलाइन बनाएंगे।