NCP와 함께하는 쿠버네티스 구축
이번 프로젝트를 진행하면서 Naver Cloud Platform을 이용해 쿠버네티스를 구축하고 개발하게 되었다. 클라우드로 쿠버네티스를 구축하는 방법과 구축 과정에서 만났던 많은…
이번 프로젝트를 진행하면서 Naver Cloud Platform을 이용해 쿠버네티스를 구축하고 개발하게 되었다. 클라우드로 쿠버네티스를 구축하는 방법과 구축 과정에서 만났던 많은 어려움들을 어떻게 해결해 나갔는지 기록해보려고 한다.
구축 순서
11. VPC 준비22. Subnet 생성33. NKS클러스터 생성44. 노드풀 생성55. 도메인 및 LB 설정66. 관리용 시스템 생성77. Bastion Host 구축88. KubeCtl 설치 NCP 설정
VPC 준비
VPC 및 서브넷을 생성한다.


BastionHost 생성
kubectl을 사용하기 위해서는 bastionHost가 필요하다.
NAT 설정
NKS 클러스터가 Private 서브넷에 구성되어있어 노드가 Public Internet에 접근할수없다. NKS 노드에 외부 인터넷이 열려야지 Docker Registry등의 서비스를 사용 가능하다. NAT Gateway 설정으로 노드는 외부에 노출하지 않고, 인터넷이 가능한 환경을 구축한다.
먼저 NAT Gatway를 생성하고, NAT Gateway를 Private 서브넷의 Route Table에 등록해준다.


BastionHost 설정
KubeCtl 설치
이번에 구축한 서버의 경우 X86-64 이고, 혹시 ARM 기반 으로 구축을 하는경우 아래 링크를 참고하자.
- 최신 릴리스 다운로드
1 curl -LO "https://dl.k8s.io/release/$(curl -L -s https://dl.k8s.io/release/stable.txt)/bin/linux/amd64/kubectl"- 바이너리 검증
1 curl -LO "https://dl.k8s.io/release/$(curl -L -s https://dl.k8s.io/release/stable.txt)/bin/linux/amd64/kubectl.sha256"1echo "$(cat kubectl.sha256) kubectl" | sha256sum --check명령어를 통해 정상 출력시 아래와 같은 내용이 표출 된다.

- kubectl 설치
1sudo install -o root -g root -m 0755 kubectl /usr/local/bin/kubectl- 설치된 버전 확인
1kubectl version --client- ncloud 접속을 위한 Config 설정
1## ~/.ncloud/configure2
3[DEFAULT]4ncloud_access_key_id = AK_XXX5ncloud_secret_access_key = SK_XXX6ncloud_api_url = https://ncloud.apigw.gov-ntruss.com1chmod 600 ~/.ncloud/configure현재 프로젝트에서 Docker Hub가 아닌 NCP에서 지원하는 Docker Registry를 사용중이여서 해당 부분을 Secret으로 만들어 설정해줘야한다.
- 도커 레지스트리 설정
1undefinedIngress 설치
Ingress Controller의 사용 방식은 2가지가 있다. 이중 내가 사용할 방식은 ALB를 생성하여 Ingress로 컨트롤 하는 방식이다.
-
Nginx Ingress
-
ALB Ingress
-
Ingress Controller 설치 확인
1kubectl get pods -n kube-system | grep ingress- 없으면 설치를 진행
- ALB 방식
1kubectl --kubeconfig=$KUBE_CONFIG apply -f https://raw.githubusercontent.com/NaverCloudPlatform/nks-alb-ingress-controller/main/docs/install/pub/install.yaml설치 완료시 아래와 같은 응답을 받을수 있다.

- Nginx 방식
1kubectl apply -f https://raw.githubusercontent.com/kubernetes/ingress-nginx/controller-v1.10.1/deploy/static/provider/cloud/deploy.yaml설치가 완료되면 이제 Ingress를 세팅해서 실제로 apply하는 작업을 수행해야 한다. 이를 위해 Ingress.yml을 작성하자. 자세한 설명은 하단의 링크를 참고하자.
NCP - ALB Ingress 설정 방법
- Ingress.yml
1ncloud@vstl-wm-kubectl:~$ cat watchmile-api-ingress.yaml 2apiVersion: networking.k8s.io/v13kind: Ingress4metadata:5 name: ansan-gov-ingress6 annotations:7 alb.ingress.kubernetes.io/listen-ports: '[{"HTTP":80}, {"HTTPS":443}]'8 alb.ingress.kubernetes.io/ssl-certificate-no: "26109"9 alb.ingress.kubernetes.io/ssl-redirect: "443"10 alb.ingress.kubernetes.io/load-balancer-name: ansan-kube-alb11 alb.ingress.kubernetes.io/load-balancer-type: "alb"12 alb.ingress.kubernetes.io/network-type: public13 alb.ingress.kubernetes.io/load-balancer-size: small14 alb.ingress.kubernetes.io/healthcheck-path: /actuator/health15spec:16 ingressClassName: alb17 tls:18 - hosts:19 - parkingapi.ansanuc.net20 secretName: dummy-tls21 rules:22 - host: parking-api.ansanuc.net23 http:24 paths:25 - path: /26 pathType: Prefix27 backend:28 service:29 name: ansan-daemin-api30 port:31 number: 8032 - host: parkingm-api.ansanuc.net33 http:34 paths:35 - path: /36 pathType: Prefix37 backend:38 service:39 name: ansan-admin-api40 port:41 number: 80파이프 라인
사용중인 레포지토리는 Bitbucket 인데, Pipeline이라는 좋은 기능을 제공한다. Github Action 처럼 Bitbucket 자체에 내장되어 CI/CD를 간편하게 해줄수있는 도구이다. 이를 통해 구축 하려고 하는 방식은 다음과 같다.

