zaki work log

作業ログやら生活ログやらなんやら

[oc / kubectl] コマンドや引数の補完設定 【completion】

bashを使っているのであれば

$ source <(oc completion bash)

とか

$ source <(kubectl completion bash)

で。

OCP v3でmasterノードでばかり作業してると、たまにCRCとかクラスタ外部サーバで作業すると、「あれ?」となってしまうので備忘録。 なお、実行にはbash-completionパッケージが必要なので、インストールされていなければyumで入れておくこと。


更にkubectlであればkkcにalias設定してると思いますが(私はocに慣れてるので、kよりkcが好きな人)、 以下で、aliasにも補完を設定できる。

$ complete -o default -F __start_kubectl kc

qiita.com

[OpenShift]指定nodeでデプロイされているpod一覧を表示する

すぐoc get pod --all-namespaces -o wide | grep ${node-name}やっちゃうんだけど、、、
v3だと便利コマンドありました。

※ 以下、小ネタです。(こんなコマンドもあるんだなー程度で見てください。たぶんストレートにgrepした方が早いです笑)

OCV v3

v3はoc adm manage-node ${node-name} --list-podsというコマンドがある。
ノードokd-node2.esxi.jp-z.jpで動いてるpod一覧を表示するには、以下のように実行。

[zaki@okd-master ~]$ oc adm manage-node okd-node2.esxi.jp-z.jp --list-pods

Listing matched pods on node: okd-node2.esxi.jp-z.jp

NAMESPACE              NAME                         READY     STATUS             RESTARTS   AGE
openshift-infra        hawkular-cassandra-1-dcdvx   1/1       Running            4          13d
openshift-infra        heapster-tgk79               1/1       Running            4          13d
openshift-logging      logging-fluentd-nw8gv        0/1       CrashLoopBackOff   124        13d
openshift-monitoring   node-exporter-8wp7c          2/2       Running            8          13d
openshift-node         sync-7dkbb                   1/1       Running            4          13d
openshift-sdn          ovs-wp9qx                    1/1       Running            4          13d
openshift-sdn          sdn-q25zn                    1/1       Running            4          13d
s2i-sample             sample-1-build               0/1       Completed          0          10d
s2i-sample             sample-2-build               0/1       Completed          0          10d

oc describe nodeでも(Running状態であれば)見れる。

[zaki@okd-master ~]$ oc describe node okd-node2.esxi.jp-z.jp
Name:               okd-node2.esxi.jp-z.jp
Roles:              compute
:
:
Non-terminated Pods:         (7 in total)
  Namespace                  Name                          CPU Requests  CPU Limits  Memory Requests  Memory Limits
  ---------                  ----                          ------------  ----------  ---------------  -------------
  openshift-infra            hawkular-cassandra-1-dcdvx    0 (0%)        0 (0%)      1G (12%)         2G (24%)
  openshift-infra            heapster-tgk79                0 (0%)        0 (0%)      937500k (11%)    3750M (46%)
  openshift-logging          logging-fluentd-nw8gv         100m (5%)     0 (0%)      756Mi (9%)       756Mi (9%)
  openshift-monitoring       node-exporter-8wp7c           10m (0%)      20m (1%)    20Mi (0%)        40Mi (0%)
  openshift-node             sync-7dkbb                    0 (0%)        0 (0%)      0 (0%)           0 (0%)
  openshift-sdn              ovs-wp9qx                     100m (5%)     0 (0%)      300Mi (3%)       0 (0%)
  openshift-sdn              sdn-q25zn                     100m (5%)     0 (0%)      200Mi (2%)       0 (0%)
Allocated resources:
:
:

OCP v4

ドキュメントとコマンドのヘルプを見る限り、v4からoc adm manage-nodeが無くなってる。(なんでだろ)
なのでoc describe nodeするしかない模様

[zaki@okd4-manager ~]$ oc describe node okd4-worker0
Name:               okd4-worker0
Roles:              worker
:
:
Non-terminated Pods:                          (18 in total)
  Namespace                                   Name                                                 CPU Requests  CPU Limits  Memory Requests  Memory Limits  AGE
  ---------                                   ----                                                 ------------  ----------  ---------------  -------------  ---
  openshift-cluster-node-tuning-operator      tuned-sqvb7                                          10m (0%)      0 (0%)      50Mi (0%)        0 (0%)         9d
  openshift-console                           downloads-cf5d8d7f4-9wtkf                            10m (0%)      0 (0%)      50Mi (0%)        0 (0%)         9d
  openshift-csi-snapshot-controller-operator  csi-snapshot-controller-operator-5f5b588bf9-2ghlk    10m (0%)      0 (0%)      50Mi (0%)        0 (0%)         9d
  openshift-dns                               dns-default-bzmq7                                    110m (7%)     0 (0%)      70Mi (0%)        512Mi (6%)     9d
  openshift-image-registry                    image-registry-7f44857cc-h6znx                       100m (6%)     0 (0%)      256Mi (3%)       0 (0%)         9d
  openshift-image-registry                    node-ca-8dk7l                                        10m (0%)      0 (0%)      10Mi (0%)        0 (0%)         9d
  openshift-ingress                           router-default-5698995cc8-5z8r4                      100m (6%)     0 (0%)      256Mi (3%)       0 (0%)         9d
  openshift-machine-config-operator           machine-config-daemon-wt5lx                          40m (2%)      0 (0%)      100Mi (1%)       0 (0%)         9d
  openshift-marketplace                       community-operators-59754d9959-pglxz                 10m (0%)      0 (0%)      100Mi (1%)       0 (0%)         16m
  openshift-monitoring                        alertmanager-main-2                                  110m (7%)     100m (6%)   245Mi (3%)       25Mi (0%)      9d
  openshift-monitoring                        node-exporter-lfsq4                                  112m (7%)     0 (0%)      200Mi (2%)       0 (0%)         9d
  openshift-monitoring                        prometheus-adapter-d48bc96cc-z8lj2                   10m (0%)      0 (0%)      20Mi (0%)        0 (0%)         8d
  openshift-monitoring                        prometheus-k8s-1                                     480m (32%)    200m (13%)  1234Mi (16%)     50Mi (0%)      9d
  openshift-multus                            multus-sfwfb                                         10m (0%)      0 (0%)      150Mi (2%)       0 (0%)         9d
  openshift-sdn                               ovs-jh5x4                                            200m (13%)    0 (0%)      400Mi (5%)       0 (0%)         9d
  openshift-sdn                               sdn-sq7q2                                            100m (6%)     0 (0%)      200Mi (2%)       0 (0%)         9d
  s2i-git-perl                                s2i-sample-4-mk5s4                                   0 (0%)        0 (0%)      0 (0%)           0 (0%)         8d
  s2i-sample                                  sample-2-q4wnv                                       0 (0%)        0 (0%)      0 (0%)           0 (0%)         8d
Allocated resources:
:
:

ちなみにv4(というかk8sのver 1.14)から--all-namespacesの短縮オプションで-Aが使えるので割と楽。

パラメタの多いdocker runをdocker-composeを使ってYAMLで定義する(GitLab CE編)

docker runのパラメタが多いと設定変更して再実行しづらかったりメンテが大変なので、YAMLに書いてdocker-composeで実行すれば色々と便利です。
ということで、お題として以下のGitLab CEを起動するdocker rundocker-composeで動かせるようにしてみます。

zaki-hmkc.hatenablog.com

元のdocker run

$ sudo docker run --detach \
   --hostname gitlab-ce.example.org \
   --env GITLAB_OMNIBUS_CONFIG="external_url 'https://gitlab-ce.example.org:8443'; nginx['listen_port']=8443; gitlab_rails['registry_enabled']=true; registry_external_url 'https://gitlab-ce.example.org:25000'" \
   --publish 8443:8443 --publish 25000:25000 \
   --name gitlab-registry \
   --restart always \
   --volume /opt/gitlab-reg/config:/etc/gitlab:Z \
   --volume /opt/gitlab-reg/logs:/var/log/gitlab:Z \
   --volume /opt/gitlab-reg/data:/var/opt/gitlab:Z \
   --volume /opt/gitlab-reg/registry:/var/opt/gitlab/gitlab-rails/shared/registry:Z \
   --volume /opt/gitlab-cert:/etc/gitlab/ssl \
   gitlab/gitlab-ce:12.7.4-ce.0

これにちょっとパラメタ追加したり変更して再実行したりするの、まぁめんどいよね、というお話。

docker-composeのインストール

debian系だとaptで入るけど、yumだとリポジトリにないので、公式の手順通りGitHubからダウンロードしてインストールする。

docs.docker.com

$ sudo curl -L "https://github.com/docker/compose/releases/download/1.25.4/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
100   617  100   617    0     0   1720      0 --:--:-- --:--:-- --:--:--  1718
100 16.3M  100 16.3M    0     0  3150k      0  0:00:05  0:00:05 --:--:-- 4093k
$ ls -l /usr/local/bin/docker-compose 
-rw-r--r--. 1 root root 17176256  2月 28 07:12 /usr/local/bin/docker-compose
$ sudo chmod 775 /usr/local/bin/docker-compose
$ docker-compose version
docker-compose version 1.25.4, build 8d51620a
docker-py version: 4.1.0
CPython version: 3.7.5
OpenSSL version: OpenSSL 1.1.0l  10 Sep 2019

Compose fileを書く

みんな大好きYAML
docker runで指定してるパラメタを基本そのまま書けばいい。
-d(--detach)のみはコンテナの動作自体の動作ではなく、docker-composeの引数に指定する必要があるのでここには書かない。

---
version: '3'
services:
  gitlab-registry:
    image: gitlab/gitlab-ce:12.7.4-ce.0
    hostname: gitlab-ce.example.org
    restart: always
    ports:
      - "8443:8443"
      - "25000:25000"
    environment:
      GITLAB_OMNIBUS_CONFIG: "external_url 'https://gitlab-ce.example.org:8443'; nginx['listen_port']=8443; gitlab_rails['registry_enabled']=true; registry_external_url 'https://gitlab-ce.example.org:25000'"
    volumes:
      - /opt/gitlab-reg/config:/etc/gitlab:Z
      - /opt/gitlab-reg/logs:/var/log/gitlab:Z
      - /opt/gitlab-reg/data:/var/opt/gitlab:Z
      - /opt/gitlab-reg/registry:/var/opt/gitlab/gitlab-rails/shared/registry:Z
      - /opt/gitlab-cert:/etc/gitlab/ssl

リファレンスはこちら

docs.docker.com

起動

元コンテナの停止

docker runで既に実行済みのコンテナがあれば止めておく(同じ設定で動かすのでportとかコンフリクトする)

