こんにちは、Red Hatでソリューションアーキテクトをしている石川です。
前回の記事ではOpenShift Pipelines(Tekton)の中でskopeoを動かし、CIパイプラインでビルドしたイメージを別クラスタのコンテナレジストリにコピーしました。 この際、あて先となるクラスタではコンテナレジストリに接続するためのrouteを公開し、それを通じてCI実行側のクラスタからイメージをコピーしました。
今回の記事ではSkupperを使うことであて先クラスタ側でrouteを公開することなくイメージのコピーを実施したいと思います。
そもそもSkupperとは?について知りたい方は赤帽ブログのこちらの記事を参照下さい。
rheb.hatenablog.com
TL;DR
・Skupperを使うと異なるクラスタのNamespace間で動いているサービスを簡単に繋ぐことができます
・OpenShiftではSkupper Operatorがあるので導入しやすいです
・今回はCIパイプラインのユースケースでSkupperを使ってみました
作りたい構成
今回も前回と同様にCIパイプラインを実行し、コンテナのビルドやイメージのコピーを行うクラスタとしてROSAクラスタを構築します。(上図左)
そしてイメージのコピー先としてAWS上にIPIでOCPクラスタを構築します。(上図右)
今回はこの2つのクラスタの特定のNamespace間でSkupperによるAMQP Linkを結び、こちらを介してコンテナイメージのコピーを実施したいと思います。
クラスタ間でのLink作成
Skupperを使いクラスタ間でLinkを作成するステップとしては以下となります。
・各クラスタにSkupper Operatorをインストール
・Linkを結びたいNamespaceにてSkupperを初期化
・Tokenを生成しLinkを作成
Skupper Operatorのインストール
まずそれぞれのクラスタでSkupper Operatorをインストールします。
OpenShiftコンソールからOperatorHubを開き、Skupperを検索してインストールしましょう。
デフォルトの設定だとクラスタ全体でSkupper Operatorを利用可能ですが、特定のNamespaceのみを対象としてインストールすることも可能です。
今回はデフォルト設定のままインストールを行います。
Skupperの初期化
Skupper Operatorをインストールできたら続いて各NamespaceでSkupperの初期化を行います。
ここからはskupper
CLIを使用していきます。
Skupperのサイトに記載されている通り以下のコマンドでskupper
コマンドを導入することができます。
# For Linux or Mac curl https://skupper.io/install.sh | sh
導入されたskupper
コマンドを実行すると以下が表示されます。
skupper --- Usage: skupper [command] Available Commands: completion Output shell completion code for bash debug Debug skupper installation delete Delete skupper installation expose Expose a set of pods through a Skupper address gateway Manage skupper gateway definitions help Help about any command init Initialise skupper installation link Manage skupper links definitions revoke-access Revoke all previously granted access to the site. service Manage skupper service definitions status Report the status of the current Skupper site token Manage skupper tokens unexpose Unexpose a set of pods previously exposed through a Skupper address update Update skupper installation version version Report the version of the Skupper CLI and services Flags: -c, --context string The kubeconfig context to use -h, --help help for skupper --kubeconfig string Path to the kubeconfig file to use -n, --namespace string The Kubernetes namespace to use Use "skupper [command] --help" for more information about a command.
skupper
コマンドが導入できたら各Namespace上でskupper init
を実行します。
各クラスタにログインし、Linkを作成したいNamespaceへ変更しておきましょう。
## 以下をそれぞれのクラスタに対し実施 # ログイン oc login https://api.xxxxxxx.xxxx.openshiftapps.com:6443 --username $USER --password $PASSWORD # Namespace変更 oc project source # skupper初期化 skupper init --- Skupper is now installed in namespace 'source'. Use 'skupper status' to get more information.
ここで1つ気を付けるポイントとして、あて先クラスタのNamespaceはopenshift-image-registry
を指定します。
最終的なコンテナイメージのコピー先はdestination
Namespaceとなりますが、Link作成はコンテナレジストリのPod等が動いているこちらのNamespaceで実施する必要があります。
Tokenの生成とLink作成
続いてTokenを作成し、そのTokenを使いLinkを作成していきます。
今回はCI実行側のクラスタでTokenを生成し、それをあて先クラスタ側で適用します。
# Tokenの生成(CI実行側のクラスタで実施) skupper token create $HOME/secret.yaml
# Tokenの適用(あて先クラスタで実施) skupper link create $HOME/secret.yaml
それぞれのコマンドを実行する際にクラスタを切り替えるため適宜oc login
コマンドを実施しましょう。
正しくLinkが作成できると以下のコマンドで状況を確認できます。
skupper link status --- Link link1 is active
無事アクティブなLinkが作成されました。
せっかくなのでSkupperのコンソールでも状況を確認したいと思います。
コンソールのURLについてはskupper status
コマンドで確認できます。
# URLの確認 skupper status --- Skupper is enabled for namespace "source" in interior mode. It is connected to 1 other site. It has no exposed services. The site console url is: https://skupper-source.apps.xxxxxxx.xxxx.openshiftapps.com The credentials for internal console-auth mode are held in secret: 'skupper-console-users' # 認証情報の確認 oc get secret skupper-console-users -o json | jq .data.admin -r | base64 -d
ブラウザから表示されたURLにアクセスし認証を行うとSkupperコンソールが表示されます。
画面左の"Network"から2つのクラスタのNamespace間でLinkが張られていることが確認できます。
Serviceのexpose
Linkが作成できたら、あて先クラスタのopenshift-image-registry
Namespaceにあるimage-registry
Serviceをexposeすることで、CI実行側のクラスタからあて先クラスタのコンテナレジストリに対しアクセス可能とします。
あて先クラスタにログインし以下のコマンドを実行します。
# レジストリの公開 skupper expose service image-registry --address dest-registry
あらためてSkupperのコンソールを見てみましょう。
画面左の"Site"を選択するとexposed serviceとしてServiceが公開されているのが確認できました。
またCI実行側クラスタのコンソールを見ると、確かにdest-registry
という名前でServiceが作成されているのがわかります。
これでCI実行側のNamespaceからあて先クラスタのコンテナレジストリに対しアクセス可能な状態となりました。
CIパイプラインの実行
レジストリにアクセス可能な状態を作ることができたため、CIパイプラインを実行していきます。
TektonのPipelineについては前回の記事と同じものを利用します。
skopeo-pipeline.yaml (クリックで展開)
apiVersion: tekton.dev/v1beta1
kind: Pipeline
metadata:
name: skopeo-pipeline
spec:
workspaces:
- name: shared-workspace
- name: tmp-vol
params:
- name: git-url
type: string
- name: git-revision
type: string
- name: target-path
type: string
- name: dest-imageurl
type: string
tasks:
- name: git-clone-health
taskRef:
name: git-clone
kind: ClusterTask
params:
- name: url
value: $(params.git-url)
- name: revision
value: $(params.git-revision)
workspaces:
- name: output
workspace: shared-workspace
- name: build-container
taskRef:
name: s2i-nodejs
kind: ClusterTask
runAfter:
- git-clone-health
workspaces:
- name: source
workspace: shared-workspace
params:
- name: PATH_CONTEXT
value: $(workspaces.source.path)/$(params.target-path)
- name: IMAGE
value: image-registry.openshift-image-registry.svc:5000/source/health-record:latest
- name: copy-image
taskRef:
name: skopeo-copy
kind: ClusterTask
runAfter:
- build-container
workspaces:
- name: images-url
workspace: tmp-vol
params:
- name: srcImageURL
value: 'docker://image-registry.openshift-image-registry.svc:5000/source/health-record'
- name: destImageURL
value: $(params.dest-imageurl)
- name: srcTLSverify
value: 'false'
- name: destTLSverify
value: 'false'
CI実行側のクラスタに適用しておきましょう。
続いてレジストリへの認証情報とServiceAccountの紐付けです。
今回もあて先クラスタのdestination
Namespaceにおけるbuilder
から認証情報を取得します。
# 認証情報の取得 SECRET=$(oc -n destination get secret | grep builder-docker | awk {'print $1'}) oc -n destination get secret $SECRET -o jsonpath="{.data['\.dockercfg']}" | base64 --decode | jq '.["image-registry.openshift-image-registry.svc:5000"].password'
こちらをpipeline-dockercfgから始まるSecretに追加していくのですが、今回はここであて先となるレジストリサーバーのアドレスにクラスタ内部のdest-registry
Serviceのアドレスを指定します。
パスワードには取得した認証情報を登録します。 これでCIパイプラインによりイメージをコピーする準備が整いました。
前回と同様にTektonのPipelineRunを作成し、実行してみましょう。
skopeo-pipelinerun.yaml (クリックで展開)
apiVersion: tekton.dev/v1beta1
kind: PipelineRun
metadata:
generateName: skopeo-pipeline-run-
spec:
pipelineRef:
name: skopeo-pipeline
params:
- name: target-path
value: 'site'
- name: git-url
value: 'https://gitlab.com/jpishikawa/starter-kit-cicd-app'
- name: git-revision
value: 'main'
- name: dest-imageurl
value: 'docker://dest-registry.source.svc:5000/destination/starter-kit-cicd-app'
workspaces:
- name: shared-workspace
volumeClaimTemplate:
spec:
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 1Gi
- name: tmp-vol
emptyDir: {}
.spec.params.dest-imageurl
の中であて先のレジストリのアドレスを記載していますが、今回はこちらをdest-registry
Serviceのアドレスに書き換えています。
PipelineRunを適用してしばらく待つとPipeline実行が成功し、無事にskopeoによるイメージのコピーまで完了したことを確認できます。
またあて先クラスタのコンソールからイメージストリームを確認すると無事にイメージが保管されています。
Skupperを通じてイメージのコピーを実行することができました!
まとめ
前回の方法ではコンテナレジストリのrouteを外部公開していましたが、今回はSkupperを使うことでコンテナレジストリへのアクセスを実現しました。
今回はCIパイプラインと組み合わせてSkupperを使用してみましたが、Skupper自体には他にも色々な用途があると考えられます。記事の中でもご紹介した通り、OpenShiftにはSkupper Operatorもあり、比較的簡単に試すことができるため皆さんもぜひ触ってみて下さい。