k8s(18)-- 创建一个Helm Chart

创建一个Helm Chart

1. 应用准备

准备一个简单的golang http服务:

main.go

package main

import (
 "fmt"
 "log"
 "net/http"
 "os"
)

func main() {
 port := os.Getenv("PORT")
 if port == "" {
  port = "8080"
 }
 username := os.Getenv("USERNAME")
 if username == "" {
  username = "world"
 }
 http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
  fmt.Fprintf(w, "Hello %s\n", username)
 })
 log.Println("go hello world starting...")
 err := http.ListenAndServe(":"+port, nil)
 if err != nil {
  panic(err)
 }
}

Dockerfile:

FROM golang:1.17.1 as builder
WORKDIR /app
COPY main.go .
ENV CGO_ENABLED=0
RUN go build -o hello-world main.go

FROM alpine:latest
WORKDIR /app
COPY --from=builder /app/hello-world /app/hello-world
ENTRYPOINT ["/app/hello-world"]
EXPOSE 8080
[root@master test]# docker build -t ms/go-hello-world:1.0 .

上传到docker仓库中:

[root@master test]# docker tag ms/go-hello-world:1.0 mszlu/go-hello-world:1.0
[root@master test]# docker push mszlu/go-hello-world:1.0
The push refers to repository [docker.io/mszlu/go-hello-world]
05feaa071f42: Pushed 
6b42f5d48464: Pushed 
9fb3aa2f8b80: Mounted from library/alpine 
1.0: digest: sha256:26a7e9362e1a8fab51d38b0cc5ec1d36723850ab57aa15802d489843ae2cb2ec size: 946

2. 创建Chart

[root@master test]# helm create hello-world
Creating hello-world

2.1 Chart.yaml

apiVersion: v2
name: hello-world
description: ms go hello world chart
type: application
version: 0.1.0
appVersion: "1.16.0"

2.2 values.yaml

replicas: 2
image:
  repository: mszlu/go-hello-world
  pullPolicy: IfNotPresent
  tag: "1.0"
service:
  type: ClusterIP
  port: 80
  targetport: 8080
ingress:
  enabled: true
  annotations: {}
  hosts:
    - host: chart.test.com
      paths: / 
  tls: []
resources:
  limits:
    cpu: 200m
    memory: 256Mi
  requests:
    cpu: 100m
    memory: 128Mi
autoscaling:
  enabled: false
  minReplicas: 1
  maxReplicas: 100
  targetCPUUtilizationPercentage: 80
  targetMemoryUtilizationPercentage: 80
nodeSelector: {}

2.3 模板简单修改:

_helpers.tpl

{{/*
资源名称
*/}}
{{- define "hello-world.fullname" -}}
{{- default .Chart.Name .Values.nameOverride | trunc 63 | trimSuffix "-" }}
{{- end }}
{{/*
公共标签选择器
*/}}
{{- define "hello-world.labels" -}}
app: {{ template "hello-world.fullname" . }}
release: {{ .Release.Name }}
chart: {{ .Chart.Name }}
{{- end }}
{{/*
标签选择器
*/}}
{{- define "hello-world.selectorLabels" -}}
app: {{ template "hello-world.fullname" . }}
release: {{ .Release.Name }}
{{- end }}

2.4 deployment.yaml

apiVersion: apps/v1
kind: Deployment
metadata:
  name: {{ include "hello-world.fullname" . }}
  labels:
    {{- include "hello-world.labels" . | nindent 4 }}
spec:
{{- if not .Values.autoscaling.enabled }}
  replicas: {{ .Values.replicaCount }}
{{- end }}
  selector:
    matchLabels:
      {{- include "hello-world.selectorLabels" . | nindent 6 }}
  template:
    metadata:
      labels:
        {{- include "hello-world.selectorLabels" . | nindent 8 }}
    spec:
      containers:
        - name: {{ .Chart.Name }}
          image: "{{ .Values.image.repository }}:{{ .Values.image.tag | default .Chart.AppVersion }}"
          imagePullPolicy: {{ .Values.image.pullPolicy }}
          {{- if .Values.resources }}
          resources:
            {{- toYaml .Values.resources | nindent 12 }}
          {{- else }}
         resources: {}
          {{- end }}

2.5 ingress.yaml

{{- if .Values.ingress.enabled -}}
{{- $fullName := include "hello-world.fullname" . -}}
{{- $svcPort := .Values.service.port -}}
{{- $paths := .Values.ingress.paths -}}
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: {{ $fullName }}
  labels:
    {{- include "hello-world.labels" . | nindent 4 }}
  {{- with .Values.ingress.annotations }}
  annotations:
    {{- toYaml . | nindent 4 }}
  {{- end }}
