nekop's blog

OpenShift / JBoss / WildFly / Infinispanの中の人 http://twitter.com/nekop

OpenShiftの基本的なソースからのビルドとデプロイでアプリケーションを動かす

OpenShift 全部俺 Advent Calendar 2017

minishiftで環境ができたので、アプリケーションをビルドして動作させてみましょう。使うのはソースからコンテナイメージをビルドするs2i (source to image)と呼ばれるビルド方式です。

初期状態ではdeveloperユーザ、myprojectというプロジェクトとなっています。この情報は~/.kube/configファイルに格納されています。

$ oc whoami
developer
$ oc status
In project My Project (myproject) on server https://192.168.42.225:8443

You have no services, deployment configs, or build configs.
Run 'oc new-app' to create an application.

myprojectみたいなデフォルトのものを使うのは後から使い分けしようとしたときに困ることが多く、あまり好きではないので、別ユーザ別プロジェクトを作成します。

nekopというユーザ、アプリケーションはRubyのものを使いますので、test-rubyというプロジェクトを作成します。minishiftではAllowAllという認証設定がされているので、ユーザ名は任意、パスワードに空文字以外で全て通るようになっています。

$ oc login -u nekop
Authentication required for https://192.168.42.225:8443 (openshift)
Username: nekop
Password: 
Login successful.

You don't have any projects. You can try to create a new project, by running

    oc new-project <projectname>

$ oc new-project test-ruby
Now using project "test-ruby" on server "https://192.168.42.225:8443".

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

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

to build a new example application in Ruby.

アプリケーションのソースコードを指定してoc new-appを発行します。SinatraというRubyのWebフレームワークで書いたHello Worldのアプリ https://github.com/nekop/hello-sinatra を指定しています。

$ oc new-app https://github.com/nekop/hello-sinatra
--> Found image a6f8569 (10 days old) in image stream "openshift/ruby" under tag "2.4" for "ruby"

    Ruby 2.4 
    -------- 
    Ruby 2.4 available as docker container is a base platform for building and running various Ruby 2.4 applications and frameworks. Ruby is the interpreted scripting language for quick and easy object-oriented programming. It has many features to process text files and to do system management tasks (as in Perl). It is simple, straight-forward, and extensible.

    Tags: builder, ruby, ruby24, rh-ruby24

    * The source repository appears to match: ruby
    * A source build using source code from https://github.com/nekop/hello-sinatra will be created
      * The resulting image will be pushed to image stream "hello-sinatra:latest"
      * Use 'start-build' to trigger a new build
    * This image will be deployed in deployment config "hello-sinatra"
    * Port 8080/tcp will be load balanced by service "hello-sinatra"
      * Other containers can access this service through the hostname "hello-sinatra"

--> Creating resources ...
    imagestream "hello-sinatra" created
    buildconfig "hello-sinatra" created
    deploymentconfig "hello-sinatra" created
    service "hello-sinatra" created
--> Success
    Build scheduled, use 'oc logs -f bc/hello-sinatra' 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-sinatra' 
    Run 'oc status' to view your app.

openshift/ruby:2.4というイメージを利用してアプリケーションがビルドされています。

状況を確認するコマンドはいろいろあります。oc status, oc get all, oc logs, oc get eventなどです。細かい説明は後日やります。たぶん。

$ oc status 
In project test-ruby on server https://192.168.42.225:8443

svc/hello-sinatra - 172.30.168.102:8080
  dc/hello-sinatra deploys istag/hello-sinatra:latest <-
    bc/hello-sinatra source builds https://github.com/nekop/hello-sinatra on openshift/ruby:2.4 
      build #1 running for 22 seconds - cf28c79: Add index.html (Takayoshi Kimura <takayoshi@gmail.com>)
    deployment #1 waiting on image or update

View details with 'oc describe <resource>/<name>' or list everything with 'oc get all'.

$ oc get all
NAME                         TYPE      FROM      LATEST
buildconfigs/hello-sinatra   Source    Git       1

NAME                     TYPE      FROM          STATUS    STARTED          DURATION
builds/hello-sinatra-1   Source    Git@cf28c79   Running   48 seconds ago   

NAME                         DOCKER REPO                               TAGS      UPDATED
imagestreams/hello-sinatra   172.30.1.1:5000/test-ruby/hello-sinatra             

NAME                              REVISION   DESIRED   CURRENT   TRIGGERED BY
deploymentconfigs/hello-sinatra   0          1         0         config,image(hello-sinatra:latest)

NAME                       READY     STATUS    RESTARTS   AGE
po/hello-sinatra-1-build   1/1       Running   0          48s

NAME                CLUSTER-IP       EXTERNAL-IP   PORT(S)    AGE
svc/hello-sinatra   172.30.168.102   <none>        8080/TCP   48s

