Search
🏄‍♀️

DevOps[2] github action으로 클라우드 서비스 (Azure)로의 빌드 / 배포 자동화

이 실습은 DevOps[1]에서 이어지는 것이므로 DevOps[1] github actions으로 개발주기 자동화 를 먼저 수행하고 와주세요
이번 실습의 목표는 다음과 같습니다.
목표 : Github Actions를 통해 flask app의 Azure Container Instances에 대한 단일 컨테이너 배포 자동화
앞서 구성했던 flask app의 배포를 자동화합니다.

1. flask app을 구동하기 위한 docker image 생성 및 테스트

이 또한 새로 branch를 만들어 작업합니다. (앞의 글에서 설명한 부분이기에 구체적인 설명은 생략하겠습니다.)
local machine에 docker 환경을 구성(window를 사용하신다면 WSL을 권장합니다)
Dockerfile로 이미지 생성
해당 이미지로 container 실행해 test
이 실습에서 사용한 Dockerfile은 다음과 같습니다.
FROM ubuntu:20.04 COPY . . LABEL "MAINTAINER"="changjoy <ui88g216@gmail.com>" RUN apt-get update && apt-get upgrade -y RUN apt install curl -y RUN apt install python3-pip -y RUN pip3 install flask RUN pip3 install pillow EXPOSE 80 ENTRYPOINT python3 ./core_codes/app.py
Docker
복사
먼저 COPY . .로 현재 Dockerfile이 있는 파일을 docker image의 .로 복사한 다음
ubuntu에서 코드 실행을 위한 패키지 (flask, pillow)를 설치하고 flask 앱 실행 기본 포트인 80을 접근할 수 있도록 열어줬습니다.
그리고 ENTRYPOINT로 컨테이너 생성시 실행될 명령을 설정해주었는데요, flask app 실행 코드인 app.py파일을 실행하도록 했습니다.
이후 docker build . -t [이미지이름] 으로 도커이미지를 만들어주고 다음 명령으로 컨테이너를 실행해줍니다.
docker run -it --name [컨테이너이름] --ipc=host -p 80:80 [이미지이름]
Plain Text
복사
Localhost:80으로 접속했을 때 다음과 같이 뜨면 앱이 잘 구동된 것입니다

2. Azure Container Instance (ACI) 에 빌드 / 배포 자동화 workflow 등록

