Google Kubernetes Engine에서 Cloud SQL에 연결

이 페이지에서는 Google Kubernetes Engine(GKE)에서 실행되는 애플리케이션에서 Cloud SQL 인스턴스로 연결을 설정하는 방법을 설명합니다.

Cloud SQL에 연결된 Google Kubernetes Engine 샘플 웹 애플리케이션을 실행하는 방법에 대한 단계별 안내빠른 시작: Google Kubernetes Engine에서 연결을 참조하세요.

Cloud SQL은 클라우드에서 관계형 데이터베이스를 설정, 유지, 관리할 수 있는 완전 관리형 데이터베이스 서비스입니다.

Google Kubernetes Engine은 Kubernetes를 자동으로 배포, 확장, 관리할 수 있는 간편한 방법입니다.

Google Kubernetes Engine을 Cloud SQL로 연결 관련 정보

Google Kubernetes Engine에서 실행되는 애플리케이션에서 Cloud SQL 인스턴스에 액세스하려면 Cloud SQL 인증 프록시(공개 IP 또는 비공개 IP 포함)를 사용하거나 비공개 IP 주소를 사용하여 직접 연결할 수 있습니다.

비공개 IP를 사용하는 경우에도 Cloud SQL에 연결하는 데 Cloud SQL 인증 프록시가 권장됩니다. 이는 Cloud SQL 인증 프록시가 IAM을 사용하여 데이터베이스를 안전하게 보호할 수 있는 강력한 암호화와 인증을 제공하기 때문입니다.

데이터베이스 연결은 서버 및 연결 애플리케이션의 리소스를 사용합니다. 항상 연결 관리 권장사항을 참고하여 애플리케이션의 사용 공간을 최소화하고 Cloud SQL 연결 한도를 초과할 가능성을 줄이세요. 자세한 내용은 데이터베이스 연결 관리를 참조하세요.

시작하기 전에

Cloud SQL에 연결하려면 다음이 필요합니다.

  • kubectl 명령줄 도구가 설치되고 클러스터와 통신하도록 구성된 GKE 클러스터

    GKE를 시작하는 데 도움이 필요하면 GKE 클러스터에 앱 배포를 참조하세요.

    비공개 IP를 사용하여 연결하려면 GKE 클러스터는 VPC 기반이고 Cloud SQL 인스턴스와 동일한 Virtual Private Cloud(VPC) 네트워크와 피어링되어야 합니다.

  • 생성된 인스턴스

    Cloud SQL 인스턴스를 만들 때 도움이 필요하면 인스턴스 만들기를 참조하세요.

  • 인스턴스에 구성된 MySQL 사용자 계정

    애플리케이션은 이 계정을 사용하여 데이터베이스에 연결합니다. 사용자 계정을 만드는 데 도움이 필요하면 사용자 만들기를 참조하세요.

Kubernetes 보안 비밀 정보

Kubernetes에서 보안 비밀은 구성 세부정보를 애플리케이션에 전달하는 안전한 방법입니다. 데이터베이스 이름, 사용자, 비밀번호 등의 세부정보가 포함된 보안 비밀을 만들어 애플리케이션에 환경 변수로 삽입할 수 있습니다.

연결 유형에 따라 보안 비밀을 사용할 수 있는 여러 가지 방법이 있습니다.

  • 데이터베이스 사용자 인증 정보 보안 비밀에는 연결하려는 데이터베이스 사용자의 이름과 사용자의 데이터베이스 비밀번호가 포함됩니다.
  • Cloud SQL 인증 프록시와 연결하는 경우 보안 비밀을 사용하여 서비스 계정의 사용자 인증 정보 파일을 저장할 수 있습니다.
  • 비공개 IP로 연결하는 경우 보안 비밀을 사용하여 Cloud SQL 인스턴스의 비공개 IP 주소를 지정할 수 있습니다.

보안 비밀을 사용하는 방법에 대한 전체 예시는 이 페이지의 뒷부분에 설명된 GitHub 저장소를 참조하세요.

보안 비밀 객체 만들기

  1. 보안 비밀 객체를 만들려면 kubectl create secret 명령어를 사용합니다.

    데이터베이스 사용자 인증 정보 보안 비밀을 만들려면 다음과 같이 작성합니다.

    kubectl create secret generic <YOUR-DB-SECRET> \
      --from-literal=username=<YOUR-DATABASE-USER> \
      --from-literal=password=<YOUR-DATABASE-PASSWORD> \
      --from-literal=database=<YOUR-DATABASE-NAME>
    
  2. 객체가 생성되면 Google Cloud 콘솔의 Google Kubernetes Engine 페이지에 있는 구성 섹션에서 확인할 수 있습니다.