$ oc logs hello-sinatra-1-build -f
---> Installing application source ...
---> Building your Ruby application from source ...
---> Running 'bundle install --deployment --without development:test' ...
Fetching gem metadata from https://rubygems.org/.........
Fetching version metadata from https://rubygems.org/.
Installing rake 11.1.2
Installing power_assert 0.2.7
Installing rack 1.6.4
Installing tilt 2.0.2
Using bundler 1.13.7
Installing test-unit 3.1.8
Installing rack-protection 1.5.3
Installing rack-test 0.6.3
Installing sinatra 1.4.7
Bundle complete! 4 Gemfile dependencies, 9 gems now installed.
Gems in the groups development and test were not installed.
Bundled gems are installed into ./bundle.
---> Cleaning up unused ruby gems ...
Running `bundle clean   --verbose` with bundler 1.13.7
Found no changes, using resolution from the lockfile
/opt/app-root/src/bundle/ruby/2.4.0/gems/rake-11.1.2/lib/rake/ext/fixnum.rb:4: warning: constant ::Fixnum is deprecated
Pushing image 172.30.1.1:5000/test-ruby/hello-sinatra:latest ...
Pushed 0/10 layers, 0% complete
Pushed 1/10 layers, 14% complete
Pushed 2/10 layers, 25% complete
Pushed 3/10 layers, 31% complete
Pushed 4/10 layers, 43% complete
Pushed 5/10 layers, 53% complete
Pushed 6/10 layers, 65% complete
Pushed 7/10 layers, 75% complete
Pushed 8/10 layers, 84% complete
Pushed 9/10 layers, 99% complete
Pushed 10/10 layers, 100% complete
Push successful

$ oc get event
LASTSEEN   FIRSTSEEN   COUNT     NAME                     KIND                    SUBOBJECT                                TYPE      REASON                     SOURCE                        MESSAGE
2m         2m          1         hello-sinatra-1-build    Pod                                                              Normal    Scheduled                  default-scheduler             Successfully assigned hello-sinatra-1-build to localhost
2m         2m          1         hello-sinatra-1-build    Pod                                                              Normal    SuccessfulMountVolume      kubelet, localhost            MountVolume.SetUp succeeded for volume "crio-socket" 
2m         2m          1         hello-sinatra-1-build    Pod                                                              Normal    SuccessfulMountVolume      kubelet, localhost            MountVolume.SetUp succeeded for volume "buildworkdir" 
2m         2m          1         hello-sinatra-1-build    Pod                                                              Normal    SuccessfulMountVolume      kubelet, localhost            MountVolume.SetUp succeeded for volume "docker-socket" 
2m         2m          1         hello-sinatra-1-build    Pod                                                              Normal    SuccessfulMountVolume      kubelet, localhost            MountVolume.SetUp succeeded for volume "builder-dockercfg-2g5jw-push" 
2m         2m          1         hello-sinatra-1-build    Pod                                                              Normal    SuccessfulMountVolume      kubelet, localhost            MountVolume.SetUp succeeded for volume "builder-token-q8h4n" 
2m         2m          1         hello-sinatra-1-build    Pod                     spec.initContainers{git-clone}           Normal    Pulling                    kubelet, localhost            pulling image "openshift/origin-sti-builder:v3.7.0"
2m         2m          1         hello-sinatra-1-build    Pod                     spec.initContainers{git-clone}           Normal    Pulled                     kubelet, localhost            Successfully pulled image "openshift/origin-sti-builder:v3.7.0"
2m         2m          1         hello-sinatra-1-build    Pod                     spec.initContainers{git-clone}           Normal    Created                    kubelet, localhost            Created container
2m         2m          1         hello-sinatra-1-build    Pod                     spec.initContainers{git-clone}           Normal    Started                    kubelet, localhost            Started container
2m         2m          1         hello-sinatra-1-build    Pod                     spec.initContainers{manage-dockerfile}   Normal    Pulled                     kubelet, localhost            Container image "openshift/origin-sti-builder:v3.7.0" already present on machine
2m         2m          1         hello-sinatra-1-build    Pod                     spec.initContainers{manage-dockerfile}   Normal    Created                    kubelet, localhost            Created container
2m         2m          1         hello-sinatra-1-build    Pod                     spec.initContainers{manage-dockerfile}   Normal    Started                    kubelet, localhost            Started container
2m         2m          1         hello-sinatra-1-build    Pod                     spec.containers{sti-build}               Normal    Pulled                     kubelet, localhost            Container image "openshift/origin-sti-builder:v3.7.0" already present on machine
2m         2m          1         hello-sinatra-1-build    Pod                     spec.containers{sti-build}               Normal    Created                    kubelet, localhost            Created container
2m         2m          1         hello-sinatra-1-build    Pod                     spec.containers{sti-build}               Normal    Started                    kubelet, localhost            Started container
1m         1m          1         hello-sinatra-1-deploy   Pod                                                              Normal    Scheduled                  default-scheduler             Successfully assigned hello-sinatra-1-deploy to localhost
1m         1m          1         hello-sinatra-1-deploy   Pod                                                              Normal    SuccessfulMountVolume      kubelet, localhost            MountVolume.SetUp succeeded for volume "deployer-token-82bmt" 
1m         1m          1         hello-sinatra-1-deploy   Pod                     spec.containers{deployment}              Normal    Pulled                     kubelet, localhost            Container image "openshift/origin-deployer:v3.7.0" already present on machine
1m         1m          1         hello-sinatra-1-deploy   Pod                     spec.containers{deployment}              Normal    Created                    kubelet, localhost            Created container
1m         1m          1         hello-sinatra-1-deploy   Pod                     spec.containers{deployment}              Normal    Started                    kubelet, localhost            Started container
1m         1m          1         hello-sinatra-1-deploy   Pod                     spec.containers{deployment}              Normal    Killing                    kubelet, localhost            Killing container with id docker://deployment:Need to kill Pod
1m         1m          1         hello-sinatra-1-jxqm5    Pod                                                              Normal    Scheduled                  default-scheduler             Successfully assigned hello-sinatra-1-jxqm5 to localhost
1m         1m          1         hello-sinatra-1-jxqm5    Pod                                                              Normal    SuccessfulMountVolume      kubelet, localhost            MountVolume.SetUp succeeded for volume "default-token-fhb4l" 
1m         1m          1         hello-sinatra-1-jxqm5    Pod                     spec.containers{hello-sinatra}           Normal    Pulling                    kubelet, localhost            pulling image "172.30.1.1:5000/test-ruby/hello-sinatra@sha256:623df61eea9fb550df241a2cd8e909b44fd2fb69a4d82298f7221f5c92488167"
1m         1m          1         hello-sinatra-1-jxqm5    Pod                     spec.containers{hello-sinatra}           Normal    Pulled                     kubelet, localhost            Successfully pulled image "172.30.1.1:5000/test-ruby/hello-sinatra@sha256:623df61eea9fb550df241a2cd8e909b44fd2fb69a4d82298f7221f5c92488167"
1m         1m          1         hello-sinatra-1-jxqm5    Pod                     spec.containers{hello-sinatra}           Normal    Created                    kubelet, localhost            Created container
1m         1m          1         hello-sinatra-1-jxqm5    Pod                     spec.containers{hello-sinatra}           Normal    Started                    kubelet, localhost            Started container
2m         2m          1         hello-sinatra-1          Build                                                            Normal    BuildStarted               build-controller              Build test-ruby/hello-sinatra-1 is now running
1m         1m          1         hello-sinatra-1          Build                                                            Normal    BuildCompleted             build-controller              Build test-ruby/hello-sinatra-1 completed successfully
1m         1m          1         hello-sinatra-1          ReplicationController                                            Normal    SuccessfulCreate           replication-controller        Created pod: hello-sinatra-1-jxqm5
2m         2m          1         hello-sinatra            BuildConfig                                                      Warning   BuildConfigTriggerFailed   buildconfig-controller        error triggering Build for BuildConfig test-ruby/hello-sinatra: Internal error occurred: build config test-ruby/hello-sinatra has already instantiated a build for imageid centos/ruby-24-centos7@sha256:905b51254a455c716892314ef3a029a4b9a4b1e832a9a1518783577f115956fd
1m         1m          1         hello-sinatra            DeploymentConfig                                                 Normal    DeploymentCreated          deploymentconfig-controller   Created new replication controller "hello-sinatra-1" for version 1

