Red Hat OpenShift on IBM Cloudで、OpenShift GitOpsを試す (アプリデプロイ編)

# はじめに
GitOpsは、Gitリポジトリに格納されている設定・情報を正として、対象のインフラ環境・アプリケーション環境をGitリポジトリ内の状態と同期させることで、環境の状態を一元的に管理できるようにするという考え方・手法です。

前記事「[Red Hat OpenShift on IBM Cloudで、OpenShift GitOpsを試す (導入編)](https://qiita.com/hisato_imanishi/private/8495b129ad5d3bc7aafd)」では、GitOpsを実現するSWとして、IBM CloudのマネージドなOpenShift環境である Red Hat OpenShift on IBM Cloud上に、「[OpenShift GitOps](https://access.redhat.com/documentation/ja-jp/openshift_container_platform/4.7/html/cicd/gitops)」を導入しました。

当記事ではその続編として、OpenShift GitOpsを用いて、サンプルのアプリケーションをOpenShiftにデプロイしてみます。

また、アプリケーションの定義(デプロイするコンテナイメージのタグ)を変更し、GitHubにpushすることで、OpenShiftに自動的に変更内容が反映されることを確認します。

# 環境
- Red Hat OpenShift on IBM Cloud 4.7.12 (VPC Gen 2環境に作成)
- OpenShift GitOps 1.1

※当記事の作成時点ではRed Hat OpenShift on IBM Cloudの最新バージョンが4.6であり、スクリーンショットはRed Hat OpenShift on IBM Cloud 4.6、および、(4.6に導入可能であった)OpenShift GitOps 1.0時点のものになります(OpenShiftのWeb管理コンソールが4.6では英語ですが、4.7からは日本語対応しています)。ただ、記事本文は上記記載の環境に準拠しています。


# 前提
- OpenShiftクラスターが既に作成済みであること
- 「[Red Hat OpenShift on IBM Cloudで、OpenShift GitOpsを試す (導入編)](https://qiita.com/hisato_imanishi/private/8495b129ad5d3bc7aafd)」が実施済みであること
- ローカル端末にOpenShift CLI(ocコマンド)が導入済みであること
- GitHubのアカウントを持っていること


# デプロイするアプリケーション(のマニフェストファイル)の準備
デプロイするアプリケーションは、OpenShift GitOpsに含まれるGitOpsソフトウェア「[Argo CD](https://argoproj.github.io/argo-cd/)」 が提供しているサンプルWebアプリケーション「[guestbook](https://github.com/argoproj/argocd-example-apps/tree/master/guestbook)」を使用します。

このサンプルWebアプリケーションは、Apacheコンテナ上のWebアプリケーションで、コンテナイメージがGCR(Google Container Registry)上に配置されています。「guestbook」の[GitHubリポジトリ](https://github.com/argoproj/argocd-example-apps/tree/master/guestbook)では、このコンテナイメージをデプロイするためのKubernetesマニフェストファイルが配置されています。

OpenShift GitOpsを試すうえでこのGitHubリポジトリや、これを自分のアカウントにForkしたリポジトリを使用することもできますが、いずれもパブリックなリポジトリとなります。

実際の運用を考慮した場合、パブリックなリポジトリを使用することはおそらく無いと思いますので、ここでは自分のアカウントにプライベートなリポジトリを作成し、「guestbook」の[GitHubリポジトリ](https://github.com/argoproj/argocd-example-apps/tree/master/guestbook)からファイルをコピーし、commit・pushして使用することにします。

GitHubに自分のプライベートなリポジトリを作成し、以下の4つのファイルをcommit・pushしてください。

**guestbook-ui-deployment.yaml**
「guestbook」の[GitHubリポジトリ](https://github.com/argoproj/argocd-example-apps/tree/master/guestbook)から取得し、一部改変しています(resources -> limitsを追加)。


```yaml:guestbook-ui-deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: guestbook-ui
spec:
  replicas: 1
  revisionHistoryLimit: 3
  selector:
    matchLabels:
      app: guestbook-ui
  template:
    metadata:
      labels:
        app: guestbook-ui
    spec:
      containers:
      - image: gcr.io/heptio-images/ks-guestbook-demo:0.2
        name: guestbook-ui
        ports:
        - containerPort: 80
        resources:
          limits:
            memory: "256Mi"
            cpu: "500m"
```


**guestbook-ui-svc.yaml**
「guestbook」の[GitHubリポジトリ](https://github.com/argoproj/argocd-example-apps/tree/master/guestbook)から取得し、オリジナルから変更はありません。

```yaml:guestbook-ui-svc.yaml
apiVersion: v1
kind: Service
metadata:
  name: guestbook-ui
spec:
  ports:
  - port: 80
    targetPort: 80
  selector:
    app: guestbook-ui
```

**guestbook-ui-route.yaml**
OpenShiftにデプロイするにあたり作成したファイルです。OpenShiftでアプリケーションを外部公開する場合、Routeリソースを使用することが多く、これを作成するために``oc expose``コマンドを使用することが多いですが、コマンドで作成したリソースがGitリポジトリに無いと、Argo CDから「同期できていない」と認識されるため、Routeリソースもマニフェストファイルで定義します。

```yaml:guestbook-ui-route.yaml
apiVersion: route.openshift.io/v1
kind: Route
metadata:
  labels:
    app: guestbook-ui
  name: guestbook-ui
spec:
  to:
    kind: Service
    name: guestbook-ui
    weight: 100
```


**argocd-guestbook-rolebinding.yaml**
[Argo CDのサンプル](https://github.com/redhat-developer/openshift-gitops-getting-started/blob/main/cluster/namespace/spring-petclinic-rolebinding.yaml)をベースに作成したファイルになります。OpenShift上でOpenShift GitOps(Argo CD)を使用する場合、対象のネームスペースにおいて、OpenShift GitOpsのServiceAccountにadmin ClusterRuleを付与する必要があります。これにより、Argo CDが対象のネームスペースに対してデプロイ処理を実施できるようになります。

このRoleBindingはネームスペースごとに適用する必要があります。

```yaml:argocd-guestbook-rolebinding.yaml
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
  name: argocd-guestbook-role-binding
  namespace: argocd-guestbook
roleRef:
  apiGroup: rbac.authorization.k8s.io
  kind: ClusterRole
  name: admin
subjects:
- kind: ServiceAccount
  name: openshift-gitops-argocd-application-controller
  namespace: openshift-gitops
```

もう1つ別の方法としては、以下のコマンドで権限を付与することも可能です。こちらの方法は一度実行すればOKで、ネームスペースごとの適用は不要です。

```bash
oc adm policy add-cluster-role-to-user cluster-admin -z openshift-gitops-argocd-application-controller -n openshift-gitops
```

# GitHubでのPersonal access tokenの発行
OpenShift GitOps(Argo CD)がプライベートなGitHubリポジトリにアクセスするには、GitHub側でPersonal access tokenを発行する必要があります。以下の手順で実施ください。

GitHubにアクセスし、画面右上のプロフィール画像→「Settings」→「Developer Settings」→「Personal access tokens」と辿ります。

「Generate new token」ボタンをクリックします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/386149/8ba010c8-5d99-1f77-2b06-f46b2d214e5b.png)

「Note」にトークンの説明を入力し、チェックボックス「repo」にチェックを入れ、「Generate token」ボタンをクリックします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/386149/362eb64c-323d-f4e2-30fb-4d167178a7d1.png)

すると、Personal access tokenが発行されるのでそれをメモしておきます。


# OpenShiftでのプロジェクト(ネームスペース)作成
以下のコマンドで、アプリケーションをデプロイする対象のプロジェクト(ネームスペース)を作成します。

```bash
oc new-project argocd-guestbook
```

また、guestbookアプリケーションのコンテナではApacheが稼働しますが、Apacheは80ポートを使用しています。80ポートを使用するためにはroot権限が必要ですが、OpenShiftで実行されるコンテナは、OpenShiftがランダムに割り当てたUIDで実行されるため、80ポートを使用することができません。

これを解決するため、対象プロジェクトのServiceAccount 「default」に対してanyuid SCCを付与し、ランダムなUIDではなく、コンテナイメージのDockerfileのUSERインストラクションで指定されているユーザでコンテナを実行できるようにする必要があります。

対象プロジェクトにおいて以下のコマンドを実行し、anyuid SCCを付与します。

```bash
oc adm policy add-scc-to-user anyuid -z default
```


# OpenShift GitOps(Argo CD)の設定
それではここからOpenShift GitOps(Argo CD)を設定し、アプリケーションをデプロイしていきます。

まず、アプリケーションのマニフェストファイルが存在するGitHubリポジトリを設定します。

Argo CDにログインし、左側の歯車アイコンをクリックし、「Repositories」をクリックします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/386149/09c61df8-5718-9d88-5257-abc0fc3308ff.png)


「CONNECT REPO USING HTTPS」ボタンをクリックします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/386149/c5835303-c177-be13-d1b2-a3de2d421c5e.png)


以下の値を入力し、「CONNECT」ボタンをクリックします。

- Repository URL　：　GitHubリポジトリのURL(末尾が .git で終わるURL)
- Username　：　任意の値(Personal access tokenを使用する場合、Usernaemは何でもよい)
- Password　：　上記でメモしたPersonal access token
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/386149/137e29a2-7723-91a0-5fa9-6708ef0aa58b.png)


すると、以下のように接続済みのリポジトリが登録され、「Successful」と表示されます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/386149/5ffc5ca5-0f89-e911-f829-1e29d63048aa.png)


次に、アプリケーションをデプロイしていきます。

アプリケーションのダッシュボードから「+ NEW APP」ボタンをクリックします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/386149/5f89dca3-4a2f-1d1f-9cad-743b502631e4.png)


以下の通り入力し、「CREATE」ボタンをクリックします。

| 項目名 | 値 | 備考 |
|:-|:-|:-|
| Application Name  |  アプリケーションの任意の名前 |  |
| Project  | default  |  |
| SYNC POLICY  | Automatic  | Gitリポジトリの更新に応じて自動的に同期する設定 |
| PRUNE RESOURCES | チェックを付ける | 削除されたマニフェストファイルがある場合、OpenShift上のリソースも削除する |
| Repository URL  | GitHubリポジトリのURL  |  |
| Revision  | HEAD  |  |
| Path  | .   | リポジトリのルートにマニフェストファイルを置いている場合「.」を入力 |
| Cluster URL  | https://kubernetes.default.svc  | Argo CDが載っているクラスターを指す場合は左記の値を設定 |
| Namespace  | デプロイ対象のネームスペース  |
| DIRECTORY RECURSE  | チェックを付ける   | サブディレクトリのマニフェストファイルも同期対象とする |

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/386149/4c39ceb0-47a2-077d-32a5-f47ff9fdbe89.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/386149/fd0e4713-c90b-7264-177e-c119ec7ad56a.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/386149/876d2a44-abe7-8913-b2c6-ff71f03a4dca.png)


