OpenStack CCM 기반 Istio Ingress Gateway 동작 원리 및 사례 분석

OpenStack CCM의 역할과 LB 관리

Sigrid Jin
21 min readFeb 11, 2025

OpenStack Cloud Controller Manager(CCM)은 Kubernetes에서 OpenStack 클라우드 자원을 관리하는 외부 클라우드 프로바이더 컴포넌트입니다. CCM은 Kubernetes와 OpenStack API 사이에서 동작하며, 노드의 메타데이터 등록, 볼륨 연결, 네트워크 연결 설정 등을 수행합니다.

특히 Service 타입이 LoadBalancer로 생성될 경우 OpenStack CCM은 OpenStack의 Load Balancer as a Service(일반적으로 Octavia)를 호출하여 외부 로드밸런서 리소스를 생성합니다. Kubernetes 서비스에 대한 외부 IP를 자동으로 할당하고, 해당 IP로 들어온 트래픽을 클러스터 내부 서비스로 전달하는 Load Balancer를 구성하는 것이 CCM의 주요 역할입니다​. 참고로 Kubernetes v1.17부터 OpenStack CCM은 Neutron-LBaaS 대신 Octavia를 기본 로드밸런서 구현으로 사용합니다.

Istio Ingress Gateway의 역할 및 OpenStack 환경에서의 동작

Istio Ingress Gateway는 서비스 메쉬의 엣지(경계) 로드밸런서 역할을 하는 Envoy 프록시입니다. 클러스터 외부에서 들어오는 HTTP/TCP 연결을 수신하여, 정의된 라우팅 규칙에 따라 내부 서비스로 트래픽을 전달합니다. Istio Ingress Gateway는 보통 istio-system 네임스페이스에 Deployment로 실행되며, 이를 외부에 노출하기 위해 Kubernetes Service를 통해 접근합니다.

OpenStack 환경에서는 이 Ingress Gateway Service를 LoadBalancer 타입으로 설정하여 외부(IP) 를 받도록 하는 것이 일반적입니다. OpenStack CCM이 Istio Ingress Service에 대해 Floating IP를 할당한 외부 로드밸런서를 생성하고, 해당 IngressGateway의 NodePort나 Pod들을 백엔드로 연결합니다. 결과적으로 사용자는 OpenStack에서 할당된 공인 IP 주소(또는 DNS)를 통해 Istio Ingress Gateway에 접속하게 되며, Ingress Gateway는 들어온 요청을 서비스 메쉬 내부로 전달합니다. 다시 말해서 Istio Ingress Gateway는 애플리케이션 레벨 트래픽 제어를 담당하고, OpenStack CCM이 생성한 외부 로드밸런서는 네트워크 레벨에서 그 Gateway까지의 접근점을 제공하는 것입니다.

OpenStack CCM과 Istio 간 Load Balancer 생성 흐름

먼저 Istio를 설치하면 기본적으로 Ingress Gateway Deployment와 함께 istio-ingressgateway라는 Service가 만들어지는데, 클라우드 환경에서는 이 Service의 타입이 LoadBalancer로 설정됩니다. 이는 Istio 설치 프로파일에 따라 자동으로 생성되거나, 사용자가 IstioOperator 등을 통해 지정할 수 있습니다.

  • istio-system 네임스페이스에 Ingress Gateway Deployment가 올라오고 Service가 생성됩니다. 예를 들어 Istio Operator나 Helm 차트를 통해 배포하면 istio-ingressgateway 서비스가 LoadBalancer 타입으로 자동 생성됩니다.

