Kubernetes
03 / 04

Deployments, Services & Manifests

Deployments, Services & Manifests

Deployment YAML

apiVersion: apps/v1
kind: Deployment
metadata:
  name: my-app
  namespace: production
  labels:
    app: my-app
spec:
  replicas: 3
  selector:
    matchLabels:
      app: my-app
  strategy:
    type: RollingUpdate
    rollingUpdate:
      maxSurge: 1           # extra pods during update
      maxUnavailable: 0     # no downtime
  template:
    metadata:
      labels:
        app: my-app
        version: "1.5"
    spec:
      containers:
        - name: app
          image: ghcr.io/myorg/myapp:1.5
          ports:
            - containerPort: 3000
          env:
            - name: NODE_ENV
              value: production
            - name: DATABASE_URL
              valueFrom:
                secretKeyRef:
                  name: app-secrets
                  key: database-url
          envFrom:
            - configMapRef:
                name: app-config
          resources:
            requests:
              memory: "256Mi"
              cpu: "100m"
            limits:
              memory: "512Mi"
              cpu: "500m"
          readinessProbe:
            httpGet:
              path: /health
              port: 3000
            initialDelaySeconds: 10
            periodSeconds: 5
            failureThreshold: 3
          livenessProbe:
            httpGet:
              path: /health
              port: 3000
            initialDelaySeconds: 30
            periodSeconds: 10
          volumeMounts:
            - name: config-volume
              mountPath: /app/config
      volumes:
        - name: config-volume
          configMap:
            name: app-config-files

Service Types

# ClusterIP — internal only (default)
apiVersion: v1
kind: Service
metadata:
  name: my-app
spec:
  selector:
    app: my-app
  ports:
    - port: 80
      targetPort: 3000
  type: ClusterIP

---
# LoadBalancer — external via cloud provider
apiVersion: v1
kind: Service
metadata:
  name: my-app-lb
spec:
  selector:
    app: my-app
  ports:
    - port: 80
      targetPort: 3000
  type: LoadBalancer

---
# NodePort — expose on each node's IP (debugging only)
spec:
  type: NodePort
  ports:
    - port: 80
      targetPort: 3000
      nodePort: 30080      # 30000-32767

Ingress

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: my-app-ingress
  annotations:
    nginx.ingress.kubernetes.io/rewrite-target: /
    cert-manager.io/cluster-issuer: letsencrypt-prod
spec:
  ingressClassName: nginx
  tls:
    - hosts:
        - myapp.example.com
      secretName: myapp-tls
  rules:
    - host: myapp.example.com
      http:
        paths:
          - path: /api
            pathType: Prefix
            backend:
              service:
                name: api-service
                port:
                  number: 80
          - path: /
            pathType: Prefix
            backend:
              service:
                name: frontend-service
                port:
                  number: 80

ConfigMap & Secret

# ConfigMap
apiVersion: v1
kind: ConfigMap
metadata:
  name: app-config
data:
  NODE_ENV: production
  PORT: "3000"
  LOG_LEVEL: info
  config.json: |
    {
      "timeout": 5000,
      "retries": 3
    }

---
# Secret (values are base64 encoded)
apiVersion: v1
kind: Secret
metadata:
  name: app-secrets
type: Opaque
data:
  database-url: cG9zdGdyZXM6Ly8...   # base64
  jwt-secret: c2VjcmV0a2V5...

# Create from CLI
kubectl create secret generic app-secrets   --from-literal=database-url="postgres://..."   --from-literal=jwt-secret="mysecret"

kubectl create configmap app-config   --from-file=config.json   --from-literal=NODE_ENV=production

Keep your own version of these notes — editable, searchable, and organised by your stack.

Start free