1
0

More than 1 year has passed since last update.

Egress Networkingを考えてから、ROSA(STS+Private Link)をつくる

Last updated at Posted at 2021-10-02

注記

  • 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で外に出ていっている...はず。)

image.png

構築

環境変数をセットアップ。

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 の フローログ

そこそこ取れてるねぇ。

image.png

外に飛んでったそれっぽい通信をユニークかけてみた。んんん~?宛先は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 %
1
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
0