본문 바로가기
Study/Naver Cloud Platform

NCP 활용하기(3) - NKS 구축 및 활용 (Next.js , SpringBoot)

by 왕방개 2024. 10. 29.

 

 

 

저는 이번 공모전을 진행하면서 NCP에서 제공받아 NKS 을 통해 배포했습니다. Frontend로는 next.js 14버전과 Backend 로 Springboot 을 활용해 배포했습니다. NKS를 사용하면서 장점으로는 역시 다양한 Cloud Service 와 연계해서 사용할 수 있다는 점이였습니다. Kubernetes로 yaml 파일만 작성하면 loadbalancer 를 통해 바로 배포가 되는것을 확인할 수 있었고, 추가적으로 모니터링 서비스와 CI/CD 등 여러가지 서비스를 쉽게 연계해서 사용했습니다.

 

하지만 단점으로는 Master Node를 제가 관리할 수 없다는 점이였습니다. "관리형" k8s 이기에 Master Node 에 있는 API-Server, ETCD, Controller Manager 등 다양한 컴포넌트들을 NCP 에서 관리하기 때무에 사용자 관점에서 관리 및 커스터마이징이 불가능했습니다. 

 

일단 구축하는 것부터 설명하고, 저같은 경우에는 NKS 안에 새로운 서버를  파서 kubectl 설치 및 ncp-iam-authenticator 를 사용해서 nks 명령어를 관리 했고, 추가적으로 Container Registry 에 저장되어 있는 image 를 받아와서 배포하는 yaml파일까지 정리했습니다.

 


 

1. NKS 생성 및 구축하기

 

1) NKS 생성

아래 [생성하기] 버튼을 클릭합니다.

 

 

2)클러스터 설정

- 필요한 정보를 입력합니다.

- 미리 VPC 와 subnet 을 구축해놓으셔야합니다. 구축하는 방법은 이전 게시글에 가능합니다.

 

 

3)Node pool 설정

- 필요한 정보 입력

- 서버 타입과 노드수를 필요한 구성만큼 하시면 됩니다.

 

 

4)인증키 설정

- 인증키가 있으시면 원래꺼 사용하시고 없으시면 생성하면 됩니다.

 

 


2. kubectl 및 ncp-iam-authenticator 설치 및 적용

저는 앞서 말씀드렸듯이 server 를 새로 파서 Ubuntu 환경에서 작업했습니다. 

https://guide.ncloud-docs.com/docs/k8s-k8sstart

여기서 밑에 kubectl 설치 하는 명령어를 확인해주시면 됩니다. 저는 linux 기반으로 정리하겠습니다.

아래 명령어로 kubectl 를 설치합니다.

 curl -LO "https://dl.k8s.io/release/$(curl -L -s https://dl.k8s.io/release/stable.txt)/bin/linux/arm64/kubectl"
  
 sudo install -o root -g root -m 0755 kubectl /usr/local/bin/kubectl
 
 #root access 가 없다면
 #chmod +x kubectl
 #mkdir -p ~/.local/bin
 #mv ./kubectl ~/.local/bin/kubectl
 
 kubectl version

 

 

아래 명령어로 ncp-iam-authenticator 를 설치합니다.

ncp-iam-authenticator 설정이 잘못됬다면 오류가 계속 뜨고 접근이 안되서 잘 설치 해야합니다.

curl -o ncp-iam-authenticator -L https://github.com/NaverCloudPlatform/ncp-iam-authenticator/releases/latest/download/ncp-iam-authenticator_linux_amd64

chmod +x ./ncp-iam-authenticator

mkdir -p $HOME/bin && cp ./ncp-iam-authenticator $HOME/bin/ncp-iam-authenticator && export PATH=$PATH:$HOME/bin

ncp-iam-authenticator help

 

하고 이제 인증키 설정해야합니다.

vim ~/.ncloud/configure

[DEFAULT]
ncloud_access_key_id = [서브계정 Access key]
ncloud_secret_access_key = [서브계정 Secret key]
ncloud_api_url = https://ncloud.apigw.ntruss.com

 

이제 kubeconfig 를 설정해야 하는데 할때 clusterUuid는 NKS 설정한 콘솔에서 확인 가능합니다.

mkdir ~/.kube

ncp-iam-authenticator create-kubeconfig --region KR --clusterUuid[클러스터아이디] -output ~/.kube/config


#제대로 설정됬는지 확인
kubectl get nodes

이까지 NKS 구축 및 kubectl 구축까지 완료했습니다.

 


 

3. yaml 파일을 통해 배포하기

next.js image 와 spring boot image 를 저는 yaml파일에 service 에서 type를  load Balancer 를 통해 배포했다가 , 후에 HTTPS 설정을 해야했기 때문에 ingress 설정을 통해 application load balancer 로 배포했습니다. load balancer 와 application load balancer 의 차이는 후에 정리하겠습니다. ingress 설정을 위해 우선 ingress-nginx 를 설치해야합니다.

 

$ kubectl --kubeconfig $KUBE_CONFIG apply -f https://raw.githubusercontent.com/kubernetes/ingress-nginx/controller-v1.11.2/deploy/static/provider/cloud/deploy.yaml

 

후에 ingress 를 통해 배포하는 yaml파일입니다.

 

 

하기 전에 secret 을 통해 container registry 의 접근 권한을 부여해야합니다.아래 명령어를 활용해서 secret 을 생성할 수 있습니다.

