不问编程问题。
假设您有一个带有给定cidr块的VPC。可以说是10.0.0.0/16。 现在假设您已经从VPC分配了大约20个子网。这些子网既不是连续的,也不是相同的宽度。即一个给定的子网是10.0.0.7/27,而另一个子网是10.0.128.0/25,依此类推。
现在没有编写非常复杂的代码,如果我想用32个ip地址(或n个ip地址)雕刻子网,该怎么办?我怎么得到它的cidr块?
是否有任何好的aws库,terraform库或任何人遇到过这个问题并解决了它。我希望能够创建具有给定宽度的新子网。
我知道我可以使用ec2.describe-subnets和jq以及ipcalc等等。但这正是我想要避免的。
答案 0 :(得分:2)
我会使用Python netaddr package来解决您的问题:
from netaddr import *
import math
cidr = '10.0.0.0/16' # Your VPC's CIDR block
assigned = [ # Networks you've already used
'10.0.0.7/27',
'10.0.128.0/25'
]
needed_ips = 32 # Number of IP addresses needed
available = IPSet([cidr]) - IPSet(assigned)
needed_prefix = 32 - math.ceil(math.log2(needed_ips))
for net in available.iter_cidrs():
if net.prefixlen <= needed_prefix:
print(next(net.subnet(needed_prefix, 1)))
break
答案 1 :(得分:0)
如果使用 Python,boto3
包与内置的 ipaddress
模块一起足以列出指定 VPC 的给定 prefix length 未使用的候选子网。
此脚本已使用 Python 3.9 进行测试,但它应该适用于 Python ≥3.6。定义 VPC_NAME
和 REQUIRED_PREFIX_LEN
的值。它将打印所需长度的所有相关未使用子网,但您可以选择调整它以减少打印。从打印的候选中,您可以仔细挑选那些尽量减少进一步碎片化的候选。
import ipaddress
from typing import List
import boto3
# Customize these parameters:
VPC_NAME = 'my-vpc'
REQUIRED_PREFIX_LEN = 23
# Get VPC CIDR
vpcs = boto3.client('ec2').describe_vpcs(Filters=[{'Name': 'tag:Name', 'Values': [config.EC2_VPC_NAME]}])['Vpcs']
assert len(vpcs) == 1
vpc = vpcs[0]
vpc_cidr = vpc['CidrBlock']
vpc_net = ipaddress.ip_network(vpc_cidr)
assert vpc_net.prefixlen < REQUIRED_PREFIX_LEN
print(f'VPC {VPC_NAME} has CIDR {vpc_cidr}.')
def print_subnets(networks: List, description: str) -> None:
print(f"\nThe {len(networks)} {description} subnets are: {' '.join(map(str, networks))}")
# Get used subnets
used_subnets = boto3.client('ec2').get_paginator('describe_subnets').paginate(Filters=[{'Name': 'vpc-id', 'Values': [vpc['VpcId']]}]).build_full_result()['Subnets']
used_subnets = [ipaddress.ip_network(s['CidrBlock']) for s in used_subnets]
print_subnets(used_subnets, 'used')
collapsed_used_subnets = list(ipaddress.collapse_addresses(used_subnets))
print_subnets(collapsed_used_subnets, 'collapsed used')
# Get unused subnets
unused_subnets = list(vpc_net.subnets(new_prefix=REQUIRED_PREFIX_LEN))
for used_subnet in collapsed_used_subnets:
unused_subnets = [unused_subnet for unused_subnet in unused_subnets if not unused_subnet.overlaps(used_subnet)]
print_subnets(unused_subnets, 'relevant unused')
collapsed_unused_subnets = list(ipaddress.collapse_addresses(unused_subnets))
print_subnets(collapsed_unused_subnets, 'relevant collapsed unused')
这不是一个算法高效的脚本,但除非您大规模执行此操作,否则不必如此。