Cloud SQL 인증 프록시를 사용하여 Cloud SQL에 연결

Cloud SQL 인증 프록시를 사용하여 연결하면 Cloud SQL 인증 프록시가 sidecar 컨테이너 패턴을 사용하여 포드에 추가됩니다. Cloud SQL 인증 프록시 컨테이너는 애플리케이션과 동일한 포드에 있으므로 localhost를 사용하여 애플리케이션을 Cloud SQL 인증 프록시에 연결할 수 있어 보안 및 성능이 향상됩니다.

Cloud SQL 인증 프록시에 대한 자세한 내용은 Cloud SQL 인증 프록시 정보를 참조하세요. 포드를 이용한 작업에 대한 자세한 내용은 Kubernetes 문서의 포드 개요를 참조하세요.

Cloud SQL 인증 프록시를 사용하여 연결하려면 다음이 필요합니다.

  1. Cloud SQL 인스턴스의 인스턴스 연결 이름

    인스턴스 연결 이름은 Google Cloud 콘솔의 Cloud SQL 인스턴스 세부정보 페이지 또는 gcloud sql instances describe INSTANCE_ID 명령어에서 볼 수 있습니다.

  2. Cloud SQL 인스턴스에 대한 적절한 권한을 가진 서비스 계정과 연결된 키 파일의 위치

    자세한 내용은 서비스 계정 만들기를 참조하세요.

  3. Cloud SQL Admin API를 사용 설정합니다.

    Enable the API

Cloud SQL 인증 프록시에 서비스 계정 제공

Google Kubernetes Engine에서 Cloud SQL 인증 프록시를 실행하는 첫 단계는 애플리케이션을 나타내는 Google 서비스 계정(GSA)을 만드는 것입니다. 어디서나 동일한 서비스 계정을 사용하지 않고 각 애플리케이션에 고유한 서비스 계정을 만드는 것이 좋습니다. 이 모델은 애플리케이션별로 권한을 제한할 수 있으므로 더 안전합니다.

애플리케이션의 서비스 계정은 다음 기준을 충족해야 합니다.

  • Cloud SQL Admin API가 사용 설정된 프로젝트에 속함
  • 연결하려는 인스턴스가 포함된 프로젝트의 Cloud SQL 클라이언트 IAM 역할(또는 이에 상응)이 부여됨
  • 비공개 IP를 사용하여 연결하는 경우 Cloud SQL 인스턴스와 동일한 VPC에서 VPC 기반 GKE 클러스터를 사용해야 함

Cloud SQL 인증 프록시에 서비스 계정을 제공하도록 GKE를 구성해야 합니다. 권장되는 두 가지 방법은 워크로드 아이덴티티 또는 서비스 계정 키 파일입니다.

워크로드 아이덴티티

Google Kubernetes Engine을 사용하는 경우 GKE의 워크로드 아이덴티티 기능을 사용하는 것이 좋습니다. 이 방법을 사용하면 Kubernetes 서비스 계정(KSA)Google 서비스 계정(GSA)에 결합할 수 있습니다. 그러면 일치하는 KSA를 사용하는 애플리케이션에서 GSA에 액세스할 수 있습니다.

Google 서비스 계정(GSA)은 Google Cloud에서 애플리케이션을 나타내는 IAM ID입니다. 이와 마찬가지로 Kubernetes 서비스 계정(KSA)은 Google Kubernetes Engine 클러스터에서 애플리케이션을 나타내는 ID입니다.

