はじめに
以下のサンプルを実際にやってみて、OCI Service Connector HubとOCI DevOpsの連携方法を確認します。
アーキテクチャとしては以下のようになります。
- コンテナイメージをOCIRにPushする
- PushをトリガーにService Connector HubがFunctionをキックする
- FunctionがOCI DevOpsのDeployment Pipelineをキックする
- Deployment PipelineがOKEにコンテナをデプロイする
※Build Pipelineを使えばシンプルにできそうな気もしますが、それはそれとして。
サンプルコードのダウンロード
サンプルコードをクライアントマシンにダウンロードします。
$ git init oci-devops-deploy-on-imageupload
Initialized empty Git repository in /home/opc/oci-devops-deploy-on-imageupload/.git/
$ cd oci-devops-deploy-on-imageupload/
$ git remote add origin https://github.com/oracle-devrel/oci-devops-examples
$ git config core.sparsecheckout true
$ echo "oci-deployment-examples/oci-devops-deploy-on-imageupload/*">>.git/info/sparse-checkout
$ git pull --depth=1 origin main
remote: Enumerating objects: 1328, done.
remote: Counting objects: 100% (1328/1328), done.
remote: Compressing objects: 100% (1199/1199), done.
remote: Total 1328 (delta 76), reused 1242 (delta 57), pack-reused 0
Receiving objects: 100% (1328/1328), 92.20 MiB | 12.27 MiB/s, done.
Resolving deltas: 100% (76/76), done.
From https://github.com/oracle-devrel/oci-devops-examples
* branch main -> FETCH_HEAD
* [new branch] main -> origin/main
$ ls -l oci-deployment-examples/oci-devops-deploy-on-imageupload/
total 36
-rw-rw-r--. 1 opc opc 235 Aug 17 06:12 Dockerfile
-rw-rw-r--. 1 opc opc 10624 Aug 17 06:12 README.md
-rw-rw-r--. 1 opc opc 0 Aug 17 06:12 __init__.py
-rw-rw-r--. 1 opc opc 1024 Aug 17 06:12 deploy.yaml
drwxrwxr-x. 2 opc opc 80 Aug 18 02:05 functions
drwxrwxr-x. 2 opc opc 4096 Aug 17 06:12 images
-rw-rw-r--. 1 opc opc 251 Aug 17 06:12 main.py
-rw-rw-r--. 1 opc opc 16 Aug 17 06:12 requirements.txt
-rw-rw-r--. 1 opc opc 631 Aug 17 06:12 setup.py
Notificationのトピック作成
DevOpsで指定するトピックを作成します。
ポリシーの設定
権限の都合上、作成済みの動的グループに以下のポリシーを設定します。
Allow dynamic-group <動的グループ名> to manage devops-family in compartment <コンパートメント名>
Allow dynamic-group <動的グループ名> to manage generic-artifacts in compartment <コンパートメント名>
Allow dynamic-group <動的グループ名> to use ons-topics in compartment <コンパートメント名>
Allow dynamic-group <動的グループ名> to manage cluster-family in compartment <コンパートメント名>
OKEクラスタ作成
クイック作成でOKEクラスタを作成します。
OCIRの作成
パブリックリポジトリを作成します。
OCI DevOpsプロジェクト作成
プロジェクトを作成します。その際、トピックは先ほど作成したトピックを指定します。
ログの有効化
プロジェクト作成後、ログを有効化します。
アーティファクトの作成
ここではOKEにデプロイするリソースのマニフェストを登録します。
アーティファクト・ソースをインライン
にして、マニフェストを値
に直接書きます。
記載したマニフェストは以下(サンプルコードにあります)。作成するリソースは3つです。
- namespace
- namespace名はデプロイメントパイプラインでパラメータとして渡します。
- Deployment
- コンテナイメージのパスは環境に合わせて以下の書式で変更します。
image: <OCI Region>.ocir.io/<Namespace>/<Name of the Repo>:${BUILDRUN_HASH}
- Service
- LoadBalancer
kind: Namespace
apiVersion: v1
metadata:
name: ${namespace}
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: python-gettingstarted-deployment
namespace: ${namespace}
spec:
selector:
matchLabels:
app: python-gettingstarted
replicas: 3
template:
metadata:
labels:
app: python-gettingstarted
spec:
containers:
- name: python-gettingstarted
# enter the path to your image, be sure to include the correct region prefix
image: us-ashburn-1.ocir.io/fahdabidiroottenancy/telesis-repo-uploadtest:${BUILDRUN_HASH}
imagePullPolicy: Always
ports:
- containerPort: 80
protocol: TCP
---
apiVersion: v1
kind: Service
metadata:
name: python-gettingstarted-service
namespace: ${namespace}
annotations:
service.beta.kubernetes.io/oci-load-balancer-shape: "10Mbps"
spec:
type: LoadBalancer
ports:
- port: 80
protocol: TCP
targetPort: 80
selector:
app: python-gettingstarted
環境の作成
Deployment Pipelineでデプロイする環境
を作成します。
Deployment Pipelineの作成
任意の名称で作成します。
パラメーターの追加
namespace
とBUILDRUN_HASH
のデフォルト値を設定します。
ステージの作成
ステージの追加
をクリックします。
Kubernetesクラスタにマニフェストを適用
を選択します。
環境
とアーティファクトの選択
で事前に作成した環境とアーティファクトを選択します。
Functionsの作成
OCIコンソールでアプリケーションを作成します。
確認します。
$ fn list app
NAME ID
my-function-app ocid1.fnapp.oc1.uk-london-1.aaaaaaaa26kmkim4da6vrgxxxxxxxxxxxxxxxxxxxxxxxxxx
コードの一部を環境に合わせて書き換えます。
$ cd oci-devops-deploy-on-imageupload/functions/
$ ls -l
total 16
-rw-rw-r--. 1 opc opc 519 Aug 17 06:12 Dockerfile
-rw-rw-r--. 1 opc opc 2651 Aug 17 06:12 func.py
-rw-rw-r--. 1 opc opc 386 Aug 17 06:12 func.yaml
-rw-rw-r--. 1 opc opc 58 Aug 17 06:12 requirements.txt
func.yaml
のoci_deployment_pipeline_id
とoci_region
を作成したDeployment PipelineのOCIDと使用しているリージョンに書き換えます。
schema_version: 20180708
name: invokedeploymentpipeline
version: 0.0.10
runtime: docker
build_image: fnproject/python:3.8-dev
run_image: fnproject/python:3.8
entrypoint: /python/bin/fdk /function/func.py handler
memory: 1024
config:
oci_deployment_pipeline_id: ocid1.devopsdeploypipeline.oc1.uk-london-1.amaaaaaassl65iqaqx66ani2e4jkhol2hiy4xxxxxxxxxxxxxxxxxxxxx
oci_region: uk-london-1
アプリケーションにFunctionをデプロイします。
$ fn deploy --app my-function-app -v
Deploying invokedeploymentpipeline to app: my-function-app
Bumped to version 0.0.11
Using Container engine docker
Building image lhr.ocir.io/orasejapan/lhr-fn-repo01/invokedeploymentpipeline:0.0.11
Dockerfile content
-----------------------------------
FROM oraclelinux:7-slim
RUN yum install -y git && \
yum-config-manager --disable ol7_developer_EPEL && \
yum install -y oracle-epel-release-el7 python36 && \
rm -rf /var/cache/yum && \
groupadd --gid 1000 fn && \
adduser --uid 1000 --gid fn fn
WORKDIR /function
ADD requirements.txt .
RUN python3 -m pip install --upgrade pip && \
python3 -m pip install -r requirements.txt
COPY func.py /function/
ENV PYTHONPATH="$PYTHONPATH:/function"
ENTRYPOINT ["fdk", "/function/func.py", "handler"]-----------------------------------
FN_REGISTRY: lhr.ocir.io/orasejapan/lhr-fn-repo01
Current Context: lhr-app01
[+] Building 162.4s (12/12) FINISHED
=> [internal] load .dockerignore 0.0s
=> => transferring context: 2B 0.0s
=> [internal] load build definition from Dockerfile 0.0s
=> => transferring dockerfile: 617B 0.0s
=> [internal] load metadata for docker.io/library/oraclelinux:7-slim 1.9s
=> [1/6] FROM docker.io/library/oraclelinux:7-slim@sha256:5e138ed4b8bc1daea6e7d102731fb07057092ab49477c40fb68330939ad58949 3.5s
=> => resolve docker.io/library/oraclelinux:7-slim@sha256:5e138ed4b8bc1daea6e7d102731fb07057092ab49477c40fb68330939ad58949 0.0s
=> => sha256:5e138ed4b8bc1daea6e7d102731fb07057092ab49477c40fb68330939ad58949 547B / 547B 0.0s
=> => sha256:fba649cd92babf77517f2836bd786e4d910cb4cf309e2582253b67a1268dad8a 529B / 529B 0.0s
=> => sha256:2ff218ecbf1b48fe4bbe266f0427ecf887e4d59e863fbe2e1a4c3b682076b966 1.48kB / 1.48kB 0.0s
=> => sha256:70e9ff4420fbc58483e68c13199a06c24b14013b2548998a7e367f59ca5157bc 50.48MB / 50.48MB 0.8s
=> => extracting sha256:70e9ff4420fbc58483e68c13199a06c24b14013b2548998a7e367f59ca5157bc 2.3s
=> [internal] load build context 0.0s
=> => transferring context: 2.91kB 0.0s
=> [2/6] RUN yum install -y git && yum-config-manager --disable ol7_developer_EPEL && yum install -y oracle-epel-release-el7 python36 && rm -rf /var/cache/yum && groupadd --gid 1000 fn 35.6s
=> [3/6] WORKDIR /function 0.1s
=> [4/6] ADD requirements.txt . 0.0s
=> [5/6] RUN python3 -m pip install --upgrade pip && python3 -m pip install -r requirements.txt 68.2s
=> [6/6] COPY func.py /function/ 0.1s
=> exporting to image 7.6s
=> => exporting layers 7.6s
=> => writing image sha256:59784998a8cd5e5c08d2fd052fce06b0365d4e6b82c19706136954b092bd7b93 0.0s
=> => naming to lhr.ocir.io/orasejapan/lhr-fn-repo01/invokedeploymentpipeline:0.0.11 0.0s
=> pushing lhr.ocir.io/orasejapan/lhr-fn-repo01/invokedeploymentpipeline:0.0.11 with docker 39.4s
=> => pushing layer 994c5f29a15a 6.5s
=> => pushing layer 049b4f228b01 36.6s
=> => pushing layer 24d7205e3c5b 6.3s
=> => pushing layer 883fa3cad799 6.5s
=> => pushing layer c1b7b3201e51 25.7s
=> => pushing layer 616461b0543d 26.1s
Updating function invokedeploymentpipeline using image lhr.ocir.io/orasejapan/lhr-fn-repo01/invokedeploymentpipeline:0.0.11...
Successfully created function: invokedeploymentpipeline with lhr.ocir.io/orasejapan/lhr-fn-repo01/invokedeploymentpipeline:0.0.11
確認します。
$ fn list f my-function-app
NAME IMAGE ID
invokedeploymentpipeline lhr.ocir.io/orasejapan/lhr-fn-repo01/invokedeploymentpipeline:0.0.11 ocid1.fnfunc.oc1.uk-london-1.aaaaaaaa3fnvhcdqpiwxj6mjixnsqewemz454c5wgrslmqljsrdgt5ke7o5q
Functionのログを有効にします。
Service Connecter Hubの作成
任意の名称を設定して、サービス・コネクタの構成
でソース
をロギング
、ターゲット
をファンクション
にして、特定のログをトリガーとして、ファンクションがキックされるようにします。
ソースの構成
では、ルートコンパートメントのAudit logが以下二つの条件を満たした場合に、ファンクションをキックするように設定します。
- Container ImageがOCIRにUploadされる
- Uploadされたリポジトリが先ほど作成したリポジトリ名
タスクの構成
には何も記載しません。
ターゲットの構成
で作成したファンクションを指定します。
動作確認
ここまでで設定が完了したので、動作確認します。
イメージのBuild/Push
サンプルコードにあるDockerfileをBuildします。
$ ls -l
total 36
-rw-rw-r--. 1 opc opc 235 Aug 17 06:12 Dockerfile
-rw-rw-r--. 1 opc opc 10624 Aug 17 06:12 README.md
-rw-rw-r--. 1 opc opc 0 Aug 17 06:12 __init__.py
-rw-rw-r--. 1 opc opc 1024 Aug 17 06:12 deploy.yaml
drwxrwxr-x. 2 opc opc 80 Aug 18 02:05 functions
drwxrwxr-x. 2 opc opc 4096 Aug 17 06:12 images
-rw-rw-r--. 1 opc opc 251 Aug 17 06:12 main.py
-rw-rw-r--. 1 opc opc 16 Aug 17 06:12 requirements.txt
-rw-rw-r--. 1 opc opc 631 Aug 17 06:12 setup.py
$ docker login lhr.ocir.io
$ docker build -t lhr.ocir.io/orasejapan/uploadevent_test:0.0 .
[+] Building 51.7s (10/10) FINISHED
=> [internal] load .dockerignore 0.0s
=> => transferring context: 2B 0.0s
=> [internal] load build definition from Dockerfile 0.0s
=> => transferring dockerfile: 333B 0.0s
=> [internal] load metadata for docker.io/library/python:3.9 2.2s
=> [1/5] FROM docker.io/library/python:3.9@sha256:9bae2a5ce72f326c8136d517ade0e9b18080625fb3ba7ec10002e0dc99bc4a70 34.5s
=> => resolve docker.io/library/python:3.9@sha256:9bae2a5ce72f326c8136d517ade0e9b18080625fb3ba7ec10002e0dc99bc4a70 0.0s
=> => sha256:9bae2a5ce72f326c8136d517ade0e9b18080625fb3ba7ec10002e0dc99bc4a70 1.86kB / 1.86kB 0.0s
=> => sha256:8bdfd6cc4bbfdbcc87f696aa7d12672b9485220ce111577099f4c2d68fbb1481 7.51kB / 7.51kB 0.0s
=> => sha256:de4cac68b6165c40cf6f8b30417948c31be03a968e233e55ee40221553a5e570 49.56MB / 49.56MB 1.2s
=> => sha256:d31b0195ec5f04dfc78eca9d73b5d223fc36a29f54ee888bc4e0615b5839e692 24.03MB / 24.03MB 0.7s
=> => sha256:fd648a271c795a281971789a1f731d284148c8d88fcd21f78f52130e0c9cf5a3 2.01kB / 2.01kB 0.0s
=> => sha256:9b1fd34c30b75e7edb20c2fd09a9862697f302ef9ae357e521ef3c84d5534e3f 64.11MB / 64.11MB 1.8s
=> => sha256:c485c4ba383179db59368a8a4d2df3e783620647fe0b014331c7fd2bd8526e5b 211.03MB / 211.03MB 6.0s
=> => extracting sha256:de4cac68b6165c40cf6f8b30417948c31be03a968e233e55ee40221553a5e570 2.9s
=> => sha256:9c94b131279a02de1f5c2eb72e9cda9830b128840470843e0761a45d7bebbefe 6.39MB / 6.39MB 2.4s
=> => sha256:863530a48f51539448368d23997c482bd210d9a629b71ee5808bccf25f85dc8f 15.82MB / 15.82MB 6.3s
=> => sha256:6738828c119ecb36cad9cb750c8260a48dac2dfb51c906d0e906ea55762b1771 242B / 242B 2.6s
=> => sha256:d271c014c3a0adbd37dae2ce6245711e2876ace65aa5c9b7859a6c515063c45f 2.85MB / 2.85MB 6.4s
=> => extracting sha256:d31b0195ec5f04dfc78eca9d73b5d223fc36a29f54ee888bc4e0615b5839e692 0.6s
=> => extracting sha256:9b1fd34c30b75e7edb20c2fd09a9862697f302ef9ae357e521ef3c84d5534e3f 2.7s
=> => extracting sha256:c485c4ba383179db59368a8a4d2df3e783620647fe0b014331c7fd2bd8526e5b 7.0s
=> => extracting sha256:9c94b131279a02de1f5c2eb72e9cda9830b128840470843e0761a45d7bebbefe 0.4s
=> => extracting sha256:863530a48f51539448368d23997c482bd210d9a629b71ee5808bccf25f85dc8f 0.5s
=> => extracting sha256:6738828c119ecb36cad9cb750c8260a48dac2dfb51c906d0e906ea55762b1771 0.0s
=> => extracting sha256:d271c014c3a0adbd37dae2ce6245711e2876ace65aa5c9b7859a6c515063c45f 0.2s
=> [internal] load build context 0.0s
=> => transferring context: 466B 0.0s
=> [2/5] WORKDIR /code 0.1s
=> [3/5] COPY ./requirements.txt /code/requirements.txt 0.0s
=> [4/5] RUN pip install --no-cache-dir --upgrade -r /code/requirements.txt 11.8s
=> [5/5] COPY ./main.py /code/ 0.1s
=> exporting to image 3.0s
=> => exporting layers 3.0s
=> => writing image sha256:47a4b093a6d61a694d2c57dbf9cfee9980caa67e70d3ba32ecf185c48cf91454 0.0s
=> => naming to lhr.ocir.io/orasejapan/uploadevent_test:0.0
$ docker image ls | head -2
REPOSITORY TAG IMAGE ID CREATED SIZE
lhr.ocir.io/orasejapan/uploadevent_test 0.0 47a4b093a6d6 About a minute ago 1.01GB
$ docker push lhr.ocir.io/orasejapan/uploadevent_test:0.0
The push refers to repository [lhr.ocir.io/orasejapan/uploadevent_test]
8e213d59fdc7: Pushed
0eb817217787: Pushed
d5305261356b: Pushed
d2d8f9cc4738: Pushed
ddab61a14989: Pushed
6e7022fb2e3d: Pushed
004040371961: Pushed
b2e5b1eee192: Pushed
b485c6cd33a6: Pushed
6aa872026017: Pushed
43ba18a5eaf8: Pushed
ff61a9b258e5: Pushed
0.0: digest: sha256:90c1e0cbada3707b3d2bcbe8d10490c9cd1f9ac7ba00071fb046877bc78c899b size: 2838
確認
Deployment Pipelineを確認すると、パイプラインが実行されていることがわかります。
Kubernetesのリソースを確認します。
NamespaceとDeployment(Pod)、Service(LoadBalancer)がデプロイされています。
$ k get all -n ns-deploy
NAME READY STATUS RESTARTS AGE
pod/python-gettingstarted-deployment-685f686848-qn8gf 1/1 Running 0 2m37s
pod/python-gettingstarted-deployment-685f686848-qvbmn 1/1 Running 0 2m37s
pod/python-gettingstarted-deployment-685f686848-v5qdb 1/1 Running 0 2m38s
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
service/python-gettingstarted-service LoadBalancer 10.96.94.43 141.147.xx.xx 80:30288/TCP 2m37s
NAME READY UP-TO-DATE AVAILABLE AGE
deployment.apps/python-gettingstarted-deployment 3/3 3 3 2m39s
NAME DESIRED CURRENT READY AGE
replicaset.apps/python-gettingstarted-deployment-685f686848 3 3 3 2m39s
LoadBalancerのEXTERNAL-IPにアクセスします。
$ curl http://141.147.xx.xx
{"Message":"demo with Service Connector Hub","Version":"0.0.0"}
詳細確認
ログを辿って詳細を確認します。
ルートコンパートメントの監査ログにService Connecter Hubで指定したリポジトリ名にコンテナイメージがUploadされたログが残されています。
Service Connecter Hubのメトリックを確認すると、3分後にこのログを読み取っています。
同時刻にターゲットに書き込んでいます。(Functionをキック)
同時刻にFunctionがキックされています。
FunctionによってDeployment Pipelineがキックされて、OKEにデプロイされています。