Java Helm chart案例

wen java案例 2

本文目录导读:

Java Helm chart案例

  1. 项目结构
  2. Chart.yaml
  3. values.yaml
  4. templates/_helpers.tpl
  5. templates/deployment.yaml
  6. templates/service.yaml
  7. templates/configmap.yaml
  8. templates/secrets.yaml
  9. templates/hpa.yaml
  10. templates/ingress.yaml
  11. templates/serviceaccount.yaml
  12. templates/pvc.yaml
  13. templates/NOTES.txt
  14. values-dev.yaml
  15. values-prod.yaml
  16. 使用方法
  17. Dockerfile 示例

我将为您提供一个完整的Java应用Helm chart案例,包括详细的配置和使用说明。

项目结构

java-app-chart/
├── Chart.yaml
├── values.yaml
├── values-dev.yaml
├── values-prod.yaml
├── templates/
│   ├── NOTES.txt
│   ├── _helpers.tpl
│   ├── deployment.yaml
│   ├── service.yaml
│   ├── ingress.yaml
│   ├── configmap.yaml
│   ├── secrets.yaml
│   ├── serviceaccount.yaml
│   ├── hpa.yaml
│   └── pvc.yaml
└── charts/

Chart.yaml

apiVersion: v2
name: java-app
description: A Helm chart for Java Spring Boot application
type: application
version: 1.0.0
appVersion: "1.0.0"
# 依赖项(如果需要)
dependencies:
  - name: mysql
    version: 9.4.0
    repository: https://charts.bitnami.com/bitnami
    condition: mysql.enabled
  - name: redis
    version: 17.3.7
    repository: https://charts.bitnami.com/bitnami
    condition: redis.enabled

values.yaml

# 默认配置
replicaCount: 2
image:
  repository: your-registry/java-app
  tag: latest
  pullPolicy: Always
  # 指定镜像拉取密钥
  pullSecrets:
    - name: registry-secret
nameOverride: ""
fullnameOverride: ""
# 环境变量配置
env:
  normal:
    - name: JAVA_OPTS
      value: "-Xms256m -Xmx512m"
    - name: SPRING_PROFILES_ACTIVE
      value: "prod"
    - name: TZ
      value: "Asia/Shanghai"
  # 引用ConfigMap的配置
  fromConfigMap:
    - configMapRef:
        name: java-app-config
  # 引用Secret的配置
  fromSecret:
    - secretRef:
        name: java-app-secret
# 容器端口配置
ports:
  - name: http
    containerPort: 8080
    protocol: TCP
# 健康检查
livenessProbe:
  httpGet:
    path: /actuator/health
    port: http
  initialDelaySeconds: 60
  periodSeconds: 10
  timeoutSeconds: 5
  failureThreshold: 3
readinessProbe:
  httpGet:
    path: /actuator/health
    port: http
  initialDelaySeconds: 30
  periodSeconds: 10
  timeoutSeconds: 5
  failureThreshold: 3
# 资源限制
resources:
  limits:
    cpu: "1"
    memory: 1Gi
  requests:
    cpu: "500m"
    memory: 512Mi
# 自动扩缩容
autoscaling:
  enabled: true
  minReplicas: 2
  maxReplicas: 10
  targetCPUUtilizationPercentage: 80
  targetMemoryUtilizationPercentage: 80
# Service配置
service:
  type: ClusterIP
  port: 80
  targetPort: http
  annotations: {}
# Ingress配置
ingress:
  enabled: true
  className: "nginx"
  annotations:
    nginx.ingress.kubernetes.io/rewrite-target: /
    kubernetes.io/ingress.class: nginx
  hosts:
    - host: app.example.com
      paths:
        - path: /
          pathType: Prefix
          backend:
            serviceName: java-app
            servicePort: 80
  tls:
    - secretName: java-app-tls
      hosts:
        - app.example.com
# ConfigMap配置
configMap:
  enabled: true
  data:
    application.yml: |
      server:
        port: 8080
      spring:
        datasource:
          url: jdbc:mysql://mysql:3306/java_app
          username: ${DB_USERNAME}
          password: ${DB_PASSWORD}
        redis:
          host: redis
          port: 6379
      logging:
        level:
          root: INFO
          com.example: DEBUG
# Secret配置
secrets:
  enabled: true
  data:
    DB_PASSWORD: UGFzc3dvcmQxMjM=  # Base64编码
    REDIS_PASSWORD: UGFzc3dvcmQxMjM=$