다음으로, Kubernetes API 서버에 새로운 LoadBalancer Service가 생기면, OpenStack CCM이 이를 감지합니다. CCM은 Service의 스펙(포트, 선택자 등)과 클라우드 설정을 바탕으로 OpenStack Octavia API를 호출하여 Load Balancer를 프로비저닝합니다. 이 과정에서 OpenStack 프로젝트 내에서 로드밸런서(VIP)와 리스너, 풀 등이 생성되고, 백엔드 풀에는 Kubernetes 노드의 IP:NodePort 혹은 Pod 네트워크 IP들이 등록됩니다. 또한 외부 접근을 위해 Floating IP를 VIP에 연결하여 외부망에서도 접근 가능하도록 합니다 (cloud.conf나 Service annotation에 설정된 floating-network-id를 사용합니다)

  • OpenStack CCM(openstack-cloud-controller-manager)의 로그를 확인하면, 새로운 LoadBalancer 서비스에 대한 처리를 시작하는 메시지가 나타납니다. 정상적이라면 “Ensuring load balancer” -> “Ensured load balancer”와 같이 LB 생성이 완료되었다는 이벤트가 기록되지만 문제가 발생하는 경우 error 로그나 경고 이벤트가 나타납니다. 예를 들어, 보안 그룹 설정이나 멤버 등록 단계에서 오류가 있으면 “failed to ensure load balancer: …” 형태의 메시지나 Kubernetes Event가 발생합니다​.

마지막으로, OpenStack에서 LB 생성이 완료되면, CCM은 Kubernetes Service 객체의 .status.loadBalancer 필드에 할당된 외부 IP(Floating IP)를 업데이트합니다. 이를 통해 kubectl get svc 등을 했을 때 EXTERNAL-IP 항목에 공인 IP가 표시되고, Service가 <Pending> 상태에서 Active 상태로 바뀌게 됩니다. 이 단계까지 완료되어야 외부 트래픽이 Istio Ingress Gateway로 정상 전달됩니다.

  • kubectl describe service istio-ingressgateway -n istio-system 명령으로 서비스의 이벤트와 상태를 점검합니다. 여기서 External IP가 할당되지 않고 Pending 상태로 남아있다면, OpenStack CCM 쪽에 이슈가 있다는 신호입니다. 정상일 경우 External-IP 필드에 OpenStack이 할당한 IP가 표시됩니다.

istio-system 에서 발생한 403 오류 원인 분석

Istio Ingress Gateway를 배포한 후 istio-system 네임스페이스에서 클라이언트 요청이 403 Forbidden 응답을 받는다면 그 원인은 무엇일까요?

먼저 Istio 서비스 메쉬에서는 AuthorizationPolicy 등의 설정에 따라 요청이 거부될 수 있습니다. 만약 Istio Ingress Gateway에 기본적으로 트래픽을 거부하는 보안 정책이 설정되어 있다면(e.g. 디폴트로 모든 외부 요청 Deny), 라우팅 규칙이 없거나 권한이 없는 요청에 대해 Envoy가 RBAC: access denied라는 메시지와 함께 403 응답을 반환합니다. 실제로 다른 네임스페이스에서 Istio 서비스로 접근 시 AuthorizationPolicy에 허용 규칙이 없으면 Error: 403 - RBAC: access denied 오류가 발생하는 것이 관찰됩니다. 따라서 istio-system 네임스페이스에 Ingress Gateway에 대한 AuthorizationPolicy가 존재하거나, 상위 레벨에서 Ingress를 막는 정책이 있었다면 403의 직접적 원인이 될 수 있었습니다.

또한, OpenStack CCM 자체는 kube-system 혹은 지정된 네임스페이스에서 클라우드-컨트롤러-매니저 계정으로 실행되며, 모든 Service 자원을 업데이트할 수 있는 ClusterRole이 필요합니다. 그런데 특정 배포환경에서 이 RBAC 설정이 누락되거나 잘못되어, istio-system 네임스페이스의 Service 상태를 갱신할 권한이 없었던 사례가 있습니다. 이 경우 CCM이 LoadBalancer Service를 생성한 뒤 Service의 .status나 최종자(finalizer)를 패치하려 할 때 Kubernetes API로부터 403 Forbidden 응답을 받게 됩니다. 실제 로그에서도 “User system:serviceaccount:kube-system:cloud-controller-manager cannot patch resource “services/status” in namespace “istio-system”” 와 유사한 에러가 발생할 수 있습니다. OpenStack CCM Pod의 로그에서는 앞서 언급한 RBAC Forbidden 에러(서비스 패치 실패)나 OpenStack API 호출 에러 스택트레이스를 확인할 수 있습니다.

  • 요청 시도 시 ingressgateway 로그에 RBAC: access denied라는 문자열이 찍힌다면 Istio AuthorizationPolicy에 의한 차단임을 알 수 있습니다. 실제 OpenShift Service Mesh(Istio 기반) 환경에서 유사한 문제가 보고되었는데, ingress를 통한 접근이 안 될 때 Envoy sidecar가 “403 - RBAC: access denied”를 리턴한 사례가 있습니다​. 링크