Bitbucket 설정
CI/CD를 적용할 레포지토리에 해당 yml을 세팅한다.
kube-deploy.yml
1apiVersion: v12kind: Service3metadata:4 name: ansan-daemin-api5spec:6 selector:7 app: ansan-daemin-api8 type: ClusterIP9 ports:10 - port: 8011 targetPort: 707012---13apiVersion: apps/v114kind: Deployment15metadata:16 name: ansan-daemin-api17spec:18 replicas: 119 selector:20 matchLabels:21 app: ansan-daemin-api22 template:23 metadata:24 labels:25 app: ansan-daemin-api26 spec:27 imagePullSecrets:28 - name: registry29 containers:30 - name: ansan-daemin-api31 image: {{image}}32 ports:33 - containerPort: 7070kube-deploy.yml은 관리의 편의성과 안정성을 위해서 필요하다. 만약 해당 yml파일이 없더라도
1kubectl set image deployment/ansan-daemin-api ansan-daemin-api=이미지명위의 CLI 명령어를 통해서 배포하는것도 가능하지만, 이렇게 하면 전체 Deployment에 대한 정의가 코드로 남지 않는다. kube-deploy.yml을 만듦으로써, 클러스터 초기화 / 재배포 상황에서 사용이 가능하고, 다른 환경을 구성 하더라도 재사용이 가능하다. 그리고 kubectl apply 를 통해 선언적으로 배포가 가능해진다.
bitbucket.yml
1image: atlassian/default-image:42
3options:4 docker: true5 size: 2x6
7definitions:8 services:9 docker:10 memory: 204811
12pipelines:13 branches:14 main:15 - step:16 name: Docker build & push17 size: 2x18 script:19 - export IMAGE_NAME=$NCLOUD_CR_URL/$APPLICATION_NAME:$BITBUCKET_COMMIT20 - docker build -t $APPLICATION_NAME .21 - docker tag $APPLICATION_NAME $IMAGE_NAME22 - echo "$NCLOUD_KEY" | docker login -u $NCLOUD_ID $NCLOUD_CR_URL --password-stdin23 - docker push $IMAGE_NAME24 services:25 - docker26 caches:27 - docker28 - step:29 name: Deploy to NKS via Bastion (GitOps style)30 deployment: production31 script:32 - export IMAGE_NAME=$NCLOUD_CR_URL/$APPLICATION_NAME:$BITBUCKET_COMMIT33 - apt-get update && apt-get install -y sshpass openssh-client34 - ssh-keyscan -H $DEV_SERVER_HOST >> ~/.ssh/known_hosts35
36 # YAML에 이미지 치환37 - sed -i "s|{{image}}|$IMAGE_NAME|g" kube-deployment.yml38
39 # Bastion에 접속해서 apply40 - cat kube-deployment.yml | sshpass -p "$SERVER_PASS" ssh -o StrictHostKeyChecking=no $SERVER_USER@$BASTION_HOST "41 export PATH=\$PATH:/home1/ncloud/bin &&42 kubectl --kubeconfig /home1/ncloud/kubeconfig-ansan.yaml apply -f -43 "44
45 ## Develop46 develop:47 - step:48 name: Docker build & push49 size: 2x50 script:51 - export IMAGE_NAME=$NCLOUD_CR_URL/$APPLICATION_NAME:latest52 - docker build -t $APPLICATION_NAME .53 - docker tag $APPLICATION_NAME $IMAGE_NAME54 - echo "$NCLOUD_KEY" | docker login -u $NCLOUD_ID $NCLOUD_CR_URL --password-stdin55 - docker push $IMAGE_NAME56 services:57 - docker58 caches:59 - docker60
61 - step:62 name: Deploy to Server63 deployment: test64 script:65 - export IMAGE_NAME=$NCLOUD_CR_URL/$APPLICATION_NAME:latest66 - apt-get update && apt-get install -y sshpass openssh-client67 - ssh-keyscan $DEV_SERVER_HOST >> ~/.ssh/known_hosts68
69 - echo "$SERVER_PASS" | sshpass -p "$SERVER_PASS" ssh -o StrictHostKeyChecking=no $SERVER_USER@$BASTION_HOST "70 cd $DOCKER_COMPOSE_PATH &&71 72 echo -n \"$NCLOUD_KEY\" | docker login -u \"$NCLOUD_ID\" --password-stdin \"$NCLOUD_CR_URL\" &&73 74 docker-compose stop ansan-daemin-api || true &&75 docker-compose rm -f ansan-daemin-api || true &&76 77 docker-compose pull ansan-daemin-api &&78 docker-compose up -d ansan-daemin-api &&79 80 docker image prune -f --filter=\"until=24h\"81 "마주쳤던 문제들
InvalidImageName 발생
1ncloud@server:~$ kubectl get pods2NAME READY STATUS RESTARTS AGE3ansan-daemin-api-7578988667-ptkqw 0/1 InvalidImageName 0 15hALB Health-check 문제
Cluster IP를 기본값으로 설정해서 ALB에서 Health Check가 불가능하였다. Cluster IP는 외부에서 접근할수없어, ALB에서 HealthCheck를 보낼수없기 때문이다. 이를 해결하기 위해 ClusterIP -> NodePort로 변경하여 해결하였다.