IK.AM

@making's tech note


cf-for-k8s(CF4K8s) 0.1.0をKind上にインストールする

🗃 {Dev/PaaS/CloudFoundry/CF4K8s}
🏷 Cloud Foundry 🏷 Kubernetes 🏷 CF4K8s 
🗓 Updated at 2020-04-17T09:14:46Z  🗓 Created at 2020-04-16T17:40:39Z   🌎 English Page

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のインストール

  • 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で適用しています。

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-ingressgatewayNodePortになっており、31080->8031443->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 です。

image

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にイメージがデプロイされていました。

image

なお、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


✒️️ Edit  ⏰ History  🗑 Delete