2NTECH-PROJE
Taha Yağız Güler
Posted on November 23, 2024
2NTECH
Proje Amacı
Bu projede, Go dilinde yazılmış bir web uygulamasının geliştirilmesi, Docker kullanarak konteynerleştirilmesi, GitHub Actions ile CI/CD sürecinin kurulması, Kubernetes kullanılarak uygulamanın dağıtımının otomatik hale getirilmesi ve Argo CD ile sürekli dağıtım sürecinin entegrasyonu üzerine odaklandım. MERN stack yerine, Golang ile oluşturulmuş basit bir Web App tercih ettim çünkü MERN ile daha önce çalışmadım ve bu projede odaklanılması gereken ana konunun, Docker, Kubernetes ve CI/CD süreçleri olduğunu düşündüm.
Projenin GitHub reposuna buradan ulaşabilirsiniz.
1. Go Web Uygulaması Oluşturulması
Aşağıda, basit bir Go web uygulamasının test edilmiş örneği yer almaktadır:
package main
import (
"net/http"
"net/http/httptest"
"testing"
)
func TestHomePage(t *testing.T) {
req, err := http.NewRequest("GET", "/", nil)
if err != nil {
t.Fatal(err)
}
rr := httptest.NewRecorder()
handler := http.HandlerFunc(homePage)
handler.ServeHTTP(rr, req)
if status := rr.Code; status != http.StatusOK {
t.Errorf("homePage handler returned wrong status code: got %v want %v", status, http.StatusOK)
}
}
func TestHomeEndpoint(t *testing.T) {
req, err := http.NewRequest("GET", "/home", nil)
if err != nil {
t.Fatal(err)
}
rr := httptest.NewRecorder()
handler := http.HandlerFunc(homePage)
handler.ServeHTTP(rr, req)
if status := rr.Code; status != http.StatusOK {
t.Errorf("home handler returned wrong status code: got %v want %v", status, http.StatusOK)
}
}
func TestAboutPage(t *testing.T) {
req, err := http.NewRequest("GET", "/about", nil)
if err != nil {
t.Fatal(err)
}
rr := httptest.NewRecorder()
handler := http.HandlerFunc(aboutPage)
handler.ServeHTTP(rr, req)
if status := rr.Code; status != http.StatusOK {
t.Errorf("aboutPage handler returned wrong status code: got %v want %v", status, http.StatusOK)
}
}
2. Konteynerleştirme - Dockerfile Kullanımı
Bu süreçte, çok aşamalı bir Dockerfile kullanarak uygulamanın boyutunu optimize ettim. Dockerfile aşağıdaki gibi hazırlanmıştır:
FROM golang:1.23 AS base
WORKDIR /app
COPY go.mod .
RUN go mod download
COPY . .
RUN go build -o main .
# Final stage - Distroless image.
FROM gcr.io/distroless/base
COPY --from=base /app/main .
COPY --from=base /app/static ./static
# Expose the port on which the application will run
EXPOSE 8080
# Command to run the application
CMD ["./main"]
3. Kubernetes ile Dağıtım
Uygulamanın Docker ile konteynerleştirilmesinin ardından, Kubernetes (K8s) kullanarak dağıtım yaptım. EKS (Amazon Elastic Kubernetes Service) kullanarak, Kubernetes kümesi oluşturdum ve Go uygulamasını bu kümeye dağıttım. AWS Kubernetes kümemi oluştururken eksctl kullandım ve Terraform ile yapmamın sebebi Bu kadar kısa bir işlem için buna gerek duymamam.
”Eğer Terraform ile ilgili projelerimi incelemek isterseniz, GitHub profilimi inceleyebilirsiniz.”
Aşağıda uygulamanın Kubernetes dağıtımı için kullanılan YAML dosyaları örnek olarak verilmiştir:
Deployment: Uygulamanın dağıtımını ve yönetimini sağlar.
Service: Uygulamanın dış dünyaya açılmasını sağlar.
Ingress: Trafiğin doğru yönlendirilmesini ve dış erişimi sağlar.
# deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: go-web-app
labels:
app: go-web-app
spec:
replicas: 1
selector:
matchLabels:
app: go-web-app
template:
metadata:
labels:
app: go-web-app
spec:
containers:
- name: go-web-app
image: tyguler/go-web-app:v1
ports:
- containerPort: 8080
# Ingress
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: go-web-app
annotations:
nginx.ingress.kubernetes.io/rewrite-target: /
spec:
ingressClassName: nginx
rules:
- host: go-web-app.local
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: go-web-app
port:
number: 80
# Service
apiVersion: v1
kind: Service
metadata:
name: go-web-app
labels:
app: go-web-app
spec:
ports:
- port: 80
targetPort: 8080
protocol: TCP
selector:
app: go-web-app
type: ClusterIP
4. Helm ile Uygulama Yönetimi
Kubernetes üzerinde uygulama yönetimini kolaylaştırmak için Helm kullanmaya karar verdim. Helm, Kubernetes için bir paket yöneticisidir ve uygulamanın dağıtımını, yapılandırmasını ve sürüm yönetimini basitleştirir.
Helm chart'ları, Kubernetes kaynaklarını yönetmek için şablonlar sağlar ve bu şablonlar, her ortamda uygulanabilir hale gelir.
İlk olarak bir chart oluşturdum:
helm create go-web-app-chart
Sonrasında K8s YAML dosyalarını templates klasörüne kopyaladım ve imajları yönetebilmek için bir değişken atadım:
image: tyguler/go-web-app:{{ .Values.image.tag }}
Bu sayede chart içerisindeki Values.yaml dosyasından kontrol sağladım.
helm install go-web-app ./go-web-app-chart
komutu ile tüm yapıyı test ettim ve sonrasında helm uninstall go-web-app
komutu ile kaynakları temizledim.
5. GitHub Actions ile CI/CD Süreci
Uygulamanın otomatik olarak test edilmesi, derlenmesi ve dağıtımı için GitHub Actions kullandım. GitHub Actions, her commit sonrası otomatik olarak testlerin çalıştırılmasını, Docker imajlarının oluşturulmasını ve bunların DockerHub'a yüklenmesini sağlar. Bu işlem, sürekli entegrasyon (CI) sürecinin temelini oluşturur.
GitHub Actions iş akışı şu şekildedir:
name: CI
on:
push:
branches:
- main
paths-ignore:
- 'README.md'
- 'helm/**'
jobs:
build:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Set up Go 1.23
uses: actions/setup-go@v2
with:
go-version: 1.23
- name: Build
run: go build -o go-web-app
- name: Test
run: go test ./... # ./... means all subdirectories
code_quality:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v4
- name: GolangCI-Lint
uses: golangci/golangci-lint-action@v6
with:
version: latest
push:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v1
- name: Login to DockerHub
uses: docker/login-action@v2
with:
username: ${{ secrets.DOCKER_USERNAME }}
password: ${{ secrets.DOCKER_PASSWORD }}
- name: Build and push
uses: docker/build-push-action@v6
with:
context: .
file: ./Dockerfile
push: true
tags: ${{ secrets.DOCKER_USERNAME }}/go-web-app:${{ github.run_id }}
update-newtag-in-helm-chart:
runs-on: ubuntu-latest
needs: push
steps:
- name: Checkout repository
uses: actions/checkout@v4
- name: Update Helm chart
run: |
# Update the Helm chart tag
sed -i 's/tag: .*/tag: ${GITHUB_RUN_ID}/' ./go-web-app-chart/values.yaml
6. Argo CD ile Sürekli Dağıtım Süreci
Son olarak, Argo CD ile sürekli dağıtım sürecini tamamladım. Argo CD, Kubernetes kümelerine otomatik dağıtım yaparak uygulamaların doğru sürümlerinin her zaman çalışmasını sağlar. Argo CD'nin kullanımını otomatikleştirdim ve Helm chart'ım ile sürekli dağıtımı Argo CD üzerinden gerçekleştirdim.
Argo CD'yi kurduktan sonra, Helm chart'ımı kaynak olarak ekledim ve Argo CD üzerinden manuel veya otomatik dağıtımlar gerçekleştirdim.
Sonuç
Proje, Docker, Kubernetes, Helm, GitHub Actions ve Argo CD entegrasyonuyla uygulama geliştirme ve dağıtım süreçlerini otomatikleştirmeme olanak tanıdı. Bu süreçlerin her birini doğru şekilde entegre etmek, sürekli entegrasyon (CI) ve sürekli dağıtım (CD) süreçlerini başarıyla kurmak, yazılım geliştirme ve dağıtımında verimliliği artırarak daha hızlı ve güvenilir sonuçlar elde edilmesini sağladı. Bu projede öğrendiğim en önemli şeylerden biri, farklı araç ve teknolojilerin birbirine nasıl entegre olacağını anlamak ve bu entegrasyonu etkin bir şekilde yönetebilmektir.
Karşılaşılan Zorluklar
Her ne kadar proje başarılı bir şekilde tamamlanmış olsa da, bazı zorluklarla karşılaştım. Bu zorluklar, proje sürecinin bazı noktalarında benim için önemli öğrenme fırsatları sundu.
GitHub Actions ile CI/CD sürecini kurarken, özellikle test aşamalarında karşılaştım. Docker imajlarının doğru bir şekilde yapılandırılması ve DockerHub'a yüklenmesi için gerekli olan adımlar zaman zaman hatalı gerçekleşti. Bu durumun üstesinden gelmek için GitHub Actions iş akışını dikkatlice optimize ettim ve her bir adımı doğru sırayla çalışacak şekilde yapılandırdım.
Argo CD ile sürekli dağıtım süreçlerini otomatikleştirmeye çalışırken, Helm chart'ları ile doğru entegrasyonu sağlamak bazen karmaşık hale geldi. Bu durumu çözmek için Argo CD'nin Helm entegrasyonunu dikkatlice araştırdım ve doğru Helm chart sürümünü kullandım. Ayrıca, Argo CD'nin düzgün çalışması için kaynakların doğru şekilde tanımlanması gerektiği konusunda birçok deneme yaptım.
Kubernetes kümesinin yönetimi, özellikle manuel yapılandırmalar ve değişikliklerin yapılması gerektiğinde zorlayıcı olabiliyor. EKS üzerinde kümeyi yönetmek, özellikle altyapı hataları veya ağ yapılandırma sorunları nedeniyle zaman zaman karmaşık hale geldi. Bu zorlukları aşmak için AWS belgelerine başvurdum ve en iyi uygulama örneklerini takip ettim.
Posted on November 23, 2024
Join Our Newsletter. No Spam, Only the good stuff.
Sign up to receive the latest update from our blog.
Related
November 27, 2024