一、Helm部署基础组件到K8s集群

1.1 Helm Chart部署

1.1.1 在线部署

1、创建ns

[root@k8s-master01 ~]# k create ns helm-test

2、安装指定chart版本为18.2.5的nginx

[root@k8s-master01 ~]# helm upgrade --install nginx bitnami/nginx --version 18.2.5 -n helm-test --set image.registry=docker.kubeasy.com --set image.repository=bitnami/nginx --set image.pullPolicy=IfNotPresent

查看安装的Release

[root@k8s-master01 ~]# helm list -n helm-test 
NAME    NAMESPACE   REVISION    UPDATED                                 STATUS      CHART           APP VERSION
nginx   helm-test   1           2025-03-26 17:15:38.675792901 +0800 CST deployed    nginx-18.2.5    1.27.2     

查看创建的pod

[root@k8s-master01 ~]# kgp -n helm-test
NAME                   READY   STATUS    RESTARTS   AGE
nginx-f4f6d796-84wll   1/1     Running   0          38s

查看Releases状态

[root@k8s-master01 ~]# helm status nginx -n helm-test 
NAME: nginx
LAST DEPLOYED: Wed Mar 26 17:22:40 2025
NAMESPACE: helm-test
STATUS: deployed
REVISION: 2
TEST SUITE: None
NOTES:
CHART NAME: nginx
CHART VERSION: 18.2.5
APP VERSION: 1.27.2
...
...

查看Releases历史版本

[root@k8s-master01 ~]# helm history nginx -n helm-test 
REVISION    UPDATED                     STATUS      CHART           APP VERSION DESCRIPTION     
1           Wed Mar 26 17:15:38 2025    superseded  nginx-18.2.5    1.27.2      Install complete
2           Wed Mar 26 17:22:40 2025    deployed    nginx-18.2.5    1.27.2      Upgrade complete

查看某个版本的状态

[root@k8s-master01 ~]# helm status nginx -n helm-test --revision 2
NAME: nginx
LAST DEPLOYED: Wed Mar 26 17:22:40 2025
NAMESPACE: helm-test
STATUS: deployed
REVISION: 2
TEST SUITE: None
NOTES:
CHART NAME: nginx
CHART VERSION: 18.2.5
APP VERSION: 1.27.2
...
...

查看某个Release的详细信息,包括值、配置、状态

[root@k8s-master01 ~]# helm get all nginx -n helm-test
NAME: nginx
LAST DEPLOYED: Wed Mar 26 17:22:40 2025
NAMESPACE: helm-test
STATUS: deployed
REVISION: 2
CHART: nginx
VERSION: 18.2.5
APP_VERSION: 1.27.2
TEST SUITE: None
USER-SUPPLIED VALUES:
image:
  pullPolicy: IfNotPresent
  registry: docker.kubeasy.com
  repository: bitnami/nginx

COMPUTED VALUES:
affinity: {}
args: []
automountServiceAccountToken: false
autoscaling:
  enabled: false
  maxReplicas: ""
  minReplicas: ""
  targetCPU: ""
  targetMemory: ""
cloneStaticSiteFromGit:
  branch: ""
  enabled: false
  extraEnvVars: []
  extraEnvVarsSecret: ""
  extraVolumeMounts: []
  gitClone:
    args: []
    command: []
  gitSync:
    args: []
    command: []
    resources: {}
    resourcesPreset: nano
  image:
    digest: ""
    pullPolicy: IfNotPresent
    pullSecrets: []
    registry: docker.io
    repository: bitnami/git
    tag: 2.47.0-debian-12-r0
  interval: 60
  repository: ""
clusterDomain: cluster.local
command: []
common:
  exampleValue: common-chart
  global:
    compatibility:
      openshift:
        adaptSecurityContext: auto
    imagePullSecrets: []
    imageRegistry: ""
commonAnnotations: {}
commonLabels: {}
containerPorts:
  http: 8080
  https: 8443
containerSecurityContext:
  allowPrivilegeEscalation: false
  capabilities:
    drop:
    - ALL
  enabled: true
  privileged: false
  readOnlyRootFilesystem: true
  runAsGroup: 1001
  runAsNonRoot: true
  runAsUser: 1001
  seLinuxOptions: {}
  seccompProfile:
    type: RuntimeDefault
customLivenessProbe: {}
customReadinessProbe: {}
customStartupProbe: {}
diagnosticMode:
  args:
  - infinity
  command:
  - sleep
  enabled: false
