minikubeでマルチサービスを立ち上げる(1)
kubernetesの勉強のために、Minikubeでマルチサービスを立ち上げます。
ボリュームが大きいので複数回に分けて紹介していきます。
ソースコードはこちらに記載していきます。
初回は1つのサービスを立ち上げ、ホストから確認できるまでをまとめます。
環境構築に関しては、今回の記事では扱いません。
Minikube, kubectl, Dockerを適宜インストールしておいてください。
今回実装するもの
- nginx
- WordPress
- phpMyAdmin
- mariaDB
- InfluxDB
- Grafana
- ftps
基本的に公式のイメージを使用しますが、ftpsは公式イメージが見つからなかったためAlpineベースのイメージを作成する予定です。
また、Minikubeでは外部のロードバランサーが使えないため、MetalLBを使用します。
minikubeを起動する
下記コマンドを実行します。
minikube start --driver=docker
minikube status # minikubeが立ち上がっているかの確認
最初のサービスを立ち上げる
一番シンプルにできる(であろう)nginxを立ち上げていきながら、基本的な流れを追っていきます。
公式のイメージに一手間加え、オレオレ証明書によるhttps接続などを追加します。
そのため、Dockerfileを以下のように作成し、コンテナイメージをビルドします。
FROM nginx
RUN mkdir /etc/nginx/ssl && openssl genrsa -out /etc/nginx/ssl/server.key 2048 && openssl req -new -x509 -days 3650 -key /etc/nginx/ssl/server.key -out /etc/nginx/ssl/server.crt -subj "/C=JP/ST=Tokyo/"
COPY nginx.conf /etc/nginx/conf.d/default.conf
server {
listen 80;
listen [::]:80;
server_name _;
return 301 https://$host$request_uri;
}
server {
listen 443 ssl default_server;
listen [::]:443 ssl default_server;
server_name _;
ssl_certificate /etc/nginx/ssl/server.crt;
ssl_certificate_key /etc/nginx/ssl/server.key;
root /usr/share/nginx/html;
index index.html;
location / {
try_files $uri $uri/ =404;
}
}
ホストマシンで、Minikube組み込みのDockerデーモンを操作できるようにするために下記のコマンドを実行します。
eval $(minikube -p minikube docker-env)
コマンド実行後にdocker images
を実行するとkubernetes関連のコンテナイメージがあり、MinikubeのDockerデーモンにつながっていることが確認できるはずです。
docker build
で今回使用するnginxのイメージを作成しましょう。
kubernetesのマニフェストのファイルを以下のように作成します。
apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx
labels:
app: nginx
spec:
replicas: 1
selector:
matchLabels:
app: nginx
template:
metadata:
labels:
app: nginx
spec:
containers:
- name: nginx
image: nginx:latest
imagePullPolicy: Never
ports:
- containerPort: 80
name: http
- containerPort: 443
name: https
オブジェクトの種類にDeploymentを指定しています。
DeploymentオブジェクトがReplicaSetオブジェクトを管理し、RepricaSetがPodを管理します。
spec.replicas
の値で複製するPodの個数を指定できます。
立ち上げるPodはspec.template
で指定しています。
spec.template.spec.containers
で使用するコンテナの指定をしています。
spec.template.spec.containers.image
でイメージの指定、spec.template.spec.containers.ports
で開放するポートを指定しています。
これ以外にも環境変数やマウントボリュームの設定を行うこともでき、それらは他のサービスの実装時に説明します。
docker run
の-p
オプションや-e
, -v
オプションだと思ってもらえればいいです。
spec.template.spec.containers.imagePullPolicy
の項目を記載しない場合はAlways
として設定されます。
リポジトリからイメージを取得する設定となりますが、今回はDokerHubを使用せずローカルのイメージを使用するため、Never
を設定しています。
yamlファイルが作成できたらkubernetesに反映させていきましょう。
kubectl apply -f nginx-deployment.yaml
kubectl get all
で起動していることを確認します。
$ kubectl get all
NAME READY STATUS RESTARTS AGE
pod/nginx-c7d66576c-vsfqc 1/1 Running 0 3s
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
service/kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 57m
NAME READY UP-TO-DATE AVAILABLE AGE
deployment.apps/nginx 1/1 1 1 3s
NAME DESIRED CURRENT READY AGE
replicaset.apps/nginx-c7d66576c 1 1 1 3s
立ち上がったPodでシェルを立ち上げ、Dockerfileやマニフェストで設定したものが反映されているのかを確認しましょう。
kubectl exec <pod> -- <command>
で指定したポッドでコマンドを実行できます。
kubectl exec -it nginx-c7d66576c-vsfqc -- sh
続いて、nginxサーバーが正しく機能しているのかを確認します。
$ kubectl get pod -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
nginx-c7d66576c-vsfqc 1/1 Running 0 4m19s 172.17.0.3 minikube <none> <none>
Minikube内でのIPアドレスが確認できたので、Minkube内に新たに検証用のPodを立てて接続を確認しましょう。
$ kubectl run busybox --image=busybox --restart=Never --rm -it sh
If you don't see a command prompt, try pressing enter.
/ # wget -q -O - http://172.17.0.3
wget: note: TLS certificate validation not implemented
<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
<style>
body {
width: 35em;
margin: 0 auto;
font-family: Tahoma, Verdana, Arial, sans-serif;
}
</style>
</head>
<body>
<h1>Welcome to nginx!</h1>
<p>If you see this page, the nginx web server is successfully installed and
working. Further configuration is required.</p>
<p>For online documentation and support please refer to
<a href="http://nginx.org/">nginx.org</a>.<br/>
Commercial support is available at
<a href="http://nginx.com/">nginx.com</a>.</p>
<p><em>Thank you for using nginx.</em></p>
</body>
</html>
ホストでwgetやcurl、ブラウザでアクセスしようとしても返ってこないので、次に外部に公開する設定をしていきましょう。
ロードバランサの導入
minikubeでは外部のロードバランサが使用できないため、MetalLBを使用します。
Minikubeのアドオン、マニフェスト、kustomizeのいずれかでインストールできます。
今回はマニフェストでインストールすることにします。
kubectl apply -f https://raw.githubusercontent.com/metallb/metallb/v0.9.6/manifests/namespace.yaml
kubectl apply -f https://raw.githubusercontent.com/metallb/metallb/v0.9.6/manifests/metallb.yaml
# On first install only
kubectl create secret generic -n metallb-system memberlist --from-literal=secretkey="$(openssl rand -base64 128)"
完了すると以下のようにPodが確認できます。
$ kubectl get pod -n metallb-system
NAME READY STATUS RESTARTS AGE
controller-64f86798cc-bmt6g 1/1 Running 0 3m11s
speaker-785lf 1/1 Running 0 3m11s
これだけではMetalLBが待機状態になっているので、公式ドキュメントの方法にならってconfigを追加します。
apiVersion: v1
kind: ConfigMap
metadata:
namespace: metallb-system
name: config
data:
config: |
address-pools:
- name: default
protocol: layer2
addresses:
- 192.168.49.50 - 192.168.49.60
ファイルが作成できたら反映させます。
kubectl apply -f metallb-configma.yaml
続いて、nginxのServiceを立ち上げていきます。
Serviceの説明は公式ドキュメントを参照します。
Kubernetesにおいて、ServiceはPodの論理的なセットや、そのPodのセットにアクセスするためのポリシーを定義します(このパターンはよくマイクロサービスと呼ばることがあります)。 ServiceによってターゲットとされたPodのセットは、たいてい セレクター (セレクターなしのServiceを利用したい場合は下記を参照してください)によって定義されます。
例えば、3つのレプリカが稼働しているステートレスな画像処理用のバックエンドを考えます。これらのレプリカは代替可能です。— フロントエンドはバックエンドが何であろうと気にしません。バックエンドのセットを構成する実際のPodのセットが変更された際、フロントエンドクライアントはその変更を気にしたり、バックエンドのPodのセットの情報を記録しておく必要はありません。
Serviceによる抽象化は、クライアントからバックエンドのPodの管理する責務を分離することを可能にします。
Serviceを導入することで適宜名前解決をしてくれるようになります。
ロードバランサだけでなく、のちに出てくるDBとの接続の際にも活用していきます。
nginxのServiceのマニフェストは以下のようにします。
apiVersion: v1
kind: Service
metadata:
name: nginx
annotations:
metallb.universe.tf/allow-shared-ip: mini_services
spec:
selector:
app: nginx
type: LoadBalancer
ports:
- name: http
port: 80
- name: https
port: 443
複数のサービスに同一のIPアドレスでアクセスできるようにmetadata.annotations.metallb.universe.tf/allow-shared-ip
を設定します。
spec.selector
でServiceで指定したいDeploymentを記載します。
ファイルができたら反映させます。
kubectl apply -f nginx-service.yaml
ここまでできたら、実際にホストから接続できるのかを確認します。
$ kubectl get svc
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 102s
nginx LoadBalancer 10.101.60.141 192.168.49.50 80:30047/TCP,443:30638/TCP 71s
EXTERNAL-IP
が設定されているのがわかります。
ホストマシンで接続を確認しましょう。
$ curl -IkL 192.168.49.50:80
HTTP/1.1 301 Moved Permanently
Server: nginx/1.19.8
Date: Fri, 26 Mar 2021 04:15:50 GMT
Content-Type: text/html
Content-Length: 169
Connection: keep-alive
Location: https://192.168.49.50/
HTTP/1.1 200 OK
Server: nginx/1.19.8
Date: Fri, 26 Mar 2021 04:15:50 GMT
Content-Type: text/html
Content-Length: 612
Last-Modified: Tue, 09 Mar 2021 15:27:51 GMT
Connection: keep-alive
ETag: "604793f7-264"
Accept-Ranges: bytes
80番ポートから443番ポートにリダイレクトされていることが確認できます。
ブラウザからアクセスすればnginxのインデックスページが表示されるはずです。
終わりに
今回は以下のオブジェクトの実装を行いました。より詳しく知りたい場合は公式のAPIリファレンスを参照してください。
- Pod
- ReplicaSet
- Deployment
- Service
- MetalLB(LoadBalancer)
kubernetesでの基本的な流れが掴めたと思うので、次回以降他のサービスを立ち上げていきます。
Discussion