따라서 RBAC 문제로 인해 Service 객체의 External-IP 업데이트가 막히면, OpenStack에서는 로드밸런서를 만들었어도 Kubernetes 쪽에는 반영되지 않아 서비스는 계속 Pending 상태에 머물고, 최종적으로 외부 접근이 불가능해집니다. 이로 인해 사용자는 연결 시 403 등의 오류를 만날 가능성이 있는데, LB가 아예 생성되지 않은 경우보다는 Istio 레벨의 거부 때문일 가능성이 높습니다. 다만 RBAC 문제는 403 응답보다는 서비스 미노출이나 Pending 상태로 드러나므로, 403 오류와 직접 연결되기보다는 간접적 원인으로 볼 수 있습니다.

OpenStack 측에서 CCM이 사용하는 계정의 권한 부족이나 정책 제약도 문제를 일으킬 수 있습니다. 일반적으로 OpenStack의 프로젝트 멤버 권한으로도 LB 생성은 가능하지만, 클라우드 관리자가 Octavia나 Neutron에 특수한 RBAC 정책을 걸어둔 경우(예: Load Balancer flavor나 네트워크 사용 제한) API 호출이 HTTP 403 Forbidden으로 실패할 수 있습니다​. 예를 들어, Octavia 대시보드의 과거 버그 중에는 일반 사용자로 LB 생성 시 내부적으로 관리자 전용 자원(flavor profiles)에 접근하여 403 오류가 난 사례가 있었습니다.

또한 OpenStack 정책 파일(policy.json 등)을 커스터마이징하여 LB 생성이 관리자에게만 허용되어 있었다면, CCM의 API 요청이 거부되어 로드밸런서 생성이 이루어지지 않습니다. 이 경우 Kubernetes 이벤트나 CCM 로그에 “OpenStack authorization failed (HTTP 403)”과 같은 오류가 나타나고, 결과적으로 Service는 External-IP 없이 Pending으로 남습니다. 특정 사례에서 istio-system 네임스페이스의 Istio Ingress Gateway Service가 403 문제를 겪었던 원인으로, OpenStack 쪽에 프로젝트 할당량(quota) 초과나 네트워크 접근 권한 부족도 조사되었습니다.

예컨대 프로젝트의 보안그룹 또는 포트 할당량 초과로 인해 LB 생성이 중단되었을 가능성도 있습니다 (Octavia는 LB 생성 시 VM 포트, 보안그룹 등을 생성하므로, 할당량 부족 시 오류 발생). 이런 OpenStack 측 이슈는 Istio보다는 CCM과 클라우드의 상호작용 문제로, 원인을 파악하려면 OpenStack 로그(Octavia API 로그 등)나 CCM 이벤트를 함께 살펴봐야 합니다.

문제 해결 방법

우선 OpenStack CCM의 Kubernetes 상 권한(RBAC) 을 점검해야 합니다. cloud-controller-manager 서비스어카운트에 대한 ClusterRole이 모든 네임스페이스의 Service를 업데이트(patch)할 수 있도록 설정되어 있는지 확인합니다. 만약 CCM이 kube-system이 아닌 다른 네임스페이스에 배포되었거나, 기본 제공되는 RBAC 설정이 누락되었다면 ClusterRoleBinding을 수동으로 패치해야 합니다. 예를 들어 앞서 문제를 겪은 환경에서는 CCM이 Service의 status 필드를 패치할 수 없어 오류가 났으므로, resources: ["services", "services/status"]에 대해 verbs: ["update", "patch"] 권한을 부여하도록 수정했습니다​.

RBAC 수정 후에는 CCM Pod를 재시작하거나 권한 변경 사항을 적용하여, 이후에는 Service 생성시 External-IP가 정상적으로 할당되었는지 확인합니다.

