とあるエンジニアブログ

備忘録みたいなもの

GKEにデプロイしHTTPロードバランシングする

Container RegistryにアプリケーションDockerイメージをプッシュする

cloud.google.com

自前でアプリケーションをビルドしたDockerfileを作成する
ビルドしContainer Registryにプッシュする

GCP_PROJECT_ID="sample-dev"
GCP_IMAGE=asia.gcr.io/$GCP_PROJECT_ID/sample:0.0.1

# build
docker build -f dockerfiles/Dockerfile -t $GCP_IMAGE .

# push
gcloud docker -- push $GCP_IMAGE

これで準備完了
kubectlを使いGKEにデプロイする

deployment.yamlを記載する

以下、レプリカ数2で作ったdeployment.yaml
詳細は省くがポイントはDBの環境変数に登録したcredentialsを使用していること

apiVersion: apps/v1beta1
kind: Deployment
metadata:
  name: deployment-dev
spec:
  replicas: 2
  template:
    metadata:
      labels:
        app: sample
    spec:
      containers:
      - name: sample
        image: asia.gcr.io/sample-dev/sample:0.0.1
        ports:
        - containerPort: 4000
        args: ["foreground"]
        env:
          - name: DB_HOST
            value: "127.0.0.1"
          - name: DB_PORT
            value: "3306"
          - name: DB_USER
            valueFrom:
              secretKeyRef:
                name: cloudsql-db-credentials
                key: username
          - name: DB_PASSWORD
            valueFrom:
              secretKeyRef:
                name: cloudsql-db-credentials
                key: password
      - name: cloudsql-proxy
        image: gcr.io/cloudsql-docker/gce-proxy:1.09
        command: ["/cloud_sql_proxy", "--dir=/cloudsql",
                  "-instances=sample-dev:asia-northeast1:db-dev=tcp:3306",
                  "-credential_file=/secrets/cloudsql/credentials.json"]
        volumeMounts:
          - name: cloudsql-instance-credentials
            mountPath: /secrets/cloudsql
            readOnly: true
          - name: ssl-certs
            mountPath: /etc/ssl/certs
          - name: cloudsql
            mountPath: /cloudsql
      volumes:
        - name: cloudsql-instance-credentials
          secret:
            secretName: cloudsql-instance-credentials
        - name: ssl-certs
          hostPath:
            path: /etc/ssl/certs
        - name: cloudsql
          emptyDir:

デプロイする

kubectl create -f deployment.yaml

実際にrsとpodが作成されているか確かめる

kubectl get deployment,rs,pod
NAME                    DESIRED   CURRENT   UP-TO-DATE   AVAILABLE   AGE
deploy/deployment-dev   2         2         2            2           20m

NAME                          DESIRED   CURRENT   READY     AGE
rs/deployment-dev-763713461   2         2         2         20m

NAME                                READY     STATUS    RESTARTS   AGE
po/deployment-dev-763713461-69r7v   2/2       Running   0          20m
po/deployment-dev-763713461-7jrmx   2/2       Running   0          20m

こんな感じでPodがRunningで出力されてればおk

service.yamlを記載する

ポイントはセレクタにdeployment.yamlで記載したappラベルを記載すること
ポート4000を80にポートフォワードする

apiVersion: v1
kind: Service
metadata:
  name: service-dev
spec:
  type: NodePort
  selector:
    app: sample
  ports:
  - protocol: TCP
    port: 80
    targetPort: 4000

Service作成

kubectl create -f service.yaml

ingress.yamlを記載する

Ingress での HTTP 負荷分散の設定  |  Container Engine ドキュメント  |  Google Cloud Platform
作成したservice-devに対してIngressを作成する

apiVersion: extensions/v1beta1
kind: Ingress
metadata:
  name: ingress-dev
spec:
  backend:
    serviceName: service-dev
    servicePort: 80

Ingress作成

kubectl create -f ingress.yaml

しばらくするとヘルスチェックが完了し動作する
実際に確認する

kubectl describe ing
Name:            ingress-dev
Namespace:      default
Address:        ************
Default backend:    service-dev:80 (************,************)
Rules:
  Host  Path    Backends
  ----  ----    --------
  * *   service-dev:80 (************,************)
Annotations:
  backends:     {"k8s-be-30189--16e23e70a11044da":"HEALTHY"}
  forwarding-rule:  k8s-fw-default-ingress-dev--16e23e70a11044da
  target-proxy:     k8s-tp-default-ingress-dev--16e23e70a11044da
  url-map:      k8s-um-default-ingress-dev--16e23e70a11044da
