(연습) k3s VIP 설정 (MetalLB)

2025. 11. 20. 14:21·인프라/Kubernetes
반응형

3대의 노드에 하나의 ip로 서비슬르 만들기 위해서 처음에 구상할때는 keepalived + haproxy 를 이용하려고 했다.

그런더 검색을 하다보니 이방법이 예전방식이고 Metallb 가 사실상 표준이 되었다고 한다.

 

MetalLB 설치

마스터 노드에서 설치 명령 실행

$ sudo k3s kubectl get nodes
NAME        STATUS   ROLES                  AGE     VERSION
k3s-node1   Ready    control-plane,master   6h40m   v1.33.5+k3s1
k3s-node2   Ready    <none>                 6h34m   v1.33.5+k3s1
k3s-node3   Ready    <none>                 6h31m   v1.33.5+k3s1

먼저 노드는 모두 잘 살아 있는지 확인 하고

 

$ sudo kubectl apply -f https://raw.githubusercontent.com/metallb/metallb/v0.14.5/config/manifests/metallb-native.yaml
namespace/metallb-system created
customresourcedefinition.apiextensions.k8s.io/bfdprofiles.metallb.io created
customresourcedefinition.apiextensions.k8s.io/bgpadvertisements.metallb.io created
customresourcedefinition.apiextensions.k8s.io/bgppeers.metallb.io created
customresourcedefinition.apiextensions.k8s.io/communities.metallb.io created
customresourcedefinition.apiextensions.k8s.io/ipaddresspools.metallb.io created
customresourcedefinition.apiextensions.k8s.io/l2advertisements.metallb.io created
customresourcedefinition.apiextensions.k8s.io/servicel2statuses.metallb.io created
serviceaccount/controller created
serviceaccount/speaker created
role.rbac.authorization.k8s.io/controller created
role.rbac.authorization.k8s.io/pod-lister created
clusterrole.rbac.authorization.k8s.io/metallb-system:controller created
clusterrole.rbac.authorization.k8s.io/metallb-system:speaker created
rolebinding.rbac.authorization.k8s.io/controller created
rolebinding.rbac.authorization.k8s.io/pod-lister created
clusterrolebinding.rbac.authorization.k8s.io/metallb-system:controller created
clusterrolebinding.rbac.authorization.k8s.io/metallb-system:speaker created
configmap/metallb-excludel2 created
secret/metallb-webhook-cert created
service/metallb-webhook-service created
deployment.apps/controller created
daemonset.apps/speaker created
validatingwebhookconfiguration.admissionregistration.k8s.io/metallb-webhook-configuration created

뭔가 엄청 빠른 속도로 끝이 났다.

 

각 노드에서 잘 설치 되었는지 확인해 보자.

$ sudo k3s kubectl get pods -n metallb-system
NAME                          READY   STATUS    RESTARTS   AGE
controller-654858564f-tkxcc   1/1     Running   0          3h41m
speaker-4hm7x                 1/1     Running   0          3h41m
speaker-r5pvd                 1/1     Running   0          3h41m
speaker-w5k89                 1/1     Running   0          3h41m

컨트롤 1개에 노드 3개니까 스피커 3개면 정상

restarts 가 0에 가까워야 이슈없음

$ sudo k3s kubectl get ds -n metallb-system
NAME      DESIRED   CURRENT   READY   UP-TO-DATE   AVAILABLE   NODE SELECTOR            AGE
speaker   3         3         3       3            3           kubernetes.io/os=linux   3h42m

Desired : 3, 즉 3대의 노드에 실행되기를 희망하는데 현재 3개가 돌고 있으므로 잘 설정됨

 

이제부터는 k3s 설치후 처음으로 설정파일을 만들어 보려고 한다.

설정파일은 어디에 두어도 좋다고 하는데

나는 루트 밑에 k8s 디렉토리를 만들어서 두려고 한다.

 

master 에만 두어도 되는건지 아직은 잘 모르겠으나 일단 가이드대로 해본다.

 

AI가 이런식으로 설정 구조를 가져가라고 추천해준다.

일단 이렇게 해보는것이 시행착오를 줄일것 같으니 해보자.

1단계: IPAddressPool 생성 (IP 주소 범위 정의)

@k3s-node1:/k8s/system/metallb

위치에 생성한다.

$ sudo vi ipaddresspool.yaml
# ipaddresspool.yaml
apiVersion: metallb.io/v1beta1
kind: IPAddressPool
metadata:
  name: my-proxmox-vip-pool
  namespace: metallb-system
