Skip to content

Commit

Permalink
케이스 7
Browse files Browse the repository at this point in the history
  • Loading branch information
uniglot committed Aug 7, 2024
1 parent ac51354 commit e5c8905
Show file tree
Hide file tree
Showing 33 changed files with 726 additions and 348 deletions.
50 changes: 50 additions & 0 deletions .github/workflows/deploy.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
name: Deploy

on:
release:
types:
- published

jobs:
build-and-push:
runs-on: ubuntu-latest

steps:
- uses: actions/checkout@v3

- name: Configure AWS credentials
uses: aws-actions/configure-aws-credentials@v2
with:
aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }}
aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
aws-region: ap-northeast-2

- name: Login to Amazon ECR
id: login-ecr
uses: aws-actions/amazon-ecr-login@v1
with:
mask-password: "true"

- name: Build and Push Container Image
env:
REGISTRY: ${{ steps.login-ecr.outputs.registry }}
IMAGE_NAME: fastcampus-app-image
run: |
SHA_SHORT=$(git rev-parse --short HEAD)
docker build -t $REGISTRY/$IMAGE_NAME:$SHA_SHORT .
docker push $REGISTRY/$IMAGE_NAME:$SHA_SHORT
- name: Create kube-config and install Helm
run: |
aws eks --region ap-northeast-2 update-kubeconfig --name fastcampus-infra-cluster
curl https://raw.githubusercontent.com/helm/helm/main/scripts/get-helm-3 | bash
- name: Install production Helm chart
env:
DATABASE_HOST: ${{ secrets.DATABASE_HOST }}
run: |
helm upgrade --install fastcampus-prod chart \
-f helm-prod-values.yaml \
--set workload.image.tag="$(git rev-parse --short HEAD)" \
--set workload.databaseHost="${{ secrets.DATABASE_HOST }}" \
--set common.awsAccount="$(aws sts get-caller-identity --query Account --output text)"
3 changes: 2 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -209,4 +209,5 @@ terraform.rc

# End of https://www.toptal.com/developers/gitignore/api/django,terraform

.DS_Store
.DS_Store
.vscode
16 changes: 16 additions & 0 deletions COE.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
# 장애 보고서 (타임라인까지)

## 장애 상황 요약

## 장애의 영향 범위

### 고객 영향

### 비기능적 요구사항

- 가용성 조건
- 비용 조건

## 장애 상황 타임라인

- [00:00]
11 changes: 6 additions & 5 deletions Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,12 @@ ENV PYTHONBUFFERED=1 \
PYTHONDONTWRITEBYTECODE=1

