쿠버네티스 전문가 양성과정 12주차 3일(3/8)

최수환·2023년 3월 8일
0

Kubernetes

목록 보기
53/75
post-thumbnail

Jenkins with EKS

EKS설치 및 Jenkins올리기

1 . Deploy EKS

eksctl create cluster --name myeks --region ap-northeast-2 --version 1.24 --instance-types t3.medium

eksctl utils associate-iam-oidc-provider --cluster myeks --approve

eksctl create iamserviceaccount \
  --name ebs-csi-controller-sa \
  --namespace kube-system \
  --cluster myeks \
  --attach-policy-arn arn:aws:iam::aws:policy/service-role/AmazonEBSCSIDriverPolicy \
  --approve \
  --role-only \
  --role-name AmazonEKS_EBS_CSI_DriverRole
  	
aws sts get-caller-identity --output text      
# service-account를 복사한다
# 숫자로만 이루어져있다

eksctl create addon --name aws-ebs-csi-driver --cluster myeks --service-account-role-arn arn:aws:iam::<ACCOUNT_ID>:role/AmazonEKS_EBS_CSI_DriverRole --force
# 복사한 account_ID를 붙여넣기 

2 . Deploy Jenkins on EKS with Helm

kubectl create namespace jenkins

helm repo add jenkinsci https://charts.jenkins.io
helm repo update

vi jenkins-values.yaml

controller:
  tag: "lts-jdk11"
  serviceType: LoadBalancer
  installPlugins:
  - kubernetes
  - workflow-aggregator
  - git
  - configuration-as-code
  - pipeline-stage-view
  adminPassword: "P@ssw0rd"

persistence:
  storageClass: "gp2"
# YAML파일 작성 

helm install jenkins jenkinsci/jenkins -n jenkins -f jenkins-values.yaml
# EKS에 Jenkins 생성 

브라우저에 로드밸런서주소:8080으로 Jenkins접속

id : Admin
password : P@ssw0rd 

EKS에서 Jenkins 활용

1 . jenkinsfile 작성

pipeline{
    agent{
        kubernetes{
yaml '''
apiVersion: v1
kind: Pod
spec:
  containers:
  - name: maven
    image: maven:3-openjdk-8
    command: ['sleep']
    args: ['infinity']

'''
      }
    }
    triggers {
      pollSCM '* * * * *'
      }

    stages{
        stage('checkout'){
          steps{
            container('maven'){
              git branch: 'main', url:'https://github.com/suhwan12/abc.git'
              }
            }
    	}
        stage('maven build project'){
            steps{
              container('maven'){
                sh 'mvn clean package -DskipTests=true'
                }
             }
        }
        stage('test maven project'){
            steps{
                container('maven'){
                    sh 'mvn test'
                    }
            }
        }
    }
}
  • 이후에 dockerfile을 빌드해야하지만 문제는 이전 블로그에서는 dind구조로 jenkins가 docker내에서 docker명령을 실행할 수 있었기 때문에 dockerfile을 빌드해서 이미지로 만들 수 있었지만 EKS에 올린 Jenkins는 docker명령을 설치하지 않았다.
  • 따라서 이미지를 빌드하기 위해 kaniko라는 이미지 빌더를 사용할 것이다
  • EKS에서 dind구조를 사용할 수 있긴 하지만 보안에 그리 좋지는 않다 (host가 모든 권한을 가지기 때문에)

Kaniko

1 . kaniko를 포함한 Jenkinsfile작성

kubectl create secret docker-registry regcred -n jenkins --docker-username=suhwan11 --docker-password=< 토큰 > --docker-server=https://index.docker.io/v1/
  • 자신의 docker hub계정명과 토큰, dockerhub서버 주소를 입력하여 시크릿을 생성
