Coder Social home page Coder Social logo

gke_k8s_ci_cd's Introduction

GKE_K8s_CI_CD

GKE를 활용한 쿠버네티스 클러스터 구축 및 젠킨스CI / argo CD 구성해보기

  • 스크린샷 2022-03-10 오후 10 16 41
목표 및 진행 방향 정리
1. 소스코드 레포지토리에서 변동 사항이 발생
2. 웹훅 트리거 -> 젠킨스에서 소스코드 변동 사항을 반영
    -> 빌드 -> 새로운 이미지 생성 및 태깅 -> 도커허브 푸쉬 -> 별도의 manifest repo안 deployment.yaml을 새로운 이미지 태그로 업데이트
3. argo cd는 manifest repo 변동사항을 바탕으로 재배포    
  
- https://github.com/skarltjr/ci_cd_test 는 코드 레포지토리
- 별도의 k8s manifest repository 

1. GKE 클러스터 구축

  • 스크린샷 2022-03-09 오후 1 14 58
  • 돌발상황을 고려하여 정적 버전을 선택
  • default-pool에서 노드의 성능을 선택할 수 있지만 여기서는 기본 세팅을 따르기로한다.
  • 만들기 선택!

2. cloud shell setting

  • 스크린샷 2022-03-09 오후 1 25 42
  • 1번을 클릭하여 cloud shell을 열고
  • 2번 - 클러스터 연결을 눌렀을 때 나오는 명령어를 복사하여
  • 3번 - 쉘에 붙여넣으면 kubectl이 자동으로 활성화!!
  • 이용준비는 완료!

3. jenkins 설치

4. jenkins ci 파이프라인 구성

도커허브에 이미지 푸쉬하기위해 젠킨스에서 도커허브에 접근할 수 있도록 credential발급
manage credentials -> jenkins -> Global credentials -> add 
유저네임 패스워드는 도커허브 계정
id는 pipeline구성시 활요할거니까 기억하기

추가로 deployment.yaml service.yaml은 gitops repo에 존재하고 나중에 이미지가 새로 빌드되었을 때 해당 레포에 변경이 반영되야한다
그래서 깃허브 credential도 동일하게 만들어준다. 이때 비밀번호는 토큰으로

도커허브 credential & github credential을 젠킨스에 생성해둔다.
이미지 생성을 위한 도커파일을 작성하자

FROM openjdk:11-jdk AS builder
COPY gradlew .
COPY gradle gradle
COPY build.gradle .
COPY settings.gradle .
COPY src src
RUN chmod +x ./gradlew
RUN ./gradlew bootJar

FROM openjdk:11-slim
# 위에서 빌드한 jar 파일을 실행해 주기 위해 다시 JDK 11 버전을 베이스로 설정합니다.

COPY --from=builder build/libs/*.jar springboot-sample-app.jar
VOLUME /tmp
EXPOSE 8080
# builder를 통해 생성된 jar 파일을 이미지로 가져옵니다.
# 8080 포트를 공개한다고 명시합니다.

ENTRYPOINT ["java", "-jar", "/springboot-sample-app.jar"]
# 가져온 jar 파일을 실행시킵니다.
배포 스크립트. 
파이프라인을 구성해보자
pipeline{
    agent any

    environment {
        dockerHubRegistry = 'skarltjr/k8s'
        dockerHubRegistryCredential = 'docker-hub'
        githubCredential = 'github'
    }

    stages {
        stage('check out application git branch'){
            steps {
                checkout scm
            }
            post {
                failure {
                    echo 'repository checkout failure'
                }
                success {
                    echo 'repository checkout success'
                }
            }
        }
        stage('build gradle') {
            steps {
                sh  './gradlew build'
                sh 'ls -al ./build'
            }
            post {
                success {
                    echo 'gradle build success'
                }
                failure {
                    echo 'gradle build failed'
                }
            }
        }
        stage('docker image build'){
            steps{
                sh "docker build . -t ${dockerHubRegistry}:${currentBuild.number}"
                sh "docker build . -t ${dockerHubRegistry}:latest"
            }
            post {
                    failure {
                      echo 'Docker image build failure !'
                    }
                    success {
                      echo 'Docker image build success !'
                    }
            }
        }
        stage('Docker Image Push') {
            steps {
                withDockerRegistry([ credentialsId: dockerHubRegistryCredential, url: "" ]) {
                    sh "docker push ${dockerHubRegistry}:${currentBuild.number}"
                    sh "docker push ${dockerHubRegistry}:latest"

                    sleep 10 /* Wait uploading */
                }
            }
            post {
                    failure {
                      echo 'Docker Image Push failure !'
                      sh "docker rmi ${dockerHubRegistry}:${currentBuild.number}"
                      sh "docker rmi ${dockerHubRegistry}:latest"
                    }
                    success {
                      echo 'Docker image push success !'
                      sh "docker rmi ${dockerHubRegistry}:${currentBuild.number}"
                      sh "docker rmi ${dockerHubRegistry}:latest"
                    }
            }
        }
        stage('K8S Manifest Update') {
            steps {
                sh "ls"
                sh 'mkdir -p gitOpsRepo'
                dir("gitOpsRepo")
                {
                    git branch: "main",
                    credentialsId: githubCredential,
                    url: 'https://github.com/skarltjr/kube-manifests.git'
                    sh "sed -i 's/k8s:.*\$/k8s:${currentBuild.number}/' deployment.yaml"
                    sh "git add deployment.yaml"
                    sh "git commit -m '[UPDATE] k8s ${currentBuild.number} image versioning'"
//                     sshagent(credentials: ['19bdc43b-f3be-4cb9-aa1d-9896f503e3e8']) {
//                         sh "git remote set-url origin [email protected]:skarltjr/kube-manifests.git"
//                         sh "git push -u origin main"
//                     }
                    withCredentials([gitUsernamePassword(credentialsId: githubCredential,
                                     gitToolName: 'git-tool')]) {
                        sh "git remote set-url origin https://github.com/skarltjr/kube-manifests"
                        sh "git push -u origin main"
                    }
                }
            }
            post {
                    failure {
                      echo 'K8S Manifest Update failure !'
                    }
                    success {
                      echo 'K8S Manifest Update success !'
                    }
            }
        }

    }
}