[zaki@registry gitlab]$ sudo docker ps
CONTAINER ID        IMAGE                          COMMAND             CREATED             STATUS                    PORTS                                                                       NAMES
64248b188a0e        gitlab/gitlab-ce:12.7.4-ce.0   "/assets/wrapper"   3 weeks ago         Up 43 minutes (healthy)   22/tcp, 80/tcp, 0.0.0.0:8443->8443/tcp, 443/tcp, 0.0.0.0:25000->25000/tcp   gitlab-registry
[zaki@registry gitlab]$ sudo docker stop gitlab-registry
gitlab-registry
[zaki@registry gitlab]$ sudo docker ps
CONTAINER ID        IMAGE               COMMAND             CREATED             STATUS              PORTS               NAMES
[zaki@registry gitlab]$

docker-compose up

ここで(必要に応じて)-dを付ける

[zaki@registry gitlab]$ sudo /usr/local/bin/docker-compose up -d
Creating network "gitlab_default" with the default driver
Creating gitlab_gitlab-registry_1 ... done
[zaki@registry gitlab]$ sudo docker ps
CONTAINER ID        IMAGE                          COMMAND             CREATED             STATUS                             PORTS                                                                       NAMES
651cc6c71558        gitlab/gitlab-ce:12.7.4-ce.0   "/assets/wrapper"   14 seconds ago      Up 13 seconds (health: starting)   22/tcp, 80/tcp, 0.0.0.0:8443->8443/tcp, 443/tcp, 0.0.0.0:25000->25000/tcp   gitlab_gitlab-registry_1

あとは起動するまで少し待てばOK

[zaki@registry gitlab]$ sudo docker ps
CONTAINER ID        IMAGE                          COMMAND             CREATED             STATUS                   PORTS                                                                       NAMES
651cc6c71558        gitlab/gitlab-ce:12.7.4-ce.0   "/assets/wrapper"   3 minutes ago       Up 2 minutes (healthy)   22/tcp, 80/tcp, 0.0.0.0:8443->8443/tcp, 443/tcp, 0.0.0.0:25000->25000/tcp   gitlab_gitlab-registry_1

停止・その他コマンド

頻度が高いものをピックアップ

composeファイルを編集して再起動(コンテナ再作成)

running状態のままおもむろにdocker-compose upすれば再作成される。便利

# docker-compose up -d
Recreating gitlab_gitlab-registry_1 ... done

Recreatingの通り、起動中だったコンテナは破棄されて、新しいコンテナが起動する。
データを永続化したい場合はvolumes設定をお忘れなく。

停止・削除する(down)

# docker-compose down

コンテナが停止して更に削除される。
(docker ps -aしても残らない)
ホストOSに設定したvolumeは消えないのでご安心を。。

再度実行するにはupする。

ポートのpublish設定など変更する場合はこちら。

停止する(stop)

# docker-compose stop

停止しただけなので、docker ps -aすれば見える。

停止中コンテナの起動(start)

stopされたコンテナを再起動する

# docker-compose start

ログを見る(logs)

# docker-compose logs

特定のコンテナのログのみ見るには、サービス名を指定。

# docker-compose logs gitlab-registry

tail -f的に見るには-f追加。

# docker-compose logs -f

SSH

2020.12.12追記:
ここまでSSHの設定に増えれてなかったので、以下の記事で追加

zaki-hmkc.hatenablog.com

[OpenShift] sccのrunAsUserを使って特定のUIDを指定してpodを実行

root(UID:0)を含む、任意のUIDでpod(の中で動作するプロセス)を動かすには。
基本的にid:nekopさんの記事の通りです。

nekop.hatenablog.com

環境

CRCを使用。あとsccの操作はcluster-admin権限が必要(のはず)。

$ oc version
Client Version: v4.3.0
Server Version: 4.2.13
Kubernetes Version: v1.14.6+a8d983c

あと、OCP v4でoc get sccで各権限のサマリが見れなくなったのは、この辺のcustom-columnsとかで工夫するしかない?

zaki-hmkc.hatenablog.com

前置き

OpenShiftではセキュリティのため、任意のUID(非0)でpodが実行されることが求められる。 通常はネームスペース毎にランダムなUIDのレンジが割り当てられ、その設定によって実行時のUIDが決定される。

$ oc describe project scc-sample
Name:                   scc-sample
Created:                12 seconds ago
Labels:                 <none>
Annotations:            openshift.io/description=
                        openshift.io/display-name=
                        openshift.io/requester=kube:admin
                        openshift.io/sa.scc.mcs=s0:c23,c22
                        openshift.io/sa.scc.supplemental-groups=1000550000/10000
                        openshift.io/sa.scc.uid-range=1000550000/10000
:
:

この出力例でいうと、sa.scc.uid-range=1000550000/10000の部分によって、UIDは1000550000が基準になる。

といっても、何らかの理由で特定のUIDでプロセスを動かしたいという要件もあるかもしれない。

  • コンテナ化するアプリが特定のUIDで実行される前提になっている
  • ウェルノウンポートを使用しており変更できない
  • その他root権限必須

などなど。。

そこで出番なのがSecurity Context Constraints(scc)で、設定を行うことで特定のUIDで動作できるようになる。

access.redhat.com

基本のコマンド

$ oc run sample-app --image=rhel:7.7 -- tail -f /dev/null
$ oc rsh sample-app-1-txzmq bash
bash-4.2$ id
uid=1000550000(1000550000) gid=0(root) groups=0(root),1000550000
bash-4.2$ ps aux
USER         PID %CPU %MEM    VSZ   RSS TTY      STAT START   TIME COMMAND
1000550+       1  0.0  0.0   4412   672 ?        Ss   12:51   0:00 tail -f /dev/null
1000550+      15  0.2  0.0  11836  2920 pts/0    Ss   12:51   0:00 bash
1000550+      23  0.0  0.0  51764  3560 pts/0    R+   12:51   0:00 ps aux

nonrootを使って指定のUID(非0)で動作させる

特定のUID(非0)でpodを実行するには、デフォルトのsccのnonrootを使うことで可能。

作業用プロジェクト作成

$ oc new-project scc-sample-nonroot

デフォルトで使用されるUIDを確認する

$ oc describe projects scc-sample-nonroot
Name:                   scc-sample-nonroot
Created:                21 seconds ago
Labels:                 <none>
Annotations:            openshift.io/description=
                        openshift.io/display-name=
                        openshift.io/requester=kube:admin
                        openshift.io/sa.scc.mcs=s0:c24,c14
                        openshift.io/sa.scc.supplemental-groups=1000580000/10000
                        openshift.io/sa.scc.uid-range=1000580000/10000
Display Name:           <none>
:
:

ServiceAccount/defaultにnonroot権限を付与

$ oc adm policy add-scc-to-user nonroot -z default
securitycontextconstraints.security.openshift.io/nonroot added to: ["system:serviceaccount:scc-sample-nonroot:default"]

設定内容を確認する

$ oc describe scc nonroot
Name:                                           nonroot
Priority:                                       <none>
Access:
  Users:                                        system:serviceaccount:scc-sample-nonroot:default
  Groups:                                       <none>
:
:

デプロイ用のマニフェスト作成

手っ取り早く、前述「基本のコマンド」に対して--dry-run -o yamlを付けて実行した結果をファイルにリダイレクトする:) (status部分は要らないので削除)

apiVersion: apps.openshift.io/v1
kind: DeploymentConfig
metadata:
  creationTimestamp: null
  labels:
    run: sample-app
  name: sample-app
spec:
  replicas: 1
  selector:
    run: sample-app
  strategy:
    resources: {}
  template:
    metadata:
      creationTimestamp: null
      labels:
        run: sample-app
    spec:
      containers:
      - args:
        - tail
        - -f
        - /dev/null
        image: rhel:7.7
        name: sample-app
        resources: {}
  test: false
  triggers: null

このマニフェスト.spec.template以下に、securityContext.runAsUser記述を追記する。 89のとこは実行に使用したいUIDを指定。

      securityContext:
        runAsUser: 89

spec部分を一部抜粋するとこんな感じ

spec:
  {...}
  template:
    {...}
    spec:
      containers:
      - args:
        - tail
        - -f
        - /dev/null
        image: rhel:7.7
        name: sample-app
        resources: {}
      securityContext:
        runAsUser: 89

デプロイ

$ oc apply -f nonroot-deploy.yml 
deploymentconfig.apps.openshift.io/sample-app created
$ oc get all
NAME                      READY   STATUS              RESTARTS   AGE
pod/sample-app-1-deploy   0/1     ContainerCreating   0          2s

NAME                                 DESIRED   CURRENT   READY   AGE
replicationcontroller/sample-app-1   0         0         0       2s

NAME                                            REVISION   DESIRED   CURRENT   TRIGGERED BY
deploymentconfig.apps.openshift.io/sample-app   1          1         0         config

Runningになるまで待つ

$ oc get pod
NAME                  READY   STATUS      RESTARTS   AGE
sample-app-1-deploy   0/1     Completed   0          21s
sample-app-1-xfnkt    1/1     Running     0          11s
$ oc rsh sample-app-1-xfnkt bash
bash-4.2$ 
bash-4.2$ id
uid=89(89) gid=0(root) groups=0(root)
bash-4.2$ ps aux
USER         PID %CPU %MEM    VSZ   RSS TTY      STAT START   TIME COMMAND
89             1  0.0  0.0   4412   696 ?        Ss   13:05   0:00 tail -f /dev/null
89            25  0.0  0.0  11836  3008 pts/0    Ss   13:05   0:00 bash
89            34  0.0  0.0  51764  3500 pts/0    R+   13:05   0:00 ps aux
bash-4.2$ cat /etc/passwd
root:x:0:0:root:/root:/bin/bash
bin:x:1:1:bin:/bin:/sbin/nologin
daemon:x:2:2:daemon:/sbin:/sbin/nologin
adm:x:3:4:adm:/var/adm:/sbin/nologin
lp:x:4:7:lp:/var/spool/lpd:/sbin/nologin
sync:x:5:0:sync:/sbin:/bin/sync
shutdown:x:6:0:shutdown:/sbin:/sbin/shutdown
halt:x:7:0:halt:/sbin:/sbin/halt
mail:x:8:12:mail:/var/spool/mail:/sbin/nologin
operator:x:11:0:operator:/root:/sbin/nologin
games:x:12:100:games:/usr/games:/sbin/nologin
ftp:x:14:50:FTP User:/var/ftp:/sbin/nologin
nobody:x:99:99:Nobody:/:/sbin/nologin
systemd-network:x:192:192:systemd Network Management:/:/sbin/nologin
dbus:x:81:81:System message bus:/:/sbin/nologin
89:x:89:0:89 user:/:/sbin/nologin