또한, Istio Ingress Gateway가 위치한 istio-system 네임스페이스에 적절한 Admission Policy나 네트워크 정책이 적용되어 있는지도 살펴봐야 합니다. 일부 조직에서는 특정 네임스페이스에서의 Service 타입 LoadBalancer 생성을 제한하거나, 외부 접근을 제어하는 NetworkPolicy를 걸어둘 수 있습니다. 이러한 정책이 Istio Ingress에 적용되면 외부 트래픽이 차단되거나 서비스 생성 자체가 거부될 수 있습니다. 따라서 istio-system 네임스페이스가 클러스터 관리 상 특별 취급되고 있지는 않은지 (Pod Security Policy, NetworkPolicy 등) 검토하고, 필요하다면 예외 규칙을 추가해야 합니다. Istio 시스템 컴포넌트가 있는 네임스페이스는 일반 애플리케이션 네임스페이스와 분리하여 관리하되, Ingress Gateway 서비스에는 외부 트래픽 허용이 필요하므로 해당 서비스에 대한 예외를 정책에 설정하는 것이 좋습니다.

마지막으로 OpenStack 측 설정도 함께 살펴봐야 완전한 해결이 가능합니다. cloud.conf 파일에 올바른 OpenStack 인증 정보와 네트워크 설정이 들어있는지 확인합니다. 특히 [LoadBalancer] 섹션에서 subnet-id, floating-network-id 등이 환경에 맞게 지정되어야 합니다. 잘못된 네트워크 ID가 설정되면 LB 생성이 실패하거나 엉뚱한 네트워크에 LB가 만들어질 수 있습니다.

또한 OpenStack에서 해당 프로젝트의 quota가 충분한지 (로드밸런서, 포트, 보안그룹 등) 확인하고, Octavia가 정상 구동 중인지도 점검해야 합니다. OpenStack 정책(Policy) 설정도 검토 포인트인데, 앞서 언급했듯이 LB 생성이 일반 사용자에게 허용되어 있는지, 혹시 모르게 특정 리소스(flavor 등)에 관리자 권한 필요 설정이 되어있지는 않은지 살펴보아야 하겠습니다. 만약 OpenStack API 호출이 스코프 문제로 실패한다면 (예: 프로젝트 스코프로 토큰이 발급되지 않아 403 발생), Keystone 인증방식을 변경하거나 Application Credential을 사용하는 방법도 고려할 수 있습니다.

OpenStack CCM의 로그에 403 오류가 직접적으로 찍힌다면 OpenStack 측에서 정책상 허용되지 않음 이라는 의미이므로, OpenStack API 권한을 조정하거나 CCM에 Admin 권한을 일시적으로 부여해볼 수 있습니다. 다만 운영 상으로는 최소 권한의 원칙을 지키는 것이 좋으므로, 가능하면 필요한 API에 대한 정책 완화 쪽으로 해결하는 것이 바람직합니다.

만약 문제의 직접 원인이 Istio의 AuthorizationPolicy였다면, 해당 정책을 수정하거나 일시적으로 비활성화해야 합니다. 예를 들어 Istio Ingress Gateway에 대해 모든 외부 요청을 허용하려면 istio-system 네임스페이스에 ingressgateway를 셀렉터로 하는 AuthorizationPolicy를 만들어 ALLOW 규칙을 지정할 수 있습니다. 또는 설치 시 기본적으로 Istio Ingress에 별도 정책이 없다면, 사용자 정의 정책 중 Ingress를 암묵적으로 막는 것이 있는지 찾아서 제거합니다.

실환경 예에서, 서비스 메쉬 전체에 적용된 디폴트 거부 정책이 Ingress까지 차단하고 있었던 적이 있습니다. 이 경우 Ingress Gateway 서비스 계정(예: istio-ingressgateway-service-account)을 대상으로 하는 예외 규칙을 추가하여, 외부로부터의 GET/POST 요청 등을 명시적으로 허용해 주었습니다.

새로운 Istio Ingress Gateway를 안전하게 배포하는 방법