kubectl create secret docker-registry {secret이름} --docker-server={이미지 주소} --docker-username={ncp public key} --docker-password={ncp secret key} --docker-email={이메일주소}

 

frontend-deployment.yaml입니다.

# SSL 인증서 ARN을 위한 Secret 정의
apiVersion: v1
kind: Secret
metadata:
  name: ssl-cert-secret
type: Opaque
data:
  ssl-certificate-arn: {{base64_encoded_arn}}  # SSL 인증서 ARN을 base64로 인코딩하여 추가하세요

---

apiVersion: apps/v1
kind: Deployment
metadata:
  name: front-service-deployment
spec:
  replicas: 1
  selector:
    matchLabels:
      app: front-service
  template:
    metadata:
      labels:
        app: front-service
    spec:
      containers:
      - name: front-service
        image: {image 주소.반드시 private 주소를 통해 불러와야함}
        imagePullPolicy: Always
        ports:
        - containerPort: 3000
      imagePullSecrets:
      - name: regcred

---

apiVersion: v1
kind: Service
metadata:
  name: frontend-service
spec:
  type: NodePort
  ports:
  - port: 80
    targetPort: 3000
  selector:
    app: front-service

---

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: ingress-frontend-app
  annotations:
    alb.ingress.kubernetes.io/description: 'Frontend Service Ingress'
    alb.ingress.kubernetes.io/load-balancer-name: 'frontend-alb'
    alb.ingress.kubernetes.io/ssl-certificate-no: "{{ .Values.sslCertificateArn }}"  # Secret에서 ARN을 참조
    alb.ingress.kubernetes.io/listen-ports: '[{"HTTPS":443}]'
    alb.ingress.kubernetes.io/enable-sticky-session: "true"
spec:
  ingressClassName: alb
  defaultBackend:
    service:
      name: frontend-service
      port:
        number: 80

 

backend-deployment.yaml입니다.

# 민감 정보를 위한 Secret 정의
apiVersion: v1
kind: Secret
metadata:
  name: backend-secret
type: Opaque
data:
  redis-host: {{base64_encoded_redis_host}}
  redis-port: {{base64_encoded_redis_port}}
  spring-datasource-url: {{base64_encoded_db_url}}
  spring-datasource-username: {{base64_encoded_db_username}}
  spring-datasource-password: {{base64_encoded_db_password}}

---

# 환경 설정을 위한 ConfigMap 정의
apiVersion: v1
kind: ConfigMap
metadata:
  name: backend-configmap
data:
  app-name: "ringmybell-backend"

---

# Spring Boot Backend Deployment
apiVersion: apps/v1
kind: Deployment
metadata:
  name: backend-service-deployment
spec:
  replicas: 1
  selector:
    matchLabels:
      app: backend-service
  template:
    metadata:
      labels:
        app: backend-service
    spec:
      containers:
        - name: backend-service
          image: {container registry private 이미지 주소}
          imagePullPolicy: Always
          ports:
            - containerPort: 8080
          env:
            - name: REDIS_HOST
              valueFrom:
                secretKeyRef:
                  name: backend-secret
                  key: redis-host
            - name: REDIS_PORT
              valueFrom:
                secretKeyRef:
                  name: backend-secret
                  key: redis-port
            - name: SPRING_DATASOURCE_URL
              valueFrom:
                secretKeyRef:
                  name: backend-secret
                  key: spring-datasource-url
            - name: SPRING_DATASOURCE_USERNAME
              valueFrom:
                secretKeyRef:
                  name: backend-secret
                  key: spring-datasource-username
            - name: SPRING_DATASOURCE_PASSWORD
              valueFrom:
                secretKeyRef:
                  name: backend-secret
                  key: spring-datasource-password
            - name: APP_NAME
              valueFrom:
                configMapKeyRef:
                  name: backend-configmap
                  key: app-name
      imagePullSecrets:
        - name: kingbk  # Naver Container Registry 인증 정보

---

# Spring Boot Backend Service (NodePort)
apiVersion: v1
kind: Service
metadata:
  name: backend-service
spec:
  type: NodePort
  selector:
    app: backend-service
  ports:
    - protocol: TCP
      port: 80
      targetPort: 8080

---

# Ingress 정의
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: ingress-backend-app
  annotations:
    alb.ingress.kubernetes.io/description: 'Backend Service Ingress'
    alb.ingress.kubernetes.io/load-balancer-name: 'backend-alb'
    alb.ingress.kubernetes.io/ssl-certificate-no: "{{ .Values.sslCertificateArn }}"  # Secret에서 ARN 참조
    alb.ingress.kubernetes.io/listen-ports: '[{"HTTPS":443}]'
    alb.ingress.kubernetes.io/enable-sticky-session: "true"
spec:
  ingressClassName: alb
  rules:
    - host: api.whichme.site  # 외부에서 접근할 호스트
      http:
        paths:
          - path: /api-test  # Swagger UI 경로
            pathType: Prefix
            backend:
              service:
                name: backend-service  # 서비스 이름
                port:
                  number: 80
          - path: /  # 기본 경로 설정
            pathType: Prefix
            backend:
              service:
                name: backend-service  # 서비스 이름
                port:
                  number: 80

 

 


 

지금까지 NKS를 활용해서 next.js 와 springboot 를 배포했습니다. 다음으로 배포한 ALB를 도메인까지 연결하는 과정을 정리하겠습니다.