이제 본격적으로 자동화를 수행해봅시다. ACI에 단일 컨테이너로 배포합니다. 전체적으로 다음 docs의 설명을 따릅니다.
2-1. 먼저 Azure에 가입하고 구독 설정을 완료합니다.
2-2. az cli 설치
2-3. Azure portal에서 (1) 리소스 그룹 생성 (2) container registry 생성
container registry로 도커 컨테이너 이미지를 간편하게 저장, 관리, 배포할 수 있습니다.
2-4. 리소스 그룹의 contributor role 할당받기. 다음 명령어를 수행해서 실행 가능
$ groupId=$(az group show \ --name <resource-group-name> \ --query id --output tsv) $ az ad sp create-for-rbac \ --scope $groupId \ --role Contributor \ --sdk-auth
Plain Text
복사
위 두 명령어를 수행한 후 다음과 같은 json 형태의 결과물이 나옵니다. 이 결과는 이후에 사용되므로 따로 저장해둡니다.
{ "clientId": "xxxx6ddc-xxxx-xxxx-xxx-ef78a99dxxxx", "clientSecret": "xxxx79dc-xxxx-xxxx-xxxx-aaaaaec5xxxx", "subscriptionId": "xxxx251c-xxxx-xxxx-xxxx-bf99a306xxxx", "tenantId": "xxxx88bf-xxxx-xxxx-xxxx-2d7cd011xxxx", "activeDirectoryEndpointUrl": "https://login.microsoftonline.com", "resourceManagerEndpointUrl": "https://management.azure.com/", "activeDirectoryGraphResourceId": "https://graph.windows.net/", "sqlManagementEndpointUrl": "https://management.core.windows.net:8443/", "galleryEndpointUrl": "https://gallery.azure.com/", "managementEndpointUrl": "https://management.core.windows.net/" }
JSON
복사
2-5. 그리고 우리가 만든 컨테이너 레지스트리에 push와 pull을 할 수 있도록 자격을 업데이트 합니다. 다음 명령어들을 실행합니다.
$ registryId=$(az acr show \ --name <registry-name> \ --resource-group <resource-group-name> \ --query id --output tsv) $ az role assignment create \ --assignee <ClientId> \ --scope $registryId \ --role AcrPush
JSON
복사
2-6. Credentials를 github repo에 저장하기  
Security > Secrets and variables > Actions 에서 repo secret추가
workflow를 통해 배포를 자동화하려면 환경변수 문제가 존재합니다. api키나 패스워드 같은 것을 github에 올릴 수는 없기 때문입니다. 가상 머신 위에서의 테스트 및 빌드에 환경변수가 필요하기 때문에 이를 위해 secrets라는 기능이 숨기고 싶은 데이터를 관리해줍니다.
action의 workflow가 실행될 때 이 secrets에 접근이 가능해 동적으로 secrets의 데이터를 취합해 .env 파일을 새로 생성합니다. 이렇게 저장된 값은 workflow에서 ${{secrets.VARIABLE_NAME}} 형태로 접근 가능합니다.
Github Secret 값 정보 AZURE_CREDENTIALS service principal을 생성할때 출력된 전체 JSON 결과 REGISTRY_LOGIN_SERVER Azure 컨테이너 레지스트리(registry) 서버 주소 예시: myregistry.azurecr.io REGISTRY_USERNAME service principal 생성시 clientId 값 REGISTRY_PASSWORD service principal 생성시 clientSecret 값 RESOURCE_GROUP service principal 생성에 사용하고, 리소스가 위치한 그룹 이름
Plain Text
복사
2-7. 크게 다음과 같은 과정을 거치는 workflow 파일을 작성합니다
Dockerfile에서 이미지 빌드
Azure 컨테이너 레지스트리에 이미지 푸시
Azure 컨테이너 인스턴스에 컨테이너 이미지 배포
name: full steps of flask app deployment to ACI on: push: branches: - ['main'] pull_request: branches: - ['main'] jobs: build: runs-on: ubuntu-latest steps: # checkout the repo - name: 'Checkout GitHub Action' uses: actions/checkout@main - name: 'Login via Azure CLI' uses: azure/login@v1 with: creds: ${{ secrets.AZURE_CREDENTIALS }} - name: 'Build and push image' uses: azure/docker-login@v1 with: login-server: ${{ secrets.REGISTRY_LOGIN_SERVER }} username: ${{ secrets.REGISTRY_USERNAME }} password: ${{ secrets.REGISTRY_PASSWORD }} - run: | docker build . -t ${{ secrets.REGISTRY_LOGIN_SERVER }}/flaskapp:${{ github.sha }} docker push ${{ secrets.REGISTRY_LOGIN_SERVER }}/flaskapp:${{ github.sha }} deploy: runs-on: ubuntu-latest needs: build steps: - name: 'Login via Azure CLI' uses: azure/login@v1 with: creds: ${{ secrets.AZURE_CREDENTIALS }} - name: 'Deploy to Azure Container Instances' uses: 'azure/aci-deploy@v1' with: resource-group: ${{ secrets.RESOURCE_GROUP }} dns-name-label: ${{ secrets.RESOURCE_GROUP }}${{ github.run_number }} image: ${{ secrets.REGISTRY_LOGIN_SERVER }}/flaskapp:${{ github.sha }} registry-login-server: ${{ secrets.REGISTRY_LOGIN_SERVER }} registry-username: ${{ secrets.REGISTRY_USERNAME }} registry-password: ${{ secrets.REGISTRY_PASSWORD }} name: aci-flaskapp location: 'korea central'
YAML
복사
build job에서 레지스트리에 이미지를 빌드하고 푸쉬하는 과정이 이루어집니다.
DevOps[1] 실습과 마찬가지로 가장 먼저 repository를 checkout해주네요. 거의 모든 workflow에서 이를 먼저 수행해준다고 생각하시면 됩니다.
이후 Azure에서 제공되는 action으로 로그인을 하고, 레지스트리에 로그인해 도커 이미지를 빌드하고 push해주네요. 이 때 secrets로 우리의 개인 정보들을 가져와 수행하는 걸 볼 수 있습니다.
deploy job에서 배포를 수행해줍니다.
이 과정은 build가 성공해야 수행되는 과정으로 정의되어 있습니다. (need: build)
build에서처럼 azure에 먼저 로그인을 해주고
deploy action을 가져와서 with에 필요한 정보들을 넣어주고 배포를 수행합니다.
aci-flaskapp이라는 이름으로 container instance가 생성됩니다.
2-8. git add / commit / push / PR 수행
PR을 수행하면 workflow가 수행됩니다.
workflow 실행이 성공하면 생성된 ACI를 확인할 수 있습니다.
workflow 수행 성공
ACI 생성됨
개요의 FQDN 주소로 접속하면 구동된 flaskapp을 확인 할 수 있습니다.
구동된 웹페이지
이렇게 테스트가 성공하면 merge를 수행합니다.

tip

on: workflow_dispatch:
YAML
복사
위와 같이 설정하면 workflow를 수동으로 수행되도록 설정할 수 있습니다.
이를 활용하면 build와 deploy workflow를 분리하여 deploy는 수동으로 수행되도록 설정할 수도 있겠죠
azure kubernetes service (AKS)를 사용하여 kubernetes로의 배포도 가능합니다.