반응형

Amazon EKS, Azure AKS, Google GKE 등과 비슷하게 Oracle OKE에서도 Network LB가 제공된다.

 

Managed Kubernetes를 사용할 때 항상 등장하는 Load Balancer와 Network Load Balancer가 비슷하면서 약간 다른데,

Oracle Cloud Infrastructure의 User Manual에는 아래와 같이 설정하고 있다.

 

 

Load Balancer

Oracle OKE - Load Balancer

  A Load Balancer improves resource utilization, facilitates scaling, and helps ensure high availability. You can configure multiple load balancing policies and application-specific health checks to ensure that the load balancer directs traffic only to healthy instances. Includes: advanced proxy features such as layer-7 routing and SSL termination.

그림에서 묘사한 것처럼

  • HTTP
  • HTTPS
  • TCP

프로토콜을 사용하는 Backend 서비스만 지원한다. 

따라서 UDP나 Dedicated Protocol을 사용하는 Backend 서비스가 있는 경우에 이 LB를 사용할 수 없다. ㅠㅠ

 

Network Load Balancer (일명, NLB)

Oracle OKE - Network Load Balancer (NLB)

A Network Load Balancer is a non-proxy layer-4 load balancing solution. It offers a scalable VIP to the customer and additionally provides the benefits of flow high availability, low latency, and source IP and port preservation.
Includes: layer-4 pass-through load balancing and client header preservation.

그림에서 묘사한 것처럼

  • TCP
  • UDP                                             # <-- 이것이 LB와 NLB가 다른 부분이다. 
  • 기타... 아무거나 다 (Any ~~~)      # <-- 이것이 LB와 NLB가 다른 부분이다.  

프로토콜을 사용하는 Backend 서비스를 지원한다. 

그런데 Oracle Cloud Infra에서는 이 NLB(Network LB)는 3개까지만 사용하도록 제한하고 있다.

OCI Web Console에서는 이 NLB Max Limit을 설정하는 메뉴가 안 보이는데, 아마 Oracle에 직접 전화해서 NLB 개수를 Upgrade해야 하는 것 같다. (아직, 확실하진 않고... 내일 Oracle에 한번 전화해서 물어봐야겠다..)

반응형

Kubernetes service의 manifest를 작성하다보면, port와 targetport가 헷갈린다.

각 term이 의미하는 것을 지금 이해해도, 몇 개월 뒤에 다시 service resource에 대한 manifest를 작성하려고 보면 또 헷갈려서 다시 문서를 뒤적거리게 된다.

 

  • Port
    • Service Object 자체의 Port.  즉, 여러 Pod를 묶어서 이 Port 값으로 노출시킨다.
    • 한 kubernetes cluster 내에서 다른 pod가 내 pod에게 Layer 4 메시지를 전송할 때 바라보는 port number.
    • 만약 MetalLB, NGINX 같은 Ingress Gateway를 사용하는 경우라면, 이 'port' 값이 Cluster 외부에서 LB(즉, Ingress Gateway)를 통해 들어오는 Port number가 된다.
      예를 들어,   http://{EXTERNAL-IP}:{SERVICE-PORT}
      이런 형태가 된다.
  • TargetPort
    • 내 pod 안에 있는 container가 listening하고 있는 port number.
    • container(즉, app)이 어떤 port를 listening하고 있는지 정확한 값을 알고 설정해야 한다. (HTTPD 설정시 기본 값을 이용했다면, 대부분 80이지 않을까?)
  • NodePort
    • kubernetes 밖으로 노출시킬 port number.
    • Ingress Gateway 또는 Istio를 사용하는 경우에는 딱히 설정할 필요없는 설정 항목.

 

 

Example

만약 2개의 TCP Port를 Service로 오픈하고 싶다면, 아래와 같이 Service Resource와 Pod Resource를 설정한다.

 

##
## Service Manifest Example
##
kind: Service
metadata:
... 중간 생략 ...
spec:
  ports:
  - name: metrics
    port: 24231
    protocol: TCP
    targetPort: metrics
  - name: logfile-metrics
    port: 2112
    protocol: TCP
    targetPort: logfile-metrics
... 중간 생략 ...   
    


##
## Pod Manifest Example
##
kind: Pod
metadata:
... 중간 생략 ...
spec:
  containers:
    name: my-container  
    ports:
    - containerPort: 24231
      name: metrics
      protocol: TCP
    - containerPort: 2112
      name: logfile-metrics
      protocol: TCP
... 중간 생략 ...

'kubernetes' 카테고리의 다른 글

MetalLB BGP 모드를 이용한 Loadbalaning  (0) 2021.08.30
Istio Circuit Break  (0) 2021.08.07
Dockerfile Example  (0) 2021.07.19
Istio Web Docs - 읽기 좋은 순서대리 정리  (0) 2021.07.19
Kubernetes Port-Forward 설정  (2) 2021.07.10
반응형

 

