Security Group for Pod - 环境准备

容器化应用程序经常需要访问外部 AWS 服务,例如RDS, ElastiCache。在 AWS 上,控制服务之间的网络访问通常是通过安全组

在发布此新功能之前,只能在节点级别分配安全组。由于节点组内的所有节点共享安全组,因此通过将访问 RDS 实例的安全组附加到节点组,这些节点上运行的所有 pod 都可以访问数据库,即使只有绿色 pod 应该具有访问权限。

SG-per-pod_1

Pod 的安全组 将EC2 安全组与 Kubernetes Pod 集成,可以使用EC2 安全组定义规则来控制进出 Pod 的入站和出站网络流量

目标

本节内容:

  • 创建一个RDS,上面绑定 RDS_SG安全组。
  • 部署一个SecurityGroupPolicy,它自动将 POD_SG 安全组附加到具有正确元数据的 pod。
  • 最后,我们将使用同一镜像部署两个 Pod(绿色和红色),并验证其中只有一个(绿色)可以连接到RDS 数据库。

SG-per-pod_3

环境准备

大多数基于 Nitro 的 Amazon EC2 实例系列都支持 Pod 安全组,包括m5c5r5p3m6gc6gr6g实例系列,但t3不支持。因此如果当前nodegroup是t3的话,需要使用Nitro实例创建第二个 NodeGroup:

mkdir ${HOME}/environment/sg-per-pod

cat << EoF > ${HOME}/environment/sg-per-pod/nodegroup-sec-group.yaml
apiVersion: eksctl.io/v1alpha5
kind: ClusterConfig
metadata:
  name: ${EKS_CLUSTER}
  region: ${AWS_REGION}

managedNodeGroups:
- name: nodegroup-sec-group
  desiredCapacity: 1
  instanceType: m5.large
EoF

eksctl create nodegroup -f ${HOME}/environment/sg-per-pod/nodegroup-sec-group.yaml

 kubectl get nodes \
  --selector node.kubernetes.io/instance-type=m5.large

创建并配置安全组

首先创建 RDS 安全组 (RDS_SG)。 Amazon RDS 实例将使用它来控制网络访问。

export VPC_ID=$(aws eks describe-cluster \
    --name $EKS_CLUSTER \
    --query "cluster.resourcesVpcConfig.vpcId" \
    --output text)

# create RDS security group
aws ec2 create-security-group \
    --description 'RDS SG' \
    --group-name 'RDS_SG' \
    --vpc-id ${VPC_ID}

# save the security group ID for future use
export RDS_SG=$(aws ec2 describe-security-groups \
    --filters Name=group-name,Values=RDS_SG Name=vpc-id,Values=${VPC_ID} \
    --query "SecurityGroups[0].GroupId" --output text)

echo "RDS security group ID: ${RDS_SG}"

image-20240204090436730

创建 Pod 安全组 (POD_SG):

# create the POD security group
aws ec2 create-security-group \
    --description 'POD SG' \
    --group-name 'POD_SG' \
    --vpc-id ${VPC_ID}

# save the security group ID for future use
export POD_SG=$(aws ec2 describe-security-groups \
    --filters Name=group-name,Values=POD_SG Name=vpc-id,Values=${VPC_ID} \
    --query "SecurityGroups[0].GroupId" --output text)

echo "POD security group ID: ${POD_SG}"

Pod 需要与其所在Node进行通信以进行 DNS 解析,因此我们将相应地更新 Node Group 安全组:

export NODE_GROUP_SG=$(aws ec2 describe-security-groups \
    --filters Name=tag:Name,Values=eks-cluster-sg-${EKS_CLUSTER}-* Name=vpc-id,Values=${VPC_ID} \
    --query "SecurityGroups[0].GroupId" \
    --output text)
echo "Node Group security group ID: ${NODE_GROUP_SG}"

# allow POD_SG to connect to NODE_GROUP_SG using TCP 53
aws ec2 authorize-security-group-ingress \
    --group-id ${NODE_GROUP_SG} \
    --protocol tcp \
    --port 53 \
    --source-group ${POD_SG}