기존 Ingress Gateway에 문제가 있어 재배포하거나 추가 게이트웨이를 생성할 경우, Istioctl과 Helm 등 공식 도구를 활용한 배포가 권장됩니다. 수동으로 쿠버네티스 리소스를 편집하기보다는, Istio에서 제공하는 IstioOperator CR을 사용하여 Ingress Gateway 설정을 관리하는 것도 좋습니다. 예컨대 IstioOperator 리소스에 spec.components.ingressGateways 항목을 추가하면 새로운 Ingress Gateway(다른 이름이나 포트 구성으로)를 생성할 수 있고, Istio는 이를 자동으로 배포합니다. 이 때 Service 타입을 LoadBalancer로 명시하면 OpenStack CCM이 동일하게 처리해줄 것입니다.

만약 기존 Gateway를 교체하는 시나리오라면, 절차적으로 배포하는 것이 중요합니다. 새로운 Ingress Gateway를 배포한 후 테스트를 거쳐 정상 동작이 확인되면, 기존 것을 제거하는 식으로 점진적 교체를 수행해야 중단을 피할 수 있습니다. Istio는 동시에 여러 ingressgateway를 가질 수 있으므로, Blue-Green 방식으로 Gateway를 교체할 수도 있습니다. 예를 들어 istio-ingressgateway-v2를 rollout한 뒤 Istio Gateway 리소스의 selector를 변경하여 트래픽을 새 게이트웨이로 전환하는 방식입니다. 이 과정을 통해 사용자는 가용성을 유지하면서 문제를 해결할 수 있습니다.

Istio Ingress Gateway를 배포할 때 istioctl을 사용하면, 필요한 Kubernetes 리소스(Deployment, Service, ServiceAccount, RBAC 등)가 표준적으로 생성되므로 권장됩니다​. Istioctl로 배포할 때 --set profile=<프로파일> 옵션이나 Helm Chart의 values.yaml을 통해 Ingress Gateway의 설정을 커스터마이즈할 수 있습니다.

OpenStack에서는 별도 특수 설정 없이 기본 LoadBalancer 타입을 사용하면 되지만, 예를 들어 LoadBalancer에 특정 annotation을 붙여야 할 경우 Istio Operator 설정의 serviceAnnotations를 활용해 지정할 수 있습니다. Istio Helm Chart에도 gateways.istio-ingressgateway.serviceAnnotations 항목이 있어 필요한 OpenStack annotation 을 넣을 수 있습니다.

새로운 Ingress Gateway를 생성할 때 ServiceAccount와 RBAC도 확인해야 합니다. 기본 Istio Ingress는 istio-ingressgateway-service-account를 사용하며, 이 계정에 필요한 권한(예: 필요한 경우 Secrets 읽기 등)이 부여되어 있습니다. custom gateway를 만들 경우에도 가급적 이 계정을 재사용하거나 동일 권한을 갖도록 해야 합니다. OpenStack CCM 입장에서는 어떤 서비스든 상관없이 처리하지만, Istio 측면에서 TLS 인증서 접근 등은 해당 SA 권한에 좌우되므로 이것도 배포 시 유념하셔야 하겠습니다.

기존 Ingress Gateway를 제거할 때는 Kubernetes Service를 삭제하면 OpenStack CCM이 대응하는 LoadBalancer를 자동 삭제합니다. 다만, 앞선 문제로 Service 상태가 갱신되지 못한 경우 OpenStack에 잔여 로드밸런서 리소스가 남아있을 수 있으므로, 서비스 삭제 후 OpenStack 콘솔/CLI로 확인하여 남아있는 LB가 있으면 수동으로 정리는 해주셔야만 합니다. 새로운 Gateway 배포 전에 이러한 오브젝트 청결 상태를 확인하면 충돌 없이 깨끗하게 LB를 재생성할 수 있습니다.

나가며

Kubernetes나 Istio 버전이 올라가면 CCM이나 CNI 등 인프라 컴포넌트와의 호환성에 변화가 있을 수 있으므로, 미리 테스트 클러스터에서 검증한 후 프로덕션에 반영해야 합니다. 특히 LoadBalancer 관련 기능은 쿠버네티스의 Cloud Provider 변경(In-Tree -> External CCM)이 있거나 OpenStack API의 버전 변화가 있을 때 영향을 받을 수 있으므로, Istio Ingress와 같은 핵심 경로는 배포 전후로 트래픽이 잘 흐르는지 실제 요청으로 검증하는 운영 습관을 들이는 것이 좋습니다.

--

--

No responses yet