MetalLB 설치


Jenkins CI/CD


  • Category : Kubernetes
  • Tag : Kubernetes


Jenkins로 CI/CD를 태우기 위해 원격서버(k8s)를 준비하고 먼저 다음과 같은 과정을 선행

  1. Deployment 배포
  2. Service 배포

위 서비스 배포시 아래와 같은 yaml파일로 진행

  • service.yaml 파일
apiVersion: v1
kind: Service
metadata:
  name: springboot-service
spec:
  selector:
    app: springboot
  ports:
  - protocol: TCP
    port: 8080          # 외부에서 접근할 포트
    targetPort: 8080    # Pod 내 컨테이너의 포트
    nodePort: 30061     # NodePort를 유효 범위 내로 설정
  type: NodePort
#   type: LoadBalancer  
  • deployment.yaml 파일
apiVersion: apps/v1
kind: Deployment
metadata:
  name: springboot-deployment
spec:
  replicas: 3
  selector:
    matchLabels:
      app: springboot
  template:
    metadata:
      labels:
        app: springboot
    spec:
      containers:
      - name: springboot
        image: iiblackcode/springboot-6060:latest
        ports:
        - containerPort: 8080

서비스를 NodePort Type으로 배포했기 때문에 서비스 주소가 노드주소+포트가 되었고 master노드에서 노드 주소를 조회해서 curl을 날려보았다.

master@master:~$ kubectl get pods -o wide
NAME                                     READY   STATUS    RESTARTS      AGE   IP            NODE    NOMINATED NODE   READINESS GATES
springboot-deployment-576d94d7fd-j4w4s   1/1     Running   1 (33m ago)   16h   10.244.1.27   node2   <none>           <none>
springboot-deployment-576d94d7fd-p9dmt   1/1     Running   1 (33m ago)   16h   10.244.1.28   node2   <none>           <none>
springboot-deployment-576d94d7fd-x48v5   1/1     Running   1 (33m ago)   16h   10.244.2.23   node1   <none>           <none>

master@master:~$ kubectl get nodes -o wide
NAME     STATUS   ROLES           AGE   VERSION   INTERNAL-IP   EXTERNAL-IP   OS-IMAGE             KERNEL-VERSION      CONTAINER-RUNTIME
master   Ready    control-plane   66d   v1.29.5   10.0.0.4      <none>        Ubuntu 20.04.6 LTS   5.15.0-1067-azure   containerd://1.7.18
node1    Ready    <none>          66d   v1.29.5   10.0.1.4      <none>        Ubuntu 20.04.6 LTS   5.15.0-1064-azure   containerd://1.6.31
node2    Ready    <none>          66d   v1.29.5   10.0.2.4      <none>        Ubuntu 20.04.6 LTS   5.15.0-1064-azure   containerd://1.6.31

curll 명령어 날림

master@master:~$ curl 10.0.1.4:30061

<!DOCTYPE html>
<html lang="en">

<head>

    <meta charset="utf-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
    <meta name="description" content="">
    <meta name="author" content="">

    <title>SB Admin 2 - Dashboard</title>

결과는 성공적이였다. 즉 Nodeport타입으로 배포하게 되면 서비스의 포트번호를 통해 배포된 노드의 내부 ip로 배포된다.

다음 서비스 타입을 LoadBalancer로 변경 후 배포테스트를 진행하였다.

  • service.yaml 파일 참고
apiVersion: v1
kind: Service
metadata:
  name: springboot-service
spec:
  selector:
    app: springboot
  ports:
  - protocol: TCP
    port: 8080          # 외부에서 접근할 포트
    targetPort: 8080    # Pod 내 컨테이너의 포트
    nodePort: 30061     # NodePort를 유효 범위 내로 설정
  type: LoadBalancer  
  # type: NodePort

다음과 같은 문제가 발생하였다.

