2025년 7월 15일8분 분량

NCP와 함께하는 쿠버네티스 구축

이번 프로젝트를 진행하면서 Naver Cloud Platform을 이용해 쿠버네티스를 구축하고 개발하게 되었다. 클라우드로 쿠버네티스를 구축하는 방법과 구축 과정에서 만났던 많은…

이번 프로젝트를 진행하면서 Naver Cloud Platform을 이용해 쿠버네티스를 구축하고 개발하게 되었다. 클라우드로 쿠버네티스를 구축하는 방법과 구축 과정에서 만났던 많은 어려움들을 어떻게 해결해 나갔는지 기록해보려고 한다.

구축 순서

bash
11. VPC 준비
22. Subnet 생성
33. NKS클러스터 생성
44. 노드풀 생성
55. 도메인 및 LB 설정
66. 관리용 시스템 생성
77. Bastion Host 구축
88. KubeCtl 설치

NCP 설정

VPC 준비

VPC 및 서브넷을 생성한다.

image22

myPage
myPage

BastionHost 생성

kubectl을 사용하기 위해서는 bastionHost가 필요하다.

NAT 설정

NKS 클러스터가 Private 서브넷에 구성되어있어 노드가 Public Internet에 접근할수없다. NKS 노드에 외부 인터넷이 열려야지 Docker Registry등의 서비스를 사용 가능하다. NAT Gateway 설정으로 노드는 외부에 노출하지 않고, 인터넷이 가능한 환경을 구축한다.

먼저 NAT Gatway를 생성하고, NAT Gateway를 Private 서브넷의 Route Table에 등록해준다.

testImage
testImage

kkkk
kkkk

BastionHost 설정

KubeCtl 설치

이번에 구축한 서버의 경우 X86-64 이고, 혹시 ARM 기반 으로 구축을 하는경우 아래 링크를 참고하자.

kubectl 구축

  1. 최신 릴리스 다운로드
bash
1 curl -LO "https://dl.k8s.io/release/$(curl -L -s https://dl.k8s.io/release/stable.txt)/bin/linux/amd64/kubectl"
  1. 바이너리 검증
bash
1 curl -LO "https://dl.k8s.io/release/$(curl -L -s https://dl.k8s.io/release/stable.txt)/bin/linux/amd64/kubectl.sha256"
bash
1echo "$(cat kubectl.sha256) kubectl" | sha256sum --check

명령어를 통해 정상 출력시 아래와 같은 내용이 표출 된다.

정상 출력
정상 출력

  1. kubectl 설치
bash
1sudo install -o root -g root -m 0755 kubectl /usr/local/bin/kubectl
  1. 설치된 버전 확인
bash
1kubectl version --client
  1. ncloud 접속을 위한 Config 설정
bash
1## ~/.ncloud/configure
2
3[DEFAULT]
4ncloud_access_key_id = AK_XXX
5ncloud_secret_access_key = SK_XXX
6ncloud_api_url = https://ncloud.apigw.gov-ntruss.com
bash
1chmod 600 ~/.ncloud/configure

현재 프로젝트에서 Docker Hub가 아닌 NCP에서 지원하는 Docker Registry를 사용중이여서 해당 부분을 Secret으로 만들어 설정해줘야한다.

  1. 도커 레지스트리 설정
bash
1undefined

Ingress 설치

Ingress Controller의 사용 방식은 2가지가 있다. 이중 내가 사용할 방식은 ALB를 생성하여 Ingress로 컨트롤 하는 방식이다.

  1. Nginx Ingress

  2. ALB Ingress

  3. Ingress Controller 설치 확인

bash
1kubectl get pods -n kube-system | grep ingress
  1. 없으면 설치를 진행
  • ALB 방식
bash
1kubectl --kubeconfig=$KUBE_CONFIG apply -f https://raw.githubusercontent.com/NaverCloudPlatform/nks-alb-ingress-controller/main/docs/install/pub/install.yaml

설치 완료시 아래와 같은 응답을 받을수 있다.

  • Nginx 방식
bash
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 설정 방법

  1. Ingress.yml
yaml
1ncloud@vstl-wm-kubectl:~$ cat watchmile-api-ingress.yaml
2apiVersion: networking.k8s.io/v1
3kind: Ingress
4metadata:
5 name: ansan-gov-ingress
6 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-alb
11 alb.ingress.kubernetes.io/load-balancer-type: "alb"
12 alb.ingress.kubernetes.io/network-type: public
13 alb.ingress.kubernetes.io/load-balancer-size: small
14 alb.ingress.kubernetes.io/healthcheck-path: /actuator/health
15spec:
16 ingressClassName: alb
17 tls:
18 - hosts:
19 - parkingapi.ansanuc.net
20 secretName: dummy-tls
21 rules:
22 - host: parking-api.ansanuc.net
23 http:
24 paths:
25 - path: /
26 pathType: Prefix
27 backend:
28 service:
29 name: ansan-daemin-api
30 port:
31 number: 80
32 - host: parkingm-api.ansanuc.net
33 http:
34 paths:
35 - path: /
36 pathType: Prefix
37 backend:
38 service:
39 name: ansan-admin-api
40 port:
41 number: 80

