Cloud Armor 구성

이 페이지에서는 BackendConfig 커스텀 리소스를 사용하여 Google Kubernetes Engine에서 Cloud Armor를 구성하는 방법을 보여줍니다.

개요

GKE 클러스터에서는 들어오는 트래픽은 Cloud Load Balancing의 구성요소인 HTTP(S) 부하 분산에 의해 처리됩니다. 일반적으로 HTTP(S) 부하 분산기는 Kubernetes Ingress 객체에서 구성 정보를 가져오는 GKE Ingress 컨트롤러에 의해 구성됩니다. Ingress는 하나 이상의 서비스 객체와 연결됩니다. 각 서비스 객체는 들어오는 요청을 특정 포드 및 포트로 보내는 데 사용되는 라우팅 정보를 포함합니다.

Kubernetes 버전 1.10.5-gke.3부터는 서비스 포트를 BackendConfig라는 커스텀 리소스와 연결하여 부하 분산기에 대해 추가 구성을 제공할 수 있습니다.

GKE Ingress 컨트롤러는 BackendConfig에서 구성 정보를 읽고 그에 따라 부하 분산기를 설정합니다. BackendConfig는 Cloud Load Balancing과 관련된 구성 정보를 포함합니다. Kubernetes 수신 및 서비스 리소스는 Cloud Armor와 같은 공급자별 기능을 구성할 수 있는 방법을 제공하지 않습니다. BackendConfig를 사용하여 이러한 구성을 수행할 수 있습니다.

이 연습에서 BackendConfig를 설정하는 방법은 크게 다음과 같습니다.

  1. BackendConfig를 만듭니다.
  2. 서비스를 만들고 포트 중 하나를 BackendConfig와 연결합니다.
  3. Ingress를 만들고 이를 (서비스, 포트) 쌍과 연결합니다.

시작하기 전에

이 작업을 준비하려면 다음 단계를 수행하세요.

  • Google Kubernetes Engine API가 사용 설정되었는지 확인합니다.
  • Google Kubernetes Engine API 사용 설정
  • Cloud SDK가 설치되었는지 확인합니다.
  • 기본 프로젝트 ID를 설정합니다.
    gcloud config set project [PROJECT_ID]
  • 영역 클러스터를 사용하는 경우 기본 컴퓨팅 영역을 설정합니다.
    gcloud config set compute/zone [COMPUTE_ZONE]
  • 지역 클러스터를 사용하는 경우 기본 컴퓨팅 지역을 설정합니다.
    gcloud config set compute/region [COMPUTE_REGION]
  • gcloud를 최신 버전으로 업데이트합니다.
    gcloud components update

네임스페이스 만들기

이 가이드의 객체를 위한 Kubernetes 네임스페이스를 만듭니다.

kubectl create namespace cloud-armor-how-to

배포 만들기

이 배포 매니페스트는 hello-app 웹 애플리케이션의 두 복제본을 실행하도록 선언합니다.

apiVersion: apps/v1
kind: Deployment
metadata:
  namespace: cloud-armor-how-to
  name: my-deployment
spec:
  selector:
    matchLabels:
      app: hello-app
  replicas: 2
  template:
    metadata:
      labels:
        app: hello-app
    spec:
      containers:
      - name: hello-app-container
        image: gcr.io/google-samples/hello-app:1.0
        ports:
        - containerPort: 8080

이름이 my-deployment.yaml인 파일에 매니페스트를 복사하고 배포를 만듭니다.

kubectl apply -f my-deployment.yaml

Cloud Armor 보안 정책 및 규칙 만들기

Cloud Armor 보안 정책을 만듭니다.

gcloud beta compute security-policies create ca-how-to-security-policy \
    --description "policy for Cloud Armor how-to topic"

보안 정책의 규칙을 만듭니다.

gcloud beta compute security-policies rules create 1000 \
    --security-policy ca-how-to-security-policy \
    --description "Deny traffic from 192.0.2.0/24." \
    --src-ip-ranges "192.0.2.0/24" \
    --action "deny-404"

보안 정책을 확인합니다.

gcloud beta compute security-policies describe ca-how-to-security-policy

출력:

...
kind: compute#securityPolicy
name: ca-how-to-security-policy
rules:
- action: deny(404)
  description: Deny traffic from 192.0.2.0/24.
  kind: compute#securityPolicyRule
  match:
    config:
      srcIpRanges:
      - 192.0.2.0/24
    versionedExpr: SRC_IPS_V1
  preview: false
  priority: 1000
  ...

BackendConfig 만들기

BackendConfig의 매니페스트는 다음과 같습니다. 이 매니페스트는 보안 정책을 지정합니다.