runAsUserで指定したUID=89で動作しているのが確認できる。

なお、99(nobody)のように、既に存在するUIDでも動く。

$ oc edit dc sample-app
 (runAsUserの値を変更)
$ oc rsh sample-app-2-6pk9t bash
bash-4.2$ id
uid=99(nobody) gid=99(nobody) groups=99(nobody)

ただし、0(root)は指定してもデプロイに失敗する。

$ oc get event
:
:
3s          Warning   FailedCreate        replicationcontroller/sample-app-3   Error creating: pods "sample-app-3-" is forbidden: unable to validate against any security context constraint: [spec.containers[0].securityContext.securityContext.runAsUser: Invalid value: 0: must be in the ranges: [1000580000, 1000589999] spec.containers[0].securityContext.securityContext.runAsUser: Invalid value: 0: running with the root UID is forbidden]

anyuidを使ってroot(UID:0)を指定して動作

nonrootでなくanyuidを使えば、runAsUser0を指定できる。
手順はnonrootの場合と全く一緒。

準備

$ oc new-project scc-sample-anyuid

ServiceAccount/defaultにanyuidを付与

$ oc adm policy add-scc-to-user anyuid -z default

マニフェスト作成

apiVersion: apps.openshift.io/v1
kind: DeploymentConfig
metadata:
  creationTimestamp: null
  labels:
    run: sample-app
  name: sample-app
spec:
  replicas: 1
  selector:
    run: sample-app
  strategy:
    resources: {}
  template:
    metadata:
      creationTimestamp: null
      labels:
        run: sample-app
    spec:
      containers:
      - args:
        - tail
        - -f
        - /dev/null
        image: rhel:7.7
        name: sample-app
        resources: {}
      securityContext:
        runAsUser: 0
  test: false
  triggers: null

デプロイ

$ oc apply -f anyuid-deploy.yml

podが起動して確認してみると

$ oc rsh sample-app-1-jvc9p bash
[root@sample-app-1-jvc9p /]# id
uid=0(root) gid=0(root) groups=0(root)
[root@sample-app-1-jvc9p /]# ps aux
USER         PID %CPU %MEM    VSZ   RSS TTY      STAT START   TIME COMMAND
root           1  0.3  0.0   4412   684 ?        Ss   13:18   0:00 tail -f /dev/null
root           7  0.3  0.0  11840  3060 pts/0    Ss   13:19   0:00 bash
root          23  0.0  0.0  51764  3436 pts/0    R+   13:19   0:00 ps aux

rootで動いてプロンプトも#になっている。

コンテナごとにID指定

前述の2つの例は、spec.template.spec直下にsecurityContextを定義したので、全コンテナで共通設定になる。 コンテナごとにUIDを指定する場合(あるいは特定のコンテナ以外は指定が不要な場合)は、containers[*]配下に設定すればOK

    spec:
      containers:
      - args:
        - tail
        - -f
        - /dev/null
        image: rhel:7.7
        name: rhel7
        securityContext:
          runAsUser: 0
      - args:
        - tail
        - -f
        - /dev/null
        image: rhscl/perl-526-rhel7:latest
        name: perl
        resources: {}
      - args:
        - tail
        - -f
        - /dev/null
        image: rhscl/python-36-rhel7:latest
        name: python
        resources: {}
        securityContext:
          runAsUser: 5000

確認

[zaki@codeready scc]$ oc rsh -c rhel7 sample-app-2-9lssg bash
[root@sample-app-2-9lssg /]# id
uid=0(root) gid=0(root) groups=0(root)
[root@sample-app-2-9lssg /]# exit
[zaki@codeready scc]$ oc rsh -c perl sample-app-2-9lssg bash
bash-4.2$ id
uid=1001(default) gid=0(root) groups=0(root)
bash-4.2$ exit
[zaki@codeready scc]$ oc rsh -c python sample-app-2-9lssg bash
(app-root) bash-4.2$ id
uid=5000(5000) gid=0(root) groups=0(root)
(app-root) bash-4.2$ exit

perlコンテナのUIDが、プロジェクトのuid-rangeに設定されている桁数のやたら長いランダムなUIDでなく1001になっているのは、ビルドに使われたDockerfileにUSER 1001の指定があるため。たぶん。

privileged(参考)

ちなみにanyuidでもroot権限で動作させることができるが、更に強い権限にprivilegedがある。
これはコンテナ内のプロセスの権限だけでなく、ホストに対するVOLUME設定などあらゆる制限がかかってない状態でpodが動作するので、変な野良コンテナなどで試さないように。

ということで、基本的にはデフォルトのrestrictedで動作するように設計しましょう。


余談:
1年くらい前にrsyslogをpodで動かしたい要件があり、無邪気にrhelコンテナにrsyslog突っ込んだイメージを作ろうとしたら、こいつ/var/runにpidファイルを作ろうするのに、このディレクトリがrootじゃないと書き込めなかったのがそもそもの経緯。
ただしこのときは、特権動作させるのではなく、rsyslogの起動オプション-iでpidファイルの作成先を指定できることが分かったので、/var/tmp辺りに作成して回避して、ずっとpodで特権動作の調査をほったらかしてましたとさ。。。

[kubectl / oc] custom-columnsを指定して欲しい情報だけリストアップする

custom-columnsの簡単な使い方について。

お題

例えばcluster-admin権限でログインしてる状態でoc get sccすると、、、

OCP v4の場合

$ oc get scc
NAME               AGE
anyuid             54d
hostaccess         54d
hostmount-anyuid   54d
hostnetwork        54d
node-exporter      54d
nonroot            54d
privileged         54d
restricted         54d

OCP v3の場合

$ oc get scc
NAME                 PRIV      CAPS      SELINUX     RUNASUSER          FSGROUP     SUPGROUP    PRIORITY   READONLYROOTFS   VOLUMES
anyuid               false     []        MustRunAs   RunAsAny           RunAsAny    RunAsAny    10         false            [configMap downwardAPI emptyDir persistentVolumeClaim projected secret]
hostaccess           false     []        MustRunAs   MustRunAsRange     MustRunAs   RunAsAny    <none>     false            [configMap downwardAPI emptyDir hostPath persistentVolumeClaim projected secret]hostmount-anyuid     false     []        MustRunAs   RunAsAny           RunAsAny    RunAsAny    <none>     false            [configMap downwardAPI emptyDir hostPath nfs persistentVolumeClaim projected secret]
hostnetwork          false     []        MustRunAs   MustRunAsRange     MustRunAs   MustRunAs   <none>     false            [configMap downwardAPI emptyDir persistentVolumeClaim projected secret]
kube-state-metrics   false     []        RunAsAny    RunAsAny           RunAsAny    RunAsAny    <none>     false            [*]
node-exporter        false     []        RunAsAny    RunAsAny           RunAsAny    RunAsAny    <none>     false            [*]
nonroot              false     []        MustRunAs   MustRunAsNonRoot   RunAsAny    RunAsAny    <none>     false            [configMap downwardAPI emptyDir persistentVolumeClaim projected secret]
privileged           true      [*]       RunAsAny    RunAsAny           RunAsAny    RunAsAny    <none>     false            [*]
restricted           false     []        MustRunAs   MustRunAsRange     MustRunAs   RunAsAny    <none>     false            [configMap downwardAPI emptyDir persistentVolumeClaim projected secret]

この情報量の差は一体…

ということで、OCP v4のoc get sccでも、一覧の表示でもう少し欲しい情報を出すにはどうすればいいかについて。

jsonpath(参考)

jsonpathを使った方法はこちら

zaki-hmkc.hatenablog.com

zaki-hmkc.hatenablog.com

ただ、jsonpathを使ったやり方は「対象のピックアップ」だけでなく、「出力時の書式」も指定する必要があるのに加え、ネームスペース上の全リソースを出力みたいなことをやろうとすると、rangeとか出てきて正直言って結構複雑。

ということで、もうちょっと簡単に、項目を選択するだけのcustom-columnsについて。

custom-columns

jsonpath同様にパスを指定するところは同じだけど、対象のパスを指定するだけ。出力の書式はocに任せられる。

ヘルプの実行例

  # List resource information in custom columns.
  oc get pod test-pod -o custom-columns=CONTAINER:.spec.containers[0].name,IMAGE:.spec.containers[0].image

というわけで、まずオブジェクト名のみ出力。

$ oc get scc -o custom-columns=NAME:.metadata.name
NAME
anyuid
hostaccess
hostmount-anyuid
hostnetwork
node-exporter
nonroot
privileged
restricted

これにrunAsUserを追加してみると、、、

$ oc get scc -o custom-columns=NAME:.metadata.name,RUNASUSER:.runAsUser.type
NAME               RUNASUSER
anyuid             RunAsAny
hostaccess         MustRunAsRange
hostmount-anyuid   RunAsAny
hostnetwork        MustRunAsRange
node-exporter      RunAsAny
nonroot            MustRunAsNonRoot
privileged         RunAsAny
restricted         MustRunAsRange

さらに、priorityを追加。

$ oc get scc -o custom-columns=NAME:.metadata.name,RUNASUSER:.runAsUser.type,PRIORITY:.priority
NAME               RUNASUSER          PRIORITY
anyuid             RunAsAny           10
hostaccess         MustRunAsRange     <nil>
hostmount-anyuid   RunAsAny           <nil>
hostnetwork        MustRunAsRange     <nil>
node-exporter      RunAsAny           <nil>
nonroot            MustRunAsNonRoot   <nil>
privileged         RunAsAny           <nil>
restricted         MustRunAsRange     <nil>

こんな感じで、必要なカラムのみ表示できるようになる。

凡例

動かしてみればすぐわかるけど、以下の通り

-o custom-columns=<HEADER-NAME>:<JSON-PATH>

複数の場合は,区切りで。

-o custom-columns=<HEADER-NAME>:<JSON-PATH>,<HEADER-NAME2>:<JSON-PATH2>

[OpenShift] Webhookを使ってGitLab CEへpushされたら自動でS2Iビルド&デプロイする

自前のS2Iスクリプトを使ったイメージビルドをプライベートネットワーク上のGitLab CEのリポジトリ上のソースコードからビルド&デプロイする手順と、更にそれをWebhookを使ってpushをトリガーに自動でビルド&デプロイする設定について。

扱っているソース・やっている内容は前回の記事の続きです。

zaki-hmkc.hatenablog.com

リポジトリからのS2Iビルド自体は以下の記事と同じです。

zaki-hmkc.hatenablog.com

リポジトリにソース一式をpushする

GitLab CEはこの子です。

zaki-hmkc.hatenablog.com

まずGitLab CEでリポジトリを作成。
(以下、普通のGit/GitLab操作です)