dnsConfig: {}
dnsPolicy: ""
existingServerBlockConfigmap: ""
existingStreamServerBlockConfigmap: ""
extraContainerPorts: []
extraDeploy: []
extraEnvVars: []
extraEnvVarsCM: ""
extraEnvVarsSecret: ""
extraVolumeMounts: []
extraVolumes: []
fullnameOverride: ""
global:
  compatibility:
    openshift:
      adaptSecurityContext: auto
  imagePullSecrets: []
  imageRegistry: ""
healthIngress:
  annotations: {}
  enabled: false
  extraHosts: []
  extraPaths: []
  extraRules: []
  extraTls: []
  hostname: example.local
  ingressClassName: ""
  path: /
  pathType: ImplementationSpecific
  secrets: []
  selfSigned: false
  tls: false
hostAliases: []
hostIPC: false
hostNetwork: false
image:
  debug: false
  digest: ""
  pullPolicy: IfNotPresent
  pullSecrets: []
  registry: docker.kubeasy.com
  repository: bitnami/nginx
  tag: 1.27.2-debian-12-r1
ingress:
  annotations: {}
  apiVersion: ""
  enabled: false
  extraHosts: []
  extraPaths: []
  extraRules: []
  extraTls: []
  hostname: nginx.local
  ingressClassName: ""
  path: /
  pathType: ImplementationSpecific
  secrets: []
  selfSigned: false
  tls: false
  tlsWwwPrefix: false
initContainers: []
kubeVersion: ""
lifecycleHooks: {}
livenessProbe:
  enabled: true
  failureThreshold: 6
  initialDelaySeconds: 30
  periodSeconds: 10
  successThreshold: 1
  timeoutSeconds: 5
metrics:
  containerPorts:
    metrics: 9113
  enabled: false
  extraArgs: []
  image:
    digest: ""
    pullPolicy: IfNotPresent
    pullSecrets: []
    registry: docker.io
    repository: bitnami/nginx-exporter
    tag: 1.3.0-debian-12-r7
  podAnnotations: {}
  port: ""
  prometheusRule:
    additionalLabels: {}
    enabled: false
    namespace: ""
    rules: []
  resources: {}
  resourcesPreset: nano
  securityContext:
    enabled: false
    runAsUser: 1001
    seLinuxOptions: {}
  service:
    annotations:
      prometheus.io/port: '{{ .Values.metrics.service.port }}'
      prometheus.io/scrape: "true"
    port: 9113
  serviceMonitor:
    enabled: false
    honorLabels: false
    interval: ""
    jobLabel: ""
    labels: {}
    metricRelabelings: []
    namespace: ""
    relabelings: []
    scrapeTimeout: ""
    selector: {}
nameOverride: ""
namespaceOverride: ""
networkPolicy:
  allowExternal: true
  allowExternalEgress: true
  enabled: true
  extraEgress: []
  extraIngress: []
  ingressNSMatchLabels: {}
  ingressNSPodMatchLabels: {}
nodeAffinityPreset:
  key: ""
  type: ""
  values: []
nodeSelector: {}
pdb:
  create: true
  maxUnavailable: ""
  minAvailable: ""
podAffinityPreset: ""
podAnnotations: {}
podAntiAffinityPreset: soft
podLabels: {}
podSecurityContext:
  enabled: true
  fsGroup: 1001
  fsGroupChangePolicy: Always
  supplementalGroups: []
  sysctls: []
priorityClassName: ""
readinessProbe:
  enabled: true
  failureThreshold: 3
  initialDelaySeconds: 5
  path: /
  periodSeconds: 5
  successThreshold: 1
  timeoutSeconds: 3
replicaCount: 1
resources: {}
resourcesPreset: nano
revisionHistoryLimit: 10
schedulerName: ""
serverBlock: ""
service:
  annotations: {}
  clusterIP: ""
  externalTrafficPolicy: Cluster
  extraPorts: []
  loadBalancerClass: ""
  loadBalancerIP: ""
  loadBalancerSourceRanges: []
  nodePorts:
    http: ""
    https: ""
  ports:
    http: 80
    https: 443
  sessionAffinity: None
  sessionAffinityConfig: {}
  targetPort:
    http: http
    https: https
  type: LoadBalancer
serviceAccount:
  annotations: {}
  automountServiceAccountToken: false
  create: true
  name: ""
sidecarSingleProcessNamespace: false
sidecars: []
startupProbe:
  enabled: false
  failureThreshold: 6
  initialDelaySeconds: 30
  periodSeconds: 10
  successThreshold: 1
  timeoutSeconds: 5