apiVersion: cloud.google.com/v1beta1
kind: BackendConfig
metadata:
  namespace: cloud-armor-how-to
  name: my-backend-config
spec:
  securityPolicy:
    name: "ca-how-to-security-policy"

이름이 my-backend-config.yaml인 파일에 매니페스트를 복사하고 BackendConfig를 만듭니다.

kubectl apply -f my-backend-config.yaml

BackendConfig를 확인합니다.

kubectl get backendconfig my-backend-config --namespace cloud-armor-how-to --output yaml

출력에 지정된 보안 정책이 표시됩니다.

apiVersion: cloud.google.com/v1beta1
kind: BackendConfig
metadata:
  name: my-backend-config
  namespace: cloud-armor-how-to
  ...
spec:
  securityPolicy:
    name: ca-how-to-security-policy

서비스 만들기

서비스의 매니페스트는 다음과 같습니다.

apiVersion: v1
kind: Service
metadata:
  namespace: cloud-armor-how-to
  name: my-service
  labels:
    app: hello-app
  annotations:
    beta.cloud.google.com/backend-config: '{"ports": {"80":"my-backend-config"}}'
spec:
  type: NodePort
  selector:
    app: hello-app
  ports:
  - port: 80
    protocol: TCP
    targetPort: 8080

이름이 my-service.yaml인 파일로 매니페스트를 저장하고 서비스를 만듭니다.

kubectl apply -f my-service.yaml

서비스를 확인합니다.

kubectl get service my-service --namespace cloud-armor-how-to --output yaml

출력은 다음과 비슷합니다.

apiVersion: v1
kind: Service
metadata:
  annotations:
    beta.cloud.google.com/backend-config: '{"ports": {"80":"my-backend-config"}}'
  labels:
    app: hello-app
  name: my-service
  namespace: cloud-armor-how-to
  ...
spec:
  clusterIP: 10.19.249.137
  externalTrafficPolicy: Cluster
  ports:
  - nodePort: 32629
    port: 80
    protocol: TCP
    targetPort: 8080
  selector:
    app: hello-app
  sessionAffinity: None
  type: NodePort
status:
  loadBalancer: {}

이 연습에서는 서비스 관련 정보를 기록하는 것이 중요합니다.

  • 서비스의 포트 80이 my-backend-config라는 BackendConfig와 연결됩니다. beta.cloud.google.com/backend-config 주석에 이 항목이 지정되어 있습니다.

  • 서비스에 NodePort 유형이 포함됩니다. 이 유형은 Ingress와 연결할 서비스에 필요합니다.

  • app: hello-app 라벨을 포함하는 모든 포드가 서비스의 구성원입니다. selector 필드에 이 항목이 지정되어 있습니다.

  • TCP 포트 80으로 서비스로 전송되는 트래픽은 구성원 포드 중 하나에서 TCP 포트 8080으로 라우팅됩니다. porttargetPort 필드에 이 항목이 지정되어 있습니다.

정적 외부 IP 주소 예약

정적 외부 IP 주소를 예약합니다.

gcloud compute addresses create cloud-armor-how-to-address --global

정적 외부 IP 주소를 확인합니다.

gcloud compute addresses list --filter "name=cloud-armor-how-to-address"

출력:

NAME                        REGION  ADDRESS        STATUS
cloud-armor-how-to-address          203.0.113.2    RESERVED

Ingress 만들기

Ingress의 매니페스트는 다음과 같습니다.

apiVersion: extensions/v1beta1
kind: Ingress
metadata:
  namespace: cloud-armor-how-to
  name: my-ingress
  annotations:
    kubernetes.io/ingress.global-static-ip-name: "cloud-armor-how-to-address"
spec:
  backend:
    serviceName: my-service
    servicePort: 80

이름이 my-ingress.yaml인 파일에 매니페스트를 복사하고 Ingress를 만듭니다.

kubectl create -f my-ingress.yaml

Kubernetes Ingress 컨트롤러가 Cloud 부하 분산기를 구성할 때까지 몇 분 정도 기다린 후 Ingress를 확인합니다.

kubectl get ingress my-ingress --output yaml --namespace cloud-armor-how-to

출력:

apiVersion: extensions/v1beta1
kind: Ingress
metadata:
  name: my-ingress
  namespace: cloud-armor-how-to
  ...
spec:
  backend:
    serviceName: my-service
    servicePort: 80
status:
  loadBalancer:
    ingress:
    - ip: 203.0.113.2