pipeline{
        agent{
                kubernetes{
yaml '''
apiVersion: v1
kind: Pod
spec:
  containers:
  - name: maven
    image: maven:3-openjdk-8
    command: ['sleep']
    args: ['infinity']
  - name: kaniko # kaniko파드 생성
    image: gcr.io/kaniko-project/executor:debug # latest보다 debug가 더 좋다
    command: ['sleep']
    args: ['infinity']
    volumeMounts: # 시클릿 볼륨 마운트 
    - name: registry-credentials
      mountPath: /kaniko/.docker 
  volumes: # 시크릿을 볼륨화 
  - name: registry-credentials
    secret:
      secretName: regcred # 생성한 시크릿 
      items:
      - key: .dockerconfigjson
        path: config.json


'''
        }
    }

    triggers {
          pollSCM '* * * * *'
          }

        stages{
            stage('checkout'){
              steps{
                container('maven'){
                      git branch: 'main', url:'https://github.com/suhwan12/abc.git'
                      }
                    }
            }
            stage('maven build project'){
                    steps{
                      container('maven'){
                        sh 'mvn clean package -DskipTests=true'
                        }
                     }
                    }
            stage('test maven project'){
                    steps{
                            container('maven'){
                                    sh 'mvn test'
                                    }
                    }
            }
            stage('Build & Tag docker image'){ # kaniko를 이용한 dockerfile 빌드 
                  steps{
                    container('kaniko'){ # kaniko 컨테이너(노드) 일시적으로 생성 
                      sh "executor --dockerfile=Dockerfile \ # dockerfile 지정 
                      --context=dir://${env.WORKSPACE} \ # dockerfile이 존재하는 directory경로 지정 
                      --destination=suhwan11/hello-world:latest \ 
                      --destination=suhwan11/hello-world:${env.BUILD_NUMBER}"
                      # dockerhub의 registry에 이미지 push 
            	}
          	}
        }
        }
     }

Argo CD

  • 선언적 GitOps지속적 배포
  • GitOps란?
    • Weaveworks에서 처음 사용하기 시작
    • Git에서 시작하여 Git으로 끝나는 접근 방식
    • SSOT : Single Source Of Truth, 신뢰 가능한 단일 소스
    • 모든 운영 환경은 Git에 존재
    • Git에서 모든 변경사항을 관찰 및 검증 가능
  • Git 저장소에 선언적인 쿠버네티스 오브젝트(리소스,yaml형식) 존재
  • 해당 소스를 쿠버네티스 클러스터에 배포
  • 오브젝트 소스 종류

📒 Argo CD참조

Argo CD설치

kubectl create namespace argocd
kubectl apply -n argocd -f https://raw.githubusercontent.com/argoproj/argo-cd/stable/manifests/install.yaml

kubectl patch svc argocd-server -n argocd -p '{"spec": {"type": "LoadBalancer"}}'

kubectl get svc -n argocd
# 로드밸런서 외부용 IP 확인
  • 브라우저에 외부용IP입력 후 접속

    ID : admin 
    Password : 시크릿 오브젝트에 저장되어 있다
    
    kubectl -n argocd get secret argocd-initial-admin-secret -o jsonpath="{.data.password}" | base64 -d; echo      
    # 패스워드 찾아내기 

새로운 git repo , workdir 생성 및 remote로 연결

1 . deployment

apiVersion: apps/v1
kind: Deployment
metadata: 
  namespace: default
  name: hello-world
spec:
  replicas: 2
  selector:
    matchLabels:
      app: hello-world
  template:
    metadata:
      labels:
        app: hello-world 
    spec:
      containers:
      - name: hello-world
        image: suhwan11/hello-world:21
        ports:
        - containerPort: 8080

2 . service

apiVersion: v1
kind: Service
metadata:
  namespace: default
  name: hello-world
spec:
  type: LoadBalancer
  selector:
    app: hello-world
  ports:
  - protocol: TCP
    port: 80
    targetPort: 8080
  • 두개의 yaml파일 생성 후 새로운 repo에 push

ArgoCD접속 및 새로운 APP생성

  • ArgoCD에서 NEW APP클릭 후 위의 사진처럼 이름 생성 및 Automatic선택
  • project name은 argocd에서 네임스페이스처럼 구분하기 위한 것이다

  • 위에서 새로 생성한 git 주소 등록
  • main브랜치의 루트디렉터리에 존재하므로 Path는 '.'

  • Cluster URL은 kubernetes의 default 네임스페이스에 있는 서비스이다. 즉 , 쿠버네티스의 api server이다