staticSiteConfigmap: ""
staticSitePVC: ""
streamServerBlock: ""
terminationGracePeriodSeconds: ""
tls:
  autoGenerated: true
  ca: ""
  cert: ""
  certCAFilename: ca.crt
  certFilename: tls.crt
  certKeyFilename: tls.key
  enabled: true
  existingSecret: ""
  key: ""
tolerations: []
topologySpreadConstraints: []
updateStrategy:
  rollingUpdate: {}
  type: RollingUpdate

HOOKS:
MANIFEST:
---
# Source: nginx/templates/networkpolicy.yaml
kind: NetworkPolicy
apiVersion: networking.k8s.io/v1
metadata:
  name: nginx
  namespace: "helm-test"
  labels:
    app.kubernetes.io/instance: nginx
    app.kubernetes.io/managed-by: Helm
    app.kubernetes.io/name: nginx
    app.kubernetes.io/version: 1.27.2
    helm.sh/chart: nginx-18.2.5
spec:
  podSelector:
    matchLabels:
      app.kubernetes.io/instance: nginx
      app.kubernetes.io/name: nginx
  policyTypes:
    - Ingress
    - Egress
  egress:
    - {}
  ingress:
    - ports:
        - port: 8080
        - port: 8443
---
# Source: nginx/templates/pdb.yaml
apiVersion: policy/v1
kind: PodDisruptionBudget
metadata:
  name: nginx
  namespace: "helm-test"
  labels:
    app.kubernetes.io/instance: nginx
    app.kubernetes.io/managed-by: Helm
    app.kubernetes.io/name: nginx
    app.kubernetes.io/version: 1.27.2
    helm.sh/chart: nginx-18.2.5
spec:
  maxUnavailable: 1
  selector:
    matchLabels:
      app.kubernetes.io/instance: nginx
      app.kubernetes.io/name: nginx
---
# Source: nginx/templates/serviceaccount.yaml
apiVersion: v1
kind: ServiceAccount
metadata:
  name: nginx
  namespace: "helm-test"
  labels:
    app.kubernetes.io/instance: nginx
    app.kubernetes.io/managed-by: Helm
    app.kubernetes.io/name: nginx
    app.kubernetes.io/version: 1.27.2
    helm.sh/chart: nginx-18.2.5
automountServiceAccountToken: false
---
# Source: nginx/templates/tls-secret.yaml
apiVersion: v1
kind: Secret
metadata:
  name: nginx-tls
  namespace: "helm-test"
  labels:
    app.kubernetes.io/instance: nginx
    app.kubernetes.io/managed-by: Helm
    app.kubernetes.io/name: nginx
    app.kubernetes.io/version: 1.27.2
    helm.sh/chart: nginx-18.2.5