f:id:zaki-hmkc:20200221152438p:plain

とりあえずサンプルなのでpublic設定で。

f:id:zaki-hmkc:20200221152545p:plain

ローカルのソースでS2Iした時のファイルpush(*.orgは削除した)。

[zaki@codeready s2isample]$ echo "# S2I sample script" > README.md
[zaki@codeready s2isample]$ find
.
./sockserv.pl
./.s2i
./.s2i/bin
./.s2i/bin/assemble
./.s2i/bin/run
./README.md
[zaki@codeready s2isample]$ git init
Initialized empty Git repository in /home/zaki/src/s2isample/.git/
[zaki@codeready s2isample]$ git remote add origin https://gitlab-ce.example.org:8443/zaki/s2i-sample.git
[zaki@codeready s2isample]$ git add .
[zaki@codeready s2isample]$ git commit -m "Initial commit"
[master (root-commit) af197a1] Initial commit
 4 files changed, 35 insertions(+)
 create mode 100644 .s2i/bin/assemble
 create mode 100644 .s2i/bin/run
 create mode 100644 README.md
 create mode 100644 sockserv.pl
[zaki@codeready s2isample]$ git push -u origin master
Username for 'https://gitlab-ce.example.org:8443': zaki
Password for 'https://zaki@gitlab-ce.example.org:8443': 
Counting objects: 8, done.
Delta compression using up to 4 threads.
Compressing objects: 100% (5/5), done.
Writing objects: 100% (8/8), 873 bytes | 0 bytes/s, done.
Total 8 (delta 0), reused 0 (delta 0)
To https://gitlab-ce.example.org:8443/zaki/s2i-sample.git
 * [new branch]      master -> master
Branch master set up to track remote branch master from origin.

f:id:zaki-hmkc:20200221153351p:plain

ここまでは普通です。
これから、このリポジトリのソースを使ってS2Iします。

ビルド&デプロイ

以下、環境はOKD4.4です。

[zaki@okd4-manager ~]$ oc version
Client Version: 4.4.0-0.okd-2020-01-28-022517
Server Version: 4.4.0-0.okd-2020-01-28-022517
Kubernetes Version: v1.17.1

作業用プロジェクト

[zaki@okd4-manager ~]$ oc login -u zaki
Logged into "https://api.okd4.naru.jp-z.jp:6443" as "zaki" using existing credentials.

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

    oc new-project <projectname>

[zaki@okd4-manager ~]$ oc new-project s2i-git-perl
Now using project "s2i-git-perl" on server "https://api.okd4.naru.jp-z.jp:6443".

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

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

to build a new example application in Python. Or use kubectl to deploy a simple Kubernetes application:

    kubectl create deployment hello-node --image=gcr.io/hello-minikube-zero-install/hello-node

Gitリポジトリの証明書secretを作成

内容はここと一緒です。

[zaki@okd4-manager ~]$ oc create secret generic gitlabcert --from-file=ca.crt=gitlab-cert/gitlab-ce.example.org.crt
secret/gitlabcert created
[zaki@okd4-manager ~]$ oc describe secret gitlabcert 
Name:         gitlabcert
Namespace:    s2i-git-perl
Labels:       <none>
Annotations:  <none>

Type:  Opaque

Data
====
ca.crt:  1822 bytes

new-app

これは足りない例

$ oc new-app https://gitlab-ce.example.org:8443/zaki/s2i-sample.git --source-secret=gitlabcert

カスタムスクリプトで実装している関係で、これだとS2Iによる言語の検知が動作しない(Perlならこのファイルがあるはず、という条件を満たしていない)ので、イメージを指定。

言語の検出については以下のドキュメント参照。

イメージを指定するには、リポジトリの前にイメージ名:tag~を付与。

[zaki@okd4-manager ~]$ oc new-app perl:5.26~https://gitlab-ce.example.org:8443/zaki/s2i-sample.git --source-secret=gitlabcert
--> Found image 57aa6a9 (3 weeks old) in image stream "openshift/perl" under tag "5.26" for "perl:5.26"

    Apache 2.4 with mod_perl/5.26 
    ----------------------------- 
    Perl 5.26 available as container is a base platform for building and running various Perl 5.26 applications and frameworks. Perl is a high-level programming language with roots in C, sed, awk and shell scripting. Perl is good at handling processes and files, and is especially good at handling text. Perl's hallmarks are practicality and efficiency. While it is used to do a lot of different things, Perl's most common applications are system administration utilities and web programming.

    Tags: builder, perl, perl526

    * A source build using source code from https://gitlab-ce.example.org:8443/zaki/s2i-sample.git will be created
      * The resulting image will be pushed to image stream tag "s2i-sample:latest"
      * Use 'oc start-build' to trigger a new build
    * This image will be deployed in deployment config "s2i-sample"
    * Port 8080/tcp will be load balanced by service "s2i-sample"
      * Other containers can access this service through the hostname "s2i-sample"

--> Creating resources ...
    imagestream.image.openshift.io "s2i-sample" created
    buildconfig.build.openshift.io "s2i-sample" created
    deploymentconfig.apps.openshift.io "s2i-sample" created
    service "s2i-sample" created
--> Success
    Build scheduled, use 'oc logs -f bc/s2i-sample' 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/s2i-sample' 
    Run 'oc status' to view your app.

各種リソースが作成される。

[zaki@okd4-manager ~]$ oc get all
NAME                     READY   STATUS     RESTARTS   AGE
pod/s2i-sample-1-build   0/1     Init:0/2   0          6s

NAME                 TYPE        CLUSTER-IP       EXTERNAL-IP   PORT(S)    AGE
service/s2i-sample   ClusterIP   172.30.154.146   <none>        8080/TCP   6s

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

NAME                                        TYPE     FROM   LATEST
buildconfig.build.openshift.io/s2i-sample   Source   Git    1

NAME                                    TYPE     FROM   STATUS    STARTED   DURATION
build.build.openshift.io/s2i-sample-1   Source   Git    Pending             

NAME                                        IMAGE REPOSITORY                                                           TAGS   UPDATED
imagestream.image.openshift.io/s2i-sample   image-registry.openshift-image-registry.svc:5000/s2i-git-perl/s2i-sample          

Gitからソースをpullし、イメージのビルドもnew-appの実行の流れで行われる。

[zaki@okd4-manager ~]$ oc get buildconfig
NAME         TYPE     FROM   LATEST
s2i-sample   Source   Git    1
[zaki@okd4-manager ~]$ oc get build
NAME           TYPE     FROM   STATUS    STARTED   DURATION
s2i-sample-1   Source   Git    Pending             
[zaki@okd4-manager ~]$

しばらくまてば、、

[zaki@okd4-manager ~]$ oc logs build/s2i-sample-1
Cloning "https://gitlab-ce.example.org:8443/zaki/s2i-sample.git" ...
        Commit: af197a1d5eff7a46e46cf227d2e1797642d520c7 (Initial commit)
        Author: zaki <zaki.hmkc@gmail.com>
        Date:   Fri Feb 21 15:32:09 2020 +0900
Caching blobs under "/var/cache/blobs".
Getting image source signatures
Copying blob sha256:455ea8ab06218495bbbcb14b750a0d644897b24f8c5dcf9e8698e27882583412
Copying blob sha256:01ace4f1c1164bbc4513b616c5cff62585fde1dc198b7469c5bc5bc5355941da
Copying blob sha256:4e466ee901fb8e61b18a0b1c172c781c8cb3609060c441a3217b9ebd2cb971cd
Copying blob sha256:bb13d92caffa705f32b8a7f9f661e07ddede310c6ccfa78fb53a49539740e29b
Copying blob sha256:84e620d0abe585d05a7bed55144af0bc5efe083aed05eac1e88922034ddf1ed2
Copying config sha256:57aa6a9e95d366288608f9e224d70922eb6803d78a2e807338cb954d6d1d0629
Writing manifest to image destination
Storing signatures
Generating dockerfile with builder image image-registry.openshift-image-registry.svc:5000/openshift/perl@sha256:4dde5621a54dc0ef542d015b42a9e30d6ed45a185ceec7ae81be5b0da43c9e2c
STEP 1: FROM image-registry.openshift-image-registry.svc:5000/openshift/perl@sha256:4dde5621a54dc0ef542d015b42a9e30d6ed45a185ceec7ae81be5b0da43c9e2c
STEP 2: LABEL "io.openshift.build.commit.ref"="master" "io.openshift.build.commit.message"="Initial commit" "io.openshift.build.image"="image-registry.openshift-image-registry.svc:5000/openshift/perl@sha256:4dde5621a54dc0ef542d015b42a9e30d6ed45a185ceec7ae81be5b0da43c9e2c" "io.openshift.build.commit.author"="zaki <zaki.hmkc@gmail.com>" "io.openshift.build.commit.date"="Fri Feb 21 15:32:09 2020 +0900" "io.openshift.build.commit.id"="af197a1d5eff7a46e46cf227d2e1797642d520c7"
STEP 3: ENV OPENSHIFT_BUILD_NAME="s2i-sample-1" OPENSHIFT_BUILD_NAMESPACE="s2i-git-perl" OPENSHIFT_BUILD_SOURCE="https://gitlab-ce.example.org:8443/zaki/s2i-sample.git" OPENSHIFT_BUILD_COMMIT="af197a1d5eff7a46e46cf227d2e1797642d520c7"
STEP 4: USER root
STEP 5: COPY upload/scripts /tmp/scripts
STEP 6: COPY upload/src /tmp/src
STEP 7: RUN chown -R 1001:0 /tmp/scripts /tmp/src
STEP 8: USER 1001
STEP 9: RUN /tmp/scripts/assemble
STEP 10: CMD /tmp/scripts/run
STEP 11: COMMIT temp.builder.openshift.io/s2i-git-perl/s2i-sample-1:96c53677
Getting image source signatures
Copying blob sha256:35817540a17b5b90cb4426078d53813b16e70c75e1cce3db116d2fbbca7fbf10
Copying blob sha256:c7fbe90ae90e9c6452e5d809f069907907e6f32532565104921f600fb956306c
Copying blob sha256:74d760a83a4b8bcb3d01e7726e06c11469f0bb2ce4645474cb91a607c27bf482
Copying blob sha256:f1cc3f0b20053e48dc0f6505734d2f476e4fcd975df9791164bd749af9332401
Copying blob sha256:8995923ae10d45d1b79c0876141c62b891d258a68c8fc2ed53743acbc076ed5d
Copying blob sha256:bd6b846d7f3b84f9d8e9de2dd380e34a2baff06916e19fbf71394afb66c43736
Copying config sha256:f37c27b818ce7f115147e306f00c8e751af29e9202b92a621f5c6d393e2c2d4a
Writing manifest to image destination
Storing signatures
f37c27b818ce7f115147e306f00c8e751af29e9202b92a621f5c6d393e2c2d4a
f37c27b818ce7f115147e306f00c8e751af29e9202b92a621f5c6d393e2c2d4a

