File size: 9,433 Bytes
c3d82b0
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
---
title: My Gradio App Mnist Classifier
emoji: 🚀
colorFrom: blue
colorTo: green
sdk: gradio
sdk_version: "5.7.1"
app_file: app.py
pinned: false
---

# aws_ec2_automation
Here’s a detailed explanation of the GitHub Actions (GHA) pipeline in **raw Markdown format**:

---

# GitHub Actions Pipeline Documentation

## Name: Deploy PyTorch Training with EC2 Runner and Docker Compose

This pipeline automates the following tasks:
1. Starts an EC2 instance as a self-hosted GitHub runner.
2. Deploys a PyTorch training pipeline using Docker Compose.
3. Builds, tags, and pushes Docker images to Amazon ECR.
4. Stops the EC2 instance after the job is completed.

---

### Workflow Triggers

```yaml
on:
  push:
    branches:
      - main
```

- **Trigger**: This workflow runs whenever a push is made to the `main` branch.

---

## Jobs Overview

### 1. **start-runner**
Starts a self-hosted EC2 runner using the GitHub Actions Runner.

#### Steps:
1. **Configure AWS Credentials**:
   ```yaml
   - name: Configure AWS credentials
     uses: aws-actions/configure-aws-credentials@v4
     with:
       aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }}
       aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
       aws-region: ${{ secrets.AWS_REGION }}
   ```
   - Authenticates with AWS using access keys and the region specified in the secrets.
   - Required for creating and managing the EC2 instance.

2. **Start EC2 Runner**:
   ```yaml
   - name: Start EC2 runner
     id: start-ec2-runner
     uses: machulav/ec2-github-runner@v2
     with:
       mode: start
       github-token: ${{ secrets.GH_PERSONAL_ACCESS_TOKEN }}
       ec2-image-id: ami-044b0717aadbc9dfa
       ec2-instance-type: t2.xlarge
       subnet-id: subnet-024811dee81325f1c
       security-group-id: sg-0646c2a337a355a31
   ```
   - Starts an EC2 instance with the specified AMI, instance type, subnet, and security group.
   - Outputs:
     - `label`: A unique label for the EC2 runner.
     - `ec2-instance-id`: The ID of the created EC2 instance.

---

### 2. **deploy**
Deploys the PyTorch training pipeline using the EC2 runner started in the previous step.

#### Dependencies:
```yaml
needs: start-runner
runs-on: ${{ needs.start-runner.outputs.label }}
```
- **Depends on** the `start-runner` job and runs on the newly created EC2 instance.

#### Steps:
1. **Checkout Repository**:
   ```yaml
   - name: Checkout repository
     uses: actions/checkout@v4
   ```
   - Clones the current repository to the runner.

2. **Set Up Docker Buildx**:
   ```yaml
   - name: Set up Docker Buildx
     uses: docker/setup-buildx-action@v3
   ```
   - Configures Docker Buildx for building multi-platform Docker images.

3. **Configure AWS Credentials**:
   ```yaml
   - name: Configure AWS credentials
     uses: aws-actions/configure-aws-credentials@v4
     with:
       aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }}
       aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
       aws-region: ${{ secrets.AWS_REGION }}
   ```
   - Reconfigures AWS credentials for Docker ECR authentication and resource management.

4. **Log in to Amazon ECR**:
   ```yaml
   - name: Log in to Amazon ECR
     id: login-ecr
     uses: aws-actions/amazon-ecr-login@v2
   ```
   - Logs into Amazon ECR for pushing and pulling Docker images.

5. **Create `.env` File**:
   ```yaml
   - name: Create .env file
     run: |
       echo "AWS_ACCESS_KEY_ID=${{ secrets.AWS_ACCESS_KEY_ID }}" >> .env
       echo "AWS_SECRET_ACCESS_KEY=${{ secrets.AWS_SECRET_ACCESS_KEY }}" >> .env
       echo "AWS_REGION=${{ secrets.AWS_REGION }}" >> .env
   ```
   - Generates a `.env` file for the application with AWS credentials and region.

6. **Run Docker Compose for Train and Eval Services**:
   ```yaml
   - name: Run Docker Compose for train and eval service
     run: |
       docker-compose build
       docker-compose up --build
       docker-compose logs --follow
       docker-compose down --remove-orphans
   ```
   - **Build**: Builds all services defined in the `docker-compose.yml` file.
   - **Up**: Runs all services, including training and evaluation.
   - **Logs**: Outputs logs for debugging purposes.
   - **Down**: Stops all services and removes orphaned containers.

7. **Build, Tag, and Push Docker Image to Amazon ECR**:
   ```yaml
   - name: Build, tag, and push Docker image to Amazon ECR
     env:
       REGISTRY: ${{ steps.login-ecr.outputs.registry }}
       REPOSITORY: soutrik71/mnist
       IMAGE_TAG: ${{ github.sha }}
     run: |
       docker build -t $REGISTRY/$REPOSITORY:$IMAGE_TAG .
       docker push $REGISTRY/$REPOSITORY:$IMAGE_TAG
       docker tag $REGISTRY/$REPOSITORY:$IMAGE_TAG $REGISTRY/$REPOSITORY:latest
       docker push $REGISTRY/$REPOSITORY:latest
   ```
   - **Build**: Creates a Docker image with the repository and tag.
   - **Push**: Pushes the image to Amazon ECR.
   - **Tag**: Updates the `latest` tag.