type: kubernetes.io/tls
data:
  tls.crt: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSURhekNDQWxPZ0F3SUJBZ0lSQU9hZ0F2NXhVaXpGMlIvTFNJbGJ6S2t3RFFZSktvWklodmNOQVFFTEJRQXcKRXpFUk1BOEdBMVVFQXhNSWJtZHBibmd0WTJFd0hoY05NalV3TXpJMk1Ea3hOVE00V2hjTk1qWXdNekkyTURreApOVE00V2pBUU1RNHdEQVlEVlFRREV3VnVaMmx1ZURDQ0FTSXdEUVlKS29aSWh2Y05BUUVCQlFBRGdnRVBBRENDCkFRb0NnZ0VCQUxOUTlFMVF4enpFQ3poZWdTQVZDa2toWW5MS0FERjFUVmhBSVhpd3RtWmt4dUdvQzhxeWk5d2QKOGJyQWxORHBxQmNNWEorU3pqTm1vSHZTT1hLY0RvUTZlcmxCMDlGaWx2SlNZTDhhQXFWODhCaXMzQ2lCV2tjUwpJYVZ6S0pvS0d0ZHZ5RmhVbEpTejN0Qk1senYrK3VvNkV0blE1ZDYvNHlxdFNGMmp3c2pxMmZaSGU4V1NrcGkzClgvKzF5eTkyMjZsNjhoeGFlVUdXSGJtQk90Z24weGQ3aHRMUFNxbGNuanNkejNPcmVVeG0zc3MvWk9idlU4ZXYKK01QMVBad1RhelVQM29qZU85WElsNkZoT1hKdHlabDljeUQwcDdSelE2UURjdzBzb1pUcmdvZXVBcXArMVBSYQpJcnAxZEpPbndCc2dOTisyWDBVTlRRRG1ZeS84NWRVQ0F3RUFBYU9CdkRDQnVUQU9CZ05WSFE4QkFmOEVCQU1DCkJhQXdIUVlEVlIwbEJCWXdGQVlJS3dZQkJRVUhBd0VHQ0NzR0FRVUZCd01DTUF3R0ExVWRFd0VCL3dRQ01BQXcKSHdZRFZSMGpCQmd3Rm9BVWdUcFJpQUs1K05CQVBvQnV3R3ZxSGxsSGU0c3dXUVlEVlIwUkJGSXdVSUlGYm1kcApibmlDRDI1bmFXNTRMbWhsYkcwdGRHVnpkSUlUYm1kcGJuZ3VhR1ZzYlMxMFpYTjBMbk4yWTRJaGJtZHBibmd1CmFHVnNiUzEwWlhOMExuTjJZeTVqYkhWemRHVnlMbXh2WTJGc01BMEdDU3FHU0liM0RRRUJDd1VBQTRJQkFRQTQKSWExeGlwWlJXOVVHcGE4SU5VcitQSHd4WjgxcHdmWXVDTU0zRmJ4V1lWeU16eVUvZThHemdnZGwyMDZOYzlqeAp1OE1Fd0VWT3V6VzNRbkpwaWY3allNcUg2bkl4Sml4RlF0YjJJeEdxcFpwVzdLWmt2RDl2RVRCOWlaMEovTG4wCmd6MVVNUVhxSXlMa3lMOWYxSC9Pa2hnWXlCdTBaaWhUZzZaNzV6VWk5SzVUaHBoc0ZTcENvQjRXZ2VNb0twdnIKS3dPRE83bXhJMzhlQXhEa1V3TzRBcG5DL1RLdDRnaGNIdVR0UnRGd0ZrRUtXdWZiNGJid3VTRXFDL0Z0eStRZgpFU3ZHQ3hqOTMyNFFhNzhwRjRVOVhxQjRtRXI2VjFlbjFvbmoxWDZDOCtYQ2RKb1p1Y1hVT2NuZGZBYWtiT2VWCjQ5bDB1YytLcnhKazhZbGpOWkpYCi0tLS0tRU5EIENFUlRJRklDQVRFLS0tLS0K
  tls.key: LS0tLS1CRUdJTiBSU0EgUFJJVkFURSBLRVktLS0tLQpNSUlFcEFJQkFBS0NBUUVBczFEMFRWREhQTVFMT0Y2QklCVUtTU0ZpY3NvQU1YVk5XRUFoZUxDMlptVEc0YWdMCnlyS0wzQjN4dXNDVTBPbW9Gd3hjbjVMT00yYWdlOUk1Y3B3T2hEcDZ1VUhUMFdLVzhsSmd2eG9DcFh6d0dLemMKS0lGYVJ4SWhwWE1vbWdvYTEyL0lXRlNVbExQZTBFeVhPLzc2NmpvUzJkRGwzci9qS3ExSVhhUEN5T3JaOWtkNwp4WktTbUxkZi83WExMM2JicVhyeUhGcDVRWllkdVlFNjJDZlRGM3VHMHM5S3FWeWVPeDNQYzZ0NVRHYmV5ejlrCjV1OVR4Ni80dy9VOW5CTnJOUS9laU40NzFjaVhvV0U1Y20zSm1YMXpJUFNudEhORHBBTnpEU3lobE91Q2g2NEMKcW43VTlGb2l1blYwazZmQUd5QTAzN1pmUlExTkFPWmpML3psMVFJREFRQUJBb0lCQUQ2UG92eUtqMGliR1ZNTQpYYjZrdUpiMUo5VG10eFNLV1hiTndSL0xmNGZQNXpkNW1zdVlhWVZkaVNYZjVNdlNpWXVwQzNPOUUyWUppenBJCkNUVDhUM0JBdXVxQmxmWTZrSEZ3M2tJdVAvZ2UwK0c0QllPNFJaZ0FNbTczODVWeXF4UzQ4a3duRGtPblViaVkKMERibGFnTm9TWVZuQlp3bWxJb2lOTm8rdFVuRldHckZCbmhIdnZpS2ZiRE5wTFhlNW0vL1c5M21rRk5rWDZrUwpQaXcyWXViUFhkbEREZ3BNS1Avb21CTm5xYS96dDBiTlBPVkw0UG9SWWZncG5GaXR5T0dseDBuVWZPT2hYeTR1CitVL3NVSjZxczczZjhnWUR2b09vRXpNc0ZzN2w0T3AxaUE3YnVUdlZtdlNqa2h4TGEwb3hYWWNLL3NIR0NKWU4KUUszOWVJRUNnWUVBeDBYU3NKQ2RmdG14b2JCTHdCOVZ6Y0VOM1JjZ25SWmErb1lFSERobjRHRVdUeHF2U2RLQwpkM3VNTUJQZW5HZ2VYWExtUnN1dkoxeDFnVnRlSU1kTG1YLzZnZENtUE5KUGJIOHFOLzhUc1IzNkNYV3QySVZvCjBZTDNLOVY0QXlidVFJMHBUeUpFNmJ4SkJQTHYvenZwSE9GVm9Ma1V0dS9qcnp0TjFkVzZtS0VDZ1lFQTVsekkKVFozQU9uNHJUY3Y2bDBuK3hLelBFb1ZRL1I2Z3BDZEdXMFM2NHR0RndxSlE1THVrck5ya1dlRTFVbWt0VVlWQwo1WW1hTzNlUzN1N3FTMWtTb3dPNm9SbFFjNkdna2VLOS9mc2U0bUlFSG9DNU9WTGUvN012U2toVy9GVDRLbUp2Cm45VnY5aXg5NldQTmNQU1REajR2SDQrUk1MUlNMUWx2YU1pQmZMVUNnWUVBbDgxOERCK09xeVNoYWdBSUpNcDYKTGV6a1o4bUhnY09XK1FRQXU1TElweWl1dXdJa0NJUEIrYzEzWk9TdUQ4NU5XM2o5TFc5YTlndzhRNWZiNC9LTwpoOWZ6ZU5MKzRKU0NCcS8wOUlWdmRkelZMa0drZHE1aXhFQVZsU0hnYzk1RFg0OXBxYXY4ZldaKzViTS8ydHJECjRjbFMxc1pIbm5pdXBUM3pOSFBGMnlFQ2dZRUF5ZGhpYWgvZlgyRk44RXphdGRWUU5tUjB6SFdrRVNYVS9BQ3QKMVNyVDFoTHJmUzljVWc5WXExemcyU0JMNkhuZ0M1NElqN2VTUEtqNU4vMS9yYVhPZnFlMXo1S3V1NkxUWHdDZQpHUDBBZ3J2L2YvcXFVV0FicFZFTURycHovWVUyTFcwekFZbXpJTEM3WXRUZ0hpa3U4VHZyYm13TmUrK0VVWklDCjNIMVRlRUVDZ1lCQWMxNG9ZQWJEamYyM1dlMmxmRStJOXBaQXd1dklWRGlZVk5CaUIrRURFV2JyRjBFUExpUWQKMjRXN1N1THVzaEdFT09QZHlQSFdVdTFSb21GKzYyeWlyZjZnK24wbmcxV2ZyRFhDRUk0RWwvOGluT0hBeVZNeQo3VHUzTTBUdFJlMXFCbE93UjRKMUt6RDNuYmVHK2RkejJHWVNqeGVtRmZ6bGh3YnUvL1pOSkE9PQotLS0tLUVORCBSU0EgUFJJVkFURSBLRVktLS0tLQo=
  ca.crt: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSURFVENDQWZtZ0F3SUJBZ0lRUWZvR1RsYU5hOUg4Q1Vtc2h1Q1l1ekFOQmdrcWhraUc5dzBCQVFzRkFEQVQKTVJFd0R3WURWUVFERXdodVoybHVlQzFqWVRBZUZ3MHlOVEF6TWpZd09URTFNemhhRncweU5qQXpNall3T1RFMQpNemhhTUJNeEVUQVBCZ05WQkFNVENHNW5hVzU0TFdOaE1JSUJJakFOQmdrcWhraUc5dzBCQVFFRkFBT0NBUThBCk1JSUJDZ0tDQVFFQTBCM0s3eEhmT284NG43NmRGa25JSWZiampXMDhYZmUwMWpPU0s5d0tyeC9XMVdiZW15ZEQKSmNBcEJKVWtIMHhSUUVTaGdEQ0FrWkZNTmFoSnRGWDlKZ05jQ2VrWEJNY3k2UjhIcUVmU2lCWHRCTm1KMEJOcgp4U00zSDNXOWRRblNQWnZ6MktpcUJ6aU9XN1hoWTFDd2ZzR3o3aERObGxLamxMOEM0MlZzY0VlUmV1VU5qdFV2ClROa2pUQ3hVUmltbXAvWGdrY2tBVWlodGpiU3hDZjdJTlJRR2hUT3lhV0ZXWVR2eERTMUxTZU91MkJRQzBEU1cKQ2l3dDJhUVpaUUZ3Zms5TlVVRFhmRytZb1IwMjEvTE9vWi9XVmR1ckRWZUhOUHlGMy8wSmRqMld1c2ozNTZGWgpGSXlyZGp0ZUVYT1pHamluV0REdlNnWWFHUkFoaERMTGd3SURBUUFCbzJFd1h6QU9CZ05WSFE4QkFmOEVCQU1DCkFxUXdIUVlEVlIwbEJCWXdGQVlJS3dZQkJRVUhBd0VHQ0NzR0FRVUZCd01DTUE4R0ExVWRFd0VCL3dRRk1BTUIKQWY4d0hRWURWUjBPQkJZRUZJRTZVWWdDdWZqUVFENkFic0JyNmg1WlIzdUxNQTBHQ1NxR1NJYjNEUUVCQ3dVQQpBNElCQVFCM205YXkydlovd0k2UFVQaTltZVpieG5HRFNsYnM0cVh0bzJWS2pnMXR6MEtXWSt5M2tqdHhDUTBqCmpMMk5QM3NJSWM0V21iakRuM3grT1IxclUraGFFb210dUo0ZHBmeGVTbWtRRnZKZFR0azF0ZjNMdmdzT1EwVWcKR0I1d3lxY2ZUc2djaFhNU0E3M09iUjlaeU1qci9nTjcwWnI3UHR3NVpoQWpMdEZEYzRYL2VTRzhvaHFlYmlEaApFcWxId2NvQjltL21MblovdEZBKzlnRFBxQTFEdk1DUVRyNFdPeklxTGtNQmVGcVorb2dnT0VRWXdodC9zNm83CmhEWkpMZG83d1pRdTRTTG5pekF0b2c1b2t4dWVJd2NPa0VBNktJMjNUZkU2K1BrRXJzRVBnOFlxZEw4ZlZ2azQKeU16R3RNeExPLzRKV3lZY241WHJCRkR1SGFXOQotLS0tLUVORCBDRVJUSUZJQ0FURS0tLS0tCg==
