Cloud FoundryをKubernetes上にインストールするcf-for-k8s (CF4K8s)の0.1.0がリリースされたので試してみます。 今回はKindをLaptopにインストールし、その上にCloud Foundryをインストールします。
CFをk8s上にデプロイするプロジェクトとしてはKubeCFもありますが、
KubeCFは既存のCFのコンポーネントをBOSHの概念と共にKubenetesに移植したプロジェクトです。既存のCF利用者からすると、短期的にはKubeCFの方が移行しやすいかもしれません。
一方、cf-for-k8sは、CFのコンポーネントをKubernetesの世界に合わせて置き換えたり(Envoy, Istio, Fluentd, Kpackなど)、書き換えたりしています。
既存CF利用者視点での互換性はKubeCFに比べて低いですが、将来的に見るとcf-for-k8sのアプローチの方が理にかなっているように思えます。なお、KubeCFはHelmでインストールし、cf-for-k8sはkappでインストールします。
cf-for-k8sはVMware Tanzu Application Service for Kubernetes (TAS for k8s)のベースとなっています。
ちなみに、ざっくりと、これまでのCloud Foundry (for BOSH)とCloud Foundry for k8sのコンポーネントの違いは次の表のようになります。
機能 | Cloud Foundry for BOSH | Cloud Foundry for k8s |
---|---|---|
Routing、Load Balancing | Go Router | Istio/Envoy |
API | Cloud Controller | Cloud Controller |
コンテナ管理 | Diego | Kubernetes |
コンテナイメージビルド | Cloud Foundry Buildpack | Cloud Native Buildpack |
Identity管理 | UAA | UAA |
ロギング | Loggregator | Fluentd (Log Cacheは残る) |
インフラライフサイクル管理 | BOSH | Kubernetes |
本記事の内容は基本的に次のドキュメントの通りです。
https://github.com/cloudfoundry/cf-for-k8s/blob/master/docs/deploy-local.md
目次
- CLIのインストール
- cf-for-k8sマニフェストの取得
- Kubernetesクラスターの作成
- Cloud Foundryのインストール
- Cloud Foundryにログイン
- Org、Spaceの作成
- Javaアプリケーションのデプロイ
- Smoke Testの実行
- Cloud Foundryのアンインストール
CLIのインストール
kubectl
kind
kapp
(cf-for-k8sのデプロイに使用します)ytt
(yamlのpatchを適用するために使用します)bosh
(yaml内のパスワードとTLS証明書を自動生成するために使用します)cf
をインストールします。
brew install kubectl
brew install kind
brew install k14s/tap/kapp
brew install k14s/tap/ytt
brew install cloudfoundry/tap/bosh-cli
brew install cloudfoundry/tap/cf-cli
動作確認したバージョンは
$ kind --version
kind version 0.7.0
$ kubectl version --client=true
Client Version: version.Info{Major:"1", Minor:"17", GitVersion:"v1.17.3", GitCommit:"06ad960bfd03b39c8310aaf92d1e7c12ce618213", GitTreeState:"clean", BuildDate:"2020-02-13T18:08:14Z", GoVersion:"go1.13.8", Compiler:"gc", Platform:"darwin/amd64"}
$ kapp version
kapp version 0.24.
$ ytt version
ytt version 0.27.1
$ bosh -v
version 6.2.1-a28042ac-2020-02-10T18:41:00Z
$ cf -v
cf version 6.51.0+2acd15650.2020-04-07
です。
cf-for-k8sマニフェストの取得
0.1.0
を使用します。
git clone https://github.com/cloudfoundry/cf-for-k8s.git -b v0.1.0
Kubernetesクラスターの作成
cf-for-k8sで使用するKubernetesをKindで作成します。Kind用のconfigはcf-for-k8s/deploy/kind/cluster.yml
に用意されています。
kind create cluster --config=./cf-for-k8s/deploy/kind/cluster.yml
KindではLoadBalancer
typeのService
を作成できないため、hostの443
ポートをKind内の31443
ポートに、hostの80
ポートを31080
ポートにマッピングするように設定し、
cf-for-k8sがLoadBalancer
の代わりにNodePort
を使用しても、ホストから443
or 80
ポートでアクセスできるようにしています。
クラスタが作成されたらkubectl
で動作確認します。
$ kubectl cluster-info
Kubernetes master is running at https://127.0.0.1:32769
KubeDNS is running at https://127.0.0.1:32769/api/v1/namespaces/kube-system/services/kube-dns:dns/proxy
$ kubectl get node
NAME STATUS ROLES AGE VERSION
kind-control-plane Ready master 10m v1.17.0
$ kubectl get pod -A
NAMESPACE NAME READY STATUS RESTARTS AGE
kube-system coredns-6955765f44-n4qzd 1/1 Running 0 3m42s
kube-system coredns-6955765f44-thqj8 1/1 Running 0 3m42s
kube-system etcd-kind-control-plane 1/1 Running 0 3m57s
kube-system kindnet-s9l7m 1/1 Running 0 3m42s
kube-system kube-apiserver-kind-control-plane 1/1 Running 0 3m57s
kube-system kube-controller-manager-kind-control-plane 1/1 Running 0 3m57s
kube-system kube-proxy-jfbm8 1/1 Running 0 3m42s
kube-system kube-scheduler-kind-control-plane 1/1 Running 0 3m57s
local-path-storage local-path-provisioner-7745554f7f-vnwh9 1/1 Running 0 3m42s
KindにはMetrics Serverが含まれておらず、これがないとcf push
でエラーが発生するので、Metrics Serverを別途インストールしておきます。
kubectl apply -f https://github.com/kubernetes-sigs/metrics-server/releases/download/v0.3.6/components.yaml
Cloud Foundryのインストール
いよいよk8s上にCloud Foundryをインストールを行います。
まずは、ソースコードをcf push
した際にCloud Native Buildpackで作成されるDockerイメージをデプロイするDockerレジストリのアカウント情報を設定します。
ここではDockerHubを使用します。
また、パスワードや証明書を自動生成して./cf-for-k8s/hack/generate-values.sh
を実行して設定値を作成します。
CFのドメインにはlocal.maki.lol
を使用します。
*.local.maki.lol
及び*.apps.local.maki.lol
、*.sys.local.maki.lol
はAレコードで127.0.0.1
を返すように登録s亭あります。誰でも利用可能です。
export DOCKERHUB_USERNAME=.......
export DOCKERHUB_PASSWORD=....
./cf-for-k8s/hack/generate-values.sh -d local.maki.lol > /tmp/cf-values.yml
cat <<EOF >> /tmp/cf-values.yml
app_registry:
hostname: https://index.docker.io/v1/
repository: ${DOCKERHUB_USERNAME}
username: ${DOCKERHUB_USERNAME}
password: ${DOCKERHUB_PASSWORD}
EOF
設定ファイルは/tmp/cf-value.yml
に出力されます。kapp
及びytt
を使用して次のコマンドでデプロイします。
kapp deploy -a cf \
-f <(ytt -f ./cf-for-k8s/config \
-f /tmp/cf-values.yml \
-f ./cf-for-k8s/config-optional/remove-resource-requirements.yml \
-f ./cf-for-k8s/config-optional/use-nodeport-for-ingress.yml)
ベースのマニフェストファイルはcf-for-k8s/config
に含まれます。これに対して、次の差分ファイルをytt
で適用しています。
cf-for-k8s/config-optional/remove-resource-requirements.yml
... Kindでもデプロイできるようにリソース(CPU、メモリ)の下限の制約を除外するcf-for-k8s/config-optional/use-nodeport-for-ingress.yml
... IstionのIngress GatewayにNodePort
を使用する
y
を入力してインストールを開始します。次のようなログが流れてインストールが成功します。
9:02:17PM: ---- applying 36 changes [0/245 done] ----
9:02:17PM: create customresourcedefinition/builds.build.pivotal.io (apiextensions.k8s.io/v1beta1) cluster
9:02:17PM: create customresourcedefinition/builders.build.pivotal.io (apiextensions.k8s.io/v1beta1) cluster
9:02:17PM: create customresourcedefinition/clusterbuilders.build.pivotal.io (apiextensions.k8s.io/v1beta1) cluster
9:02:17PM: create customresourcedefinition/custombuilders.experimental.kpack.pivotal.io (apiextensions.k8s.io/v1beta1) cluster
9:02:17PM: create customresourcedefinition/customclusterbuilders.experimental.kpack.pivotal.io (apiextensions.k8s.io/v1beta1) cluster
...(略)...
9:07:43PM: ^ Condition Ready is not True (False)
9:07:44PM: ok: reconcile deployment/cf-blobstore-minio (apps/v1) namespace: cf-blobstore
9:07:44PM: ---- waiting on 1 changes [244/245 done] ----
9:07:47PM: ongoing: reconcile deployment/capi-api-server (apps/v1) namespace: cf-system
9:07:47PM: ^ Waiting for 1 unavailable replicas
9:07:47PM: L ok: waiting on replicaset/capi-api-server-bd668b897 (apps/v1) namespace: cf-system
9:07:47PM: L ok: waiting on pod/capi-api-server-bd668b897-cprlv (v1) namespace: cf-system
9:07:47PM: L ongoing: waiting on pod/capi-api-server-bd668b897-7drpp (v1) namespace: cf-system
9:07:47PM: ^ Condition Ready is not True (False)
9:07:57PM: ok: reconcile deployment/capi-api-server (apps/v1) namespace: cf-system
9:07:57PM: ---- applying complete [245/245 done] ----
9:07:57PM: ---- waiting complete [245/245 done] ----
Succeeded
インストール後のPod
一覧は次の通りです。
$ kubectl get pod -A
NAMESPACE NAME READY STATUS RESTARTS AGE
cf-blobstore cf-blobstore-minio-6745578955-nz8bf 2/2 Running 0 4m43s
cf-db cf-db-postgresql-0 2/2 Running 0 4m53s
cf-system capi-api-server-bd668b897-7drpp 5/5 Running 2 4m45s
cf-system capi-api-server-bd668b897-cprlv 5/5 Running 3 4m45s
cf-system capi-clock-76d55f5dc9-kqjnk 2/2 Running 1 4m55s
cf-system capi-deployment-updater-6b8bddb85b-m2fds 2/2 Running 1 4m53s
cf-system capi-kpack-watcher-598bf58c77-gbjfb 2/2 Running 0 4m54s
cf-system capi-worker-8bc56859d-jtdlw 2/2 Running 1 4m53s
cf-system cfroutesync-785c568d7b-krrvn 2/2 Running 0 4m43s
cf-system eirini-7d5b6f65cb-ndjwf 2/2 Running 0 4m44s
cf-system fluentd-d2zlm 2/2 Running 0 4m54s
cf-system log-cache-9cb8b6bd9-5fzb9 5/5 Running 2 4m44s
cf-system metric-proxy-6db4567cf9-jmcmh 2/2 Running 0 4m43s
cf-system uaa-79bdb97476-xnwcz 2/2 Running 0 4m42s
istio-system istio-citadel-6c7788b-5cjm8 1/1 Running 0 6m24s
istio-system istio-galley-59647cbf86-jv7s7 2/2 Running 0 6m24s
istio-system istio-ingressgateway-ldb72 2/2 Running 0 6m
istio-system istio-pilot-6cf5468446-wkrzg 2/2 Running 0 6m23s
istio-system istio-policy-6858f85497-kxw6n 2/2 Running 2 6m23s
istio-system istio-sidecar-injector-6647645d86-xlbcw 1/1 Running 0 6m24s
istio-system istio-telemetry-f84bd7d77-kjjrq 2/2 Running 1 6m23s
kpack kpack-controller-559cd7f665-p6txb 1/1 Running 0 6m27s
kpack kpack-webhook-5bdfdf487c-vv5vr 1/1 Running 0 6m26s
kube-system coredns-6955765f44-n4qzd 1/1 Running 0 29m
kube-system coredns-6955765f44-thqj8 1/1 Running 0 29m
kube-system etcd-kind-control-plane 1/1 Running 0 29m
kube-system kindnet-s9l7m 1/1 Running 0 29m
kube-system kube-apiserver-kind-control-plane 1/1 Running 0 29m
kube-system kube-controller-manager-kind-control-plane 1/1 Running 0 29m
kube-system kube-proxy-jfbm8 1/1 Running 0 29m
kube-system kube-scheduler-kind-control-plane 1/1 Running 0 29m
local-path-storage local-path-provisioner-7745554f7f-vnwh9 1/1 Running 0 29m
metacontroller metacontroller-0 2/2 Running 0 4m53s
インストール後のService
一覧は次の通りです。istio-ingressgateway
がNodePort
になっており、31080
->80
、31443
->443
になっていることに注目してください。
Kindの設定内容と一致します。
$ kubectl get svc -A
NAMESPACE NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
cf-blobstore cf-blobstore-minio ClusterIP 10.96.78.163 <none> 9000/TCP 6m34s
cf-db cf-db-postgresql ClusterIP 10.96.218.112 <none> 5432/TCP 6m32s
cf-db cf-db-postgresql-headless ClusterIP None <none> 5432/TCP 6m32s
cf-system capi ClusterIP 10.96.131.69 <none> 80/TCP 6m34s
cf-system cfroutesync ClusterIP 10.96.8.232 <none> 80/TCP 6m34s
cf-system eirini ClusterIP 10.96.99.214 <none> 8085/TCP 6m34s
cf-system log-cache ClusterIP 10.96.95.99 <none> 8083/TCP 6m34s
cf-system log-cache-syslog ClusterIP 10.96.207.232 <none> 8082/TCP 6m34s
cf-system metric-proxy ClusterIP 10.96.76.205 <none> 8080/TCP 6m34s
cf-system uaa ClusterIP 10.96.43.61 <none> 8080/TCP 6m32s
default kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 29m
istio-system istio-citadel ClusterIP 10.96.221.120 <none> 8060/TCP,15014/TCP 6m34s
istio-system istio-galley ClusterIP 10.96.55.132 <none> 443/TCP,15014/TCP,9901/TCP,15019/TCP 6m34s
istio-system istio-ingressgateway NodePort 10.96.33.9 <none> 15020:32508/TCP,80:31080/TCP,443:31443/TCP,15029:32477/TCP,15030:30356/TCP,15031:30882/TCP,15032:31281/TCP,15443:30490/TCP 6m33s
istio-system istio-pilot ClusterIP 10.96.100.89 <none> 15010/TCP,15011/TCP,8080/TCP,15014/TCP 6m33s
istio-system istio-policy ClusterIP 10.96.107.158 <none> 9091/TCP,15004/TCP,15014/TCP 6m33s
istio-system istio-sidecar-injector ClusterIP 10.96.157.123 <none> 443/TCP 6m33s
istio-system istio-telemetry ClusterIP 10.96.3.64 <none> 9091/TCP,15004/TCP,15014/TCP,42422/TCP 6m32s
kpack kpack-webhook ClusterIP 10.96.104.123 <none> 443/TCP 6m34s
kube-system kube-dns ClusterIP 10.96.0.10 <none> 53/UDP,53/TCP,9153/TCP
kube-system metrics-server ClusterIP 10.96.161.224 <none> 443/TCP 3m34s
インストール後のPersistentVolume
一覧は次の通りです。データベースとしてPostgreSQL、BlobstoreとしてMinioがPersistentVolume
を使用しています。
$ kubectl get pv
NAME CAPACITY ACCESS MODES RECLAIM POLICY STATUS CLAIM STORAGECLASS REASON AGE
pvc-dd2c1c7d-f741-4f9a-bd4a-b450baa24046 8Gi RWO Delete Bound cf-db/data-cf-db-postgresql-0 standard 5m33s
pvc-dea38d71-286c-415d-9754-a252deb94a59 10Gi RWO Delete Bound cf-blobstore/cf-blobstore-minio standard 5m19s
kapp
を使ってインストールした場合はkapp inspect -a <アプリ名> --tree
コマンドで、作成されたリソース一覧を確認できます。
次のエンドポイントにアクセスして、Cloud Controllerのバージョンを確認できます。
$ curl -s -k https://api.local.maki.lol/v2/info | jq .
{
"name": "",
"build": "",
"support": "",
"version": 0,
"description": "",
"authorization_endpoint": "https://login.local.maki.lol",
"token_endpoint": "https://uaa.local.maki.lol",
"min_cli_version": "",
"min_recommended_cli_version": "",
"app_ssh_endpoint": "TODO.TODO",
"app_ssh_host_key_fingerprint": "placeholder",
"app_ssh_oauth_client": "placeholder",
"doppler_logging_endpoint": "wss://doppler.local.maki.lol:443",
"api_version": "2.148.0",
"osbapi_version": "2.15",
"routing_endpoint": "https://api.local.maki.lol/routing"
}
Cloud Foundryにログイン
早速Cloud Foundryにログインしてみます。
admin
ユーザーのパスワードはbosh int /tmp/cf-values.yml --path /cf_admin_password
で取得できます。
次のコマンドでログインします。
cf login -a api.local.maki.lol -u admin -p $(bosh int /tmp/cf-values.yml --path /cf_admin_password) --skip-ssl-validation
次のようなログが出力されればOKです。
API endpoint: api.local.maki.lol
Authenticating...
OK
Targeted org system
API endpoint: https://api.local.maki.lol (API version: 3.83.0)
User: admin
Org: system
Space: No space targeted, use 'cf target -s SPACE'
Docker Imageをそのままデプロイできる機能を有効にします。0.1.0ではBuildpackを使う場合はもこの設定が必要です。
$ cf enable-feature-flag diego_docker
Setting status of diego_docker as admin...
OK
Feature diego_docker Enabled.
UAAにアクセスしてみます。URLは https://uaa.local.maki.lol です。
Org、Spaceの作成
demo
Orgとdemo
Spaceを作成します。
cf create-org demo
cf create-space demo -o demo
cf target -o demo -s demo
Javaアプリケーションのデプロイ
Spring Bootのアプリをデプロイします。
雛形プロジェクトを作成し、ビルドします。
cd /tmp
curl https://start.spring.io/starter.tgz \
-d artifactId=hello-cf \
-d baseDir=hello-cf \
-d dependencies=web,actuator \
-d packageName=com.example \
-d applicationName=HelloCfApplication | tar -xzvf -
cd hello-cf
./mvnw clean package -DskipTests=true
cf push
します。
$ cf push hello -p target/hello-cf-0.0.1-SNAPSHOT.jar
Pushing app hello to org demo / space demo as admin...
Getting app info...
Creating app with these attributes...
+ name: hello
path: /private/tmp/hello-cf/target/hello-cf-0.0.1-SNAPSHOT.jar
routes:
+ hello.local.maki.lol
Creating app hello...
Mapping routes...
Comparing local files to remote cache...
Packaging files to upload...
Uploading files...
315.39 KiB / 315.39 KiB [===========================================================================================================================================================] 100.00% 1s
Waiting for API to complete processing files...
Staging app and tracing logs...
Waiting for app to start...
name: hello
requested state: started
isolation segment: placeholder
routes: hello.local.maki.lol
last uploaded: Thu 16 Apr 23:37:16 JST 2020
stack:
buildpacks:
type: web
instances: 1/1
memory usage: 1024M
state since cpu memory disk details
#0 running 2020-04-16T14:37:26Z 0.0% 0 of 1G 0 of 1G
デプロイが成功しました。
cf apps
コマンドでアプリケーション一覧を確認します。
$ cf apps
Getting apps in org demo / space demo as admin...
OK
name requested state instances memory disk urls
hello started 1/1 1G 1G hello.local.maki.lol
cf app
コマンドでアプリの詳細を確認できます。
$ cf app hello
Showing health and status for app hello in org demo / space demo as admin...
name: hello
requested state: started
isolation segment: placeholder
routes: hello.local.maki.lol
last uploaded: Thu 16 Apr 23:37:16 JST 2020
stack:
buildpacks:
type: web
instances: 1/1
memory usage: 1024M
state since cpu memory disk details
#0 running 2020-04-16T14:37:26Z 0.0% 0 of 1G 0 of 1G
/actuator/health
エンドポイントにアクセスします。
$ curl http://hello.local.maki.lol/actuator/health
{"status":"UP"}
0.1.0ではHTTPエンドポイントだけ利用可能で、HTTPSやTCPは使えません。
また、これまでのCloud FoundryではBuildpack v2が使用されていましたが、cf-for-k8sではkpack経由でCloud Native Buildpacksが使用されます。
cf push
で作成されたコンテナイメージはインストール時に設定したDocker Registryにデプロイされます。実際にDockerHubにイメージがデプロイされていました。
なお、Kpackが使用するCloud Native Buildpacks一覧はkubectl get builder -n cf-workloads-staging cf-autodetect-builder -o yaml
で確認っできます。
現時点では言語として、Java, Node.js, .NET, Goが利用できます。(Builderとしてcloudfoundry/cnb:0.0.55-bionic
が登録されています。)
cf logs hello --recent
コマンドでログを確認できます。Cloud Native Buildpacksの実行結果が出力されています。
cf-for-k8sでは、EiriniというコンポーネントがCloud Controllerからのリクエストを受けてKubernetesにアプリをStatefulset
としてデプロイします。Eiriniが作成したStatefulSet
及び、それにより作られたPod
は次のコマンドで確認できます。
$ kubectl get statefulset,pod -n cf-workloads
NAME READY AGE
statefulset.apps/hello-demo-76752befbe 1/1 4m55s
NAME READY STATUS RESTARTS AGE
pod/hello-demo-76752befbe-0 2/2 Running 0 4m55s
現時点でcf-for-k8sでDeveloper(
cf push
を使うユーザー)がkubectl
を使うことは想定していません。kubectl
はPlatformエンジニアが使う想定です。
Smoke Testの実行
cf push
は成功しましたが、インストールが適切にできているか確認するために、Smoke Testを実行してみます。
Smoke Testを実行するにはginkgoをインストールする必要があります。
brew install go
go get -u github.com/onsi/ginkgo/ginkgo
export PATH=$PATH:$HOME/go/bin
次のコマンドでSmoke Testを実行します。
export SMOKE_TEST_APPS_DOMAIN=local.maki.lol
export SMOKE_TEST_API_ENDPOINT=api.local.maki.lol
export SMOKE_TEST_USERNAME=admin
export SMOKE_TEST_PASSWORD=$(bosh int /tmp/cf-values.yml --path /cf_admin_password)
export SMOKE_TEST_SKIP_SSL=true
./cf-for-k8s/hack/run-smoke-tests.sh
次のような結果が出力されれば成功です。
Running Suite: Smoke Tests Suite
================================
Random Seed: 1587047286
Will run 2 of 2 specs
..(略)..
Ran 2 of 2 Specs in 119.501 seconds
SUCCESS! -- 2 Passed | 0 Failed | 0 Pending | 0 Skipped
PASS
Ginkgo ran 1 suite in 2m0.870246904s
Test Suite Passed
Cloud Foundryのアンインストール
アンインストールはkapp
で一発です。
kapp delete -a cf
cf-for-k8s 0.1.0を試しました。
まだまだ制限は多く、Productionで利用できるレベルではないですが、少しずつ機能が追加されていくでしょう。 現時点でのKnown Issuesは次のページに記載されています。
https://github.com/cloudfoundry/cf-for-k8s/releases/tag/v0.1.0