今回は実際にKubernetesを使って、何かを作ろうと思って、シナリオを考えました。
手頃なオープンソースソフトウエアでいいかなと思って、WordPress(ブログサイトを作るもの)にしました。
構成
構成としては、以下のように考えています。
- GCP(Google Cloud Platform)のマネジッドサービスのGKE(Kubernetes)を使用
- WordPressはPodとして稼働(3レプリカ)
- DatabaseはGCPのマネジッドサービスのcloudSQLを使用
- WordPressとcloudSQLはGCP内部ネットワーク(VPC)を通じて通信
構成図:
前提条件
今回管理を作るための前提としては、以下のものを事前に用意する必要があります。
- GCPの環境
- GCPでGKEとcloudSQLの管理者権限
- GCPの下記API有効化されていること
- Service Networking API:プライベートIP使用のため
リソースの作成
GCPで以下のリソースを作成する必要があります。
- GKE
- cloudSQL
以下で作成方法について、説明していきます。
GKEの作成
今回WordpressとcloudSQLの通信は内部ネットワークを使用することを前提としているので、GKEはVPCネイティブで作成する必要があります。
VPCネイティブでGKEを作成する時に、--enable-ip-alias
オプションを付けて作成すればいいです。
下記作成コマンド例を適切に修正し、GCPのcloudshellで実行すればいいです。
※cloudshellの起動はこちらをご確認ください。
作成コマンド例:
# GKE cluster名:demo-cluster
# enable-ip-alias:VPCネイティブ
# create-subnetwork:サブネット作成
# サブネットのプライマリIP範囲(Node用):"10.0.0.0/20"
# サブネットのセカンダリIP範囲(Pod用):"10.1.0.0/16"
# サブネットのセカンダリIP範囲(Service用):"10.2.0.0/20"
gcloud container clusters create demo-cluster \
--no-enable-autoupgrade \
--zone="asia-northeast1-a" \
--enable-ip-alias \
--create-subnetwork name="gke-subnet",range="10.0.0.0/20" \
--cluster-ipv4-cidr="10.1.0.0/16" \
--services-ipv4-cidr="10.2.0.0/20"
... 5分ほどで作成可能です。
cloudSQLの作成
cloudSQLの作成はコマンドでプライベートIPのみ持っているcloudSQLを作成します。
※プライベートIPを持たせるための設定は、現時点beta版のコマンドしかできないので、gcloud beta sql instances create
を使用しております。
下記作成コマンド例を適切に修正し、GCPのcloudshellで実行すればいいです。
作成コマンド例:
# cloudSQLリソース名:demo-db
# tier:sql用仮想マシンのタイプ(スペック)
# region:リソースのリージョン
# database-version:データベースの種類とバージョン
# root-password:mysqlのrootユーザーパスワード
# network:プライベートIPのVPCはdefaultを使用する
# no-assign-ip:global ip割り振らない
gcloud beta sql instances create demo-db \
--tier="db-n1-standard-1" \
--region="asia-northeast1" \
--database-version="MYSQL_5_7" \
--root-password="t0Dq9rkNIro" \
--network="default" \
--no-assign-ip
...5分ほどかかります
これで作成されたら、cloudSQLはプライベートIP持ちの形式で作成されます。
作成後、cloudshellコンソールに結果が表示されます。そのうちのPRIVATE_ADDRESSに表示されたIPをメモしておきましょう。
これは、wordpressのDB接続に使用されます。
以下のコマンドで直接IP取得できます。(スクリプトとかには使えるかと)
gcloud sql instances list --filter="name=demo-db" | awk '{print $6}' | sed -e '1d' | head -n 1
wordpress用のDBとユーザーの作成
wordpress用のDBとユーザーを事前に用意する必要があります。
今回作成したcloudSQLの実質はMySQLなので、mysqlクライアントから接続して作成してもいいですが、gcloudコマンドも簡単に作成できます。
データベース作成
# データベース名:wp-database
# instance:対象cloudSQLを指定
# charset:データベースの文字コード種類
gcloud sql databases create wp-database --instance=demo-db --charset=utf8
ユーザー作成
# username:demouser
# instance:対象cloudSQLを指定
# password:パスワード指定
# host:接続元許可リスト、"%"はすべて許可
gcloud sql users create demouser --instance=demo-db --password=demouserpass --host="%"
※今回作成したcloudSQLはプライベートIPしか持たないので、--host
が%
に設定しても、プライベートネットワークしか接続できないので、セキュリティは担保できるかと思います。
公開用global IPの作成
次は、kubernetesのloadbalancer用のglobal ipを用意します。
作成コマンド例:
# globalIPリソース名:wordpress-ip
# リソースのリージョン:asia-northease1(東京)
gcloud compute addresses create wordpress-ip --region="asia-northeast1"
このIPは後で作成するKubernetesのLoadbalancerに使うので、抑える必要があります。
以下のコマンドで、作成したIPを取得できます
# wordpress-ipのIPを取得する
gcloud compute addresses list --filter="name=wordpress-ip" | awk '{print $2}' | sed -e '1d' | head -n 1
ここまで、GCPリソースの準備は整えました。
次から、いよいよKubernetesのリソース作成に取り掛かります。
manifestの用意
今回の構成は、以下のものが必要です。
- wordpressの設定情報を保持するためのsecret
- wordpressデプロイするためのdeployment workload
- wordpressへ接続&ロードバランシングするためのLoadbalancer Service
では、順番に例を挙げていきます。
secret
secretの作成は設定ファイルを用いて作ったほうが簡単なので、ここでは設定ファイルの方を用意します。
このsecretは、wordpressのDB接続設定の内容が書かれています。
ファイル名は任意なんですが、この例でwp-db-env.confをファイル名とします。
また、設定値はcloudSQL作成と設定した内容を書き換えればいいです。
WORDPRESS_DB_HOST=<cloudSQL privateIP>
WORDPRESS_DB_USER=demouser
WORDPRESS_DB_PASSWORD=demouserpass
WORDPRESS_DB_NAME=wp-database
WORDPRESS_TABLE_PREFIX=wp_
設定内容説明:
- WORDPRESS_DB_HOST:cloudSQLのプライベートIP
- WORDPRESS_DB_USER:wordpressデータベース接続用ユーザー
- WORDPRESS_DB_PASSWORD:wordpressデータベース接続用ユーザーのパスワード
- WORDPRESS_DB_NAME:wordpressデータベース
- WORDPRESS_TABLE_PREFIX:wordpressのテーブルのプレフィックス(wp_そのままでいいです)
※WordPressの設定について、Dockerイメージの説明をご参照ください。
loadbalancer
Loadbalancerを作成する時に、先ほど作成したglobal IPを用意する必要があります。
ファイル名をwp-loadbalancer.yamlとします。
apiVersion: v1
kind: Service
metadata:
name: my-nlb-service
labels:
app: wordpress
spec:
selector:
app: wordpress
type: LoadBalancer
loadBalancerIP: "<global ipのアドレス>" # 先ほど作成したGCPのグローバルIPのアドレス
ports:
- port: 8080 # 受付ポート
targetPort: 80 # Podへ転送するポート
deployment
WordPressのdeploymentを作成するためのmanifest
ファイル名をwp-deployment.yamlとします。
apiVersion: apps/v1
kind: Deployment
metadata:
name: wp-deployment
labels:
app: wordpress
spec:
replicas: 3
selector:
matchLabels:
app: wordpress
template:
metadata:
labels:
app: wordpress
spec:
containers:
- name: wp-container
image: wordpress:latest
ports:
- containerPort: 80
lifecycle:
postStart:
exec:
command: ["/bin/sh", "-c", "echo $(hostname) > /var/www/html/test.php"] # wpのホームディレクトリにページファイルを作成する
envFrom: # wpがDBへ接続に使う環境変数
- secretRef:
name: wp-db-env # 作成されたsecret名
kubernetesリソースの作成
GCPのcloudshellでは、kubectlのSDKはデフォルトで入っていますので、そのままで使用可能です。
しかも、ローカルのファイルはドラッグアンドドロップするだけで、cloudshellの~
ディレクトリにアップロードできます。
そのため、以下のことをすれば、マニフェストの適用ができます。
- manifestファイルをcloudshellにアップロード
2.GKEへ接続 - kubectl apply -f を実行する
- secret作成
- deployment作成
- loadbalancer作成
manifestファイルのアップロード
先ほど作成した以下のファイルをドラッグアンドドロップでcloudshellへアップロードします。
- wp-db-env.conf
- wp-deployment.yaml
- wp-loadbalancer.yaml
アップロード後、以下のコマンドで、ファイルがアップロードされていることを確認します。
cd ~
ls
GKEへの接続
cloudshellからGKEへ接続するために、以下のコマンドを実行します。
# 接続先:demo-cluster
# zone:GKEクラスタのzone
gcloud container clusters get-credentials demo-cluster --zone asia-northeast1-a
以下の内容が表示されたら、接続成功です。
Fetching cluster endpoint and auth data.
kubeconfig entry generated for <cluster name>.
リソース作成
順番に以下のコマンドを実行して、リソースを作成していきます。
# secret名はwp-db-envでsecretを作成
kubectl create secret generic wp-db-env --save-config --from-env-file=wp-db-env.conf
# deploymentとLoadbalancerを作成
kubectl apply -f ./wp-deployment.yaml -f ./wp-loadbalancer.yaml
リソースの確認
以下のコマンドで、リソースが作成されたことを確認します。
kubectl get pods # podsがすべてrunning状態であることを確認
kubectl get secrets
kubectl get loadbalancer
以上で、環境の構築と設定がすべて完了です。
環境の確認
http://<loadbalancerのIP>:8080 でwordpressのサイトへアクセスしてみよう。
最初設定画面が表示されるはずです、画面に従って、設定を完成させてたら、wordpressのホームページが表示されます。
今回の例では、loadbalancerがロードバランシングしていることを確認するため、<ホームページ>/test.phpページを用意しています。
このペースにアクセスすると、pod名が表示されますので、アクセスごとに時間をちょっと置いてからアクセスすると、変わったことでロードバランシングされていることがわかります。
以上で完了です。
最後
今回の構成はシンプルだけど、汎用的なWebサイト公開の構成かと思います。
WordPressをWEBサーバに入れ替えれば、大量アクセスに耐えられるサイトが作ることが可能かと思います。
wordpressでは、基本管理者の操作はログインしてからになるので、ロードバランシングで他のpodに行くと、ログイン状態が変わります。
これの対処方法は一応以下の2つを考えています。
- 管理者専用のGCEか、StatefulSetを作って、管理者専用のエンドポイントを用意して対応(管理者しかログインしない場合)
- Loadbalancerに同じソース端末からの接続を維持する設定をする(誰でもログインできる場合)
+ ※設定自体は可能ってことは知っていますが、設定方法は筆者も調べないといけないので、また今後機会あれば書こうと思います- 2020/6/25更新:cloud LoadBalancerに「セッション アフィニティ」の設定で、セッションを維持することが可能ということがわかったのですが、作成済みのLoadBalancerは変更できないぽいです。
継続調査中... - 2020/07/07更新:cloud LoadBalancerの「セッション アフィニティ」設定はインスタンスへのセッション維持らしいです。Podのセッション維持ではありませんでした。
- 2020/6/25更新:cloud LoadBalancerに「セッション アフィニティ」の設定で、セッションを維持することが可能ということがわかったのですが、作成済みのLoadBalancerは変更できないぽいです。
いかがでしたでしょうか。
ここまで読んでいただいて、お疲れ様でした。
コメント
看着好难。