---
# Source: nginx/templates/svc.yaml
apiVersion: v1
kind: Service
metadata:
  name: nginx
  namespace: "helm-test"
  labels:
    app.kubernetes.io/instance: nginx
    app.kubernetes.io/managed-by: Helm
    app.kubernetes.io/name: nginx
    app.kubernetes.io/version: 1.27.2
    helm.sh/chart: nginx-18.2.5
  annotations:
spec:
  type: LoadBalancer
  sessionAffinity: None
  externalTrafficPolicy: "Cluster"
  ports:
    - name: http
      port: 80
      targetPort: http
    - name: https
      port: 443
      targetPort: https
  selector:
    app.kubernetes.io/instance: nginx
    app.kubernetes.io/name: nginx
---
# Source: nginx/templates/deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx
  namespace: "helm-test"
  labels:
    app.kubernetes.io/instance: nginx
    app.kubernetes.io/managed-by: Helm
    app.kubernetes.io/name: nginx
    app.kubernetes.io/version: 1.27.2
    helm.sh/chart: nginx-18.2.5
spec:
  replicas: 1
  revisionHistoryLimit: 10
  strategy:
    rollingUpdate: {}
    type: RollingUpdate
  selector:
    matchLabels:
      app.kubernetes.io/instance: nginx
      app.kubernetes.io/name: nginx
  template:
    metadata:
      labels:
        app.kubernetes.io/instance: nginx
        app.kubernetes.io/managed-by: Helm
        app.kubernetes.io/name: nginx
        app.kubernetes.io/version: 1.27.2
        helm.sh/chart: nginx-18.2.5
      annotations:
    spec:

      shareProcessNamespace: false
      serviceAccountName: nginx
      automountServiceAccountToken: false
      affinity:
        podAffinity:

        podAntiAffinity:
          preferredDuringSchedulingIgnoredDuringExecution:
            - podAffinityTerm:
                labelSelector:
                  matchLabels:
                    app.kubernetes.io/instance: nginx
                    app.kubernetes.io/name: nginx
                topologyKey: kubernetes.io/hostname
              weight: 1
        nodeAffinity:

      hostNetwork: false
      hostIPC: false
      securityContext:
        fsGroup: 1001
        fsGroupChangePolicy: Always
        supplementalGroups: []
        sysctls: []
      initContainers:
        - name: preserve-logs-symlinks
          image: docker.kubeasy.com/bitnami/nginx:1.27.2-debian-12-r1
          imagePullPolicy: "IfNotPresent"
          securityContext:
            allowPrivilegeEscalation: false
            capabilities:
              drop:
              - ALL
            privileged: false
            readOnlyRootFilesystem: true
            runAsGroup: 1001
            runAsNonRoot: true
            runAsUser: 1001
            seLinuxOptions: {}
            seccompProfile:
              type: RuntimeDefault
          resources:
            limits:
              cpu: 150m
              ephemeral-storage: 2Gi
              memory: 192Mi
            requests:
              cpu: 100m
              ephemeral-storage: 50Mi
              memory: 128Mi
          command:
            - /bin/bash
          args:
            - -ec
            - |
              #!/bin/bash
              . /opt/bitnami/scripts/libfs.sh
              # We copy the logs folder because it has symlinks to stdout and stderr
              if ! is_dir_empty /opt/bitnami/nginx/logs; then
                cp -r /opt/bitnami/nginx/logs /emptydir/app-logs-dir
              fi
          volumeMounts:
            - name: empty-dir
              mountPath: /emptydir
      containers:
        - name: nginx
          image: docker.kubeasy.com/bitnami/nginx:1.27.2-debian-12-r1
          imagePullPolicy: "IfNotPresent"
          securityContext:
            allowPrivilegeEscalation: false
            capabilities:
              drop:
              - ALL
            privileged: false
            readOnlyRootFilesystem: true
            runAsGroup: 1001
            runAsNonRoot: true
            runAsUser: 1001
            seLinuxOptions: {}
            seccompProfile:
              type: RuntimeDefault
          env:
            - name: BITNAMI_DEBUG
              value: "false"
            - name: NGINX_HTTP_PORT_NUMBER
              value: "8080"
            - name: NGINX_HTTPS_PORT_NUMBER
              value: "8443"
          envFrom:
          ports:
            - name: http
              containerPort: 8080
            - name: https
              containerPort: 8443
          livenessProbe:
            failureThreshold: 6
            initialDelaySeconds: 30
            periodSeconds: 10
            successThreshold: 1
            timeoutSeconds: 5
            tcpSocket:
              port: http
          readinessProbe:
            failureThreshold: 3
            initialDelaySeconds: 5
            periodSeconds: 5
            successThreshold: 1
            timeoutSeconds: 3
            httpGet:
              path: /
              port: http
          resources:
            limits:
              cpu: 150m
              ephemeral-storage: 2Gi
              memory: 192Mi
            requests:
              cpu: 100m
              ephemeral-storage: 50Mi
              memory: 128Mi
          volumeMounts:
            - name: empty-dir
              mountPath: /tmp
              subPath: tmp-dir
            - name: empty-dir
              mountPath: /opt/bitnami/nginx/conf
              subPath: app-conf-dir
            - name: empty-dir
              mountPath: /opt/bitnami/nginx/logs
              subPath: app-logs-dir
            - name: empty-dir
              mountPath: /opt/bitnami/nginx/tmp
              subPath: app-tmp-dir
            - name: certificate
              mountPath: /certs
      volumes:
        - name: empty-dir
          emptyDir: {}
        - name: certificate
          secret:
            secretName: nginx-tls
            items:
              - key: tls.crt
                path: server.crt
              - key: tls.key
                path: server.key