Pushing image image-registry.openshift-image-registry.svc:5000/s2i-git-perl/s2i-sample:latest ...
Getting image source signatures
Copying blob sha256:bd6b846d7f3b84f9d8e9de2dd380e34a2baff06916e19fbf71394afb66c43736
Copying blob sha256:01ace4f1c1164bbc4513b616c5cff62585fde1dc198b7469c5bc5bc5355941da
Copying blob sha256:455ea8ab06218495bbbcb14b750a0d644897b24f8c5dcf9e8698e27882583412
Copying blob sha256:bb13d92caffa705f32b8a7f9f661e07ddede310c6ccfa78fb53a49539740e29b
Copying blob sha256:4e466ee901fb8e61b18a0b1c172c781c8cb3609060c441a3217b9ebd2cb971cd
Copying blob sha256:84e620d0abe585d05a7bed55144af0bc5efe083aed05eac1e88922034ddf1ed2
Copying config sha256:f37c27b818ce7f115147e306f00c8e751af29e9202b92a621f5c6d393e2c2d4a
Writing manifest to image destination
Storing signatures
Successfully pushed image-registry.openshift-image-registry.svc:5000/s2i-git-perl/s2i-sample@sha256:c0cb8460b2dad54b76607978a1267313f22ad3383f325e56a13a7f764ffab4ab
Push successful

イメージのビルドが完了し、内部イメージレジストリへpushされる。

[zaki@okd4-manager ~]$ oc get build
NAME           TYPE     FROM          STATUS     STARTED              DURATION
s2i-sample-1   Source   Git@af197a1   Complete   About a minute ago   1m50s
[zaki@okd4-manager ~]$ 
[zaki@okd4-manager ~]$ oc get pod
NAME                  READY   STATUS              RESTARTS   AGE
s2i-sample-1-build    0/1     Completed           0          2m
s2i-sample-1-deploy   0/1     ContainerCreating   0          9s
[zaki@okd4-manager ~]$ 
[zaki@okd4-manager ~]$ oc get is
NAME         IMAGE REPOSITORY                                                           TAGS     UPDATED
s2i-sample   image-registry.openshift-image-registry.svc:5000/s2i-git-perl/s2i-sample   latest   13 seconds ago

さらに続けてdeploy podも動き出す。

[zaki@okd4-manager ~]$ oc get pod
NAME                  READY   STATUS              RESTARTS   AGE
s2i-sample-1-585bz    0/1     ContainerCreating   0          13s
s2i-sample-1-build    0/1     Completed           0          2m21s
s2i-sample-1-deploy   1/1     Running             0          30s

アプリケーションpodがRunningになる。

[zaki@okd4-manager ~]$ oc get pod
NAME                  READY   STATUS      RESTARTS   AGE
s2i-sample-1-585bz    1/1     Running     0          30s
s2i-sample-1-build    0/1     Completed   0          2m38s
s2i-sample-1-deploy   0/1     Completed   0          47s

アプリケーションpodが動作したので、exposeする。

[zaki@okd4-manager ~]$ oc get svc
NAME         TYPE        CLUSTER-IP       EXTERNAL-IP   PORT(S)    AGE
s2i-sample   ClusterIP   172.30.154.146   <none>        8080/TCP   3m16s
[zaki@okd4-manager ~]$
[zaki@okd4-manager ~]$ oc expose svc/s2i-sample
route.route.openshift.io/s2i-sample exposed
[zaki@okd4-manager ~]$ oc get route
NAME         HOST/PORT                                        PATH   SERVICES     PORT       TERMINATION   WILDCARD
s2i-sample   s2i-sample-s2i-git-perl.apps.okd4.naru.jp-z.jp          s2i-sample   8080-tcp                 None
[zaki@okd4-manager ~]$ 

アクセス

