0730

고수가 되고 싶은 감자·2026년 7월 31일

아르고. 젠킨스. 도메인 주소 이렇게 접속하게 할 수 있도록 하려면
인그레스 룰을 설정해야함
인그레스 룰 서브/ 하위 폴더에 들어가면 매니페스트들이 있음 거기서 설정해줘야함

해주면 이제 원하는 도메인으로 접속이 가능함.

깃헙에 푸시되면 젠킨스로 웹훅을 보내게 설정?
젠킨스가 실행을 할 수 있도록

우리는 iac 과정을 연습하고 있기 때문에
젠킨스에다가 파이프라인을 만드는데, 파이프라인 자체도 테라폼으로 구성가능함

values.yaml 코드를 바꾸고 푸시 -> 그럼 젠킨스가 푸시 웹훅을 받고 실행

젠킨스 파이프라인을 만들기 -> 이름 적고 파이프라인 만들기 제네럴에서 설정하기
파이프라인이 있으려면 플러그인이 설치되어야함
플러그인으로 가서 설치를 하고
설치하는건 깃헙과 제너릭웹훅트리거
설치해주삼

만드는 작업이 젠킨스를 추가할때마다 설치하려면 귀찮아짐.
파이프라인을 만들어서 xml로 다운받아서 다음에는 이 문서를 이용해서 파이프라인이 자동으로 만들어지도록 할 수 있음

CI skip? 이 동작할 수 있도록 웹 훅 트리거를 설정했다함

expressions 여기에는

이런식으로 커밋 메세지를 읽어와서 COMMIT_MSG라는 변수에 담겠다)라는 의미의 제이슨값? 표현식을 넣어주는 듯함

토큰은 지난번에 발급받았던 토큰사용?(뭐가 들어가는거지?)

CI skip에 관련된 내용..이 들어간다

커밋메세지가 정규표현식을 통과해야지만 실행되도록 하겠다 라는 거임

커밋메세지 안에 CI skip이라는 문자열이 있으면 파이프라인을 실행하지 않겠다는 의미
쓸데없이 파이프라인이 두번 돌지않도록 했음

파이프라인은 SCM으로부터 가져오겠다

그럴려면 크레덴셜이 필요함
일단은 없으니까 세이브하고
셋팅에 들어가서 추가하면 됨

크레덴셜은 깃에 접속할 수 있는 자격 증명

보니깐 깃 접속 정보인듯 깃허브 접속 정보

깃헙 계정, 토큰 정도만 입력하고 그 밑에는 커스텀인듯함

ECR 접속 정보는 필요 없음 왜 IRSA 방식을 쓸거니깐 (IAM ROLE SERVICE ACCOUTANT)

다시 만들던 파이프라인으로 가가지고 접속 정보 넣어주고 스크립트 파일은
hello/jenkinsfile_irsa
-> 이런 이름으로 젠킨스 파일 하나 추가했었음

자 이제 파이프라인을 세이브하고

파이프라인이 만들어진것을 확인이 가능함

이거는 우리가 수동으로 만든 것임.
수동으로 만들기는 이 파이프라인이 복잡해지면 힘들어질 수 있음.

그래서 이렇게 설정을 한번 해놓음 다음에 XML 변환해서 불러오게 코드로 자동화하면 편하겠져?

얻어내는 방법은 URL에다가 config.xml을 추가해주는 것임
그러면 xml 문서로 변환이 됨.

문자열을 저장하고 -> config.xml문서로
테라폼으로 젠킨스에 접속해서 파이프라인을 만들 수 있다. 라는것임

한번은 수동으로 만들어서 xml 문서를 만들고 나중가서는 자동화가 가능한 구조

우리가 원하는 쉘 스크립트만 작성해놓으면 ECR에 빌드가되면 자동으로 푸시도 되게 해놓은거라네요

파이프라인은 완성되었고 파이프 라인이 정상적으로 실행됨을 확인할 수 있음

커밋하고 푸시하면

젠킨스 파이프라인이 정상작동함 이거는 커밋메세지에 CI skip이라는 글자가 없기때문에 정상적으로 동작하는 것임