NOTES:
CHART NAME: nginx
CHART VERSION: 18.2.5
APP VERSION: 1.27.2
...
...

查看某个Release设置的值(主要记录更新的内容信息)

[root@k8s-master01 ~]# helm get values nginx -n helm-test
USER-SUPPLIED VALUES:
image:
  pullPolicy: IfNotPresent
  registry: docker.kubeasy.com
  repository: bitnami/nginx

1.1.2 离线部署

2.6.1.2.1 离线部署nginx

1、创建ns

[root@k8s-master01 ~]# k create ns helm-test

2、下载chart版本为18.2.5的nginx

[root@k8s-master01 ~]# mkdir helm
[root@k8s-master01 ~]# cd helm
[root@k8s-master01 helm]# helm pull  bitnami/nginx --version 18.2.5

3、解压包并进行包安装

[root@k8s-master01 helm]# tar xf nginx-18.2.5.tgz 
[root@k8s-master01 helm]# cd nginx/
[root@k8s-master01 nginx]# helm install nginx-test . -n helm-test

查看创建的pod,观察到拉取不到国外的镜像

[root@k8s-master01 ~]# kgp -n helm-test | grep nginx-test
nginx-test-854586c6b5-m4mxt   0/1     Init:ImagePullBackOff   0          14m

