この投稿はFUJITSU その2 Advent Calendar 2018の22日目の記事です。
(注意)この記事は個人の見解であり、所属する会社、組織を代表するものではありません。
諸事情により投稿が遅くなりました。ごめんなさい。
GitLab Serverlessとは
12月22日にリリースされたばかりのGitLab 11.6の新機能です。
GitLab Serverlessを利用することで、KnativeをインストールしたKubernetes上にGitLab CI経由でサーバレスアプリケーションをデプロイすることができます。
また、サーバレスアプリケーションの管理ツールであるTriggerMeshを利用することでサーバレスアプリケーションデプロイ後の管理もGitLab上から行えるようになっています。
今回はいち早くGitLab Serverlessを利用して実際にアプリケーションをデプロイするところまでやってみたいと思います。
...が、先に言ってしまうと結果としてはCI実行中にエラーが発生し、アプリケーションを実行するまでには至りませんでした。
時間切れとなってしまったので、今後解決でき次第更新したいと思います。
事前準備
GitLab環境構築
Cloud Native GitLab Helm Chartを使ってKubernetesクラスタ上にデプロイしたGitLabで検証しています。
GitLabのk8s連携機能を利用するにあたりGitLab自体をk8sクラスタ上で実行する必要は特にありません。
が、今回はk8s上ですべて完結させてみたかったので上記helmチャートを利用しました。
構築方法は主題ではないので引っかかった部分だけ簡単に説明すると、
今回利用したバージョン1.4.0
のhelmチャートが依存しているgitlab-runner
helmチャートのバージョン0.1.38
では
以下の問題が発生したので、公式ドキュメントの方法にいくつか設定を追加しています。
-
gitlab-runner
のPodがCrashLoopBackOff
を繰り返し立ち上がらない- helmチャートから生成されるmanifestにgitlab-runnerのlock有無を指定する環境変数の値が指定されないことが原因です。
-
helm upgradle --install
時に明示的に--set gitlab-runner.runners.locked=false
を指定することで解決します。
- CI実行時に
a DNS-1123 subdomain must consist of lower case alphanumeric characters...
というエラーが発生し失敗する- CI JobをPodとして実行できるrunnerの実行方式である
kubernetes executor
に問題があり、CI Job実行時に起動するPod名がk8sの命名規則に準拠していないため、GitLabとの通信時のDNS参照に失敗します。 -
gitlab-runner
helmチャートのバージョン0.1.38
で起動するgitlab-runner:alpine-v11.5.0
コンテナイメージに固有の問題のようなので、helm upgradle --install
時に明示的に--set gitlab-runner.image=gitlab/gitlab-runner:alpine-v11.5.1
以上を指定することで解決します。
- CI JobをPodとして実行できるrunnerの実行方式である
これ以降の内容はk8s上でGitLabを実行し、GitLabのk8s連携を有効にしている前提とします。
Knativeをk8sにデプロイする
KnativeはKubernetesのオペレーションやコンテナイメージビルド、デプロイの複雑さを低減し、開発者がコードを書くこと自体により集中できるようにしつつ、コンテナの恩恵を受けたサービス構築を実現するツールです。
また、冒頭にサーバレスアプリケーションをデプロイできるといったとおり、通常Kubernetesではできない、普段Podが0の状態で、トリガーとなるイベント発生時に初めてPodを起動するといったワークロードが実現できます。
Knativeは以下のコンポーネントで構成されています。
- Build: ソースコードからコンテナイメージをビルド、レジストリへプッシュの一連の作業を実行
- Eventing: サポートするSubscribe先からのメッセージを受け取る
- Serving: アプリケーションをデプロイ、公開し、デフォルトではPodが0の状態からリクエストを受けPodのスケーリングを行います。また、サービスメッシュであるIstioによりルーティングを制御します。
GitLab Serverlessを利用するため事前にKubernetesへデプロイしておく必要がありますが、GitLabではKnativeのインストールもGitLabのWeb UI経由で実行できてしまいます。
helm-tillerのデプロイ
GitLab経由でKnativeをデプロイするにあたり、まずはGitLab経由でhelmをインストールする必要があります。
k8sを有効にしたプロジェクトのOperations > Kubernetes Clusters > 連携済みKubernetesクラスタ名
の画面からHelm Tillerのinstall
を実行します。
しばらくすると表示がinstalled
となります。
ここでk8sのPodを確認すると、gitlab-managed-apps
にtiller podがデプロイされていることがわかります。
$ kubectl get pod -n gitlab-managed-apps
NAME READY STATUS RESTARTS AGE
tiller-deploy-74f5d65d77-k5pzn 1/1 Running 0 5m
knativeデプロイ
helmインストール時と同じ画面からKnativeをデプロイします。
この際、サーバレスアプリケーションを公開するドメイン名を指定する必要があります。
しばらくすると、表示がinstalled
となり、Knative IP Address
欄が追加されます。
ここに表示されているIPアドレスを指定したドメインのワイルドカードDNS Aレコードとして登録しておきます。
このIPアドレスはアプリケーションへのルーティングを担うknative-ingressgateway
コンポーネントのEXTERNAL-IPであり、以下のコマンドでも取得できます。
$ kubectl get svc --namespace=istio-system knative-ingressgateway -o jsonpath='{.status.loadBalancer.ingress[0].ip} '
35.243.127.45
ここでk8sクラスタの状態を確認します。
まず、Istioがデプロイされていることが確認できます。
$ kubectl get pod -n istio-system
NAME READY STATUS RESTARTS AGE
istio-citadel-84fb7985bf-c6vfg 1/1 Running 0 15m
istio-egressgateway-bd9fb967d-mvblb 1/1 Running 0 15m
istio-galley-655c4f9ccd-h5mhx 1/1 Running 0 15m
istio-ingressgateway-688865c5f7-jcqpp 1/1 Running 0 15m
istio-pilot-6cd69dc444-bb77k 2/2 Running 0 15m
istio-policy-6b9f4697d-nbtmz 2/2 Running 0 15m
istio-sidecar-injector-8975849b4-jt8d2 1/1 Running 0 15m
istio-statsd-prom-bridge-7f44bb5ddb-mqqq2 1/1 Running 0 15m
istio-telemetry-6b5579595f-pxrf9 2/2 Running 0 15m
knative-ingressgateway-5f5dc4b4cd-xw2qg 1/1 Running 0 15m
さらに、Knativeのコンポーネントであるknative-build
、knative-serving
がそれぞれ別のネームスペースにデプロイされています。
$ kubectl get pod -n knative-build
NAME READY STATUS RESTARTS AGE
build-controller-65f855ccd6-dgg87 1/1 Running 0 14m
build-webhook-864d45f66f-hdtcs 1/1 Running 0 14m
$ kubectl get pod -n knative-serving
NAME READY STATUS RESTARTS AGE
activator-847cf57479-6tzmk 2/2 Running 0 15m
controller-5d7f46bfd6-rbqrf 1/1 Running 0 15m
webhook-7f8ddf4499-hgv49 1/1 Running 0 15m
ここまでで事前準備は完了です。
実際にアプリケーションをデプロイしていきます。
サーバレスアプリケーションのデプロイ
GitLab Serverlessで利用可能なランタイム
現在はnode.js
またはkaniko
がサポートされているようです。
今回はnode.jsアプリケーションを試します。
.gitlab-ci.yml
の作成
以下の内容の.gitlab-ci.ymlをプロジェクトのリポジトリに追加します。
TriggerMeshのCLIであるtm
コマンドを実行し、Knativeの機能を利用してコンテナイメージビルド〜デプロイまでを実行するJobを定義しています。
stages:
- deploy
functions:
stage: deploy
environment: test
image: gcr.io/triggermesh/tm:v0.0.7
script:
- tm -n "$KUBE_NAMESPACE" set registry-auth gitlab-registry --registry "$CI_REGISTRY" --username "$CI_REGISTRY_USER" --password "$CI_JOB_TOKEN"
- tm -n "$KUBE_NAMESPACE" --registry-host "$CI_REGISTRY_IMAGE" deploy --wait
serverless.yaml
の作成
GitLab Serverlessでは下記ファイルでKnativeでアプリケーションをデプロイする際のメタ情報を定義するようです。
このあたりがGitLab CI/CDと統合された、ピュアKnativeとは異なるところでしょうか。
アプリケーションのサービス名やビルドするソースコードを格納するディレクトリ、アプリケーションのランタイムなどを定義します。
service: knative-test
description: "Deploying functions from GitLab using Knative"
provider:
name: triggermesh
registry-secret: gitlab-registry
environment:
FOO: BAR
functions:
echo:
handler: echo
runtime: https://gitlab.com/triggermesh/runtimes/raw/master/nodejs.yaml
description: "echo function using node.js runtime"
buildargs:
- DIRECTORY=echo
environment:
FUNCTION: echo
アプリケーションコードをリポジトリに格納
TriggerMeshのサンプルコードのうち、node.jsのサンプルコードをserverless.yaml
のbuildargs
に定義したソース格納先であるecho
ディレクトリ配下に格納します。
リポジトリにPushしCIを実行
リポジトリにソースコード及びserverless.yaml
、.gitlab-ci.yml
をPushすることでCIが実行され、Knativeによりアプリケーションのコンテナイメージビルド〜デプロイ、公開までが実行されます。
...のはずでしたが、どうやらGitLabのコンテナレジストリへのコンテナイメージPush時に認証エラーとなっており、CIに失敗してしまいました。
以下はCI Jobのログです。
Running with gitlab-runner 11.5.1 (7f00c780)
on gitlab-gitlab-runner-5c7d4bfbdf-bvqbj EnNm5sja
Using Kubernetes namespace: default
Using Kubernetes executor with image gcr.io/triggermesh/tm:v0.0.7 ...
Waiting for pod default/runner-ennm5sja-project-1-concurrent-08fk4p to be running, status is Pending
Waiting for pod default/runner-ennm5sja-project-1-concurrent-08fk4p to be running, status is Pending
Waiting for pod default/runner-ennm5sja-project-1-concurrent-08fk4p to be running, status is Pending
Waiting for pod default/runner-ennm5sja-project-1-concurrent-08fk4p to be running, status is Pending
Waiting for pod default/runner-ennm5sja-project-1-concurrent-08fk4p to be running, status is Pending
Waiting for pod default/runner-ennm5sja-project-1-concurrent-08fk4p to be running, status is Pending
Running on runner-ennm5sja-project-1-concurrent-08fk4p via gitlab-gitlab-runner-5c7d4bfbdf-bvqbj...
Cloning repository...
Cloning into '/k-srkw/serverless-test'...
Checking out 6a038601 as master...
Skipping Git submodules setup
$ tm -n "$KUBE_NAMESPACE" set registry-auth gitlab-registry --registry "$CI_REGISTRY" --username "$CI_REGISTRY_USER" --password "$CI_JOB_TOKEN"
Registry credentials set
$ tm -n "$KUBE_NAMESPACE" --registry-host "$CI_REGISTRY_IMAGE" deploy --wait
Creating knative-test-echo function
Deployment started. Run "tm -n serverless-test-1 describe service knative-test-echo" to see the details
Waiting for ready state....2018/12/23 18:32:09 Revision "knative-test-echo-00001" failed with message: "no token in bearer response:\n{\"errors\":[{\"code\":\"DENIED\",\"message\":\"access forbidden\"}],\"http_status\":403}".
ERROR: Job failed: command terminated with exit code 1
実際にアプリケーションがデプロイされるとプロジェクトのWeb UI上のOperations > Serverlessからfunction名やURLが確認できるのですが、その登録自体は行われていました。
ただし、アプリケーションはデプロイできていないため、アクセスはできませんでした。
今回はここまで。
上記問題が解決できたら更新したいと思います。