GitLab은 GitLab Runner라는 것을 작동하여 CI/CD 파이프라인을 구현할 수 있다. Runner에도 여러 버전이 있지만 default로 모든 프로젝트를 지원하는 Shared Runner를 사용해 GKE에 application 배포해볼 것이다.
비공개 GKE 클러스터를 생성해줄 것이다. 우선 VPC를 커스텀모드로 따로 생성해주자
클러스터 생성 시 위에서 만들어준 VPC와 서브넷을 지정해주고 비공개 클러스터로 설정해준다.
아래의 gcloud 명령어로 간편하게 생성할 수도 있다.
gcloud container clusters create <클러스터 이름> \
--create-subnetwork name=<서브넷 이름> \
--enable-master-authorized-networks \
--enable-ip-alias \
--enable-private-nodes \
--enable-private-endpoint \
--master-ipv4-cidr 172.16.0.0/28
GitLab 프로젝트 생성
여기서 중요한 설정이 하나 있다. GitLab은 GCP의 리소스가 아니고 모든 클라우드 플랫폼과의 연동이 가능한 오픈소스다.
때문에 GKE에 리소스를 배포하려면 GKE의 권한을 가진 서비스 계정 키를 사용하여 GKE에 배포할 수 있는데, 이 키를 repo에 그대로 올릴 수는 없는 법... GitLab CI/CD 세팅에서 변수를 등록해줄 수 있는데 여기 키 파일을 등록해주고 변수를 받아와서 사용할 것이다.
서비스 계정 키를 다운 받은 후 안의 내용을 아래와 같이 변수 명과 함께 등록해준다.
저장소를 처음 만들면 로컬에서 저장소를 연동할 수 있는 코드를 보여준다. 아래 사진의 코드를 그대로 실행하면 되는데 git 사용이 처음이라고 하면 해당 디렉토리로 가서 아래의 명령어를 먼저 설정해줘야 한다.
git init
git config --global user.name "<이름>"
git config --global user.email "<메일 주소>"
그러고 GitLab의 username과 password를 입력하라는데 GitLab 계정의 username과 password를 입력하면 안될 것이다. 이유는 여기서 말하는 password는 토큰을 발급받아서 해당 토큰을 통해 인증하는 방식이기 때문이다.
토큰 발급(귀찮아서 다 줬는데 필요한 권한만 주자..)
app.py
from flask import Flask
app = Flask('hello-world')
@app.route('/')
def hello():
return "Hello world!\n"
if __name__ == '__main__':
app.run(host = '0.0.0.0', port = 8080)
Dockerfile
FROM python:3.7-slim
RUN pip install flask
WORKDIR /app
COPY app.py /app/app.py
ENTRYPOINT ["python"]
CMD ["/app/app.py"]
deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: gitlab-gke-cicd
labels:
app: python
spec:
replicas: 3
selector:
matchLabels:
app: python
template:
metadata:
labels:
app: python
spec:
containers:
- name: python-hello-world
image: gcr.io/<프로젝트 이름>/gitlab-gke-cicd:<VERSION>
imagePullPolicy: Always
ports:
- containerPort: 8080
readinessProbe:
httpGet:
path: /
port: 8080
initialDelaySeconds: 5
timeoutSeconds: 5
periodSeconds: 5
---
apiVersion: v1
kind: Service
metadata:
name: python-service
labels:
app: python
spec:
ports:
- port: 8080
targetPort: 8080
selector:
app: python
위의 파일들은 쿠버네티스에 어플리케이션을 배포하는데에 필요한 기본적인 매니페스트 파일들이다. GitLab CI/CD를 구현하려면 한 가지 파일이 더 필요하다 .gitlab-ci.yml파일이고 GitLab에 .gitlab-ci.yml 파일을 push하면 알아서 해당 파일에 있는 작업을 실행한다.
.gitlab-ci.yml
CI_PROJECT_NAME은 GitLab 프로젝트 이름에서 도커 이미지 이름을 상속하기 위한 옵션으로 GitLab에 미리 정의된 변수이다. 우리가 따로 설정해줘야 하는 것은 없다.
stages:
- build-push
- deploy
image: docker:19.03.12
variables:
DOCKER_HOST: tcp://docker:2375/
DOCKER_TLS_CERTDIR: ""
REGISTRY_HOSTNAME: gcr.io/<프로젝트 이름>
DOCKER_IMAGE_NAME: ${CI_PROJECT_NAME}
services:
- docker:19.03.12-dind
# docker image로 build > deploy 파이프라인 생성
build-push:
stage: build-push
before_script:
- docker info
- echo "$SERVICE_ACCOUNT_KEY" > key.json
- docker login -u _json_key --password-stdin https://gcr.io < key.json
script:
- docker build --tag $REGISTRY_HOSTNAME/$DOCKER_IMAGE_NAME:$CI_COMMIT_SHORT_SHA .
- docker push $REGISTRY_HOSTNAME/$DOCKER_IMAGE_NAME:$CI_COMMIT_SHORT_SHA
deploy:
stage: deploy
image: google/cloud-sdk
script:
# Authenticate with GKE
- echo "$SERVICE_ACCOUNT_KEY" > key.json
- gcloud auth activate-service-account --key-file=key.json
- gcloud config set project <프로젝트 이름>
- gcloud config set container/cluster <클러스터 이름>
- gcloud config set compute/zone <zone ex) us-central1-c>
- gcloud container clusters get-credentials <클러스터 이름> --zone <zone> --project <프로젝트 이름>
- sed -i "s/<VERSION>/${CI_COMMIT_SHORT_SHA}/g" deployment.yaml
- kubectl apply -f deployment.yaml
gcloud container clusters get-credentials는 아래 사진과 같이 GKE 클러스터에서 연결을 누르면 나오는 명령어이다.
저장소에 push를 했지만 GitLab CI/CD를 처음 사용한다고 하면 아래와 같은 오류가 뜰 것이다.
카드 등록,, 해주자,,
그리고 다시 로컬에서 코드를 push하면 아래와 같이 .gitlab-ci.yml을 통해 자동으로 파이프라인이 동작하는 것을 확인할 수 있다.
콘솔에 GCR로 가보면 이미지도 생성된 것을 확인할 수 있다.
포트포워딩을 통해 컨테이너 포트와 8090포트를 매핑해서 어플리케이션이 동작하는지를 확인해보자
kubectl port-forward svc/python-service 8090:8080
성공적으로 어플리케이션이 나온다.
이제 GCP의 LB를 통해 앱을 외부로 노출시켜볼 것이다.
여기선 고정 ip를 하나 생성해주고 LB에서 해당 고정 ip를 쓰도록 할 것이다.
이제 git push를 하면 아래의 이 ip를 통해 외부에서 어플리케이션이 보이게 파이프라인을 생성할 것이다.
이를 위해선 ingress 파일을 만들고 기존의 매니페스트 파일들에서 몇 가지를 수정해줘야 한다.
ingress.yaml
annotaions 설정을 통해 LB에 내가 만들어준 고정 ip를 사용하게 할 것이다.
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: gitlab-gke-ingress
annotations:
kubernetes.io/ingress.global-static-ip-name: "mhk-gke-ingress"
spec:
rules:
- http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: python-service
port:
number: 80
deployment.yaml
service부분에서 컨테이너를 단일진입점을 통해 외부로 노출시켜주는 NodePort 설정을 해주자.
.gitlab-ci.yml
아래와 같이 배포 script에 ingress를 배포시키는 명령어 추가.
조금 기다리면 ingress가 생성되고 ALB가 생긴것을 확인할 수 있다.
성공
[GitLab CI/CD를 사용하여 GKE에 어플리케이션 배포 참고]
https://blog.searce.com/gitlab-ci-cd-to-deploy-applications-on-gke-using-shared-runner-47f8c42817ac