spec:
  # 10.34.1.150 단일 IP만 할당하기 위해 /32 서브넷 마스크를 사용합니다.
  addresses:
  - 10.34.1.150/32
~
~

$ sudo kubectl apply -f ipaddresspool.yaml
ipaddresspool.metallb.io/my-proxmox-vip-pool created

적용까지 하니까 뭔가 빠르게 끝난다.

 

2단계: L2Advertisement 생성 (L2 모드 광고 활성화)

정의된 IP 주소 풀을 L2(ARP/NDP) 모드로 클러스터 노드가 네트워크에 광고하도록 설정하는 설정이라고 한다.

내가 이런 아이피를 vip를 쓸거야 니들 노드들 잘 알고 있어..~ 뭐 이런건가 보다.

# l2advertisement.yaml
apiVersion: metallb.io/v1beta1
kind: L2Advertisement
metadata:
  name: l2-advertisement-for-vip
  namespace: metallb-system
spec:
  # 위에서 정의한 IPAddressPool 이름을 지정합니다.
  ipAddressPools:
  - my-proxmox-vip-pool
  
  
$ sudo kubectl apply -f l2advertisement.yaml
l2advertisement.metallb.io/l2-advertisement-for-vip created

 

3단계: 서비스 생성 및 VIP 할당 확인

2단계까지 했으면 실제 VIP 셋팅은 끝난것으로 보인다.

그럼 실제로 서비스 + pod 를 만들어서 잘 되는지를 확인해 보면 될것 같다.

일단 nginx 를 하나 올리고 기본 페이지가 뜨는 것을 해보도록 한다.

 

nginx pod 배포

파일 구조는 아래처럼 하려고 한다.

베이스를 두고 설정이 달라질수 있는 부분을 별도로 빼서 관리하는게 정석이라고 안내를 해준다.

# k8s/apps/test-nginx/base/deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx-deployment
  labels:
    app: nginx
spec:
  replicas: 1 # 기본값은 1개
  selector:
    matchLabels:
      app: nginx
  template:
    metadata:
      labels:
        app: nginx
    spec:
      containers:
      - name: nginx
        image: nginx:latest
        ports:
        - containerPort: 80
# k8s/apps/test-nginx/base/service.yaml
apiVersion: v1
kind: Service
metadata:
  name: nginx-vip-service
spec:
  selector:
    app: nginx
  ports:
    - protocol: TCP
      port: 80
      targetPort: 80
  type: LoadBalancer # MetalLB가 인식하는 타입
# k8s/apps/test-nginx/base/kustomization.yaml
resources:
- deployment.yaml
- service.yaml

순서대로 이렇게 만들어 주고 production 설정을 만든다.

내용을 쭉보니 base 에서 만든설정들을 베이스로 overwrite 를 해서 최종 설정을 하는듯 하다.

 

production 설정

# k8s/apps/test-nginx/production/kustomization.yaml 최종 수정본

apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization

resources:
- ../base
- ingress.yaml

patches:
# --- 패치 1: Deployment의 Pod 개수(replicas) 수정 (유지) ---
- target:
    kind: Deployment
    name: nginx-deployment
  patch: |
    - op: replace
      path: /spec/replicas
      value: 3
# --------------------------------------------------

# --- 패치 2: Service 타입을 ClusterIP로 변경 (새로 추가) ---
- target:
    kind: Service
    name: nginx-vip-service
  patch: |
    - op: replace
      path: /spec/type
      value: ClusterIP # LoadBalancer 대신 ClusterIP로 변경
# -----------------------------------------------------------

 

ingress 도 설정한다.

(Ingress는 클러스터 외부에 Pod의 IP 주소나 NodePort를 직접 노출하지 않으면서, 사용자 친화적인 방식으로 서비스에 접근할 수 있게 해줍니다.)

$ vi ingress.yaml
# nginx-ingress.yaml 파일 수정 (또는 새로운 ingress 추가)
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: nginx-default-ingress
  annotations:
    kubernetes.io/ingress.class: traefik
spec:
  rules:
  # --- 기존 Host 규칙 ---
  - host: nginx.prod.local
    http:
      paths:
      - path: /
        pathType: Prefix
        backend:
          service:
            name: nginx-vip-service
            port:
              number: 80
~
~
~

 

여기까지 하고 적용하면

$ sudo kubectl apply -k /k8s/system/apps/test-nginx/production
service/nginx-vip-service created
deployment.apps/nginx-deployment configured

 

요렇게 잘 끝났다고 나온다.