$ oc get pod
NAME                    READY     STATUS      RESTARTS   AGE
hello-sinatra-1-build   0/1       Completed   0          1m
hello-sinatra-1-jxqm5   1/1       Running     0          25s

最後の出力を見るとアプリケーションのpodがRunningになっているので正常にデプロイされているようです。

oc new-appコマンドでは外部アクセス用のRouteは自動的に作成されないので、作成してアクセスしてみます。

$ oc expose svc hello-sinatra
route "hello-sinatra" exposed
$ oc get route
NAME            HOST/PORT                                       PATH      SERVICES        PORT       TERMINATION   WILDCARD
hello-sinatra   hello-sinatra-test-ruby.192.168.42.225.nip.io             hello-sinatra   8080-tcp                 None
$ curl hello-sinatra-test-ruby.192.168.42.225.nip.io
curl: (6) Could not resolve host: hello-sinatra-test-ruby.192.168.42.225.nip.io

あれれ、エラーになりましたね。どうやらminishiftがデフォルトで利用するDNSサービスの nip.io が落ちているようです。とりあえずは同種のサービスである xip.io に変更してみましょう。

$ oc delete route hello-sinatra
route "hello-sinatra" deleted
$ oc expose svc hello-sinatra --hostname hello-sinatra-test-ruby.192.168.42.225.xip.io
route "hello-sinatra" exposed
$ oc get route
NAME            HOST/PORT                                       PATH      SERVICES        PORT       TERMINATION   WILDCARD
hello-sinatra   hello-sinatra-test-ruby.192.168.42.225.xip.io             hello-sinatra   8080-tcp                 None
$ curl hello-sinatra-test-ruby.192.168.42.225.xip.io
hello

きちんとアプリケーションからhelloが返却されました。

一連の操作はWebコンソール上のGUIでも可能です。minishift consoleコマンドでブラウザ上でWebコンソールが開くようになっています。