워크로드 아이덴티티는 KSA를 GSA에 결합하기 때문에 해당 KSA를 사용한 모든 배포에서 Google Cloud와의 상호작용 시 GSA로 인증하게 됩니다.

  1. 클러스터에 워크로드 아이덴티티를 사용 설정합니다.
  2. 일반적으로 각 애플리케이션에는 KSA와 GSA 쌍으로 표시되는 고유 ID가 있습니다. kubectl apply -f service-account.yaml을 실행하여 애플리케이션의 KSA를 만듭니다.

    apiVersion: v1
    kind: ServiceAccount
    metadata:
      name: <YOUR-KSA-NAME> # TODO(developer): replace these values
  3. YOUR-GSA-NAMEYOUR-KSA-NAME 간에 IAM binding을 사용 설정합니다.

    gcloud iam service-accounts add-iam-policy-binding \
    --role="roles/iam.workloadIdentityUser" \
    --member="serviceAccount:YOUR-GOOGLE-CLOUD-PROJECT.svc.id.goog[YOUR-K8S-NAMESPACE/YOUR-KSA-NAME]" \
    YOUR-GSA-NAME@YOUR-GOOGLE-CLOUD-PROJECT.iam.gserviceaccount.com
  4. YOUR-KSA-NAME에 주석을 추가하여 binding을 완료합니다.

    kubectl annotate serviceaccount \
    YOUR-KSA-NAME \
    iam.gke.io/gcp-service-account=YOUR-GSA-NAME@YOUR-GOOGLE-CLOUD-PROJECT.iam.gserviceaccount.com
  5. 마지막으로 k8s 객체의 서비스 계정을 지정해야 합니다.

    apiVersion: apps/v1
    kind: Deployment
    metadata:
      name: <YOUR-DEPLOYMENT-NAME>
    spec:
      selector:
        matchLabels:
          app: <YOUR-APPLICATION-NAME>
      template:
        metadata:
          labels:
            app: <YOUR-APPLICATION-NAME>
        spec:
          serviceAccountName: <YOUR-KSA-NAME>

서비스 계정 키 파일

또는 워크로드 아이덴티티를 사용할 수 없는 경우 서비스 계정 키 파일을 Cloud SQL 인증 프록시 포드에 마운트하고 --credentials-file 플래그를 사용하는 것이 좋습니다.

  1. 서비스 계정 키의 사용자 인증 정보 파일을 만듭니다.

    gcloud iam service-accounts keys create ~/key.json \
    --iam-account=YOUR-SA-NAME@project-id.iam.gserviceaccount.com
  2. 서비스 계정 키를 k8s 보안 비밀로 바꿉니다.

    kubectl create secret generic YOUR-SA-SECRET \
    --from-file=service_account.json=~/key.json
  3. k8s 객체의 spec: 아래에 보안 비밀을 볼륨으로 마운트합니다.

    volumes:
    - name: <YOUR-SA-SECRET-VOLUME>
      secret:
        secretName: <YOUR-SA-SECRET>
  4. 다음 섹션의 안내에 따라 Cloud SQL 인증 프록시의 포드에서 볼륨에 액세스합니다.

사이드카 패턴으로 Cloud SQL 인증 프록시 실행

애플리케이션에 포드를 공유하는 추가 컨테이너로 Cloud SQL 인증 프록시를 sidecar 패턴으로 실행하는 것이 좋습니다. 다음과 같은 이유로 인해 별도의 서비스로 실행하는 것이 좋습니다.

  • SQL 트래픽이 로컬에 노출되지 않도록 합니다. Cloud SQL 인증 프록시는 발신 연결에 대한 암호화를 제공하지만 수신 연결의 노출을 제한해야 합니다.
  • 단일 장애점을 방지합니다. 데이터베이스에 대한 각 애플리케이션의 액세스는 다른 애플리케이션에 대해 독립적이므로 복원력이 더 우수합니다.
  • Cloud SQL 인증 프록시에 대한 액세스를 제한합니다. 그러면 데이터베이스를 전체 클러스터에 노출하는 대신 애플리케이션당 IAM 권한을 사용할 수 있습니다.
  • 리소스 요청 범위를 더 정확하게 지정할 수 있습니다. Cloud SQL 인증 프록시는 사용량에 비례하여 리소스를 소비하므로 이 패턴을 사용하면 확장되는 애플리케이션에 맞게 리소스 범위를 더 정확하게 지정하고 요청할 수 있습니다.

  • containers에서 포드 구성에 Cloud SQL 인증 프록시를 추가합니다.

    - name: cloud-sql-proxy
      # It is recommended to use the latest version of the Cloud SQL Auth Proxy
      # Make sure to update on a regular schedule!
      image: gcr.io/cloud-sql-connectors/cloud-sql-proxy:2.11.4
      args:
        # If connecting from a VPC-native GKE cluster, you can use the
        # following flag to have the proxy connect over private IP
        # - "--private-ip"
    
        # Enable structured logging with LogEntry format:
        - "--structured-logs"
    
        # Replace DB_PORT with the port the proxy should listen on
        - "--port=<DB_PORT>"
        - "<INSTANCE_CONNECTION_NAME>"
    
      securityContext:
        # The default Cloud SQL Auth Proxy image runs as the
        # "nonroot" user and group (uid: 65532) by default.
        runAsNonRoot: true
      # You should use resource requests/limits as a best practice to prevent
      # pods from consuming too many resources and affecting the execution of
      # other pods. You should adjust the following values based on what your
      # application needs. For details, see
      # https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/
      resources:
        requests:
          # The proxy's memory use scales linearly with the number of active
          # connections. Fewer open connections will use less memory. Adjust
          # this value based on your application's requirements.
          memory: "2Gi"
          # The proxy's CPU use scales linearly with the amount of IO between
          # the database and the application. Adjust this value based on your
          # application's requirements.
          cpu:    "1"

    서비스 계정 키를 사용하는 경우 보안 비밀 볼륨을 지정하고 명령어에 --credentials-file 플래그를 추가합니다.

      # This flag specifies where the service account key can be found
      - "--credentials-file=/secrets/service_account.json"
    securityContext:
      # The default Cloud SQL Auth Proxy image runs as the
      # "nonroot" user and group (uid: 65532) by default.
      runAsNonRoot: true
    volumeMounts:
    - name: <YOUR-SA-SECRET-VOLUME>
      mountPath: /secrets/
      readOnly: true
  • 마지막으로 명령어 섹션에서 지정한 DB_PORT127.0.0.1을 사용하여 연결하도록 애플리케이션을 구성합니다.

