নেটওয়ার্কের ছ-টা resource আর প্রতিটার কারণ, সেই একটা নির্ভরতা যেটা নিজে থেকে বোঝা যায় না, metadata-service শক্ত করা, deploy করা আর event পড়া, একটা ব্যর্থতা ও rollback, ব্রাউজারে যাচাই, আর এক কমান্ডে পুরোটা মুছে ফেলা।
পর্ব ১৯-এ template-এর ব্যাকরণ শিখেছি। এবার একটা পূর্ণ জিনিস — আর শুরু হবে নেটওয়ার্ক দিয়ে, কারণ সার্ভারটা সবচেয়ে সহজ অংশ।
একটা ইন্টারনেট থেকে পৌঁছানো যায় এমন সার্ভারের জন্য ছ-টা নেটওয়ার্ক resource লাগে। প্রথমে এটা বেশি মনে হয়, কিন্তু প্রতিটার একটা নির্দিষ্ট কাজ আছে, আর একটা বাদ দিলে কী ভাঙে সেটাও নির্দিষ্ট।
১. VPC — নিজের একটা নেটওয়ার্ক
LabVpc:
Type: AWS::EC2::VPC
Properties:
CidrBlock: 10.0.0.0/16
EnableDnsHostnames: true10.0.0.0/16 মানে ৬৫,৫৩৬টা ঠিকানা — শেখার জন্য প্রচুর। আর EnableDnsHostnames ছাড়া instance-গুলো public DNS নাম পায় না, যেটা পরে বিরক্ত করে।
২. Internet Gateway — বাইরের পথ
InternetGateway: Type: AWS::EC2::InternetGateway
কোনো property নেই। লক্ষ্য করো এটা কোনো VPC-র উল্লেখ করছে না — একটা gateway নিজে থেকে কোনো নেটওয়ার্কের অংশ নয়। আর সেটাই পরের resource-টার কারণ।
৩. Attachment — gateway-টাকে VPC-তে জোড়া
AttachGateway:
Type: AWS::EC2::VPCGatewayAttachment
Properties:
VpcId: !Ref LabVpc
InternetGatewayId: !Ref InternetGatewayএটা একটা আলাদা resource, আর এটাই পরের সেকশনের ফাঁদের উৎস। একটা gateway আর তার সংযোগ দুটো আলাদা জিনিস।
৪. Subnet — VPC-র একটা টুকরো, একটা zone-এ
PublicSubnet:
Type: AWS::EC2::Subnet
Properties:
VpcId: !Ref LabVpc
CidrBlock: 10.0.1.0/24
AvailabilityZone: !Select [0, !GetAZs '']
MapPublicIpOnLaunch: trueতিনটে জিনিস লক্ষ্য করো।
!Select [0, !GetAZs ''] — এটা "এই region-এর প্রথম availability zone"। নামটা লিখে দিলে (us-east-1a) template-টা এক region-এর হয়ে যেত — পর্ব ১৯-এর AMI-র সমস্যাটার হুবহু একই রূপ।
MapPublicIpOnLaunch: true — এটাই subnet-টাকে "public" করার অর্ধেক শর্ত। অর্ধেক, কারণ একটা public ঠিকানা থাকা আর ওই ঠিকানায় পৌঁছানো যাওয়া দুটো আলাদা জিনিস। বাকি অর্ধেকটা resource ৫ আর ৬।
৫. Route table — নিয়মের তালিকা
PublicRouteTable:
Type: AWS::EC2::RouteTable
Properties:
VpcId: !Ref LabVpcতৈরি হওয়ার সময় এটা প্রায় খালি — শুধু একটা local route থাকে (VPC-র ভেতরের যোগাযোগের জন্য), যেটা AWS নিজে যোগ করে।
৬. Route — আর এই এক লাইনটাই subnet-টাকে public করে
PublicRoute:
Type: AWS::EC2::Route
Properties:
RouteTableId: !Ref PublicRouteTable
DestinationCidrBlock: 0.0.0.0/0
GatewayId: !Ref InternetGatewayপড়ো: "যে কোনো ঠিকানায় যাওয়া ট্র্যাফিক gateway দিয়ে পাঠাও"। পর্ব ৩-এ এই লাইনটাই দেখেছি একটা তালিকায়; এখন এটা লিখছি।
আর একটা সপ্তম জিনিস, যেটা সহজে ভুলে যাওয়া যায়:
SubnetRouteTableAssociation:
Type: AWS::EC2::SubnetRouteTableAssociation
Properties:
SubnetId: !Ref PublicSubnet
RouteTableId: !Ref PublicRouteTableএকটা route table তৈরি করা মানে কোনো subnet সেটা ব্যবহার করছে, এমন নয়। এই association-টাই দুটোকে জোড়ে।
আর এটা ভুলে গেলে লক্ষণটা নিষ্ঠুর: stack সফলভাবে তৈরি হয়, সার্ভারের একটা public IP থাকে,2/2আসে — আর ব্রাউজারে কিছুই আসে না। কারণ subnet-টা ডিফল্ট route table ব্যবহার করছে, যেটায় ইন্টারনেটের পথ নেই।
পর্ব ৬-এর সেই পদ্ধতিটা এখানেই কাজে লাগে: ভেতর থেকেcurl localhostকাজ করবে, বাইরে থেকে ঝুলে থাকবে — আর সেটা firewall-এর মতো দেখতে, অথচ সমস্যাটা routing-এ। এজন্যইdescribe-route-tablesএকটা কাজের কমান্ড।
# The six (really seven) network resources, and the one line that # makes the subnet public LabVpc: AWS::EC2::VPC InternetGateway: AWS::EC2::InternetGateway # no VpcId! AttachGateway: AWS::EC2::VPCGatewayAttachment # joins them PublicSubnet: AWS::EC2::Subnet PublicRouteTable: AWS::EC2::RouteTable PublicRoute: AWS::EC2::Route # 0.0.0.0/0 -> igw SubnetRouteTableAssociation: AWS::EC2::SubnetRouteTableAssociation # Forget the last one and the stack still succeeds: the server gets a # public IP, the checks pass 2/2, and the browser gets nothing -- because # the subnet is using the default route table, which has no way out. # # Symptom: curl localhost works inside, the browser hangs outside. That # looks exactly like a firewall problem and is a routing problem. $ aws ec2 describe-route-tables
ছবিটা দেখো। প্রতিটা কালো তীর একটা !Ref — আর সেগুলো CloudFormation নিজে থেকে বুঝে নেয়। লাল ফুটকি-তীরটা আলাদা, আর সেটাই এই সেকশনের বিষয়।
সমস্যাটা ঠিক কী:
PublicRoute resource-টা দুটো জিনিসের উল্লেখ করে — route table আর internet gateway। অর্থাৎ CloudFormation জানে ওই দুটো আগে দরকার।
কিন্তু একটা route কাজ করতে gateway-টা VPC-তে যুক্ত থাকা দরকার — আর ওই যুক্ত থাকাটা একটা আলাদা resource (AttachGateway), যার উল্লেখ route-টায় নেই।
তাই CloudFormation ভাবতে পারে: "gateway তৈরি হয়েছে, route table তৈরি হয়েছে, এখন route বানাই" — আর attachment-টা তখনো তৈরি হয়নি।
ফলটা একটা অস্পষ্ট ভুল:
১৭১টি অংশের ৩৫টি দেখানো হয়েছে, ১৩৬টি বাকি