파이프 라인

사용중인 레포지토리는 Bitbucket 인데, Pipeline이라는 좋은 기능을 제공한다. Github Action 처럼 Bitbucket 자체에 내장되어 CI/CD를 간편하게 해줄수있는 도구이다. 이를 통해 구축 하려고 하는 방식은 다음과 같다.

Bitbucket 설정

CI/CD를 적용할 레포지토리에 해당 yml을 세팅한다.

kube-deploy.yml

yaml
1apiVersion: v1
2kind: Service
3metadata:
4 name: ansan-daemin-api
5spec:
6 selector:
7 app: ansan-daemin-api
8 type: ClusterIP
9 ports:
10 - port: 80
11 targetPort: 7070
12---
13apiVersion: apps/v1
14kind: Deployment
15metadata:
16 name: ansan-daemin-api
17spec:
18 replicas: 1
19 selector:
20 matchLabels:
21 app: ansan-daemin-api
22 template:
23 metadata:
24 labels:
25 app: ansan-daemin-api
26 spec:
27 imagePullSecrets:
28 - name: registry
29 containers:
30 - name: ansan-daemin-api
31 image: {{image}}
32 ports:
33 - containerPort: 7070

kube-deploy.yml은 관리의 편의성과 안정성을 위해서 필요하다. 만약 해당 yml파일이 없더라도

bash
1kubectl set image deployment/ansan-daemin-api ansan-daemin-api=이미지명

위의 CLI 명령어를 통해서 배포하는것도 가능하지만, 이렇게 하면 전체 Deployment에 대한 정의가 코드로 남지 않는다. kube-deploy.yml을 만듦으로써, 클러스터 초기화 / 재배포 상황에서 사용이 가능하고, 다른 환경을 구성 하더라도 재사용이 가능하다. 그리고 kubectl apply 를 통해 선언적으로 배포가 가능해진다.

bitbucket.yml

yaml
1image: atlassian/default-image:4
2
3options:
4 docker: true
5 size: 2x
6
7definitions:
8 services:
9 docker:
10 memory: 2048
11
12pipelines:
13 branches:
14 main:
15 - step:
16 name: Docker build & push
17 size: 2x
18 script:
19 - export IMAGE_NAME=$NCLOUD_CR_URL/$APPLICATION_NAME:$BITBUCKET_COMMIT
20 - docker build -t $APPLICATION_NAME .
21 - docker tag $APPLICATION_NAME $IMAGE_NAME
22 - echo "$NCLOUD_KEY" | docker login -u $NCLOUD_ID $NCLOUD_CR_URL --password-stdin
23 - docker push $IMAGE_NAME
24 services:
25 - docker
26 caches:
27 - docker
28 - step:
29 name: Deploy to NKS via Bastion (GitOps style)
30 deployment: production
31 script:
32 - export IMAGE_NAME=$NCLOUD_CR_URL/$APPLICATION_NAME:$BITBUCKET_COMMIT
33 - apt-get update && apt-get install -y sshpass openssh-client
34 - ssh-keyscan -H $DEV_SERVER_HOST >> ~/.ssh/known_hosts
35
36 # YAML에 이미지 치환
37 - sed -i "s|{{image}}|$IMAGE_NAME|g" kube-deployment.yml
38
39 # Bastion에 접속해서 apply
40 - 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 ## Develop
46 develop:
47 - step:
48 name: Docker build & push
49 size: 2x
50 script:
51 - export IMAGE_NAME=$NCLOUD_CR_URL/$APPLICATION_NAME:latest
52 - docker build -t $APPLICATION_NAME .
53 - docker tag $APPLICATION_NAME $IMAGE_NAME
54 - echo "$NCLOUD_KEY" | docker login -u $NCLOUD_ID $NCLOUD_CR_URL --password-stdin
55 - docker push $IMAGE_NAME
56 services:
57 - docker
58 caches:
59 - docker
60
61 - step:
62 name: Deploy to Server
63 deployment: test
64 script:
65 - export IMAGE_NAME=$NCLOUD_CR_URL/$APPLICATION_NAME:latest
66 - apt-get update && apt-get install -y sshpass openssh-client
67 - ssh-keyscan $DEV_SERVER_HOST >> ~/.ssh/known_hosts
68
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 발생

bash
1ncloud@server:~$ kubectl get pods
2NAME READY STATUS RESTARTS AGE
3ansan-daemin-api-7578988667-ptkqw 0/1 InvalidImageName 0 15h

ALB Health-check 문제

Cluster IP를 기본값으로 설정해서 ALB에서 Health Check가 불가능하였다. Cluster IP는 외부에서 접근할수없어, ALB에서 HealthCheck를 보낼수없기 때문이다. 이를 해결하기 위해 ClusterIP -> NodePort로 변경하여 해결하였다.

Ref.