ECR 접속하면 새 이미지가 푸시된 것을 확인이 가능함.

이제 배포할 대상이 필요함

여기에서는 아르고씨디를 사용할 것임

아르고씨디 디플로이 테라폼 코드로 프로비저닝하고..
그러면 만들어지고..

아르고씨디도 동작을 할 것임

그리고 아르고씨디.도메인 주소도 인그레스 룰에서 실행되게 해주자

배포가 된 것을 확인이 가능함

이제 이 텍스트를 한번 수정햅 보겠음

개발자가 이런식으로 코드를 수정하고 깃허브에 푸시를 날리면..

젠킨스 -> 아르고씨디를 거쳐서 자동으로 배포가 완료됨

3분을 기준으로 확인하면서 새로운 버전을 가져와서 배포함

만약에 즉각적인 배포를 원한다면

이렇게 웹훅을 날려주면 됨

3분이 지나고 빌드를 거치면 배포가 된 것을 확인할 수 있음..

이제는 아르고씨디에 웹훅을 설정해주기 위한 작업들을 한번 해주겠음

05_argocd/my-values.yaml 파일에 설정을 추가해보겠음

마지막 줄에

# 깃허브에서 웹훅을 보낼때 사용할 토큰 설정
config:
	secret:
    	extra:
        	webhook.github.secret: "my-token"

지금은 토큰이 간단한 문자열이지만.. 실제로 쓸 때는 토큰을 좀 더 복잡하게 만들어줘야함

아르고씨디 들어가서 어플라이 해주게되면..

아르고 씨디에 보낼 웹훅을 하나 더 추가해주겠음
깃헙 들어가서 웹훅 추가하기

argocd URL 입력해주고.. (https 접속이 가능해야함)

토큰, 타입 다 입력해주기

시크릿이 없으면 아무나 웹훅 보낼 수 있음

이렇게 해주면 깃헙에서 아르고씨디로 웹훅을 보내줘서 바로 배포 과정에 반영될 수 있음

폴더하나 만들겠음 eks_allinone에

젠킨스 파이프라인이라는 폴더를 만들겠음

main.tf 만들어주고

아까의 xml 문서 변환하는 방식으로 xml 문서 만들기

나온 문서를 복사 해주시고

다시 vsc로 돌아가서 config.xml 파일을 만들어주자

그리고 거기에 넣어주삼

여기에는 우리가 설정했던 내용들이 다 적혀있음

이제 이걸 실행할 수 있는 테라폼 파일을 만들어보자

아까 만들어놓은 main.tf 파일에 아래와 같이 코드를 작성함

# 0. 변수 선언 (새로 추가)
variable "jenkins_api_token" {
  description = "Jenkins API 토큰"
  type        = string
  sensitive   = true # 화면이나 로그에 노출되지 않도록 암호화 처리
}

terraform {
  required_providers {
    jenkins = {
      source  = "taiidani/jenkins"
      version = "~> 0.10.0"
    }
  }
}

# 1. Jenkins 접속 정보 설정
provider "jenkins" {
  server_url = "https://jenkins.cloud-learning.site"
  username   = "admin"
  password   = var.jenkins_api_token #  변수 참조
}

# 2. 파이프라인 Job 생성
resource "jenkins_job" "msa_pipeline" {
  name     = "msa-backend-pipeline"
  template = file("${path.module}/config.xml")
}

젠킨스에서 비밀번호를 그냥 문자열로 설정할 수 있겠지만, 토큰으로 발급받아서 해보겠음

XML 문서만 잘 만들어져 있다면 테라폼으로 쉽게 자동화할 수 있음

이제 젠킨스 토큰을 발급받아보겠음

젠킨스 계정 설정에서 시큐리티에 들어가서 토큰 발급받기

이름과 만료기한 알아서 원하는 만큼 설정해주기

토큰이 생성되었음

복사해서 테라폼으로 쓰기위해 var로 넣어주자

파일새로 만들어서 terraform.tfvar를 만든다.

여기에 발급받은 토큰을 ""로 감싸서 넣어주자

