Connect to Memorystore from Cloud Run

后端 未结 3 1924
我寻月下人不归
我寻月下人不归 2020-12-30 02:48

I want to run a service on Google Cloud Run that uses Cloud Memorystore as cache.

I created an Memorystore instance in the same region as Cloud Run and used the ex

3条回答
  •  醉梦人生
    2020-12-30 03:16

    While waiting for serverless VPC connectors on Cloud Run - Google said yesterday that announcements would be made in the near term - you can connect to Memorystore from Cloud Run using an SSH tunnel via GCE.

    The basic approach is the following.

    First, create a forwarder instance on GCE

    gcloud compute instances create vpc-forwarder --machine-type=f1-micro --zone=us-central1-a
    

    Don't forget to open port 22 in your firewall policies (it's open by default).

    Then install the gcloud CLI via your Dockerfile

    Here is an example for a Rails app. The Dockerfile makes use of a script for the entrypoint.

    # Use the official lightweight Ruby image.
    # https://hub.docker.com/_/ruby
    FROM ruby:2.5.5
    
    # Install gcloud
    RUN curl https://dl.google.com/dl/cloudsdk/release/google-cloud-sdk.tar.gz > /tmp/google-cloud-sdk.tar.gz
    RUN mkdir -p /usr/local/gcloud \
      && tar -C /usr/local/gcloud -xvf /tmp/google-cloud-sdk.tar.gz \
      && /usr/local/gcloud/google-cloud-sdk/install.sh
    ENV PATH $PATH:/usr/local/gcloud/google-cloud-sdk/bin
    
    # Generate SSH key to be used by the SSH tunnel (see entrypoint.sh)
    RUN mkdir -p /home/.ssh && ssh-keygen -b 2048 -t rsa -f /home/.ssh/google_compute_engine -q -N ""
    
    # Install bundler
    RUN gem update --system
    RUN gem install bundler
    
    # Install production dependencies.
    WORKDIR /usr/src/app
    COPY Gemfile Gemfile.lock ./
    ENV BUNDLE_FROZEN=true
    RUN bundle install
    
    # Copy local code to the container image.
    COPY . ./
    
    # Run the web service on container startup.
    CMD ["bash", "entrypoint.sh"]
    

    Finally open an SSH tunnel to Redis in your entrypoint.sh script

    
    # !/bin/bash
    
    # Memorystore config
    MEMORYSTORE_IP=10.0.0.5
    MEMORYSTORE_REMOTE_PORT=6379
    MEMORYSTORE_LOCAL_PORT=6379
    
    # Forwarder config
    FORWARDER_ID=vpc-forwarder
    FORWARDER_ZONE=us-central1-a
    
    # Start tunnel to Redis Memorystore in background
    gcloud compute ssh \
      --zone=${FORWARDER_ZONE} \
      --ssh-flag="-N -L ${MEMORYSTORE_LOCAL_PORT}:${MEMORYSTORE_IP}:${MEMORYSTORE_REMOTE_PORT}" \
      ${FORWARDER_ID} &
    
    # Run migrations and start Puma
    bundle exec rake db:migrate && bundle exec puma -p 8080
    

    With the solution above Memorystore will be available to your application on localhost:6379.

    There are a few caveats though

    1. This approach requires the service account configured on your Cloud Run service to have the roles/compute.instanceAdmin role, which is quite powerful.
    2. The SSH keys are backed into the image to speedup container boot time. That's not ideal.
    3. There is no failover if your forwarder crashes.

    I've written a longer and more elaborated approach in a blog post that improves the overall security and adds failover capabilities. The solution uses plain SSH instead of the gcloud CLI.

提交回复
热议问题