注記
- ROSAとはあんまり関係のない、URLフィルタリング可能なOutboundアクセスの経路をAWS上につくります。
- 作った上で、ROSAのインストールが成功するかを検証してみます。
ROSA (Red Hat OpenShift on AWS) on Bring Your Own VPC
- この構成をとった場合でもアウトバウンドのアクセスは必要
- しかもこのアクセスはHTTP Proxyを通せない(設定できない)
- よって、ROSAクラスタからL3のルーティングでアウトバウンドの経路を確保しないといけない
- ただ、普通にルーティングすると、ROSAクラスタ上のコンテナからも自由にアウトバウンドできてしまう
- せめて、URLフィルタリングするなり、ログを取るなりしないと、怒られる><
構成
Network Firewallの機能で、URLフィルタリングできそうだったので、この構成を目指す。
(ピンクの線は自信ない...Network FirewallはNATしてくれないらしいから、一旦NAT Gatewayに戻ってる、NAT GatewayのEIPで外に出ていっている...はず。)
構築
環境変数をセットアップ。
export ROSA_CLUSTER_NAME=rosa
export REGION=ap-northeast-1
export AZ=ap-northeast-1a
export VPC_CIDR=10.0.0.0/16
export NWFW_CIDR=10.0.10.0/24
export NAT_CIDR=10.0.20.0/24
export ROSA_CIDR=10.0.30.0/24
VPC作る
# === VPC ===
VPC_ID=`aws ec2 create-vpc --cidr-block $VPC_CIDR | jq -r .Vpc.VpcId`
aws ec2 create-tags --resources $VPC_ID --tags Key=Name,Value=$ROSA_CLUSTER_NAME-vpc
aws ec2 modify-vpc-attribute --vpc-id $VPC_ID --enable-dns-hostnames
Subnetも作る(3つ)
# === Subnet ===
NWFW_SUBNET=`aws ec2 create-subnet --vpc-id $VPC_ID --cidr-block $NWFW_CIDR --availability-zone $AZ | jq -r .Subnet.SubnetId`
NAT_SUBNET=`aws ec2 create-subnet --vpc-id $VPC_ID --cidr-block $NAT_CIDR | jq -r .Subnet.SubnetId`
ROSA_SUBNET=`aws ec2 create-subnet --vpc-id $VPC_ID --cidr-block $ROSA_CIDR | jq -r .Subnet.SubnetId`
aws ec2 create-tags --resources $NWFW_SUBNET --tags Key=Name,Value=$ROSA_CLUSTER_NAME-nwfw
aws ec2 create-tags --resources $NAT_SUBNET --tags Key=Name,Value=$ROSA_CLUSTER_NAME-nat
aws ec2 create-tags --resources $ROSA_SUBNET --tags Key=Name,Value=$ROSA_CLUSTER_NAME-rosa
IGWも作って、VPCにくっつける
# === IGW ===
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
aws ec2 create-tags --resources $I_GW --tags Key=Name,Value=$ROSA_CLUSTER_NAME-igw
NAT Gateway 作って、真ん中のSubnetに置く
このNAT GatewayはPrivateじゃだめで、EIPが必要だった。
この展開モデルでは、Network Firewallを使用して、あらゆるインターネット行きのトラフィックを保護します。ワークロードのサブネットには、対応するAZのファイアウォールエンドポイントへのデフォルトルートがあります。Firewallサブネットには、IGW経由のデフォルトルートがあります。Network FirewallはNATを行わないため、インターネットへの出入りは、ワークロードサブネット内の個々のElastic Network Interface(ENI)に関連付けられたパブリックIPまたはEIPに依存します。IGWではVPC Ingress Routingを利用して戻りのトラフィックを対応するAZのファイアウォールのエンドポイントに誘導します。これにより、トラフィックは正しいファイアウォールエンドポイントに対称的に戻され、ステートフルトラフィックインスペクションを維持することができます。
# === NAT GW ===
EIP=`aws ec2 allocate-address --domain vpc | jq -r .AllocationId`
NAT_GW=`aws ec2 create-nat-gateway --subnet-id $NAT_SUBNET --allocation-id $EIP | jq -r .NatGateway.NatGatewayId`
aws ec2 create-tags --resources $EIP --resources $NAT_GW --tags Key=Name,Value=$ROSA_CLUSTER_NAME-natgw
Network Firewall作るんだけど、
Rule Groupつくって、Firewall Policyつくってからじゃないと作れないので、順番に作る。
ここで、example.com
へのアクセスをALLOWLIST
に入れている。
# === NWFW ===
cat <<EOF > rule-group.json
{
"RulesSource": {
"RulesSourceList": {
"Targets": [
"example.com"
],
"TargetTypes": [
"HTTP_HOST",
"TLS_SNI"
],
"GeneratedRulesType": "ALLOWLIST"
}
}
}
EOF
StatefulRuleGroup=`aws network-firewall create-rule-group --rule-group-name $ROSA_CLUSTER_NAME-rule-group --type STATEFUL --capacity 100 --rule-group file://rule-group.json | jq -r .RuleGroupResponse.RuleGroupArn`
cat <<EOF > firewall-policy.json
{
"StatelessRuleGroupReferences": [],
"StatelessDefaultActions": [
"aws:forward_to_sfe"
],
"StatelessFragmentDefaultActions": [
"aws:forward_to_sfe"
],
"StatelessCustomActions": [],
"StatefulRuleGroupReferences": [
{
"ResourceArn": "$StatefulRuleGroup"
}
]
}
EOF
FirewallPolicyArn=`aws network-firewall create-firewall-policy --firewall-policy-name $ROSA_CLUSTER_NAME-fw-policy --firewall-policy file://firewall-policy.json | jq -r .FirewallPolicyResponse.FirewallPolicyArn`
sleep 120;
FirewallArn=`aws network-firewall create-firewall --firewall-name $ROSA_CLUSTER_NAME-nwfw --firewall-policy-arn $FirewallPolicyArn --vpc-id $VPC_ID --subnet-mappings SubnetId=$NWFW_SUBNET | jq -r .Firewall.FirewallArn`
sleep 120;
VPC_E=`aws network-firewall describe-firewall --firewall-arn $FirewallArn | jq -r .FirewallStatus.SyncStates'["ap-northeast-1a"]'.Attachment.EndpointId`
各サブネットからのゲートウェイがそれぞれできたので、(IGW、Network FirewallのVPCe、NAT GW)
Route Tableをつくる。
# === ROUTE TABLE ===
NWFW_R_TABLE=`aws ec2 create-route-table --vpc-id $VPC_ID | jq -r .RouteTable.RouteTableId`
aws ec2 create-route --route-table-id $NWFW_R_TABLE --destination-cidr-block 0.0.0.0/0 --gateway-id $I_GW
aws ec2 associate-route-table --subnet-id $NWFW_SUBNET --route-table-id $NWFW_R_TABLE
aws ec2 create-tags --resources $NWFW_R_TABLE --tags Key=Name,Value=$ROSA_CLUSTER_NAME-nwfw-rt
NAT_R_TABLE=`aws ec2 create-route-table --vpc-id $VPC_ID | jq -r .RouteTable.RouteTableId`
aws ec2 create-route --route-table-id $NAT_R_TABLE --destination-cidr-block 0.0.0.0/0 --vpc-endpoint-id $VPC_E
aws ec2 associate-route-table --subnet-id $NAT_SUBNET --route-table-id $NAT_R_TABLE
aws ec2 create-tags --resources $NAT_R_TABLE --tags Key=Name,Value=$ROSA_CLUSTER_NAME-nat-rt
ROSA_R_TABLE=`aws ec2 create-route-table --vpc-id $VPC_ID | jq -r .RouteTable.RouteTableId`
aws ec2 create-route --route-table-id $ROSA_R_TABLE --destination-cidr-block 0.0.0.0/0 --gateway-id $NAT_GW
aws ec2 associate-route-table --subnet-id $ROSA_SUBNET --route-table-id $ROSA_R_TABLE
aws ec2 create-tags --resources $ROSA_R_TABLE --tags Key=Name,Value=$ROSA_CLUSTER_NAME-rosa-rt
IGW_R_TABLE=`aws ec2 create-route-table --vpc-id $VPC_ID | jq -r .RouteTable.RouteTableId`
aws ec2 create-route --route-table-id $IGW_R_TABLE --destination-cidr-block $NAT_CIDR --vpc-endpoint-id $VPC_E
aws ec2 associate-route-table --gateway-id $I_GW --route-table-id $IGW_R_TABLE
aws ec2 create-tags --resources $IGW_R_TABLE --tags Key=Name,Value=$ROSA_CLUSTER_NAME-igw-rt
あとは、適当に踏み台のEC2と最奥のEC2を作る。(割愛)
テスト
cURLで試す。うまく動いてそう。
$ curl -I https://example.com
HTTP/2 200
...snip...
$ curl -I https://google.com
(応答なし)
片付け
非同期でレスが返ってくるので、ちゃんと消えてからじゃないと、次のコマンド打てない。
# Delete Route
aws ec2 delete-route --route-table-id $ROSA_R_TABLE --destination-cidr-block 0.0.0.0/0
aws ec2 delete-route --route-table-id $NAT_R_TABLE --destination-cidr-block 0.0.0.0/0
aws ec2 delete-route --route-table-id $NWFW_R_TABLE --destination-cidr-block 0.0.0.0/0
aws ec2 delete-route --route-table-id $IGW_R_TABLE --destination-cidr-block $NAT_CIDR
# Delete Network Firewall
aws network-firewall delete-firewall --firewall-name $ROSA_CLUSTER_NAME-nwfw
aws network-firewall delete-firewall-policy --firewall-policy-name $ROSA_CLUSTER_NAME-fw-policy --firewall-policy-arn $FirewallPolicyArn
aws network-firewall delete-rule-group --rule-group-name $ROSA_CLUSTER_NAME-rule-group --type STATEFUL
# Delete NAT Gateway & EIP
aws ec2 delete-nat-gateway --nat-gateway-id $NAT_GW
aws ec2 release-address --allocation-id $EIP
# Delete Internet Gateway
aws ec2 detach-internet-gateway --vpc-id $VPC_ID --internet-gateway-id $I_GW
aws ec2 delete-internet-gateway --internet-gateway-id $I_GW
# Delete Subnet
aws ec2 delete-subnet --subnet-id $NWFW_SUBNET
aws ec2 delete-subnet --subnet-id $NAT_SUBNET
aws ec2 delete-subnet --subnet-id $ROSA_SUBNET
# Delete Route Table
aws ec2 delete-route-table --route-table-id $NWFW_R_TABLE
aws ec2 delete-route-table --route-table-id $NAT_R_TABLE
aws ec2 delete-route-table --route-table-id $ROSA_R_TABLE
aws ec2 delete-route-table --route-table-id $IGW_R_TABLE
# Delete VPC
aws ec2 delete-vpc --vpc-id $VPC_ID
ROSAの構築
前提
- Network Firewallの制限は切っておく。代わりにロギングをONにしておく
-
rosa
コマンドのインストールが済んでいる -
rosa login
が済んでいる -
rosa init
が未済である(実行するとosdCcsAdminというIAM Userが作られてしまうため)
ROSAのインストール
# 環境変数をセット
export VERSION=4.8.5 \
ROSA_CLUSTER_NAME=rosacluster \
AWS_ACCOUNT_ID=`aws sts get-caller-identity --query Account --output text` \
REGION=ap-northeast-1 \
AWS_PAGER=""
# AWSの権限が十分かを確認する
rosa verify permissions
# ROSAに必要な各種RoleやPolicyをつくる
rosa create account-roles --mode auto --version "${VERSION%.*}" -y
# ROSAクラスタのインストールを開始する
rosa create cluster -y --sts --cluster-name ${ROSA_CLUSTER_NAME} \
--region ${REGION} --version ${VERSION} \
--subnet-ids=$ROSA_SUBNET \
--private-link --machine-cidr=$VPC_CIDR \
--support-role-arn arn:aws:iam::${AWS_ACCOUNT_ID}:role/ManagedOpenShift-Support-Role \
--role-arn arn:aws:iam::${AWS_ACCOUNT_ID}:role/ManagedOpenShift-Installer-Role \
--master-iam-role arn:aws:iam::${AWS_ACCOUNT_ID}:role/ManagedOpenShift-ControlPlane-Role \
--worker-iam-role arn:aws:iam::${AWS_ACCOUNT_ID}:role/ManagedOpenShift-Worker-Role
OIDCの設定(Red Hat SREチーム向け)
rosa create operator-roles -c $ROSA_CLUSTER_NAME --mode auto --yes
rosa create oidc-provider -c $ROSA_CLUSTER_NAME --mode auto --yes
ROSAのインストールの進捗確認
watch "rosa describe cluster -c $ROSA_CLUSTER_NAME"
Network Firewall の フローログ
そこそこ取れてるねぇ。
外に飛んでったそれっぽい通信をユニークかけてみた。んんん~?宛先はS3かぁ~?
dst_ip | dst_port |
---|---|
52.119.222.137 | 443 |
52.219.1.87 | 443 |
52.219.16.250 | 443 |
52.219.68.43 | 443 |
52.219.8.226 | 443 |
93.184.216.34 | 443 |
93.184.216.34 | 80 |
----------------- | ----------------- |
インストールはできた
めでたし、めでたし。
$ rosa logs install -c $ROSA_CLUSTER_NAME
I: Cluster 'rosa' has been successfully installed
ROSAのお片付け(IAM RoleやPolicy編)
ただのメモ。きたねぇ花火だ。
aws iam list-roles | jq -r '.Roles[] | select(.RoleName | startswith("ManagedOpenShift")) | .RoleName' | xargs -I% aws iam delete-role-policy --role-name % --policy-name %-Policy
InstanceProfileName=`aws iam list-instance-profiles | jq -r '.InstanceProfiles[] | select(.Roles[].RoleName | startswith("ManagedOpenShift")) | .InstanceProfileName'`
RoleName=`aws iam list-instance-profiles | jq -r '.InstanceProfiles[].Roles[] | select(.RoleName | startswith("ManagedOpenShift")) | .RoleName'`
aws iam remove-role-from-instance-profile --instance-profile-name $InstanceProfileName --role-name $RoleName
aws iam delete-role --role-name ManagedOpenShift-Installer-Role
aws iam delete-role --role-name ManagedOpenShift-ControlPlane-Role
aws iam delete-role --role-name ManagedOpenShift-Worker-Role
aws iam delete-role --role-name ManagedOpenShift-Support-Role
aws iam list-roles | jq -r ".Roles[] | select(.RoleName | startswith(\"$ROSA_CLUSTER_NAME\")) | .RoleName" | xargs -I% aws iam delete-role --role-name %
for i in `seq 5`
do
RoleName=`aws iam list-roles | jq -r ".Roles[] | select(.RoleName | startswith(\"$ROSA_CLUSTER_NAME\")) | .RoleName" | head -n 1`
PolicyArn=`aws iam list-attached-role-policies --role-name $RoleName | jq -r .AttachedPolicies[].PolicyArn`
aws iam detach-role-policy --policy-arn $PolicyArn --role-name $RoleName
aws iam delete-role --role-name $RoleName
done
aws iam delete-policy --policy-arn arn:aws:iam::${AWS_ACCOUNT_ID}:policy/ManagedOpenShift-openshift-machine-api-aws-cloud-credentials
aws iam delete-policy --policy-arn arn:aws:iam::${AWS_ACCOUNT_ID}:policy/ManagedOpenShift-openshift-cloud-credential-operator-cloud-crede
aws iam delete-policy --policy-arn arn:aws:iam::${AWS_ACCOUNT_ID}:policy/ManagedOpenShift-openshift-image-registry-installer-cloud-creden
aws iam delete-policy --policy-arn arn:aws:iam::${AWS_ACCOUNT_ID}:policy/ManagedOpenShift-openshift-ingress-operator-cloud-credentials
aws iam delete-policy --policy-arn arn:aws:iam::${AWS_ACCOUNT_ID}:policy/ManagedOpenShift-openshift-cluster-csi-drivers-ebs-cloud-credent
OPENID_PROVIDER_ARN=`aws iam list-open-id-connect-providers | jq -r .OpenIDConnectProviderList[].Arn`
aws iam delete-open-id-connect-provider --open-id-connect-provider-arn $OPENID_PROVIDER_ARN
aws iam list-roles | jq '.Roles[] | select(.RoleName | startswith("rosa")) | .RoleName' | xargs -I% aws iam delete-role --role-name %