출처 : 컨테이너 인프라 환경 구축을 위한 쿠버네티스 / 도커 p.279
- 깃허브와 같은 저장소에 저장해둔 애플리케이션 소스 코드를 내려 받아 도커 컨테이너 이미지로 빌드
- 빌드한 컨테이너 이미지를 K8S 에서 사용할 수 있게 레지스트리에 등록
- 레지스트리에 등록된 이미지를 통해 K8S 오브젝트 생성
- 생성한 오브젝트를 서비스를 서비스 형태로 외부에 노출
- Service Mash 에 등록
- Jenkins 는 작업 내용을 Item 단위로 정의하고, 조건에 따라 자동으로 작업을 수행한다
- 컨테이너 인프라 환경에서 Jenkins 를 사용하는 주된 이유는 애플리케이션을 컨테이너로 만들고, 배포하는 과정을 자동화하기 위함이다

- Jenkins 에서 master 에게 전달할 때의 계정과 master 가 worker 에게 전달할 때의 계정이 다르므로 권한 문제가 있을 수 있다
- Jenkins 를 Pod 형태로 배포하므로, 언제든 삭제될 수 있다. 따라서 영구적으로 Data 를 저장할 Volume 을 Master Node 에 두고 사용해야 한다
- Jenkins Controller 가 명령을 내리면, Node 위에 Agent 파드가 생긴다. 해당 Pod 는 명령 수행 후 Controller 에게 보고하고, 보고 후 Agent 파드는 삭제된다
- Control : Jenkins 관리 & 작업 설정
- Agent : 작업 실행
git clone https://github.com/beomtaek/cicd_samplecode.git
- CI / CD Sample Code 를 git 에서 다운 받자
mv kustomize-install.sh metallb.yaml metallb-l2config.yaml namespace.yaml metallb/
root@master:~/lab2/cicd_samplecode/metallb# ls
kustomize-install.sh metallb-l2config.yaml metallb.yaml namespace.yaml
- 사용할 4 개의 파일을 옮기자
sh kustomize-install.sh
- Kustomize 를 설치하자
kustomize create --namespace=metallb-system --resources namespace.yaml,metallb.yaml,metallb-l2config.yaml
- kustomize create 를 이용해 kustomization.yaml 파일을 만들자. namespace 는 작업의 namespace 를 정의하며, resource 는 kustomization.yaml 를 만들기 위한 소스 파일들을 정의한다
root@master:~/lab2/cicd_samplecode/metallb# cat kustomization.yaml
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
resources:
- namespace.yaml
- metallb.yaml
- metallb-l2config.yaml
namespace: metallb-system
- 만들어진 kustomization.yaml 확인
kustomize build | kubectl apply -f -
- kustomization.yaml 을 이용해 매니페스트를 build 하고 이를 바로 배포하자. kubectl apply -f - 를 통해 빌드한 결과를 바로 전달하여 배포되게 한다
- build 는 배포를 위한 매니페스트 파일을 만들어준다
docker pull metallb/speaker:v0.8.2
docker pull metallb/controller:v0.8.2
```shell
root@master:~/lab2/cicd_samplecode/metallb# k get pod -n metallb-system -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
controller-675d6c9976-wlqx9 0/1 ImagePullBackOff 0 4m23s 172.16.182.17 worker3 <none> <none>
speaker-2qszc 1/1 Running 0 4m23s 192.168.8.101 worker1 <none> <none>
speaker-9dn7m 1/1 Running 0 4m23s 192.168.8.102 worker2 <none> <none>
speaker-qp446 1/1 Running 0 4m23s 192.168.8.100 master <none> <none>
speaker-v8nh4 1/1 Running 0 4m23s 192.168.8.103 worker3 <none> <none>
- 잘 배포되었다
- Helm 기본 저장소 ( 아티팩트허브 ) : https://artifacthub.io/
- 차트란? 다양한 요구 조건을 처리할 수 있는 패키지
- Helm 의 배포 대상은 차트 ( 패키지 ) 이다
root@master:~/lab2/cicd_samplecode# chmod +x helm-install.sh
root@master:~/lab2/cicd_samplecode# ./helm-install.sh
- 파일 권한을 설정하고, Helm 을 설치하자
curl -fsSL -o get_helm.sh https://raw.githubusercontent.com/helm/helm/main/scripts/get-helm-3
chmod 700 get_helm.sh
export DESIRED_VERSION=v3.2.1
./get_helm.sh
- Helm 을 설치하자
helm repo add edu https://iac-source.github.io/helm-charts
- helm repo 를 등록하자
root@master:~/lab2/cicd_samplecode# helm repo list
NAME URL
edu https://iac-source.github.io/helm-charts
- helm repo 가 잘 등록됬는지 확인하자
helm repo update
- 저장소를 update 해주자
helm install metallb edu/metallb \
--namespace=metallb-system \
--create-namespace \
--set controller.tag=v0.8.3 \
--set speaker.tag=v0.8.3 \
--set configmap.ipRange=192.168.8.201-192.168.8.239
- 위 명령어를 통해 MetalLB 구축이 가능하다
Kubernetes로 Jenkins를 설치하자
p. 303
docker container run -d --restart=always --name registry -p 5000:5000 registry
docker run -d -p 8888:8080 --restart always --name registry-web --link registry -e REGISTRY_URL=http://192.168.8.100:5000/v2 -e REGISTRY_NAME=192.168.8.100:5000 hyper/docker-registry-web
- 사설 저장소를 설치하고, 해당 저장소를 Web 에서 확인할 수 있게 구축하자

- 8888 Port 로 잘 접속된다
root@master:~/cicd/green# vi /etc/docker/daemon.json
{
"insecure-registries" : [ "192.168.8.100:5000" ]
}
root@master:~/cicd/green# systemctl restart docker
- 위 내용을 모든 노드에 적용하자
root@worker1:~# docker image ls | grep brian24
brian24/testweb green 59c366d9922b 10 days ago 142MB
brian24/testweb blue de012d57031e 10 days ago 142MB
- 현재 다운 받은 Image 를 확인하자
root@worker1:~# docker tag brian24/testweb:green 192.168.8.100:5000/green:1.0
root@worker1:~# docker tag brian24/testweb:blue 192.168.8.100:5000/blue:1.0
root@worker1:~# docker push 192.168.8.100:5000/blue:1.0
root@worker1:~# docker push 192.168.8.100:5000/green:1.0
- 해당 Image 를 192.168.8.100:5000/blue:1.0 과 green:1.0 으로 이름을 변경하여 사설 저장소에 Push 하자

- 잘 Push 되었다
apt install -y nfs-server
- master 에 nfs-server 를 설치하자
apt install -y nfs-common
- 모든 Node 에 nfs-common 을 설치하자
systemctl enable nfs-server --now
- nfs-server 를 실행하자
#!/usr/bin/env bash
nfsdir=/nfs_shared/$1
if [ $# -eq 0 ]; then
echo "usage: nfs-exporter.sh <name>"; exit 0
fi
if [[ ! -d $nfsdir ]]; then
mkdir -p $nfsdir
echo "$nfsdir 192.168.8.0/24(rw,sync,no_root_squash)" >> /etc/exports
if [[ $(systemctl is-enabled nfs) -eq "disabled" ]]; then
systemctl enable nfs
fi
systemctl restart nfs
fi
- 위 파일을 작성하여 실행하자. NFS 설정과 jenkins 디렉토리를 생성해준다
chmod +x nfs-exporter.sh
./nfs-exporter.sh jenkins
- 파일을 실행하자
root@master:~/lab2/cicd_samplecode# ls -nl /nfs_shared/
total 4
drwxr-xr-x 2 0 0 4096 10월 27 16:23 jenkins
- jenkins 를 위한 디렉토리가 공유 디렉토리에 생성되었다. 허나, Jenkins 에서는 1000 번으로 작업을 하므로 권한을 1000:1000 으로 변경해야 한다
chown 1000:1000 /nfs_shared/jenkins/
- 해당 디렉토리에 권한을 변경해주자
---
apiVersion: v1
kind: PersistentVolume
metadata:
name: jenkins
spec:
capacity:
storage: 5Gi
accessModes:
- ReadWriteMany
persistentVolumeReclaimPolicy: Retain
nfs:
server: 192.168.8.100
path: /nfs_shared/jenkins
---
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: jenkins
spec:
accessModes:
- ReadWriteMany
resources:
requests:
storage: 5Gi
- PV 와 PVC 배포를 위한 yaml 파일 작성
kubectl apply -f jenkins-volume.yaml
- 배포해주자
root@master:~/lab2/cicd_samplecode# k get pv,pvc
NAME CAPACITY ACCESS MODES RECLAIM POLICY STATUS CLAIM STORAGECLASS REASON AGE
persistentvolume/jenkins 5Gi RWX Retain Bound default/jenkins 38s
NAME STATUS VOLUME CAPACITY ACCESS MODES STORAGECLASS AGE
persistentvolumeclaim/jenkins Bound jenkins 5Gi RWX 38s
- 배포한 PV 와 PVC 가 Bound 되었는지 확인하자
root@master:~/lab2/cicd_samplecode# chmod +x jenkins-install.sh
root@master:~/lab2/cicd_samplecode# ./jenkins-install.sh
- 다운 받은 파일중 Jenkins 설치 파일을 실행하자
root@master:~/lab2/cicd_samplecode# k get svc
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
jenkins LoadBalancer 10.98.38.220 192.168.8.201 80:31457/TCP 4m56s
jenkins-agent ClusterIP 10.111.60.164 <none> 50000/TCP 4m56s
kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 7h7m
- 서비스에 jenkins 가 배포되었는지 확인하자
docker pull jenkins/inbound-agent:4.3-4
docker pull jenkins/jenkins:2.249.3-lts-centos7
docker pull kiwigrid/k8s-sidecar:0.1.193
- 만약, 설치가 잘 안된다면 이미지 파일이 다운로드 되지 않는 문제일 수 있다. 위 이미지 3 개를 수동으로 다운 받자
root@master:~/lab2/cicd_samplecode# k get pod
NAME READY STATUS RESTARTS AGE
jenkins-6f46869d7b-ncnsb 2/2 Running 0 11m
root@master:~/lab2/cicd_samplecode# ls /nfs_shared/jenkins/
casc_configs jobs
config.xml labels
copy_reference_file.log logs
hudson.model.UpdateCenter.xml nodeMonitors.xml
hudson.plugins.git.GitSCM.xml nodes
hudson.plugins.git.GitTool.xml org.jenkinsci.main.modules.sshd.SSHD.xml
hudson.tasks.Mailer.xml plugins
hudson.triggers.SCMTrigger.xml plugins.txt
identity.key.enc queue.xml.bak
io.jenkins.plugins.junit.storage.JunitTestResultStorageConfiguration.xml secret.key
jenkins.fingerprints.GlobalFingerprintConfiguration.xml secret.key.not-so-secret
jenkins.install.InstallUtil.lastExecVersion secrets
jenkins.install.UpgradeWizard.state updates
jenkins.model.GlobalBuildDiscarderConfiguration.xml userContent
jenkins.model.JenkinsLocationConfiguration.xml users
jenkins.security.apitoken.ApiTokenPropertyConfiguration.xml war
jenkins.telemetry.Correlator.xml workflow-libs
- 잘 설치됬는지 확인하자

- 플러그인 관리에 들어가자

- Compatible 을 누르고 다운로드를 누르자

- 재시작을 체크해주자

- Jenkins 관리의 시스템 설정에 들어가자. Jenkins URL 의 주소가 맞는지 확인하자

- Jenkins 관리에서 Node 관리에 들어가자

- Configure Clouds 에 들어가자

- Pod Templates 를 누르자

- Pod Template details 에 들어가자

- Value 에서 주소를 201 로 수정

-/usr/bin/docker 로 수정하고, apply 및 save 하자