Commit 77558cf7 authored by Muhammad Umair Khan's avatar Muhammad Umair Khan
Browse files

fix ansible idempotentency and roles

parent 5c109fd8
Loading
Loading
Loading
Loading
+2 −1
Original line number Diff line number Diff line
@@ -3,3 +3,4 @@ skip_list: # rules to skip
  - name
  - risky-shell-pipe
  - role-name[path]
  - var-naming[no-role-prefix]
 No newline at end of file
+188 −141
Original line number Diff line number Diff line
# ETSI MEC Sandbox Ansible Setup

This folder provides an **Ansible-based automation framework** to set up a multi-node Kubernetes cluster for ETSI MEC Sandbox.
This folder provides an **Ansible-based automation framework** to set up a multi-node Kubernetes cluster and deploy the ETSI MEC Sandbox platform.

---

@@ -10,6 +10,10 @@ Before running the playbooks, ensure:

1. You have **Ansible** installed on your control machine.
2. You have **SSH access** to all remote nodes (master & workers, if applicable).
3. Both repositories are cloned as siblings in the same parent directory:
   - `etsi-mec-sandbox` (backend)
   - `etsi-mec-sandbox-frontend` (frontend)
4. You have a **GitHub OAuth application** configured (Client ID & Secret for MEC Sandbox authentication).

   > **Note:** If your playbooks are running on `localhost` (control machine itself), **SSH is not required**. SSH setup is only necessary for remote worker or master nodes.  

@@ -30,7 +34,7 @@ ssh-copy-id -i ~/.ssh/id_ed25519.pub <your-username>@<remote-host-ip>
## Folder Structure

```
mec-sandbox-ansible-best-practices-multinode/
playbooks/
├── ansible.cfg                # Ansible configuration
├── requirements.yml           # External role/collection dependencies
├── site.yml                   # Main playbook entrypoint
@@ -50,9 +54,12 @@ mec-sandbox-ansible-best-practices-multinode/
    │   ├── master/            # Master node setup (API server, etcd, controller)
    │   └── worker/            # Worker node join configuration
    ├── helm/                  # Install Helm package manager
    └── dev_env/
        ├── golang/            # Install Go environment
        └── node/              # Install Node.js environment (via NVM)
    ├── dev_env/
    │   ├── golang/            # Install Go environment
    │   └── node/              # Install Node.js environment (via NVM)
    └── mec_sandbox/
        ├── mec_config/        # Configure MEC Sandbox (charts, secrets, OAuth)
        └── mec_deploy/        # Build & deploy MEC Sandbox (meepctl, frontend, core)
```

---
@@ -60,23 +67,32 @@ mec-sandbox-ansible-best-practices-multinode/
## Roles & Tasks Overview

| Role                         | Purpose                                              |
| --------------------- | --------------------------------------- |
| ---------------------------- | ---------------------------------------------------- |
| **common**                   | Base system setup and dependencies                   |
| **kernel**                   | Kernel modules, sysctl, network tuning               |
| **containerd**               | Install & configure containerd runtime               |
| **docker**            | Optional Docker setup & configuration   |
| **cni\_calico**       | Deploy Calico networking                |
| **docker**                   | Docker runtime setup & daemon configuration          |
| **cni\_calico**              | Deploy Calico CNI networking                         |
| **kubernetes/common**        | Install kubeadm, kubelet, kubectl                    |
| **kubernetes/master**        | Initialize master & control-plane setup              |
| **kubernetes/worker**        | Join worker nodes (requires SSH)                     |
| **helm**                     | Install Helm for package management                  |
| **dev\_env/golang**   | Setup Go development environment        |
| **dev\_env/node**     | Setup Node.js/NVM environment           |
| **dev\_env/golang**          | Setup Go development environment (conditional)       |
| **dev\_env/node**            | Setup Node.js/NVM environment (conditional)          |
| **mec\_sandbox/mec\_config** | Configure MEC Sandbox charts, secrets & OAuth        |
| **mec\_sandbox/mec\_deploy** | Build & deploy MEC Sandbox (meepctl, frontend, core) |