stage('Update Kubernetes Manifests'){
        steps{
          container('maven'){
            git branch: 'main', url:'https://github.com/suhwan12/hello-kube.git'
            sh 'sed -i "s/image:.*/image: suhwan11\\/hello-world:${BUILD_NUMBER}/g" deployment.yaml'
            sh 'git add deployment.yaml'
            sh 'git config --global user.name suhwan12'
            sh 'git config --global user.email xman0120@naver.com'
            sh 'git commit -m "Jenkins Build Number - ${BUILD_NUMBER}"'
            withCredentials([gitUsernamePassword(credentialsId: 'github-credential', gitToolName: 'Default')]) {
                sh 'git push origin main'
        }
      }	
    }	
}
  • 새로 생성한 git주소를 checkout한다
  • sed명령어로 deployment.yaml의 image를 dockerhub에 새로 추가된 이미지로 갈아끼운다
  • git에 commit을 하기 위해서 config --global로 이름과 이메일을 등록해야한다.
  • jenkinsfile을 작업하는 것은 jenkins이고 image를 빌드 후 docker hub에 올리면 최종적으로 해당 이미지를 새로운 git의 deployment.yaml에 적용 후 commit과 push를 해야한다.
    jenkins가 github에 대한 접근권한이 있어야한다.
    • 해당 git의 personal access token에서 새로운 token(classic)생성
    • jenkins의 manage credential 접속
    • global 클릭 후 add credential 클릭

      -> username : git사용자 이름
      -> password : git에서 생성한 토큰 복사
      -> id : 구분하기 위한 이름
  • github-credential이라는 이름으로 인증서 생성
    • withCredentials 구문에서 해당 인증서를 사용하여 권한을 가지고 최종적으로 git에 push한다

최종적으로 빌드를 하게 되면 dockerhub에 이미지가 생성된다

이후 deployment.yaml의 컨테이너의 이미지를 결정하는 부분을 위의 이미지로 변경한뒤 commit과 push가 된다

현재 deployment.yaml을 통해 파드를 배포한 Argo CD에서 자신에게 등록된 git을 계속 monitoring하다가 deployment.yaml이 commit되어 push된 것을 인지하고 새로운 레플리카셋을 만들어 변경된 이미지가 적용된 컨테이너가 존재하는 파드를 롤링 업데이트로 배포한다

deployment로 배포된 파드와 해당 파드를 외부로 노출시키는 로드밸런서 타입의 서비스가 존재한다. 브라우저에 로드밸런서의 외부용ip/hello-world를 입력하면 원하는 웹페이지가 뜬다

만일 git에서 버전을 바꾸는 등의 새로운 작업 후 commit과 push가 되면 변경사항이 적용된 새로운 이미지가 생성되는 작업부터 위의 과정이 자동으로 수행된다.
= Pipeline , Automation


정리

  • jenkins파일에서 eks가 작업에 맞는 이미지로 생성된 컨테이너를 정의하고 있다가 maven서버가 필요하면 maven이미지로 생성된 컨테이너를 임시적으로 생성하여 mvn clean package, test 등의 작업을 수행을 한다. 이후 컨테이너(= 노드)는 종료된다.
    이 작업을 통해 target디렉터리에 war파일이 생성된다
  • 이후 tomcat서버를 구축하고 위에서 생성한 war파일에 대해 webapps디렉터리 아래에 복사하는 작업을 하는 dockerfile을 작성한다.
  • kaniko를 통해 해당 dockerfile을 빌드하여 이미지를 생성한다
    결과적으로 war파일을 생성하고 웹에 배포하는 이미지가 생성된다
  • 이후 새로운 git에 쿠버네티스 리소스들을 생성하고(deployment , 서비스..), ArgoCD에 git을 등록해서 이 리소스들을 배포할 수 있게 한다.
  • 이때 새로운 버전의 이미지가 생성되면 ArgoCD가 모니터링하고 있는 git의 deployment.yaml의 image를 새로운 버전의 이미지로 갈아끼운다.
  • ArgoCD는 새로 갈아끼워져 commit , push된 deployment.yaml를 감지하고 , 새로운 레플리카셋을 생성하고 ,새로운 이미지가 적용된 컨테이너를 가진 파드를 롤링 업데이트를 통해 배포한다

이 모든 과정이 파이프라이닝을 통해 자동화 시킬 수 있다 .

profile
성실하게 열심히!

0개의 댓글