1 はじめに
ある AWS Account に ROSA HCP クラスターを作成した後、別の AWS Account から oc
コマンドを実行できるように構成してみます。
この構成が取れる事自体はドキュメントに記載があるのですが、AWS側の設定の詳細な手順が載っていないので、実際に手を動かして AWS側の設定を確認してみます。
AWS側の構成は環境によっていろいろ異なってくるので、このドキュメントの手順はあくまで一例である事をご理解ください。
2.作業開始の前提条件
この手順では、ROSAが構成されており、以下の状態の AWS コンポーネントが存在している状態を想定してます。
3. AWS Account-B 側での作業
3.1 Bastion-B のツールの準備
EC2 bastion-B
にログインして、oc
コマンドなどの必要なツールをセットアップします。
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
oc
コマンドが実行できる事を確認します。(この時点では、Cluster には接続できないので、コマンドのインストールだけの確認になります。)
oc version
3.2 IAM Role と IAM Policy の準備
3.2.1 IAM Policy の作成
以下の vpce-policy.json
ファイルを作成します。
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "VisualEditor0",
"Effect": "Allow",
"Action": [
"vpce:*",
"ec2:CreateVpcEndpointServiceConfiguration",
"ec2:CreateVpcEndpoint",
"ec2:CreateVpcEndpointConnectionNotification"
],
"Resource": "*"
}
]
}
上記の json を使って IAMPolicy (名前:ROSAHcpVPCEndpointPolicy) を作成します。
IAM_POLICY_ARN=$(aws iam create-policy \
--policy-name ROSAHcpVPCEndpointPolicy \
--policy-document file://vpce-policy.json \
--query 'Policy.Arn' \
--output text )
3.2.2 IAMRole の作成
現在使用している IAM User の ARNを取得します。
IAMUSER_ARN=$(aws sts get-caller-identity \
--query "Arn" \
--output text)
以下のような信頼関係の json ファイルを作成します。
cat > trust-policy.json <<EOF
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": {
"AWS": "$IAMUSER_ARN"
},
"Action": "sts:AssumeRole"
}
]
}
EOF
作成した json ファイルを使用して IAMRole (名前:ROSAHcpVPCEndpointRole) を作成します。
IAM_ROLE_ARN=$(aws iam create-role \
--role-name ROSAHcpVPCEndpointRole \
--assume-role-policy-document file://trust-policy.json \
--query 'Role.Arn' \
--output text )
作成した IAMRole の ARN を確認します。
echo $IAM_ROLE_ARN
結果は、arn:aws:iam::822827512345:role/ROSAHcpVPCEndpointRole
のような値になるはずです。この後使うのでメモしておきます。
IAMRole に IAMPolicy をアタッチします。
aws iam attach-role-policy \
--role-name ROSAHcpVPCEndpointRole \
--policy-arn $IAM_POLICY_ARN
これで必要な IAMRole が完成しました。
3.3 AWS CLI から作成した IAMRole に AssumeRole できるようにする設定
前の手順で作成した IAMRole を使用するように AWS CLI を構成します。
~/.aws/config を編集して、以下のような [profile myporfile]
移行の部分を作成します。
今回、作成した IAMRole の ARN の値を入れます。 (この手順の例ではarn:aws:iam::822827512345:role/ROSAHcpVPCEndpointRole
)
[default]
region = <AWS Reigon Name>
[profile myprofile]
role_arn = <作成したIAM_ROLE_ARN の値>
source_profile = default
region = < 自分の AWS Region>
※[default] を含む、はじめの2行は、筆者の環境での既存の記述です。
4. AWS Account-A 側での作業
4.1 IAMRole の rosa cluster への登録
こちらのアカウントでは、rosa
コマンドを使って、AWS Account-B で作成した IAMRole の ARN を登録します。
Bastion-A (もしくは rosa コマンドが実行できる場所) から、以下のコマンドを実行します。
変数を準備します。IAMRole の ARN は、arn:aws:iam::822827512345:role/ROSAHcpVPCEndpointRole
のような値です。
CLUSTER_NAME=$(rosa list clusters -o json | jq '.[0].name' | sed 's/"//g')
IAM_ROLE_ARN=< AWS Account-B で作成した IAMRole の ARN>
変数の準備が終わったら、以下を実行し、AWS Account-B 側で作成した IAMRole を登録します。
rosa edit cluster -c $CLUSTER_NAME --additional-allowed-principals $IAM_ROLE_ARN
きちんと IAMRole の ARN が得録されたかは以下のコマンドで確認できます。
rosa describe cluster -c $CLUSTER_NAME | grep "Additional Principals:"
4.2 VPC Endpoint の Service Name を確認
Hosted Controlplane にアクセスするために使われている VPC Endpoint の Service Name を調べます。
環境内に複数の VPC Endpoint がある場合もあるので、適切なものを選びます。
$ aws ec2 describe-vpc-endpoints --query "VpcEndpoints[*].[VpcEndpointId, ServiceName]" --output table
--------------------------------------------------------------------------------------------
| DescribeVpcEndpoints |
+-------------------------+----------------------------------------------------------------+
| vpce-063e11f70f9425678 | com.amazonaws.vpce.ap-northeast-1.vpce-svc-00d2aa09630561234 |
+-------------------------+----------------------------------------------------------------+
$
上記の例では、com.amazonaws.vpce.ap-northeast-1.vpce-svc-00d2aa09630561234
が Hosted Controlplane にアクセスするための Service Name
になります。この名前は後の作業で使うのでメモしておきます。
4.3 ROSA Cluster の API URLの取得
ROSA Cluster の API URLを調べます。この値は後で使うのでメモしておきます。 https://api.rosahcp.3314.p3.openshiftapps.com:443
のような値です。
rosa describe cluster -c $CLUSTER_NAME -o json | jq -r '.api.url'
5. AWS Account-B 側での作業
5.1 VPC Endpoint の作成
変数を準備します。
AWS Account-A でメモした、VPC Endpoint の Serivce Name
を変数に設定します。
この手順の例では、com.amazonaws.vpce.ap-northeast-1.vpce-svc-00d2aa09630561234
がそれになります。
SERVICE_NAME=<AWS Account-A で取得した VPC Endpoint の Service Name>
AWS Account-B の EC2のインスタンスIDを AWSコンソールなどで調べて変数に設定します。
ISNTANCE_ID=<EC2 bastion-B のインスタンスID>
EC2のIMDSが有効になっている場合は、以下のコマンドで ISNTANCE ID を取得できます。
curl -s http://169.254.169.254/latest/meta-data/instance-id
Instance ID を使って、EC2 が所属している Subnet ID を取得します。
SUBNET_ID=$(aws ec2 describe-instances \
--instance-id $INSTANCE_ID \
--query "Reservations[0].Instances[0].SubnetId" \
--output text)
Subnet ID を使って Subnet の CIDRを取得します。
SUBNET_CIDR=$(aws ec2 describe-subnets \
--subnet-ids $SUBNET_ID \
--query "Subnets[0].CidrBlock" \
--output text)
Instance ID を使って、EC2 が所属している VPC ID を取得します。
VPC_ID=$(aws ec2 describe-instances \
--instance-ids $INSTANCE_ID \
--query "Reservations[0].Instances[0].VpcId" \
--output text)
VPC Endpoint を作成する前に、必要な変数が全て揃っているか確認します。
echo "VPC_ID="$VPC_ID, "SERVICE_NAME="$SERVICE_NAME, "SUBNET_ID="$SUBNET_ID, "SUBNET_CIDR="$SUBNET_CIDR
VPC Endpoint 用の Security Group を作成します。
SEC_GROUP_ID=$(aws ec2 create-security-group \
--group-name MyVPCEndpointSG \
--description "Security Group for VPC Endpoint" \
--vpc-id $VPC_ID \
--tag-specifications 'ResourceType=security-group,Tags=[{Key=Name,Value=MyVPCEndpointSG}]' \
--query 'GroupId' \
--output text)
Security Group 用に インバウンドのルールを追加します。EC2のサブネットからインバウンドを許可する設定にしています。
aws ec2 authorize-security-group-ingress \
--group-id $SEC_GROUP_ID \
--protocol tcp \
--port 443 \
--cidr $SUBNET_CIDR
以下のコマンドで VPC Endpoint を、AWS Account-B 内に作成します。
ENDPOINT_ID=$(aws ec2 create-vpc-endpoint \
--vpc-id $VPC_ID \
--service-name $SERVICE_NAME \
--vpc-endpoint-type Interface \
--subnet-ids $SUBNET_ID \
--security-group-ids $SEC_GROUP_ID \
--query 'VpcEndpoint.VpcEndpointId' \
--output text --profile myprofile )
この時 VPC EndPoint を作成する AWS CLI コマンドが、ROSA Cluster に登録した IAMRole
を使って実行されるように --profile myprofile
オプションを付けて実行されている事に注目してください。
この作業で得にエラーがでなければ、以下の部分が作成された事になります。
次に、Route53 に DNS Zone と レコードを作成し、ROSA HCP API Server の URLを叩いた時に、今、作成した VPC Endpoint にアクセスが誘導されるように構成します。
5.2 Private DNS Zone の作成
oc コマンドを実行した時に、api server のホスト名などが、作成した VPC Endpoint にルートされるように DNSの設定を作成します。
VPC Endpoint の DNS名を取得します。
ENDPOINT_DNS=$(aws ec2 describe-vpc-endpoints \
--vpc-endpoint-ids $ENDPOINT_ID \
--query 'VpcEndpoints[0].DnsEntries[0].DnsName' \
--output text)
手順 4.3 で取得した API URLの値から必要なドメイン名だけ取得して変数 DOMAIN
に設定します。DOMAIN
の値は rosahcp.3314.p3.openshiftapps.com
のような値になるはずです。
API_URL=< ROSA Cluster の API URL>
DOMAIN=$(echo $API_URL | cut -d '/' -f3 | sed 's/^api\.//;s/:.*//')
取得したドメインを使って、Route53 に Zone を作成します。
AWS Region 名が必要なので、作業中の AWS Region 名 (例:ap-northeast-1
) を変数にセットします。
REGION=<作業中の EC2がある AWS Region名>
全ての変数が揃っているか確認します。
echo "DOMAIN="$DOMAIN, "REGION="$REGION, "VPC_ID="$VPC_ID
変数がセットされていたら、以下のコマンドで、Route53に Zone を作成します。
HOSTED_ZONE_ID=$(aws route53 create-hosted-zone \
--name $DOMAIN \
--vpc VPCRegion=$REGION,VPCId=$VPC_ID \
--caller-reference $(date +%s) \
--hosted-zone-config PrivateZone=true \
--query 'HostedZone.Id' \
--output text | cut -d'/' -f3)
作成した Zone に登録するレコードの Json を作成します。
必要な変数が全て揃っている事を確認します。
echo "DOMAIN="$DOMAIN, "HOSTED_ZONE_ID="$HOSTED_ZONE_ID, "ENDPOINT_DNS"=$ENDPOINT_DNS
以下の json を作成します。
cat > record.json <<EOF
{
"Changes": [
{
"Action": "CREATE",
"ResourceRecordSet": {
"Name": "api.$DOMAIN",
"Type": "CNAME",
"TTL": 300,
"ResourceRecords": [
{
"Value": "$ENDPOINT_DNS"
}
]
}
},
{
"Action": "CREATE",
"ResourceRecordSet": {
"Name": "oauth.$DOMAIN",
"Type": "CNAME",
"TTL": 300,
"ResourceRecords": [
{
"Value": "$ENDPOINT_DNS"
}
]
}
}
]
}
EOF
作成した json ファイルを使用してレコードを、Zoneに登録します。
aws route53 change-resource-record-sets \
--hosted-zone-id $HOSTED_ZONE_ID \
--change-batch file://record.json
これで、ROSA Cluster の API URL にアクセスすると、VPC End Point の DNS名に解決されて、リクエストが Hosted Control Plane に行くようになります。
6.接続確認
oc コマンドが実行できるかどうか確認します。
oc login $API_URL --username cluster-admin --password <password>