그러면 이제 테라폼을 통해 내 젠킨스 계정으로 접속이 가능하고
젠킨스에서 파이프라인 생성이 가능하다.

테라폼을 실행해보겠다

젠킨스의 파이프 라인을 다 지워주고

테라폼 실행을 해준 상태

젠킨스 들어가면 정상적으로 파이프라인이 생긴것을 확인 가능함

만약에 테라폼 destroy를 누르면 어떻게 될까

눌러보겠음

파이프 라인이 삭제됨을 알 수 있다.

이로써 EKS 환경에서 젠킨슨 파이프라인도 테라폼 코드를 통해 편하게 관리가 가능함을 확인할 수 있다

다음 로컬 환경에서의 실습파일들을 관리의 용이성을 위해 테라폼 기반의 코드들로 바꿔보겠다.
실습을 위해 컨텍스트 변경을 해보겠음

클러스터들도 준비를 해주자

실습을 위해 이런식으로 폴더를 재정리해보겠다

폴더들을 만들어주고

그안에 테라폼 파일도 하나 만들어보자

# 01_cloudflared_ingress/main.tf

# main.tf
terraform {
  required_providers {
    # cloudflare 를 terraform 에서 사용할수 있도록 준비
    cloudflare = {
      source  = "cloudflare/cloudflare"
      version = "~> 4.0"
    }
    random = {
      source  = "hashicorp/random"
      version = "~> 3.0"
    }
    # terraform 으로 k8s 자원들을 provision 할수 있도록 provider 추가 
    kubernetes = {
      source  = "hashicorp/kubernetes"
      version = "~> 2.30" 
    }
    # terraform 으로 helm chart 를 직접 배포 가능하도록 하는 provider 추가
    helm = {
      source = "hashicorp/helm"
      version = "~> 2.14"
    }    
  }
}

# 클러스터 접속정보 (eks 를 바라 보도록 context 가 변경되어 있어야 한다)
provider "kubernetes" {
  config_path = "~/.kube/config"
}

# helm provider 가 동작하려면 config 파일 정보를 전달해야 한다. 
provider "helm" {
  kubernetes {
    config_path = "~/.kube/config"
  }
}

# cloudflared 에 로그인해서 아래의 변수에 전달할 정보를 가지고 와서 terraform.tfvars 파일에 미리 기입을 해둔다.
variable "cloudflare_api_token" {
  description = "Cloudflare API Token"
  type        = string
  sensitive   = true
}

variable "cloudflare_zone_id" {
  description = "Cloudflare Zone ID (도메인의 고유 ID)"
  type        = string
}

variable "cloudflare_account_id" {
  description = "Cloudflare account ID"
  type        = string
}

variable "domain_name" {
  description = "연결할 외부 도메인 (예: yourdomain.com)"
  type        = string
}

# --- Provider -----------------------------------------------------------------
provider "cloudflare" {
  # 변수에 있는 api 토큰을 사용한다 
  api_token = var.cloudflare_api_token
}

# --- 1. Tunnel Secret 생성 (터널 인증용 무작위 암호) ------------------------
resource "random_password" "tunnel_secret" {
  length  = 64
  special = false
}

# --- 2. Cloudflare Tunnel 본체 생성 -------------------------------------------
resource "cloudflare_tunnel" "vmware_tunnel" {
  account_id = var.cloudflare_account_id
  name       = "vmware-local-tunnel"
  secret     = base64encode(random_password.tunnel_secret.result)
}

# --- 3. DNS CNAME 레코드 생성 (내 도메인 -> 클라우드플레어 터널 연결) ---
resource "cloudflare_record" "vmware_dns" {
  # 1. Zone ID: 어떤 도메인(예: cloud-learning.site)에 레코드를 추가할지 지정합니다. (변수에서 가져옴)
  zone_id = var.cloudflare_zone_id

  # 2. 레코드 이름(Name): "@"는 서브도메인(www 등) 없이 '루트 도메인' 자체로 접속함을 의미합니다.
  name    = "@"

  # 3. 목적지(Content): 도메인으로 들어온 트래픽을 보낼 도착지입니다. 
  # 클라우드플레어가 발급한 "터널의 고유 ID.cfargotunnel.com" 주소로 동적 라우팅합니다.
  content = "${cloudflare_tunnel.vmware_tunnel.id}.cfargotunnel.com"

  # 4. 레코드 타입(Type): IP 주소가 아닌 도메인 이름(cfargotunnel.com)으로 연결하므로 'CNAME'을 사용합니다.
  type    = "CNAME"

  # 5. 프록시 활성화 (proxied = true): 클라우드플레어의 핵심 기능입니다. (주황색 구름 아이콘 ON)
  # 이 옵션이 true여야 무료 SSL(HTTPS) 인증서, DDoS 공격 방어, CDN 캐싱 기능이 터널에 적용됩니다.
  proxied = true
}


