본문 바로가기
CICD/k8s

쿠버네티스 정리 (2) Ingress

by windy7271 2024. 3. 12.
728x90
반응형

인그레스

  • 외부에서 접속가능한 URL 사용
  • 트래픽 로드밸런싱
  • SSL 인증서 처리
  • 도메인 기반 가상 호스팅 제공

인그레스는 위와 같은 기능들에 대해 정의해둔 규칙들을 정의해둔 리소스이고,

이를 동작하기 위해서는 인그레스 컨트롤러가 필요하다.

 

이 전글에서는 Depl (pod) 와, service를 따로 해줬지만 여기서는 한 yml로 만든다.

Ingress 중간에서 라우팅을 해주는 역할이다. 

 

apiVersion: apps/v1
kind: Deployment
metadata:
  name: boseok-nginx-depl
spec:
  replicas: 2
  selector: 
    matchLabels:
      app: boseok-nginx 
  template: 
    metadata:
      labels: # nodeport와 매핑
        app: boseok-nginx 
    spec:
      containers:
      - name: nginx
        image: nginx
        ports:
        - containerPort: 80
---
apiVersion: v1
kind: Service
metadata:
  name: boseok-nginx-service
spec:
# ClustreIP는 클러스터 내부에서만 접근가능한 service를 생성
  type: ClusterIP
  ports:
  - name: http
    port: 80
    targetPort: 80
  selector:
    app: boseok-nginx

 

apply 해주면 두 개 pods와 service가 생성된다.

 

하지만 라우팅이 끊겨 있고 격리되어 있는 상태이다. 

내부포트는 80이지만 외부포트가 없다. Service에 접근이 안돼서 라우팅이안된다.

 

해결 방법은 Ingress를 두어야한다.

 

1. controller 먼저 적용해준다.

 

직접적으로 LoadBalancer를 이용하는 것보다, 하나의 Ingress Controller를 통해 여러 서비스로 트래픽을 분산할 수 있으므로, 여러 LoadBalancer 서비스를 생성하는 것보다 경제적이다.

# ingress controller 설치 명령어 
# kubectl apply -f https://raw.githubusercontent.com/kubernetes/ingress-nginx/controller-v1.8.1/deploy/static/provider/aws/deploy.yaml

 

2. ingress 적용

# ingress controller 설치 명령어 
# kubectl apply -f https://raw.githubusercontent.com/kubernetes/ingress-nginx/controller-v1.8.1/deploy/static/provider/aws/deploy.yaml

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: boseok-nginx-ingress
  annotations:
    kubernetes.io/ingress.class: nginx
    nginx.ingress.kubernetes.io/rewrite-target: /$1 # 첫번째 prefix제거

spec:
  rules:
    - http:
        paths:
          - path: /boseok/ # 모든 url 요청을 nginx-service로 라우팅 한다.
            pathType: Prefix
            backend:
              service:
                name: boseok-nginx-service
                port:
                  number: 80

 

내 이름으로 접속하면 웰컴이 뜬다.

 

나 말고 내 팀원들도 가능하다.

로드밸런스에서 ingress controller로 넘겨줘 controller에서 라우팅을 해준다.

 

 

 

https 설정하기 ingress.yml

1. cert-manager 설정

2. ClusterIssuer 생성, 

3. certification 리소스 생성

 

 

- ingress.yml

# ingress controller 설치 명령어 
# kubectl apply -f https://raw.githubusercontent.com/kubernetes/ingress-nginx/controller-v1.8.1/deploy/static/provider/aws/deploy.yaml

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: boseok-nginx-ingress
  annotations:
    kubernetes.io/ingress.class: nginx
    nginx.ingress.kubernetes.io/rewrite-target: /$1 # 첫번째 prefix제거
    cert-manager.io/cluster-issuer: letsencrypt-prod

spec:
  tls:
  - hosts:
    - "server.songboseok.shop"
    secretName: nginx-songboseok-com-tls
  rules:
    - host: server.songboseok.shop
      http:
        paths:
          - path: /boseok/ # 모든 url 요청을 nginx-service로 라우팅 한다.
            pathType: Prefix
            backend:
              service:
                name: boseok-nginx-service
                port:
                  number: 80

 

 