Events:
  FirstSeen LastSeen    Count   From            SubObjectPath   Type        Reason  Message
  --------- --------    -----   ----            -------------   --------    ------  -------
  8m        8m      1   loadbalancer-controller         Normal      ADD default/ingress-dev
  7m        7m      1   loadbalancer-controller         Normal      CREATE  ip: ************
  7m        2m      5   loadbalancer-controller         Normal      Service default backend set to service-dev:30189

backendsがHEALTHYになっていたらおk
これは / に GETリクエストを投げて200を確認している

外部IPにアクセスする

Address:     ************

ここにアクセスしてアプリケーションの起動と名前解決を確認する

GKEコンテナからCloudSQLにプロキシ接続する

シークレットを作成する

Google Container Engine から接続する  |  Cloud SQL for MySQL  |  Google Cloud Platform

シークレットを作成

kubectl create secret generic cloudsql-instance-credentials \
                       --from-file=credentials.json=[PROXY_KEY_FILE_PATH]

ユーザーとパスワードを登録

kubectl create secret generic cloudsql-db-credentials --from-literal=username=[USER] --from-literal=password=[PASSWORD]

deployment.yamlを作成しデプロイする

deployment.yamlファイルを記述する
DB_USER, DB_PASSWORD 環境変数を設定

- name: DB_USER
  valueFrom:
    secretKeyRef:
      name: cloudsql-db-credentials
      key: username
- name: DB_PASSWORD
  valueFrom:
    secretKeyRef:
      name: cloudsql-db-credentials
      key: password

CloudSQLインスタンス接続コマンド記載

- image: gcr.io/cloudsql-docker/gce-proxy:1.09
  name: cloudsql-proxy
  command: ["/cloud_sql_proxy", "--dir=/cloudsql",
            "-instances=[INSTANCE_CONNECTION_NAME]=tcp:3306",
            "-credential_file=/secrets/cloudsql/credentials.json"]
  volumeMounts:
    - name: cloudsql-instance-credentials
      mountPath: /secrets/cloudsql
      readOnly: true
    - name: ssl-certs
      mountPath: /etc/ssl/certs
    - name: cloudsql
      mountPath: /cloudsql
volumes:
  - name: cloudsql-instance-credentials
    secret:
      secretName: cloudsql-instance-credentials
  - name: ssl-certs
    hostPath:
      path: /etc/ssl/certs
  - name: cloudsql
    emptyDir:

アプリケーション側でDB_USER, DB_PASSWORDを読み込む用実装する
次回Elixirアプリケーションも記載したdeployment.yamlを作成する

GKEコンテナクラスタを作成しkubectlセットアップ

ともかくコンテナクラスタを作る

コンテナ クラスタの操作  |  Container Engine ドキュメント  |  Google Cloud Platform
ケチケチコンテナクラスタ作成
f:id:yuki-toida:20170922152743p:plain

デフォルトのクラスタを設定する

デフォルトのクラスタを設定するには、gcloud container コマンドを使用します。

gcloud config set container/cluster [クラスタ名]

kubectl を設定する

gcloud container clusters get-credentials [クラスタ名]

アプリケーションデフォルト認証を行う

gcloud auth application-default login
Credentials saved to file: [/Users/[user]/.config/gcloud/application_default_credentials.json]

These credentials will be used by any library that requests
Application Default Credentials.

こんな出力がされたら認証完了

kubectl config の確認

kubectl config view

clusters/contexts/users がそれぞれ正しいか確認
ゴミが会った場合以下のように削除する

kubectl config unset clusters.[クラスタ名]
kubectl config unset contexts.[クラスタ名]
kubectl config unset users.[クラスタ名]

Cloud Storage を構築しファイルをアップロードする

なにはともあれCloud Storageを作成する

ストレージ バケットの作成  |  Cloud Storage ドキュメント  |  Google Cloud Platform
開発環境なので Regional を選択する
ロケーションはもちろんasia-northeast1

gsutil を使いアップロード

gsutil ツール  |  Cloud Storage ドキュメント  |  Google Cloud Platform

gsutil -m rsync -r -d hoge.jpg gs://[bucket-name]/hoge.jpg

これだけ!
rsync - Synchronize content of two buckets/directories  |  Cloud Storage Documentation  |  Google Cloud Platform
rsyncコマンドを使って同期をとるのが良いと思われる

| [915/915 files][ 17.0 MiB/ 17.0 MiB] 100% Done   1.1 MiB/s ETA 00:00:00       
Operation completed over 915 objects/17.0 MiB.   

