Edited at

Kubernetes と OpenShift の違いを確かめてみた

IBM Cloud の Kubernetes サービスに 2019年7月で Red Hat OpenShift が加わった。このOpenShiftは、Red Hat がサブスクリプションでサポートするソフトウェアであり、Kubernetesの本来の機能に加えて、Red Hat の魅力的な機能が、たくさん追加されている。

その一端を知るために、IBM Cloud のOpenShift チュートリアルを実行しながら、KubernetesとOpenShiftの違いを確かめたメモである。

本メモは、OpenShift on IBM Cloud をデプロイした後に、oc login が成功して、ocコマンドが実行できる状態からの開始を想定している。oc login までの手順は、OpenShiftクラスタ管理画面のタブ「アクセス」に従ってセットアップできるので省略する。


バージョンの表示

最初にOpenShiftのバージョンを確認する。 OpneShiftのバージョンは、v3の最新バージョンである事が読み取れる。

$ oc version

oc v3.11.0+0cbc58b
kubernetes v1.11.0+d4cacc0
features: Basic-Auth

Server https://c100-e.jp-tok.containers.cloud.ibm.com:30617
openshift v3.11.135
kubernetes v1.11.0+d4cacc0

それから、ocコマンドと一緒にkubectlコマンドもインストールされるが、これまでのIKSクラスタを利用してきた関係で、kubectl コマンドもインストールしてありパスが先にある。そこで、kubectlコマンドでもバージョンを確認してみる。kubectlコマンドは、IKSの実行時点のデフォルトバージョン v1.14 であり、OpenShift のマスターノードは、Kubernetes v1.11 である。つまり、kubectlコマンドのバージョンが高い状態である。

$ kubectl version --short

Client Version: v1.14.0
Server Version: v1.11.0+d4cacc0


名前空間のリスト

OpenShiftの特徴として、プロジェクトの名前空間を生成して、その中にアプリケーションをデプロイする。そのため、チュートリアルを先に進める前に先立って名前空間を確認しておく。ここでは、oc コマンドと kubectl コマンドの結果に違いはない。


ocコマンドで名前空間をリストした結果

$ oc get ns

NAME STATUS AGE
default Active 1d
ibm-cert-store Active 1d
ibm-system Active 1d
kube-proxy-and-dns Active 1d
kube-public Active 1d
kube-service-catalog Active 1d
kube-system Active 1d
openshift Active 1d
openshift-ansible-service-broker Active 1d
openshift-console Active 1d
openshift-infra Active 1d
openshift-monitoring Active 1d
openshift-node Active 1d
openshift-template-service-broker Active 1d
openshift-web-console Active 1d


kubectlコマンドで名前空間をリストした結果

$ kubectl get ns

NAME STATUS AGE
default Active 1d
ibm-cert-store Active 1d
ibm-system Active 1d
<以下前述と同じ>

OpenShift で kubectl コマンドが利用できる理由や、違いについては、OpenShift英語ドキュメントの Differences Between oc and kubectl が参考になる。


プロジェクトの作成

チュートリアルの手順に従って、OpenShiftのプロジェクトを作成する。

oc new-project プロジェクト名でプロジェクトを作成すると、プロジェクトの名前空間が作成され、デフォルトのコンテキストがプロジェクトの名前空間に切り替わる。


OpneShiftプロジェクトの作成

$ oc new-project hello-world

Now using project "hello-world" on server "https://c100-e.jp-tok.containers.cloud.ibm.com:30617".

You can add applications to this project with the 'new-app' command. For example, try:

oc new-app centos/ruby-25-centos7~https://github.com/sclorg/ruby-ex.git

to build a new example application in Ruby.


Kubernetesとしての動きの確認

oc new-project プロジェクト名の実行結果をkubectlコマンドで確認すると、プロジェクトの名前空間 hello-worldが作成された事が読み取れる。

$ kubectl get ns

NAME STATUS AGE
default Active 1d
hello-world Active 1m
<以下省略>