4、重新修改

[root@k8s-master01 nginx]# vim values.yaml
...
...
# 修改81行内容
81   registry: docker.kubeasy.com
...
...

5、更新后重新部署

[root@k8s-master01 nginx]# helm upgrade nginx-test . -n helm-test

验证查看

[root@k8s-master01 ~]# kgp -n helm-test | grep nginx-test
nginx-test-7875cf7965-cffhk   1/1     Running   0          36s
2.6.1.2.2 离线部署缺点-无法查询更新内容

离线部署存在一个缺点,就是查看不到更新内容信息

[root@k8s-master01 ~]# helm get values nginx-test -n helm-test
USER-SUPPLIED VALUES:
null

针对此类问题,可以在更新values.yaml文件之前,做个备份

[root@k8s-master01 nginx]# cp values.yaml values-revision-v1.yaml

再通过vimdiff命令对比文件,以此来查看更新内容信息

[root@k8s-master01 nginx]# vimdiff values.yaml values-revision-v1.yaml

二、Helm Chart更新回滚

2.1 Helm Chart更新

注意事项:在更新的时候需要带上之前所有的更新参数,而不是只加本次的更新参数,这样会导致之前的更新参数丢失

1、扩容副本数为2

[root@k8s-master01 ~]# helm upgrade --install nginx bitnami/nginx --version 18.2.5 -n helm-test --set image.registry=docker.kubeasy.com --set image.repository=bitnami/nginx --set image.pullPolicy=IfNotPresent --set replicaCount=2