---

## Running the Playbooks

### Interactive Prompts

When running the playbook, you will be prompted for:
- **Sudo password** for privilege escalation
- **MEC host IP/domain** (e.g., `192.168.1.100` or `mec.example.com`)
- **GitHub OAuth Client ID** and **Client Secret**

### Worker Nodes (Optional)

If you want to add worker nodes to your cluster, you need to **uncomment both the inventory entries and the worker play in `site.yml`**.
@@ -123,19 +139,50 @@ ansible-playbook -i inventories/dev/hosts.ini site.yml -K

## Variables

* `container_runtime`: `"containerd"` (default) or `"docker"`
* `kube_version`: `"1.29.*"`
* `pod_network_cidr`: `"192.168.0.0/16"`
### Kubernetes & Container Runtime
* `kubernetes_version`: `"v1.35"`
* `pod_network_cidr`: `"92.68.0.0/16"`
* `service_cidr`: `"10.96.0.0/12"`
* `calico_version`: `"v3.30.0"`

### Development Environment
* `install_dev_env`: `true` → set to `false` to disable Node/Go tooling
* `go_version`: `"1.17"`
* `node_version`: `"12.19.0"`

### MEC Sandbox
* `install_mec_sandbox`: `true` → set to `false` to skip MEC Sandbox deployment
* `mec_sandbox_dir`: Path to the etsi-mec-sandbox repository
* `mec_frontend_dir`: Path to the etsi-mec-sandbox-frontend repository

## Tags

You can run just parts of the setup with `--tags` or skip parts with `--skip-tags`. (The roles here are intentionally simple and do not define custom tags; feel free to add them if you want finer control.)

## MEC Sandbox Role Details

### mec_sandbox/mec_config
Configures the MEC Sandbox environment:
- Patches chart security contexts (uid/gid 1001 → 1000)
- Updates GitHub OAuth credentials in secrets
- Configures ingress host address
- Adds Kubernetes CA to system trust store

### mec_sandbox/mec_deploy
Builds and deploys MEC Sandbox components:
1. Installs `meepctl` CLI tool
2. Configures meepctl with IP and gitdir
3. Builds and deploys frontend
4. Deploys dependencies (`meepctl deploy dep`)
5. Builds all components (`meepctl build --nolint all`)
6. Dockerizes all components (`meepctl dockerize all`)
7. Deploys core (`meepctl deploy core`)

## Notes

* Ensure worker nodes have SSH access configured before running.
* Use `--tags` if you want to run specific roles (e.g. `--tags kubernetes,helm`).
* The MEC Sandbox roles require both `etsi-mec-sandbox` and `etsi-mec-sandbox-frontend` repositories to be present as siblings.
* Thanos/Prometheus deployment failures during `deploy dep` are expected and ignored.

---
+156 −53
Original line number Diff line number Diff line
# MEC Sandbox Ansible Deployment Guide

## Prerequisites

### 1. Generate GitHub OAuth App Client ID & Secret

The MEC Sandbox uses GitHub OAuth for authentication. You need to register an OAuth App in your GitHub account's Developer Settings to obtain a **Client ID** and **Client Secret**.

**Steps:**

