Terraform ile AWS EC2 uygulaması ( Infrastructure as Code nedir? #3 )

Everything as Code : Infrastructure as Code

Ali Can Kuştemur
Devops Türkiye☁️ 🐧 🐳 ☸️
11 min readAug 15, 2018

--

Merhaba arkadaşlar ,
Infrastructure as Code ( IaC ) yazı serisine devam ediyoruz.

Bu yazı da end2end olarak bir AWS EC2 altyapısını Terraform ile oluşturacağız.Aşağıdaki AWS şemasına sahip altyapıyı oluşturmaya başlayalım.

AWS EC2 Altyapı Şeması

Yukarıdaki şema da 172.31.0.0/16 CIDR’ına ait ( AWS Default VPC CIDR ) bir Virtual Private Cloud ( VPC ) bulunmaktadır. Bu VPC içerisinde 172.31.1.0/24 CIDR’ı olan bir subnet oluşturulmuş.Bir adet Route Table’a sahip ve bu 0.0.0.0/0 (Her IP için) IP için Internet Gateway’e attach olmuş durumda. Burada instance içerisindeki trafik VPC içerisinden Route Table’a sorulur ve Route Table ilgili IP setine özel bir tanımlama yok ise 0.0.0.0/0 yani bütün istekleri Internet Gateway’e yönlendirir.

Subnet ( 172.31.1.0/24) içerisinde de bir Elastic Compute Cloud ( EC2 ) instance’ı bulunmaktadır. Bu instance’in AWS tarafından EC2’lara attach olmuş default 8 GB’lık bir Elastic Block Storage ( EBS ) alanı vardır. Instance içerisinde Nginx çalışmaktadır. Bu instance’a SSH ile bağlanabilmemiz için AWS’de host’umuzun public key’ine sahip bir Key Pair oluşturulmuş.

Aşağıdaki bütün kod bloklarında kullanılan tags Name değeri AWS içerisindeki resource’un ismini tanımlar.

— Virtual Private Cloud ( VPC )

enable_dns_hostnames değeri VPC içerisinde DNS hostname atamasını aktif eder. Bu değer default olarak false ‘dur.

— Subnet

vpc_id değerinin aws_vpc.default.id olduğuna dikkat edin. Terraform’un aws_vpc resource’undaki default name’ine sahip VPC’nin id değerini alıyoruz. Böylelikle subnet yukarıda oluşturduğumuz VPC’ye bağlanmış oluyor.

cidr_block değerine verdiğimiz 172.31.1.0/24 ile subnet toplam da 254 host’a denk gelmekte.

availability_zone değeri us-east-2a (Ohio) burada altyapının oluşturacağı region’a ait bir availability zone ekliyoruz.

— Security Group

Burada yine vpc_id değeri ile Security Group’u oluşturduğumuz VPC’ye bağladığımızı unutmayın.

  • Ingress

Ingress ile dışarıdan gelen trafiğin hangi IP’lere göre kısıtlanacağını ve içerideki hangi portlara erişebileceğini belirtiyoruz.

Burada 80 portunu dışarıdan gelen tüm IP’lere ( 0.0.0.0/0) cevap verebilir şekilde ekliyoruz.

Yazının ilerleyen kısımlarında 0.0.0.0/0 değeri herkese açık olarak isimlendirilecektir.

Dışarıdan SSH yapabilmek için 22 portunu herkese açık hale getiriyoruz. Son olarak da ping yapabilmemiz için icmpfrom -1 to -1 ( tüm portlar için ) dışarıdan içeriye erişilebilir hale getiriyoruz.

  • Egress

Egress ile içeriden dışarıya erişebileceğimiz IP’leri kısıtlıyoruz. 80,443 portları ile dışarıdaki her IP’ye erişebilir hale getiriyoruz. Son olarak da ping yapabilmemiz için icmpfrom -1 to -1 ( tüm portlar için ) içeriden dışarıya erişilebilir hale getiriyoruz.

— Key Pair

Oluşturacağımız instance’a SSH ile bağlanabilmemiz için public keyimizi AWS içerisine eklememiz ve bağlandığımız instance’a bu Key Pair ile bağlanacağımızı belirtmemiz gerekiyor.

Burada Terraform’un file fonksiyonu ile yolunu belirttiğimiz herhangi bir dosyaya erişebiliriz. Public key’imizin yolunu belirtip Key Pair işlemini de tamamlıyoruz.

AMI

Instance çalıştırabilmemiz için bir işletim sistemi imajına ihtiyacımız var. AWS içerisinde bu imajlar Amazon Machine Images ( AMI ) olarak isimlendirilmektedir. Bu örnekte Ubuntu 16.04 amd64 hvm-ssd özelliklerinde bir imaj kullanacağız.

Ubuntu’nun official olarak AWS içerisinde EC2 AMI’ları listelediği bir site var.

Biz bu listeden altyapıyı oluşturacağımız region’a ait AMI idsini alıp çok hızlı bir şekilde ilerleyebiliriz. Ama bunu daha profesyonel yapmak için Terraform’un Data Source özelliğini kullanacağız.

Yukarıdaki kullanacağımız imajın adıdır. Biz her region için AMI id değişikliği ile uğraşmak yerine Terraform’a : Bu imaj adına sahip olan imajı istiyorum. diyeceğiz. Bir Inversion of Control (IoC) örneği.

artık ${data.aws_ami.ubuntu.id} çağırdığımızda bu id’ye erişip gerekli yerlerde kullanacağız ve id değerinin farklı olması bizi ilgilendirmeyecek.

— Internet Gateway

AWS’nin her region için bir default VPC oluşturduğunu biliyoruz, aynı şekilde bu VPC’ye attached edilmiş bir Internet Gateway’de oluşturur.

Biz bu kod ile yeni bir Internet Gateway oluşturmuyoruz, AWS’nin oluşturduğunu kullanıyoruz.

— Route Table

Burada VPC içerisinden çıkacak olan0.0.0.0/0 trafiğinin yani bütün trafiğin Internet’e çıkmasını sağlayacağız. Instance içerisinden bir istek gelecek VPC bunu Route Table’daki değerlere bakıp ilgili gateway’e yönlendirecek o gateway’de bize Internet erişimini sağlamış olacak.

aws_internet_gateway.default.id değeri ile yukarıda eklediğimiz resource’u Route Table’a bağlıyoruz.

— Route Table Association

Burada yapılan routing işlemlerini subnet bazlı yapabilmemizi sağlayan bir yapı bulunmakta. Biz şu anda bu tablonun oluşturduğumuz subnet’e spesifik olmasını istiyoruz.Bunun için bu oluşturduğumuz subnet ile route table’ı birbirine bağladığımız kısım Route Table Association’dır.

— Instance

Şimdi geldik ana amacımıza, artık basit olarak bir instance için gerekli tüm altyapıyı kodladık. Şimdi bu altyapıyla ilişkili bir instance tanımlayalım.

Yukarıdaki kod bloğunda oluşturduğumuz resource ve datasource’ları instance’a bağlıyoruz.(AMI, Key Pair, Security Group ve Subnet)

instance_type t2.micro 1 Core CPU ve 1 GB Memory özelliklerine sahip.

associate_public_ip_address ile instance’e erişebilmek için Public Ip atamasının yapılmasını aktifleştiriyoruz.

Kod bloğunda bulunan connection kısmında ki bilgiler SSH yapılabilmesi için gerekli olan bilgilerdir. Instance oluşturulduktan sonra bu kısım çalışmaya başlar ve SSH bağlantısını gerçekleştirdikten sonra provisioner kısmındaki scriptleri instance içerisinde execute eder.

bu script ise Nginx’in apt paketini instance’a kurar.

Şimdi bu yaptıklarımızı apply etme zamanı.

dediğimizde aşağıdakine benzer bir çıktı elde ederiz.

yes dedikten sonra,

SSH ile instance’a bağlanalım.

Google’a ping atalım.

Dış dünyadan instance’a ping atalım.

Dış dünyadan instance’a port erişim testi yapalım.

— Ingress

  • 80
  • 22
  • 443

Security Group Ingress değerlerini sadece 80,22 portları için açmıştık, burada instance’in 443 portuna bağlanamadığımızı görüyoruz.

— Egress

Burada da sadece 80,443 portlarına izin verdiğimiz için herhangi bir IP üzerindeki açık olan bu portlara bağlanabildiğimizi görüyoruz.

Son olarak Welcome Nginx sayfası ile şemadaki altyapıyı Terraform ile AWS üzerinde oluşturmuş olduk.

AWS Console’una gidip EC2’nun public ipsine gittiğimizde ise karşımıza Welcome Nginx sayfası gelmektedir.

EC2 Welcome Nginx Sayfası

Şemada ki altyapı örneğini tamamladık. Oluşturduğumuz altyapıyı AWS üzerinden terraform destroy komutu ile tamamen kaldırabiliriz.

Terraform’un - ile işaretlediği resourcelar destroy edilecek anlamına gelir ve biz 8 resource oluşturmuştuk, tamamını sistemden kaldırdı.

Bu örneğe GitHub hesabımdaki repo üzerinden erişebilirsiniz.

--

--