# Configuration Deployments

Source: https://docs.ops0.com/docs/configurations/deployments

Deploy Ansible playbooks or Kubernetes manifests to their targets.

## Deployment Flow

1. **Review** - Check target and options

2. **Dry Run** - Preview changes (optional)

3. **Approval** - Wait for approval (if required)

4. **Execute** - Run playbook or apply manifests

## Deployment Options

Ansible

Limit, Tags, Skip Tags, Check Mode, Diff Mode, Verbose

Kubernetes

Namespace, Dry Run, Prune

## Task Status Colors

| Status | Color | Meaning |
|--------|-------|---------|
| **ok** | Green | Succeeded, no change |
| **changed** | Yellow | Made changes |
| **failed** | Red | Task failed |
| **skipped** | Cyan | Skipped |
| **unreachable** | Red | Host unreachable |

## Deployment Statuses

| Status | Description |
|--------|-------------|
| **Queued** | Waiting to start |
| **Pending Approval** | Awaiting approval |
| **Running** | Executing |
| **Completed** | Success |
| **Failed** | Errors occurred |
| **Cancelled** | Stopped by user |

## Approval Workflow

When a policy attached to the project requires approval before deployment:

### Deployment enters Pending Approval
The deployment is queued but not executed. Approvers are notified via configured alert channels.

### Approver reviews
The approver sees the deployment in the project's deployment history with a **Pending Approval** badge and can review the planned changes.

### Approve or Reject

| Decision | Result |
|----------|--------|
| **Approve** | Deployment proceeds immediately |
| **Reject** | Deployment is cancelled — a rejection reason is required and stored |

**Rejection reason** is stored on the deployment record and visible in deployment history. This creates an audit trail of why a deployment was stopped.

---

## Configuration Drift

After a successful deployment, ops0 records the expected configuration state. Subsequent discovery scans compare live server/cluster state against this expected state. When a discrepancy is found:

- A drift record is created linking the configuration project to the changed resource
- The dashboard drift counter increments
- Drift is visible on the project card and in the compliance dashboard

Run the configuration deployment again to bring the server back to the expected state and resolve the drift.

## Troubleshooting

Unreachable

SSH connection failed. Check server is online, SSH config is correct, and port is open.

Permission Denied

Missing sudo or privileges. Add `become: yes` to playbook or fix permissions.

Module Not Found

Missing Ansible collection. Install required collection and retry.

K8s Apply Error

Validate YAML syntax, check namespace exists, verify RBAC permissions.

## Rollback

Ansible

Create and deploy a rollback playbook, or revert to previous version

Kubernetes

`kubectl rollout undo deployment/name`

Best Practices

• Use Check Mode first - run dry run before real deployment

• Start small - use `--limit` to test on one host

• Use tags - for granular control over which tasks run

• Review output - read full output for issues

• Version control - keep playbooks in Git

---

## Example: Ansible Deployment

### Deployment Configuration

```
Project:     nginx-webserver-setup
Target:      production-web (4 servers)
Options:
  ☑ Check Mode (dry run first)
  ☑ Diff Mode (show changes)
  ☐ Verbose
  Limit:       (none - all servers)
  Tags:        nginx,ssl
```

### Check Mode Output (Dry Run)

```
PLAY [Configure secure nginx web server] *****************************

TASK [Gathering Facts] ***********************************************
ok: [web-1.example.com]
ok: [web-2.example.com]
ok: [web-3.example.com]
ok: [web-4.example.com]

TASK [nginx : Install nginx] *****************************************
ok: [web-1.example.com]
ok: [web-2.example.com]
ok: [web-3.example.com]
ok: [web-4.example.com]

TASK [nginx : Copy nginx configuration] ******************************
changed: [web-1.example.com]
changed: [web-2.example.com]
changed: [web-3.example.com]
changed: [web-4.example.com]

--- /etc/nginx/nginx.conf
+++ /etc/nginx/nginx.conf.new
@@ -23,6 +23,8 @@
+    gzip on;
+    gzip_types text/plain text/css application/json;

TASK [certbot : Obtain SSL certificate] ******************************
changed: [web-1.example.com]
changed: [web-2.example.com]
changed: [web-3.example.com]
changed: [web-4.example.com]

PLAY RECAP ***********************************************************
web-1.example.com  : ok=6  changed=3  unreachable=0  failed=0
web-2.example.com  : ok=6  changed=3  unreachable=0  failed=0
web-3.example.com  : ok=6  changed=3  unreachable=0  failed=0
web-4.example.com  : ok=6  changed=3  unreachable=0  failed=0
```

### Real Deployment Output

```
Deployment #47 - nginx-webserver-setup
Started: 2024-01-15 10:30:00
Status:  Completed
Duration: 2m 34s

Summary:
─────────────────────────────────────
Hosts:     4
OK:        24
Changed:   12
Failed:    0
Skipped:   0
─────────────────────────────────────
```

---

## Example: Kubernetes Deployment

### Deployment Configuration

```
Project:     api-gateway-deploy
Target:      production-eks
Namespace:   api-gateway
Options:
  ☑ Dry Run (server-side)
  ☐ Prune
```

### Dry Run Output

```
namespace/api-gateway created (dry run)
deployment.apps/nodejs-app created (dry run)
service/nodejs-app created (dry run)
horizontalpodautoscaler.autoscaling/nodejs-app-hpa created (dry run)
```

### Real Deployment Output

```
Deployment #23 - api-gateway-deploy
Started: 2024-01-15 14:22:00
Status:  Completed
Duration: 45s

Applied Resources:
─────────────────────────────────────
✓ namespace/api-gateway          created
✓ deployment.apps/nodejs-app     created
✓ service/nodejs-app             created
✓ horizontalpodautoscaler/nodejs-app-hpa created
─────────────────────────────────────

Deployment Rollout:
  Desired:    3
  Updated:    3
  Ready:      3
  Available:  3
```

### Post-Deployment Verification

```
kubectl get pods -n api-gateway

NAME                          READY   STATUS    RESTARTS   AGE
nodejs-app-7d9f8c6b4d-2xkjp   1/1     Running   0          45s
nodejs-app-7d9f8c6b4d-9vwrt   1/1     Running   0          45s
nodejs-app-7d9f8c6b4d-kp3mn   1/1     Running   0          45s

kubectl get hpa -n api-gateway

NAME             REFERENCE               TARGETS   MINPODS   MAXPODS   REPLICAS
nodejs-app-hpa   Deployment/nodejs-app   12%/70%   3         10        3
```
