Red Hatさんのご厚意により、OpenShiftのマネージドサービスであるROSAのHosted Control Planeの機能をお試しさせてもらうことになりました。先週あった、Red Hat Summitでも当該機能のPublic Preview開始のアナウンスがありました。この記事では、ROSA with HCPをインストールしてみて、作成されるリソースをみていきたいと思います。
ROSA with Hosted Control Plane
Hosted Control Plane(HCP)は OpenShift 関連製品で提供予定の技術です。Self Managed 版のOpenShift の他、ROSA でも提供予定とされており、Self Managed 版のOpenShift 4.12では、Tech Previewとなっています。ROSAはHCPを使用することで、専用のコントロールプレーンがRed HatによりManaged Serviceとして提供され、より効率的かつ信頼性の高いアーキテクチャが実現できるとされています。
ただし、ROSA with HCPを利用する上では、以下の点の留意が必要です。
- 既にROSAをご自身のAWSアカウント上で展開している場合で、ROSA with HCPの機能を利用するためには、既存のクラスターを「アップグレード」することはできないため、新しいクラスターを作成する必要があります。
- すべてのROSA with HCPクラスターには、AWS Security Token Service (STS)の有効化が必要です。
これまでのROSAとの比較
ROSA with HCPに於けるControl Plane(Master Node)は、Red HatにManagedされるため、実際に自分達のAWSアカウント内に構築されるNodeはWorker Nodeのみとなります。そのため、数分で新しいクラスターを迅速に作成し、アプリケーションを展開することができます。これまでのROSAでもそうでしたが、ROSA with HCPでもWorker Nodeは最小2ノードのみを必要とし、同時に大規模なプロジェクトや企業にむけたスケールアウトも可能となっています。
これまでのROSAとROSA with HCPの違いは以下の通りです。
- インストールパス
- HCP:etcd、APIサーバー、OAuthなどのコントロールプレーンのコンポーネントが別のAWS上に展開され、Red Hatが所有および管理するアカウント内にホストされます。
- Classic:コントロールプレーンのコンポーネントとインフラストラクチャ、ワーカーノードが顧客の同じAWSアカウント内で一緒に展開されます。ただし、Red Hatが管理します。
- プロビジョニング時間
- HCP:約10分
- Classic:約40分
- アーキテクチャ
- HCP:エンドカスタマーが直接アクセスできないように、コントロールプレーンのインフラストラクチャは完全に管理されます。
- Classic:顧客がコントロールプレーンとAWSインフラストラクチャをホストする責任がありますが、Red Hatによって管理されます。
- フットプリント
- HCP:1つのクラスターには最低2つのノードが必要です。
- Classic:1つのクラスターには最低7つのノードが必要です。(Master Node と Infra Nodeを含む)
- デプロイメント
- HCP:ROSA CLIまたはWeb UIを使用して展開します。
- Classic:ROSA CLIまたはWeb UIを使用して展開します。
- アップグレード
- HCP:選択的にコントロールプレーンとマシンプールを別々にアップグレードできます。
- Classic:クラスター全体を一度にアップグレードします。
- リージョンの可用性:
- HCP:eu-central-1、eu-west-1、us-east-1、us-east-2、us-west-2で利用可能です。
- Classic:AWSが利用可能なすべてのリージョンで利用可能です。
- コンプライアンス
- HCP:GA後にコンプライアンス認証が計画されています。
- Classic:FIPSコンプライアンスはまだ利用できません。ISO 27001、17、18、SOC 2 Type 2、SOC 3、PCI-DSS、HIPAAの準拠があります。
ROSA with HCPのセットアップ
前置きは以上とし、セットアップしていきましょう。
セットアップのゴール
- HCPモードでROSAを動かす
- Red Hat側のコントロールプレーンとはPrivate Link経由で接続する(インターネットにエンドポイントを晒さない)
- そのため、ROSAはPrivate Subnetに配置する
- そのため、ROSAがインターネットとのアクセスをするときはForward Proxy経由とする
- コントロールプレーン上のetcdは、自身のAWSアカウント上で管理されているKMSの鍵で暗号化する
- 他のオプションはデフォルトとする
前提条件
AWSリソースの作成
CloudFormationを使って、ROSAをインストールする環境をセットアップします。
- VPCと2つのサブネットを作成する(PrivateとPublic)
- EC2をそれぞれのサブネットに配置して、PublicのEC2にはApacheをプロキシ構成でインストールする
- 後ほど、ROSAのインストールで使うパラメータをOutputする
AWSTemplateFormatVersion: 2010-09-09
Parameters:
RegionParameter:
Type: String
Default: ap-northeast-1
AllowedValues:
- ap-northeast-1
- ap-northeast-2
- ap-northeast-3
- us-east-1
- us-east-2
Ec2ImageId:
Type: AWS::SSM::Parameter::Value<String>
Default: /aws/service/ami-amazon-linux-latest/amzn2-ami-hvm-x86_64-gp2
Ec2InstanceType:
Type: String
Default: t3.nano
KeyPair:
Type: AWS::EC2::KeyPair::KeyName
Description: EC2 Key Pair
MyIP:
Type: String
Description: Your IP address (e.g., 203.0.113.1)
Resources:
CfVPC:
Type: AWS::EC2::VPC
Properties:
CidrBlock: 10.0.0.0/16
EnableDnsSupport: 'true'
EnableDnsHostnames: 'true'
Tags:
-
Key: Name
Value: CfVPC
CfPublicSubnet:
Type: AWS::EC2::Subnet
Properties:
CidrBlock: 10.0.1.0/24
MapPublicIpOnLaunch: true
VpcId: !Ref CfVPC
AvailabilityZone: !Join
- ''
- - !Ref RegionParameter
- 'a'
Tags:
- Key: Name
Value: CfPublicSubnet
CfPrivateSubnet:
Type: AWS::EC2::Subnet
Properties:
CidrBlock: 10.0.2.0/24
MapPublicIpOnLaunch: false
VpcId: !Ref CfVPC
AvailabilityZone: !Join
- ''
- - !Ref RegionParameter
- 'a'
Tags:
- Key: Name
Value: CfPrivateSubnet
CfInternetGateway:
Type: AWS::EC2::InternetGateway
Properties:
Tags:
- Key: Name
Value: CfInternetGateway
AttachCfInternetGateway:
Type: AWS::EC2::VPCGatewayAttachment
Properties:
InternetGatewayId : !Ref CfInternetGateway
VpcId: !Ref CfVPC
CfRouteTableForPublicSubnet:
Type: AWS::EC2::RouteTable
Properties:
VpcId: !Ref CfVPC
Tags:
- Key: Name
Value: CfRouteTableForPublicSubnet
CfRouteForPublicSubnet:
Type: AWS::EC2::Route
Properties:
RouteTableId: !Ref CfRouteTableForPublicSubnet
DestinationCidrBlock: 0.0.0.0/0
GatewayId: !Ref CfInternetGateway
CfAssocciateRouteTableForPublicSubnet:
Type: AWS::EC2::SubnetRouteTableAssociation
Properties:
RouteTableId: !Ref CfRouteTableForPublicSubnet
SubnetId: !Ref CfPublicSubnet
NatGatewayEIP:
Type: AWS::EC2::EIP
Properties:
Domain: vpc
CfNatGateway:
Type: AWS::EC2::NatGateway
Properties:
AllocationId:
Fn::GetAtt:
- NatGatewayEIP
- AllocationId
SubnetId: !Ref CfPublicSubnet
Tags:
- Key: Name
Value: CfNatGateway
CfRouteTableForPrivateSubnet:
Type: AWS::EC2::RouteTable
Properties:
VpcId: !Ref CfVPC
Tags:
- Key: Name
Value: CfRouteTableForPrivateSubnet
CfRouteForPrivateSubnet:
Type: AWS::EC2::Route
Properties:
RouteTableId: !Ref CfRouteTableForPrivateSubnet
DestinationCidrBlock: 0.0.0.0/0
NatGatewayId: !Ref CfNatGateway
CfAssocciateRouteTableForPrivateSubnet:
Type: AWS::EC2::SubnetRouteTableAssociation
Properties:
RouteTableId: !Ref CfRouteTableForPrivateSubnet
SubnetId: !Ref CfPrivateSubnet
CfPublicSecurityGroup:
Type: AWS::EC2::SecurityGroup
Properties:
GroupDescription: Allow SSH and all traffic from VPC
VpcId: !Ref CfVPC
SecurityGroupIngress:
- IpProtocol: tcp
FromPort: 22
ToPort: 22
CidrIp: !Ref MyIP
- IpProtocol: -1
FromPort: -1
ToPort: -1
CidrIp: 10.0.0.0/16
CfPrivateSecurityGroup:
Type: AWS::EC2::SecurityGroup
Properties:
GroupDescription: Allow all traffic from VPC
VpcId: !Ref CfVPC
SecurityGroupIngress:
- IpProtocol: -1
FromPort: -1
ToPort: -1
CidrIp: 10.0.0.0/16
CfPublicEC2Instance:
Type: AWS::EC2::Instance
Properties:
ImageId: !Ref Ec2ImageId
InstanceType: !Ref Ec2InstanceType
KeyName: !Ref KeyPair
SubnetId: !Ref CfPublicSubnet
SecurityGroupIds:
- !Ref CfPublicSecurityGroup
UserData:
Fn::Base64: !Sub |
#!/bin/bash
yum update -y
yum install -y httpd
tee /etc/httpd/conf.d/proxy.conf <<EOF
Listen 3128
<IfModule proxy_module>
ProxyRequests On
ProxyVia On
ProxyTimeout 300
AllowCONNECT 443
CustomLog logs/proxy_log combined
<Proxy *>
Order allow,deny
Allow from all
</Proxy>
</IfModule>
EOF
systemctl enable httpd
systemctl start httpd
Tags:
- Key: Name
Value: PublicEC2Instance
CfPrivateEC2Instance:
Type: AWS::EC2::Instance
Properties:
ImageId: !Ref Ec2ImageId
InstanceType: !Ref Ec2InstanceType
KeyName: !Ref KeyPair
SubnetId: !Ref CfPrivateSubnet
SecurityGroupIds:
- !Ref CfPrivateSecurityGroup
Tags:
- Key: Name
Value: PrivateEC2Instance
Outputs:
PublicEC2InstancePublicIP:
Description: "Public IP of the Public EC2 instance"
Value: !GetAtt CfPublicEC2Instance.PublicIp
PublicEC2InstancePrivateIP:
Description: "Private IP of the Public EC2 instance"
Value: !GetAtt CfPublicEC2Instance.PrivateIp
PrivateEC2InstancePrivateIP:
Description: "Private IP of the Private EC2 instance"
Value: !GetAtt CfPrivateEC2Instance.PrivateIp
PrivateSubnetId:
Description: "Subnet ID of the private subnet"
Value: !Ref CfPrivateSubnet
create-stack
します。MyIPには、作業環境のグローバルIPアドレスをいれます。
% aws cloudformation create-stack --stack-name rosahcp ¥
--parameters ParameterKey=KeyPair,ParameterValue=rosahcp-vpc ¥
ParameterKey=MyIP,ParameterValue=xxx.xxx.xxx.xxx./32 ¥
ParameterKey=RegionParameter,ParameterValue=us-east-1 ¥
--template-body file://rosahcp-cfn.yaml
Create STS roles and policies
ROSAが利用する各種IAM RoleとIAM Policyを作成していきます。
# Account Roleの作成
% rosa create account-roles --mode auto
I: Logged in as '...snip...' on 'https://api.openshift.com'
...snip...
I: To create a cluster with these roles, run the following command:
rosa create cluster --sts
# OIDC Configの作成
% rosa create oidc-config --mode auto
? Would you like to create a Managed (Red Hat hosted) OIDC Configuration Yes
...snip...
? Create the OIDC provider? Yes
...snip...
I: Created OIDC provider with ARN 'arn:aws:iam::68 ...snip... 92:oidc-provider/rh-oidc.s3.us-east-1.amazonaws.com/23 ...snip... 5d'
# Operator Roleを作成
% rosa create operator-roles --prefix rosahcp --oidc-config-id 23 ...snip... 5d
? Role creation mode: auto
? Operator roles prefix: rosahcp
? Create hosted control plane operator roles (optional): Yes
...snip...
? Permissions boundary ARN (optional):
...snip...
I: To create a cluster with these roles, run the following command:
rosa create cluster --sts --oidc-config-id 23 ...snip... 5d --operator-roles-prefix rosahcp --hosted-cp
ここで、rosa create oidc-config
というコマンドを実行しました。
コントロールプレーンをRed Hatがマネージドすることとなったため、IDトークンの署名用の秘密鍵の所在や、/openid-configuration
のエンドポイントの所在や、そもそものOpenID Providerの持ち主を決めたりするのかもしれません。2023/5下旬時点では、あまりドキュメンテーションされていないので、こちらのページの更新を待ちましょう。
暗号化用の鍵をKMSに作成
コントロールプレーンの管理がRed Hatになったので、etcdも自ずとRed Hat管理となります。etcdには秘密の情報がsecretに格納されたりしますので、暗号化は必須と言えます。面倒くさがらずに、ちゃんと暗号化しましょう。ロールの名前にrosahcp
とはいっていますが、Operator Roleを作成した時のprefixを入れるようにしましょう。
# Key Policyのドキュメントを準備
% cat rosahcp-kms-policy.yaml
{
"Version": "2012-10-17",
"Id": "key-default-1",
"Statement": [
{
"Sid": "Enable IAM User Permissions",
"Effect": "Allow",
"Principal": {
"AWS": [
"arn:aws:iam::NNNNNNNNNNNN:role/ManagedOpenShift-Installer-Role",
"arn:aws:iam::NNNNNNNNNNNN:role/rosahcp-kube-system-kms-provider",
"arn:aws:iam::NNNNNNNNNNNN:role/rosahcp-openshift-cluster-csi-drivers-ebs-cloud-credentials",
"arn:aws:iam::NNNNNNNNNNNN:role/rosahcp-kube-system-capa-controller-manager",
"arn:aws:iam::NNNNNNNNNNNN:root"
]
},
"Action": "kms:*",
"Resource": "*"
}
]
}
# 鍵の作成
% aws kms create-key --policy file://rosahcp-kms-policy.yaml
{
"KeyMetadata": {
"AWSAccountId": "NNNNNNNNNNNN",
"KeyId": "64 ...snip... bb",
"Arn": "arn:aws:kms:us-east-1:NNNNNNNNNNNN:key/64 ...snip... bb",
"CreationDate": "2023-05-29T22:54:54.994000+09:00",
"Enabled": true,
"Description": "",
"KeyUsage": "ENCRYPT_DECRYPT",
"KeyState": "Enabled",
"Origin": "AWS_KMS",
"KeyManager": "CUSTOMER",
"CustomerMasterKeySpec": "SYMMETRIC_DEFAULT",
"KeySpec": "SYMMETRIC_DEFAULT",
"EncryptionAlgorithms": [
"SYMMETRIC_DEFAULT"
],
"MultiRegion": false
}
}
鍵の作成時(aws kms create-key
)のアウトプットのうち、Arnはrosa create cluster
するときに使うので、コピーしときましょう。
ROSA with HCPの作成
前提が整ったので、rosa create cluster
しましょう。
# ROSAをインストールする先のサブネットのIDを取得
% aws cloudformation describe-stacks --stack-name rosahcp ¥
--query 'Stacks[0].Outputs[?OutputKey==`PrivateSubnetId`].OutputValue' ¥
--output text
# ROSAが使うProxyのIPを取得
% aws cloudformation describe-stacks --stack-name rosahcp ¥
--query 'Stacks[0].Outputs[?OutputKey==`PublicEC2InstancePrivateIP`].OutputValue' ¥
--output text
# ROSA with HCPの作成
rosa create cluster \
--cluster-name rosahcp \
--sts \
--role-arn arn:aws:iam::NNNNNNNNNNNN:role/ManagedOpenShift-Installer-Role \
--support-role-arn arn:aws:iam::NNNNNNNNNNNN:role/ManagedOpenShift-Support-Role \
--worker-iam-role arn:aws:iam::NNNNNNNNNNNN:role/ManagedOpenShift-Worker-Role \
--operator-roles-prefix rosahcp \
--oidc-config-id 24 ...snip... e7 \
--region us-east-1 \
--version 4.12.18 \
--enable-autoscaling \
--min-replicas 2 \
--max-replicas 2 \
--compute-machine-type m5.xlarge \
--machine-cidr 10.0.0.0/16 \
--service-cidr 172.30.0.0/16 \
--pod-cidr 10.128.0.0/14 \
--host-prefix 23 \
--private-link \
--subnet-ids subnet-0f2d12e7d7b1d10f2 \
--etcd-encryption \
--http-proxy http://10.0.1.13:3128/ \ #一つ前の手順のPublicEC2InstancePrivateIP
--https-proxy http://10.0.1.13:3128/ \ #一つ前の手順のPublicEC2InstancePrivateIP
--no-proxy "10.0.0.0/16" \
--kms-key-arn arn:aws:kms:us-east-1:NNNNNNNNNNNN:key/64 ...snip... bb \ #さっきコピーしたKMSのArn
--hosted-cp \
--etcd-encryption-kms-arn arn:aws:kms:us-east-1:NNNNNNNNNNNN:key/64 ...snip... bb #さっきコピーしたKMSのArn
# インストール後のログ確認(10分程度で終わる)
% rosa logs install -c rosahcp --watch
I: Cluster 'rosahcp' has been successfully installed
インストール後の探索
cluster-adminの作成
% rosa create admin --cluster=rosahcp
oc login https://api.rosahcp.1gjb.p3.openshiftapps.com:443 --username cluster-admin --password i6 ...snip... 6F
ここで、oc login
の時に利用するURLが還元されますが、このURLは利用できません。
PrivateLinkを有効にするセットアップとしているので、プライベートからしかアクセスできないようになっています。
hypershift.local
というHosted Zoneが切られています。
その中のapi.rosahcp.hypershift.local
が、その対象となっています。
VPC EndpointのSecurity Groupの設定変更
ROSAクラスタが作成されると、ROSAを配置したサブネットにVPC Endpointがくっついています。先ほどのapi.rosahcp.hypershift.local
は、このVPC EndpointにCNAMEが切られています。現時点ではこのVPC EndpointのSecurity GroupのインバウンドルールはデフォルトのSecurity Groupからのアクセスのみを許可する設定となっているので、変更しましょう。(変更しないと、このあとのoc login
ができないです)
# VPC EndpointのIDを取得する
% aws ec2 describe-vpc-endpoints --query 'VpcEndpoints[].VpcEndpointId' --output text
vpce-0d9fba9f6cc0616da
# そのVPC Endpointに設定されているSecurity GroupのIDを取得する
% aws ec2 describe-vpc-endpoints ¥
| jq --raw-output '.VpcEndpoints[] ¥
| select(.VpcEndpointId == "vpce-0d9fba9f6cc0616da") ¥
| .Groups[0].GroupId'
sg-04e148ded114f8b6c
# VPC内からのアクセスを許可する
% aws ec2 authorize-security-group-ingress --group-id sg-04e148ded114f8b6c --protocol all --cidr 10.0.0.0/16
oc get nodes
しよう
それでは、oc get nodes
をしに行きましょう。
先ほども触れた通り、インターネット経由でoc
コマンドは実行できないので、Private Subnetに展開したEC2まで移動する必要があります。入力するパラメータはCloudFormationのOutputから適宜拾ってください。
# 多段SSHの実行
ssh -o ProxyCommand='ssh -i ~/Downloads/rosahcp-vpc.pem -W %h:%p ec2-user@<PublicEC2InstancePublicIP>' -i ~/Downloads/rosahcp-vpc.pem ec2-user@<PrivateEC2InstancePrivateIP>
# rosaコマンドのダウンロードと展開
curl -L https://mirror.openshift.com/pub/openshift-v4/clients/rosa/latest/rosa-linux.tar.gz ¥
| tar -xz -C /tmp ¥
&& sudo mv /tmp/rosa /usr/local/bin ¥
&& sudo chmod +x /usr/local/bin/rosa
# ocコマンドのダウンロードと展開
$ tar -zxvf ./openshift-client-linux.tar.gz -C /tmp/ ¥
&& sudo mv /tmp/oc /usr/local/bin/ ¥
&& sudo chmod +x /usr/local/bin/oc
# バージョンの確認
$ oc version
Client Version: 4.13.0
Kustomize Version: v4.5.7
# oc login
$ oc login https://api.rosahcp.hypershift.local:443 --username cluster-admin --password ...snip...
...snip...
Login successful.
# oc get nodes
$ oc get nodes
NAME STATUS ROLES AGE VERSION
ip-10-0-2-169.ec2.internal Ready worker 2m2s v1.25.8+37a9a08
ip-10-0-2-35.ec2.internal Ready worker 2m4s v1.25.8+37a9a08
Master Nodeが見えないようになっています!
おわりに
今回はPrivate Tech Preview中であるROSAのHosted Control Planeのインストールをお試ししてみました。コントロールプレーンをRed Hatがマネージドしてくれることで、コストを抑えられますし、何より起動時間がとても短くなったのが嬉しいです。m5.xlargeが2台で構成できるので、お財布にも優しいです。
また、大きな企業の場合、AWSアカウントはLanding Zoneのような構成を取るでしょうし、これまでのROSAやOCPを展開するときは、お金の都合で複数システム相乗りとなりがちだったのかなとも想像します。ROSA with HCPを使うことで、AWSのPrescriptive Guidanceに沿った実装に近づけることができるとも思います。
ROSAの中の人曰く、GAは2023Q3を予定しているそうです。楽しみです。