2、验证,观察到已扩容

[root@k8s-master01 ~]# kgp -n helm-test
NAME                   READY   STATUS    RESTARTS   AGE
nginx-f4f6d796-84wll   1/1     Running   0          14m
nginx-f4f6d796-gcrjq   1/1     Running   0          33s

2.2 Helm Chart回滚

1、查看Releases历史版本

[root@k8s-master01 ~]# helm history nginx -n helm-test 
REVISION    UPDATED                     STATUS      CHART           APP VERSION DESCRIPTION     
1           Wed Mar 26 17:15:38 2025    superseded  nginx-18.2.5    1.27.2      Install complete
2           Wed Mar 26 17:22:40 2025    superseded  nginx-18.2.5    1.27.2      Upgrade complete
3           Wed Mar 26 17:36:21 2025    deployed    nginx-18.2.5    1.27.2      Upgrade complete

2、查看revision为2的版本的状态

[root@k8s-master01 ~]# helm status nginx -n helm-test --revision 2
NAME: nginx
LAST DEPLOYED: Wed Mar 26 17:22:40 2025
NAMESPACE: helm-test
STATUS: superseded
REVISION: 2
TEST SUITE: None
NOTES:
CHART NAME: nginx
CHART VERSION: 18.2.5
APP VERSION: 1.27.2
...
...

3、回滚到revision为2,即还是单pod的版本

[root@k8s-master01 ~]# helm rollback nginx 2 -n helm-test
Rollback was a success! Happy Helming!

4、验证,观察到已成功回滚

[root@k8s-master01 ~]# kgp -n helm-test
NAME                   READY   STATUS    RESTARTS   AGE
nginx-f4f6d796-84wll   1/1     Running   0          17m

三、Helm Chart导出模板

如果想根据Chart导出Yaml,可以使用template字段:

# 注意这条命令应该在Chart.yaml文件和templates目录所在位置执行
[root@k8s-master01 nginx]# helm template nginx . -n helm-test --output-dir yaml

查看结果

[root@k8s-master01 nginx]# ls yaml/nginx/templates/
deployment.yaml  networkpolicy.yaml  pdb.yaml  serviceaccount.yaml  svc.yaml  tls-secret.yaml

四、Helm Chart卸载

4.1 在线方式安装后进行卸载

卸载名为nginx的Helm Chart

[root@k8s-master01 ~]# helm delete nginx -n helm-test

4.2 离线方式安装后进行卸载

卸载名为nginx-test的Helm Chart

[root@k8s-master01 ~]# cd /root/helm/nginx
[root@k8s-master01 nginx]# helm delete nginx-test -n helm-test