いしぐめも

プログラミングとかしたことを書きます。

Kubernetes in Docker (KinD) で OpenFaaS を動かす!

OpenFaaS が気になる、でもそのために Kubernetes 動かすのもなぁ…

そんなときに、サクッと Kubernetes をコンテナ上で動かせる Kubernetes in Docker (KinD) を使えば、簡単に OpenFaaS オタメシ環境が構築できます!

はじめに

Kubernetes in Docker (KinD) 、Dockerコンテナをノードとしてふるまわせ、従来通り kubectl などでコントロールできるすごいやつです。形容詞kindと同じつづりなのでググらびりてぃが恐ろしく低いですが、「Kubernetes in Docker」で調べると情報が出てきます。

ノードの数だけDockerコンテナが立ち上がり、それらを消してしまえばまた環境をまっさらにできるので、まさに Kubernetes オタメシにはもってこいの環境です。主に Kubernetes 自体の開発用途で使われているんだとか。

今回はその簡単に作ったり壊したりできる Kubernetes 環境を使って、 OpenFaaS を使えるようにしてみたいと思います。

手順

では早速

用意するもの

  • Dockerが使えるマシン(筆者の環境は Ubuntu 18.04 x86_64 16GBメモリ)
    • sudo なしでDockerが扱えるように、作業するユーザーを docker グループに入れて下さい

1. KinD の導入

まずは Go を導入します。下記サイトに従って導入しました。

Download and install - The Go Programming Language

wget https://golang.org/dl/go1.16.4.linux-amd64.tar.gz
sudo rm -rf /usr/local/go && sudo tar -C /usr/local -xzf go1.16.4.linux-amd64.tar.gz

そして下記を ~/.profile に追記。

export PATH=$PATH:/usr/local/go/bin
export PATH=$PATH:$(go env GOPATH)/bin

いったんログアウトしてからログインし、go version などでgoが導入できたことを確認。

次に、KinD 本体を導入します。公式ドキュメント にあるように 下記コマンドで導入できます。

GO111MODULE="on" go get sigs.k8s.io/kind@v0.10.0

2. KinD の動作確認

KinD を使った Kubernetesクラスタ起動は下記コマンドで行えます。

kind create cluster

クラスタ削除は下記

kind delete cluster

簡単です。

3. ローカルレジストリの作成

FaaS のハンドラ(Pod)は指定したDockerのレジストリからコンテナイメージがpullされ実行されます。

オタメシで使うようなコンテナイメージを Docker Hub に上げるわけにもいかないので、ローカルにレジストリをDockerでたちあげ、それを参照するように設定します。

下記URLを参考にシェルスクリプトを作成し、クラスタを立ち上げる時はそのシェルスクリプトを実行するようにしました。

#!/bin/sh
set -o errexit

reg_name='kind-registry'
reg_port='5000'
running="$(docker inspect -f '{{.State.Running}}' "${reg_name}" 2> /dev/null || true)"

if [ "${running}" != 'true' ]; then
  docker run \
    -d --restart=always -p "${reg_port}:5000" --name "${reg_name}" \
    registry:2
fi

cat <<EOF | NO_PROXY=${NO_PROXY},${reg_name} kind create cluster --config=-
kind: Cluster
apiVersion: kind.x-k8s.io/v1alpha4
containerdConfigPatches:
- |-
  [plugins."io.containerd.grpc.v1.cri".registry.mirrors."localhost:${reg_port}"]
    endpoint = ["http://${reg_name}:${reg_port}"]
EOF

docker network connect "kind" "${reg_name}" || true

cat <<EOF | kubectl apply -f -
apiVersion: v1
kind: ConfigMap
metadata:
  name: local-registry-hosting
  namespace: kube-public
data:
  localRegistryHosting.v1: |
    host: "localhost:${reg_port}"
    help: "https://kind.sigs.k8s.io/docs/user/local-registry/"
EOF