master@master:~/web$ kubectl get svc -o wide
NAME                 TYPE           CLUSTER-IP     EXTERNAL-IP   PORT(S)          AGE    SELECTOR
kubernetes           ClusterIP      10.96.0.1      <none>        443/TCP          66d    <none>
springboot-service   LoadBalancer   10.105.231.9   <pending>     8080:30061/TCP   7m1s   app=springboot

배포한 서비스(springboot-service)의 EXTERNAL-IP가 로 외부에서 접근이 되지않았다.

검색해보니 온프렘 환경에서 kubernetes가 LoadBalancer를 사용하기 위해서 MetalLB설치가 필요하다고 한다.

따라서 다음과 같은 과정으로 MetalLB설치하는 과정을 기술 해 본다.

MetalLB 설치

1. ARP 모드를 활성화

# 명령어 실행
kubectl edit configmap -n kube-system kube-proxy

# 설정
ipvs:
  strictARP: true

2. Manifast로 설치

kubectl apply -f https://raw.githubusercontent.com/metallb/metallb/v0.11.0/manifests/namespace.yaml
kubectl apply -f https://raw.githubusercontent.com/metallb/metallb/v0.11.0/manifests/metallb.yaml

3. configmap yaml 생성

apiVersion: v1
kind: ConfigMap
metadata:
  namespace: metallb-system
  name: config
data:
  config: |
    address-pools:
    - name: default
      protocol: layer2
      addresses: # 각 노드에 할당된 subnet의 범위를 지정
      - 10.0.0.240-10.0.0.250
      - 10.0.1.240-10.0.1.250
      - 10.0.2.240-10.0.2.250

4. service.yaml

apiVersion: v1
kind: Service
metadata:
  name: springboot-service
spec:
  selector:
    app: springboot
  ports:
  - protocol: TCP
    port: 8080          # 외부에서 접근할 포트
    targetPort: 8080    # Pod 내 컨테이너의 포트
    nodePort: 30061     # NodePort를 유효 범위 내로 설정
  type: LoadBalancer  
  # type: NodePort

5. deployment.yaml 파일

apiVersion: apps/v1
kind: Deployment
metadata:
  name: springboot-deployment
spec:
  replicas: 3
  selector:
    matchLabels:
      app: springboot
  template:
    metadata:
      labels:
        app: springboot
    spec:
      containers:
      - name: springboot
        image: iiblackcode/springboot-6060:latest
        ports:
        - containerPort: 8080

service 및 node ip 조회

master@master:~/web$ kubectl get svc
NAME                 TYPE           CLUSTER-IP      EXTERNAL-IP   PORT(S)          AGE
kubernetes           ClusterIP      10.96.0.1       <none>        443/TCP          66d
springboot-service   LoadBalancer   10.105.172.46   10.0.0.240    8080:30061/TCP   4m54s

master@master:~/web$ kubectl get nodes -o wide
NAME     STATUS   ROLES           AGE   VERSION   INTERNAL-IP   EXTERNAL-IP   OS-IMAGE             KERNEL-VERSION      CONTAINER-RUNTIME
master   Ready    control-plane   66d   v1.29.5   10.0.0.4      <none>        Ubuntu 20.04.6 LTS   5.15.0-1067-azure   containerd://1.7.18
node1    Ready    <none>          66d   v1.29.5   10.0.1.4      <none>        Ubuntu 20.04.6 LTS   5.15.0-1064-azure   containerd://1.6.31
node2    Ready    <none>          66d   v1.29.5   10.0.2.4      <none>        Ubuntu 20.04.6 LTS   5.15.0-1064-azure   containerd://1.6.31

문제는 LoadBalancer 타입이였다. 온프렘에서는 따로 LoadBalancer을 위한 조취가 필요했는데 해당 플러그인이 없어 Service에서 EXTERNAL-IP을 할당받지 못하고 있었다.

마지막으로 master노드의 외부 public ip를 통해 서비스에 할당된 포트로 접근을 시도 해 보았다.

img

정상적으로 배포된 서비스가 확인된다.


Share this post