# --- 4. Tunnel 라우팅 규칙 (리버스 프록시 설정) -------------------------------
# 터널로 들어온 트래픽을 사설망 어디로 보낼지 결정합니다.
resource "cloudflare_tunnel_config" "vmware_config" {
  account_id = cloudflare_tunnel.vmware_tunnel.account_id
  tunnel_id  = cloudflare_tunnel.vmware_tunnel.id

  config {
    # 첫 번째 규칙: 지정한 도메인으로 들어오면 vmware 내부 서비스로 전달
    ingress_rule {
      # cloud-learning.site 로 요청이 들어오면 터널과 연결된 아래의 위치로 전달한다 
      hostname = var.domain_name
      # istio gateway 로 전달 
      service  = "http://istio-ingressgateway.istio-system.svc.cluster.local:80"
      # nginx 인그래스 컨트롤러로 전달
      # service  = "http://ingress-nginx-controller.ingress-nginx.svc.cluster.local:80" 

      # local cluster 의 svc 중에서 default 네임스페이스에 있는 nginx-svc 라는 이름의 서비스로 전달
      # service  = "http://nginx-svc.default.svc.cluster.local:80"
    }
    
    # 마지막 규칙: 매칭되는 도메인이 없으면 404 에러 반환 (필수 설정)
    ingress_rule {
      service = "http_status:404"
    }
  }
}

# cloudflared 라는 이름의 namespace 만들기
resource "kubernetes_namespace" "cloudflared_ns" {
  metadata {
    name = "cloudflared"
  }
}

resource "null_resource" "install_cloudflared_pod" {
    # 1. 터널 라우팅 규칙과 DNS 세팅, namespace 생성이 "완벽히 끝난 후"에 앤서블을 실행해라!
    depends_on = [
        cloudflare_tunnel_config.vmware_config,
        cloudflare_record.vmware_dns,
        kubernetes_namespace.cloudflared_ns
    ]

    # 2. 터널 토큰이 바뀌면 무조건 앤서블을 다시 실행해라! (항상 실행하려면 timestamp 적용)
    triggers = {
        always_run = "${timestamp()}"
    }

    # aws 에 프로비저닝을 하는것이 아닌 local 에서 직접 ansible 플레이북을 실행 
    provisioner "local-exec" {
        command = "ansible-playbook -i localhost, -c local playbook-kubectl.yml --extra-vars 'tunnel_token=${cloudflare_tunnel.vmware_tunnel.tunnel_token}'"
    }

    # terraform destroy 했을때 deploy 와 secret 도 같이 삭제 되도록 한다.
    provisioner "local-exec"{
      when = destroy
      command = <<-EOF
        kubectl delete -f deploy-cloudflared.yaml
        kubectl delete secret tunnel-credentials -n cloudflared --ignore-not-found=true
      EOF
    }
}

# 터널 토큰을 얻어내기 위한 블럭 
output "tunnel_real_token" {
  description = "Cloudflare Tunnel Token"
  value       = cloudflare_tunnel.vmware_tunnel.tunnel_token
  sensitive   = true  
}

resource "helm_release" "ingress_nginx" {
  name             = "ingress-nginx"
  # helm 저장소의 위치
  repository       = "https://kubernetes.github.io/ingress-nginx"
  # chart 의 이름
  chart            = "ingress-nginx"
  # chart 버전
  version          = "4.11.0"
  # namespace 설정 
  namespace        = "ingress-nginx"
  create_namespace = true
  # 서비스 type 을 LoadBalancer 가 아닌 ClusterIP type 으로 만들어 지도록 설정
  set {
    name  = "controller.service.type"
    value = "ClusterIP"
  }
}