kubectlコマンドやocコマンドのスコープをプロジェクトの名前空間に移動するために、kubectl configによってコンテキストが追加され、コンテキストのカレントが、移動している事が、次のコマンドの実行結果から読み取れる。つまり、これから実行するコマンドに、毎回 -n 名前空間名を付与して名前空間を指定しなくても良いことを意味する。 ocコマンドは 複数のkubectlコマンドを一度に複合して実行する利便性を提供している。

$ kubectl config get-contexts

CURRENT NAME
default/c100-e-jp-tok-containers-cloud-ibm-com:30617/IAM#TAKARA@jp.ibm.com
* hello-world/c100-e-jp-tok-containers-cloud-ibm-com:30617/IAM#TAKARA@jp.ibm.com

oc get projectsで、プロジェクトのリストを表示した。すると、名前空間と同じリストが表示され、OpenShiftではプロジェクトごとに、名前空間を作成する思想が感じられる。

$ oc get projects

NAME DISPLAY NAME STATUS
default Active
hello-world Active
<以下省略>

これは面白いことに、本来 kubectl v1.14 にproject のリソースは定義が無いが、kubectl get project でも同じ結果を得る事ができた。


アプリケーションの作成

チュートリアルに従って、oc new-app --name プロジェクト名を使ってプロジェクトの名前空間 hello-world にアプリケーションを作成する。

oc new-app --name hello-world https://github.com/IBM/container-service-getting-started-wt --context-dir="Lab 1"を実行すると、GitHubのURL https://github.com/IBM/container-service-getting-started-wt/tree/master/Lab%201の Dockerfile が読み取られ、リソースが作成される。この中でも、Dockerfileが読み取られ、イメージがビルドされる動作が興味深い。

$ oc new-app --name hello-world https://github.com/IBM/container-service-getting-started-wt --context-dir="Lab 1"

--> Found Docker image b5f9499 (19 months old) from Docker Hub for "node:9.4.0-alpine"

* An image stream tag will be created as "node:9.4.0-alpine" that will track the source image
* A Docker build using source code from https://github.com/IBM/container-service-getting-started-wt will be created
* The resulting image will be pushed to image stream tag "hello-world:latest"
* Every time "node:9.4.0-alpine" changes a new build will be triggered
* This image will be deployed in deployment config "hello-world"
* Port 8080/tcp will be load balanced by service "hello-world"
* Other containers can access this service through the hostname "hello-world"
* WARNING: Image "node:9.4.0-alpine" runs as the 'root' user which may not be permitted by your cluster administrator

--> Creating resources ...
imagestream.image.openshift.io "node" created
imagestream.image.openshift.io "hello-world" created
buildconfig.build.openshift.io "hello-world" created
deploymentconfig.apps.openshift.io "hello-world" created
service "hello-world" created
--> Success
Build scheduled, use 'oc logs -f bc/hello-world' to track its progress.
Application is not exposed. You can expose services to the outside world by executing one or more of the commands below:
'oc expose svc/hello-world'
Run 'oc status' to view your app.

このGitHubのURLのREADME.mdには、OpenShiftを使わない場合の、イメージのビルド方法、レジストリの登録方法、アプリケーションのデプロイ方法が解説されているが、OpenShiftでは Dockerfile を手がかりに、ビルド、内部レジストリへの登録、アプリの実行までを実施してくれる。

従来のkubectlコマンドやibmcloudコマンドを組み合わせて、実行することに比べると、oc new-appコマンドの生産性は高い。

チュートリアルに戻って、oc status コマンドで、アプリケーションのステータスを表示すると、デプロイされたアプリケーションのポッド、コントローラー、サービスが表示される。ここで興味深いことにkubectl statusコマンドは存在しない。 oc statusは、OpenShift独自に拡張した機能である。

$ oc status

In project hello-world on server https://c100-e.jp-tok.containers.cloud.ibm.com:30617

svc/hello-world - 172.21.202.186:8080
dc/hello-world deploys istag/hello-world:latest <-
bc/hello-world docker builds https://github.com/IBM/container-service-getting-started-wt on istag/node:9.4.0-alpine
deployment #1 deployed about a minute ago - 1 pod

