ROSA に独自ドメイン用の IngressController を追加する

# はじめに

この手順は `OCP 4.14` を使用した `ROSA` を前提にしています。
`ROSA HCP`を使用していますが、`ROSA Classic` でも同様（のはず）です。

# このドキュメントの背景

`ROSA` (`OCP 4.13.x`) では、`CDO (Custom Domain Operator)` を使って、独自ドメイン用の追加 `IngressController` を作成していましたが、`OCP 4.14.x` 以降の `ROSA` では、`CDO` が非推奨になり、独自ドメイン用の `IngressController` も標準の `IngressController` リソースを作って作成されるようになりました。

ここでは、その手法を実際に解説しています。

# ROSA 標準のドメイン

通常の self managed の OpenShift で独自ドメインを使用するには、ユーザーがレジストラからドメインを購入してそのドメインを IngressController で使用する必要するがあります。

ROSA では、デフォルトで外向きのドメインが提供されています。デフォルトで提供されているドメインは以下のコマンドで確認できます。

```
rosa list ingress -c myhcpcluster
```

出力例：
```
$ rosa list ingress -c myhcpcluster
ID    APPLICATION ROUTER                                        PRIVATE  DEFAULT  ROUTE SELECTORS  LB-TYPE  EXCLUDED NAMESPACE  WILDCARD POLICY  NAMESPACE OWNERSHIP
v8e4  https://apps.rosa.myhcpcluster.rc4b.p3.openshiftapps.com  no       yes                       nlb                                           
$ 
```

上記の例の出力の `apps.rosa.myhcpcluster.rc4b.p3.opeshiftapps.com` というドメインをワイルドカードにした`*.apps.rosa.myhcpcluster.rc4b.p3.opeshiftapps.com`というホスト名がユーザーが作成したアプリケーションに使われます。

`*` の部分の文字列は、HTTPレイヤーではアプリケーションを区別するのに使用されますが、IPアドレスとしては ELB が同じIPに解決されます。

```
$ dig test.apps.rosa.myhcpcluster.rc4b.p3.openshiftapps.com +short
13.113.213.84
$ dig hello.apps.rosa.myhcpcluster.rc4b.p3.openshiftapps.com +short
13.113.213.84
$ 
```

:::note info
同じIPアドレスで複数の HTTP/HTTPS アプリケーションをホストする方法は、IPアドレスの節約のために一般的に用いられている方法です。

HTTPSの場合は、証明書を一枚に統一する事ができるようになるので、証明書の維持コストの削減にも繋がります。
:::

# 独自ドメイン用の IngressController

この手順では `*.apps.rosa.myhcpcluster.rc4b.p3.openshiftapps.com` のようなホスト名ではなく、`*.ocp4.work` のようなユーザーが取得した独自ドメインを使用する IngressController を追加で作成してみます。

証明書は Let's Encrypt を使用して作成します。

 :::note info

独自ドメインのアプリ(例：`hello.mycompany.com`) は、追加の `IngressController` を作成せずとも、標準の `IngressController` を使って作成する事も可能ですが、ここではその方法については触れません。
:::


# 独自ドメインの取得

ここでは、`ocp4.work` というドメインを お名前.com で取得しました。そのため、取得したドメインは、最初は、お名前.com の DNSサーバーによって管理されています。

取得したドメインを使うだけなら、そのままでも良いのですが、Route53ユーザーが多いと思うので、お名前.com から Route53 にドメイン(Zone) の管理を移管します。

:::note info
この手順では触れませんが、Route53にドメインの管理を移管しておくと、OpenShift の Cert-Manager を使ったドメインの証明書の自動更新の仕組みも使えるようようになります。
:::


まず、AWS Route53 に Zone を作成してホストする事にします。詳細な手順は省略しますが、Route53 上に取得した自分のドメインの Zone を作成します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/99425/7296c3f6-7100-0f44-3758-c4cd4ae535b2.png)



Route53上でゾーン(ドメインの入れ物) を作成すると、画面に、そのゾーンを管理する NSレコード (DNSサーバーのアドレス) が表示されます。上記の表示の `ns-711.awsdns-24.net` `ns-1066.awsdns-05.org` .... がそれです。可用性を保つために複数のDNSサーバーが提供されます。


Route53で提供された DNSサーバー名をお名前.com 側の管理ツールに入力して、暫く待ちます。
以下は お名前.com の DNSサーバーの設定変更画面です。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/99425/68f64d94-c53e-bdc2-c7ea-05c5c7716f97.png)