RUN apt-get update && apt-get install -y \
gcc \
g++ \
pkg-config \
build-essential \
libpq-dev \
default-libmysqlclient-dev \
default-mysql-client \
&& rm -rf /var/lib/apt/lists/*

WORKDIR /app
Expand All @@ -33,7 +37,4 @@ COPY --from=builder /usr/local/bin /usr/local/bin
COPY --from=builder /usr/local/lib/python3.12/site-packages /usr/local/lib/python3.12/site-packages
COPY ./application /app

ARG DJANGO_SETTINGS
ENV DJANGO_SETTINGS=$DJANGO_SETTINGS

CMD [ "/bin/bash", "-c", "python manage.py migrate && gunicorn config.wsgi:application --bind 0.0.0.0:8000"]
CMD [ "/bin/bash", "-c", "python manage.py migrate && gunicorn config.wsgi:application -w 4 -b 0.0.0.0:8000"]
76 changes: 57 additions & 19 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,32 +1,70 @@
# Fastcampus - System Designs with Anti-Patterns
# Fast Campus - 실전 장애 케이스 8가지 실습과 보고서 작성

## Instruction
> [!CAUTION]
> 본 프로젝트의 시스템 구성에는 교육 목적을 위한 의도적인 결함이 존재합니다.
> This project presents a system with deliberate flaws for educational purposes.
### Preliminary
## 준비 사항

1. Create your AWS credentials and store them safely.
2. Create a file named `secrets.tfvars` inside the directory `infrastructure`.
3. Fill the file as below:
1. AWS 액세스 키와 시크릿 키를 발급받아 안전하게 보관하세요.
2. `secrets.tfvars` 라는 이름의 파일을 `infrastructure` 디렉토리 안에 생성하세요.
3. 해당 파일에 아래와 같이 채워 주세요.
```
aws_access_key = "YOURAWSACCESSKEY"
aws_secret_key = "YOURAWSSECRETACCESSKEY"
```
4. Move inside the `infrastructure` directory and enter `terraform init` in your terminal.
4. 터미널에서 `infrastructure` 디렉토리로 이동한 뒤 `terraform init`을 입력하세요.
### Terraform plan and apply
## 테라폼 플래닝 및 인프라 적용
- To plan the infrastructure definitions, enter `terraform plan -var-file=secrets.tfvars` inside the terraform root.
- To apply the plan results, issue the command `terraform apply -var-file=secrets.tfvars`.
- 테라폼 코드를 플래닝하여 인프라가 어떻게 생성될지 보려면, `terraform plan -var-file=secrets.tfvars` 커맨드를 `infrastructure` 디렉토리에서 실행하세요.
- 실제로 테라폼 코드를 적용하여 인프라를 생성 또는 수정하고자 한다면, `terraform apply -var-file=secrets.tfvars` 커맨드를 `infrastructure` 디렉토리에서 실행하세요.
- 약 20분 내외 소요됩니다.
### Access the EKS cluster
## EKS 클러스터 접속
1. Install AWS CLI and kubectl.
2. Register your AWS credentials as a profile in your AWS CLI configuration file.
3. Enter `aws eks --region ap-northeast-2 update-kubeconfig --name fc-sre-cluster` to register your cluster to the `kubectl` configuration.
- If you're using a profile other than the default profile, you should append `--profile your-profile` on the command above.
4. Enter `kubectl config use-context arn:aws:eks:ap-northeast-2:1234567890:cluster/fc-sre-cluster` (change `1234567890` to your account ID).
5. Check `kubectl get nodes`
1. AWS CLI, `kubectl`, `helm`, `k9s`를 설치하세요.
2. `aws configure --profile fastcampus` 커맨드를 실행하여 AWS 액세스 키와 시크릿 키를 AWS CLI에서 사용하도록 설정하세요.
3. 터미널에서 `aws eks --region ap-northeast-2 update-kubeconfig --name fastcampus-infra-cluster --profile fastcampus`를 실행하여 `kubectl`을 통해 생성한 클러스터에 접근할 수 있도록 합니다.
4. 터미널에서 `kubectl config use-context arn:aws:eks:ap-northeast-2:1234567890:cluster/fastcampus-infra-cluster`을 실행해서 현재 쿠버네티스 컨텍스트를 생성한 클러스터를 바라보게 합니다. (`1234567890`을 본인의 계정 ID로 바꿔주세요.)
5. `kubectl get pods -n kube-system` 커맨드를 실행해 파드들이 정상적으로 출력되는지 확인해 주세요.
### Destroying resources
## 인프라 제거
To destory all the resources that have been provisioned, make sure issuing `terraform destroy -var-file=secrets.tfvars`.
1. 쿠버네티스 클러스터에 설치된 모든 자원을 제거하기 위해서, `helm uninstall fastcampus-prod` 커맨드를 입력해 주세요.
2. 프로비저닝된 모든 인프라를 제거하기 위해서, 터미널에서 `terraform destroy -var-file=secrets.tfvars` 커맨드를 입력해 주세요.
- 약 10분 내외 소요됩니다.
3. RDS 콘솔에서 스냅샷과 PITR로 생성된 데이터베이스 인스턴스를 수동으로 삭제해 주세요.
4. RDS 콘솔 > Snapshots > Manual 에서 RDS 스냅샷을 삭제해 주세요.
5. 로컬 `kubectl` 설정 파일을 정리하기 위해서, 아래의 커맨드를 입력해 주세요.
- `kubectl config delete-context arn:aws:eks:ap-northeast-2:1234567890:cluster/fastcampus-infra-cluster` (`1234567890`을 본인의 계정 ID로 바꿔주세요.)
- `kubectl config delete-cluster arn:aws:eks:ap-northeast-2:1234567890:cluster/fastcampus-infra-cluster`
- `kubectl config delete-user arn:aws:eks:ap-northeast-2:1234567890:cluster/fastcampus-infra-cluster`
## 문제 해결
### VPC가 마지막에 다음과 같이 정확하게 삭제되지 않는 경우가 있습니다.
실습 도중 테라폼으로 보안그룹이 추적되지 않은 경우가 발생했을 때 이런 현상이 발생할 수 있습니다.
![problem-vpc-terraform](https://assets.uniglot.dev/images/problem-vpc-terraform.png)
이럴 때는 콘솔에서 VPC를 아래와 같이 수동으로 삭제해 주시면 됩니다.
![problem-vpc-console](https://assets.uniglot.dev/images/problem-vpc-console.png)
### 테라폼 제거 과정에서 Helm 관련하여 에러가 뜨면서 제거가 되지 않습니다.
아래와 같이 쿠버네티스 서비스 어카운트나 헬름 관련으로 테라폼 에러가 발생하는 경우가 있습니다.
![problem-eks-terraform](https://assets.uniglot.dev/images/problem-eks-terraform.png)
이 경우 테라폼 관리 대상에서 쿠버네티스와 헬름을 제거하면 됩니다. 테라폼으로 쿠버네티스나 헬름 자원을 제거하지 않더라도 쿠버네티스 클러스터가 제거되면서 자연스럽게 함께 제거됩니다.
- `infrastructure/eks.tf`에서 `resource "kubernetes_service_account"`와 `resource "helm_release"`로 되어 있는 블럭을 모두 주석으로 처리해 주세요.
- 주석으로 처리한 리소스 타입과 이름을 참조해서 아래와 같이 모든 자원의 상태를 제거해 주세요.
```bash
terraform state rm kubernetes_service_account.lb_controller_sa
terraform state rm helm_release.aws_load_balancer_controller
```
- 그 다음 다시 `terraform destroy -var-file=secrets.tfvars`를 입력해 주세요.
17 changes: 16 additions & 1 deletion application/config/settings/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@
# SECURITY WARNING: don't run with debug turned on in production!
DEBUG = True

ALLOWED_HOSTS = []
ALLOWED_HOSTS = ["*"]


# Application definition
Expand All @@ -50,6 +50,11 @@
'django.middleware.clickjacking.XFrameOptionsMiddleware',
]

REST_FRAMEWORK = {
'DEFAULT_PAGINATION_CLASS': 'rest_framework.pagination.PageNumberPagination',
'PAGE_SIZE': 10,
}

ROOT_URLCONF = 'config.urls'

TEMPLATES = [
Expand Down Expand Up @@ -81,6 +86,16 @@
}
}

CACHES = {
"default": {
"BACKEND": "django_redis.cache.RedisCache",
"LOCATION": "redis://localhost:6379/0",
"OPTIONS": {
"CLIENT_CLASS": "django_redis.client.DefaultClient",
},
}
}


# Password validation
# https://docs.djangoproject.com/en/4.2/ref/settings/#auth-password-validators
Expand Down
27 changes: 20 additions & 7 deletions application/config/settings/prod.py
Original file line number Diff line number Diff line change
@@ -1,15 +1,28 @@
import os

DEBUG = False

ALLOWED_HOSTS = ["*"]

DATABASES = {
"default": {
"ENGINE": "django.db.backends.postgresql",
"NAME": os.environ.get("DATABASE_NAME"),
"USER": os.environ.get("DATABASE_USER"),
"PASSWORD": os.environ.get("DATABASE_PASSWORD"),
"ENGINE": "django.db.backends.mysql",
"NAME": "sample",
"USER": "fastcampus",
"PASSWORD": "supersecretpassword",
"HOST": os.environ.get("DATABASE_HOST"),
"PORT": "3306",
"CONN_MAX_AGE": 300,
}
}

CACHES = {
"default": {
"BACKEND": "django_redis.cache.RedisCache",
"LOCATION": "redis://redis-master.default.svc.cluster.local:6379/0",
"OPTIONS": {
"CLIENT_CLASS": "django_redis.client.DefaultClient",
"PASSWORD": "supersecretpassword",
"SOCKET_TIMEOUT": 3,
"SOCKET_CONNECT_TIMEOUT": 3,
},
}
}
}
9 changes: 8 additions & 1 deletion application/config/urls.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,10 +17,17 @@
from django.contrib import admin
from django.urls import path

from lectures.views import LectureView, LectureRegisterView
from lectures.views import (
LectureDetailView,
LectureView,
LectureRegisterView,
RandomLectureRegisterView,
)

urlpatterns = [
path('admin/', admin.site.urls),
path('lectures/', LectureView.as_view()),
path('lectures/<int:lecture_id>/', LectureDetailView.as_view()),
path('lectures/register/', LectureRegisterView.as_view()),
path('lectures/random/', RandomLectureRegisterView.as_view()),
]
Loading

0 comments on commit e5c8905

Please sign in to comment.