# allow POD_SG to connect to NODE_GROUP_SG using UDP 53
aws ec2 authorize-security-group-ingress \
    --group-id ${NODE_GROUP_SG} \
    --protocol udp \
    --port 53 \
    --source-group ${POD_SG}

image-20240204090840986

最后,我们添加两个入站流量(ingress)规则到 RDS_SG 安全组:

  • 一个用于 Cloud9(用于填充数据库)
  • 另一个是允许 POD_SG 安全组连接数据库
# Cloud9 IP
export C9_IP=$(curl -s http://169.254.169.254/latest/meta-data/public-ipv4)

# allow Cloud9 to connect to RDS
aws ec2 authorize-security-group-ingress \
    --group-id ${RDS_SG} \
    --protocol tcp \
    --port 5432 \
    --cidr ${C9_IP}/32

# Allow POD_SG to connect to the RDS
aws ec2 authorize-security-group-ingress \
    --group-id ${RDS_SG} \
    --protocol tcp \
    --port 5432 \
    --source-group ${POD_SG}

image-20240204091034178

创建RDS

现在安全组已准备就绪,现在创建RDS for PostgreSQL 数据库。

首先需要创建一个subnet group, 我们将使用与 EKS 集群相同的子网。

export PUBLIC_SUBNETS_ID=$(aws ec2 describe-subnets \
    --filters "Name=vpc-id,Values=$VPC_ID" "Name=tag:Name,Values=eksctl-${EKS_CLUSTER}-cluster/SubnetPublic*" \
    --query 'Subnets[*].SubnetId' \
    --output json | jq -c .)

echo $PUBLIC_SUBNETS_ID

# create a db subnet group
aws rds create-db-subnet-group \
    --db-subnet-group-name rds-eksworkshop \
    --db-subnet-group-description rds-eksworkshop \
    --subnet-ids ${PUBLIC_SUBNETS_ID}

image-20240204091252243

创建数据库:

# get RDS SG ID
export RDS_SG=$(aws ec2 describe-security-groups \
    --filters Name=group-name,Values=RDS_SG Name=vpc-id,Values=${VPC_ID} \
    --query "SecurityGroups[0].GroupId" --output text)

# generate a password for RDS
export RDS_PASSWORD="$(date | md5sum  |cut -f1 -d' ')"
echo ${RDS_PASSWORD}    # 记下来这个密码


# create RDS Postgresql instance
aws rds create-db-instance \
    --db-instance-identifier rds-eksworkshop \
    --db-name eksworkshop \
    --db-instance-class db.t3.micro \
    --engine postgres \
    --db-subnet-group-name rds-eksworkshop \
    --vpc-security-group-ids $RDS_SG \
    --master-username eksworkshop \
    --publicly-accessible \
    --master-user-password ${RDS_PASSWORD} \
    --backup-retention-period 0 \
    --allocated-storage 20

创建数据库最多需要 4 分钟,可以使用此命令验证它是否可用:

aws rds describe-db-instances \
    --db-instance-identifier rds-eksworkshop \
    --query "DBInstances[].DBInstanceStatus" \
    --output text

等待数据库状态变成available

获取数据库端点:

# get RDS endpoint
export RDS_ENDPOINT=$(aws rds describe-db-instances \
    --db-instance-identifier rds-eksworkshop \
    --query 'DBInstances[0].Endpoint.Address' \
    --output text)

echo "RDS endpoint: ${RDS_ENDPOINT}"

连接到数据库:

 PGPASSWORD=${RDS_PASSWORD} psql -h ${RDS_ENDPOINT} -U eksworkshop  -d eksworkshop

image-20240204092548191

在数据库中创建一些内容:

CREATE TABLE welcome (column1 TEXT);
insert into welcome values ('--------------------------');
insert into welcome values ('Welcome to the eksworkshop');
insert into welcome values ('--------------------------');

image-20240204092627092