以下のコマンドを指定して、NSレコードの状態を確認できます。

```
$ dig <取得したドメイン名> ns +short
```

指定した DNSサーバーに変更されるまで待ちます。

親となるドメインの複数のDNSサーバーに対して情報更新を行う(しかもその親は複数のドメインの親である）ので、暫く時間がかかる事があります。私の場合は1時間ほどで更新されました。

```
$ dig ocp4.work ns +short
01.dnsv.jp.                   # 初期状態。ドメイン取得元(お名前.com) の NS サーバーが表示されている。
03.dnsv.jp.
02.dnsv.jp.
04.dnsv.jp.
$

<お名前.com 側の Interface で、Route53から提供された DNSサーバー名を入力>
<待つ事およそ一時間 (管理コンソールのメッセージによると24時間くらいかかる事もあるとの事) >

$ dig ocp4.work ns +short
ns-1781.awsdns-30.co.uk.  # AWSが提供する DNSサーバーが表示されるようになる。
ns-711.awsdns-24.net.
ns-51.awsdns-06.com.
ns-1066.awsdns-05.org.
$ 
```

Route53 の DNSサーバーの値が NS レコードとして返ってくれば Route53での取得ドメインのホストが開始されています。

`dig` コマンドの `+short` というオプションは出力を簡略化してくれるオプションなので覚えて置くと便利です。



# 証明書の取得

今回は、Let's Encrypt で証明書を作成します。

:::note warn
AWS環境だと ACM (AWS Certificate Manager) で、証明書が発行をしたくなりますが、ACMは、AWSのサービスである ELBやCloudFront 等のサービスに対してのみ証明書が発行できる仕組みです。EC2上等で稼働する一般のアプリケーションに対して証明書を発行(サーバー証明書と秘密鍵をファイルとして Export する）機能は持っていません。
:::


**作業環境を整える**

後のコマンドがコピペで済むようにするため、必要な情報を環境変数にセットします。
この例では、`ocp4.work` という独自ドメインを取得したので、それを使用します。

```
$ CERT_DIR=~/mycert
$ mkdir -p $CERT_DIR
$ EMAIL="myemail@test.com"             # 有効な email アドレス
$ DOMAIN="ocp4.work"                   # 取得した独自ドメイン
```


**Let's Enrypt証明書の取得に必要なソフトウェアのインストール**

certbot と呼ばれる Let's Encrypt のモジュールを適当な環境にインストールします。インターネットに接続できる環境である必要があります。作業手順を考えると oc コマンドが実行でき ROSAクラスターにアクセスできるようにセットアップされた環境が便利です。

私の環境は Amazon Linux 2 の環境なので、[こちらの公式ガイド](https://docs.aws.amazon.com/ja_jp/AWSEC2/latest/UserGuide/SSL-on-amazon-linux-2.html#letsencrypt)を見ながら以下のコマンドを実行しました。

```
$ sudo wget -r --no-parent -A 'epel-release-*.rpm' https://dl.fedoraproject.org/pub/epel/7/x86_64/Packages/e/
$ sudo rpm -Uvh dl.fedoraproject.org/pub/epel/7/x86_64/Packages/e/epel-release-*.rpm
$ sudo amazon-linux-extras install epel -y
$ sudo yum install -y certbot python2-certbot-apache 
```


**証明書取得の開始(certbot コマンドの実行)**

certbot の実行。証明書は `*.` でワイルドカード証明書を取得しています。

```
certbot certonly --manual \
   --preferred-challenges=dns \
   --email $EMAIL \
   --agree-tos \
   --config-dir "$CERT_DIR/config" \
   --work-dir "$CERT_DIR/work" \
   --logs-dir "$CERT_DIR/logs" \
   -d "*.$DOMAIN" 
```

:::note warn
<details><summary>テストで何度も証明書を発行を繰り返す可能性がある場合の注意</summary>


一週間に5回以上、同じリクエストをすると Rate Limit にひっかかり、以下のようなエラーがでる事があります。

```
too many certificates (5) already issued for this exact set of domains in the
last 168 hours: example.com login.example.com: see https://letsencrypt.org/docs/duplicate-certificate-limit
```

この事象については、[こちらのブログ](https://letsencrypt.org/docs/duplicate-certificate-limit/) に記載があります。

発行対象の名前を変更する方法もありますが、回避策の一つとして、テスト用に何度も発行する事が想定する時は、` --test-cert` オプションを付けておく方法があります。

```
certbot certonly --manual \
   --preferred-challenges=dns \
   --email $EMAIL \
   --agree-tos \
   --config-dir "$CERT_DIR/config" \
   --work-dir "$CERT_DIR/work" \
   --logs-dir "$CERT_DIR/logs" \
   -d "*.$DOMAIN" \
   --test-cert
```

ただし、この場合の Root CA は通常のブラウザなどには含まれてないものになりますので、curl だと -k オプションを使用するか、Root CA の証明書をダウンロードしておく必要があります。[こちらの記事](https://letsencrypt.org/docs/staging-environment/) に詳細の解説があります。

</details>
:::

certbot コマンドを実行すると以下のような出力が出てきます。**慌てて Enter を押さず、一回止まって指示を良く読みます。**

```
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Would you be willing, once your first certificate is successfully issued, to
share your email address with the Electronic Frontier Foundation, a founding
partner of the Let's Encrypt project and the non-profit organization that
develops Certbot? We'd like to send you email about our work encrypting the web,
EFF news, campaigns, and ways to support digital freedom.
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
(Y)es/(N)o: y　　　　　　　　　# ここは お好みで。
Account registered.
Saving debug log to /home/ec2-user/mycert/logs/letsencrypt.log
Plugins selected: Authenticator manual, Installer None
Requesting a certificate for *.ocp4.work
Performing the following challenges:                     # Challenge を実行して下さいと指示をしている。
dns-01 challenge for ocp4.work

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Please deploy a DNS TXT record under the name            # DNS TXT レコードを設定しなさいと指示が出ている。
_acme-challenge.ocp4.work with the following value:      # _acme-challenge.ocp4.work という TXT レコードに

L_BVE3S_cAeHEnodB2xwLCcZYxStOeUutxlTevhX2NQ              # L_BVE3S_cAeHEnodB2xwLCcZYxStOeUutxlTevhX2NQ  という値を設定

Before continuing, verify the record is deployed.        # これ以上進む前に、TXTレコードがデプロイされた確認する。
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Press Enter to Continue
```

上記のメッセージを解読すると DNS 上に `_acme-challenge.ocp4.work` という TXT レコードを作成し、そのレコードに`L_BVE3S_cAeHEnodB2xwLCcZYxStOeUutxlTevhX2NQ`  という値を設定しな、レコードがインターネット上から解決できる状態になったら、Enter をクリックして下さい。と言っています。

:::note info
ドメインを管理している DNS に、指定された値を追加する事で、このドメインの編集権限がある持ち主である事を証明しています。証明書の発行母体(この場合 Let's Encrypt)から与えられるこの課題を `Challenge` と呼びます。証明書を発行してもらうには、この`Challenge`に応える必要があります。

独自ドメインをホストするDNSサーバーは、闇で立てたDNSサーバーのようなものは使う事はできず、ドメインを購入したレジストラ等で「このDNSサーバーでホストします」登録する必要があります。[example.com]を取得した場合は、上位の[.com] の DNS権威サーバーに、子ゾーンである [example.com] の DNS権威サーバーのアドレスを登録する必要があります。

今回の例では、お名前.com(レジストラ）の設定画面で、Route53 の DNSサーバー名を登録した作業がこれに当たります。[ocp4.work]というドメインを取得しましたが、[.work]の権威DNSサーバーに[ocp4.work]をホストする権威DNSサーバーとして、Route53のDNSサーバーを登録した事になります。
:::

**DNSへのレコードの登録**

今回の場合は、独自ドメイン`ocp4.work`の権威DNSサーバーを、Route53にしているので、Route53の該当画面に飛び、指定された TXT レコードを登録します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/99425/5acc7db4-e6f6-708b-8557-9462cbac9232.png)

レコードを登録したら、以下のコマンドで値が返ってくるまで待ちます。

```
dig (_acme-challenge.ではじまる指定されたドメイン名)  TXT +short 
```

どのくらいでレコードが反映されるかは、事業者毎によって違います。[Route53の場合は、通常1分程度](https://aws.amazon.com/jp/route53/faqs/) で反映されるようです。

```
$ dig _acme-challenge.ocp4.work TXT +short      # TXT レコードを指定
$                                               # 何も出てこないので暫く待つ。
<暫く待つ>
$ dig _acme-challenge.ocp4.work TXT +short       
"45D1lL4FxRuV__fBdgApFH9uNtNixDiSLzSs0duC0Lk"   # 登録した TXT レコードが表示される (状況によりますが、今回は1分程度で出てきました）
```


**certbot コマンドの実行画面に戻る**

TXT レコードが表示されるようになったら、certbotコマンドを実行していた画面で Enter を実行します。
端末によって DNSレコードの反映に少し時間差がある場合もあるので、あまり急いでテキパキと操作をしない方が良いです。(challenge に失敗すると certbot の実行からやり直しになり、DNSへの登録もやり直しになります)

```
<省略>
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Please deploy a DNS TXT record under the name            # DNS TXT レコードを設定しなさいと指示が出ている。
_acme-challenge.ocp4.work with the following value:      # _acme-challenge.ocp4.work という TXT レコードに

vl-6-7guKT4ShQS0OtNLBp1VtNgHQdiu1VpbFVeVC6I              # vl-6-7guKT4ShQS0OtNLBp1VtNgHQdiu1VpbFVeVC6I  という値を設定

Before continuing, verify the record is deployed.
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Press Enter to Continue
Waiting for verification...
Cleaning up challenges
Non-standard path(s), might not work with crontab installed by your operating system package manager

IMPORTANT NOTES:
 - Congratulations! Your certificate and chain have been saved at:      # Challenge 成功です。
   /home/ec2-user/mycert/config/live/ocp4.work/fullchain.pem            # 証明書は左のパスに保存されています。
   Your key file has been saved at:
   /home/ec2-user/mycert/config/live/ocp4.work/privkey.pem　　　　       # 秘密鍵は左のパスに保存されています。
   Your certificate will expire on 2023-03-27. To obtain a new or
   tweaked version of this certificate in the future, simply run
   certbot again. To non-interactively renew *all* of your
   certificates, run "certbot renew"
 - If you like Certbot, please consider supporting our work by:

   Donating to ISRG / Let's Encrypt:   https://letsencrypt.org/donate
   Donating to EFF:                    https://eff.org/donate-le

$ 
```

これで証明書(=公開鍵を含んだ物体)と秘密鍵が生成されました。
念のため、生成された書かれているディレクトリを確認してみます。

```
$ ls $CERT_DIR/config/live/$DOMAIN
README  cert.pem  chain.pem  fullchain.pem  privkey.pem
$
```

それっぽいものが生成されているのがわかります。

ここのファイルが何かを解説するには、Webの証明書の仕組みを解説する必要があるので、説明は省略しますが、私達が注目すべきは、`fullcahin.pem` と `privkey.pem` の2つのファイルです。

# 証明書の Secret の作成

後々のコマンドを楽にするために、変数に証明書があるパスを設定しておきます。
```
MY_CERT=$CERT_DIR/config/live/$DOMAIN
```


発行された証明書と秘密鍵を使った `Secret` を作成します。この `Secret` は、`openshift-ingress` `project` 内に作成される必要があります。

```
oc create secret tls my-tls --cert=$MY_CERT/fullchain.pem --key=$MY_CERT/privkey.pem -n  openshift-ingress
```

`Secret` 名 `my-tls` が作成された事を確認します。

```
$ oc get secret my-tls -n openshift-ingress
NAME     TYPE                DATA   AGE
my-tls   kubernetes.io/tls   2      15s
$ 
```

# 追加IngressControllerの作成

```
oc project openshift-ingress-operator
```

以下の yaml を apply して追加 `IngressController` を作成します。
追加 `IngressController` の名前は `additional` としています。

```
cat << EOF | oc apply -f -
apiVersion: operator.openshift.io/v1
kind: IngressController
metadata:
  annotations:
    ingress.operator.openshift.io/auto-delete-load-balancer: "true"
  finalizers:
  - ingresscontroller.operator.openshift.io/finalizer-ingresscontroller
  labels:
    hypershift.openshift.io/managed: "true"
  name: additional
  namespace: openshift-ingress-operator
spec:
  clientTLS:
    clientCA:
      name: ""
    clientCertificatePolicy: ""
  defaultCertificate:
    name: my-tls
  domain: $DOMAIN
  endpointPublishingStrategy:
    loadBalancer:
      dnsManagementPolicy: Managed
      providerParameters:
        aws:
          networkLoadBalancer: {}
          type: NLB  
        type: AWS
      scope: External
    type: LoadBalancerService
  httpCompression: {}
  httpEmptyRequestsPolicy: Respond
  httpErrorCodePages:
    name: ""
  replicas: 2
  tuningOptions:
    reloadInterval: 0s
  unsupportedConfigOverrides: null
EOF
```

:::note info
yaml は、デフォルトの `IngressController` を `oc get -o yaml` してベースを作成し、`metadata.name` を `additional` にし、`spec.defaultCertificate.name` に、作成した Secret 名 `my-tls`を指定、`spec.domain` には、`$DOMAIN` (ocp4.work)を指定しています。
:::

`IngressController` が作成されたか以下のコマンドで確認します。

```
$ oc get ingresscontroller
NAME         AGE
additional   2m31s
default      8h
$
```

`Router pod` が作成されている事を確認します。以下のコマンドで確認できます。

```
$ oc get pods -n openshift-ingress
NAME                                 READY   STATUS    RESTARTS   AGE
router-additional-6667c9f8d6-5gr5l   1/1     Running   0          7m33s
router-additional-6667c9f8d6-bmtrl   1/1     Running   0          7m33s
router-default-578b69d8f4-k99j7      1/1     Running   0          8h
router-default-578b69d8f4-tq9m8      1/1     Running   0          8h
$
```

ここでは、上の `router-additional-<ランダム>` という名前がついた Pod が、追加の `IngressController` 用の `Router Pod`です。

:::note info

`IngressController` リソースを作成する `project` は、`openshift-ingress-operator` ですが、それによって生成される `Router Pod` は、`openshift-ingress` という別の `project` 内に作成されます。
:::

# 追加 IngressControler 用に作成された NLB のドメインに CNAMEする

`IngressController` オブジェクトに `additional` という名前を付けたので、`additional` という名前が入った `kind:Service Type=LoadBalancer` が生成されているはずです。LoadBalancer で使われているドメイン名を取得します。
この Service オブジェクトは、openshift-ingress プロジェクト内に作成されています。

```
$ oc get svc  -n openshift-ingress | grep additional | grep  LoadBalancer
router-additional            LoadBalancer   172.30.170.214   ae404960926084e3c898cc0df3dfeb52-28d0487bfc639c47.elb.ap-northeast-1.amazonaws.com   80:30318/TCP,443:31344/TCP   3m21s
$ 
```

NLB ドメインが `ae404960926084e3c898cc0df3dfeb52-28d0487bfc639c47.elb.ap-northeast-1.amazonaws.com` である事がわかります。

**情報の整理**
この作業で使うドメインは以下の2つです。

[独自ドメイン]： `ocp4.work`  お名前.com で取得し、Route53 に管理を移管したドメイン。
[追加 `IngressController` によって作られたドメイン(`AWS` `NLB`名)]: `ae404960926084e3c898cc0df3dfeb52-28d0487bfc639c47.elb.ap-northeast-1.amazonaws.com`

**CNAME**
独自ドメイン `*.ocp4.work` へのアクセスを、IngressController によって作られたNLBのドメイン　`ae404960926084e3c898cc0df3dfeb52-28d0487bfc639c47.elb.ap-northeast-1.amazonaws.com`　に誘導するには CNAMEという作業をします。

Route53 の `ocp4.work` ゾーンに以下の黄色でハイライトしている CNAMEレコードを追加します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/99425/5aa8c489-adf0-fda7-cc71-3d2b2f7483f2.png)


:::note info
Route53 の独自機能でエイリアスという機能があり、それを使用しても上記の CNAMEと同様な事が実現可能です。が、ここでは RFCで定められた標準的な CNAMEを使って設定を行っています。
:::

1分程度したら、*.ocp4.work の * の所を適当な文字列にして、dig で状況を確認してみます。DNS上にレコードとして`*`で登録しているので、どんな文字列でもDNSレコードにマッチして解決されるはずです。(abc **.** def **.** ocp4.work のようなものは **.** が2つあるのでマッチしません)

ここでは、`test.ocp4.work` に対して dig を実行してみます。

```
$ dig test.ocp4.work 

<省略>

;; ANSWER SECTION:
test.ocp4.work.         0       IN      CNAME   ae404960926084e3c898cc0df3dfeb52-28d0487bfc639c47.elb.ap-northeast-1.amazonaws.com.
ae404960926084e3c898cc0df3dfeb52-28d0487bfc639c47.elb.ap-northeast-1.amazonaws.com. 0 IN A 54.248.114.57

<省略>
```

`test.ocp4.work` は、先ほど設定した CNAME により `ae404960926084e3c898cc0df3dfeb52-28d0487bfc639c47.elb.ap-northeast-1.amazonaws.com` (NLBのドメイン名) に誘導され、さらに NLBドメイン名がIPアドレスに解決されている事がわかります。

この CLIの画面からはわかりませんが、CLBのIPに到達したトラフィックは、さらに `OpenShift` 上の `Router Pod` (実際のHTTP/Sトラフィックの処理を行うPod) にフォワードされるように設定されています。

**Router Podでの処理**

前述のように`[独自ドメイン]->[NLBドメイン]->(NLB IPアドレス) -> (Router Pod IPアドレス)`と言う流れでトラフィックの宛先が変わっていきます。

`IngressController` オブジェクトを作成した時に、証明書の `Secret` を指定しましたが、この証明書は、`Router Pod` に渡されています。そのため `Router Pod` は `HTTPS`を復号化する事ができます。

`Route Pod` は、HTTP/Sのリクエストと一緒にやってきた宛先のドメインの情報を見て、どのユーザーの `Service` (Kbuerentes で定義されているリソース) にフォワードするか決定します。そのためには、ドメイン名とユーザーの`Service` 名の紐付けの設定が書かれたオブジェクトが、アプリケーション毎に別途必要です。これを `OpenShift` では、`Route`リソースと呼んでいます。 

`Route`リソースは、Kuberentes の `Ingerss` リソースの元になったもので、YAMLの記述内容も `Ingress` とかなり似たものになっています。

OpenShiftでも`Ingress`リソースが使えるのですが、歴史的に `Route` が先に作成された事もあり、OpenShift の各種ドキュメントは、今でも基本`Route`が前提とした書き方になっています。そのため、敢えて変えるのも混乱するので`Route`をそのまま使うのがおすすめです。

この`Route`は、ユーザーアプリ(`Pod`や`Service`)と一緒に、ユーザーが作成する必要があるリソースになります。次のステップでは実際にサンプルアプリと一緒に`Route`を作成します。

:::note info
ここで `Ingress` と呼んでいるのは、`kind: Ingress` (`Ingress` リソース/リソースの定義) の事で、L7(HTTP/S)トラフィックを取り扱う<b>機能としての ingress </b>の事ではない事に注意して下さい。L7トラフィックを扱う機能としての ingress を指す場合は、OpenShift 上では、`IngressController`リソースが作成する AWS の `NLB`や`Router Pod` がその機能を果たしているので、これらの仕組みの事を ingressと呼ぶ場合もあります。

`Ingress` リソースは、ベンダー毎に様々な機能拡張がされ、同じ `Ingress` リソース (kind: Ingress) もできる事が違っているというのが実態です。もはや `Ingress` という標準化は意味をなしておらず、個人的には無理に `Route` を `Ingress` に置き換える意味もほぼ無いだろうと思っています。OpenShift が Ingress リソースをサポートしつつも、未だに Route をメインに据えているのもこの辺りの背景があるのかもしれません。

また様々な形に派生してしまった Ingress リソースをそのまま発展させていくのも難しいため、それに変わるものとして [Gateway API](https://gateway-api.sigs.k8s.io/) というものが Kubernetes の SIG(Special Interest Group) で開発されており、[様々なベンダーがその実装を公開](https://gateway-api.sigs.k8s.io/implementations/)しはじめています。

:::


# テスト用のサンプルアプリをデプロイしてアクセスを確認する

アクセスすると "Hello OpenShift!" とテキストを返すシンプルな HTTPS アプリをデプロイしてみます。
イメージは、`docker.io/openshift/hello-openshift`  に置かれています。

**Projectの作成**

テスト用に新しい `test-app` という新しい Project を作成します。

```
$ oc new-project test-app   
``` 

**hello-openshift アプリのデプロイとクラスター内への公開**

`oc new-app` コマンドに、イメージ名を指定して、テスト用のコンテナ (hello-openshift)を Pod としてデプロイします。
イメージ名を指定するだけで、 `Service` を作成してクラスター内にコンテナを公開する所までやってくれます。

```
oc newa-app --image=<イメージ名>
```

実際のコマンドは以下の通りです。

```
$ oc new-app --image=docker.io/openshift/hello-openshift
$ oc get svc
NAME              TYPE        CLUSTER-IP      EXTERNAL-IP   PORT(S)             AGE
hello-openshift   ClusterIP   172.30.80.122   <none>        8080/TCP,8888/TCP   4m18s
$    
```

:::note info
通常コンテナイメージを Kubernetes (OpenShift)上にデプロイするには、Pod 化するために Deployment のYAMLを書いたり、Service を作成する必要がありますが、oc new-app は、[イメージか自動的にデプロイに必要なオブジェクトを作成し](https://access.redhat.com/documentation/ja-jp/openshift_container_platform/4.11/html-single/building_applications/index#applications-create-using-cli-modify_creating-applications-using-cli) Service として公開してくれます。
:::

**hello-openshift アプリのクラスター外への公開**

上記の Service `hello-openshit` を、クラスター外部に公開します。OpenShift では、`oc create route edge` に Service 名を引数指定する事で公開できます。

`Route`リソースの主な役割の一つは、Router Pod がHTTP/Sトラフィックを受けた取った時に、受け取ったドメイン名に対して、紐付けされている Service を教える事です。

```
oc create route edge --service=<サービス名> <作成するルート名> --hostname <公開ホスト名>
```
`--hostname` オプションを使用してクラスター外部に公開するドメイン名を指定します。ここに独自ドメインを使ったホスト名を指定します。

今回の例では `*.ocp4.work` にマッチするドメイン名であれば、`--hostname` に、どんな値も指定できます。ここでは、サービス名と同じ `hello-openshift` を使用して `hello-openshift.ocp4.work` というドメイン名で公開する事にします。

:::note info
ここでさりげなく `edge` と指定していますが、これは Ingress Pod (=Router Pod)で HTTPSを終端しそこから先は暗号化しない方法です。この手順の中で作成して Secret に格納した証明書は、内部的に Router Pod に渡されており、Router Pod はそれを使用してHTTPSを終端します。

Router Pod と、ユーザーのアプリ(Pod)の間はクラスター内のプライベートネットワークなので外部に公開されないネットワークです。もし、Route Pod から先も暗号化したい場合は、個別のユーザーの Pod に証明書を入れて別途管理する必要があります。

[edge](https://access.redhat.com/documentation/ja-jp/openshift_container_platform/4.11/html/networking/nw-ingress-creating-an-edge-route-with-a-custom-certificate_secured-routes#doc-wrapper) 以外にも、[re-encrypt](https://access.redhat.com/documentation/ja-jp/openshift_container_platform/4.11/html/networking/configuring-default-certificate#nw-ingress-creating-a-reencrypt-route-with-a-custom-certificate_secured-routes) や [passthrough](https://access.redhat.com/documentation/ja-jp/openshift_container_platform/4.11/html/networking/nw-ingress-creating-a-passthrough-route_secured-routes) というオプションがあります。これらの方法は、いずれもユーザーPod側で別途証明書を組み込む必要があります。
:::

実際のコマンドの実行結果は以下のようになります。

```
$ oc create route edge --service=hello-openshift hello-openshift-tls --hostname hello-openshit.$DOMAIN
route.route.openshift.io/hello-openshift-tls created
$ oc get route
NAME                  HOST/PORT                    PATH   SERVICES          PORT       TERMINATION   WILDCARD
hello-openshift-tls   hello-openshit.ocp4.work ... 1 more          hello-openshift   8080-tcp   edge          None
$ 
```


**独自ドメイン名でのアクセス確認**

curl で、 `hello-openshift.ocp4.work` にアクセスして確認してみます。

```
$ curl  https://hello-openshit.$DOMAIN
Hello OpenShift!
$
```

無事、独自ドメイン名で HTTPS を使用してサンプルアプリにアクセスできました。

サンプルアプリでは、`hello`.ocp4.work という名前にしていますが、証明書は `*` で取得していて、DNSへのドメイン登録も`*`で登録されているので、`*`.ocp4.work にマッチすればどんな名前でも使用可能です。


**サンプルアプリの削除**


プロジェクト毎そこに含まれるサンプルアプリを廃棄するのが一番簡単です。以下のコマンドを実行します。

```
oc delete project <プロジェクト名>
```

実際のコマンドの実行結果は以下のようになります。

```
$ oc delete project test-app
project.project.openshift.io "test-app" deleted
$ 
```