第6章 Kubernetes with minikube
いよいよKubernetesを使ってマイクロサービスを構築していきます。
本章では、ローカル環境で簡単にKubernetes環境を構築できるminikubeを使ってKubernetes上にマイクロサービスを構築します。
チュートリアル全体
構成
minikubeとkubectlの準備
まずは、Kubernetesをローカル環境で再現できるminikubeを準備します。
公式ドキュメントにしたがってインストールを行います。
インストールが完了したら下記コマンドでminikubeを起動します。
minikube start
※ 私の環境はLinux Mintなのですが、VirtualBox版の起動がうまくいかないため、minikube start --vm-driver kvm
でKVM版を起動しています。
ingressアドオンを有効にします。(少し時間がかかります)
minikube addons enable ingress
minikubeでは、下記のコマンドを実行することで、ダッシュボードにブラウザでアクセスできます。
minikube dashboard
ブラウザで自動で下記のダッシュボードが開かれます。(画像では既に本章で構築するマイクロサービスが稼働している状態です)
続いて、Kubernetesをコマンドラインから操作するkubectl
コマンドをインストールします。
公式ドキュメントの説明に沿ってインストールします。
インストールできたら、minikubeを認識しているか、下記のコマンドで確認してみましょう。
currentの*
がminikubeについていれば問題ありません。
(既にGKE等の別のKubernetes環境を利用している場合はkubectl config use-context minikube
で切り替えましょう)
kubectl config get-contexts
CURRENT NAME CLUSTER AUTHINFO NAMESPACE
* minikube minikube minikube
以上でminikubeとkubectlの準備は完了です。
minikubeにDockerイメージを登録する
docker
コマンドが利用するdocker enginをminikubeのものに変更します。
eval $(minikube docker-env)
次に前章で作成したmicroservice-sample-integration
リポジトリのmake build
でDockerイメージを作成し、minikubeのイメージリポジトリへ登録します。
cd path/to/microservice-sample-integration
make build
以上でminikube上へDockerイメージをpushできました。
yamlファイルによるKubernetesの設定
それでは、Kubernetesの設定を記述していきます。
Kubernetesはkubectl
コマンドやダッシュボードを利用した操作の他に、マニュフェストファイルというyaml形式で記述されたファイルを利用した操作が可能と成っています。
おそらく、ほとんどの現場ではこのマニュフェストファイルでの管理を実施しているはずだと思います。
今回作成する各マニュフェストファイルと、それぞれの役割について紹介します。
- tweet-db.yml
- Tweetサービスのデータベースです
- PersistentVolumeを使いデータの永続化を行います
- StatefulSetを使い、MongoDBのクラスター構成を構築できるようにします
- tweet.yml
- Tweetサービスです
- k8sのServiceとDeploymentを記述します
- user-db.yml
- Userサービスのデータベースです
- tweet-dbとほぼ同じ設定です
- user.yml
- Userサービスです
- k8sのServiceとDeploymentを記述します
- web.yml
- Webサービスです
- ingress.yml
- ロードバランサーの設定です
- cluster-role.yml
- Kubernetes APIのRoleを設定します
- MongoDBのside carからAPIを利用するために作成します
それでは、詳細に1ファイルずつ確認していきます。
tweet-db.yml
Tweetサービスのデータベース用のサービスの設定です。
複数のノードからなるデータベースはステートフルのため、少し工夫が必要です。
公式ブログのRunning MongoDB on Kubernetes with StatefulSetsを参考に実装しています。
---
apiVersion: v1
kind: Service
metadata:
name: tweet-db
labels:
name: tweet-db
spec:
ports:
- port: 27017
targetPort: 27017
clusterIP: None
selector:
app: tweet-db
---
apiVersion: apps/v1
kind: StatefulSet
metadata:
name: tweet-db
spec:
selector:
matchLabels:
app: tweet-db
serviceName: tweet-db
replicas: 3
template:
metadata:
labels:
app: tweet-db
spec:
terminationGracePeriodSeconds: 10
containers:
- name: tweet-db
image: mongo
command:
- mongod
- "--bind_ip"
- 0.0.0.0
- "--replSet"
- rs0
- "--smallfiles"
- "--noprealloc"
ports:
- containerPort: 27017
volumeMounts:
- name: tweet-db-pvc
mountPath: /data/db
- name: tweet-db-sidecar
image: cvallance/mongo-k8s-sidecar
env:
- name: MONGO_SIDECAR_POD_LABELS
value: "app=tweet-db"
- name: KUBERNETES_MONGO_SERVICE_NAME
value: tweet-db
volumeClaimTemplates:
- metadata:
name: tweet-db-pvc
spec:
accessModes:
- "ReadWriteOnce"
resources:
requests:
storage: 100Mi
tweet.yml
TweetサービスのNode.jsで実装したAPI部分を動かす部分です。コンテナを動かすDeploymentとそれをクラスター内へ公開するServiceを定義しています。
---
apiVersion: v1
kind: Service
metadata:
name: tweet-service
spec:
ports:
- port: 3000
targetPort: 3000
selector:
app: tweet
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: tweet-deployment
labels:
app: tweet
spec:
replicas: 1
selector:
matchLabels:
app: tweet
template:
metadata:
labels:
app: tweet
spec:
containers:
- name: tweet
image: microservice_tweet:1.0
ports:
- containerPort: 3000
env:
- name: MONGODB_URL
value: mongodb://tweet-db:27017/tweet?replicaSet=rs0
- name: WAIT_HOSTS
value: tweet-db:27017
user-db.yml
UserサービスのDB部分です。tweet-db.yml
とほぼ同じ構成です。
---
apiVersion: v1
kind: Service
metadata:
name: user-db
labels:
name: user-db
spec:
ports:
- port: 27017
targetPort: 27017
clusterIP: None
selector:
app: user-db
---
apiVersion: apps/v1
kind: StatefulSet
metadata:
name: user-db
spec:
selector:
matchLabels:
app: user-db
serviceName: user-db
replicas: 3
template:
metadata:
labels:
app: user-db
spec:
terminationGracePeriodSeconds: 10
containers:
- name: user-db
image: mongo
command:
- mongod
- "--bind_ip"
- 0.0.0.0
- "--replSet"
- rs0
- "--smallfiles"
- "--noprealloc"
ports:
- containerPort: 27017
volumeMounts:
- name: user-db-pvc
mountPath: /data/db
- name: user-db-sidecar
image: cvallance/mongo-k8s-sidecar
env:
- name: MONGO_SIDECAR_POD_LABELS
value: "app=user-db"
- name: KUBERNETES_MONGO_SERVICE_NAME
value: user-db
volumeClaimTemplates:
- metadata:
name: user-db-pvc
spec:
accessModes:
- "ReadWriteOnce"
resources:
requests:
storage: 100Mi
user.yml
UserサービスのAPI部分です。こちらもtweet.yml
とほぼ同じ構成です。
---
apiVersion: v1
kind: Service
metadata:
name: user-service
spec:
ports:
- port: 3000
targetPort: 3000
selector:
app: user
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: user-deployment
labels:
app: user
spec:
replicas: 1
selector:
matchLabels:
app: user
template:
metadata:
labels:
app: user
spec:
containers:
- name: user
image: microservice_user:1.0
ports:
- containerPort: 3000
env:
- name: MONGODB_URL
value: mongodb://user-db:27017/user?replicaSet=rs0
- name: WAIT_HOSTS
value: user-db:27017
web.yml
Webサービスでは、GitHubのOAuth用環境変数をSecretから取得する設定にしています。
Secretの作成は後述します。
---
apiVersion: v1
kind: Service
metadata:
name: web-service
labels:
app: web-service
spec:
ports:
- port: 3000
targetPort: 3000
selector:
app: web
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: web-deployment
labels:
app: web
spec:
replicas: 1
selector:
matchLabels:
app: web
template:
metadata:
labels:
app: web
spec:
containers:
- name: web
image: microservice_web:1.0
ports:
- containerPort: 3000
env:
- name: GITHUB_CLIENT_ID
valueFrom:
secretKeyRef:
name: github-oauth
key: GITHUB_CLIENT_ID
- name: GITHUB_CLIENT_SECRET
valueFrom:
secretKeyRef:
name: github-oauth
key: GITHUB_CLIENT_SECRET
- name: CALLBACK_URL
value: http://microservice.test/callback
- name: BASE_URL
value: http://microservice.test
- name: NUXT_HOST
value: 0.0.0.0
- name: USER_SERVICE
value: http://user-service:3000
- name: TWEET_SERVICE
value: http://tweet-service:3000
dnsConfig:
nameservers:
- 8.8.8.8
ingress.yml
Ingressを利用してWebサービスを公開します。
Ingressを利用することで、AWSならALB、GCPならLoadBalancerを作成してくれます。
k8sでのサービスの公開方法はいくつかありますが、この記事が参考になります。
---
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
name: ingress
spec:
rules:
- host: microservice.test
http:
paths:
- backend:
serviceName: web-service
servicePort: 3000
cluster-role.yml
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
name: admin
rules:
- apiGroups: [""]
resources: ["pods", "nodes"]
verbs: ["get", "watch", "list"]
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
name: rbac
subjects:
- kind: ServiceAccount
name: default
namespace: default
roleRef:
kind: ClusterRole
name: admin
apiGroup: rbac.authorization.k8s.io
サービスを構築する
それでは、作成したマニュフェストファイルを使い、サービスが稼働するように構築していきます。
minikubeはローカルPC上のVMで稼働しているため、エンドポイントがminikubeのIPとなってしまいます。
Ingressの設定をhttpで作成したので、この場合は、http://<minikubeのIP>
がwebサービスのエンドポイントになっています。
今回はこのIPアドレスにhostsでmicroservice.test
という名前をつけ、エンドポイントをhttp://microservice.test
という形でアクセスするように設定しましょう。
OAuth設定の作成
エンドポイントが変更になったので、前章までのlocalhost:3000
用のOAuth設定は利用できません。
新しいOAuth設定を作成します。
こちらを参考に、GitHubでOAuth用のClientIDとClientSecretを取得してください。
その際、callbackURLはhttp://microservice.test/callback
とします。
作成したOAuth設定のIDとSecretは.env.minikube
に以下の形式で設定しておきましょう。
GITHUB_CLIENT_ID=xxxxxxxxxxxxxx
GITHUB_CLIENT_SECRET=xxxxxxxxxxxxxxxxx
hostsの設定
minikubeのIPをmicroservice.testという名前でhostsに設定します。
minikubeのIPはminikube ip
コマンドで取得できます。
# 略
192.168.42.242 microservice.test
Secretの作成
先ほど作成したGitHubのOAuth設定をSecretというKubernetesの機能を利用して、Kubernetes上から参照できるようにします。
以下のコマンドでファイルを指定してSecretが作成できます。
kc create secret generic github-oauth --from-env-file .env.minikube
作成できたらダッシュボードから確認してみましょう。
ダッシュボードはminikube dashboard
で開くことができます。
kubectlで構築
それでは、kubectlコマンドでマニュフェストファイルを利用しサービスを構築していきます。
kubectl apply -f manifests/cluster-role.yml
kubectl apply -f manifests/tweet-db.yml
kubectl apply -f manifests/tweet.yml
kubectl apply -f manifests/user-db.yml
kubectl apply -f manifests/user.yml
kubectl apply -f manifests/web.yml
kubectl apply -f manifests/ingress.yml
作成できたら、ブラウザでhttp://microservice.test
へアクセスしてみましょう。
userやtweetを何も作成していないため、データは表示されませんが、下記コマンドで前章と同様にデータを投入できます。
kubectl exec <user/tweetのpod名> node scripts/initialize.sh
# deployment名は下記コマンドで確認可能
kubectl get pods
無事にサービスが動いていれば、本章のチュートリアルは完了です。
その他デバッグに役立つコマンド
# ターミナル接続
kubectl -it exec <pod名> sh
# ログの確認(ダッシュボード上でも確認可能)
kubectl logs -f <pod名>
まとめ
本章ではminikubeを使い、ローカルPC上に構築したKubernetesに対し、マイクロサービスを構築しました。
以上で本チュートリアルは終了です。
いかがだったでしょうか?
不足している点などは、今後追記していこうかと思います。
ありがとうございました。