2 infos identified, use 'oc status --suggest' to see details.

さらに、dc/hello-worlddcは、DeploymentConfig の略であり、Kubernetesに存在しない独自のコンローラーである。

次に表示されている bc/hello-worldbc は、BuildConfig の略であり、同じくKubernetesに存在しない独自のコンローラーである。

しかし、CNCFが配布する v1.14の kubectl コマンドでも、次のように表示できる。OpenShiftでは、Kubernetesにリソースやコントローラーなどの機能を追加して、利用者の生産性が高くなるようにKubernetesとしての機能が強化されている事が読み取れる。ここで、ポッドは、Red Hat 独自実装の DeploymentConfig と、Kubernetesでは非推奨の扱いのReplicationController によって起動された事がわかる。

$ kubectl get svc

NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
hello-world ClusterIP 172.21.202.186 <none> 8080/TCP 4m

$ kubectl get deploymentconfig
NAME REVISION DESIRED CURRENT TRIGGERED BY
hello-world 1 1 1 config,image(hello-world:latest)

$ kubectl get buildconfig
NAME TYPE FROM LATEST
hello-world Docker Git 1

$ kubectl get replicationcontroller
NAME DESIRED CURRENT READY AGE
hello-world-1 1 1 1 4m

$ kubectl get pods
NAME READY STATUS RESTARTS AGE
hello-world-1-5cr9p 1/1 Running 0 7m
hello-world-1-build 0/1 Completed 0 8m

Kubernetesで推奨されている DeploymentsReplicaSet で起動されていないことを確認するために、次のコマンドで確認した。

$ kubectl get deploy

No resources found.

$ kubectl get rs
No resources found.

ReplicationControllerは、ReplicaSetによって置き換わる事が決まっているが、CNCFはReplicationControllerのサポートを打ち切らない事からも、OpenShiftの存在の強さを察する事ができると思う。


OpenShift のビルドプロセス

OpenShiftの特徴的な動作であるDeploymentConfigBuildConfig の動作について見ていくことにする。

次の結果にように、oc get allkubectl get all の両方で、同じ結果を得る事ができる。


oc get allの実行結果

$ oc get all

NAME READY STATUS RESTARTS AGE
pod/hello-world-1-5cr9p 1/1 Running 0 8m
pod/hello-world-1-build 0/1 Completed 0 9m

NAME DESIRED CURRENT READY AGE
replicationcontroller/hello-world-1 1 1 1 8m

NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
service/hello-world ClusterIP 172.21.202.186 <none> 8080/TCP 9m

NAME REVISION DESIRED CURRENT TRIGGERED BY
deploymentconfig.apps.openshift.io/hello-world 1 1 1 config,image(hello-world:latest)

NAME TYPE FROM LATEST
buildconfig.build.openshift.io/hello-world Docker Git 1

NAME TYPE FROM STATUS STARTED DURATION
build.build.openshift.io/hello-world-1 Docker Git@fb14410 Complete 9 minutes ago 35s

NAME DOCKER REPO TAGS UPDATED
imagestream.image.openshift.io/hello-world docker-registry.default.svc:5000/hello-world/hello-world latest 8 minutes ago
imagestream.image.openshift.io/node docker-registry.default.svc:5000/hello-world/node 9.4.0-alpine 9 minutes ago


kubectl get allの実行結果

$ kubectl get all

NAME READY STATUS RESTARTS AGE
pod/hello-world-1-5cr9p 1/1 Running 0 12m
pod/hello-world-1-build 0/1 Completed 0 13m

NAME DESIRED CURRENT READY AGE
replicationcontroller/hello-world-1 1 1 1 12m

NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
service/hello-world ClusterIP 172.21.202.186 <none> 8080/TCP 13m

NAME REVISION DESIRED CURRENT TRIGGERED BY
deploymentconfig.apps.openshift.io/hello-world 1 1 1 config,image(hello-world:latest)

NAME TYPE FROM LATEST
buildconfig.build.openshift.io/hello-world Docker Git 1