MetalLB v0.13.x  설치 및 테스트 (2023년 2월 14일)

MetalLB의 버전에 따라 설치 결과가 조금씩 달라서 MetalLB를 설치한 날짜를 밝힌다.

아래 절차를 따라하면 MetalLB 설치, 그리고 예제 앱 테스트 모두 잘 동작한다.

 

 

MetalLB 설치에 관한 공식 문서는 아래 Web Docs를 참고
   https://metallb.universe.tf/installation/

 

 

위 Web Docs는 여러 도구를 이용한 설치 방법을 설명하지만, 나는 Manifest  방식을 이용하여 MetalLB를 설치했다.

위 Web docs를 보면서 따라해보면, 막힘없이 쭉쭉~ 잘 설치되었다.

설치 완료한 이후에 LB 테스트를 해봤는데 잘 동작했다.

내가 설치한 환경은 이렇다.


Kubernetes: v1.25.3
CNI: Calico v3.24.5

 

내가 Web docs를 보면서 수행했던 명령 및 설정 파일 편집한 내역만 추려보면 이렇다.

 

strict ARP mode 활성화하기

아래 예제처럼 kube-proxy  configmap을 수정한다. 

(strictARP 항목을 false 에서 true 로 변경)

## 아래 명령을 수행
$  kubectl edit configmap -n kube-system kube-proxy

... 중간 생략 ...

apiVersion: kubeproxy.config.k8s.io/v1alpha1
kind: KubeProxyConfiguration
mode: "ipvs"
ipvs:
  strictARP: true  ## 이 부분을 수정한다.  false -> true

... 중간 생략 ...

 

Manifest 이용하여 Metal LB 설치하기

아래 명령을 따라서 수행한다.

$  kubectl apply -f https://raw.githubusercontent.com/metallb/metallb/v0.13.7/config/manifests/metallb-native.yaml


##
## MetalLB가 잘 설치되었다면,
## 아래와 같이 metallb-controller와 metallb-speaker pod가 Running 상태로 보일 것이다.
##

$  kubectl get -n metallb-system pod
NAME                          READY   STATUS    RESTARTS   AGE
controller-84d6d4db45-g94mh   1/1     Running   0          31s
speaker-6jqzw                 1/1     Running   0          31s
speaker-hlrg7                 1/1     Running   0          31s
speaker-sq94q                 1/1     Running   0          31s


## 참고: speaker가 running 상태가 되려면 대략 25~30초 정도 걸린다.
##      Pod의 상태가 ConfigErr로 보인다고 당황해하지 않아도 된다.
##      30초 후에 Running 상태로 변경될거다.

 

IP Address Pool 설정하기

$  cat >> my-network.yaml <<-EOF

apiVersion: metallb.io/v1beta1
kind: IPAddressPool
metadata:
  name: first-pool
  namespace: metallb-system
spec:
  addresses:
  - 10.1.4.160/28
  - 10.1.4.176/28
  - 10.1.4.192-10.1.4.200

---

apiVersion: metallb.io/v1beta1
kind: IPAddressPool
metadata:
  name: second-pool
  namespace: metallb-system
spec:
  addresses:
  - 10.1.4.150-10.1.4.159


---


apiVersion: metallb.io/v1beta1
kind: L2Advertisement
metadata:
  name: my-network-l2
  namespace: metallb-system
spec:
  ipAddressPools:
  - first-pool
  - second-pool
  
EOF

$  kubectl apply -n metallb-system -f my-network.yaml

ipaddresspool.metallb.io/first-pool created
ipaddresspool.metallb.io/second-pool created
l2advertisement.metallb.io/my-network-l2 created

$

 

 

주의할 점:
  위와 같이 L2Advertisement, IPAddressPool을 변경하고 적용해도 실제로 Service resource가 생성될 때,
  과거의 IPAddressPool을 이용한다.
  아마 MetalLB  버그 같은데, 과감하게 metallb-system 네임스페이스의 controller pod를 종료시키고 재기동하면 
  새로운 IPAddressPool이 적용된다. (아래 명령을 참고)

 

$ kubectl get -n metallb-system pod -l component=controller

NAME                          READY   STATUS    RESTARTS   AGE
controller-84d6d4db45-vgt9r   1/1     Running   0          6m12s

$ kubectl delete -n metallb-system pod controller-84d6d4db45-vgt9r

## 20초 정도 후에 Pod가 재기동되고, 그 뒤로 새로운 IPAddressPool이 정상적으로 반영된다.

 

 

 

Example App을 이용하여 MetalLB 동작 확인

$  cat >> my-example.yaml <<-EOF
apiVersion: v1
kind: Pod
metadata:
  name: almighty
  labels:
    app: almighty