こんな感じの出力がされたらアップロード完了
楽ちん

一般公開する

データの一般公開  |  Cloud Storage ドキュメント  |  Google Cloud Platform

  • 公開するバケットのプルダウン メニューをクリックします。
  • プルダウン メニューはバケットの行の右側にある 3 つのドットが縦に並んだアイコンです。
  • [バケットの権限を編集] を選択します。
  • [メンバーを追加] フィールドに allUsers を入力します。
  • [役割を選択] プルダウン メニューで [ストレージ] サブメニューを選択し、[ストレージ オブジェクト閲覧者] オプションを選択します。
  • [追加] をクリックします。

これで公開完了

Cloud SQLを構築してローカルからアクセスする

なにはともあれCloudSQLインスタンスを作成する

インスタンスを作成する  |  Cloud SQL for MySQL  |  Google Cloud Platform
一番安いケチケチインスタンスにする

Cloud SQL フラグを設定する  |  Cloud SQL for MySQL  |  Google Cloud Platform
MySQLのフラグは下記にした(説明省略)

character-set-server=utf8mb4
collation-server=utf8mb4_unicode_ci
default_time_zone=+09:00
general_log=0
log_output=TABLE
slow_query_log=1
log_queries_not_using_indexes=1
long_query_time=0.5

Cloud SQL Proxy を使用してローカルから接続する

Cloud SQL Proxy を使用して MySQL クライアントを接続する  |  Cloud SQL ドキュメント  |  Google Cloud Platform

Cloud SQL Proxyインストール

任意のフォルダでインストールする

wget https://dl.google.com/cloudsql/cloud_sql_proxy.linux.amd64
mv cloud_sql_proxy.linux.amd64 cloud_sql_proxy
chmod +x cloud_sql_proxy

サービス アカウントを作成する

役割でCloud SQL クライアントを選択
f:id:yuki-toida:20170922135542p:plain
[新しい秘密鍵の提供]にチェックを入れ、Cloud SQL Proxyインストールフォルダにダウンロード

プロキシを起動する

インスタンス名と秘密鍵を指定してプロキシを開始する
proxy.shのようなシェルスクリプトがあると便利

#!/bin/sh

PORT=3306
INSTANCE="instance-name"
CREDENTIAL="credential.json"

./cloud_sql_proxy -instances=$INSTANCE=tcp:$PORT -credential_file=$CREDENTIAL
Listening on 127.0.0.1:3306 for instance-name
Ready for new connections

この出力がされたらプロキシが開始されている
mysqlクライアントなりSequel Pro なりでアクセスすればおk

mysql -u <USERNAME> -p --host 127.0.0.1

GCEにDockerでRedisサーバを構築する

GCE作成

インスタンスの作成と起動  |  Compute Engine ドキュメント  |  Google Cloud Platform

開発環境は一番やすいインスタンスを作ればよろし

マシンタイプ:f1-micro(vCPU x 1、メモリ 0.6 GB)
CPU プラットフォーム:Intel Broadwell
OS:debian-9
ゾーン:asia-northeast1-a

GCEにローカルからSSH接続

gcloud compute ssh [INSTANCE_NAME]

これだけという衝撃の楽さ!!!
秘密鍵:/Users/[user]/.ssh/google_compute_engine.
公開鍵:/Users/[user]/.ssh/google_compute_engine.pub.
が初回に作られるはず

GCEにDocker CEをインストール

当然SSH接続しているGCE内で行う
docs.docker.com

古いDockerをアンインストール

sudo apt-get remove docker docker-engine docker.io

aptパッケージ更新

sudo apt-get update

HTTPS経由でリポジトリを使用できるように必要なパッケージをインストールする

sudo apt-get install \
     apt-transport-https \
     ca-certificates \
     curl \
     gnupg2 \
     software-properties-common

公式GPGキーを追加

curl -fsSL https://download.docker.com/linux/$(. /etc/os-release; echo "$ID")/gpg | sudo apt-key add -

指紋9DC8 5822 9FC7 DD38 854A E2D8 8D81 803C 0EBF CD88の最後の8文字を検索して、指紋のあるキーがあることを確認

sudo apt-key fingerprint 0EBFCD88

リポジトリ追加

sudo add-apt-repository \
   "deb [arch=amd64] https://download.docker.com/linux/$(. /etc/os-release; echo "$ID") \
   $(lsb_release -cs) \
   stable"

Docker CEをインストール

sudo apt-get update
sudo apt-get install docker-ce

