ROSA を自分が作成した VPCにインストールする (Single AZ)

# はじめに

標準のROSAのインストール方法では、インストールコマンドが、AWS上にVPCを作成して、そこに ROSAを構成するインスタンスをデプロイします。この時 `10.0.0.0/16` という VPC Netwoek が作成されます。

ここでは、`10.0.0.0/16`ではなく、自分で作成した VPC `10.7.0.0/16` に ROSA をインストールしてみます。この方法は BYOVPC (Bring Your Own VPC) とも呼ばれています。

# インストールする VPCを用意する

まずは、図に書くと以下のような VPCを作成します。VPC そのものだけでなくて、VPC内のサブネットや、Internet Gateway、NAT Gateway と言ったコンポーネントも必要です。

![VPC Network Template.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/99425/07578399-2a65-4857-b6a9-19543121747e.png)

VPC の Network アドレスや、その中に作り込む Public Subnet そして Private Subnet の Network アドレスを、最低限決める必要があります。ここでは以下のように決めました。

```
VPC の Network 10.7.0.0/16                 
VPC 内の Public Subnet 10.7.128.0/17        
VPC 内の Private Subnet 10.7.0.0/17          
```

この VPC をどうやって作って行くかですが、AWS Console から GUIで一つ一つ作っていく他に

## A. CloudFormation で VPC や Subnet を作成する

CloudFormation で作成するのが一番簡単です。以下のGistにコードを貼り付けています。

<a href="https://gist.github.com/yuhkih/06797c53a39fbc59fa812933bf085b66" target=”_blank" >CloudFormation ROSA Single AZ Network Template</a>

このコードを AWS の CloudFormation の Console にアップロードして、名前を付けるレベルで簡単に作成できます。
また削除も作成した「スタック」毎削除できるので、何度も作成/廃棄を繰り返す場合は CloudFormation が簡単だと思います。

上記のコードを適当なファイル名で保存して CloudFormation のサービスの画面から「スタックの作成」をクリックします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/99425/bd581dfe-573d-3cc3-b748-b1b3ce0dda19.png)

「テンプレートファイルのアップロード」を選び、保存してある CloudFormation の YAMLファイルをアップロードします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/99425/0b24498f-97e6-f764-a76a-b8b717667d08.png)

名前を付けます。ここでは「test-single-az」と付けています。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/99425/02599921-3092-220a-9964-b88bab2e3095.png)

いろいろ設定を変更できますが、初回はデフォルトで大丈夫だと思います。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/99425/0150196f-21fb-858f-1029-b8ae8e4dd2ca.png)

最後は「送信」をクリックすれば、VPCや必要なサブネットが作成されます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/99425/74abe7e3-d6ca-6053-d6b5-75cb1c034adb.png)


## B. CLI で VPC や Subnet を作成する

CLIで、一つ一つコマンドを打つのは大変なのでシェル化します。

私は、成り行きではじめはこの方法でやっていましたが、何度も同じ環境を作成/廃棄したりする必要がある環境ではおすすめしません。
また、ここでは作成スクリプトだけでを記載していて、削除は別途方法を考える必要があります。

(※ここでは Single Zone 用にネットワークを構成しています。Multi AZ にするには、サブネット等の必要なコンポーネントを AZ分作成する必要があります) 

