이번 실습의 목표는 다음과 같습니다.
목표 : 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로의 배포도 가능합니다.