# Kubernetes Deployment - Detailed Reference

Detailed configurations và examples cho Kubernetes deployment trong GoodGo.

## Table of Contents

1. [Complete Deployment Example](#complete-deployment-example)
2. [Helm Chart Templates](#helm-chart-templates)
3. [Kustomize Configuration](#kustomize-configuration)
4. [CI/CD Integration](#cicd-integration)
5. [Production Configurations](#production-configurations)

---

## Complete Deployment Example

### Namespace

```yaml
# k8s/base/namespace.yaml
apiVersion: v1
kind: Namespace
metadata:
  name: goodgo
  labels:
    name: goodgo
    environment: production
```

### Complete Service Deployment

```yaml
# k8s/base/iam-service/deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: iam-service
  namespace: goodgo
  labels:
    app.kubernetes.io/name: iam-service
    app.kubernetes.io/part-of: goodgo
    app.kubernetes.io/version: "1.0.0"
spec:
  replicas: 3
  revisionHistoryLimit: 5
  strategy:
    type: RollingUpdate
    rollingUpdate:
      maxSurge: 1
      maxUnavailable: 0
  selector:
    matchLabels:
      app.kubernetes.io/name: iam-service
  template:
    metadata:
      labels:
        app.kubernetes.io/name: iam-service
      annotations:
        prometheus.io/scrape: "true"
        prometheus.io/port: "8080"
        prometheus.io/path: "/metrics"
    spec:
      serviceAccountName: iam-service
      securityContext:
        runAsNonRoot: true
        runAsUser: 1000
        fsGroup: 1000
      containers:
        - name: iam-service
          image: goodgo/iam-service:1.0.0
          imagePullPolicy: IfNotPresent
          securityContext:
            allowPrivilegeEscalation: false
            readOnlyRootFilesystem: true
            capabilities:
              drop:
                - ALL
          ports:
            - name: http
              containerPort: 8080
              protocol: TCP
          envFrom:
            - configMapRef:
                name: iam-config
          env:
            - name: ConnectionStrings__DefaultConnection
              valueFrom:
                secretKeyRef:
                  name: iam-secrets
                  key: database-url
            - name: Jwt__SecretKey
              valueFrom:
                secretKeyRef:
                  name: iam-secrets
                  key: jwt-secret
          resources:
            requests:
              memory: "256Mi"
              cpu: "100m"
            limits:
              memory: "512Mi"
              cpu: "500m"
          livenessProbe:
            httpGet:
              path: /health/live
              port: http
            initialDelaySeconds: 10
            periodSeconds: 10
            timeoutSeconds: 5
            failureThreshold: 3
          readinessProbe:
            httpGet:
              path: /health/ready
              port: http
            initialDelaySeconds: 5
            periodSeconds: 5
            timeoutSeconds: 3
            failureThreshold: 3
          startupProbe:
            httpGet:
              path: /health/startup
              port: http
            initialDelaySeconds: 5
            periodSeconds: 5
            failureThreshold: 30
          volumeMounts:
            - name: tmp
              mountPath: /tmp
      volumes:
        - name: tmp
          emptyDir: {}
      affinity:
        podAntiAffinity:
          preferredDuringSchedulingIgnoredDuringExecution:
            - weight: 100
              podAffinityTerm:
                labelSelector:
                  matchLabels:
                    app.kubernetes.io/name: iam-service
                topologyKey: kubernetes.io/hostname
      topologySpreadConstraints:
        - maxSkew: 1
          topologyKey: topology.kubernetes.io/zone
          whenUnsatisfiable: ScheduleAnyway
          labelSelector:
            matchLabels:
              app.kubernetes.io/name: iam-service
```

### Service Account

```yaml
# k8s/base/iam-service/serviceaccount.yaml
apiVersion: v1
kind: ServiceAccount
metadata:
  name: iam-service
  namespace: goodgo
---
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
  name: iam-service-role
  namespace: goodgo
rules:
  - apiGroups: [""]
    resources: ["configmaps", "secrets"]
    verbs: ["get", "list", "watch"]
---
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
  name: iam-service-rolebinding
  namespace: goodgo
subjects:
  - kind: ServiceAccount
    name: iam-service
roleRef:
  kind: Role
  name: iam-service-role
  apiGroup: rbac.authorization.k8s.io
```

### PodDisruptionBudget

```yaml
# k8s/base/iam-service/pdb.yaml
apiVersion: policy/v1
kind: PodDisruptionBudget
metadata:
  name: iam-service-pdb
  namespace: goodgo
spec:
  minAvailable: 2
  selector:
    matchLabels:
      app.kubernetes.io/name: iam-service
```

---

## Helm Chart Templates

### Chart.yaml

```yaml
# charts/goodgo-service/Chart.yaml
apiVersion: v2
name: goodgo-service
description: A Helm chart for GoodGo microservices
type: application
version: 1.0.0
appVersion: "1.0.0"
maintainers:
  - name: GoodGo Team
    email: team@goodgo.vn
```

### Deployment Template

```yaml
# charts/goodgo-service/templates/deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: {{ include "goodgo-service.fullname" . }}
  labels:
    {{- include "goodgo-service.labels" . | nindent 4 }}
spec:
  {{- if not .Values.autoscaling.enabled }}
  replicas: {{ .Values.replicaCount }}
  {{- end }}
  selector:
    matchLabels:
      {{- include "goodgo-service.selectorLabels" . | nindent 6 }}
  template:
    metadata:
      annotations:
        checksum/config: {{ include (print $.Template.BasePath "/configmap.yaml") . | sha256sum }}
        {{- with .Values.podAnnotations }}
        {{- toYaml . | nindent 8 }}
        {{- end }}
      labels:
        {{- include "goodgo-service.selectorLabels" . | nindent 8 }}
    spec:
      serviceAccountName: {{ include "goodgo-service.serviceAccountName" . }}
      securityContext:
        {{- toYaml .Values.podSecurityContext | nindent 8 }}
      containers:
        - name: {{ .Chart.Name }}
          securityContext:
            {{- toYaml .Values.securityContext | nindent 12 }}
          image: "{{ .Values.image.repository }}:{{ .Values.image.tag | default .Chart.AppVersion }}"
          imagePullPolicy: {{ .Values.image.pullPolicy }}
          ports:
            - name: http
              containerPort: {{ .Values.service.targetPort }}
              protocol: TCP
          {{- if .Values.env }}
          env:
            {{- toYaml .Values.env | nindent 12 }}
          {{- end }}
          {{- if .Values.envFromSecret }}
          envFrom:
            - secretRef:
                name: {{ include "goodgo-service.fullname" . }}-secrets
          {{- end }}
          livenessProbe:
            httpGet:
              path: {{ .Values.probes.liveness.path }}
              port: http
            initialDelaySeconds: {{ .Values.probes.liveness.initialDelaySeconds }}
            periodSeconds: {{ .Values.probes.liveness.periodSeconds }}
          readinessProbe:
            httpGet:
              path: {{ .Values.probes.readiness.path }}
              port: http
            initialDelaySeconds: {{ .Values.probes.readiness.initialDelaySeconds }}
            periodSeconds: {{ .Values.probes.readiness.periodSeconds }}
          resources:
            {{- toYaml .Values.resources | nindent 12 }}
```

### Helpers Template

```yaml
# charts/goodgo-service/templates/_helpers.tpl
{{/*
Expand the name of the chart.
*/}}
{{- define "goodgo-service.name" -}}
{{- default .Chart.Name .Values.nameOverride | trunc 63 | trimSuffix "-" }}
{{- end }}

{{/*
Create a default fully qualified app name.
*/}}
{{- define "goodgo-service.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 }}

{{/*
Common labels
*/}}
{{- define "goodgo-service.labels" -}}
helm.sh/chart: {{ include "goodgo-service.chart" . }}
{{ include "goodgo-service.selectorLabels" . }}
app.kubernetes.io/version: {{ .Values.image.tag | default .Chart.AppVersion | quote }}
app.kubernetes.io/managed-by: {{ .Release.Service }}
{{- end }}

{{/*
Selector labels
*/}}
{{- define "goodgo-service.selectorLabels" -}}
app.kubernetes.io/name: {{ include "goodgo-service.name" . }}
app.kubernetes.io/instance: {{ .Release.Name }}
{{- end }}
```

### Production Values

```yaml
# charts/goodgo-service/values/production.yaml
replicaCount: 3

image:
  repository: gcr.io/goodgo/iam-service
  tag: "1.0.0"
  pullPolicy: IfNotPresent

resources:
  requests:
    memory: "512Mi"
    cpu: "250m"
  limits:
    memory: "1Gi"
    cpu: "1000m"

autoscaling:
  enabled: true
  minReplicas: 3
  maxReplicas: 20
  targetCPUUtilizationPercentage: 70
  targetMemoryUtilizationPercentage: 80

ingress:
  enabled: true
  className: nginx
  annotations:
    nginx.ingress.kubernetes.io/rate-limit: "100"
    nginx.ingress.kubernetes.io/rate-limit-window: "1m"
  hosts:
    - host: api.goodgo.vn
      paths:
        - path: /api/v1/iam
          pathType: Prefix
  tls:
    - secretName: goodgo-tls
      hosts:
        - api.goodgo.vn

probes:
  liveness:
    path: /health/live
    initialDelaySeconds: 10
    periodSeconds: 10
  readiness:
    path: /health/ready
    initialDelaySeconds: 5
    periodSeconds: 5
```

---

## CI/CD Integration

### GitHub Actions Deploy

```yaml
# .github/workflows/deploy.yml
name: Deploy to Kubernetes

on:
  push:
    branches: [main]
    tags: ['v*']

jobs:
  deploy:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4

      - name: Set up Docker Buildx
        uses: docker/setup-buildx-action@v3

      - name: Login to GCR
        uses: docker/login-action@v3
        with:
          registry: gcr.io
          username: _json_key
          password: ${{ secrets.GCP_SA_KEY }}

      - name: Build and push
        uses: docker/build-push-action@v5
        with:
          context: ./services/iam-service-net
          push: true
          tags: gcr.io/goodgo/iam-service:${{ github.sha }}
          cache-from: type=gha
          cache-to: type=gha,mode=max

      - name: Set up kubectl
        uses: azure/setup-kubectl@v3

      - name: Set up Helm
        uses: azure/setup-helm@v3

      - name: Deploy to Kubernetes
        run: |
          helm upgrade --install iam-service ./charts/goodgo-service \
            --namespace goodgo \
            --create-namespace \
            --values ./charts/goodgo-service/values/production.yaml \
            --set image.tag=${{ github.sha }} \
            --wait
```

---

## Resources / Tài Nguyên

- [Kubernetes Documentation](https://kubernetes.io/docs/)
- [Helm Documentation](https://helm.sh/docs/)
- [Kustomize Documentation](https://kustomize.io/)
- [NGINX Ingress Controller](https://kubernetes.github.io/ingress-nginx/)