```shell-session
#!/bin/bash

VPC_NETWORK=10.7.0.0/16                 # VPC の Network 
VPC_SUBNET_PUBLIC=10.7.128.0/17         # VPC 内の Public Subnet
VPC_SUBNET_PRIVATE=10.7.0.0/17          # VPC 内の Private Subnet

# Create a VPC
echo "[STEP1] Create VPC " $VPC_NETWORK 
VPC_ID=`aws ec2 create-vpc --cidr-block $VPC_NETWORK | jq -r .Vpc.VpcId`
aws ec2 modify-vpc-attribute --vpc-id $VPC_ID --enable-dns-hostnames | jq .
echo "VPCID = " $VPC_ID "has been created" 

# Create a public subnet in the VPC
echo "[STEP2] Create Public Subnet " $VPC_SUBNET_PUBLIC 
PUBLIC_SUBNET=`aws ec2 create-subnet --vpc-id $VPC_ID --cidr-block $VPC_SUBNET_PUBLIC | jq -r .Subnet.SubnetId`
aws ec2 create-tags --resources $PUBLIC_SUBNET --tags Key=Name,Value=my-public | jq .
echo "Public subnet ID = " $PUBLIC_SUBNET "has been created" 

# Create a privatesubnet in the VPC
echo "[STEP3] Create Private Subnet " $VPC_SUBNET_PRIVATE
PRIVATE_SUBNET=`aws ec2 create-subnet --vpc-id $VPC_ID --cidr-block $VPC_SUBNET_PRIVATE | jq -r .Subnet.SubnetId`
aws ec2 create-tags --resources $PRIVATE_SUBNET --tags Key=Name,Value=my-private | jq .
echo "Private subnet ID = " $PRIVATE_SUBNET "has been created" 

# Create Internet Gateway
echo "[STEP4] Create Internet Gateway in VPC " $VPC_ID 
I_GW=`aws ec2 create-internet-gateway | jq -r .InternetGateway.InternetGatewayId`
aws ec2 attach-internet-gateway --vpc-id $VPC_ID --internet-gateway-id $I_GW | jq .
echo "Internet Gateway ID = " $I_GW "has been created" 

# Create a route table for public subnet
echo "[STEP5] Create a Route table for the public subnet id" $PUBLIC_SUBNET
R_TABLE=`aws ec2 create-route-table --vpc-id $VPC_ID | jq -r .RouteTable.RouteTableId`
# -- sometimes it takes time to get Route Table id --
while ! aws ec2 describe-route-tables --route-table-id $R_TABLE  | jq .; do sleep 1; done
aws ec2 create-route --route-table-id $R_TABLE --destination-cidr-block 0.0.0.0/0 --gateway-id $I_GW | jq .
aws ec2 associate-route-table --subnet-id $PUBLIC_SUBNET --route-table-id $R_TABLE | jq .
echo "Route table ID " $R_TABLE " for the public subnet(" $PUBLIC_SUBNET ") has been created" 

# Create a NAT Gateway
echo "[STEP6] Create NAT Gateway in "  $PUBLIC_SUBNET
EIP=`aws ec2 allocate-address --domain vpc | jq -r .AllocationId`
NAT_GW=`aws ec2 create-nat-gateway --subnet-id $PUBLIC_SUBNET --allocation-id $EIP | jq -r .NatGateway.NatGatewayId`      
echo "NAT Gateway ID " $NAT_GW " has been created in the public subnet(" $PUBLIC_SUBNET ")"

# Wait for NAT Gateway created. Sometimes it took a few minutes
NAT_GW_STATUS=`aws ec2 describe-nat-gateways --nat-gateway-id $NAT_GW | jq -r .NatGateways[].State`
echo "- NAT Gateway status is " $NAT_GW_STATUS
while [ $NAT_GW_STATUS != "available" ]
do
  NAT_GW_STATUS=`aws ec2 describe-nat-gateways --nat-gateway-id $NAT_GW | jq -r .NatGateways[].State`
  if [ $NAT_GW_STATUS != "available" ] ; then
    echo "- NAT Gatewya id = " $NAT_GW " State = " $NAT_GW_STATUS
    echo "- Waiting for the NAT Gateway available"
    sleep 10;
  else
    echo "- NAT Gatewya id = " $NAT_GW " State = " $NAT_GW_STATUS
  fi
done

# Create a Route Tatble  for Private subnet
echo "[STEP7] Create a Route Table for the private subnet " $PRIVATE_SUBNET
R_TABLE_NAT=`aws ec2 create-route-table --vpc-id $VPC_ID | jq -r .RouteTable.RouteTableId`
# -- sometimes it takes time to get Route Table id --
while ! aws ec2 describe-route-tables --route-table-id $R_TABLE_NAT  | jq . ; do sleep 1; done
aws ec2 create-route --route-table-id $R_TABLE_NAT --destination-cidr-block 0.0.0.0/0 --gateway-id $NAT_GW | jq .
aws ec2 associate-route-table --subnet-id $PRIVATE_SUBNET --route-table-id $R_TABLE_NAT | jq .
echo "Route table ID " $R_TABLE_NAT " for the public subnet(" $PRIVATE_SUBNET ") has been created" 
```