-ingress.cert.yml

 

Https로도 접속 할 수 있게 만들기위한 것이다.

 

# https 인증서 적용 절차
# 1. cert-manager 생성

# cert-manager 생성을 위한 cert-manager namespace 생성

# 1-1) kubectl create namespace cert-manager

# 1-2) Helm 설치
# brew update 
# brew install Helm
# 1-3) cert-manager 를 설치하기 위한 Jetstack Helm 레포지토리 추가
# helm repo add jetstack https://charts.jetstack.io

# 1-4) Helm repositroy 업데이트
# helm repo update

# 1-5) cert-manager 차트 설치
# 명령어 : helm install cert-manager jetstack/cert-manager --namespace cert-manager --version v1.5.0 --create-namespace --set installCRDs=true


# 2.ClusterIssuer 생성
apiVersion: cert-manager.io/v1
kind: ClusterIssuer
metadata:
  name: letsencrypt-prod
spec:
  acme: 
  # 인증서 서버 주소, 해당 서버에서 인증서 발행
    server: https://acme-v02.api.letsencrypt.org/directory
    # 인증서 만료 또는 갱신 필요시 알람이 갈 email 설정
    email: fa7271@naver.com 
    privateKeySecretRef:
      name: letsencrypt-prod
    solvers:
    - http01:
        ingress:
          class: nginx
---
# 3. ClussterIssue 를 사용하여 Certificate 리소스 생성하기. : Certificate 리소스 생성시에 인증서 발급
apiVersion: cert-manager.io/v1
kind: Certificate
metadata:
  name: nginx-boseok-com-tls
  namespace: default
spec:
  secretName: nginx-boseok-com-tls
  duration: 2160h # 90d
  renewBefore: 360h
  issureRef:
    name: letsencrypt-prod
    kind: ClusterIssuer
  commonName: server.songboseok.shop
  dnsNames:
  - server.songboseok.shop

 

router53에 등록하면 

5

server.songboseok.shop/boseok/ 에 들어가도 정상적으로 홈페이지가 나온다.

 


ordering System k8s 무중단 배포 

 

개발자 -> github,git action 을 해준다. eks를 통해 명령어를 실행해야하므로 git action에서 eks에 접근할 수 있게 권한을 열어 줘야한다.

 

 

시스템에 host 정보 저장해놓고 가져다 쓴다.

-> 밖으로 노출이 안된다.

kubectl create secret generic db-infos --from-literal=DB_HOST="db이름" --from-literal=DB_USERNAME=admin --from-literal=DB_PASSWORD=gksghk12!

 

 

kubectl로 조회해 보면 비밀번호가 들어가게 된다.

 

k8s secret에 db정보가 들어있어 거기서 뽑아서 바인딩 해준다.

 

 

apiVersion: apps/v1
kind: Deployment
metadata:
  name: boseok-order-backend-depl
spec:
  replicas: 2
  selector: 
    matchLabels:
      app: boseok-order-backend 
  template: 
    metadata:
      labels: # nodeport와 매핑
        app: boseok-order-backend 
    spec:
      containers:
      - name: order-backend
        image: 346903264902.dkr.ecr.ap-northeast-2.amazonaws.com/team6-order:latest
        ports:
        - containerPort: 80
        resources:
        # container가 사용할 수 있는 리소스의 최대치
          limits:
            cpu: "1"
            memory: "500Mi"
        # container가 시작될때 보장받아야 하는 최소 자원
          requests:
            cpu: "0.5"
            memory: "250Mi"
        # 런타임이라 db주입, github에 sercrets key에서 넣어주는게 아니라
        # 비밀번호를 내장 저장해서 사용한다.
        env:
        - name: DB_HOST 
          valueFrom:
            secretKeyRef: 
              name: db-infos
              key: DB_HOST
        - name: DB_USERNAME
          valueFrom:
            secretKeyRef: 
              name: db-infos
              key: DB_USERNAME
        - name: DB_PASSWORD
          valueFrom:
            secretKeyRef: 
              name: db-infos
              key: DB_PASSWORD
---
apiVersion: v1
kind: Service
metadata:
  name: boseok-order-backend-service
