foundev.github.io

Busy Engineers Guide to Deploying on K8s Part 3 - Helm

Post Valid as of October 12, 2021.

Busy Engineer’s Guide to Deploying On K8s

Ok so now that you have Kubernetes installing in a deployment and you can see it with kubectl port-forward how to you get beyond the toy stage?

Helm Charts

Helm is a great way to make your app “production ready” on Kubernetes with minimal effort assuming you do not try to overthink your deployment. Helm fundamentally provides a way for us to deploy apps to kubernetes by easily changing a handful of values at deployment time or in something called a values.yaml

A helm “chart” is a series of kubernetes yaml templates with a values.yaml file providing you default values for your deployment. Do the following to get a basic one up and running

# Default values for myapp.
# This is a YAML-formatted file.
# Declare variables to be passed into your templates.

replicaCount: 1

image:
  repository: nginx
  pullPolicy: IfNotPresent
  # Overrides the image tag whose default is the chart appVersion.
  tag: "main"

imagePullSecrets:
- name: regcred
nameOverride: ""
fullnameOverride: ""

serviceAccount:
  # Specifies whether a service account should be created
  create: true
  # Annotations to add to the service account
  annotations: {}
  # The name of the service account to use.
  # If not set and create is true, a name is generated using the fullname template
  name: ""

podAnnotations: {}

podSecurityContext: {}
  # fsGroup: 2000

securityContext: {}
  # capabilities:
  #   drop:
  #   - ALL
  # readOnlyRootFilesystem: true
  # runAsNonRoot: true
  # runAsUser: 1000

service:
  type: ClusterIP
  port: 3000

ingress:
  enabled: false
  className: ""
  annotations: {}
    # kubernetes.io/ingress.class: nginx
    # kubernetes.io/tls-acme: "true"
  hosts:
    - host: chart-example.local
      paths:
        - path: /
          pathType: ImplementationSpecific
  tls: []
  #  - secretName: chart-example-tls
  #    hosts:
  #      - chart-example.local

resources: {}
  # We usually recommend not to specify default resources and to leave this as a conscious
  # choice for the user. This also increases chances charts run on environments with little
  # resources, such as Minikube. If you do want to specify resources, uncomment the following
  # lines, adjust them as necessary, and remove the curly braces after 'resources:'.
  # limits:
  #   cpu: 100m
  #   memory: 128Mi
  # requests:
  #   cpu: 100m
  #   memory: 128Mi

autoscaling:
  enabled: false
  minReplicas: 1
  maxReplicas: 100
  targetCPUUtilizationPercentage: 80
  # targetMemoryUtilizationPercentage: 80

nodeSelector: {}

tolerations: []

affinity: {}
apiVersion: apps/v1
kind: Deployment
metadata:
  name: 
  labels:
spec:
  replicas: 
  selector:
    matchLabels:
  template:
    metadata:
      annotations:
      labels:
    spec:
      imagePullSecrets:
      serviceAccountName: 
      securityContext:
      containers:
        - name: 
          securityContext:
          image: ":"
          imagePullPolicy: 
          ports:
            - name: http
              containerPort: 3000
              protocol: TCP
          livenessProbe:
            httpGet:
              path: /
              port: http
          readinessProbe:
            httpGet:
              path: /
              port: http
          resources:
      nodeSelector:
      affinity:
      tolerations:

Ingress

Ok so this portfoward stuff is great and all but not super impressive

cat <<EOF | kind create cluster --config=-
kind: Cluster
apiVersion: kind.x-k8s.io/v1alpha4
nodes:
- role: control-plane
  kubeadmConfigPatches:
  - |
    kind: InitConfiguration
    nodeRegistration:
      kubeletExtraArgs:
        node-labels: "ingress-ready=true"
  extraPortMappings:
  - containerPort: 80
    hostPort: 80
    protocol: TCP
  - containerPort: 443
    hostPort: 443
    protocol: TCP
EOF
ingress:
  enabled: true
  className: ""
  annotations:
    # allows nginx to rewrite urls to keep everything happy
    nginx.ingress.kubernetes.io/rewrite-target: /$1
  hosts:
    - host: localhost # set localhost since that is how we will be accessing it
      paths:
        - path: /app/?(.*) #needed to allow node to be ok with this /app path
          pathType: Prefix # defines our strategy to be prefix instead of whatever default is on various platforms
  tls: []

Recap