上記のシェルを実行すればVPCと必要なコンポーネントが作成されるはずです。

# 作成した VPCに ROSAを作成する

AWS CLI は導入されて構成済みとします。

端末に必要なコマンドをダウンロードしてセットアップします。

```
curl -LO https://mirror.openshift.com/pub/openshift-v4/clients/rosa/latest/rosa-linux.tar.gz
tar -zxf rosa-linux.tar.gz 
sudo mv ./rosa /usr/local/bin/
rosa download oc
tar -xzf openshift-client-linux.tar.gz 
sudo mv ./oc /usr/local/bin
sudo mv ./kubectl /usr/local/bin
```

環境を初期化します。

```
rosa init
```

はじめて行う場合は、Red Hat Customer Portal に誘導するリンクが出てくるので、もろもろの指示に従います。

ROSA クラスターの インストールを開始します。ここでは、手順を簡略化するために STS は使用しないものとします。
CLI のワンライナーでインストールする事もできますが、インタラクティブモードで行う方が簡単です。

```
rosa create cluster
```

を実行します。

```shell-session
$ rosa create cluster
I: Enabling interactive mode
? Cluster name: rosa-cluster
? Deploy cluster using AWS STS: No
? OpenShift version: 4.11.9
? Multiple availability zones (optional): No
? AWS region: ap-northeast-1
? PrivateLink cluster (optional): No
? Private cluster (optional): No
? Install into an existing VPC (optional): [? for help] (y/N) y  # ここで Y　を入力します。
? Subnet IDs (optional):  [Use arrows to move, space to select, <right> to all, <left> to none, type to filter, ? for more help]                                    
  [x]  subnet-0a2360ce9dca34f9d (ap-northeast-1d)　　　　# Single AZ の場合は PrivateとPublicの 2つのSubnetを選択
  [x]  subnet-03a000478bacb81f6 (ap-northeast-1d)       # Single AZ の場合は PrivateとPublicの 2つのSubnetを選択
? Enable Customer Managed key (optional): No
? Compute nodes instance type: m5.xlarge
? Enable autoscaling (optional): No
? Compute nodes: 2
? Machine CIDR: 10.7.0.0/16    # Machine CIDR は、作成した VPCと同じものを入力
? Service CIDR: 172.30.0.0/16  # 内部ネットワークなので Default で OK
? Pod CIDR: 10.128.0.0/14      # 内部ネットワークなので Default で OK
? Host prefix: 23
? Encrypt etcd data (optional): No
? Disable Workload monitoring (optional): No
? Use cluster-wide proxy (optional): No
? Additional trust bundle file path (optional):
I: Creating cluster 'rosa-cluster'
I: To create this cluster again in the future, you can run:
   rosa create cluster --cluster-name rosa-cluster --region ap-northeast-1 --version 4.11.9 --compute-nodes 2 --compute-machine-type m5.xlarge --machine-cidr 10.7.0.0/16 --service-cidr 172.30.0.0/16 --pod-cidr 10.128.0.0/14 --host-prefix 23 --subnet-ids subnet-0a2360ce9dca34f9d,subnet-03a000478bacb81f6
I: To view a list of clusters and their status, run 'rosa list clusters'
I: Cluster 'rosa-cluster' has been created.
I: Once the cluster is installed you will need to add an Identity Provider before you can login into the cluster. See 'rosa create idp --help' for more information.
Name:                       rosa-cluster2
ID:                         1vj97skq8vbe14qgks2e6vahjskeccj0
External ID:
OpenShift Version:
Channel Group:              stable
DNS:                        rosa-cluster2.70d7.p1.openshiftapps.com
AWS Account:                311687714843
API URL:
Console URL:
Region:                     ap-northeast-1
Multi-AZ:                   false
Nodes:
 - Control plane:           3
 - Infra:                   2
 - Compute:                 2
Network:
 - Type:                    OVNKubernetes
 - Service CIDR:            172.30.0.0/16
 - Machine CIDR:            10.7.0.0/16
 - Pod CIDR:                10.128.0.0/14
 - Host Prefix:             /23
State:                      validating
Private:                    No
Created:                    Oct 26 2022 07:29:59 UTC
Details Page:               https://console.redhat.com/openshift/details/s/2GfAjT8ErBwzsHmWxJkvjhYNFSJ

I: To determine when your cluster is Ready, run 'rosa describe cluster -c rosa-cluster'.
I: To watch your cluster installation logs, run 'rosa logs install -c rosa-cluster --watch'.
$ 

```

