diff --git a/k8s/ROLLOUTS.md b/k8s/ROLLOUTS.md new file mode 100644 index 0000000000..6e7f3c2f35 --- /dev/null +++ b/k8s/ROLLOUTS.md @@ -0,0 +1,233 @@ +# ROLLOUTS.md — Argo Rollouts Progressive Delivery + +## 1. Argo Rollouts Setup + +### Installation +Argo Rollouts controller was installed in the cluster: + +```bash +kubectl create namespace argo-rollouts +kubectl apply -n argo-rollouts -f https://github.com/argoproj/argo-rollouts/releases/latest/download/install.yaml +```` + +Verification: + +```bash +kubectl get pods -n argo-rollouts +``` + +All controller pods are running successfully. + +### Kubectl Plugin + +Installed kubectl plugin: + +```bash +kubectl argo rollouts version +``` + +### Dashboard + +Dashboard installed and accessed via port-forward: + +```bash +kubectl port-forward svc/argo-rollouts-dashboard -n argo-rollouts 3100:3100 +``` + +URL: + +``` +http://localhost:3100 +``` + +--- + +## 2. Canary Deployment + +### Strategy Configuration + +The application was converted from Deployment to Rollout with canary strategy: + +* Progressive traffic shifting +* Manual and automatic pauses +* Gradual rollout steps + +### Canary Steps + +Configured rollout steps: + +* 20% traffic → manual pause +* 40% traffic → pause 30s +* 60% traffic → pause 30s +* 80% traffic → pause 30s +* 100% traffic + +### Behavior Observed + +* New ReplicaSet created for each update +* Traffic gradually shifted between stable and canary pods +* Intermediate pauses observed in dashboard +* Final state: 100% traffic to new version + +### Promotion + +Manual promotion used during first pause: + +```bash +kubectl argo rollouts promote myapp-dev -n dev +``` + +### Rollback Test + +Rollback was tested using abort command: + +```bash +kubectl argo rollouts abort myapp-dev -n dev +``` + +Result: + +* Traffic immediately reverted to stable version +* New ReplicaSet scaled down +* No downtime observed + +--- + +## 3. Blue-Green Deployment + +### Strategy Configuration + +Blue-green strategy implemented with: + +* Active service (production traffic) +* Preview service (new version testing) +* Manual promotion control + +### Services + +* `myapp-dev` → active service +* `myapp-dev-preview` → preview service + +### Flow + +1. Initial version deployed (blue) +2. New version created (green) +3. Preview service used to validate new version +4. Manual promotion applied + +### Access + +```bash +kubectl port-forward svc/myapp-dev 8080:80 +kubectl port-forward svc/myapp-dev-preview 8081:80 +``` + +### Promotion + +```bash +kubectl argo rollouts promote myapp-dev -n dev +``` + +### Rollback Behavior + +* Rollback is instantaneous +* Traffic switches immediately back to previous version +* No gradual transition (unlike canary) + +--- + +## 4. Strategy Comparison + +### Canary Deployment + +**Advantages:** + +* Gradual traffic shift +* Safer for production +* Early detection of issues +* Fine-grained control + +**Disadvantages:** + +* Slower rollout +* More complex configuration + +--- + +### Blue-Green Deployment + +**Advantages:** + +* Instant switch between versions +* Simple rollback +* Clear separation of environments + +**Disadvantages:** + +* Requires double resources +* No gradual validation under load + +--- + +### Recommendation + +* Use **Canary** for production APIs and user-facing services +* Use **Blue-Green** for critical releases requiring instant rollback +* Use Canary when risk needs to be minimized gradually + +--- + +## 5. CLI Commands Reference + +### Rollout Monitoring + +```bash +kubectl argo rollouts get rollout myapp-dev -n dev -w +``` + +### Promotion + +```bash +kubectl argo rollouts promote myapp-dev -n dev +``` + +### Abort Rollout + +```bash +kubectl argo rollouts abort myapp-dev -n dev +``` + +### Restart Rollout + +```bash +kubectl argo rollouts restart myapp-dev -n dev +``` + +### Status Check + +```bash +kubectl get rollout -n dev +kubectl get rs -n dev +kubectl get pods -n dev +``` + +--- + +## 6. Observations + +* Canary rollout successfully performed with step-based traffic shifting +* Blue-green deployment verified via preview service +* Rollback operations are instant and reliable +* Argo Rollouts dashboard clearly visualizes deployment state +* System remains stable during all transitions + +--- + +## Conclusion + +Argo Rollouts provides safe progressive delivery mechanisms: + +* Canary → gradual rollout with controlled exposure +* Blue-Green → instant switching between environments + +Both strategies were successfully implemented and tested in the cluster. \ No newline at end of file diff --git a/k8s/myapp/files/config.json b/k8s/myapp/files/config.json index 308fef17a2..a582228e05 100644 --- a/k8s/myapp/files/config.json +++ b/k8s/myapp/files/config.json @@ -1,6 +1,6 @@ { "appName": "devops-info-service", - "environment": "dev", + "environment": "dev-v2", "featureFlags": { "enableVisits": true } diff --git a/k8s/myapp/templates/deployment.yaml b/k8s/myapp/templates/rollout-bluegreen.yaml similarity index 84% rename from k8s/myapp/templates/deployment.yaml rename to k8s/myapp/templates/rollout-bluegreen.yaml index 1a4d511179..50272746d1 100644 --- a/k8s/myapp/templates/deployment.yaml +++ b/k8s/myapp/templates/rollout-bluegreen.yaml @@ -1,23 +1,27 @@ -apiVersion: apps/v1 -kind: Deployment +apiVersion: argoproj.io/v1alpha1 +kind: Rollout metadata: name: {{ include "myapp.fullname" . }} spec: replicas: {{ .Values.replicaCount }} + selector: matchLabels: app: {{ include "myapp.name" . }} + template: metadata: labels: app: {{ include "myapp.name" . }} annotations: checksum/config: {{ include (print $.Template.BasePath "/configmap-file.yaml") . | sha256sum }} + spec: volumes: - name: config-volume configMap: name: {{ include "myapp.fullname" . }}-config + - name: data-volume persistentVolumeClaim: claimName: {{ include "myapp.fullname" . }}-data @@ -50,4 +54,11 @@ spec: path: / port: {{ .Values.service.targetPort }} initialDelaySeconds: 5 - periodSeconds: 3 \ No newline at end of file + periodSeconds: 3 + + strategy: + blueGreen: + activeService: {{ include "myapp.fullname" . }} + previewService: {{ include "myapp.fullname" . }}-preview + + autoPromotionEnabled: false \ No newline at end of file diff --git a/k8s/myapp/templates/rollout.yaml b/k8s/myapp/templates/rollout.yaml new file mode 100644 index 0000000000..f6db9b4a06 --- /dev/null +++ b/k8s/myapp/templates/rollout.yaml @@ -0,0 +1,72 @@ +apiVersion: argoproj.io/v1alpha1 +kind: Rollout +metadata: + name: {{ include "myapp.fullname" . }} +spec: + replicas: {{ .Values.replicaCount }} + revisionHistoryLimit: 10 + + selector: + matchLabels: + app: {{ include "myapp.name" . }} + + template: + metadata: + labels: + app: {{ include "myapp.name" . }} + annotations: + checksum/config: {{ include (print $.Template.BasePath "/configmap-file.yaml") . | sha256sum }} + spec: + volumes: + - name: config-volume + configMap: + name: {{ include "myapp.fullname" . }}-config + - name: data-volume + persistentVolumeClaim: + claimName: {{ include "myapp.fullname" . }}-data + + containers: + - name: app + image: "{{ .Values.image.repository }}:{{ .Values.image.tag }}" + ports: + - containerPort: {{ .Values.service.targetPort }} + + envFrom: + - configMapRef: + name: {{ include "myapp.fullname" . }}-env + + volumeMounts: + - name: config-volume + mountPath: /config + - name: data-volume + mountPath: /data + + livenessProbe: + httpGet: + path: / + port: {{ .Values.service.targetPort }} + initialDelaySeconds: 10 + periodSeconds: 5 + + readinessProbe: + httpGet: + path: / + port: {{ .Values.service.targetPort }} + initialDelaySeconds: 5 + periodSeconds: 3 + + strategy: + canary: + steps: + - setWeight: 20 + - pause: {} + - setWeight: 40 + - pause: + duration: 30s + - setWeight: 60 + - pause: + duration: 30s + - setWeight: 80 + - pause: + duration: 30s + - setWeight: 100 \ No newline at end of file diff --git a/k8s/myapp/templates/service-preview.yaml b/k8s/myapp/templates/service-preview.yaml new file mode 100644 index 0000000000..a86e76c04a --- /dev/null +++ b/k8s/myapp/templates/service-preview.yaml @@ -0,0 +1,13 @@ +apiVersion: v1 +kind: Service +metadata: + name: {{ include "myapp.fullname" . }}-preview +spec: + type: {{ .Values.service.type }} + + selector: + app: {{ include "myapp.name" . }} + + ports: + - port: {{ .Values.service.port }} + targetPort: {{ .Values.service.targetPort }} \ No newline at end of file diff --git a/k8s/myapp/values-dev.yaml b/k8s/myapp/values-dev.yaml index 7560359274..15c25f18ad 100644 --- a/k8s/myapp/values-dev.yaml +++ b/k8s/myapp/values-dev.yaml @@ -14,7 +14,7 @@ persistence: enabled: true size: 100Mi -environment: dev +environment: dev-v2 secrets: username: admin