그리고 step02_cloudflared_ingress에 있는 deploy-cloudflared.yaml과 playpook-kubectl.yaml, terraform.tfvars
파일을 가져온다

deploy-cloudflared.yaml에 가서 네임스페이스를 디폴트가 아닌 cloudflared로 변경해주자

playbook-kubectl.yaml로 가서 네임 스페이스 명을 바꿔주자

인그레스도 이걸로 바꿔주자

이 예제를 실행하면 클라우드 플레어 터널이 생기고 인그레스 엔진엑스가 생성된다

그다음 02_metallb_prepare 폴더를 구성해주고

# custom resource definition 삭제 
kubectl get crd -o name | grep metallb | xargs kubectl delete

# metallb namespace 삭제 
kubectl delete namespace metallb-system --ignore-not-found=true

# metallb-webhook-configuration 삭제
kubectl delete ValidatingWebhookConfiguration metallb-webhook-configuration

새로 만들어야 하기때문에 기존에 있던건 지워준다.

클리어 후에 테라폼 실행

메탈LB가 준비되고 있는 것을 확인할 수 있다

03_nfs_client_prepare 폴더도 만들어보자

헬름을 통해서 인스톨했었는데, 이걸 언인스톨하고 테라폼 기반으로 바꿔보겠다.
이런식으로 하나씩 명령어를 통해 설정하면 나중가서 관리가 어려워진다.


### 모든 node 에 nfs client 가 설치 되어 있어야 한다

>설치되어 있지않은 경우 playbook 을 실행해서 설치하기


### 기존에 설치한적이 있으면 nfs-client 초기화 한다

# 1. 헬름으로 배포한 nfs-client 삭제
helm uninstall nfs-client -n kube-system

# 2. 헬름이 혹시 지우지 않고 남겨뒀을 수 있는 StorageClass(설계도) 확인 및 삭제
kubectl delete storageclass nfs-client

길었던 명령어들을 value.yaml에 넣어서 대신할 수 있다.

다음은 Cnpg 생성하는 04_cnpg_prepare폴더를 만들어주자

main.tf 파일을 작성해보자

# main.tf 파일
terraform {
  required_providers {
    # terraform 으로 k8s 자원들을 provision 할수 있도록 provider 추가 
    kubernetes = {
      source  = "hashicorp/kubernetes"
      version = "~> 2.30" 
    }
    # terraform 으로 helm chart 를 직접 배포 가능하도록 하는 provider 추가
    helm = {
      source = "hashicorp/helm"
      version = "~> 2.14"
    }
  }
}
# 클러스터 접속정보 (eks 를 바라 보도록 context 가 변경되어 있어야 한다)
provider "kubernetes" {
  config_path = "~/.kube/config"
}

# helm provider 가 동작하려면 config 파일 정보를 전달해야 한다. 
provider "helm" {
  kubernetes {
    config_path = "~/.kube/config"
  }
}


# helm provider 가 동작할 준비가 되어 있으면 "helm_release" 를 사용할수 있다.
resource "helm_release" "cnpg" {
  name             = "cnpg"
  # helm 저장소의 위치
  repository       = "https://cloudnative-pg.github.io/charts"
  # chart 의 이름
  chart            = "cloudnative-pg"
  # chart 버전
  version          = "0.29.0"
  # namespace 설정 
  namespace        = "cnpg-system"
  create_namespace = true
}

# 이파일을 실행하면 cnpg 기반의  postgres DB 를 만들 준비가 된것이다
# DB 는 argocd_deploy 에서 생성할 예정 

이거는 이제 디비를 만들진 않고 만드는 준비만 한다. 컨트롤러만 만든다

어플라이를 하면 만들어진다

오늘은 cnpg를 띄우기위한 설정까지만 했음

이후 작업들은 내일 진행할 예정.

profile
DevOps 엔지니어 지망생

0개의 댓글