バージョン確認

docker -v

Docker version 17.06.2-ce, build cec0b72
こんな感じで出力されるはず、これでインストール完了

sudo コマンドなしで docker コマンドを実行できるようにする

docs.docker.com
docker グループ作成

sudo groupadd docker

docker グループにユーザー追加

sudo usermod -aG docker $USER

GCEからログアウトしてログインし直せばsudoコマンドなしでdockerコマンドが実行できるはず

Redisコンテナ起動

optにredisのデータをマウントするのが良さげ

cd /opt
docker run --name redis -d -p 6379:6379 -v /redis/data:/data redis redis-server --appendonly yes

こんだけ
latestバージョンのredisコンテナが、ポート6379にホスティングされ、/redis/dataにデータは永続化される
dockerはほんと便利

Redisコンテナの動作確認

redis-toolsをインストール

sudo apt-get install redis-tools

redisサーバーに ping 投げてみる

redis-cli ping

PONG を出力されたらおk
これでGCEへのRedisサーバー構築完了

GCPコトハジメ

何はともあれプロジェクト作成

任意のプロジェクト名とグローバルで一意なプロジェクトIDをつける
開発環境と本番環境で分けるのがベストプラクティスらしい

Preparing a Container Engine Environment for Production  |  Solutions  |  Google Cloud Platform

プロジェクト名:sample-dev
プロジェクトID:sample-dev
こんな感じでよい

Google Cloud SDK セットアップ(ユーザーアカウント認証)

ユーザーアカウント認証は主にローカルでの使用に使われるはず

Mac OS X 用のクイックスタート  |  Cloud SDK のドキュメント  |  Google Cloud Platform

初期化

gcloud init

アカウントとプロジェクトを選択

Choose the account you would like to use to perform operations for 
this configuration:
 [1] hoge@candee.co.jp
 [2] Log in with a new account
Please enter your numeric choice:  1    

You are logged in as: [yuki.toida@candee.co.jp].

Pick cloud project to use: 
 [1] sample-dev
 [2] Create a new project
Please enter numeric choice or text value (must exactly match list 
item):  1

GCEのデフォルトゾーン選択

Which Google Compute Engine zone would you like to use as project 
default?
If you do not specify a zone via a command line flag while working 
with Compute Engine resources, the default is assumed.
 [1] asia-east1-c
 [2] asia-east1-b
 [3] asia-east1-a
 [4] asia-northeast1-b
 [5] asia-northeast1-a
 [6] asia-northeast1-c
 [7] asia-southeast1-a
 [8] asia-southeast1-b
 [9] australia-southeast1-c
 [10] australia-southeast1-a
 [11] australia-southeast1-b
 [12] europe-west1-d
 [13] europe-west1-c
 [14] europe-west1-b
 [15] europe-west2-c
 [16] europe-west2-b
 [17] europe-west2-a
 [18] europe-west3-b
 [19] europe-west3-a
 [20] europe-west3-c
 [21] southamerica-east1-b
 [22] southamerica-east1-a
 [23] southamerica-east1-c
 [24] us-central1-c
 [25] us-central1-f
 [26] us-central1-a
 [27] us-central1-b
 [28] us-east1-b
 [29] us-east1-c
 [30] us-east1-d
 [31] us-east4-b
 [32] us-east4-a
 [33] us-east4-c
 [34] us-west1-a
 [35] us-west1-c
 [36] us-west1-b
 [37] Do not set default zone
Please enter numeric choice or text value (must exactly match list 

Config確認

gcloud config list

問題なければセットアップ完了

Google Cloud SDK セットアップ(サービスアカウント認証)

サービスアカウント認証は主にデプロイサーバ等で使われるはず

Cloud SDK ツールの承認  |  Cloud SDK のドキュメント  |  Google Cloud Platform

Google Cloud Platform Console の [Service Accounts] ページに移動します。

[SERVICE ACCOUNTS] ページに移動
[Create service account] をクリックするか、既存のアカウントを選択します。
サービス アカウントの表の [Options] 列にある [More] ボタン 鍵ファイルを作成する をクリックし、[Create key] を選択して、JSON 形式の鍵ファイルを作成してダウンロードします。

鍵ファイルを作成する
必要に応じて、Cloud SDK ツールを承認するシステム上の場所に鍵ファイルを移動します。
gcloud auth activate-service-account を実行します。

gcloud auth activate-service-account --key-file [KEY_FILE]
システムから鍵ファイルを削除します。

これでローカルマシンとデプロイマシンからgcloudコマンドを発行できる