NAME TYPE FROM STATUS STARTED DURATION
build.build.openshift.io/hello-world-1 Docker Git@fb14410 Complete 13 minutes ago 35s

NAME DOCKER REPO TAGS UPDATED
imagestream.image.openshift.io/hello-world docker-registry.default.svc:5000/hello-world/hello-world latest 12 minutes ago
imagestream.image.openshift.io/node docker-registry.default.svc:5000/hello-world/node 9.4.0-alpine 13 minutes ago

この両者の結果で、Kubernetesで見る事が無いpod/hello-world-1-build 0/1 Completedの理由について、ログから追ってみる。

oc logs pod/hello-world-1-buildの結果を読んでいくと、コンテナをビルドして、レジストリへ登録するビルドコンテナである事がわかる。これはoc new-app --name プロジェクト名によって、起動されたBuildConfigのコンテナ・イメージのビルドとレジストリ登録のステップを受け持ったポッドである事がわかる。

$ oc logs pod/hello-world-1-build

Step 1/8 : FROM node@sha256:359a2efa481b9edeff9ca120128f89387ce13dafe30b05f762ec63c7f770e415
---> b5f94997f35f
Step 2/8 : COPY app.js .
---> 2df08d71e264
Removing intermediate container 2581f82c9f49
Step 3/8 : COPY package.json .
---> 31a632dcc681
Removing intermediate container 73ee4b3dd8d1
Step 4/8 : RUN npm install && apk update && apk upgrade
---> Running in f26e410e22c0

npm notice created a lockfile as package-lock.json. You should commit this file.
npm WARN hello-world-demo@0.0.1 No repository field.
npm WARN hello-world-demo@0.0.1 No license field.
added 50 packages in 1.833s

