Qiang Blog

Just another zhangjingqiang's blog.

Kubernetes deploy Rails app to Google Container Engine

Create a Rails App

rails new todo
rails g scaffold task title:string notes:string due:datetime completion:integer

Config Gemfile

gem 'rails', '4.2.0'
gem 'sass-rails', '~> 5.0'
gem 'uglifier', '>= 1.3.0'
gem 'coffee-rails', '~> 4.1.0'

gem 'jquery-rails'
gem 'turbolinks'
gem 'jbuilder', '~> 2.0'
gem 'sdoc', '~> 0.4.0', group: :doc

group :production do
  gem 'pg'
end

gem 'capistrano-rails', group: :development

group :development, :test do
  gem 'byebug'
  gem 'web-console', '~> 2.0'
  gem 'spring'
  gem 'sqlite3'
end

Config config/database.yml

production:
  <<: *default
  adapter: postgresql
  encoding: unicode
  database: todo_production
  username: <%= ENV['PG_ENV_POSTGRES_USER'] %>
  password: <%= ENV['PG_ENV_POSTGRES_PASSWORD'] %>
  host:     <%= ENV['PG_PORT_5432_TCP_ADDR'] %>

Add Dockerfile at Rails Root

FROM rails:onbuild

ENV RAILS_ENV=production

CMD ["sh", "/usr/src/app/init.sh"]

Use official rails on docker hub: https://hub.docker.com/_/rails/

Make init.sh at Rails Root

export SECRET_KEY_BASE=$(bundle exec rake secret)

bundle exec rake db:create db:migrate
bundle exec rails server -b 0.0.0.0

Deploying Locally

docker build -t your_user_name/todo .

Run PostgreSQL Database

docker run --name db -e POSTGRES_PASSWORD=password -e POSTGRES_USER=rails -d postgres

Check Process

$ docker ps

CONTAINER ID        IMAGE               COMMAND                CREATED             STATUS              PORTS               NAMES
30e1420e8a57        postgres:9          "/docker-entrypoint.   7 seconds ago       Up 6 seconds        5432/tcp            db

Run Web App

docker run --name web -d -p 3000:3000 --link db:pg your_user_name/todo

Deploying with Kubernetes on Google Container Engine

Create a project on http://console.developers.google.com. Enable Google Container Engine API, Compute Engine API, and Cloud Storage API.

Use Google Cloud SDK do local config

gcloud config set project my-project-id
gcloud config set compute/zone asia-east1-a

Create Google Container Cluster

gcloud container clusters create todo
gcloud container clusters get-credentials todo

Building and Sharing the Container Image

docker build -t todo .
docker tag -f todo gcr.io/my_project_id/todo:v1
gcloud docker push gcr.io/my_project_id/todo:v1

Deploying the Database

Make Database Pod File

# db-pod.yml
apiVersion: v1
kind: Pod
metadata:
  labels:
    name: db
  name: db
spec:
  containers:
  - image: postgres
    name: db
    env:
    - name: POSTGRES_PASSWORD
      value: password
    - name: POSTGRES_USER
      value: rails
    ports:
    - name: pg
      containerPort: 5432
      hostPort: 5432

Create Database Pod

kubectl create -f db-pod.yml

Make Database Service File

#db-service.yml
apiVersion: v1
kind: Service
metadata:
  labels:
    name: db
  name: db
spec:
  ports:
    - port: 5432
      targetPort: 5432
  selector:
    name: db

Create Database Service

kubectl create -f db-service.yml

Deploying Rails

Make Web Controller File

# web-controller.yml
apiVersion: v1
kind: ReplicationController
metadata:
  labels:
    name: web
  name: web-controller
spec:
  replicas: 2
  selector:
    name: web
  template:
    metadata:
      labels:
        name: web
    spec:
      containers:
      - image: gcr.io/YOUR_PROJECT_ID_HERE/todo:v1
        env:
          - name: POSTGRES_PASSWORD
            value: password
          - name: POSTGRES_USER
            value: rails
        name: web
        ports:
        - containerPort: 3000
          name: http-server

Create Web Controller

kubectl create -f web-controller.yml

Make Web Service File

# web-service.yml
apiVersion: v1
kind: Service
metadata:
  name: web
  labels:
    name: web
spec:
  type: LoadBalancer
  ports:
    - port: 3000
      targetPort: 3000
      protocol: TCP
  selector:
    name: web

Create Web Service

kubectl create -f web-service.yml

Check pods, controllers, services on kubernetes

kubectl get pods
kubectl get rc
kubectl get services

Accessing the Running Site

Check Nodes

kubectl get nodes
NAME                          LABELS                                               STATUS
gke-todo-5ccd2616-node-3bj5   kubernetes.io/hostname=gke-todo-5ccd2616-node-3bj5   Ready
gke-todo-5ccd2616-node-7afx   kubernetes.io/hostname=gke-todo-5ccd2616-node-7afx   Ready
gke-todo-5ccd2616-node-fd7e   kubernetes.io/hostname=gke-todo-5ccd2616-node-fd7e   Ready

Create Firewall

gcloud compute firewall-rules create --allow=tcp:3000 --target-tags=gke-todo-5ccd2616-node todo

Get Address

gcloud compute forwarding-rules list
NAME                             REGION      IP_ADDRESS    IP_PROTOCOL TARGET
9ea34fd96220f1e15959942001a0f5ae asia-east1-a 104.197.XXX.XXX TCP         asia-east1-a/targetPools/9ea34fd96220f1e15959942001a0f5ae

Access IP_ADDRESS

http://104.197.XXX.XXX:3000/tasks


Thanks To

docker google-cloud-platform kubernetes