이 연습에서는 Ingress 관련 정보를 기록하는 것이 중요합니다.

  • 들어오는 트래픽의 IP 주소는 loadBalancer:ingress: 아래에 나열됩니다.

  • Ingress에는 모든 호스트에서 들어오는 HTTP 요청에 적용되는 하나의 규칙이 있습니다. 이것은 규칙에 host 필드가 없기 때문입니다. 따라서 기본적으로 규칙이 모든 호스트에 적용됩니다.

  • 모든 들어오는 요청은 URL 경로에 관계없이 동일하게 취급됩니다. 이것은 path/*로 지정되어 있습니다.

  • 들어오는 요청은 my-service의 구성원인 포드로 라우팅됩니다. 이 연습에서는 구성원 포드에 app: hello-app 라벨이 포함됩니다.

  • 요청이 my-service에 지정된 대상 포트의 포드로 라우팅됩니다. 이 연습에서 포드 대상 포트는 8080입니다.

웹 앱 보기

몇 분 정도 기다립니다. 그런 후 브라우저에서 정적 외부 IP 주소를 입력합니다.

배포의 포드 중 하나에서 실행되는 hello-app 웹 애플리케이션의 응답이 페이지에 표시됩니다.

Hello, world!
Version: 1.0.0
Hostname: my-deployment-574ddbdf88-f9fbj

curl을 사용하여 웹 앱을 확인합니다.

curl -v [STATIC_ADDRESS]

여기서 [STATIC_ADDRESS]는 정적 외부 IP 주소입니다.

hello-app의 응답이 출력됩니다.

Hello, world!
Version: 1.0.0
Hostname: my-deployment-574ddbdf88-zpb94

보안 정책 분리

Ingress에서 보안 정책을 분리하려면 BackendConfig에서 보안 정책 이름을 빈 값으로 설정합니다. 보안 정책 분리 예는 다음과 같습니다.

apiVersion: cloud.google.com/v1beta1
kind: BackendConfig
metadata:
  namespace: cloud-armor-how-to
  name: my-backend-config
spec:
  securityPolicy:
    name: ""

제한사항

할당량 제한

이 기능이 베타 상태인 동안에는 작성 가능한 Cloud Armor 규칙 수가 제한되어 있습니다. 이러한 제한은 기능이 일반에 공개되었을 때 삭제될 예정입니다.

IP 허용 목록 및 차단 목록만 지원

Cloud Armor에서는 IP 허용 목록 및 IP 차단 목록만 지원됩니다.

문제해결

BackendConfig를 찾을 수 없음

이 오류는 서비스 포트에 대해 BackendConfig가 서비스 주석에 지정되었지만 실제 BackendConfig 리소스를 찾을 수 없을 때 발생합니다. 이 문제는 개발자가 BackendConfig 리소스를 전혀 만들지 않았거나, 잘못된 네임스페이스로 만들었거나, 서비스 주석에서 참조 철자를 잘못 쓴 경우에 발생할 수 있습니다.

kubectl get event
KIND    ... SOURCE
Ingress ... loadbalancer-controller

MESSAGE
Error during sync: error getting BackendConfig for port 80 on service "default/my-service":
no BackendConfig for service port exists

보안 정책을 찾을 수 없음

Ingress 객체가 생성된 다음 보안 정책이 부하 분산기 서비스와 올바르게 연결되지 않은 경우, Kubernetes 이벤트에서 구성 실수가 있는지 확인합니다. 특히 BackendConfig에 존재하지 않는 정책이 지정된 경우, 경고 이벤트가 주기적으로 발생합니다. 이 문제를 해결하려면 BackendConfig에서 올바른 보안 정책 이름을 지정했는지 확인합니다.

kubectl get event
KIND    ... SOURCE
Ingress ... loadbalancer-controller

MESSAGE
Error during sync: The given security policy "my-policy" does not exist.

삭제

이 페이지의 연습을 완료한 후에는 다음 단계에 따라 자신의 계정에 원치 않는 비용이 발생하지 않도록 리소스를 삭제합니다.

이 연습을 위해 만든 Kubernetes 객체를 삭제합니다.

kubectl delete ingress my-ingress --namespace cloud-armor-how-to
kubectl delete service my-service --namespace cloud-armor-how-to
kubectl delete backendconfig my-backend-config --namespace cloud-armor-how-to
kubectl delete deployment my-deployment --namespace cloud-armor-how-to
kubectl delete namespace cloud-armor-how-to

정적 외부 IP 주소를 삭제합니다.

gcloud compute addresses delete cloud-armor-how-to-address --global

보안 정책을 삭제합니다.

gcloud beta compute security-policies delete ca-how-to-security-policy

다음 단계

이 페이지가 도움이 되었나요? 평가를 부탁드립니다.

다음에 대한 의견 보내기...

Kubernetes Engine