JenkinsパイプラインからSkaffoldでCI/CDしてみる

f:id:fclout:20200627212859p:plain

今回はDevopsネタです。
JenkinsパイプラインからSkaffoldを使ってアプリケーションをCI/CDしてみます。

前提

Kubernetesクラスタが構築されていることが前提です。
JenkinsはHelmを使って導入します。


Kubernetesクラスタの構築(オンプレ-kubeadm)方法は以下を参考にしてください。
github.com


やりたいこと

開発環境でのCI/CD効率を上げるために、
Githubへコミット後の、ビルド・プッシュ・デプロイ・ユニットテストを自動化します。
一連の流れはJenkinsパイプラインを使用します。
その中でdockerイメージのビルド・プッシュ・デプロイはSkaffoldを使用します。


今回はサンプルのアプリとして以下のリポジトリを使いたいと思います。
github.com

後述するjenkinsfileやskaffold.yamlも入っています



Skaffoldコンテナイメージを用意する

今回はJenkinsのkubernetesプラグインを使って、
Skaffoldコンテナを用意して、その中でビルド・プッシュ・デプロイを実施します。

Skaffoldの概要とコンテナ構築方法については以下を参考にしてください。
fclout.hateblo.jp


Jenkinsを用意する

次にkubernetesコンテナにJenkinsをデプロイします。
今回はHelm(stable/jenkins)を使います。

kubectl apply -f ./systems/pv-jenkins.yaml
helm install -f ./systems/helm-jenkins.yaml --name myjenkins --namespace $NS stable/jenkins
kubectl port-forward svc/myjenkins -n $NS 8005:8080 --address 0.0.0.0 &


デプロイとポートフォワードが完了するとブラウザ画面でhttp://localhost:8005でJenkinsにアクセスできます。
ログイン用のパスワードは以下のコマンドで入手できます。

# printf $(kubectl get secret --namespace myblog-system myjenkins -o jsonpath="{.data.jenkins-admin-password}" | base64 --decode);echo
VMIyMoLy3K

Jenkinsパイプラインを作成する

Jenkinsfileを作成する

次にCI/CDするためのパイプラインを作成します。
GithubへのコミットをwebhookさせるためのJenkinsfileを作成します。


パイプラインの中では大まかに以下のことをします。

1. Skaffoldコンテナのデプロイ
1. コンテナ内でのSkaffold Runの実行

これだけです。
前述したDockerイメージのビルドやデプロイ等はすべてskaffold.yamlで記載します。
以下がJenkinsfileの記載例です。

podTemplate(
  label: 'skaffold',
  containers: [
    containerTemplate(name: 'skaffold-insider', image: 'ultimania/skaffold', ttyEnabled: true, command: 'cat')
  ],
  volumes: [
    hostPathVolume(hostPath: '/var/run/docker.sock', mountPath: '/var/run/docker.sock')
  ]
) {
  node('skaffold') {
    withCredentials([
      usernamePassword(credentialsId: 'docker_id', usernameVariable: 'DOCKER_ID_USR', passwordVariable: 'DOCKER_ID_PSW')
    ]) {
      stage('Info') {
        container('skaffold-insider') {
          sh """
            uname -a
            whoami
            pwd
            ls -al
            env
          """
        }
      }
      stage('Image Build & Push by skaffold') {
        git 'https://github.com/ultimania/myblog'
        container('skaffold-insider') {
          sh """
            docker login --username=$DOCKER_ID_USR --password=$DOCKER_ID_PSW
            skaffold run -p release
          """
        }
      }
    }
  }
}

次にSkaffold runで実行するためのskaffold.yamlを作成します。
Skaffoldでやりたいのは以下の内容です。