Argo CD上でアプリケーション(の定義)が作成されます。アプリケーションの詳細を確認するため、赤枠部分をクリックします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/386149/d230b2e4-ac24-680f-2801-bd5570b9dde3.png)


アプリケーションの詳細です。マニフェストファイルで定義された各種のリソースが作成されていることが分かります。また、赤枠部分の「Healthy」「Synced」「Sync OK」の表示から、GitリポジトリとOpenShiftの状態が同期され、アプリケーションが正常に動作していることも分かります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/386149/569e66f9-33b5-e45a-ea47-31a7e6b5aeb1.png)


OpenShiftのWebコンソールのDeveloperパースペクティブで、対象プロジェクトの「Topology」を確認します。Argo CDで同期したguestbookアプリケーションがデプロイされていることが分かります。アプリケーション右上のアイコン(赤枠部分。右斜め上の矢印アイコン)をクリックすると、アプリケーション(Fancy Guestbook)にアクセスすることができます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/386149/e5f4b9f2-5e05-9bd6-f763-71f425e60efd.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/386149/dcb6eda6-fb91-8f67-5e35-183282cb9fdd.png)



次に、アプリケーションのマニフェストファイルの定義を変更し、GitHubにpushしたとき、自動的にOpenShift上のアプリケーションの状態が同期されることを確認します。