ここで、kind create cluster を実行するときに NO_PROXY=${NO_PROXY},${reg_name} として、NO_PROXY環境変数を設定しました。下記URLにあるように、KinDはクラスタ立ち上げ時の環境変数を見て、ノード内のポッドが通信できるように渡してくれるんですが、今回立てたレジストリはプロキシを通してしまうとコンテナイメージをプルできなくなるので、明示する必要があります。(プロキシを使用していない環境であれば必要ありません。)

https://kind.sigs.k8s.io/docs/user/quick-start/#configure-kind-to-use-a-proxy

4. openfaasをインストールする

下記手順に従ってopenfaasを導入していきます。

Kubernetes - OpenFaaS

まずはopenfaas の管理ツールである faas-cli を導入します。

curl -sL https://cli.openfaas.com | sudo sh

次に、3.で作成したシェルスクリプトを実行して立ち上げたクラスタに対して、arkade を使用して openfaas を導入します。

arkade とは、Kubernetes で利用できるサービスを導入できるマーケットプレイスアプリらしいです。

github.com

下記コマンドで arkade を導入して、、、

curl -SLsf https://dl.get-arkade.dev/ | sudo sh

kubernetes に openfaas を導入します。

arkade install openfaas

5. openfaas に外からアクセスできるようにする

ここまででは openfaas にアクセスできないので管理用のWebアプリ「gateway」にアクセスできるようにポートフォワーディングを設定します。

kubectl rollout status -n openfaas deploy/gateway
kubectl port-forward -n openfaas svc/gateway 8080:8080 --address 0.0.0.0 &

こうすることで、Dockerのノード内で実行されている gateway にアクセスすることができるようになります。

--address 0.0.0.0 を指定しているのは、リモートホストからアクセスできるようにしたかったためです。(省略すれば localhost からのみアクセス可能になります)

上記を実行した後に 「<IPアドレス>:8080」にアクセスすると下記のように管理画面が開けばOKです

f:id:yoh1496:20210517175605p:plain
OpenFaaS管理画面

f:id:yoh1496:20210517175701p:plain
ストアから試したいFunctionを追加することもできる

f:id:yoh1496:20210517175856p:plain
実行結果

6. 自作Functionをデプロイしてみる

Local Registry with KinD - OpenFaaS

コチラにある内容を試せば自作Functionがデプロイできることを試せます。

筆者はプロキシ必須の環境で試したので、めちゃくちゃハマったんですが、この PyDictionary を使ったサンプル、通信が伴うのでまず pydict/handler.py

from PyDictionary import PyDictionary
dictionary = PyDictionary()

def handle(word):
    return word
    # return dictionary.meaning(word)

といった感じで通信を行わない、オウム返しのFunctionで試すのがよいと思います。

また、Function実行時の環境変数を指定したい場合は

version: 1.0
provider:
  name: openfaas
  gateway: http://127.0.0.1:8080
functions:
  pydict:
    lang: python3-flask-debian
    handler: ./pydict
    image: localhost:5000/pydict:latest
    environment:
      http_proxy: http://proxy.host.example:8080/
      https_proxy: http://proxy.host.example:8080/
      no_proxy: localhost,127.0.0.1

といった感じで、 pydict.yml ファイルに environment を書けばよいでしょう。(要調査)

f:id:yoh1496:20210517181236p:plain
pydict 実行結果

参考

色々ドハマりしたときに役立ったコマンドなど

デプロイした Functionがいつまでたっても Not Ready のまま

いつまでたってもReadyにならない。デプロイしたFunctionがどこでコケているのか、ログを見ましょう。

kubectl logs -n openfaas-fn deploy/pydict

ノードからローカルのレジストリにアクセスできているか確認したい

正しく環境変数など設定できているか確認するために、Kubernetesのノードが動いているDockerコンテナに入り込んでしまって、 curl kind-registry:5000 とか叩いてしまうのも手です。

docker exec -it kind-control-plane bash

終わりに

以上、OpenFaaS を Kubernetes in Docker で試してみる、といった内容でした。 (本当は faasd でやりたかったんだけど、プロキシでドハマりして情報が少なすぎて断念した)

自分の作ったスクリプトAPI化して置いておくなど、イイ感じの活用を考えたいところです。