fetch http://dl-cdn.alpinelinux.org/alpine/v3.6/main/x86_64/APKINDEX.tar.gz
fetch http://dl-cdn.alpinelinux.org/alpine/v3.6/community/x86_64/APKINDEX.tar.gz
v3.6.5-44-gda55e27396 [http://dl-cdn.alpinelinux.org/alpine/v3.6/main]
v3.6.5-34-gf0ba0b43d5 [http://dl-cdn.alpinelinux.org/alpine/v3.6/community]
OK: 8448 distinct packages available
Upgrading critical system libraries and apk-tools:
(1/1) Upgrading apk-tools (2.7.5-r0 -> 2.7.6-r0)
Executing busybox-1.26.2-r9.trigger
Continuing the upgrade transaction with new apk-tools:
(1/7) Upgrading musl (1.1.16-r14 -> 1.1.16-r15)
(2/7) Upgrading busybox (1.26.2-r9 -> 1.26.2-r11)
Executing busybox-1.26.2-r11.post-upgrade
(3/7) Upgrading libressl2.5-libcrypto (2.5.5-r0 -> 2.5.5-r2)
(4/7) Upgrading libressl2.5-libssl (2.5.5-r0 -> 2.5.5-r2)
(5/7) Installing libressl2.5-libtls (2.5.5-r2)
(6/7) Installing ssl_client (1.26.2-r11)
(7/7) Upgrading musl-utils (1.1.16-r14 -> 1.1.16-r15)
Executing busybox-1.26.2-r11.trigger
OK: 5 MiB in 15 packages
---> 936e33141d50
Removing intermediate container f26e410e22c0
Step 5/8 : EXPOSE 8080
---> Running in b65ba08bc6e9
---> 5763ed8d3254
Removing intermediate container b65ba08bc6e9
Step 6/8 : CMD node app.js
---> Running in 60c0eff924fb
---> 3adc7a7fb8c7
Removing intermediate container 60c0eff924fb
Step 7/8 : ENV "OPENSHIFT_BUILD_NAME" "hello-world-1" "OPENSHIFT_BUILD_NAMESPACE" "hello-world" "OPENSHIFT_BUILD_SOURCE" "https://github.com/IBM/container-service-getting-started-wt" "OPENSHIFT_BUILD_COMMIT" "fb14410f3f05f8b8b1d1ce62b4cd132723a36d33"
---> Running in 7d64577fbed0
---> c336489ffd70
Removing intermediate container 7d64577fbed0
Step 8/8 : LABEL "io.openshift.build.commit.author" "John Pape \u003cjpapejr@icloud.com\u003e" "io.openshift.build.commit.date" "Mon Aug 19 15:23:21 2019 -0400" "io.openshift.build.commit.id" "fb14410f3f05f8b8b1d1ce62b4cd132723a36d33" "io.openshift.build.commit.message" "Merge pull request #103 from IBM/api-dep" "io.openshift.build.commit.ref" "master" "io.openshift.build.name" "hello-world-1" "io.openshift.build.namespace" "hello-world" "io.openshift.build.source-context-dir" "Lab 1" "io.openshift.build.source-location" "https://github.com/IBM/container-service-getting-started-wt"
---> Running in 2a6d51151b0d
---> ecdc16510bad
Removing intermediate container 2a6d51151b0d
Successfully built ecdc16510bad

Pushing image docker-registry.default.svc:5000/hello-world/hello-world:latest ...
Pushed 3/6 layers, 55% complete
Pushed 4/6 layers, 100% complete
Pushed 5/6 layers, 100% complete
Pushed 6/6 layers, 100% complete
Push successful

ここで、ビルドしたコンテナ・イメージは、外部のレジストリサービスではなく、OpenShiftのクラスタ内のレジストリである事が、oc get imagestream の実行結果からわかる。

$ oc get imagestreams 

NAME DOCKER REPO TAGS UPDATED
hello-world docker-registry.default.svc:5000/hello-world/hello-world latest 26 minutes ago
node docker-registry.default.svc:5000/hello-world/node 9.4.0-alpine 27 minutes ago


外部からアクセス可能なように公開する

チュートリアルに戻って、ポッドのアプリケーションをインターネットからアクセスできるように進めていく。

ここまでの操作で、hello-world サービスのタイプは、ClusterIPとなっており、K8sクラスタ外部からアクセスができない状態である。ここから、K8sクラスタ外部からアクセス可能なように設定する。

$ oc get svc

NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
hello-world ClusterIP 172.21.202.186 <none> 8080/TCP 1h

$ kubectl get svc
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
hello-world ClusterIP 172.21.202.186 <none> 8080/TCP 1h

CNCF Kubernetes には、routeというリソースは存在しないが、kubectl コマンドでも表示が可能である。

$ oc get route

No resources found.

$ kubectl get route
No resources found.

oc create route edge --service=hello-world -n hello-worldコマンドによって、名前空間 hello-world の ClusterIPタイプのサービスへのルートを設定する。

$ oc create route edge --service=hello-world -n hello-world

route.route.openshift.io/hello-world created

実行結果の確認は、kubectl get routeでも同じようにできる。公開されたURLが読み取れるので、curlコマンドでアクセスする。

$ oc get route

NAME HOST/PORT PATH SERVICES PORT TERMINATION WILDCARD
hello-world hello-world-hello-world.iks202-dd3a245ee37e0f22836f16bc6000a054-0001.jp-tok.containers.appdomain.cloud hello-world 8080-tcp edge None

curlコマンドのURLには、必ずhttpsでなければならない。実行結果から、アプリケーションが応答を返している事がわかる。

$ curl -i https://hello-world-hello-world.iks202-dd3a245ee37e0f22836f16bc6000a054-0001.jp-tok.containers.appdomain.cloud

HTTP/1.1 200 OK
X-Powered-By: Express
Content-Type: text/html; charset=utf-8
Content-Length: 79
ETag: W/"4f-FHSLeAA/5K++jT9rAbveOkNLE/Y"
Date: Sat, 31 Aug 2019 01:01:39 GMT
Set-Cookie: b52fcf595fb6234fdbaa488498af05fb=cdf3405b3d976db6c91eb3f729714429; path=/; HttpOnly; Secure
Cache-control: private

Hello world from hello-world-1-5cr9p! Your app is up and running in a cluster!


routeがALBであるかの確認

IKS上のアプリケーション公開する場合には、イングレスコントローラーとして、ALB(Application LoadBalancer)または、ただの LBを利用する事が一般的で、HTTPSでのアクセスとなると、ポッドにTLSの設定を入れなければ、ALBが必要となる。そこでこれが、ALBを利用してるかの確認するために、kubectl get ingressibmcloud ks cluster-get クラスタ名実行した結果である。ALBのURLと異なり、イングレス・オブジェクトも存在しない事が読み取れる。

$ kubectl get ingress

No resources found.

$ bx ks cluster-get iks202

クラスター iks202 を取得中...
OK

名前: iks202
ID: bljo5g6t0qm7ro9lltk0
状態: normal
作成日時: 2019-08-29T07:46:28+0000
ロケーション: tok05
<中略>
マスター・ロケーション: Tokyo
マスター状況: Ready (1 day ago)
マスター状態: deployed
マスター正常性: normal
Ingress サブドメイン: iks202.jp-tok.containers.appdomain.cloud
Ingress の秘密: iks202
ワーカー: 1
ワーカー・ゾーン: tok05
バージョン: 3.11.135_1522_openshift
<以下省略>


routeの実体確認

routeオブジェクトの実体を確認するために、全名前空間のポッドをリストした。言うまでもない無いが、kubectl get pod --all-namespacesでも同じ結果が得られる。ここで、名前空間 default に reouter-xxxxxxxから始まるポッドが存在する。このrouterは、OpenShiftの実装であり、連携するロードバランサーに応じたものがある事がわかる。`oc describe pod ルーターのポッド名'とすれば、コンテナ・イメージが読み取れる。

$ oc get pod --all-namespaces

NAMESPACE NAME READY STATUS
default docker-registry-775bc74474-9hnnq 1/1 Running
default docker-registry-775bc74474-nbm45 1/1 Running
default registry-console-7f689b5f9-2mp8c 1/1 Running
default router-76cf9c9df8-jf7n8 1/1 Running
default router-76cf9c9df8-p6mjl 1/1 Running
default test-web 1/1 Running
hello-world hello-world-1-5cr9p 1/1 Running
hello-world hello-world-1-build 0/1 Completed
ibm-system ibm-cloud-provider-ip-***-***-**-250-6cbd8bc764-8zw22 0/1 Pending
ibm-system ibm-cloud-provider-ip-***-***-**-250-6cbd8bc764-944f8 1/1 Running
ibm-system ibm-cloud-provider-ip-***-***-**-251-5697d4d9b7-dbwhm 0/1 Pending
ibm-system ibm-cloud-provider-ip-***-***-**-251-5697d4d9b7-ph4gd 1/1 Running
kube-proxy-and-dns proxy-and-dns-kgvlk 1/1 Running
kube-service-catalog apiserver-57c8b74849-f8qz9 1/1 Running
kube-service-catalog apiserver-57c8b74849-ln7lb 1/1 Running
kube-service-catalog controller-manager-559c569db7-pc7dj 1/1 Running
kube-service-catalog controller-manager-559c569db7-xzsr9 1/1 Running
kube-system calico-kube-controllers-7c97d855cd-s7vth 1/1 Running
kube-system calico-node-6nb52 1/1 Running
kube-system heapster-664dfd6df6-4r2dr 2/2 Running
kube-system ibm-file-plugin-66d458f9cd-d6vll 1/1 Running
kube-system ibm-keepalived-watcher-qlk5j 1/1 Running
kube-system ibm-kube-fluentd-md5mb 1/1 Running
kube-system ibm-master-proxy-static-10.193.10.50 2/2 Running
kube-system ibm-storage-watcher-58bc48fd4-89frl 1/1 Running
kube-system ibmcloud-block-storage-driver-mcn67 1/1 Running
kube-system ibmcloud-block-storage-plugin-5548584945-2c94h 1/1 Running
kube-system public-crbljo5g6t0qm7ro9lltk0-alb1-7c749bcc9b-8svb4 4/4 Running
kube-system public-crbljo5g6t0qm7ro9lltk0-alb1-7c749bcc9b-ftgtw 0/4 Pending
kube-system vpn-5684cf4bbd-gx46x 1/1 Running
openshift-ansible-service-broker asb-68d56b9f7b-xpg7g 1/1 Running
openshift-console console-7d8cfb7b8b-wqx5z 1/1 Running
openshift-monitoring alertmanager-main-0 3/3 Running
openshift-monitoring alertmanager-main-1 3/3 Running
openshift-monitoring alertmanager-main-2 3/3 Running
openshift-monitoring cluster-monitoring-operator-57ffbc5599-kbrx7 1/1 Running
openshift-monitoring grafana-79b7f5d8f8-cz78t 2/2 Running
openshift-monitoring kube-state-metrics-68d55f97b7-bthtz 3/3 Running
openshift-monitoring node-exporter-tqfjr 2/2 Running
openshift-monitoring prometheus-k8s-0 4/4 Running
openshift-monitoring prometheus-k8s-1 4/4 Running
openshift-monitoring prometheus-operator-68c7f86c8-jpm9h 1/1 Running
openshift-template-service-broker apiserver-74f9c4dc7f-2pldw 1/1 Running
openshift-template-service-broker apiserver-74f9c4dc7f-87vsv 1/1 Running
openshift-web-console webconsole-85897f4875-nrn97 1/1 Running

サービスをリストすると、二つのLoadBalancer が立ち上がっている事が読み取れる。そのうちの一方がrouterで、他方がIKSのクラスタが起動する際に確保されるロードバランサーである事が読み取れる。

$ oc get svc --all-namespaces

NAMESPACE NAME TYPE CLUSTER-IP EXTERNAL-IP
default docker-registry ClusterIP 172.21.198.116 <none>
default kubernetes ClusterIP 172.21.0.1 <none> default registry-console ClusterIP 172.21.153.110 <none> default router LoadBalancer 172.21.210.164 ***.***.**.251 hello-world hello-world ClusterIP 172.21.202.186 <none> kube-service-catalog apiserver ClusterIP 172.21.52.167 <none> kube-service-catalog controller-manager ClusterIP 172.21.31.241 <none> kube-system heapster ClusterIP 172.21.10.33 <none> kube-system kube-controllers ClusterIP None <none> kube-system kubelet ClusterIP None <none> kube-system public-crbljo5g6t0qm7ro9lltk0-alb1 LoadBalancer 172.21.206.212 ***.***.**.250 openshift-ansible-service-broker asb ClusterIP 172.21.255.65 <none> openshift-console console ClusterIP 172.21.255.119 <none> openshift-monitoring alertmanager-main ClusterIP 172.21.187.233 <none> openshift-monitoring alertmanager-operated ClusterIP None <none> openshift-monitoring cluster-monitoring-operator ClusterIP None <none> openshift-monitoring grafana ClusterIP 172.21.181.164 <none> openshift-monitoring kube-state-metrics ClusterIP None <none> openshift-monitoring node-exporter ClusterIP None <none> openshift-monitoring prometheus-k8s ClusterIP 172.21.22.58 <none> openshift-monitoring prometheus-operated ClusterIP None <none> openshift-monitoring prometheus-operator ClusterIP None <none> openshift-template-service-broker apiserver ClusterIP 172.21.247.202 <none> openshift-web-console webconsole ClusterIP 172.21.133.23 <none>

つまり、OpenShift on IBM Cloud では、デフォルトの公開用アドレス以外に、OpenShift の router に対して、パブリックIPが取得され公開されている事がわかる。


IKSでデフォルトの公開用URL

$ nslookup iks202.jp-tok.containers.appdomain.cloud

Server: 192.168.1.1
Address: 192.168.1.1#53

Non-authoritative answer:
Name: iks202.jp-tok.containers.appdomain.cloud
Address: ***.***.**.250


OpenShift で割り当てられたURL

$ nslookup hello-world-hello-world.iks202-dd3a245ee37e0f22836f16bc6000a054-0001.jp-tok.containers.appdomain.cloud

Server: 192.168.1.1
Address: 192.168.1.1#53

Non-authoritative answer:
hello-world-hello-world.iks202-dd3a245ee37e0f22836f16bc6000a054-0001.jp-tok.containers.appdomain.cloud canonical name = iks202-dd3a245ee37e0f22836f16bc6000a054-0001.jp-tok.containers.appdomain.cloud.
Name: iks202-dd3a245ee37e0f22836f16bc6000a054-0001.jp-tok.containers.appdomain.cloud
Address: ***.***.**.251


クリーンナップ

チュートリアルに従って、アプリケーションを消去する。

$ oc delete all -l app=hello-world -n hello-world

pod "hello-world-1-5cr9p" deleted
replicationcontroller "hello-world-1" deleted
service "hello-world" deleted
deploymentconfig.apps.openshift.io "hello-world" deleted
buildconfig.build.openshift.io "hello-world" deleted
imagestream.image.openshift.io "hello-world" deleted
imagestream.image.openshift.io "node" deleted
route.route.openshift.io "hello-world" deleted

アプリケーションは削除されたが、プロジェクトが消えた訳ではいので、プロジェクトまで消したい時は、以下を事項する

$ oc delete project hello-world

project.project.openshift.io "hello-world" deleted

プロジェクトを消しても、コンテキストは、hello-world のままなので、変更する。

$ kubectl config get-contexts

CURRENT NAME NAMESPACE
default/c100-e-jp-tok-containers-cloud-ibm-com:30617/IAM#TAKARA@jp.ibm.com default
* hello-world/c100-e-jp-tok-containers-cloud-ibm-com:30617/IAM#TAKARA@jp.ibm.com hello-world

コンテキストの変更

$ kubectl config use-context default/c100-e-jp-tok-containers-cloud-ibm-com:30617/IAM#TAKARA@jp.ibm.com 

Switched to context "default/c100-e-jp-tok-containers-cloud-ibm-com:30617/IAM#TAKARA@jp.ibm.com".


まとめ

Kubernetesの本来の機能に加えて、Red Hat の魅力的なサービスが、沢山追加されている。この検証で解ったことを、以下に列挙する。


  • OpenShiftでは、kubectlコマンドに代わりocコマンドを利用する。

  • CNCFが配布するkubectlコマンドを利用しても、OpenShiftの操作ができる。


  • ocコマンドは、kubectlコマンドの複合的な操作を一度に実行できる。oc new-project プロジェクト名oc new-app --name プロジェクト名など。


  • oc new-project プロジェクト名は、プロジェクト用名前空間を作成して、カレント・コンテキストを切り替える。


  • oc new-app --name プロジェクト名は、指定のDockerfileを読んで、コンテナのビルド、レジストリへの登録、デプロイの一連の作業を実行する。


  • oc create route edge --service=サービス名 -n 名前空間名は、名前空間 hello-world の ClusterIPタイプのサービスへのルートを設定して、アプリケーションをクラスタ外部からアクセスできるようにする。このコマンドは、OpenShift固有のHA-Proxyを利用して公開されるため、URLが異なる。

  • クリーンナップでは、コンテキストスイッチがデフォルトに戻らないため、自分で切り替える必要がある。

  • OpenShiftでは、独自実装のコントローラーDeploymentConfigBuildConfig が利用されるが、これらのオブジェクトはkubectlでも操作可能である。

  • OpenShiftではReplicationControllerを利用して、複数のポッドを起動する。

  • もちろん、Kubernetes で推奨される DeploymentsReplicaSet の組み合わせでも起動できるが、OpenShift v3ではocコマンドからは利用されない。

Kubernetes を知っていれば、OpenShift が如何に、使いやすく強化されている事が理解できる。しかし、最初から OpenShift を利用すると、CNCF のアップストリームの Kubernetes が不便に感じると思う。そもそもコアとなるAPIは同じであるため、OpenShift をより使い熟すためにも、Kubernetes の知識は必須だと思う。