1. Dockerイメージのビルド
1. Dockerイメージのプッシュ(プライベートレジストリ
1. ビルドしたイメージからコンテナをデプロイ


上記の内容を行うために作成したskaffold.yamlが以下になります。

apiVersion: skaffold/v1alpha2
kind: Config
build:
  tagPolicy:
    sha256: {}
  artifacts:
  - imageName: pshost01:5000/study/mydjango
    workspace: .
    docker:
      dockerfilePath: ./kubernetes/docker_dev/Dockerfile
  local:
    skipPush: true
deploy:
  kubectl:
    manifests:
    - ./kubernetes/helm/templates/deployments.yaml
profiles:
  - name: release
    build:
      artifacts:
      - imageName: pshost01:5000/study/mydjango
        workspace: .
        docker:
          dockerfilePath: ./kubernetes/docker_dev/Dockerfile
      local:
        skipPush: false
      tagPolicy:
        gitCommit: {}
    deploy:
      kubectl:
        manifests:
        - ./kubernetes/helm/templates/deployments.yaml

skaffoldからkubernetesへのデプロイは、helmだとうまくいかなったため、今回はkubectlを使用します。

自分で新しく作成した場合はwebhookさせるGithubリポジトリにプッシュしておくことを忘れずに。


pipelineを作成する

次にJenkinsの画面でパイプラインを作成していきます。

Jenkinsにログインします。
f:id:fclout:20200627235457p:plain

ユーザ名はadminです。
パスワードは前述したとおり、コマンドで入手したものです。


f:id:fclout:20200627235533p:plain

ログイン後にメニューから「Open Blue Ocean」を選択。
※Blue Oceanプラグインを入れてない場合はブラグインの管理画面からインストールしてください。


f:id:fclout:20200627235639p:plain

「Create New Pipeline」をクリック。


f:id:fclout:20200627235707p:plain

今回はGithubリポジトリをwebhookするので「Github」を選択。


f:id:fclout:20200627235745p:plain

対象のGithubアカウントを選択。

※初回の場合はAPIトークンの入力を求められるので、
Githubのページにいってトークンを発行してください。



f:id:fclout:20200627235848p:plain

webhookさせるリポジトリを選択します。



f:id:fclout:20200628000013p:plain

パイプラインが作成されます。



f:id:fclout:20200628000034p:plain

作成されたパイプラインを選択すると実行状況の詳細が見れます。



f:id:fclout:20200614231924p:plain


うまくいっているようです。
詳細なログを見てみましょう。



+ docker login '--username=****' '--password=****'
WARNING! Using --password via the CLI is insecure. Use --password-stdin.
WARNING! Your password will be stored unencrypted in /root/.docker/config.json.
Configure a credential helper to remove this warning. See
https://docs.docker.com/engine/reference/commandline/login/#credentials-store
Login Succeeded
+ skaffold run -p release
Generating tags...
 - pshost01:5000/study/mydjango -> pshost01:5000/study/mydjango:latest
Some taggers failed. Rerun with -vdebug for errors.
Checking cache...
 - pshost01:5000/study/mydjango: Not found. Building
Building [pshost01:5000/study/mydjango]...
Sending build context to Docker daemon  6.144kB
Step 1/15 : FROM centos
 ---> 470671670cac
Step 2/15 : LABEL maintainer="Ultimania <yng.****.gmail.com>"
 ---> Using cache
 ---> 5493211a7630
Step 3/15 : WORKDIR /root
 ---> Using cache
 ---> 5e1e4afa980b
Step 4/15 : ENV PATH="$PATH:/usr/local/python/bin"
 ---> Using cache
 ---> 24536bd11581
Step 5/15 : ENV PYTHON_VERSION="3.8.2"
 ---> Using cache
 ---> 7e0e2efd8e3c
Step 6/15 : ENV DJANGO_VERSION="3.0.5"
 ---> Using cache
 ---> 3e4a7f3e254e
Step 7/15 : ENV PROJECT_NAME="myproject"
 ---> Using cache
 ---> ce66bf28d694
Step 8/15 : ENV DB_NAME="django"
 ---> Using cache
 ---> 38b71806fc11
Step 9/15 : RUN set -x &&     dnf -y install mariadb-devel libffi-devel xz xz-devel git zlib-devel bzip2 bzip2-devel openssl-devel gcc make &&     cd /usr/local/src &&     curl -O https://www.python.org/ftp/python/${PYTHON_VERSION}/Python-${PYTHON_VERSION}.tgz &&     tar xvzf Python-${PYTHON_VERSION}.tgz &&     cd Python-${PYTHON_VERSION} &&     ./configure --prefix=/usr/local/python &&     make &&     make install &&     cd ~ &&     ln -s /usr/local/python/bin/python3 /usr/local/bin/python &&     ln -s /usr/local/python/bin/pip3 /usr/local/bin/pip
 ---> Using cache
 ---> 29b3e72bf8f5
Step 10/15 : RUN set -x &&     pip install --upgrade pip &&     pip install django==${DJANGO_VERSION} &&     pip install django-filter &&     pip install mysqlclient &&     pip install PyMySQL &&     pip install uwsgi &&     pip install django-hamlpy &&     pip install mpl_finance &&     pip install django-widget-tweaks &&     pip install pycrypto &&     pip install gensim &&     pip install django-extensions &&     pip install jupyterlab &&     django-admin startproject ${PROJECT_NAME}
---> Running in 7ecab2a347b5
+ pip install --upgrade pip
Collecting pip
  Downloading https://files.pythonhosted.org/packages/43/84/23ed6a1796480a6f1a2d38f2802901d078266bda38388954d01d3f2e821d/pip-20.1.1-py2.py3-none-any.whl (1.5MB)
Installing collected packages: pip
  Found existing installation: pip 19.2.3
    Uninstalling pip-19.2.3:
Successfully uninstalled pip-19.2.3
Successfully installed pip-20.1.1
+ pip install django==3.0.5
Collecting django==3.0.5
  Downloading Django-3.0.5-py3-none-any.whl (7.5 MB)
Collecting sqlparse>=0.2.2
  Downloading sqlparse-0.3.1-py2.py3-none-any.whl (40 kB)
Collecting pytz
  Downloading pytz-2020.1-py2.py3-none-any.whl (510 kB)
Collecting asgiref~=3.2
  Downloading asgiref-3.2.7-py2.py3-none-any.whl (19 kB)
Installing collected packages: sqlparse, pytz, asgiref, django
Successfully installed asgiref-3.2.7 django-3.0.5 pytz-2020.1 sqlparse-0.3.1
+ pip install django-filter
Collecting django-filter
  Downloading django_filter-2.3.0-py3-none-any.whl (73 kB)
Requirement already satisfied: Django>=2.2 in /usr/local/python/lib/python3.8/site-packages (from django-filter) (3.0.5)
Requirement already satisfied: pytz in /usr/local/python/lib/python3.8/site-packages (from Django>=2.2->django-filter) (2020.1)
Requirement already satisfied: sqlparse>=0.2.2 in /usr/local/python/lib/python3.8/site-packages (from Django>=2.2->django-filter) (0.3.1)
Requirement already satisfied: asgiref~=3.2 in /usr/local/python/lib/python3.8/site-packages (from Django>=2.2->django-filter) (3.2.7)
Installing collected packages: django-filter
Successfully installed django-filter-2.3.0
+ pip install mysqlclient
Collecting mysqlclient
  Downloading mysqlclient-1.4.6.tar.gz (85 kB)
Using legacy setup.py install for mysqlclient, since package 'wheel' is not installed.
Installing collected packages: mysqlclient
    Running setup.py install for mysqlclient: started
Running setup.py install for mysqlclient: finished with status 'done'
Successfully installed mysqlclient-1.4.6
+ pip install PyMySQL
Collecting PyMySQL
  Downloading PyMySQL-0.9.3-py2.py3-none-any.whl (47 kB)
Installing collected packages: PyMySQL
Successfully installed PyMySQL-0.9.3
+ pip install uwsgi
Collecting uwsgi
  Downloading uwsgi-2.0.18.tar.gz (801 kB)
Using legacy setup.py install for uwsgi, since package 'wheel' is not installed.
Installing collected packages: uwsgi
    Running setup.py install for uwsgi: started
Running setup.py install for uwsgi: finished with status 'done'
Successfully installed uwsgi-2.0.18
+ pip install django-hamlpy
Collecting django-hamlpy
  Downloading django_hamlpy-1.2-py2.py3-none-any.whl (41 kB)
Collecting regex
  Downloading regex-2020.6.8-cp38-cp38-manylinux2010_x86_64.whl (673 kB)
Requirement already satisfied: django in /usr/local/python/lib/python3.8/site-packages (from django-hamlpy) (3.0.5)
Requirement already satisfied: sqlparse>=0.2.2 in /usr/local/python/lib/python3.8/site-packages (from django->django-hamlpy) (0.3.1)
Requirement already satisfied: asgiref~=3.2 in /usr/local/python/lib/python3.8/site-packages (from django->django-hamlpy) (3.2.7)
Requirement already satisfied: pytz in /usr/local/python/lib/python3.8/site-packages (from django->django-hamlpy) (2020.1)
Installing collected packages: regex, django-hamlpy
Successfully installed django-hamlpy-1.2 regex-2020.6.8
+ pip install mpl_finance
Collecting mpl_finance
  Downloading mpl_finance-0.10.1-py3-none-any.whl (8.4 kB)
Collecting matplotlib
  Downloading matplotlib-3.2.1-cp38-cp38-manylinux1_x86_64.whl (12.4 MB)
Collecting python-dateutil>=2.1
  Downloading python_dateutil-2.8.1-py2.py3-none-any.whl (227 kB)
Collecting pyparsing!=2.0.4,!=2.1.2,!=2.1.6,>=2.0.1
  Downloading pyparsing-2.4.7-py2.py3-none-any.whl (67 kB)
Collecting cycler>=0.10
  Downloading cycler-0.10.0-py2.py3-none-any.whl (6.5 kB)
Collecting kiwisolver>=1.0.1
  Downloading kiwisolver-1.2.0-cp38-cp38-manylinux1_x86_64.whl (92 kB)
Collecting numpy>=1.11
  Downloading numpy-1.18.5-cp38-cp38-manylinux1_x86_64.whl (20.6 MB)
Collecting six>=1.5
  Downloading six-1.15.0-py2.py3-none-any.whl (10 kB)
Installing collected packages: six, python-dateutil, pyparsing, cycler, kiwisolver, numpy, matplotlib, mpl-finance
Successfully installed cycler-0.10.0 kiwisolver-1.2.0 matplotlib-3.2.1 mpl-finance-0.10.1 numpy-1.18.5 pyparsing-2.4.7 python-dateutil-2.8.1 six-1.15.0
+ pip install django-widget-tweaks
Collecting django-widget-tweaks
  Downloading django_widget_tweaks-1.4.8-py2.py3-none-any.whl (11 kB)
Installing collected packages: django-widget-tweaks
Successfully installed django-widget-tweaks-1.4.8
+ pip install pycrypto
Collecting pycrypto
Downloading pycrypto-2.6.1.tar.gz (446 kB)
Using legacy setup.py install for pycrypto, since package 'wheel' is not installed.
Installing collected packages: pycrypto
    Running setup.py install for pycrypto: started
Running setup.py install for pycrypto: finished with status 'done'
Successfully installed pycrypto-2.6.1
+ pip install gensim
Collecting gensim
  Downloading gensim-3.8.3-cp38-cp38-manylinux1_x86_64.whl (24.2 MB)
Requirement already satisfied: numpy>=1.11.3 in /usr/local/python/lib/python3.8/site-packages (from gensim) (1.18.5)
Collecting scipy>=0.18.1
  Downloading scipy-1.4.1-cp38-cp38-manylinux1_x86_64.whl (26.0 MB)
Collecting smart-open>=1.8.1
  Downloading smart_open-2.0.0.tar.gz (103 kB)
Requirement already satisfied: six>=1.5.0 in /usr/local/python/lib/python3.8/site-packages (from gensim) (1.15.0)
Collecting requests
  Downloading requests-2.23.0-py2.py3-none-any.whl (58 kB)
Collecting boto
  Downloading boto-2.49.0-py2.py3-none-any.whl (1.4 MB)
Collecting boto3
  Downloading boto3-1.14.2-py2.py3-none-any.whl (128 kB)
Collecting urllib3!=1.25.0,!=1.25.1,<1.26,>=1.21.1
  Downloading urllib3-1.25.9-py2.py3-none-any.whl (126 kB)
Collecting idna<3,>=2.5
  Downloading idna-2.9-py2.py3-none-any.whl (58 kB)
Collecting chardet<4,>=3.0.2
  Downloading chardet-3.0.4-py2.py3-none-any.whl (133 kB)
Collecting certifi>=2017.4.17
  Downloading certifi-2020.4.5.2-py2.py3-none-any.whl (157 kB)
Collecting botocore<1.18.0,>=1.17.2
  Downloading botocore-1.17.2-py2.py3-none-any.whl (6.3 MB)
Collecting s3transfer<0.4.0,>=0.3.0
  Downloading s3transfer-0.3.3-py2.py3-none-any.whl (69 kB)
Collecting jmespath<1.0.0,>=0.7.1
  Downloading jmespath-0.10.0-py2.py3-none-any.whl (24 kB)
Requirement already satisfied: python-dateutil<3.0.0,>=2.1 in /usr/local/python/lib/python3.8/site-packages (from botocore<1.18.0,>=1.17.2->boto3->smart-open>=1.8.1->gensim) (2.8.1)
Collecting docutils<0.16,>=0.10
  Downloading docutils-0.15.2-py3-none-any.whl (547 kB)
Using legacy setup.py install for smart-open, since package 'wheel' is not installed.
Installing collected packages: scipy, urllib3, idna, chardet, certifi, requests, boto, docutils, jmespath, botocore, s3transfer, boto3, smart-open, gensim
Running setup.py install for smart-open: started
    Running setup.py install for smart-open: finished with status 'done'
Successfully installed boto-2.49.0 boto3-1.14.2 botocore-1.17.2 certifi-2020.4.5.2 chardet-3.0.4 docutils-0.15.2 gensim-3.8.3 idna-2.9 jmespath-0.10.0 requests-2.23.0 s3transfer-0.3.3 scipy-1.4.1 smart-open-2.0.0 urllib3-1.25.9
+ pip install django-extensions
Collecting django-extensions
  Downloading django_extensions-2.2.9-py2.py3-none-any.whl (217 kB)
Requirement already satisfied: six>=1.2 in /usr/local/python/lib/python3.8/site-packages (from django-extensions) (1.15.0)
Installing collected packages: django-extensions
Successfully installed django-extensions-2.2.9
+ pip install jupyterlab
Collecting jupyterlab
  Downloading jupyterlab-2.1.4-py3-none-any.whl (7.6 MB)
Collecting jinja2>=2.10
  Downloading Jinja2-2.11.2-py2.py3-none-any.whl (125 kB)
Collecting tornado!=6.0.0,!=6.0.1,!=6.0.2
  Downloading tornado-6.0.4.tar.gz (496 kB)
Collecting jupyterlab-server<2.0,>=1.1.0
  Downloading jupyterlab_server-1.1.5-py3-none-any.whl (29 kB)
Collecting notebook>=4.3.1
  Downloading notebook-6.0.3-py3-none-any.whl (9.7 MB)
Collecting MarkupSafe>=0.23
  Downloading MarkupSafe-1.1.1-cp38-cp38-manylinux1_x86_64.whl (32 kB)
Requirement already satisfied: requests in /usr/local/python/lib/python3.8/site-packages (from jupyterlab-server<2.0,>=1.1.0->jupyterlab) (2.23.0)
Collecting json5
  Downloading json5-0.9.5-py2.py3-none-any.whl (17 kB)
Collecting jsonschema>=3.0.1
  Downloading jsonschema-3.2.0-py2.py3-none-any.whl (56 kB)
Collecting ipython-genutils
  Downloading ipython_genutils-0.2.0-py2.py3-none-any.whl (26 kB)
Collecting pyzmq>=17
  Downloading pyzmq-19.0.1-cp38-cp38-manylinux1_x86_64.whl (1.1 MB)
Collecting prometheus-client
  Downloading prometheus_client-0.8.0-py2.py3-none-any.whl (53 kB)
Collecting jupyter-core>=4.6.1
  Downloading jupyter_core-4.6.3-py2.py3-none-any.whl (83 kB)
Collecting nbconvert
  Downloading nbconvert-5.6.1-py2.py3-none-any.whl (455 kB)
Collecting nbformat
  Downloading nbformat-5.0.7-py3-none-any.whl (170 kB)
Collecting ipykernel
  Downloading ipykernel-5.3.0-py3-none-any.whl (119 kB)
Collecting traitlets>=4.2.1
  Downloading traitlets-4.3.3-py2.py3-none-any.whl (75 kB)
Collecting terminado>=0.8.1
  Downloading terminado-0.8.3-py2.py3-none-any.whl (33 kB)
Collecting Send2Trash
  Downloading Send2Trash-1.5.0-py3-none-any.whl (12 kB)
Collecting jupyter-client>=5.3.4
  Downloading jupyter_client-6.1.3-py3-none-any.whl (106 kB)
Requirement already satisfied: chardet<4,>=3.0.2 in /usr/local/python/lib/python3.8/site-packages (from requests->jupyterlab-server<2.0,>=1.1.0->jupyterlab) (3.0.4)
Requirement already satisfied: certifi>=2017.4.17 in /usr/local/python/lib/python3.8/site-packages (from requests->jupyterlab-server<2.0,>=1.1.0->jupyterlab) (2020.4.5.2)
Requirement already satisfied: urllib3!=1.25.0,!=1.25.1,<1.26,>=1.21.1 in /usr/local/python/lib/python3.8/site-packages (from requests->jupyterlab-server<2.0,>=1.1.0->jupyterlab) (1.25.9)
Requirement already satisfied: idna<3,>=2.5 in /usr/local/python/lib/python3.8/site-packages (from requests->jupyterlab-server<2.0,>=1.1.0->jupyterlab) (2.9)
Requirement already satisfied: six>=1.11.0 in /usr/local/python/lib/python3.8/site-packages (from jsonschema>=3.0.1->jupyterlab-server<2.0,>=1.1.0->jupyterlab) (1.15.0)
Collecting attrs>=17.4.0
  Downloading attrs-19.3.0-py2.py3-none-any.whl (39 kB)
Requirement already satisfied: setuptools in /usr/local/python/lib/python3.8/site-packages (from jsonschema>=3.0.1->jupyterlab-server<2.0,>=1.1.0->jupyterlab) (41.2.0)
Collecting pyrsistent>=0.14.0
  Downloading pyrsistent-0.16.0.tar.gz (108 kB)
Collecting entrypoints>=0.2.2
  Downloading entrypoints-0.3-py2.py3-none-any.whl (11 kB)
Collecting bleach
  Downloading bleach-3.1.5-py2.py3-none-any.whl (151 kB)
Collecting pygments
  Downloading Pygments-2.6.1-py3-none-any.whl (914 kB)
Collecting pandocfilters>=1.4.1
  Downloading pandocfilters-1.4.2.tar.gz (14 kB)
Collecting defusedxml
  Downloading defusedxml-0.6.0-py2.py3-none-any.whl (23 kB)
Collecting testpath
  Downloading testpath-0.4.4-py2.py3-none-any.whl (163 kB)
Collecting mistune<2,>=0.8.1
  Downloading mistune-0.8.4-py2.py3-none-any.whl (16 kB)
Collecting ipython>=5.0.0
  Downloading ipython-7.15.0-py3-none-any.whl (783 kB)
Collecting decorator
  Downloading decorator-4.4.2-py2.py3-none-any.whl (9.2 kB)
Collecting ptyprocess; os_name != "nt"
  Downloading ptyprocess-0.6.0-py2.py3-none-any.whl (39 kB)
Requirement already satisfied: python-dateutil>=2.1 in /usr/local/python/lib/python3.8/site-packages (from jupyter-client>=5.3.4->notebook>=4.3.1->jupyterlab) (2.8.1)
Collecting webencodings
  Downloading webencodings-0.5.1-py2.py3-none-any.whl (11 kB)
Collecting packaging
  Downloading packaging-20.4-py2.py3-none-any.whl (37 kB)
Collecting prompt-toolkit!=3.0.0,!=3.0.1,<3.1.0,>=2.0.0
  Downloading prompt_toolkit-3.0.5-py3-none-any.whl (351 kB)
Collecting pickleshare
  Downloading pickleshare-0.7.5-py2.py3-none-any.whl (6.9 kB)
Collecting backcall
  Downloading backcall-0.2.0-py2.py3-none-any.whl (11 kB)
Collecting jedi>=0.10
  Downloading jedi-0.17.0-py2.py3-none-any.whl (1.1 MB)
Collecting pexpect; sys_platform != "win32"
  Downloading pexpect-4.8.0-py2.py3-none-any.whl (59 kB)
Requirement already satisfied: pyparsing>=2.0.2 in /usr/local/python/lib/python3.8/site-packages (from packaging->bleach->nbconvert->notebook>=4.3.1->jupyterlab) (2.4.7)
Collecting wcwidth
  Downloading wcwidth-0.2.4-py2.py3-none-any.whl (30 kB)
Collecting parso>=0.7.0
  Downloading parso-0.7.0-py2.py3-none-any.whl (100 kB)
Using legacy setup.py install for tornado, since package 'wheel' is not installed.
Using legacy setup.py install for pyrsistent, since package 'wheel' is not installed.
Using legacy setup.py install for pandocfilters, since package 'wheel' is not installed.
Installing collected packages: MarkupSafe, jinja2, tornado, ipython-genutils, pyzmq, prometheus-client, decorator, traitlets, jupyter-core, entrypoints, webencodings, packaging, bleach, pygments, attrs, pyrsistent, jsonschema, nbformat, pandocfilters, defusedxml, testpath, mistune, nbconvert, jupyter-client, wcwidth, prompt-toolkit, pickleshare, backcall, parso, jedi, ptyprocess, pexpect, ipython, ipykernel, terminado, Send2Trash, notebook, json5, jupyterlab-server, jupyterlab
    Running setup.py install for tornado: started
Running setup.py install for tornado: finished with status 'done'
Running setup.py install for pyrsistent: started
    Running setup.py install for pyrsistent: finished with status 'done'
Running setup.py install for pandocfilters: started
    Running setup.py install for pandocfilters: finished with status 'done'
Successfully installed MarkupSafe-1.1.1 Send2Trash-1.5.0 attrs-19.3.0 backcall-0.2.0 bleach-3.1.5 decorator-4.4.2 defusedxml-0.6.0 entrypoints-0.3 ipykernel-5.3.0 ipython-7.15.0 ipython-genutils-0.2.0 jedi-0.17.0 jinja2-2.11.2 json5-0.9.5 jsonschema-3.2.0 jupyter-client-6.1.3 jupyter-core-4.6.3 jupyterlab-2.1.4 jupyterlab-server-1.1.5 mistune-0.8.4 nbconvert-5.6.1 nbformat-5.0.7 notebook-6.0.3 packaging-20.4 pandocfilters-1.4.2 parso-0.7.0 pexpect-4.8.0 pickleshare-0.7.5 prometheus-client-0.8.0 prompt-toolkit-3.0.5 ptyprocess-0.6.0 pygments-2.6.1 pyrsistent-0.16.0 pyzmq-19.0.1 terminado-0.8.3 testpath-0.4.4 tornado-6.0.4 traitlets-4.3.3 wcwidth-0.2.4 webencodings-0.5.1
+ django-admin startproject myproject
 ---> 94bac9708f5f
Step 11/15 : COPY ./kubernetes/docker_dev/my_setting.py /root/${PROJECT_NAME}/${PROJECT_NAME}/
 ---> a5f23ac8b277
Step 12/15 : COPY ./kubernetes/docker_dev/startup.sh /root/
 ---> 9abeb8c49204
Step 13/15 : RUN set -x &&     cat ~/${PROJECT_NAME}/${PROJECT_NAME}/my_setting.py >> ~/${PROJECT_NAME}/${PROJECT_NAME}/settings.py &&     useradd admin -G root &&     chmod 777 /root/startup.sh
 ---> Running in 1a13748e2343
+ cat /root/myproject/myproject/my_setting.py
+ useradd admin -G root
+ chmod 777 /root/startup.sh
 ---> 4430679a771e
Step 14/15 : ENV DB_HOST="django-dev"
---> Running in 254c4a2acb49
 ---> 75b15cade02d
Step 15/15 : CMD [ "/bin/sh" , "/root/startup.sh"]
---> Running in a7cb69f70cc8
 ---> c1b029ca8d4f
Successfully built c1b029ca8d4f
Successfully tagged pshost01:5000/study/mydjango:latest
The push refers to repository [pshost01:5000/study/mydjango]
a41e385eaeb0: Preparing
d2d3f64531c4: Preparing
83628dc785e0: Preparing
f69f5c817488: Preparing
a4aaaa2e9177: Preparing
0683de282177: Preparing
0683de282177: Waiting
a4aaaa2e9177: Layer already exists
0683de282177: Layer already exists
83628dc785e0: Pushed
a41e385eaeb0: Pushed
d2d3f64531c4: Pushed
f69f5c817488: Pushed
latest: digest: sha256:af86d5e5d303b3aca9268fd4635a3a07e52a03b1e8f253aa0b0dd7bc38c8a6b2 size: 1577
Tags used in deployment:
 - pshost01:5000/study/mydjango -> pshost01:5000/study/mydjango:latest@sha256:af86d5e5d303b3aca9268fd4635a3a07e52a03b1e8f253aa0b0dd7bc38c8a6b2
Starting deploy...
- deployment.apps/django-dev configured
Waiting for deployments to stabilize...
 - myblog-prod:deployment/django-dev: waiting for deployment spec update to be observed...
- myblog-prod:deployment/django-dev: waiting for rollout to finish: 1 old replicas are pending termination...
    - myblog-prod:pod/django-dev-5bdb5fb997-k4t6l: creating container ap-server
- myblog-prod:deployment/django-dev is ready.
Deployments stabilized in 7.071943209s
You can also run [skaffold run --tail] to get the logs
Help improve Skaffold! Take a 10-second anonymous survey by running
   skaffold survey

ログから見てもわかるとおり、
「Successfully built 」した後に「The push refers to repository [pshost01:5000/study/mydjango]」して、「Starting deploy...」してます。
想定通りの動きをしてることがわかります。



これでGithubにコミットをかけてからイメージビルド・プッシュ・デプロイまでの一連の流れを自動化することができました。