1. Log in to [GitHub](https://github.com) and go to your account **Settings**.
2. In the left sidebar, scroll down and click **Developer settings**.
3. Click **OAuth Apps****New OAuth App**.
4. Fill in the application details:
   - **Application name**: e.g., `MEC Sandbox`
   - **Homepage URL**: e.g., `https://<VM_IP>` (or Deployment URL or VM IP)
   - **Authorization callback URL**: e.g., `https://<VM_IP>/platform-ctrl/v1/authorize`
5. Click **Register application**.
6. On the next page, note down your **Client ID**.
7. Click **Generate a new client secret** and copy the **Client Secret** immediately (it is only shown once).

```yaml
github_oauth_client_id: "<your-client-id>"
github_oauth_client_secret: "<your-client-secret>"
```

> **Important:** You will need the GitHub OAuth credentials for the playbook so that the MEC Sandbox can be deployed and configured properly.
This runbook provides step-by-step instructions for deploying the ETSI MEC Sandbox platform using Ansible.

---

### 2. Navigate to the Playbooks Folder

All Ansible commands must be run from within the `playbooks` directory. Navigate there first:
## Prerequisites

```bash
cd /home/<your-username>/etsi-mec-sandbox/playbooks
```
Before running the playbooks, ensure you have:

> Replace `<your-username>` with your actual Linux username. All subsequent commands in this guide assume your working directory is `playbooks/`.
1. **Ansible** installed on your control machine
2. **Both repositories** cloned as siblings:
   - `~/etsi-mec-sandbox` (backend)
   - `~/etsi-mec-sandbox-frontend` (frontend)
3. **GitHub OAuth Application** credentials (Client ID & Client Secret)
4. A **target IP address or domain** for your MEC Sandbox installation

---

@@ -61,23 +38,90 @@ ansible_become_method=sudo

---

## Running Playbooks
## Quick Start (Single-Node Deployment)

### Step 1: Install Ansible Collections

1. Install required collections:
```bash
ansible-galaxy collection install -r requirements.yml
```

2. Run site.yml (masters + optional workers):
### Step 2: Run the Playbook

```bash
   ansible-playbook -K -i inventories/dev/hosts.ini site.yml
ansible-playbook -i inventories/dev/hosts.ini site.yml
```

   > `-K` prompts for the sudo password. Omit it if passwordless sudo is configured.
You will be prompted for:
- **Sudo password**: Your local sudo password
- **MEC host address**: IP or domain (e.g., `192.168.1.100` or `mec.example.com`)
- **GitHub OAuth Client ID**: From your GitHub OAuth app
- **GitHub OAuth Client Secret**: From your GitHub OAuth app

3. Single-node cluster: keep `k8s_workers` empty → only master node runs.
### Step 3: Verify Deployment

4. Multi-node cluster: add worker nodes under `[k8s_workers]` in inventory.
After successful completion, access the MEC Sandbox at:
```
https://<your-mec-host-address>
```

---

## Execution Flow

The playbook executes the following roles in order:

| Order | Role                         | Description                                      |
|-------|------------------------------|--------------------------------------------------|
| 1     | common                       | Base packages and system configuration           |
| 2     | kernel                       | Kernel modules and sysctl tuning                 |
| 3     | docker                       | Docker runtime installation and configuration    |
| 4     | kubernetes/master            | Initialize Kubernetes control plane              |
| 5     | cni_calico                   | Deploy Calico CNI networking                     |
| 6     | helm                         | Install Helm package manager                     |
| 7     | dev_env/golang (conditional) | Go development environment                       |
| 8     | dev_env/node (conditional)   | Node.js/NVM environment                          |
| 9     | mec_sandbox/mec_config       | Configure MEC Sandbox (charts, secrets, OAuth)   |
| 10    | mec_sandbox/mec_deploy       | Build and deploy MEC Sandbox components          |

---

## MEC Sandbox Deployment Details

### mec_sandbox/mec_config Role

This role configures the MEC Sandbox environment:

1. **Adds kubectl bash completion** to `.bashrc`
2. **Updates /etc/hosts** with docker registry entry
3. **Copies Kubernetes CA** to system trust store
4. **Patches chart values**:
   - Updates `fsGroup` and `runAsUser` from 1001 → 1000 in:
     - `charts/postgis/values.yaml`
     - `charts/redis/values.yaml`
     - `charts/docker-registry/values.yaml`
5. **Updates GitHub OAuth credentials** in `secrets.yaml`
6. **Updates ingress host address** in `.meepctl-repocfg.yaml`

### mec_sandbox/mec_deploy Role

This role builds and deploys all MEC Sandbox components:

1. **Install meepctl**: Runs `install.sh` from `go-apps/meepctl`
2. **Configure meepctl**:
   ```bash
   meepctl config ip <mec-host-address>
   meepctl config gitdir <sandbox-dir>
   ```
3. **Build & Deploy Frontend**:
   ```bash
   cd etsi-mec-sandbox-frontend && bash build.sh && bash deploy.sh
   ```
4. **Configure Secrets**: Runs `configure-secrets.py`
5. **Deploy Dependencies**: `meepctl deploy dep` (with retries)
6. **Build All**: `meepctl build --nolint all`
7. **Dockerize All**: `meepctl dockerize all`
8. **Deploy Core**: `meepctl deploy core`

---

@@ -86,27 +130,86 @@ ansible_become_method=sudo
If you want to add worker nodes (separate machines), follow these steps:

1. On each worker node prepare SSH access and ensure Ansible can reach them (or run the play locally on that host).
2. Edit `inventories/dev/hosts.ini` and add entries under `[k8s_workers]` like:

2. Edit `inventories/dev/hosts.ini` and add entries under `[k8s_workers]`:
   ```ini
   [k8s_workers]
   worker1 ansible_host=192.168.56.11 ansible_user=ubuntu
   worker2 ansible_host=192.168.56.12 ansible_user=ubuntu
   ```
3. Run the playbook for master first (to initialize control plane and produce join script):

3. Uncomment the worker play in `site.yml`.

4. Run the playbook for master first (to initialize control plane and produce join script):
   ```bash
   ansible-playbook -K -l k8s_masters site.yml
   ```
   After successful run, a join command will be generated on the master at `/tmp/kube_join_cmd.sh`. You can retrieve it with `scp` or `ansible.builtin.fetch`.
4. Copy the `/tmp/kube_join_cmd.sh` to each worker node (e.g., `/tmp/kube_join_cmd.sh`) so that the worker play can use it. Example using scp:
   After successful run, a join command will be generated on the master at `/tmp/kube_join_cmd.sh`.

5. Copy the `/tmp/kube_join_cmd.sh` to each worker node:
   ```bash
   scp /tmp/kube_join_cmd.sh user@worker1:/tmp/kube_join_cmd.sh
   ```
   Alternatively, you can fetch it programmatically in Ansible from master and distribute to workers via a small play/role.
5. Run the worker play:

6. Run the worker play:
   ```bash
   ansible-playbook -K -l k8s_workers site.yml
   ```

**Notes:**
- Worker nodes will only run `common`, `kernel`, `containerd` (or `docker`), and `kubernetes/worker` roles.
- The `kubernetes/worker` role expects a join script (created on master) at `/tmp/kube_join_cmd.sh`. If you prefer, you can expose the master token & CA hash via a secure variable and run `kubeadm join` directly in the role.
 No newline at end of file
---

## Conditional Roles

The following roles can be enabled/disabled via variables in `group_vars/all.yml`:

| Variable             | Default | Description                          |
|----------------------|---------|--------------------------------------|
| `install_dev_env`    | `true`  | Install Go and Node.js environments  |
| `install_mec_sandbox`| `true`  | Configure and deploy MEC Sandbox     |

To skip MEC Sandbox deployment:
```bash
ansible-playbook -i inventories/dev/hosts.ini site.yml -e "install_mec_sandbox=false"
```

---

## Troubleshooting

### Thanos/Prometheus Deployment Failures
During `meepctl deploy dep`, thanos and prometheus failures are **expected and ignored**. The deployment will continue.

### Repository Not Found Errors
Ensure both repositories are cloned as siblings:
```
~/etsi-mec-sandbox/
~/etsi-mec-sandbox-frontend/
```

### Permission Issues (uid/gid 1001)
The `mec_config` role automatically patches chart values from uid/gid 1001 → 1000. If you still encounter issues, verify the patches were applied.

### Docker Group Issues
If dockerize fails, ensure your user is in the docker group:
```bash
sudo usermod -aG docker $USER
newgrp docker
```

---

## Logs

Deployment logs are saved to `/tmp/`:
- `/tmp/meepctl_deploy_dep.log`
- `/tmp/meepctl_build.log`
- `/tmp/meepctl_dockerize.log`
- `/tmp/meepctl_deploy_core.log`

---

## Notes

- Worker nodes will only run `common`, `kernel`, `containerd`, `kubernetes/common`, and `kubernetes/worker` roles.
- The `kubernetes/worker` role expects a join script (created on master) at `/tmp/kube_join_cmd.sh`.
- The MEC Sandbox deployment requires significant resources; ensure adequate CPU, memory, and disk space.
 No newline at end of file
+3 −0
Original line number Diff line number Diff line
collections:
  - name: community.general
  - name: ansible.posix
 No newline at end of file
+15 −6
Original line number Diff line number Diff line
@@ -19,6 +19,7 @@ disable_swap: true

# Container runtime
docker_package_state: present
containerd_version: "1.7.27-1"
containerd_config_path: /etc/containerd/config.toml

# Docker (latest from official repo, no version pin)
@@ -28,22 +29,29 @@ docker_repo_list_path: "/etc/apt/sources.list.d/docker.list"
docker_repo_url: "https://download.docker.com/linux/ubuntu"
docker_repo_component: "stable"
# System facts for repo (calculated dynamically in tasks, but you can override if needed)
docker_repo_arch: "{{ 'amd64' if ansible_architecture == 'x86_64' else 'arm64' if ansible_architecture == 'aarch64' else ansible_architecture }}"
docker_repo_codename: "{{ ansible_lsb.codename | default('jammy') }}"
docker_repo_arch: >-
  {{
    'amd64' if ansible_facts['architecture'] == 'x86_64'
    else 'arm64' if ansible_facts['architecture'] == 'aarch64'
    else ansible_facts['architecture']
  }}
docker_repo_codename: "{{ ansible_facts['lsb']['codename'] | default('jammy') }}"


# Kubernetes
kubernetes_version: "v1.35.1"
kubernetes_repo_apt_key_url: "https://pkgs.k8s.io/core:/stable:/v1.35/deb/Release.key"
kubernetes_repo_apt_entry: "deb [signed-by=/etc/apt/keyrings/kubernetes-apt-keyring.gpg] https://pkgs.k8s.io/core:/stable:/v1.35/deb/ /"
kubernetes_repo_apt_key_url: >-
  https://pkgs.k8s.io/core:/stable:/{{ kubernetes_version }}/deb/Release.key
kubernetes_repo_apt_entry: >-
  deb [signed-by=/etc/apt/keyrings/kubernetes-apt-keyring.gpg]
  https://pkgs.k8s.io/core:/stable:/{{ kubernetes_version }}/deb/ /
kubeadm_cluster_name: "mec-sandbox"
pod_network_cidr: "92.68.0.0/16"
service_cidr: "10.96.0.0/12"
apiserver_advertise_address: "127.0.0.1"

# CNI (Calico)
calico_version: "v3.31.4"
calico_operator_crds_manifest: "https://raw.githubusercontent.com/projectcalico/calico/{{ calico_version }}/manifests/operator-crds.yaml"
calico_version: "v3.30.0"
calico_operator_manifest: "https://raw.githubusercontent.com/projectcalico/calico/{{ calico_version }}/manifests/tigera-operator.yaml"
calico_custom_resources_manifest: "https://raw.githubusercontent.com/projectcalico/calico/{{ calico_version }}/manifests/custom-resources.yaml"

@@ -62,6 +70,7 @@ eslint_version: "5.16.0"
python_packages: [pyyaml]

# MEC Sandbox paths (derived from target_home)
install_mec_sandbox: true
mec_sandbox_dir: "{{ target_home }}/etsi-mec-sandbox"
mec_frontend_dir: "{{ target_home }}/etsi-mec-sandbox-frontend"

Loading