如何在AWS中创建Kubernetes集群并为Pod配置安全组[完整手册]
Amazon Elastic Kubernetes Service (EKS) Pod安全组是一项强大功能,可在Pod级别实现精细的网络安全控制。本指南将引导您实现此功能,从初始集群设置到测试Pod级别安全组分配。
传统EKS网络与Pod安全组架构
传统EKS网络
在标准EKS网络设置中,安全发生在节点级别而非Pod级别。使用传统模型创建EKS集群时,每个EC2工作节点都会分配一个安全组。该节点上运行的所有Pod都继承来自其宿主节点的相同安全组设置。
这种方法有显著限制。例如,如果一个Pod需要访问数据库而另一个Pod不应该访问,当两个Pod共享节点的安全组时,您无法强制执行此区分。
Pod安全组架构
这种网络模型完全改变了这种范式。启用Pod安全组后,您可以根据Pod的特定需求为其分配专用安全组。某些Pod可以获得自己的弹性网络接口(ENI)和自定义安全组分配,而不是所有Pod都继承节点的安全组。
ENI本质上是AWS中的虚拟网卡。当我们为Pod分配ENI时,该Pod获得与其运行节点分离的专用网络身份。
工作原理
Pod安全组的实现依赖于几个相互连接的机制协同工作。首先,当您通过SecurityGroupPolicy标记Pod进行特殊安全组处理时,系统会自动为该Pod配置专用ENI。
分支网络能力在此至关重要。EC2实例对它们可以支持的ENI数量有限制。VPC CNI插件使用这些额外的ENI插槽为需要自定义安全组的Pod创建分支接口。
基础设施基础
IAM角色和策略设置
EKS集群服务角色
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
|
# 创建EKS集群服务角色
aws iam create-role \
--role-name EKSClusterRole \
--assume-role-policy-document '{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": {
"Service": "eks.amazonaws.com"
},
"Action": "sts:AssumeRole"
}
]
}'
|
EKS集群附加角色策略
1
2
3
4
5
6
7
8
|
# 附加所需策略
aws iam attach-role-policy \
--role-name EKSClusterRole \
--policy-arn arn:aws:iam::aws:policy/AmazonEKSClusterPolicy
aws iam attach-role-policy \
--role-name EKSClusterRole \
--policy-arn arn:aws:iam::aws:policy/AmazonEKSVPCResourceController
|
EKS节点组角色
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
|
# 创建节点组角色
aws iam create-role \
--role-name EKSNodeGroupRole \
--assume-role-policy-document '{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": {
"Service": "ec2.amazonaws.com"
},
"Action": "sts:AssumeRole"
}
]
}'
|
VPC和网络基础设施
VPC创建和配置
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
|
# 创建VPC
export VPC_ID=$(aws ec2 create-vpc \
--cidr-block 10.0.0.0/16 \
--name 'eks-security-demo'
--query 'Vpc.VpcId' \
--output text)
# 创建Internet Gateway
export IGW_ID=$(aws ec2 create-internet-gateway \
--query 'InternetGateway.InternetGatewayId' \
--output text)
# 将Internet Gateway附加到VPC
aws ec2 attach-internet-gateway \
--internet-gateway-id $IGW_ID \
--vpc-id $VPC_ID
|
子网架构策略
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
|
# 公共子网用于NAT网关和负载均衡器
export PUBLIC_SUBNET_1=$(aws ec2 create-subnet \
--vpc-id $VPC_ID \
--cidr-block 10.0.1.0/24 \
--availability-zone eu-west-1a \
--query 'Subnet.SubnetId' \
--output text)
export PUBLIC_SUBNET_2=$(aws ec2 create-subnet \
--vpc-id $VPC_ID \
--cidr-block 10.0.2.0/24 \
--availability-zone eu-west-1b \
--query 'Subnet.SubnetId' \
--output text)
# 私有子网用于工作节点和RDS
export PRIVATE_SUBNET_1=$(aws ec2 create-subnet \
--vpc-id $VPC_ID \
--cidr-block 10.0.3.0/24 \
--availability-zone eu-west-1a \
--query 'Subnet.SubnetId' \
--output text)
export PRIVATE_SUBNET_2=$(aws ec2 create-subnet \
--vpc-id $VPC_ID \
--cidr-block 10.0.4.0/24 \
--availability-zone eu-west-1b \
--query 'Subnet.SubnetId' \
--output text)
|
EKS集群配置
EKS集群创建
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
|
export CLUSTER_ROLE_ARN=$(aws iam get-role \
--role-name EKSClusterRole \
--query 'Role.Arn' \
--output text)
# 创建EKS集群
aws eks create-cluster \
--name pod-security-cluster-demo \
--kubernetes-version 1.33 \
--role-arn $CLUSTER_ROLE_ARN \
--access-config authenticationMode=API_AND_CONFIG_MAP \
--resources-vpc-config subnetIds=$PUBLIC_SUBNET_1,$PUBLIC_SUBNET_2,$PRIVATE_SUBNET_1,$PRIVATE_SUBNET_2
# 等待集群激活
aws eks wait cluster-active --name pod-security-cluster-demo
|
托管节点组设置
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
|
# 获取节点组角色的ARN
export NODE_ROLE_ARN=$(aws iam get-role \
--role-name EKSNodeGroupRole \
--query 'Role.Arn' \
--output text)
# 创建托管节点组
aws eks create-nodegroup \
--cluster-name pod-security-cluster-demo \
--nodegroup-name workers \
--subnets $PRIVATE_SUBNET_1 $PRIVATE_SUBNET_2 \
--node-role $NODE_ROLE_ARN \
--instance-types m5.large \
--scaling-config minSize=1,maxSize=3,desiredSize=2 \
--disk-size 20 \
--capacity-type ON_DEMAND
|
安全组配置
Pod级别安全组创建
1
2
3
4
5
6
7
8
9
|
# 为需要数据库访问的Pod创建安全组
aws ec2 create-security-group \
--description 'Pod Security Group - Database Access' \
--group-name 'POD_SG' \
--vpc-id ${VPC_ID}
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)
|
数据库安全组配置
1
2
3
4
5
6
7
8
9
|
# 为RDS数据库创建安全组
aws ec2 create-security-group \
--description 'RDS Security Group - PostgreSQL Database' \
--group-name 'RDS_SG' \
--vpc-id ${VPC_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)
|
CNI插件配置
启用Pod ENI支持
1
2
3
4
5
6
|
# 在AWS VPC CNI上启用Pod ENI功能
kubectl -n kube-system set env daemonset aws-node ENABLE_POD_ENI=true
# 重启CNI Pod以应用配置
kubectl -n kube-system rollout restart daemonset aws-node
kubectl -n kube-system rollout status daemonset aws-node
|
安全策略实施
SecurityGroupPolicy资源创建
1
2
3
4
5
6
7
8
9
10
11
12
|
apiVersion: vpcresources.k8s.aws/v1beta1
kind: SecurityGroupPolicy
metadata:
name: allow-rds-access
namespace: networking
spec:
podSelector:
matchLabels:
app: green-pod
securityGroups:
groupIds:
- ${POD_SG}
|
测试和验证
绿色Pod(授权数据库访问)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
|
apiVersion: apps/v1
kind: Deployment
metadata:
name: green-pod
namespace: networking
labels:
app: green-pod
spec:
replicas: 1
selector:
matchLabels:
app: green-pod
template:
metadata:
labels:
app: green-pod
spec:
containers:
- name: postgres-client
image: postgres:13-alpine
env:
- name: PGHOST
valueFrom:
secretKeyRef:
name: rds
key: host
- name: PGPASSWORD
valueFrom:
secretKeyRef:
name: rds
key: password
command: ["/bin/sh"]
args:
- -c
- |
echo "Green pod starting - should have database access..."
if psql -c "SELECT version();" 2>/dev/null; then
echo "SUCCESS: Connected to PostgreSQL!"
else
echo "ERROR: Could not connect to database"
fi
sleep 3600
|
红色Pod(未授权数据库访问)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
|
apiVersion: apps/v1
kind: Deployment
metadata:
name: red-pod
namespace: networking
labels:
app: red-pod
spec:
replicas: 1
selector:
matchLabels:
app: red-pod
template:
metadata:
labels:
app: red-pod
spec:
containers:
- name: postgres-client
image: postgres:13-alpine
env:
- name: PGHOST
valueFrom:
secretKeyRef:
name: rds
key: host
- name: PGPASSWORD
valueFrom:
secretKeyRef:
name: rds
key: password
command: ["/bin/sh"]
args:
- -c
- |
echo "Red pod starting - should NOT have database access..."
if psql -c "SELECT version();" 2>/dev/null; then
echo "UNEXPECTED: Connected to database!"
else
echo "EXPECTED: Could not connect to database"
fi
sleep 3600
|
清理和维护
Kubernetes资源清理
1
2
3
4
5
6
7
8
9
10
11
12
|
# 删除应用部署
kubectl delete -f green-pod.yaml
kubectl delete -f red-pod.yaml
# 删除安全组策略
kubectl delete -f sg-per-pod-policy.yaml
# 删除命名空间
kubectl delete namespace networking
# 禁用Pod ENI功能
kubectl -n kube-system set env daemonset aws-node ENABLE_POD_ENI=false
|
EKS集群删除
1
2
3
4
5
6
7
|
# 首先删除托管节点组
aws eks delete-nodegroup \
--cluster-name pod-security-cluster-demo \
--nodegroup-name workers
# 删除EKS集群
aws eks delete-cluster --name pod-security-cluster-demo
|
本综合指南演示了如何在Amazon EKS中实现Pod安全组,在Pod级别提供精细的网络安全控制。