샘플 구성 파일을 완료합니다.

워크로드 아이덴티티

# Copyright 2021 Google LLC
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#      http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

apiVersion: apps/v1
kind: Deployment
metadata:
  name: <YOUR-DEPLOYMENT-NAME>
spec:
  selector:
    matchLabels:
      app: <YOUR-APPLICATION-NAME>
  template:
    metadata:
      labels:
        app: <YOUR-APPLICATION-NAME>
    spec:
      serviceAccountName: <YOUR-KSA-NAME>
      containers:
      - name: <YOUR-APPLICATION-NAME>
        # ... other container configuration
        env:
        - name: DB_USER
          valueFrom:
            secretKeyRef:
              name: <YOUR-DB-SECRET>
              key: username
        - name: DB_PASS
          valueFrom:
            secretKeyRef:
              name: <YOUR-DB-SECRET>
              key: password
        - name: DB_NAME
          valueFrom:
            secretKeyRef:
              name: <YOUR-DB-SECRET>
              key: database
      - name: cloud-sql-proxy
        # It is recommended to use the latest version of the Cloud SQL Auth Proxy
        # Make sure to update on a regular schedule!
        image: gcr.io/cloud-sql-connectors/cloud-sql-proxy:2.11.4
        args:
          # If connecting from a VPC-native GKE cluster, you can use the
          # following flag to have the proxy connect over private IP
          # - "--private-ip"

          # Enable structured logging with LogEntry format:
          - "--structured-logs"

          # Replace DB_PORT with the port the proxy should listen on
          - "--port=<DB_PORT>"
          - "<INSTANCE_CONNECTION_NAME>"

        securityContext:
          # The default Cloud SQL Auth Proxy image runs as the
          # "nonroot" user and group (uid: 65532) by default.
          runAsNonRoot: true
        # You should use resource requests/limits as a best practice to prevent
        # pods from consuming too many resources and affecting the execution of
        # other pods. You should adjust the following values based on what your
        # application needs. For details, see
        # https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/
        resources:
          requests:
            # The proxy's memory use scales linearly with the number of active
            # connections. Fewer open connections will use less memory. Adjust
            # this value based on your application's requirements.
            memory: "2Gi"
            # The proxy's CPU use scales linearly with the amount of IO between
            # the database and the application. Adjust this value based on your
            # application's requirements.
            cpu:    "1"

서비스 계정 키

# Copyright 2021 Google LLC
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#      http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

apiVersion: apps/v1
kind: Deployment
metadata:
  name: <YOUR-DEPLOYMENT-NAME>