spec:
  ingressClassName: nginx
  {{- if .Values.ingress.tls }}
  tls:
    {{- range .Values.ingress.tls }}
    - hosts:
        {{- range .hosts }}
        - {{ . | quote }}
        {{- end }}
      secretName: {{ .secretName }}
    {{- end }}
  {{- end }}
  rules:
    {{- range .Values.ingress.hosts }}
    - host: {{ .host | quote }}
      http:
        paths:
          - path: {{ .paths }}
            pathType: Prefix
            backend:
              service:
                name: {{ $fullName }}
                port: 
                  number: {{ $svcPort }}
    {{- end }}
  {{- end }}

2.6 service.yaml

apiVersion: v1
kind: Service
metadata:
  name: {{ include "hello-world.fullname" . }}
  labels:
    {{- include "hello-world.labels" . | nindent 4 }}
spec:
  type: {{ .Values.service.type }}
  ports:
    - port: {{ .Values.service.port }}
      targetPort: {{ .Values.service.targetport }}
      protocol: TCP
      name: http
  selector:
    {{- include "hello-world.selectorLabels" . | nindent 4 }}

2.7 NOTES.txt

1. Get the application URL by running these commands:
{{- if .Values.ingress.enabled }}
  http{{ if $.Values.ingress.tls }}s{{ end }}://{{- range .Values.ingress.hosts }}{{ .host }}{{.paths}}{{end}} 
{{- else if contains "NodePort" .Values.service.type }}
  export NODE_PORT=$(kubectl get --namespace {{ .Release.Namespace }} -o jsonpath="{.spec.ports[0].nodePort}" services {{ include "hello-world.fullname" . }})
  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.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 "hello-world.fullname" . }}'
  export SERVICE_IP=$(kubectl get svc --namespace {{ .Release.Namespace }} {{ include "demo.fullname" . }} --template "{{"{{ range (index .status.loadBalancer.ingress 0) }}{{.}}{{ end }}"}}")
  echo http://$SERVICE_IP:{{ .Values.service.port }}
{{- else if contains "ClusterIP" .Values.service.type }}
  export POD_NAME=$(kubectl get pods --namespace {{ .Release.Namespace }} -l "app.kubernetes.io/name={{ include "hello-world.fullname" . }},app.kubernetes.io/instance={{ .Release.Name }}" -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:80
{{- end }}

3. 试运行

[root@master test]# helm install web hello-world/ --dry-run
NAME: web
LAST DEPLOYED: Tue Sep 20 15:25:28 2022
NAMESPACE: default
STATUS: pending-install
REVISION: 1
TEST SUITE: None
HOOKS:
MANIFEST:
---
# Source: hello-world/templates/service.yaml
apiVersion: v1
kind: Service
metadata:
  name: hello-world
  labels:
    app: hello-world
    release: web
    chart: hello-world
spec:
  type: ClusterIP
  ports:
    - port: 80
      targetPort: 8080
      protocol: TCP
      name: http
  selector:
    app: hello-world
    release: web
---
# Source: hello-world/templates/deployment.yaml

4. 安装

[root@master test]# helm install web hello-world/ -n dev
NAME: web
LAST DEPLOYED: Tue Sep 20 15:27:35 2022
NAMESPACE: dev
STATUS: deployed
REVISION: 1
TEST SUITE: None
NOTES:
1. Get the application URL by running these commands:
  http://chart.test.com/
[root@master test]# helm list -n dev
NAME    NAMESPACE       REVISION        UPDATED                                 STATUS          CHART                   APP VERSION
web     dev             1               2022-09-20 15:27:35.425054994 +0800 CST deployed        hello-world-0.1.0       1.16.0  
[root@master test]# kubectl get pods -n dev
NAME                           READY   STATUS    RESTARTS   AGE
hello-world-5f58b77b87-cm2fp   1/1     Running   0          43s
[root@master test]# kubectl get ingress -n dev
NAME          CLASS   HOSTS            ADDRESS   PORTS   AGE
hello-world   nginx   chart.test.com             80      96s
[root@master test]# kubectl get svc -n dev
NAME          TYPE        CLUSTER-IP      EXTERNAL-IP   PORT(S)   AGE
hello-world   ClusterIP   10.96.220.214   <none>        80/TCP    114s

访问浏览器:http://chart.test.com/ 验证是否正常

一定要记得安装ingress环境,在入门教程中,我们已经安装过

注意遇到网络问题:

#删除对应节点的cnio
[root@node2 ~]# ifconfig cni0 down    
[root@node2 ~]# ip link delete cni0
#删除coredns的pod 让其重建 原因是网络未配置正确 coredns 应该运行在工作节点才对
[root@master test]# kubectl delete pod coredns-6d8c4cb4d-wphbn -n kube-system
pod "coredns-6d8c4cb4d-wphbn" deleted


k8s(18)-- 创建一个Helm Chart
http://47.123.5.226:8090//archives/k8s-18----chuang-jian-yi-ge-helm-chart
作者
pony
发布于
2024年04月28日
许可协议