「MicroK8sでKubernetesのお勉強」にて、シングル構成(1台だけ)の Kubernetes環境を作り、「MicroK8sのクラスタ作成」にて、3台のクラスタ環境を作りました。
しかし依然として、Kubernetesクラスタ内の Podで展開されているサーバープロセスに外部からアクセスすることができません。
そんな環境を作って何の意味があるのか?
と思われると思いますが、これには理由があります。
ここからちょっと昔話を。
Dockerが世に出てきて、Dockerのお勉強を進めている時に複数ノードに渡る Docker環境を統合管理する Kubernetesが作られました。
革新的なもので当時コンテナをいじっていた連中がこぞってこれを使い始めたので、情報がインターネット上によく出ていました。
私は当時 CentOS7に Dockerをインストールして Kubernetes環境を作りながらお勉強をしていたのですが、ブログの情報をマンマ真似ても、ある箇所がどうしても上手く行かないのでした。
それは Kubernetesクラスターが提供するサービスに対してクラスター外部からアクセスするという至極当たり前の使い方、複数のノードに冗長化/負荷分散された Podに対してのアクセスをどうやって振り分けるかの機能の箇所でした。
ブログに載っているサービス作成の yamlファイルには、シレッと type行に LoadBalancerと書いてあり、それで上手く行くとあったのですが、実は LoadBalancerサービスはパブリッククラウドサービス側が用意してくれている機能でオンプレじゃ使えないんですね。
Kubernetesはクラウドを使えない貧乏人には拓かれてなかったのでした…。
これを知った時に私は大層ガッカリして、当面仕事でクラウドを使う予定もなかったため、そこで Kubernetesのお勉強を止めてしまいました。
ノードポートに対して、クラスタ外部の NGINXロードバランサーで振り分ける事も考えましたが、何だか Kubernetesの機能がスポイルされている気がしたのです。
LoadBalancerが使えなければ、Kubernetesは殆ど存在意義がないように思えました。
そんな ITエンジニアが世界中にいたんでしょうね。
オンプレ Kubernetes環境で LoadBalancerタイプのサービスを実現するものが作られました。
それがこれ。
MetalLB
「Why?」の段落を読んで私は「我が意を得たり!」と興奮しましたね。
「この仕様(パブリッククラウド前提)がオンプレ Kubernetesの民を二等国民たらしめた」的な事が書いてあって、「これに対抗するために作られた」ともあり、「そうだそうだ〜」と小躍りしたものです。
古傷のルサンチマンが喚起されて長くなってしまいましたが、ここでは MicroK8sで作った Kubernetesクラスタ環境に MetalLBを導入し、外部ノードから同クラスタで展開されているサーバーサービスに接続してみます。
2022年9月11日時点で、MetalLBの最新バージョンは 0.13.5ですが、依然として「まだ未熟なプロジェクトなので本番環境で使ってはいけない」という注意喚起があります。
残念ですが、まだお勉強用に留めておいて下さい。
MicroK8sでの MetalLBの使用の仕方は、本家の Canonicalのサイトに書かれています。
Addon: MetalLB
導入手順もありますので、素直にそれに従って導入します。
先だって作っておいた MicroK8sの 3台クラスタを起動した所からスタートです。
まずマスターノード(サブロウ家では microk8s-master)で現在の設定を見てみます。
subro@microk8s-master:~$ sudo microk8s status --wait-ready
microk8s is running
high-availability: yes
datastore master nodes: 192.168.1.120:19001 192.168.1.121:19001 192.168.1.122:19001
datastore standby nodes: none
addons:
enabled:
ha-cluster # (core) Configure high availability on the current node
disabled:
community # (core) The community addons repository
dashboard # (core) The Kubernetes dashboard
dns # (core) CoreDNS
gpu # (core) Automatic enablement of Nvidia CUDA
helm # (core) Helm 2 - the package manager for Kubernetes
helm3 # (core) Helm 3 - Kubernetes package manager
host-access # (core) Allow Pods connecting to Host services smoothly
hostpath-storage # (core) Storage class; allocates storage from host directory
ingress # (core) Ingress controller for external access
mayastor # (core) OpenEBS MayaStor
metallb # (core) Loadbalancer for your Kubernetes cluster
metrics-server # (core) K8s Metrics Server for API access to service metrics
prometheus # (core) Prometheus operator for monitoring and logging
rbac # (core) Role-Based Access Control for authorisation
registry # (core) Private image registry exposed on localhost:32000
storage # (core) Alias to hostpath-storage add-on, deprecated
MicroK8sではデフォルトインストールされていて、無効化されているだけのようですね。
自分でインストールしなくて良いとは何と楽なことか。
手順に従って [metallb]サービスを有効化します。
subro@microk8s-master:~$ sudo microk8s enable metallb
Infer repository core for addon metallb
Enabling MetalLB
Enter each IP address range delimited by comma (e.g. '10.64.140.43-10.64.140.49,192.168.0.105-192.168.0.111'): 192.168.1.120-192.168.1.122
Applying Metallb manifest
namespace/metallb-system created
secret/memberlist created
Warning: policy/v1beta1 PodSecurityPolicy is deprecated in v1.21+, unavailable in v1.25+
podsecuritypolicy.policy/controller created
podsecuritypolicy.policy/speaker created
serviceaccount/controller created
serviceaccount/speaker created
clusterrole.rbac.authorization.k8s.io/metallb-system:controller created
clusterrole.rbac.authorization.k8s.io/metallb-system:speaker created
role.rbac.authorization.k8s.io/config-watcher created
role.rbac.authorization.k8s.io/pod-lister created
clusterrolebinding.rbac.authorization.k8s.io/metallb-system:controller created
clusterrolebinding.rbac.authorization.k8s.io/metallb-system:speaker created
rolebinding.rbac.authorization.k8s.io/config-watcher created
rolebinding.rbac.authorization.k8s.io/pod-lister created
Warning: spec.template.spec.nodeSelector[beta.kubernetes.io/os]: deprecated since v1.14; use "kubernetes.io/os" instead
daemonset.apps/speaker created
deployment.apps/controller created
configmap/config created
MetalLB is enabled
途中で、MetalLBがクラスタサービスの外部公開に使って良い IPアドレスの範囲を聞かれましたので、とりあえずこのクラスタ環境を作っている 3つの OSの IPを渡しました。
2箇所非推奨(古い)機能利用のワーニングが出ていますが、これは Canonicalにお願いする所なので無視します。
もう一度状態確認をすると MetalLBが有効になっていました。
subro@microk8s-master:~$ sudo microk8s status --wait-ready
microk8s is running
high-availability: yes
datastore master nodes: 192.168.1.120:19001 192.168.1.121:19001 192.168.1.122:19001
datastore standby nodes: none
addons:
enabled:
ha-cluster # (core) Configure high availability on the current node
metallb # (core) Loadbalancer for your Kubernetes cluster
disabled:
community # (core) The community addons repository
dashboard # (core) The Kubernetes dashboard
dns # (core) CoreDNS
gpu # (core) Automatic enablement of Nvidia CUDA
helm # (core) Helm 2 - the package manager for Kubernetes
helm3 # (core) Helm 3 - Kubernetes package manager
host-access # (core) Allow Pods connecting to Host services smoothly
hostpath-storage # (core) Storage class; allocates storage from host directory
ingress # (core) Ingress controller for external access
mayastor # (core) OpenEBS MayaStor
metrics-server # (core) K8s Metrics Server for API access to service metrics
prometheus # (core) Prometheus operator for monitoring and logging
rbac # (core) Role-Based Access Control for authorisation
registry # (core) Private image registry exposed on localhost:32000
storage # (core) Alias to hostpath-storage add-on, deprecated
これで type: LoadBalancer が使えるようになったと思ったら、手順では [ingress]サービスも有効化しないとダメとありました。
先に言えよと。
ingressは Kubernetesクラスターの IPを外部公開してくれます。
ingressも有効化します。
subro@microk8s-master:~$ sudo microk8s enable ingress
Infer repository core for addon ingress
Enabling Ingress
ingressclass.networking.k8s.io/public created
namespace/ingress created
serviceaccount/nginx-ingress-microk8s-serviceaccount created
clusterrole.rbac.authorization.k8s.io/nginx-ingress-microk8s-clusterrole created
role.rbac.authorization.k8s.io/nginx-ingress-microk8s-role created
clusterrolebinding.rbac.authorization.k8s.io/nginx-ingress-microk8s created
rolebinding.rbac.authorization.k8s.io/nginx-ingress-microk8s created
configmap/nginx-load-balancer-microk8s-conf created
configmap/nginx-ingress-tcp-microk8s-conf created
configmap/nginx-ingress-udp-microk8s-conf created
daemonset.apps/nginx-ingress-microk8s-controller created
Ingress is enabled
subro@microk8s-master:~$ sudo microk8s status --wait-ready
microk8s is running
high-availability: yes
datastore master nodes: 192.168.1.120:19001 192.168.1.121:19001 192.168.1.122:19001
datastore standby nodes: none
addons:
enabled:
ha-cluster # (core) Configure high availability on the current node
ingress # (core) Ingress controller for external access
metallb # (core) Loadbalancer for your Kubernetes cluster
disabled:
community # (core) The community addons repository
dashboard # (core) The Kubernetes dashboard
dns # (core) CoreDNS
gpu # (core) Automatic enablement of Nvidia CUDA
helm # (core) Helm 2 - the package manager for Kubernetes
helm3 # (core) Helm 3 - Kubernetes package manager
host-access # (core) Allow Pods connecting to Host services smoothly
hostpath-storage # (core) Storage class; allocates storage from host directory
mayastor # (core) OpenEBS MayaStor
metrics-server # (core) K8s Metrics Server for API access to service metrics
prometheus # (core) Prometheus operator for monitoring and logging
rbac # (core) Role-Based Access Control for authorisation
registry # (core) Private image registry exposed on localhost:32000
storage # (core) Alias to hostpath-storage add-on, deprecated
有効化できました。
今度こそ良いはずです。
実験してみます。
まず NGINX x30個を以下の yamlファイルでデプロイします。
subro@microk8s-master:~$ cat nginx.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx-deployment
spec:
selector:
matchLabels:
app: nginx
replicas: 30
template:
metadata:
labels:
app: nginx
spec:
containers:
- name: nginx
image: nginx
ports:
- containerPort: 80
subro@microk8s-master:~$ sudo microk8s kubectl apply -f nginx.yaml
deployment.apps/nginx-deployment configured
PCのファンがウンウン唸り始めました。
Podが 30個出来上がるまでちょっと待ちます。
できました。
subro@microk8s-master:~$ sudo microk8s kubectl get all --all-namespaces
NAMESPACE NAME READY STATUS RESTARTS AGE
kube-system pod/calico-kube-controllers-75f94bc9d6-v85bq 1/1 Running 2 (23m ago) 2d4h
kube-system pod/calico-node-6gjm2 1/1 Running 1 (22m ago) 2d
kube-system pod/calico-node-tbfql 1/1 Running 1 (23m ago) 2d
kube-system pod/calico-node-48s54 1/1 Running 2 (22m ago) 2d
metallb-system pod/speaker-9fspt 1/1 Running 0 14m
metallb-system pod/speaker-97tpg 1/1 Running 0 14m
metallb-system pod/speaker-8vppd 1/1 Running 0 14m
metallb-system pod/controller-6dfbf9b9c6-5mvn4 1/1 Running 0 14m
default pod/nginx-deployment-6c8b449b8f-lwbsm 1/1 Running 0 99s
default pod/nginx-deployment-6c8b449b8f-fgl4j 1/1 Running 0 100s
default pod/nginx-deployment-6c8b449b8f-svqtr 1/1 Running 0 99s
default pod/nginx-deployment-6c8b449b8f-d9nqb 1/1 Running 0 99s
default pod/nginx-deployment-6c8b449b8f-5gmd5 1/1 Running 0 99s
default pod/nginx-deployment-6c8b449b8f-qdpwn 1/1 Running 0 99s
default pod/nginx-deployment-6c8b449b8f-94rxb 1/1 Running 0 99s
default pod/nginx-deployment-6c8b449b8f-t7zw6 1/1 Running 0 99s
default pod/nginx-deployment-6c8b449b8f-2hp5c 1/1 Running 0 99s
default pod/nginx-deployment-6c8b449b8f-bp88w 1/1 Running 0 100s
default pod/nginx-deployment-6c8b449b8f-k9n5s 1/1 Running 0 99s
default pod/nginx-deployment-6c8b449b8f-mdcsr 1/1 Running 0 100s
default pod/nginx-deployment-6c8b449b8f-tm8mp 1/1 Running 0 99s
default pod/nginx-deployment-6c8b449b8f-7hfd8 1/1 Running 0 99s
default pod/nginx-deployment-6c8b449b8f-sfv6w 1/1 Running 0 99s
default pod/nginx-deployment-6c8b449b8f-7bgvt 1/1 Running 0 99s
default pod/nginx-deployment-6c8b449b8f-62g5r 1/1 Running 0 99s
default pod/nginx-deployment-6c8b449b8f-dvsc5 1/1 Running 0 99s
default pod/nginx-deployment-6c8b449b8f-ps546 1/1 Running 0 99s
default pod/nginx-deployment-6c8b449b8f-znqs9 1/1 Running 0 99s
default pod/nginx-deployment-6c8b449b8f-wmtmx 1/1 Running 0 99s
default pod/nginx-deployment-6c8b449b8f-2xljx 1/1 Running 0 99s
default pod/nginx-deployment-6c8b449b8f-sz8px 1/1 Running 0 99s
default pod/nginx-deployment-6c8b449b8f-gpbls 1/1 Running 0 99s
default pod/nginx-deployment-6c8b449b8f-tqv66 1/1 Running 0 99s
default pod/nginx-deployment-6c8b449b8f-vz9sq 1/1 Running 0 99s
default pod/nginx-deployment-6c8b449b8f-vczlg 1/1 Running 0 99s
default pod/nginx-deployment-6c8b449b8f-rdjn8 1/1 Running 0 99s
default pod/nginx-deployment-6c8b449b8f-7484x 1/1 Running 0 99s
default pod/nginx-deployment-6c8b449b8f-8zx5d 1/1 Running 0 99s
NAMESPACE NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
default service/kubernetes ClusterIP 10.152.183.1 <none> 443/TCP 2d4h
NAMESPACE NAME DESIRED CURRENT READY UP-TO-DATE AVAILABLE NODE SELECTOR AGE
kube-system daemonset.apps/calico-node 3 3 3 3 3 kubernetes.io/os=linux 2d4h
metallb-system daemonset.apps/speaker 3 3 3 3 3 beta.kubernetes.io/os=linux 14m
NAMESPACE NAME READY UP-TO-DATE AVAILABLE AGE
kube-system deployment.apps/calico-kube-controllers 1/1 1 1 2d4h
metallb-system deployment.apps/controller 1/1 1 1 14m
default deployment.apps/nginx-deployment 30/30 30 30 47h
NAMESPACE NAME DESIRED CURRENT READY AGE
kube-system replicaset.apps/calico-kube-controllers-75f94bc9d6 1 1 1 2d4h
metallb-system replicaset.apps/controller-6dfbf9b9c6 1 1 1 14m
default replicaset.apps/nginx-deployment-6c8b449b8f 30 30 30 47h
この一連の NGINX群([nginx-deployment]という名前でデプロイされている)を MetalLB(と ingress)で外部公開します。
手順に載っていた yamlをウチのものに合わせてちょっと改変しました。
ピンク色の箇所が NGINXのデプロイに繋ぐところと、MetalLBを使う箇所です。
subro@microk8s-master:~$ cat ingress-service.yaml
apiVersion: v1
kind: Service
metadata:
name: ingress
namespace: ingress
spec:
selector:
name: nginx-deployment
type: LoadBalancer
# loadBalancerIP is optional. MetalLB will automatically allocate an IP
# from its pool if not specified. You can also specify one manually.
# loadBalancerIP: x.y.z.a
ports:
- name: http
protocol: TCP
port: 80
targetPort: 80
type: LoadBalancer の行は、以前 MetalLBが無い頃にやった際にサービス状態が [Pending] のまま何も進まなかったのです…。
では、満を持してサービスを開始します。
subro@microk8s-master:~$ sudo microk8s kubectl apply -f ingress-service.yaml
service/ingress created
以前も create はされたんですよね。
ちゃんと動いているんでしょうか。
subro@microk8s-master:~$ sudo microk8s kubectl get all --all-namespaces
NAMESPACE NAME READY STATUS RESTARTS AGE
kube-system pod/calico-kube-controllers-75f94bc9d6-v85bq 1/1 Running 2 (53m ago) 2d5h
kube-system pod/calico-node-6gjm2 1/1 Running 1 (53m ago) 2d
kube-system pod/calico-node-tbfql 1/1 Running 1 (53m ago) 2d
kube-system pod/calico-node-48s54 1/1 Running 2 (53m ago) 2d
default pod/nginx-deployment-6c8b449b8f-lwbsm 1/1 Running 0 32m
default pod/nginx-deployment-6c8b449b8f-fgl4j 1/1 Running 0 32m
default pod/nginx-deployment-6c8b449b8f-svqtr 1/1 Running 0 32m
default pod/nginx-deployment-6c8b449b8f-d9nqb 1/1 Running 0 32m
default pod/nginx-deployment-6c8b449b8f-5gmd5 1/1 Running 0 32m
default pod/nginx-deployment-6c8b449b8f-qdpwn 1/1 Running 0 32m
default pod/nginx-deployment-6c8b449b8f-94rxb 1/1 Running 0 32m
default pod/nginx-deployment-6c8b449b8f-t7zw6 1/1 Running 0 32m
default pod/nginx-deployment-6c8b449b8f-2hp5c 1/1 Running 0 32m
default pod/nginx-deployment-6c8b449b8f-bp88w 1/1 Running 0 32m
default pod/nginx-deployment-6c8b449b8f-k9n5s 1/1 Running 0 32m
default pod/nginx-deployment-6c8b449b8f-mdcsr 1/1 Running 0 32m
default pod/nginx-deployment-6c8b449b8f-tm8mp 1/1 Running 0 32m
default pod/nginx-deployment-6c8b449b8f-7hfd8 1/1 Running 0 32m
default pod/nginx-deployment-6c8b449b8f-sfv6w 1/1 Running 0 32m
default pod/nginx-deployment-6c8b449b8f-7bgvt 1/1 Running 0 32m
default pod/nginx-deployment-6c8b449b8f-62g5r 1/1 Running 0 32m
default pod/nginx-deployment-6c8b449b8f-dvsc5 1/1 Running 0 32m
default pod/nginx-deployment-6c8b449b8f-ps546 1/1 Running 0 32m
default pod/nginx-deployment-6c8b449b8f-znqs9 1/1 Running 0 32m
default pod/nginx-deployment-6c8b449b8f-wmtmx 1/1 Running 0 32m
default pod/nginx-deployment-6c8b449b8f-2xljx 1/1 Running 0 32m
default pod/nginx-deployment-6c8b449b8f-sz8px 1/1 Running 0 32m
default pod/nginx-deployment-6c8b449b8f-gpbls 1/1 Running 0 32m
default pod/nginx-deployment-6c8b449b8f-tqv66 1/1 Running 0 32m
default pod/nginx-deployment-6c8b449b8f-vz9sq 1/1 Running 0 32m
default pod/nginx-deployment-6c8b449b8f-vczlg 1/1 Running 0 32m
default pod/nginx-deployment-6c8b449b8f-rdjn8 1/1 Running 0 32m
default pod/nginx-deployment-6c8b449b8f-7484x 1/1 Running 0 32m
default pod/nginx-deployment-6c8b449b8f-8zx5d 1/1 Running 0 32m
ingress pod/nginx-ingress-microk8s-controller-hph6l 1/1 Running 0 22m
ingress pod/nginx-ingress-microk8s-controller-f9h6f 1/1 Running 0 22m
ingress pod/nginx-ingress-microk8s-controller-dxcc6 1/1 Running 0 22m
metallb-system pod/speaker-85hh9 1/1 Running 0 2m5s
metallb-system pod/speaker-r2m85 1/1 Running 0 2m5s
metallb-system pod/speaker-tnwp6 1/1 Running 0 2m5s
metallb-system pod/controller-6dfbf9b9c6-zx2fc 1/1 Running 0 2m5s
NAMESPACE NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
default service/kubernetes ClusterIP 10.152.183.1 <none> 443/TCP 2d5h
ingress service/ingress LoadBalancer 10.152.183.12 192.168.1.120 80:30745/TCP 9s
NAMESPACE NAME DESIRED CURRENT READY UP-TO-DATE AVAILABLE NODE SELECTOR AGE
kube-system daemonset.apps/calico-node 3 3 3 3 3 kubernetes.io/os=linux 2d5h
ingress daemonset.apps/nginx-ingress-microk8s-controller 3 3 3 3 3 <none> 22m
metallb-system daemonset.apps/speaker 3 3 3 3 3 beta.kubernetes.io/os=linux 2m5s
NAMESPACE NAME READY UP-TO-DATE AVAILABLE AGE
kube-system deployment.apps/calico-kube-controllers 1/1 1 1 2d5h
default deployment.apps/nginx-deployment 30/30 30 30 2d
metallb-system deployment.apps/controller 1/1 1 1 2m5s
NAMESPACE NAME DESIRED CURRENT READY AGE
kube-system replicaset.apps/calico-kube-controllers-75f94bc9d6 1 1 1 2d5h
default replicaset.apps/nginx-deployment-6c8b449b8f 30 30 30 2d
metallb-system replicaset.apps/controller-6dfbf9b9c6 1 1 1 2m5s
見た目は動いているようですが…
外部IPは 192.168.1.120 の模様。
ここの 80/tcp にアクセスすると 30個ある NGINXの Podのどれかまで繋いでくれるはずです。
どうせならと、VMware Workstation Player のホストOSである Windows10の Edgeでチャレンジです。
「やったよママ! NGINXが 404を返してくれた!\(^o^)/」
どうも引っ張ってきた NGINXのコンテナイメージは index.htmlが無いようです。
404てのがちょっとアレですが、NGINXが返してきたのは確かで。
特に苦労もなく、サービスの設定で type: LoadBalancer を使えるようになってしまいました。
素晴らしい。
パブリッククラウドの Kubernetesのサービスを使うに、ここまでの環境構築のスキルは一切必要ないのだと思います。
ですが、あのお高いクラウド課金をかけずに、Kubernetes環境にアプリを展開するのはどういう事かを味わうには、これが必要です。
とは言っても、MicroK8sを使ったところ簡単にできてしまいましたので、実際に環境を作ってみると良いと思います。
慣れれば 2時間もあれば、OSインストールからここまで作れるんじゃないでしょうか。
ここでは 3台のクラスタを作っていますが、MetalLBの使用には 1台のクラスタでも問題ないはずですので、メモリが 8GBの中古ノートPCでやれるでしょう。
パブリッククラウド各社のサービスでは、ベースは同じ Kubernetesであっても、提供されている UIはそれぞれ違うはずです。
応用を利かせるには素の Kubernetesをイジっておくのがお勧めなので、これが自宅にあるとお勉強が捗るなぁ、というのが素直な感想でした。
![]() | 現場で使えるkubernetes [ 牧田剣吾/松浦崇仁 ] 価格:4,202円 |
![](https://www12.a8.net/0.gif?a8mat=3NAB73+1DF0RE+2HOM+BWGDT)
![]() | Kubernetes CI/CDパイプラインの実装 (impress top gear impress top gear) [ 北山晋吾 ] 価格:3,960円 |
![](https://www17.a8.net/0.gif?a8mat=3NAB73+1DF0RE+2HOM+BWGDT)