後は30分ほど待っていれば Cluster が作成されるはずです。

```
rosa list cluster
```

で ready になっていれば完成です。

```
$ rosa list cluster
ID                                NAME           STATE
1vj97skq8vbe14qgks2e6vahjskeccj0  rosa-cluster  ready
$ 
```


# 管理ユーザー作成

```
$ rosa create admin --cluster=<クラスタ名>
```

で、管理者ユーザーを作成します。

```
$ rosa create admin --cluster=rosa-cluster
I: Admin account has been added to cluster 'rosa-cluster'.
I: Please securely store this generated password. If you lose this password you can delete and recreate the cluster admin user.
I: To login, run the following command:

   oc login https://api.rosa-cluster.70d7.p1.openshiftapps.com:6443 --username cluster-admin --password P8P9Y-HhAPB-ihneH-un5db

I: It may take up to a minute for the account to become active.
$ 
```

最後にログインするためのコマンドが出力されています。
ただ、ユーザーが作成されて、実際にログインできるようになるには、5分程度待ちます。ユーザーができるまでは、ログインしようとしても 401 で Fail します。

暫くしたら、` rosa create admin --cluster=クラスタ名`  実行時の最後に出力されていたコマンドで、ログインしてみます。

```
oc login https://api.rosa-cluster.70d7.p1.openshiftapps.com:6443 --username cluster-admin --password P8P9Y-HhAPB-ihneH-un5db
Login successful.

You have access to 99 projects, the list has been suppressed. You can list all projects with 'oc projects'

Using project "default".
$
```

ログインができる事が確認できれば、クラスターの作成は完了です。

# GitHub ID 連携

実験環境であれば、管理者ユーザーでそのまま使っても良いですが、GitHub と連携して GitHub のユーザーを ROSA で使用する事もできます。

これを行うには、GitHub にアカウントを持っている事、Organization を作成している事が必要です。
Organization の作成方法については、以下に解説があります。
https://docs.github.com/ja/organizations/collaborating-with-groups-in-organizations/creating-a-new-organization-from-scratch


ROSA では、

```
rosa create idp --type=github --cluster=<クラスタ名>
```

で、GitHub を IdP として構成できます。