spec:
  terminationGracePeriodSeconds: 3
  containers:
  - name: almighty
    image: docker.io/andrewloyolajeong/almighty:0.2.4

---

apiVersion: v1
kind: Service
metadata:
  name: almighty
spec:
  type: LoadBalancer
  externalTrafficPolicy: Local
  selector:
    app: almighty
  ports:
    - name: myweb
      protocol: TCP
      port: 8080
      targetPort: 8080
    - name: yourweb
      protocol: TCP
      port: 80
      targetPort: 80

EOF

$

$  kubectl create ns ns1


$  kubectl apply -n ns1 -f my-example.yaml


$  kubectl get -n ns1 svc

NAME       TYPE           CLUSTER-IP       EXTERNAL-IP   PORT(S)                       AGE
almighty   LoadBalancer   10.104.156.217   10.1.4.150    8080:30859/TCP,80:31917/TCP   116s

$

##
## 위 결과에서 EXTERNAL-IP에 적절한 IP Address가 출력되면, 잘 되는 것이다.
## 그리고 아래와 같이 실제로 MetalLB가 할당해준 10.1.4.150 주소를 통해 Networking이 되는지 확인한다.
##

$  curl 10.1.4.150:8080

 Hello from example application. (written by Andrew)
 
$  curl 10.1.4.150:80

<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
<style>
...
...
<p><em>Thank you for using nginx.</em></p>
</body>
</html>

$

 

올레~~~ 잘 동작한다 ^^

 

 

 

 


 

 

참고:  ping 명령으로 EXTERNAL-IP 통신 여부를 확인하지 말 것 !!!

MetalLB 설치하고, 많은 사용자들이 실수하는 것이 아래처럼 ping 명령으로 External-IP로 ICMP 패킷이 전달되는지 체크한다.

$ ping 10.10.12.43

MetalLB가 만든 External-IP 주소는 K8S Cluster의 특정 Worker Node의 Netfilter에만 존재하는 Chain Rule일 뿐이다.

즉, OS Kernel이 물린 Network Port의 MAC Address에 Binding한 IP Address가 아니다보니, OS Kernel이 ICMP Echo Request에 대해 반응할리 없다. 단, K8s LoadBalancer 구현체(즉, MetalLB)의 구현에 따라서 MetalLB가 직접 ICMP Echo Response를 만들 수는 있지만, 이것은 구현체의 버전에 따라 다를 수 있으니까 ICMP Echo(즉, Ping)에 대한 테스트를 시도하지 않는 것이 좋다.

아래와 같이 CURL을 이용하여 테스트하는 것이 정확한 테스트 방법이다.

$ curl  https://10.10.12.43:8443

다시 한번 강조한다.  절대 ping 명령으로 MetalLB의 External-IP 동작 유무를 체크하지 말자 !!!

 

 

 

 

참고:  Address 설정은  모든 대역의 주소가 다 가능한다.

아래 설정 예제처럼 특정 addresses 대역을 사용하겠다고 지정하면, MetalLB Speaker가 알아서 동일한 Broadcast Domain에 해당하는 Network Port로 GARP(Gratuitous ARP)를  Broadcasting한다.

 

$  vi metallb/values.yaml
... 중간 생략 ...
configInline:
  address-pools:
   - name: default
     protocol: layer2
     addresses:
     - 10.10.12.40/29
... 중간 생략 ...

따라서 Worker Node에 Network Port가 여러 개 있다면, 위 address-pools에 설정된 ip address 대역 중에서 broadcast domain이 일치하는 Network Port로 GARP 패킷이 흘러나간다.

 

 

 

참고:  특정 Service에 특정 External-IP(Public IP)를 고정해서 사용하기

External-IP는 Kubernetes Cluster 밖에 있는 Client App이 접근하기 위한 주소이기 때문에 고정하는게 운영상 편하다.

그런데 MetalLB는 IP Address Range를 설정하도록 되어 있기 때문에 K8s Service 생성시 어떤 External-IP가 K8s Service에 할당될지 알 수 없다.

이럴 때 아래와 같이 K8s Service에 설정을 추가하면 특정 External-IP(즉, Public IP Address)를 고정해서 사용할 수 있다.

 

$ cat  my-svc.yaml

apiVersion: v1
kind: Service
metadata:
  name: mysvc
  
(... 중간 생략 ...)

spec:
  type: LoadBalancer
  ## MetalLB의 IP Address Range가 211.10.3.160 ~ 190 이라고 가정하고
  ## 이 mysvc에 211.10.3.165 주소를 고정해서 사용하고 싶아면 아래와 같이 사용한다.
  loadBalancerIP: 211.10.3.165

(... 중간 생략 ...)

 

 

게시물 작성자: sejong.jeonjo@gmail.com

 

 

+ Recent posts