참고로 여기서 헤맸다.
깜빡하고 도커 파이프라인 플러그인설치를 안함 젠킨스에.

sh "sed -i 's/k8s:.*\$/k8s:${currentBuild.number}/g' deployment.yaml" 를 통해 
deployment.yaml에 있는 image: skarltjr/k8s:{jenkins build number}중 k8s부터 뒤 모든 부분을  k8s:${currentBuild.number} 
새로 푸쉬된 이미지 태그로 갈아끼운다-> yaml수정이 된다.

sed 커맨드는 참고: https://m.blog.naver.com/hanajava/220595096628
배포 manifest를 작성하자
참고로 해당 manifest는 별도의 레포지토리 https://github.com/skarltjr/kube-manifests / 소스코드 레포랑 별개다

apiVersion: v1
kind: Service
metadata:
  labels:
    app: k8s
  name: k8s
spec:
  type: LoadBalancer
  selector:
    app: k8s
  ports:
    - port: 8080
      targetPort: 8080

---      
apiVersion: apps/v1
kind: Deployment
metadata:
  labels:
    app: k8s
  name: k8s
spec:
  replicas: 3
  selector:
    matchLabels:
      app: k8s
  strategy: {}
  template:
    metadata:
      creationTimestamp: null
      labels:
        app: k8s
    spec:
      containers:
      - name: k8s
        image: {dockerhub}/k8s:{jenkins build number}
        ports:
          - containerPort: 8080
  • 드디어 완성!
  • 이제 소스코드 레포지토리 변경사항 -> 웹훅 -> 젠킨스를 통해 빌드&이미지 새로 구성&이미지 푸쉬 -> k8s manifest repository update가 완료!
  • 스크린샷 2022-03-09 오후 11 40 58
  • 스크린샷 2022-03-10 오후 7 27 07
  • 스크린샷 2022-03-10 오후 7 25 40

5. argo CD 구성 준비

지금까지 CD를 위한 CI를 구성했다.
이제는 새로운 이미지 태그로 변경되어 manifest레포에 푸쉬되면 이를 바탕으로 argo가 재배포하도록 할 것이다.

앞에서 젠킨스는 쿠버네티스 클러스터와 직접적인 연관이 없기에 이를 별도로 관리하는것이 더 좋다고 생각했다.
argo cd의 경우 직접적으로 클러스터내에 배포를 수행해야하기에 클러스터에 띄우고자한다.

6. argo 설치

  • 스크린샷 2022-03-10 오후 10 26 13
  • kubectl create namespace argocd // 네임스페이스 생성
  • kubectl apply -n argocd -f https://raw.githubusercontent.com/argoproj/argo-cd/stable/manifests/install.yaml
  • 스크린샷 2022-03-10 오후 10 29 42
argo가 잘 띄워진걸 확인할 수 있다.
여기서 살펴볼부분은 argo server service가 현재 clusterIp로 동작
직접 접근을 위해 해당 부분을 LoadBalancer로 변경해준다.
  • kubectl patch svc argocd-server -n argocd -p '{"spec": {"type": "LoadBalancer"}}'
  • 스크린샷 2022-03-10 오후 10 31 40
  • service의 external-ip로 접근해보자 / 나는 https://35.222.118.22
  • 패스워드 확인 kubectl -n argocd get secret argocd-initial-admin-secret -o jsonpath="{.data.password}" | base64 -d
  • 초기 username = admin / password = 바로위에서 확인
  • 스크린샷 2022-03-10 오후 10 43 04

6. argo app 생성

  • 우리가 관리할 프로젝트를 구성하자
  • 먼저 private repo접근을 위해 설정
  • 스크린샷 2022-03-10 오후 10 57 11
  • 참고로 비밀번호는 마찬가지로 토큰으로
  • new app
  • 스크린샷 2022-03-10 오후 11 05 04
  • manifest repository는 private으로 루트에 바로 manifest파일들이 있다
  • 스크린샷 2022-03-10 오후 10 48 35
  • 스크린샷 2022-03-10 오후 10 51 07
  • 바로 위에서 네임스페이스를 지정했기때문에 쿠버네티스에 네임스페이스 생성 springboot-ns
  • 스크린샷 2022-03-10 오후 11 03 00

7. 확인해보자

지금 현재 클러스터에 어떤 배포도 일어나지 않았다.
이제 소스코드를 변경하면 새로운 이미지가 생겨나고 이를 적용한 deployment.yaml을 바탕으로 배포가 자동 진행되는지 확인해보자

todo

github actions 공부하고 젠킨스 대체하기

gke_k8s_ci_cd's People

Contributors

skarltjr avatar

Stargazers

Neo(hyeong-jun.Kim) avatar Jiun Kim avatar

Watchers

James Cloos avatar  avatar

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.