...

Text file src/github.com/GoogleCloudPlatform/cloudsql-proxy/examples/k8s-sidecar/README.md

Documentation: github.com/GoogleCloudPlatform/cloudsql-proxy/examples/k8s-sidecar

     1# Using the Cloud SQL proxy on Kubernetes
     2
     3The Cloud SQL proxy is the recommended way to connect to Cloud SQL, even when
     4using private IP. This is because the proxy provides strong encryption and
     5authentication using IAM, which help keep your database secure.
     6
     7## Configure your application with Secrets
     8
     9In Kubernetes, [Secrets][ksa-secret] are a secure way to pass configuration
    10details to your application. Each Secret object can contain multiple key/value
    11pairs that can be pass to your application in multiple ways. When connecting to
    12a database, you can create a Secret with details such as your database name,
    13user, and password which can be injected into your application as env vars.
    14
    151. Create a secret with information needed to access your database:
    16    ```shell
    17    kubectl create secret generic <YOUR-DB-SECRET> \
    18        --from-literal=username=<YOUR-DATABASE-USER> \
    19        --from-literal=password=<YOUR-DATABASE-PASSWORD> \
    20        --from-literal=database=<YOUR-DATABASE-NAME>
    21    ```
    222. Next, configure your application's container to mount the secrets as env
    23   vars:
    24    > [proxy_with_workload_identity.yaml](proxy_with_workload_identity.yaml#L21-L36)
    25    ```yaml
    26       env:
    27        - name: DB_USER
    28          valueFrom:
    29            secretKeyRef:
    30              name: <YOUR-DB-SECRET>
    31              key: username
    32        - name: DB_PASS
    33          valueFrom:
    34            secretKeyRef:
    35              name: <YOUR-DB-SECRET>
    36              key: password
    37        - name: DB_NAME
    38          valueFrom:
    39            secretKeyRef:
    40              name: <YOUR-DB-SECRET>
    41              key: database
    42    ```
    433. Finally, configure your application to use these values. In the example
    44above, the values will be in the env vars `DB_USER`, `DB_PASS`, and `DB_NAME`.
    45
    46[ksa-secret]: https://kubernetes.io/docs/concepts/configuration/secret/
    47
    48## Setting up a service account
    49
    50The first step to running the Cloud SQL proxy in Kubernetes is creating a
    51service account to represent your application. It is recommended that you create
    52a service account unique to each application, instead of using the same service
    53account everywhere. This model is more secure since it allows your to limit
    54permissions on a per-application basis.
    55
    56The service account for your application needs to meet the following criteria:
    57
    581. Belong to a project with the [Cloud SQL Admin API][admin-api] enabled
    591. [Has been granted][grant-sa] the
    60   [`Cloud SQL Client` IAM role (or equivalent)][csql-roles]
    61   for the project containing the instance you want to connect to
    621. If connecting using private IP, you must use a
    63   [VPC-native GKE cluster][vpc-gke], in the same VPC as your Cloud SQL instance
    64
    65[admin-api]: https://console.cloud.google.com/flows/enableapi?apiid=sqladmin&redirect=https://console.cloud.google.com
    66[grant-sa]: https://cloud.google.com/iam/docs/granting-roles-to-service-accounts
    67[csql-roles]: https://cloud.google.com/iam/docs/understanding-roles#cloud-sql-roles
    68[vpc-gke]: https://cloud.google.com/kubernetes-engine/docs/how-to/alias-ips
    69
    70## Providing the service account to the proxy
    71
    72Next, you need to configure Kubernetes to provide the service account to the
    73Cloud SQL Auth proxy. There are two recommended ways to do this.
    74
    75### Workload Identity
    76
    77If you are using [Google Kubernetes Engine][gke],  the preferred method is to
    78use GKE's [Workload Identity][workload-id] feature. This method allows you to
    79bind a [Kubernetes Service Account (KSA)][ksa] to a Google Service Account
    80(GSA). The GSA will then be accessible to applications using the matching KSA.
    81
    821. [Enable Workload Identity for your cluster][enable-wi]
    831. [Enable Workload Identity for your node pool][enable-wi-node-pool]
    841. Create a KSA for your application `kubectl apply -f service-account.yaml`:
    85
    86    > [service-account.yaml](service_account.yaml#L2-L5)
    87    ```yaml
    88    apiVersion: v1
    89    kind: ServiceAccount
    90    metadata:
    91      name: <YOUR-KSA-NAME> # TODO(developer): replace these values
    92    ```
    931. Enable the IAM binding between your `<YOUR-GSA-NAME>` and `<YOUR-KSA-NAME>`:
    94    ```sh
    95    gcloud iam service-accounts add-iam-policy-binding \
    96      --role roles/iam.workloadIdentityUser \
    97      --member "serviceAccount:<YOUR-GCP-PROJECT>.svc.id.goog[<YOUR-K8S-NAMESPACE>/<YOUR-KSA-NAME>]" \
    98      <YOUR-GSA-NAME>@<YOUR-GCP-PROJECT>.iam.gserviceaccount.com
    99    ```
   1001. Add an annotation to `<YOUR-KSA-NAME>` to complete the binding:
   101    ```sh
   102    kubectl annotate serviceaccount \
   103       <YOUR-KSA-NAME> \
   104       iam.gke.io/gcp-service-account=<YOUR-GSA-NAME>@<YOUR-GCP-PROJECT>.iam.gserviceaccount.com
   105    ```
   1061. Finally, make sure to specify the service account for the k8s pod spec:
   107    > [proxy_with_workload_identity.yaml](proxy_with_workload_identity.yaml#L2-L15)
   108    ```yaml
   109    apiVersion: apps/v1
   110    kind: Deployment
   111    metadata:
   112      name: <YOUR-DEPLOYMENT-NAME>
   113    spec:
   114      selector:
   115        matchLabels:
   116          app: <YOUR-APPLICATION-NAME>
   117      template:
   118        metadata:
   119          labels:
   120            app: <YOUR-APPLICATION-NAME>
   121        spec:
   122          serviceAccountName: <YOUR-KSA-NAME>
   123    ```
   124
   125[gke]: https://cloud.google.com/kubernetes-engine
   126[workload-id]: https://cloud.google.com/kubernetes-engine/docs/how-to/workload-identity
   127[ksa]: https://kubernetes.io/docs/tasks/configure-pod-container/configure-service-account/
   128[enable-wi]: https://cloud.google.com/kubernetes-engine/docs/how-to/workload-identity#enable_on_existing_cluster
   129[enable-wi-node-pool]: https://cloud.google.com/kubernetes-engine/docs/how-to/workload-identity#option_2_node_pool_modification
   130
   131### Service account key file
   132
   133Alternatively, if your can't use Workload Identity, the recommended pattern is
   134to mount a service account key file into the Cloud SQL proxy pod and use the
   135`-credential_file` flag.
   136
   1371. Create a credential file for your service account key:
   138    ```sh
   139    gcloud iam service-accounts keys create ~/key.json \
   140      --iam-account <YOUR-SA-NAME>@project-id.iam.gserviceaccount.com
   141    ```
   1421. Turn your service account key into a k8s [Secret][k8s-secret]:
   143    ```shell
   144    kubectl create secret generic <YOUR-SA-SECRET> \
   145    --from-file=service_account.json=~/key.json
   146    ```
   1473. Mount the secret as a volume under the`spec:` for your k8s object:
   148    > [proxy_with_sa_key.yaml](proxy_with_sa_key.yaml#L74-L77)
   149    ```yaml
   150    volumes:
   151    - name: <YOUR-SA-SECRET-VOLUME>
   152      secret:
   153        secretName: <YOUR-SA-SECRET>
   154    ```
   155
   1564. Follow the instructions in the next section to access the volume from the
   157   proxy's pod.
   158
   159[k8s-secret]: https://kubernetes.io/docs/concepts/configuration/secret/
   160
   161## Run the Cloud SQL proxy as a sidecar
   162
   163We recommend running the proxy in a "sidecar" pattern (as an additional
   164container sharing a pod with your application). We recommend this over running
   165as a separate service for several reasons:
   166
   167* Prevents your SQL traffic from being exposed locally - the proxy provides
   168  encryption on outgoing connections, but you should limit exposure for
   169  incoming connections
   170* Prevents a single point of failure - each application's access to
   171  your database is independent from the others, making it more resilient.
   172* Limits access to the proxy, allowing you to use IAM permissions per
   173  application rather than exposing the database to the entire cluster
   174* Allows you to scope resource requests more accurately - because the
   175  proxy consumes resources linearly to usage, this pattern allows you to more
   176  accurately scope and request resources to match your applications as it
   177  scales
   178
   1791. Add the Cloud SQL proxy to the pod configuration under `containers`:
   180    > [proxy_with_workload-identity.yaml](proxy_with_workload_identity.yaml#L39-L69)
   181    ```yaml
   182    - name: cloud-sql-proxy
   183      # It is recommended to use the latest version of the Cloud SQL proxy
   184      # Make sure to update on a regular schedule!
   185      image: gcr.io/cloudsql-docker/gce-proxy:1.17
   186      command:
   187        - "/cloud_sql_proxy"
   188
   189        # If connecting from a VPC-native GKE cluster, you can use the
   190        # following flag to have the proxy connect over private IP
   191        # - "-ip_address_types=PRIVATE"
   192
   193        # Replace DB_PORT with the port the proxy should listen on
   194        # Defaults: MySQL: 3306, Postgres: 5432, SQLServer: 1433
   195        - "-instances=<INSTANCE_CONNECTION_NAME>=tcp:<DB_PORT>"
   196      securityContext:
   197        # The default Cloud SQL proxy image runs as the
   198        # "nonroot" user and group (uid: 65532) by default.
   199        runAsNonRoot: true
   200      # Resource configuration depends on an application's requirements. You
   201      # should adjust the following values based on what your application
   202      # needs. For details, see https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/
   203      resources:
   204        requests:
   205          # The proxy's memory use scales linearly with the number of active
   206          # connections. Fewer open connections will use less memory. Adjust
   207          # this value based on your application's requirements.
   208          memory: "2Gi"
   209          # The proxy's CPU use scales linearly with the amount of IO between
   210          # the database and the application. Adjust this value based on your
   211          # application's requirements.
   212          cpu:    "1"
   213    ```
   214   If you are using a service account key, specify your secret volume and add
   215   the `-credential_file` flag to the command:
   216
   217   > [proxy_with_sa_key.yaml](proxy_with_sa_key.yaml#L49-L58)
   218    ```yaml
   219      # This flag specifies where the service account key can be found
   220      - "-credential_file=/secrets/service_account.json"
   221    securityContext:
   222      # The default Cloud SQL proxy image runs as the
   223      # "nonroot" user and group (uid: 65532) by default.
   224      runAsNonRoot: true
   225    volumeMounts:
   226    - name: <YOUR-SA-SECRET-VOLUME>
   227      mountPath: /secrets/
   228      readOnly: true
   229    ```
   230
   2311. Finally, configure your application to connect via `127.0.0.1` on whichever
   232   `<DB_PORT>` you specified in the command section.
   233
   234
   235## Connecting without the Cloud SQL proxy
   236
   237While not as secure, it is possible to connect from a VPC-native GKE cluster to
   238a Cloud SQL instance on the same VPC using private IP without the proxy.
   239
   2401. Create a secret with your instance's private IP address:
   241    ```shell
   242    kubectl create secret generic <YOUR-PRIVATE-IP-SECRET> \
   243        --from-literal=db_host=<YOUR-PRIVATE-IP-ADDRESS>
   244    ```
   245
   2462. Next make sure you add the secret to your application's container:
   247   > [no_proxy_private_ip.yaml](no_proxy_private_ip.yaml#L34-L38)
   248   ```yaml
   249   - name: DB_HOST
   250     valueFrom:
   251       secretKeyRef:
   252         name: <YOUR-PRIVATE-IP-SECRET>
   253         key: db_host
   254   ```
   255
   2563. Finally, configure your application to connect using the IP address from the
   257   `DB_HOST` env var. You will need to use the correct port for your db-engine
   258   (MySQL: `3306`, Postgres: `5432`, SQLServer: `1433`).

View as plain text