8. **Pull and Verify Docker Image from ECR**:
   ```yaml
   - name: Pull Docker image from ECR and verify
     env:
       REGISTRY: ${{ steps.login-ecr.outputs.registry }}
       REPOSITORY: soutrik71/mnist
       IMAGE_TAG: ${{ github.sha }}
     run: |
       docker pull $REGISTRY/$REPOSITORY:$IMAGE_TAG
       docker images | grep "$REGISTRY/$REPOSITORY"
   ```
   - **Pull**: Pulls the built image from ECR.
   - **Verify**: Ensures the image exists locally.

9. **Clean Up Environment**:
   ```yaml
   - name: Clean up environment
     run: |
       rm -f .env
       docker system prune -af
   ```
   - Deletes the `.env` file and removes unused Docker resources.

---

### 3. **stop-runner**
Stops and terminates the EC2 runner created in the `start-runner` job.

#### Dependencies:
```yaml
needs:
  - start-runner
  - deploy
```

#### Steps:
1. **Configure AWS Credentials**:
   ```yaml
   - name: Configure AWS credentials
     uses: aws-actions/configure-aws-credentials@v4
     with:
       aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }}
       aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
       aws-region: ${{ secrets.AWS_REGION }}
   ```

2. **Stop EC2 Runner**:
   ```yaml
   - name: Stop EC2 runner
     uses: machulav/ec2-github-runner@v2
     with:
       mode: stop
       github-token: ${{ secrets.GH_PERSONAL_ACCESS_TOKEN }}
       label: ${{ needs.start-runner.outputs.label }}
       ec2-instance-id: ${{ needs.start-runner.outputs.ec2-instance-id }}
   ```
   - Stops the EC2 runner instance created in the first job.

3. **Validate EC2 Termination**:
   ```yaml
   - name: Validate EC2 termination
     run: aws ec2 describe-instances --instance-ids ${{ needs.start-runner.outputs.ec2-instance-id }}
   ```
   - Ensures the EC2 instance has been properly terminated.

---

### Key Highlights
1. **Sequential Execution**:
   - The `start-runner`, `deploy`, and `stop-runner` jobs are executed sequentially.

2. **Error Handling**:
   - The `stop-runner` job runs even if previous jobs fail (`if: ${{ always() }}`).

3. **Efficiency**:
   - Docker layer caching speeds up builds.
   - Cleanup steps maintain a clean environment.

4. **Security**:
   - Secrets are masked and removed after use.
   - Proper resource cleanup ensures cost efficiency.

---

This pipeline ensures robust deployment with error handling, logging, and cleanup mechanisms. So far we have discussed the GitHub Actions pipeline , the basic structure of the pipeline, and the steps involved in the pipeline.
Next we will have an interdependent pipeline where the output of one job will be used as input for the next job.

---
## Advanced Pipeline with 
* Sequential Flow: Each job has clear dependencies, ensuring no step runs out of order.
* Code Checkout: Explicit repository checkout in each job ensures consistent source code.
* Secure Credential Handling: Sensitive credentials are masked and stored securely.
* Resource Cleanup: Includes Docker clean-up and EC2 instance termination validation.
* Logging: Added detailed logs to improve debugging and monitoring.


Step 1: Start EC2 Runner
  Purpose: Initializes a self-hosted EC2 runner for running subsequent jobs.
  Key Actions:
  Configures AWS credentials.
  Launches an EC2 instance using specified AMI, instance type, and networking configurations.
  Outputs the runner label and instance ID for downstream jobs.
Step 2: Test PyTorch Code Using Docker Compose
  Purpose: Tests the PyTorch training and evaluation services.
  Key Actions:
  Checks out the repository.
  Sets up Docker Buildx for advanced build capabilities.
  Configures AWS credentials and creates a masked .env file for secure credential sharing.
  Runs all services (train, eval) using Docker Compose, monitors logs, and cleans up containers.
Step 3: Build, Tag, and Push Docker Image
  Purpose: Builds a Docker image, tags it, and pushes it to Amazon ECR after successful tests.
  Key Actions:
  Checks out the repository again to ensure consistency.
  Logs into Amazon ECR using AWS credentials.
  Builds and tags the Docker image with latest and SHA-based tags.
  Pushes the image to Amazon ECR and verifies by pulling it back.
Step 4: Stop and Delete EC2 Runner
  Purpose: Stops and terminates the EC2 instance to ensure cost efficiency and cleanup.
  Key Actions:
  Configures AWS credentials.
  Stops the EC2 instance using the label and instance ID from start-runner.
  Validates the termination state of the EC2 instance to ensure proper cleanup.