[zaki@okd4-manager ~]$ curl http://s2i-sample-s2i-git-perl.apps.okd4.naru.jp-z.jp
curl: (52) Empty reply from server
[zaki@okd4-manager ~]$ curl -v http://s2i-sample-s2i-git-perl.apps.okd4.naru.jp-z.jp
* About to connect() to s2i-sample-s2i-git-perl.apps.okd4.naru.jp-z.jp port 80 (#0)
*   Trying 172.16.0.50...
* Connected to s2i-sample-s2i-git-perl.apps.okd4.naru.jp-z.jp (172.16.0.50) port 80 (#0)
> GET / HTTP/1.1
> User-Agent: curl/7.29.0
> Host: s2i-sample-s2i-git-perl.apps.okd4.naru.jp-z.jp
> Accept: */*
> 
* Empty reply from server
* Connection #0 to host s2i-sample-s2i-git-perl.apps.okd4.naru.jp-z.jp left intact
curl: (52) Empty reply from server

ん…?

[zaki@okd4-manager s2isample]$ oc rsh s2i-sample-1-585bz bash
bash-4.2$ curl http://localhost:8080
カレーは汗をかくのでスポーツ
curl: (56) Recv failure: Connection reset by peer
bash-4.2$ 

接続まではできてるし、中のアプリは動いてはいるね。

[zaki@okd4-manager ~]$ curl -v http://s2i-sample-s2i-git-perl.apps.okd4.naru.jp-z.jp
* About to connect() to s2i-sample-s2i-git-perl.apps.okd4.naru.jp-z.jp port 80 (#0)
*   Trying 172.16.0.50...
* Connected to s2i-sample-s2i-git-perl.apps.okd4.naru.jp-z.jp (172.16.0.50) port 80 (#0)
> GET / HTTP/1.1
> User-Agent: curl/7.29.0
> Host: s2i-sample-s2i-git-perl.apps.okd4.naru.jp-z.jp
> Accept: */*
> 
< HTTP/1.1 502 Bad Gateway
< content-length: 107
< cache-control: no-cache
< content-type: text/html
< connection: close
< 
<html><body><h1>502 Bad Gateway</h1>
The server returned an invalid or incomplete response.
</body></html>
* Closing connection 0

たまにこういうレスポンスになる。
なんでや…?

そう。ソースコードを見直して思い出したけど、これ「TCPソケットサーバー」であって、別にHTTP喋ってないんですよね。
クライアントから接続があったら、文字列を接続元にただprintしてるだけで、HTTP/1.1 200 OKとかContent-typeとか何も言わずにぶっきらぼうに要件だけ喋っているコミュ障なので、routerで動作しているHAProxyさんがさばいてない状態。
(OpenShiftのrouteは、HTTP/HTTPSを処理する)

ということでバージョン1は「OpenShift的にpodのビルド&デプロイはできてる」けど、「アプリケーションは動作していない」ので、修正します。
※ アプリケーションとしては動いてないけど、oc new-appのみでpodのビルド&デプロイが完了してる。

リビルド

コード修正・push

というわけで、ソケットサーバーにHTTPを喋らせる処理を追加。

[zaki@codeready s2isample]$ git diff
diff --git a/sockserv.pl b/sockserv.pl
index bb81d2b..0843941 100644
--- a/sockserv.pl
+++ b/sockserv.pl
@@ -16,6 +16,8 @@ die "IO::Socket $!" unless $server;
 for (;;) {
     if (my $client = $server->accept()) {
         print "connected from " . $client->peerhost() . "\n";
+        print $client "HTTP/1.1 200 OK\n";
+        print $client "content-type: text/plain\n\n";
         print $client "カレーは汗をかくのでスポーツ\n";
         close $client;
         print "disconected...\n";

commit/pushする。

イメージのリビルド

BuildConfigにリポジトリの情報は含まれている。

[zaki@okd4-manager ~]$ oc describe bc s2i-sample
Name:           s2i-sample
Namespace:      s2i-git-perl
Created:        2 hours ago
Labels:         app=s2i-sample
                app.kubernetes.io/component=s2i-sample
                app.kubernetes.io/instance=s2i-sample
Annotations:    openshift.io/generated-by=OpenShiftNewApp
Latest Version: 1

Strategy:       Source
URL:            https://gitlab-ce.example.org:8443/zaki/s2i-sample.git
Source Secret:  gitlabcert
From Image:     ImageStreamTag openshift/perl:5.26
Output to:      ImageStreamTag s2i-sample:latest

:
:

なので、リビルドするには、start-buildでBuildConfigを指定すればOK

[zaki@okd4-manager ~]$ oc start-build s2i-sample 
build.build.openshift.io/s2i-sample-2 started
[zaki@okd4-manager ~]$ 
[zaki@okd4-manager ~]$ 
[zaki@okd4-manager ~]$ oc get build
NAME           TYPE     FROM          STATUS     STARTED       DURATION
s2i-sample-1   Source   Git@af197a1   Complete   2 hours ago   1m50s
s2i-sample-2   Source   Git           Pending                  
[zaki@okd4-manager ~]$ oc get pod
NAME                  READY   STATUS      RESTARTS   AGE
s2i-sample-1-585bz    1/1     Running     0          98m
s2i-sample-1-build    0/1     Completed   0          100m
s2i-sample-1-deploy   0/1     Completed   0          98m
s2i-sample-2-build    0/1     Init:0/2    0          5s

リポジトリからソースをpullし、イメージをビルド完了すれば、deploy podが起動し、アプリケーションpodを新しいイメージからデプロイする。

[zaki@okd4-manager ~]$ oc get build
NAME           TYPE     FROM          STATUS     STARTED              DURATION
s2i-sample-1   Source   Git@af197a1   Complete   2 hours ago          1m50s
s2i-sample-2   Source   Git@ae51ef0   Complete   About a minute ago   40s
[zaki@okd4-manager ~]$ oc get pod
NAME                  READY   STATUS        RESTARTS   AGE
s2i-sample-1-585bz    1/1     Terminating   0          99m
s2i-sample-1-build    0/1     Completed     0          101m
s2i-sample-1-deploy   0/1     Completed     0          99m
s2i-sample-2-build    0/1     Completed     0          61s
s2i-sample-2-deploy   1/1     Running       0          21s
s2i-sample-2-dzmwb    1/1     Running       0          12s

アプリケーションpodがデプロイまで完了し、Running状態になる。
さて、、、

[zaki@okd4-manager ~]$ curl http://s2i-sample-s2i-git-perl.apps.okd4.naru.jp-z.jp 
カレーは汗をかくのでスポーツ
[zaki@okd4-manager ~]$ curl -v http://s2i-sample-s2i-git-perl.apps.okd4.naru.jp-z.jp 
* About to connect() to s2i-sample-s2i-git-perl.apps.okd4.naru.jp-z.jp port 80 (#0)
*   Trying 172.16.0.50...
* Connected to s2i-sample-s2i-git-perl.apps.okd4.naru.jp-z.jp (172.16.0.50) port 80 (#0)
> GET / HTTP/1.1
> User-Agent: curl/7.29.0
> Host: s2i-sample-s2i-git-perl.apps.okd4.naru.jp-z.jp
> Accept: */*
> 
< HTTP/1.1 200 OK
< content-type: text/plain
< connection: close
< 
カレーは汗をかくのでスポーツ
* Closing connection 0
[zaki@okd4-manager ~]$ 

ちゃんと動きました(・∀・)

Webhook

最後にWebhookの設定。
これは、BuildConfigのトリガーにWebhookを設定することで、リポジトリにpushすることでpodのリビルド&デプロイを行うというもの。

なお、トリガーの設定はoc set triggerでできる。

初期状態

[zaki@okd4-manager ~]$ oc set triggers bc s2i-sample
NAME                     TYPE     VALUE                AUTO
buildconfigs/s2i-sample  config                        true
buildconfigs/s2i-sample  image    openshift/perl:5.26  true
buildconfigs/s2i-sample  webhook  <secret>             
buildconfigs/s2i-sample  github   <secret>  

BuildConfigに設定を追加する

[zaki@okd4-manager ~]$ oc set triggers bc s2i-sample --from-gitlab 
buildconfig.build.openshift.io/s2i-sample triggers updated

BuildConfigの設定はこれだけ。

[zaki@okd4-manager ~]$ oc set triggers bc s2i-sample
NAME                     TYPE     VALUE                AUTO
buildconfigs/s2i-sample  config                        true
buildconfigs/s2i-sample  image    openshift/perl:5.26  true
buildconfigs/s2i-sample  webhook  <secret>             
buildconfigs/s2i-sample  github   <secret>             
buildconfigs/s2i-sample  gitlab   <secret>     

gitlabの設定が追加されている。
BuildConfigの内容は-o yamlで確認すれば以下の部分が追加されている。

   triggers:
   - github:
       secret: ********************
     type: GitHub
   - generic:
       secret: ********************
     type: Generic
   - type: ConfigChange
   - imageChange:
       lastTriggeredImageID: image-registry.openshift-image-registry.svc:5000/openshift/perl@sha256:4dde5621a54dc0ef542d015b42a9e30d6ed45a185ceec7ae81be5b0da43c9e2c
     type: ImageChange
+  - gitlab:
+      secret: ********************
+    type: GitLab

このsecretの値をGitLabの設定で使用する。
また、BuildConfigをoc describeで確認すると、以下のように出力される。

Build Run Policy:       Serial
Triggered by:           Config, ImageChange
Webhook GitLab:
        URL:    https://api.okd4.naru.jp-z.jp:6443/apis/build.openshift.io/v1/namespaces/s2i-git-perl/buildconfigs/s2i-sample/webhooks/<secret>/gitlab
Webhook GitHub:
        URL:    https://api.okd4.naru.jp-z.jp:6443/apis/build.openshift.io/v1/namespaces/s2i-git-perl/buildconfigs/s2i-sample/webhooks/<secret>/github
Webhook Generic:
        URL:            https://api.okd4.naru.jp-z.jp:6443/apis/build.openshift.io/v1/namespaces/s2i-git-perl/buildconfigs/s2i-sample/webhooks/<secret>/generic
        AllowEnv:       false
Builds History Limit:
        Successful:     5
        Failed:         5

この中の、Webhook GitLabのURLの<secret>となっている個所に、前述-o yamlで確認したsecretの値に置き換えたURLをGitLab CEに設定する。

GitLabにWebhookの設定追加

初めに作成したs2i-sampleプロジェクトをGitLab CEで開き、メニューの"Settings"->"Integrations"を開く。

f:id:zaki-hmkc:20200221190138p:plain

設定画面のURLに、前述のsecret込みURLを入力する。
(字が似てるので、間違えてGitHubの値を混ぜないように注意。私はこれで時間を溶かしました)

それ以外にTriggerのチェックは設定変更無し・Enable SSL verificationは(OpenShiftクラスタの証明書をGitLab CEリポジトリ側に設定していなければ)チェックを外し、ページの中央付近にある"Add webhook"を押下。


※ GitLab CEでは、ローカルネットワークでのWebhookはデフォルト禁止になっているため、以下のエラーが出る場合は、admin設定で制限を外す必要がある。

Url is blocked: Requests to the local network are not allowed

taikii.net

f:id:zaki-hmkc:20200221191906p:plain

これにチェックしておく。


Webhookが追加されたら、Push eventsのTestを行う。

f:id:zaki-hmkc:20200221192329p:plain

設定がうまくいっていれば、200 OKになる。

f:id:zaki-hmkc:20200221192438p:plain

これで準備OK

というかこのTestでダミーのpush eventが発行されているので、OpenShift側ではBuildConfigの設定によってこのイベントを検知し、リポジトリからソースをpullしてイメージのリビルド・デプロイが行われている。

[zaki@okd4-manager ~]$ oc get pod
NAME                  READY   STATUS      RESTARTS   AGE
s2i-sample-1-build    0/1     Completed   0          3h16m
s2i-sample-1-deploy   0/1     Completed   0          3h14m
s2i-sample-2-build    0/1     Completed   0          95m
s2i-sample-2-deploy   0/1     Completed   0          95m
s2i-sample-3-build    0/1     Completed   0          4m27s
s2i-sample-3-deploy   0/1     Completed   0          3m44s
s2i-sample-3-nwsxg    1/1     Running     0          3m35s
[zaki@okd4-manager ~]$ oc get dc
NAME         REVISION   DESIRED   CURRENT   TRIGGERED BY
s2i-sample   3          1         1         config,image(s2i-sample:latest)

バージョンが2になっている。

コードを修正しpushする

というわけで本番。
また分かりやすいように文言を更新。

[zaki@codeready s2isample]$ git diff
diff --git a/sockserv.pl b/sockserv.pl
index 0843941..7961e7e 100644
--- a/sockserv.pl
+++ b/sockserv.pl
@@ -18,7 +18,7 @@ for (;;) {
         print "connected from " . $client->peerhost() . "\n";
         print $client "HTTP/1.1 200 OK\n";
         print $client "content-type: text/plain\n\n";
-        print $client "カレーは汗をかくのでスポーツ\n";
+        print $client "カレーは時に甘く時に辛いので人生\n";
         close $client;
         print "disconected...\n";
     }

commit & pushする。

[zaki@codeready s2isample]$ git add sockserv.pl
[zaki@codeready s2isample]$ git commit -m "update: 文言変更"
[zaki@codeready s2isample]$ git push

これだけ。 Gitにpushするだけで、新しいBuildが動き出す

[zaki@okd4-manager ~]$ oc get build
NAME           TYPE     FROM          STATUS     STARTED          DURATION
s2i-sample-1   Source   Git@af197a1   Complete   3 hours ago      1m50s
s2i-sample-2   Source   Git@ae51ef0   Complete   2 hours ago      40s
s2i-sample-3   Source   Git@af197a1   Complete   10 minutes ago   42s
s2i-sample-4   Source   Git@5c7b4f5   Pending      
[zaki@okd4-manager ~]$ oc get pod
NAME                  READY   STATUS      RESTARTS   AGE
s2i-sample-1-build    0/1     Completed   0          3h22m
s2i-sample-1-deploy   0/1     Completed   0          3h20m
s2i-sample-2-build    0/1     Completed   0          101m
s2i-sample-2-deploy   0/1     Completed   0          101m
s2i-sample-3-build    0/1     Completed   0          10m
s2i-sample-3-deploy   0/1     Completed   0          9m46s
s2i-sample-3-nwsxg    1/1     Running     0          9m37s
s2i-sample-4-build    0/1     Init:1/2    0          10s

しばらく待てば

[zaki@okd4-manager ~]$ oc get pod
NAME                  READY   STATUS              RESTARTS   AGE
s2i-sample-1-build    0/1     Completed           0          3h22m
s2i-sample-1-deploy   0/1     Completed           0          3h20m
s2i-sample-2-build    0/1     Completed           0          102m
s2i-sample-2-deploy   0/1     Completed           0          101m
s2i-sample-3-build    0/1     Completed           0          11m
s2i-sample-3-deploy   0/1     Completed           0          10m
s2i-sample-3-nwsxg    1/1     Running             0          10m
s2i-sample-4-build    0/1     Completed           0          45s
s2i-sample-4-deploy   0/1     ContainerCreating   0          3s
[zaki@okd4-manager ~]$
[zaki@okd4-manager ~]$ oc get pod
NAME                  READY   STATUS        RESTARTS   AGE
s2i-sample-1-build    0/1     Completed     0          3h23m
s2i-sample-1-deploy   0/1     Completed     0          3h21m
s2i-sample-2-build    0/1     Completed     0          102m
s2i-sample-2-deploy   0/1     Completed     0          102m
s2i-sample-3-build    0/1     Completed     0          11m
s2i-sample-3-deploy   0/1     Completed     0          10m
s2i-sample-3-nwsxg    1/1     Terminating   0          10m
s2i-sample-4-build    0/1     Completed     0          71s
s2i-sample-4-deploy   0/1     Completed     0          29s
s2i-sample-4-mk5s4    1/1     Running       0          20s

また新しいpodがRunningになった。

webアクセスすると

[zaki@okd4-manager ~]$ curl http://s2i-sample-s2i-git-perl.apps.okd4.naru.jp-z.jp
カレーは時に甘く時に辛いので人生

新しいバージョンになりました。


まとめ

ということで、Webhookの設定を行ったBuildConfigとGitリポジトリを組み合わせることで、ocコマンドを使ったオペレーション無しに任意のアプリケーションをビルド&デプロイできるようになりました。
またGitLab CEを使うことで、クローズドな環境のリポジトリでも利用できます。

これがGitOpsの入り口なんですね…

f:id:zaki-hmkc:20200221194950p:plain

[OpenShift]自作のS2Iスクリプトを使ってローカルにあるPerlスクリプトをS2Iビルドしてデプロイする

単体で動作するPerlスクリプトをS2I使ってビルド&デプロイする。
環境はCodeReady Containers (OpenShift v4.3)ですが、OKD 3.11でも同じ。

[zaki@codeready s2isample]$ crc version
crc version: 1.4.0+d5bb3a3
OpenShift version: 4.2.13 (embedded in binary)
[zaki@codeready s2isample]$ 
[zaki@codeready s2isample]$ oc version
Client Version: v4.3.0
Kubernetes Version: v1.14.6+a8d983c

S2Iについて

詳しく説明されている方が何人もいらっしゃるのでそちらを参考してください。。

qiita.com

nekop.hatenablog.com

enakai00.hatenablog.com

一言で言うと、Dockerfileを使わずにコンテナイメージをビルドする仕組みです。
Dockerfileの完全な代替になるかというと、そうではないですが、

  • イメージ作成前の処理(ソースコードから実行バイナリをビルドしたり)
  • イメージ内のファイル構成(必要なパッケージをyumしたり↑のバイナリを配置したりスクリプトコピーしたり)
  • コンテナデプロイ時に実行する処理(CMDから呼ばれるスクリプトの実装)

といったことをS2Iで実現できます。
逆に、

  • Listenするポート番号を指定(EXPOSE)
  • Volumeを指定(VOLUME)

のようにイメージそのもののメタな設定はS2Iでは(たぶん)行えません。
これは、S2Iビルドする際のベースイメージ側で設定しておきます。(本記事ではこちらは扱いません)

OpenShiftではデフォルトでS2Iの仕組みを利用でき、S2Iが期待している構成をしているアプリケーションであれば、oc new-appでpodをデプロイする際にそのアプリケーションのリポジトリを指定するだけで勝手にビルド&デプロイを行うことができる便利なツールです。

例えばこんな感じ

zaki-hmkc.hatenablog.com

ただし、S2Iが期待している構成で動作するため、JavaEEみたいにビルド(mvnとか)とデプロイのファイル構成などにお作法があるものだと標準のものが使えますが、単体でHTTP ListenするPerlスクリプトなんかだと、標準で用意されている(S2Iにも対応した)Perlイメージリポジトリを指定するだけだと使えなかったりします。(というのもこのイメージはhttpd内蔵でPerlスクリプトCGIとして動作するっぽい?)

というわけで前置きが長くなったけど、この記事では「既存のイメージを使って、自作のS2Iスクリプトで期待するビルド&デプロイ動作をするイメージを作成」するにはどするかについて説明します。

使用するイメージは、クラスタデプロイ時にopenshift/perlとしてImageStreamが用意されている、前述のrhscl/perl-526-rhel7です。(Perlといいつつこれ"Apache 2.4 with mod_perl/5.26"なのでHTTPサーバーのイメージだけど)

また、このイメージは8080でListenする設定になっているので、使うポート番号は8080限定です。(変更が必要な場合はベースイメージの作成が必要)

なお、本記事では話を単純にするためにsave-artifactsについては説明しません。

作業用プロジェクト作成

[zaki@codeready s2isample]$ oc login -u developer -p developer https://api.crc.testing:6443
Login successful.

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

    oc new-project <projectname>

[zaki@codeready s2isample]$ oc new-project  s2i-sample
Now using project "s2i-sample" on server "https://api.crc.testing:6443".

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

    oc new-app django-psql-example

to build a new example application in Python. Or use kubectl to deploy a simple Kubernetes application:

    kubectl create deployment hello-node --image=gcr.io/hello-minikube-zero-install/hello-node

ソース

アプリケーションpodで実行するスクリプト
sockserv.plという名前で次のPerlスクリプトを作成する。

#!/usr/bin/perl

use IO::Socket;
use strict;

my $server = new IO::Socket::INET(
    Listen => 3,
    LocalAddr => '0.0.0.0',
    LocalPort => 8080,
    Proto => 'tcp',
    Reuse => 1
    );

die "IO::Socket $!" unless $server;

for (;;) {
    if (my $client = $server->accept()) {
        print "connected from " . $client->peerhost() . "\n";
        print $client "カレーは粉でできてるのでカロリーゼロ\n";
        close $client;
        print "disconected...\n";
    }
}
close $server;
exit;

S2Iスクリプト

ここからS2I固有の作り込みだけど、nekopさんのブログにも説明がある通り、作りは単純です。

  1. --scripts-url指定のディレクト
  2. .sti/binディレクト
  3. label io.openshift.s2i.scripts-urlで指定のディレクト

の順序で、S2Iのスクリプトがあるかどうかを検査し、見つかった時点でそのパスにあるスクリプトを使用します。
Perlのベースイメージでは、io.openshift.s2i.scripts-urlにimage:///usr/libexec/s2iの指定があり、イメージ内の/usr/libexec/s2iディレクトリ以下にあるスクリプトが使用されます。(これは任意のpodをPerlのベースイメージでデプロイし、oc rshなどで確認できます)

今回はこれを使わずに、自前のS2Iスクリプトを使ってビルドしたいので、この指定より優先度の高い.s2i/binディレクトリを用意します。

[zaki@codeready s2isample]$ mkdir -p .s2i/bin

簡単ですね。このディレクトリに次のスクリプトを作成します。

assemble

今回はスクリプトファイル単体で動作するpodを作りたいので、スクリプトファイルをコンテナ内に配置するのみです。
実行時に配置したスクリプトファイルをフルパス指定するので、配置先はどこでも良いです。

ただし配置時のコピー元は、イメージビルド時にはまず/tmp/srcにホストOSからコピーされるため、ここから配置することになります。

[zaki@codeready s2isample]$ cat .s2i/bin/assemble 
#!/bin/bash

APP_ROOT=/opt/app-root/src
SRC=/tmp/src

cp -a $SRC/* $APP_ROOT/

run

コンテナデプロイ時に呼ばれるスクリプトです。
今回のPerlスクリプトは単体で動作するため、単純にperlコマンドの引数に指定しています。
(試してないけど、実行権限つけてスクリプトファイルのみ指定でも多分動く)

[zaki@codeready s2isample]$ cat .s2i/bin/run 
#!/bin/bash

perl /opt/app-root/src/sockserv.pl

イメージのビルド

BuildConfig作成

[zaki@codeready s2isample]$ oc new-build --image-stream=openshift/perl:5.26 --name=sample
error: you must specify at least one source repository URL, provide a Dockerfile, or indicate you wish to use binary builds

未指定だとダメ。

[zaki@codeready s2isample]$ oc new-build --image-stream=openshift/perl:5.26 --name=sample --binary
--> Found image acdb469 (2 months old) in image stream "openshift/perl" under tag "5.26" for "openshift/perl:5.26"

    Apache 2.4 with mod_perl/5.26 
    ----------------------------- 
    Perl 5.26 available as container is a base platform for building and running various Perl 5.26 applications and frameworks. Perl is a high-level programming language with roots in C, sed, awk and shell scripting. Perl is good at handling processes and files, and is especially good at handling text. Perl's hallmarks are practicality and efficiency. While it is used to do a lot of different things, Perl's most common applications are system administration utilities and web programming.

    Tags: builder, perl, perl526

    * A source build using binary input will be created
      * The resulting image will be pushed to image stream tag "sample:latest"
      * A binary build was created, use 'oc start-build --from-dir' to trigger a new build

--> Creating resources with label build=sample ...
    imagestream.image.openshift.io "sample" created
    buildconfig.build.openshift.io "sample" created
--> Success

BuildConfigとImageStreamが作成された。

[zaki@codeready s2isample]$ oc get all
NAME                                    TYPE     FROM     LATEST
buildconfig.build.openshift.io/sample   Source   Binary   0

NAME                                    IMAGE REPOSITORY                                                            TAGS   UPDATED
imagestream.image.openshift.io/sample   default-route-openshift-image-registry.apps-crc.testing/s2i-sample/sample

build実行

ディレクトリ構造はこの通り

[zaki@codeready s2isample]$ tree -a
.
├── .s2i
│   └── bin
│       ├── assemble
│       └── run
└── sockserv.pl

2 directories, 3 files

ビルド開始

[zaki@codeready s2isample]$ oc start-build sample --from-dir=.
Uploading directory "." as binary input for the build ...
..
Uploading finished
build.build.openshift.io/sample-1 started

build podが起動。

[zaki@codeready s2isample]$ oc get pod
NAME             READY   STATUS    RESTARTS   AGE
sample-1-build   1/1     Running   0          14s

ビルドログはBuildリソースに対してoc logsで確認できる。(処理中の場合は-fすれば良い)

[zaki@codeready s2isample]$ oc get build
NAME       TYPE     FROM     STATUS    STARTED          DURATION
sample-1   Source   Binary   Running   17 seconds ago   
[zaki@codeready s2isample]$ oc logs build/sample-1
Receiving source from STDIN as archive ...
Caching blobs under "/var/cache/blobs".
Getting image source signatures
Copying blob sha256:ebd3f573bf3070c27e95131569c9cadc0b791dfef6996010348fb5ed17853aa2
Copying blob sha256:4fbc3bafa3d4400bb97a733c1fe12f2f99bf38b9d5b913d5034f29798739654d
Copying blob sha256:e778df67329e8784693961cf548c61861486b53c86af171baef51fe1e93ba6cb
Copying blob sha256:34971b2d1eb98e410c2802e6bb3a7f499f9c5bff1b870ed329089ecdb21cf856
Copying blob sha256:1cd26fbb2b2181a18c41ece85dff8b293e399e50dc3abe227b1940450bf6298b
Copying config sha256:acdb46932f4b462ef9268ed012f05fed711aea57a0bbeb8b405547bb8b454c65
Writing manifest to image destination
Storing signatures
Generating dockerfile with builder image image-registry.openshift-image-registry.svc:5000/openshift/perl@sha256:9ce4be160b024ba1a98b87f568ab26361251001370951e0c06f057f8d27fb2ae
STEP 1: FROM image-registry.openshift-image-registry.svc:5000/openshift/perl@sha256:9ce4be160b024ba1a98b87f568ab26361251001370951e0c06f057f8d27fb2ae
STEP 2: LABEL "io.openshift.build.image"="image-registry.openshift-image-registry.svc:5000/openshift/perl@sha256:9ce4be160b024ba1a98b87f568ab26361251001370951e0c06f057f8d27fb2ae" "io.openshift.build.source-location"="/tmp/build/inputs"
STEP 3: ENV OPENSHIFT_BUILD_NAME="sample-1" OPENSHIFT_BUILD_NAMESPACE="s2i-sample"
STEP 4: USER root
STEP 5: COPY upload/scripts /tmp/scripts
STEP 6: COPY upload/src /tmp/src
STEP 7: RUN chown -R 1001:0 /tmp/scripts /tmp/src
time="2020-02-20T11:30:33Z" level=warning msg="pkg/chroot: error unmounting \"/tmp/buildah069784024/mnt/rootfs\": error checking if \"/tmp/buildah069784024/mnt/rootfs/sys/fs/cgroup/memory\" is mounted: no such file or directory"
time="2020-02-20T11:30:33Z" level=warning msg="pkg/bind: error unmounting \"/tmp/buildah069784024/mnt/rootfs\": error checking if \"/tmp/buildah069784024/mnt/rootfs/sys/fs/cgroup/memory\" is mounted: no such file or directory"
STEP 8: USER 1001
STEP 9: RUN /tmp/scripts/assemble
time="2020-02-20T11:30:34Z" level=warning msg="pkg/chroot: error unmounting \"/tmp/buildah171662949/mnt/rootfs\": error checking if \"/tmp/buildah171662949/mnt/rootfs/sys/fs/cgroup/memory\" is mounted: no such file or directory"
time="2020-02-20T11:30:34Z" level=warning msg="pkg/bind: error unmounting \"/tmp/buildah171662949/mnt/rootfs\": error checking if \"/tmp/buildah171662949/mnt/rootfs/sys/fs/cgroup/memory\" is mounted: no such file or directory"
STEP 10: CMD /tmp/scripts/run
STEP 11: COMMIT temp.builder.openshift.io/s2i-sample/sample-1:380cc258
Getting image source signatures
Copying blob sha256:5a92562cd21a35fc8c0ee33c58d88c5b6c1417cde40a2a83e630232435c4c1d5
Copying blob sha256:18ea39fd2965157d2f9011362919a340e134b5a053ebeca62a118f90983cbd58
Copying blob sha256:ac49297ec1c627dbf5c8cd6c447675489ec3550e7651534344bb9f27c4dae6db
Copying blob sha256:6953a567dfff60c737bdf8e0d614b2474d472a62ef7263e9bd704570116bbc7b
Copying blob sha256:133a5862e485a4ab3527e93d2b2bd8cacab1ce7d7a48c2c6d3bc869f8ccd11df
Copying blob sha256:d58f12a4557c807a0550f122c47654824d5f5796b0d45a276cfb6fabe6254225
Copying config sha256:d000858f0572b8217edf7a33cdb13db49380cc7536a860c3b93476ce1e6958d8
Writing manifest to image destination
Storing signatures
d000858f0572b8217edf7a33cdb13db49380cc7536a860c3b93476ce1e6958d8

Pushing image image-registry.openshift-image-registry.svc:5000/s2i-sample/sample:latest ...
Getting image source signatures
Copying blob sha256:d58f12a4557c807a0550f122c47654824d5f5796b0d45a276cfb6fabe6254225
Copying blob sha256:e778df67329e8784693961cf548c61861486b53c86af171baef51fe1e93ba6cb
Copying blob sha256:1cd26fbb2b2181a18c41ece85dff8b293e399e50dc3abe227b1940450bf6298b
Copying blob sha256:34971b2d1eb98e410c2802e6bb3a7f499f9c5bff1b870ed329089ecdb21cf856
Copying blob sha256:ebd3f573bf3070c27e95131569c9cadc0b791dfef6996010348fb5ed17853aa2
Copying blob sha256:4fbc3bafa3d4400bb97a733c1fe12f2f99bf38b9d5b913d5034f29798739654d
Copying config sha256:d000858f0572b8217edf7a33cdb13db49380cc7536a860c3b93476ce1e6958d8
Writing manifest to image destination
Storing signatures
Successfully pushed image-registry.openshift-image-registry.svc:5000/s2i-sample/sample@sha256:d30a49e68a52c51de4c09d62a7d6c95b83df329b221d9c0d78f0e966ac98b1e5
Push successful

ビルドが完了するとイメージが内部レジストリ(default/docker-registry)へpushされる。 Push successfulが出力されていれば正常に完了している。 ここまで確認できれば、build podも処理完了となる。

[zaki@codeready s2isample]$ oc get pod
NAME             READY   STATUS      RESTARTS   AGE
sample-1-build   0/1     Completed   0          100s
[zaki@codeready s2isample]$ oc get all
NAME                 READY   STATUS      RESTARTS   AGE
pod/sample-1-build   0/1     Completed   0          103s

NAME                                    TYPE     FROM     LATEST
buildconfig.build.openshift.io/sample   Source   Binary   1

NAME                                TYPE     FROM     STATUS     STARTED              DURATION
build.build.openshift.io/sample-1   Source   Binary   Complete   About a minute ago   43s

NAME                                    IMAGE REPOSITORY                                                            TAGS     UPDATED
imagestream.image.openshift.io/sample   default-route-openshift-image-registry.apps-crc.testing/s2i-sample/sample   latest   About a minute ago

ImageStreamも更新されている。

アプリのデプロイ

デプロイ

[zaki@codeready s2isample]$ oc new-app sample
--> Found image d000858 (2 minutes old) in image stream "s2i-sample/sample" under tag "latest" for "sample"

    Apache 2.4 with mod_perl/5.26 
    ----------------------------- 
    Perl 5.26 available as container is a base platform for building and running various Perl 5.26 applications and frameworks. Perl is a high-level programming language with roots in C, sed, awk and shell scripting. Perl is good at handling processes and files, and is especially good at handling text. Perl's hallmarks are practicality and efficiency. While it is used to do a lot of different things, Perl's most common applications are system administration utilities and web programming.

    Tags: builder, perl, perl526

    * This image will be deployed in deployment config "sample"
    * Port 8080/tcp will be load balanced by service "sample"
      * Other containers can access this service through the hostname "sample"

--> Creating resources ...
    deploymentconfig.apps.openshift.io "sample" created
    service "sample" created
--> Success
    Application is not exposed. You can expose services to the outside world by executing one or more of the commands below:
     'oc expose svc/sample' 
    Run 'oc status' to view your app.

deploy pod(pod/sample-1-deploy)がまず起動し、アプリケーションpod(下の出力であればpod/sample-1-8m17z)がデプロイされる。

[zaki@codeready s2isample]$ oc get dc,rc,pod,svc
NAME                                        REVISION   DESIRED   CURRENT   TRIGGERED BY
deploymentconfig.apps.openshift.io/sample   1          1         1         config,image(sample:latest)

NAME                             DESIRED   CURRENT   READY   AGE
replicationcontroller/sample-1   1         1         1       37s

NAME                  READY   STATUS      RESTARTS   AGE
pod/sample-1-8ml7z    1/1     Running     0          28s
pod/sample-1-build    0/1     Completed   0          3m49s
pod/sample-1-deploy   0/1     Completed   0          37s

NAME             TYPE        CLUSTER-IP      EXTERNAL-IP   PORT(S)    AGE
service/sample   ClusterIP   172.30.31.179   <none>        8080/TCP   37s

podがRunningになれば成功

route作成

[zaki@codeready s2isample]$ oc expose svc/sample
route.route.openshift.io/sample exposed
[zaki@codeready s2isample]$ oc get route
NAME     HOST/PORT                            PATH   SERVICES   PORT       TERMINATION   WILDCARD
sample   sample-s2i-sample.apps-crc.testing          sample     8080-tcp                 None

動作確認

[zaki@codeready s2isample]$ curl http://sample-s2i-sample.apps-crc.testing
カレーは粉でできてるのでカロリーゼロ

期待通りの動作

アプリの更新

ソースコードを変更し、リビルドするには。

ソースの更新

ちょっと文言を更新します。

[zaki@codeready s2isample]$ diff -u sockserv.pl.org sockserv.pl
--- sockserv.pl.org     2020-02-20 20:25:31.230606041 +0900
+++ sockserv.pl 2020-02-20 20:38:27.725759274 +0900
@@ -16,7 +16,7 @@
 for (;;) {
     if (my $client = $server->accept()) {
         print "connected from " . $client->peerhost() . "\n";
-        print $client "カレーは粉でできてるのでカロリーゼロ\n";
+        print $client "カレーは汗をかくのでスポーツ\n";
         close $client;
         print "disconected...\n";
     }

リビルド

[zaki@codeready s2isample]$ oc start-build sample --from-dir=.
Uploading directory "." as binary input for the build ...
..
Uploading finished
build.build.openshift.io/sample-2 started

--from-dirは必要(無いとイメージに転送するファイルを特定できないためエラーになる)

新しいバージョンのbuild podが実行され、イメージがビルドされる。

[zaki@codeready s2isample]$ oc get build
NAME       TYPE     FROM     STATUS     STARTED          DURATION
sample-1   Source   Binary   Complete   9 minutes ago    43s
sample-2   Source   Binary   Running    12 seconds ago   

しばらく待てばビルド完了

[zaki@codeready s2isample]$ oc get build
NAME       TYPE     FROM     STATUS     STARTED          DURATION
sample-1   Source   Binary   Complete   10 minutes ago   43s
sample-2   Source   Binary   Complete   49 seconds ago   43s

ビルド完了と共に新しいイメージが内部レジストリへpushさる。
その際にDeploymentConfigのTriggerにimageが設定されているため、「イメージが更新された」というトリガーによってアプリケーションpodも再作成される。

[zaki@codeready s2isample]$ oc get dc
NAME     REVISION   DESIRED   CURRENT   TRIGGERED BY
sample   2          1         1         config,image(sample:latest)
[zaki@codeready s2isample]$ oc get pod
NAME              READY   STATUS              RESTARTS   AGE
sample-1-8ml7z    1/1     Running             0          6m55s
sample-1-build    0/1     Completed           0          10m
sample-1-deploy   0/1     Completed           0          7m4s
sample-2-build    0/1     Completed           0          53s
sample-2-deploy   1/1     Running             0          10s
sample-2-xx796    0/1     ContainerCreating   0          1s
[zaki@codeready s2isample]$ oc get pod
NAME              READY   STATUS        RESTARTS   AGE
sample-1-8ml7z    1/1     Terminating   0          7m22s
sample-1-build    0/1     Completed     0          10m
sample-1-deploy   0/1     Completed     0          7m31s
sample-2-build    0/1     Completed     0          80s
sample-2-deploy   0/1     Completed     0          37s
sample-2-xx796    1/1     Running       0          28s

結果、podも新しいバージョン(sample-2-xvwld)となり、start-buildによるイメージのビルドからpodデプロイまでが自動で行われる。

[zaki@codeready s2isample]$ curl http://sample-s2i-sample.apps-crc.testing
カレーは汗をかくのでスポーツ

新しいソースコードでアプリケーションpodが動作している。


これだけだと「ふーん、、で…?」という感じが少ししますが、これをGitリポジトリと連携・さらにWebhookを設定すれば、ソースをリポジトリへpushすれば最新のソースコードでアプリケーションpodをリビルド&デプロイ、という構成を作れるようになるので、それは次の記事で。

zaki-hmkc.hatenablog.com


今日のOpenShiftウェビナー第3回でも、ちょうどコンテナアプリケーションのビルド&デプロイのお話がありS2Iも出てくるので、ご参考ください。

www.redhat.com