그럼 잘 돌아가는지 한 번 볼까?

$ sudo k3s kubectl get svc nginx-vip-service
NAME                TYPE           CLUSTER-IP      EXTERNAL-IP   PORT(S)        AGE
nginx-vip-service   LoadBalancer   10.43.229.103   <pending>     80:32558/TCP   2m36s

 

이제 호출해보자

$ curl -H "Host: nginx.prod.local" http://10.34.1.150
<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
<style>
html { color-scheme: light dark; }
body { width: 35em; margin: 0 auto;
font-family: Tahoma, Verdana, Arial, sans-serif; }
</style>
</head>
<body>
<h1>Welcome to nginx!</h1>
<p>If you see this page, the nginx web server is successfully installed and
working. Further configuration is required.</p>

<p>For online documentation and support please refer to
<a href="http://nginx.org/">nginx.org</a>.<br/>
Commercial support is available at
<a href="http://nginx.com/">nginx.com</a>.</p>

<p><em>Thank you for using nginx.</em></p>
</body>
</html>
taehyongi@k3s-node1:/k8s/system/apps/test-nginx/production$

성공했다.

그런데 왜 curl 로 했느냐..

traefik 이라는 솔루션은 Host 기반으로 처리한다고 한다.

가상 컨테이너 구조상 같은 vip 로 여러 서비스가 올라갈텐데 서비스를 구분하기 위해서 

포트를 구분할수도 있을텐데 도메인으로 구분한다는 것이다.

설정을 하면 아이피로도 할수 있는것 같은데 host 가 기본이고 이것이 맞으므로 일단 그대로 둔다.

 

브라우저에서 10.34.1.150 으로 접속하면 not found 에러가 나온다.

Git 으로 설정 관리

참고로 여기까지 하고 이 설정들이 master 노드에 있다면 이 노드인 1번 서버가 죽어버리면 어떻게 되는거지?

하는 의문이 생겼다. 검색해보니.. etcd 라는 내부 저장소에 이것들이 모두 올라간다고 한다.

그럼 실제 노드들끼리는 그 etcd 를 바라본다는 얘기이다.

위에서 만든 yaml 파일을을 kubectl 로 apply 하는 과정은 설치 과정 뿐만 아니라 etcd 에 올리는 과정이 포함되어 있을것이라고 본다.

그럼 이 설정파일들을 잊어버리면 안되므로 git 을 통해 최신화 관리를 하는것이 바람직한 방법으로 보인다.

 

다음으로는 도메인으로 어느 서비스로 갈지 분기하는것을 해보자.

ssl 인증서도 자동 셋팅하고...

반응형

'인프라 > Kubernetes' 카테고리의 다른 글

(연습) k3s HA 구성 트래픽 흐름 구조  (0) 2025.11.21
(연습) k3s 설치하기 (마스터1, 워커2 설치)  (0) 2025.11.17
'인프라/Kubernetes' 카테고리의 다른 글
  • (연습) k3s HA 구성 트래픽 흐름 구조
  • (연습) k3s 설치하기 (마스터1, 워커2 설치)
GG.Lab
GG.Lab
GG.Lab
    반응형
  • GG.Lab
    GG.Lab
    GG.Lab
  • 전체
    오늘
    어제
    • 분류 전체보기 (41) N
      • APP (25)
        • 함쓰가계부 (22)
        • 랭킹구구단 (3)
      • 인프라 (11) N
        • Docker (1)
        • Proxmox (4)
        • Kubernetes (3) N
        • Network (3) N
      • DB (5)
        • Postgresql (5)
  • 블로그 메뉴

    • 홈
    • 태그
    • 방명록
    • 함쓰 메뉴얼
    • 함쓰 카페
  • 링크

  • 공지사항

  • 인기 글

  • 태그

    연인가계부
    serial컬럼중복
    푸시인식
    가족가계부
    스피드구구단
    해외통화지원
    푸시인식가계부
    부부가계부
    sms인식가계부
    Flutter
    구구단
    k3s
    랭킹구구단
    실적자동푸시
    sms자동등록
    pfsense
    자작앱
    해외통화가계부
    플러터
    공유가계부
    앱출시
    함쓰
    가계부공유
    함께쓰는가계부
    커플가계부
    Proxmox
    가계부편의기능
    문자자동인식가계부
    문자자동인식
    함쓰가계부
  • 최근 댓글

  • 최근 글

  • hELLO· Designed By정상우.v4.10.5
GG.Lab
(연습) k3s VIP 설정 (MetalLB)
상단으로

티스토리툴바