-
[GCP] GKE 인그레스와 cloud Load balancingAWS & GCP 2025. 3. 31. 23:39
GKE에서 인그레스를 세팅하고 배포하면 자동으로 cloud load balancing 서비스를 전개합니다. 여기서 ingress나 service에 어노테이션을 추가하여 cloud load balancing 서비스의 옵션을 설정하거나 정상 실행을 하려면 꼭 있어야 하는 옵션에 대해 설명합니다.
설정
다음과 같이 values, service, ingress가 세팅이 되어있고 배포를 했다고 가정합니다.
# Default values for mario. # This is a YAML-formatted file. # Declare variables to be passed into your templates. replicaCount: 2 resources: limits: cpu: 1000m memory: 4Gi requests: cpu: 1000m memory: 4Gi image: repository: us-docker.pkg.dev/google-samples/containers/gke/hello-app pullPolicy: IfNotPresent # Overrides the image tag whose default is the chart appVersion. tag: "1.0" imagePullSecrets: [] nameOverride: "" fullnameOverride: "" serviceAccount: # Specifies whether a service account should be created create: true # Automatically mount a ServiceAccount's API credentials? automount: true # Annotations to add to the service account annotations: {} # The name of the service account to use. # If not set and create is true, a name is generated using the fullname template name: "" podAnnotations: {} podLabels: {} podSecurityContext: {} # fsGroup: 2000 securityContext: {} # capabilities: # drop: # - ALL # readOnlyRootFilesystem: true # runAsNonRoot: true # runAsUser: 1000 service: type: ClusterIP port: 80 targetPort: 8080 # annotations: # cloud.google.com/neg: '{"ingress": true}' # cloud.google.com/backend-config: '{"default": "my-backendconfig"}' ingress: enabled: true className: "gce" # gke에서는 classname은 사용하지 않고 annotations를 사용한다. 따라서 제거해도 무방함 annotations: kubernetes.io/ingress.class: gce # kubernetes.io/ingress.global-static-ip-name: "test-ip" # 고정 IP 사용시 리전 귀속 IP가 아닌, 전역 IP만 연결이 가능 # kubernetes.io/ingress.allow-http: "true" # networking.gke.io/v1beta1.FrontendConfig: "my-frontendconfig" tls: [] # - secretName: chart-example-tls # hosts: # - chart-example.local autoscaling: enabled: false minReplicas: 1 maxReplicas: 2 targetCPUUtilizationPercentage: 80 # targetMemoryUtilizationPercentage: 80 # Additional volumes on the output Deployment definition. volumes: [] # - name: foo # secret: # secretName: mysecret # optional: false # Additional volumeMounts on the output Deployment definition. volumeMounts: [] # - name: foo # mountPath: "/etc/foo" # readOnly: true nodeSelector: {} tolerations: [] affinity: {}
values.yaml
apiVersion: v1 kind: Service metadata: name: {{ include "mario.fullname" . }} {{- with .Values.service.annotations }} annotations: {{- toYaml . | nindent 4 }} {{- end }} labels: {{- include "mario.labels" . | nindent 4 }} spec: type: {{ .Values.service.type }} ports: - port: {{ .Values.service.port }} targetPort: {{ .Values.service.targetPort }} protocol: TCP name: http selector: {{- include "mario.selectorLabels" . | nindent 4 }}
service.yaml
{{- if .Values.ingress.enabled -}} {{- $fullName := include "mario.fullname" . -}} {{- $svcPort := .Values.service.port -}} apiVersion: networking.k8s.io/v1 kind: Ingress metadata: name: {{ $fullName }} labels: {{- include "mario.labels" . | nindent 4 }} {{- with .Values.ingress.annotations }} annotations: {{- toYaml . | nindent 4 }} {{- end }} spec: ingressClassName: {{ .Values.ingress.className }} {{- if .Values.ingress.tls }} tls: {{- range .Values.ingress.tls }} - hosts: {{- range .hosts }} - {{ . | quote }} {{- end }} secretName: {{ .secretName }} {{- end }} {{- end }} defaultBackend: service: name: {{ $fullName }} port: number: {{ $svcPort }} rules: {{/* - host: chart-example.local # 호스트가 현재 없음*/}} - http: paths: - path: / pathType: ImplementationSpecific backend: service: name: {{ $fullName }} port: number: {{ $svcPort }} {{- end }}
ingress.yaml
위 차트를 배포하면 cloud load balancing에 아래와 같이 자동으로 배포가 된 것을 볼 수 있습니다.
gke에서 인그레스가 정상적으로 실행되려면 startup probe가 구성되어 있어야함
만약 startup probe가 필요없다고 해서 제거하면 인그레스가 정상적으로 실행되지 않고 cloud load balancing 서비스 또한 프론트엔드(외부)에서 받은 트래픽을 백엔드(내부=인그레스)로 전달할 수 없게 됩니다.
인그레스 클래스 네임
GKE에서는 ingress class name을 다음과 같이 설정할 수 있습니다.
kubernetes.io/ingress.class 값 ingressClassName 값 GKE 인그레스 컨트롤러 동작
설정되지 않음 설정되지 않음 인그레스 매니페스트를 처리하고 외부 애플리케이션 부하 분산기를 만듭니다. 설정되지 않음 모든 값 수행할 작업이 없습니다. 인그레스 매니페스트가 타사 인그레스 컨트롤러(배포된 경우)로 처리될 수 있습니다. gce 모든 값 이 필드는 무시됩니다. 인그레스 매니페스트를 처리하고 외부 애플리케이션 부하 분산기를 만듭니다. gce-internal 모든 값 이 필드는 무시됩니다. 인그레스 매니페스트를 처리하고 내부 애플리케이션 부하 분산기를 만듭니다. gce 또는 gce-internal 이외의 값으로 설정 모든 값 수행할 작업이 없습니다. 인그레스 매니페스트가 타사 인그레스 컨트롤러(배포된 경우)로 처리될 수 있습니다. 이전 GKE 버전을 실행하는 클러스터의 경우 GKE 컨트롤러는 kubernetes.io/ingress.class 주석이 없거나 gce 또는 gce-internal 값의 주석이 있는 인그레스를 처리합니다.
kubernetes.io/ingress.class 어노테이션은 Kubernetes에서 지원 중단되었지만 GKE는 이 어노테이션을 계속 사용합니다. 즉, ingressClassName 필드를 사용하여 GKE 인그레스를 지정할 수 없고 kubernetes.io/ingress.class 어노테이션을 사용해야 합니다.
인그레스, 서비스의 어노테이션으로 cloud load balancing 서비스 옵션 설정
인그레스와 서비스에 어노테이션을 추가해 cloud load balancing 서비스의 옵션을 설정할 수 있습니다.
인그레스 어노테이션
주석 설명 kubernetes.io/ingress.allow-http 클라이언트와 HTTP(S) 부하 분산기 간에 HTTP 트래픽을 허용할지 여부를 지정합니다. 가능한 값은 'true', 'false'입니다. 기본값은 'true'입니다. HTTP 중지를 참조하세요. ingress.gcp.kubernetes.io/pre-shared-cert 이 주석을 사용하여 GKE 인그레스 리소스에 인증서 리소스를 연결합니다. 자세한 내용은 외부 애플리케이션 부하 분산기에 여러 SSL 인증서 사용을 참조하세요. kubernetes.io/ingress.global-static-ip-name 이 주석을 사용하여 부하 분산기에서 이전에 만든 고정 외부 IP 주소를 사용하도록 지정합니다. HTTP(S) 부하 분산기의 고정 IP 주소를 참조하세요. networking.gke.io/v1beta1.FrontendConfig 이 주석을 사용하여 부하 분산기의 클라이언트 연결 구성을 맞춤설정합니다. 자세한 내용은 인그레스 구성을 참조하세요. networking.gke.io/suppress-firewall-xpn-error 인그레스 부하 분산기의 경우, Kubernetes가 권한 부족으로 인해 방화벽 규칙을 변경할 수 없으면 몇 분 간격으로 firewallXPNError
이벤트가 발생합니다. GLBC 1.4 이상에서는 인그레스 리소스에networking.gke.io/suppress-firewall-xpn-error: "true"
주석을 추가하여firewallXPNError
이벤트가 발생하지 않도록 할 수 있습니다. 이 주석을 삭제하면 이벤트가 다시 발생합니다. 가능한 값은true
및false
입니다. 기본값은false
입니다.서비스 어노테이션
주석 설명 cloud.google.com/app-protocols 이 주석을 사용하여 부하 분산기와 애플리케이션 간의 통신 프로토콜을 설정합니다. 가능한 프로토콜은 HTTP, HTTPS, HTTP2입니다. 부하 분산기와 애플리케이션 간 HTTPS 및 인그레스를 사용한 부하 분산용 HTTP/2를 참조하세요. cloud.google.com/backend-config 이 주석을 사용하여 서비스와 연결된 백엔드 서비스를 구성합니다. 자세한 내용은 인그레스 구성을 참조하세요. cloud.google.com/neg 이 주석을 사용하여 부하 분산기에서 네트워크 엔드포인트 그룹을 사용하도록 지정합니다. 컨테이너 기반 부하 분산 사용을 참조하세요. 예시
고정 IP 설정하기
위 인그레스의 어노테이션을 통해 고정 IP를 명시해 사용할 수 있습니다. 만약 해당 어노테이션이 없다면 cloud load balancing 서비스는 자동으로 임시 외부 IP를 발급받아 사용하며 해당 서비스가 제거되면 IP 또한 삭제됩니다.
해당 어노테이션을 사용하기 전, 한 가지 제약사항으로는 해당 어노테이션을 사용하기 전 미리 고정 IP를 등록해줘야 합니다. 또한 고정 IP를 사용하려면 리전 귀속 IP가 아닌 전역 IP만 가능합니다. 25-03-31 기준으로 표준 계층의 IP는 리전 귀속 IP만 사용 가능하므로 프리미엄 계층의 전역 IP로 생성해야 합니다. 이러한 이유는 cloud load balancing 서비스는 글로벌 리소스이므로 리전 귀속 IP는 허용하지 않는 것으로 보입니다.
사용 방법은 다음과 같습니다.
- 프리미엄 계층의 전역 고정 IP 생성
- 인그레스의 어노테이션에
kubernetes.io/ingress.global-static-ip-name: "static-ip"
와 같이 1번에서 생성한 고정 IP 이름 명시 - 배포
cloud load balancing 서비스의 프론트엔드 설정을 어노테이션으로 설정하기
cloud load balancing 서비스의 콘솔의 수정 화면에서 프론트엔드 설정을 확인해보면 다음과 같이 여러 설정을 할 수 있는 것으로 확인할 수 있습니다.
프론트엔드 추가/수정 화면 프론트엔드 구성은 SSL 정책, HTTP-HTTPS 리디렉션을 추가할 수 있습니다.
다음과 같은 yaml 파일을 추가하고 인그레스의 어노테이션에 추가합니다.
# frontconfig.yaml apiVersion: networking.gke.io/v1beta1 kind: FrontendConfig metadata: name: my-frontendconfig # 어노테이션에서 사용할 이름 spec: sslPolicy: test-mario-domain # SSL 정책 설정 redirectToHttps: # http 요청을 https로 리다이렉트 enabled: true responseCodeName: MOVED_PERMANENTLY_DEFAULT
frontconfig.yaml
ingress: enabled: true className: "gce" # gke에서는 classname은 사용하지 않고 annotations를 사용한다. 따라서 제거해도 무방함 annotations: networking.gke.io/v1beta1.FrontendConfig: "my-frontendconfig"
values.yaml
responseCodeName은 다음 중 하나를 입력하면 되고 입력을 하지 않으면
MOVED_PERMANENTLY_DEFAULT
이 기본값으로 설정됩니다.MOVED_PERMANENTLY_DEFAULT
301 리디렉션 응답 코드를 반환합니다(responseCodeName
가 지정되지 않은 경우 기본값).FOUND
302 리디렉션 응답 코드를 반환합니다.SEE_OTHER
303 리디렉션 응답 코드를 반환합니다.TEMPORARY_REDIRECT
307 리디렉션 응답 코드를 반환합니다.PERMANENT_REDIRECT
308 리디렉션 응답 코드를 반환합니다.
cloud load balancing 서비스의 백엔드 설정을 어노테이션으로 설정하기
cloud load balancing 서비스의 콘솔에서 수정 화면에서 백엔드 설정을 확인해보면 다음과 같이 여러 설정을 할 수 있는 것으로 확인할 수 있습니다.
백엔드 추가/수정 화면 백엔드 구성은 타임아웃, ingress에서 사용할 health probe, 로깅 설정, iap 등 다양한 설정을 할 수 있습니다.
# my-backendconfig.yaml apiVersion: cloud.google.com/v1 kind: BackendConfig metadata: name: my-backendconfig spec: timeoutSec: 40 # 타임아웃 시간: 기본값 30초 connectionDraining: drainingTimeoutSec: 60 # 백엔드 인스턴스가 종료되거나 비활성화될 때, 기존 요청을 일정 시간 동안 계속 처리한 후 종료하여 트래픽 손실을 방지 (기본값 0초) healthCheck: # Ingress에서 사용할 hearth probe 설정 checkIntervalSec: 5 # probe의 interval timeoutSec: 5 # probe의 timeout healthyThreshold: 2 # 상태확인시 몇회 이상 정상이 되어야 하는지 unhealthyThreshold: 5 # 상태확인시 몇회 이상 비정상이 되어야 하는지 type: HTTP # HTTP, HTTPS, HTTP/2 중에서 선택 requestPath: /status # url path 미설정시 / 이 기본값 port: 8080 # 커스텀 포트일경우 설정, 미설정시 80 포트가 기본값 (파드의 container port와 일치해야 함) securityPolicy: name: "example-security-policy" # cloud armor 보안 정책 이름 logging: enable: true # 로그 사용 여부 sampleRate: 0.01 # 로그 샘플링 비율
my-backendconfig.yaml
service: type: ClusterIP port: 80 targetPort: 8080 annotations: cloud.google.com/backend-config: '{"default": "my-backendconfig"}'
values.yaml
위 설정 이외에도 cdn 설정, iap, 사용자 정의 커스텀 헤더 등 다양한 기능이 있으니 https://cloud.google.com/kubernetes-engine/docs/how-to/ingress-configuration?hl=ko#configuring_ingress_features_through_backendconfig_parameters 에서 확인하고 필요한 옵션을 사용하면 됩니다.
Google ACME 구성
사용하는 도메인에 대해 Google 관리 SSL 인증서를 구성할 수 있습니다. 기능을 사용하려면
ingressClassName
는"gce"
여야 하며 같은 프로젝트와 네임스페이스에Ingress
및ManagedCertificate
리소스를 적용해야 합니다.# managed-cert.yaml apiVersion: networking.gke.io/v1 kind: ManagedCertificate metadata: name: managed-cert spec: domains: - brownbear.io # 구글에 등록된 SSL 인증서 이름
managed-cert.yaml
ingress: enabled: true className: "gce" # gke에서는 classname은 사용하지 않고 annotations를 사용한다. 따라서 제거해도 무방함 annotations: kubernetes.io/ingress.class: gce networking.gke.io/managed-certificates: managed-cert
values.yaml
궁금
cloud load balancing 서비스에 특정 IP만 접근하도록 설정을 어떻게 할 수 있을까
GKE에 설정된 VPC의 방화벽에 특정 IP만 접근하도록 추가해도 먹히지 않습니다. 그 이유는 cloud load balancing 서비스가 자동으로 방화벽 역할을 하기 때문입니다. 즉, 로드 밸런서가 자동으로 방화벽 역할을 하므로 방화벽 규칙을 따로 추가하지 않아도 동작 가능합니다. 방화벽 규칙을 보지 않고도 Ingress + GCP 로드 밸런서 조합으로 외부에서 접근 가능하도록 GCP가 관리하는 것이 정상적인 동작입니다. cloud load balancing 서비스에 특정 IP만 접근하도록 하려면 cloud armor 라는 WAF 역할을 하는 서비스를 추가하여 제어해야 합니다.
트래픽의 흐름은 다음과 같습니다.
- 클라이언트가 외부 IP (예:
34.10.7.3
) 로 요청을 보냄. - GCP의 글로벌 프록시가 요청을 수신 (이 프록시는 GCP가 관리).
- GCP 프록시가 트래픽을 백엔드 서비스(GKE)로 전달.
- VPC 방화벽은 백엔드 VM(Pod)으로 가는 트래픽만 필터링 가능하지만 로드 밸런서의 프록시(VIP)에는 영향을 주지 않음.
- 방화벽 규칙은 GKE 내부 Pod 또는 VM을 보호하는 용도로만 사용 가능
레퍼런스
https://ysyu.kr/2022/02/how-to-implement-ingress-configuration-using-http-or-https-lb-in-gke/
https://cloud.google.com/kubernetes-engine/docs/how-to/ingress-configuration?hl=ko
https://cloud.google.com/kubernetes-engine/docs/how-to/managed-certs?hl=ko