spec:
# ClustreIP는 클러스터 내부에서만 접근가능한 service를 생성
  type: ClusterIP
  ports:
  - name: http
    port: 80
    targetPort: 80
  selector:
    app: boseok-order-backend

 

container 안에 image 에는

docker images에 있는 repository를 넣어야한다. 근데 지금 private로 되어 있지만 

ECR을 사용해서 배포를 해보려고한다. hub에서 public으로 바꾸면 설정을 여러가지 해줘야하고, 비밀번호들이 있기 때문에 불안하고 private로 하면 설정하는데 번거롭기 때문에 더 간편하고 무조건 private인 

ECR을 사용한다.

 

ingress.yml 에는 service: name 부분만 바꿔주면 된다.

 

ingress-controller 에서 원래는 nginx-service를 바라보고 있었는데 그것을 order-backend-service로 바꿔주는것이다.

즉 A->B 로 가는것을 A-> C 로 바꿔주는 것이다.

 

1. ingress apply

kubectl apply -f ingress.yml

 

 

2. DockerHub 대신 ECR 

레포 생성해주고 DNS를 images에 넣어주면 된다.

 

권한이 있어야지 땡겨올 수 있기 때문에 권한 관련 설정을 해줘야한다.

 

name: deploy order backend-system

on:
    push:
        branches:
            - main
jobs:
    build-and-deploy:
        runs-on: ubuntu-latest
        steps:
            - name: checkout github
              uses: actions/checkout@v2
            
            - name: install kubectl
              uses: azure/setup-kubectl@v3
              with:
                version: "v1.25.9"
              id: install

            - name: configure aws
              uses: aws-actions/configure-aws-credentials@v1
              with: 
                aws-access-key-id: ${{secrets.AWS_ACCESS_KEY_ID}}
                aws-secret-access-key: ${{secrets.AWS_SECRETE_ACCESS_KEY}}
                aws-region: ap-northeast-2
            
            - name: update cluster infomation
              run: aws eks update-kubeconfig --name 6team-cluster --region ap-northeast-2
            
            - name: login to ECR
              id: login-cer
              uses: aws-actions/amazon-ecr-login@v1
              
            - name: build and push docker image to ecr
              env:
                REGISTRY: 346903264902.dkr.ecr.ap-northeast-2.amazonaws.com
                REPOSITORY: team6-order
                IMAGE_TAG: latest
              run: |
                docker build \
                -t $REGISTRY/$REPOSITORY:$IMAGE_TAG \
                -f ./ordering/Dockerfile ./ordering 
                docker push $REGISTRY/$REPOSITORY:$IMAGE_TAG

 

AWS 에 접근을 해서  클러스터에 들어가고. ECR에 로그인해서 이미지를 업로드한다.

기존에 도커 허브에 이미지를 올리는 것을 ecr로 올리는 것이다.

마지막에 run할때 도커이미지를 ecr에 올리는것이다.

 

DB도 yml에서 받아준다.

 

spring:
  security:
    user:
      name: user
      password: 1234
  datasource:
    driver-class-name: org.mariadb.jdbc.Driver
    url: jdbc:mariadb://%{DB_HOST}:3306/spring_order
    username: ${DB_USERNAME}
    password: ${DB_PASSWORD}
  jpa:
    database: mysql
    database-platform: org.hibernate.dialect.MariaDBDialect
    generate-ddl: true
    hibernate:
      ddl-auto: update
    show-sql: true
jwt:
  expiration: 30 # 30?
  secretKey: mysecret # ??? ?

 

 

돌리면 결과.

 

git action script => docker. build 할때 build.arg -> docker파일에 전달 ,

arg 통해서 전달 받고 빌드 => run을 할때 env를통해 spring에서 yml에 전달한다.

 

 

DB까지 추가하고 전달해주면 다시 add 해주면 성공한다.

 

 

내 서버에 등록을 하기 위해 

 

 

router 53에 로드밸런서에 나온 Dname을 추가해줬다

 

그럼 성공

 

다음엔 msa구조를 한 번 해보도록 하겠다.

 

 

msa 구조 ingress랑 ,certificate는 1개씩필요하고,

serve랑 service는 다 필요

반응형

댓글