```
$ rosa create idp --type=github --cluster=rosa-cluster2
? Restrict to members of: organizations
? GitHub organizations: ocp-test1  # これはあらかじめ GitHub 側で作成してある Organization
? To use GitHub as an identity provider, you must first register the application:
  - Open the following URL:
    https://github.com/organizations/ocp-test1/settings/applications/new?oauth_application%5Bcallback_url%5D=https%3A%2F%2Foauth-openshift.apps.rosa-cluster2.70d7.p1.openshiftapps.com%2Foauth2callback%2Fgithub-1&oauth_application%5Bname%5D=rosa-cluster2&oauth_application%5Burl%5D=https%3A%2F%2Fconsole-openshift-console.apps.rosa-cluster2.70d7.p1.openshiftapps.com
  - Click on 'Register application'
? Client ID: [? for help]
```

ここで "Client ID" を入力するように言われますが、これは、その前段に出力されているリンクをクリックします。以下の画面に飛ばされるはずです。
「Register application」をクリックします。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/99425/1073b30f-9600-33c2-eee6-5d704e7059ac.png)

今度は別の画面に遷移して、そこに「Client ID」が表示されているはずです。これを、コマンドラインの方にコピペします。

![clientID.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/99425/7e224f2e-9afd-3dd7-e6b5-997bd039f854.png)


```
? Client ID: c2b6f8d1da9807
? Client Secret: [? for help]
```

今度は 「Client Secret」を聞かれます。これはGitHub側で「Genereate new client secret」をクリックして生成します。

![clientsecret.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/99425/e55d5bcd-091d-ff0f-31a3-d19a9e3670ed.png)


生成された ID をコピペして入力します。

```
? Client Secret: [? for help] ****************************************
```

「Client ID」と「Client Secret」を入力した後は、デフォルトで大丈夫です。
エンターを連打します。

```
? Client ID: c2b6f8d1da9807a0ef82
? Client Secret: [? for help] ****************************************
? GitHub Enterprise Hostname (optional): 
? Mapping method: claim
I: Configuring IDP for cluster 'rosa-cluster2'

I: Identity Provider 'github-1' has been created.
   It will take up to 1 minute for this configuration to be enabled.
   To add cluster administrators, see 'rosa grant user --help'.     
   To login into the console, open https://console-openshift-console.apps.rosa-cluster.70d7.p1.openshiftapps.com and click on github-1.
$ 
```

最後にコンソールのリンクが表示されています。これで IdP が作成されましたが、実際にアクセスできるようになるには、暫く待つ必要があります。数分程度かかります。

リンクにアクセスすると、以下のように「github-1」と「htpasswd」が表示されているはずです。(「github-1」が表示されてない場合はもう少し待ちましょう）
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/99425/dd03479d-3e2d-b090-22cb-ad0bc7c4b6b1.png)

「github-1」をクリックすると以下のような画面がでるので「Authorize ocp-test1」をクリックします。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/99425/a7050c41-d2dd-cadd-b7e7-505c309267e7.png)

以下のログイン画面に飛ばされるはずです。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/99425/61888ff8-4d88-5ffa-f7a0-bbb91ef771d6.png)

以上で GitHub連携は完了です。


# GitHub ユーザーに管理者権限を与える

このままだと GitHub のユーザーは、一般ユーザー権限しかもっていません。

```
$ rosa grant user dedicated-admin --user=<ユーザー名> --cluster=<クラスタ名>
```

で、<ユーザー名>に、`dedicated-admin` の権限を付ける事ができます。

```
$ rosa grant user dedicated-admin --user=yuhkih --cluster=rosa-cluster
I: Granted role 'dedicated-admins' to user 'yuhkih' on cluster 'rosa-cluster'
$ rosa list users --cluster=rosa-cluster
ID       GROUPS
yuhki    dedicated-admins
$
```

一旦ログアウトして、ログインしなおすと、管理者が使用できるメニューが表示されているはずです。
(数分かかるかもしれません）

例えば、`dedicated-admin` グループでは、「Administrator」パースペクティブで、「Operator」→「OperatorHub」のメニューが見えるようになります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/99425/85cd45d7-7152-ae9a-8e75-3ab1d8e312df.png)