guestbook-ui-deployment.yaml の image のタグを 0.2 -> 0.1 に変更します(バージョンを落としてみます)。

```yaml:guestbook-ui-deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: guestbook-ui
spec:
  replicas: 1
  revisionHistoryLimit: 3
  selector:
    matchLabels:
      app: guestbook-ui
  template:
    metadata:
      labels:
        app: guestbook-ui
    spec:
      containers:
      - image: gcr.io/heptio-images/ks-guestbook-demo:0.1   # ここを変更
        name: guestbook-ui
        ports:
        - containerPort: 80
        resources:
          limits:
            memory: "256Mi"
            cpu: "500m"
```

変更したファイルをGitHubリポジトリにpushし、しばらく(数分程度)待つと、以下のように「OutOfSync」の状態であることが検知され、自動的に同期処理が実行されます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/386149/0c97f31e-50d6-bc47-390d-ea545ef50911.png)


同期処理が完了すると、再度「Synced」「Sync OK」の状態になります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/386149/1d4ca017-fd77-6a61-1812-798da10a6fa7.png)


Podの状態を確認すると、イメージのタグが 0.1 となっており、Gitリポジトリ内のマニフェストファイルと同期されていることが分かります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/386149/95c0b7d7-14d1-4fce-1b11-6d1264a3b8df.png)

以上です。