# 持久化存储
persistence:
  enabled: true
  storageClass: ""
  accessMode: ReadWriteOnce
  size: 10Gi
  existingClaim: ""
  annotations: {}
# ServiceAccount
serviceAccount:
  create: true
  name: ""
  annotations: {}
# 其他配置
nodeSelector: {}
tolerations: []
affinity: {}
# 滚动更新策略
strategy:
  type: RollingUpdate
  rollingUpdate:
    maxUnavailable: 1
    maxSurge: 1
# 自定义标签
labels:
  app.kubernetes.io/name: java-app
  app.kubernetes.io/managed-by: helm

templates/_helpers.tpl

{{- define "java-app.name" -}}
{{- default .Chart.Name .Values.nameOverride | trunc 63 | trimSuffix "-" -}}
{{- end -}}
{{- define "java-app.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 -}}
{{- define "java-app.labels" -}}
helm.sh/chart: {{ printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" }}
{{ include "java-app.selectorLabels" . }}
{{- if .Chart.AppVersion }}
app.kubernetes.io/version: {{ .Chart.AppVersion | quote }}
{{- end }}
app.kubernetes.io/managed-by: {{ .Release.Service }}
{{- with .Values.labels }}
{{ toYaml . }}
{{- end }}
{{- end -}}
{{- define "java-app.selectorLabels" -}}
app.kubernetes.io/name: {{ include "java-app.name" . }}
app.kubernetes.io/instance: {{ .Release.Name }}
{{- end -}}
{{- define "java-app.serviceAccountName" -}}
{{- if .Values.serviceAccount.create -}}
    {{ default (include "java-app.fullname" .) .Values.serviceAccount.name }}
{{- else -}}
    {{ default "default" .Values.serviceAccount.name }}
{{- end -}}
{{- end -}}

templates/deployment.yaml

apiVersion: apps/v1
kind: Deployment
metadata:
  name: {{ include "java-app.fullname" . }}
  labels:
    {{- include "java-app.labels" . | nindent 4 }}
spec:
  replicas: {{ .Values.replicaCount }}
  strategy:
    {{- toYaml .Values.strategy | nindent 4 }}
  selector:
    matchLabels:
      {{- include "java-app.selectorLabels" . | nindent 6 }}
  template:
    metadata:
      labels:
        {{- include "java-app.selectorLabels" . | nindent 8 }}
        {{- with .Values.podLabels }}
        {{- toYaml . | nindent 8 }}
        {{- end }}
    spec:
      serviceAccountName: {{ include "java-app.serviceAccountName" . }}
      {{- with .Values.image.pullSecrets }}
      imagePullSecrets:
        {{- toYaml . | nindent 8 }}
      {{- end }}
      containers:
        - name: {{ .Chart.Name }}
          image: "{{ .Values.image.repository }}:{{ .Values.image.tag }}"
          imagePullPolicy: {{ .Values.image.pullPolicy }}
          ports:
            {{- toYaml .Values.ports | nindent 12 }}
          env:
            {{- toYaml .Values.env.normal | nindent 12 }}
            {{- if .Values.env.fromConfigMap }}
            {{- toYaml .Values.env.fromConfigMap | nindent 12 }}
            {{- end }}
            {{- if .Values.env.fromSecret }}
            {{- toYaml .Values.env.fromSecret | nindent 12 }}
            {{- end }}
          livenessProbe:
            {{- toYaml .Values.livenessProbe | nindent 12 }}
          readinessProbe:
            {{- toYaml .Values.readinessProbe | nindent 12 }}
          resources:
            {{- toYaml .Values.resources | nindent 12 }}
          volumeMounts:
            {{- if .Values.configMap.enabled }}
            - name: config
              mountPath: /app/config
              readOnly: true
            {{- end }}
            {{- if .Values.persistence.enabled }}
            - name: data
              mountPath: /app/data
            {{- end }}
      volumes:
        {{- if .Values.configMap.enabled }}
        - name: config
          configMap:
            name: {{ include "java-app.fullname" . }}-config
        {{- end }}
        {{- if .Values.persistence.enabled }}
        - name: data
          persistentVolumeClaim:
            claimName: {{ if .Values.persistence.existingClaim }}{{ .Values.persistence.existingClaim }}{{ else }}{{ include "java-app.fullname" . }}{{ end }}
        {{- end }}
      {{- with .Values.nodeSelector }}
      nodeSelector:
        {{- toYaml . | nindent 8 }}
      {{- end }}
      {{- with .Values.affinity }}
      affinity:
        {{- toYaml . | nindent 8 }}
      {{- end }}
      {{- with .Values.tolerations }}
      tolerations:
        {{- toYaml . | nindent 8 }}
      {{- end }}

templates/service.yaml

apiVersion: v1
kind: Service
metadata:
  name: {{ include "java-app.fullname" . }}
  labels:
    {{- include "java-app.labels" . | nindent 4 }}
  {{- with .Values.service.annotations }}
  annotations:
    {{- toYaml . | nindent 4 }}
  {{- end }}
spec:
  type: {{ .Values.service.type }}
  ports:
    - port: {{ .Values.service.port }}
      targetPort: {{ .Values.service.targetPort }}
      protocol: TCP
      name: http
  selector:
    {{- include "java-app.selectorLabels" . | nindent 4 }}

templates/configmap.yaml

{{- if .Values.configMap.enabled }}
apiVersion: v1
kind: ConfigMap
metadata:
  name: {{ include "java-app.fullname" . }}-config
  labels:
    {{- include "java-app.labels" . | nindent 4 }}
data:
  {{- range $key, $value := .Values.configMap.data }}
  {{ $key }}: |
{{ $value | indent 4 }}
  {{- end }}
{{- end }}

templates/secrets.yaml

{{- if .Values.secrets.enabled }}
apiVersion: v1
kind: Secret
metadata:
  name: {{ include "java-app.fullname" . }}-secret
  labels:
    {{- include "java-app.labels" . | nindent 4 }}
type: Opaque
data:
  {{- range $key, $value := .Values.secrets.data }}
  {{ $key }}: {{ $value | quote }}
  {{- end }}
{{- end }}

templates/hpa.yaml

{{- if .Values.autoscaling.enabled }}
apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
  name: {{ include "java-app.fullname" . }}
  labels:
    {{- include "java-app.labels" . | nindent 4 }}
spec:
  scaleTargetRef:
    apiVersion: apps/v1
    kind: Deployment
    name: {{ include "java-app.fullname" . }}
  minReplicas: {{ .Values.autoscaling.minReplicas }}
  maxReplicas: {{ .Values.autoscaling.maxReplicas }}
  metrics:
    {{- if .Values.autoscaling.targetCPUUtilizationPercentage }}
    - type: Resource
      resource:
        name: cpu
        target:
          type: Utilization
          averageUtilization: {{ .Values.autoscaling.targetCPUUtilizationPercentage }}
    {{- end }}
    {{- if .Values.autoscaling.targetMemoryUtilizationPercentage }}
    - type: Resource
      resource:
        name: memory
        target:
          type: Utilization
          averageUtilization: {{ .Values.autoscaling.targetMemoryUtilizationPercentage }}
    {{- end }}
{{- end }}

templates/ingress.yaml

{{- if .Values.ingress.enabled }}
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: {{ include "java-app.fullname" . }}
  labels:
    {{- include "java-app.labels" . | nindent 4 }}
  {{- with .Values.ingress.annotations }}
  annotations:
    {{- toYaml . | nindent 4 }}
  {{- end }}
spec:
  {{- if .Values.ingress.className }}
  ingressClassName: {{ .Values.ingress.className }}
  {{- end }}
  {{- if .Values.ingress.tls }}
  tls:
    {{- toYaml .Values.ingress.tls | nindent 4 }}
  {{- end }}
  rules:
    {{- range .Values.ingress.hosts }}
    - host: {{ .host | quote }}
      http:
        paths:
          {{- range .paths }}
          - path: {{ .path }}
            pathType: {{ .pathType }}
            backend:
              service:
                name: {{ include "java-app.fullname" $ }}
                port:
                  number: {{ .backend.servicePort }}
          {{- end }}
    {{- end }}
{{- end }}

templates/serviceaccount.yaml

{{- if .Values.serviceAccount.create }}
apiVersion: v1
kind: ServiceAccount
metadata:
  name: {{ include "java-app.serviceAccountName" . }}
  labels:
    {{- include "java-app.labels" . | nindent 4 }}
  {{- with .Values.serviceAccount.annotations }}
  annotations:
    {{- toYaml . | nindent 4 }}
  {{- end }}
{{- end }}

templates/pvc.yaml

{{- if and .Values.persistence.enabled (not .Values.persistence.existingClaim) }}
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: {{ include "java-app.fullname" . }}
  labels:
    {{- include "java-app.labels" . | nindent 4 }}
  {{- with .Values.persistence.annotations }}
  annotations:
    {{- toYaml . | nindent 4 }}
  {{- end }}
spec:
  accessModes:
    - {{ .Values.persistence.accessMode | quote }}
  {{- if .Values.persistence.storageClass }}
  storageClassName: {{ .Values.persistence.storageClass }}
  {{- end }}
  resources:
    requests:
      storage: {{ .Values.persistence.size }}
{{- end }}

templates/NOTES.txt

Get the application URL:
{{- if .Values.ingress.enabled }}
  http://{{ .Values.ingress.hosts[0].host }}
{{- else if eq .Values.service.type "ClusterIP" }}
  export POD_NAME=$(kubectl get pods --namespace {{ .Release.Namespace }} -l "app.kubernetes.io/name={{ include "java-app.name" . }},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:8080
{{- else if eq .Values.service.type "NodePort" }}
  export NODE_PORT=$(kubectl get --namespace {{ .Release.Namespace }} -o jsonpath="{.spec.ports[0].nodePort}" services {{ include "java-app.fullname" . }})
  export NODE_IP=$(kubectl get nodes --namespace {{ .Release.Namespace }} -o jsonpath="{.items[0].status.addresses[0].address}")
  echo "Visit http://$NODE_IP:$NODE_PORT to use your application"
{{- end }}

values-dev.yaml

replicaCount: 1
image:
  repository: your-registry/java-app
  tag: dev-latest
  pullPolicy: Always
env:
  normal:
    - name: SPRING_PROFILES_ACTIVE
      value: "dev"
    - name: JAVA_OPTS
      value: "-Xms128m -Xmx256m"
resources:
  limits:
    cpu: "500m"
    memory: 512Mi
  requests:
    cpu: "250m"
    memory: 256Mi
autoscaling:
  enabled: false
ingress:
  enabled: false
service:
  type: ClusterIP

values-prod.yaml

replicaCount: 3
image:
  repository: your-registry/java-app
  tag: stable
  pullPolicy: IfNotPresent
resources:
  limits:
    cpu: "2"
    memory: 2Gi
  requests:
    cpu: "1"
    memory: 1Gi
autoscaling:
  enabled: true
  minReplicas: 3
  maxReplicas: 10
  targetCPUUtilizationPercentage: 70
ingress:
  enabled: true
  hosts:
    - host: prod-app.example.com
      paths:
        - path: /
          pathType: Prefix
          backend:
            servicePort: 80
  tls:
    - secretName: prod-tls
      hosts:
        - prod-app.example.com

使用方法

安装chart

# 基本安装
helm install java-app ./java-app-chart
# 指定环境
helm install java-app ./java-app-chart -f values-dev.yaml
helm install java-app ./java-app-chart -f values-prod.yaml
# 指定命名空间
helm install java-app ./java-app-chart -n my-namespace --create-namespace

升级

# 升级release
helm upgrade java-app ./java-app-chart -f values-prod.yaml
# 指定版本
helm upgrade java-app ./java-app-chart --set image.tag=1.0.1

回滚

# 查看历史版本
helm history java-app
# 回滚到指定版本
helm rollback java-app 2

卸载

helm uninstall java-app -n my-namespace

调试和测试

# 渲染模板
helm template java-app ./java-app-chart -f values-dev.yaml
# 检查语法
helm lint ./java-app-chart
# 渲染并调试
helm install java-app ./java-app-chart --dry-run --debug

Dockerfile 示例

# 多阶段构建
FROM maven:3.8.4-openjdk-17 AS build
WORKDIR /app
COPY pom.xml .
RUN mvn dependency:go-offline
COPY src ./src
RUN mvn clean package -DskipTests
# 运行时镜像
FROM openjdk:17-jdk-alpine
WORKDIR /app
COPY --from=build /app/target/*.jar app.jar
EXPOSE 8080
ENTRYPOINT ["java", "-jar", "app.jar"]

这个完整的Helm chart案例包含了Java应用部署所需的所有资源,可以根据实际需求进行调整和扩展。

抱歉,评论功能暂时关闭!