spec:
  selector:
    matchLabels:
      app: <YOUR-APPLICATION-NAME>
  template:
    metadata:
      labels:
        app: <YOUR-APPLICATION-NAME>
    spec:
      containers:
      - name: <YOUR-APPLICATION-NAME>
        # ... other container configuration
        env:
        - name: DB_USER
          valueFrom:
            secretKeyRef:
              name: <YOUR-DB-SECRET>
              key: username
        - name: DB_PASS
          valueFrom:
            secretKeyRef:
              name: <YOUR-DB-SECRET>
              key: password
        - name: DB_NAME
          valueFrom:
            secretKeyRef:
              name: <YOUR-DB-SECRET>
              key: database
      - name: cloud-sql-proxy
        # It is recommended to use the latest version of the Cloud SQL Auth Proxy
        # Make sure to update on a regular schedule!
        image: gcr.io/cloud-sql-connectors/cloud-sql-proxy:2.11.4
        args:
          # If connecting from a VPC-native GKE cluster, you can use the
          # following flag to have the proxy connect over private IP
          # - "--private-ip"

          # Enable structured logging with LogEntry format:
          - "--structured-logs"


          # Replace DB_PORT with the port the proxy should listen on
          - "--port=<DB_PORT>"
          - "<INSTANCE_CONNECTION_NAME>"

          # This flag specifies where the service account key can be found
          - "--credentials-file=/secrets/service_account.json"
        securityContext:
          # The default Cloud SQL Auth Proxy image runs as the
          # "nonroot" user and group (uid: 65532) by default.
          runAsNonRoot: true
        volumeMounts:
        - name: <YOUR-SA-SECRET-VOLUME>
          mountPath: /secrets/
          readOnly: true
        # Resource configuration depends on an application's requirements. You
        # should adjust the following values based on what your application
        # needs. For details, see https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/
        resources:
          requests:
            # The proxy's memory use scales linearly with the number of active
            # connections. Fewer open connections will use less memory. Adjust
            # this value based on your application's requirements.
            memory: "2Gi"
            # The proxy's CPU use scales linearly with the amount of IO between
            # the database and the application. Adjust this value based on your
            # application's requirements.
            cpu:    "1"
      volumes:
      - name: <YOUR-SA-SECRET-VOLUME>
        secret:
          secretName: <YOUR-SA-SECRET>

Cloud SQL 인증 프록시 없이 Cloud SQL에 연결

안전하지는 않지만 Cloud SQL 인증 프록시 없이 비공개 IP를 사용하여 VPC 기반 GKE 클러스터에서 동일한 VPC의 Cloud SQL 인스턴스로 연결할 수 있습니다.

  1. 인스턴스의 비공개 IP 주소로 보안 비밀을 만듭니다.

    kubectl create secret generic <YOUR-PRIVATE-IP-SECRET> \
        --from-literal=db_host=<YOUR-PRIVATE-IP-ADDRESS>
    
  2. 그런 다음 애플리케이션의 컨테이너에 보안 비밀을 추가합니다.

    - name: DB_HOST
      valueFrom:
        secretKeyRef:
          name: <YOUR-PRIVATE-IP-SECRET>
          key: db_host
  3. 마지막으로 애플리케이션을 구성하여 DB_HOST 환경 변수의 IP 주소를 통해 연결합니다. MySQL에 올바른 포트(3306)를 사용해야 합니다.

샘플 구성 파일을 완료합니다.

비공개 IP

# Copyright 2021 Google LLC
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#      http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

apiVersion: apps/v1
kind: Deployment
metadata:
  name: <YOUR-DEPLOYMENT-NAME>
spec:
  selector:
    matchLabels:
      app: <YOUR-APPLICATION-NAME>
  template:
    metadata:
      labels:
        app: <YOUR-APPLICATION-NAME>
    spec:
      containers:
      - name: <YOUR-APPLICATION-NAME>
        # ... other container configuration
        env:
        - name: DB_USER
          valueFrom:
            secretKeyRef:
              name: <YOUR-DB-SECRET>
              key: username
        - name: DB_PASS
          valueFrom:
            secretKeyRef:
              name: <YOUR-DB-SECRET>
              key: password
        - name: DB_NAME
          valueFrom:
            secretKeyRef:
              name: <YOUR-DB-SECRET>
              key: database
        - name: DB_HOST
          valueFrom:
            secretKeyRef:
              name: <YOUR-PRIVATE-IP-SECRET>
              key: db_host

문제 해결

도움이 필요하신가요? 프록시 문제를 해결하는 데 도움이 필요하면 Cloud SQL 인증 프록시 연결 문제 해결 또는 Cloud SQL 지원 페이지를 참조하세요.

다음 단계