헬름(helm)
헬름을 통한 배포는 커스터마이즈에서 제한적이었던 주소 할당 영역과 같은 값을 대체하면서 간단하게 설치할 수 있도록 설계되어있다.
헬름은 쿠버네티스에 패키지를 손쉽게 배포할 수 있도록 패키지를 관리하는 쿠버네티스 전용 패키지 매니저이다.
- 패키지: 실행 파일, 실행 환경에 필요한 의존성 파일과 환경 정보들의 묶음
- 패키지 매니저: 다양한 목적으로 사용되지만, 가장 중요한 목적은 설치에 필요한 의존성 파일들을 관리하고 간편하게 설치할 수 있도록 도움을 줌
헬름은 차트(chart)라는 것을 사용하는데, 요구 조건별로 리소스를 편집하거나 변수를 넘겨서 처리하는 패키지내용을 처리해준다. 또한 차트는 헬름 저장소에 공개하여 여러 사용자들과 공유할 수 있다. (즉, 동료들과 동일한 환경 구성이 가능하다는 의미)
(Docker 컨테이너와 원리가 비슷한듯..)
헬름의 기본저장소는 아티팩트허브(artifacthub.io)이다.
헬름으로 배포 간편화
- 커스터마이즈(kustomize)로 배포 간편화 예제 확인: https://xggames.tistory.com/95
= helm-install.sh
최신버전 & 공식홈 제공 스크립트: https://raw.githubusercontent.com/helm/helm/main/scripts/get-helm-3
# 스크립트로 헬름설치
[root@m-k8s-ys vagrant]# ./helm-install.sh
Downloading https://get.helm.sh/helm-v3.8.1-linux-amd64.tar.gz
Verifying checksum... Done.
Preparing to install helm into /usr/local/bin
helm installed into /usr/local/bin/helm
예제에서는 차트저장소에서 metallb로 검색하여 확인한 차트를 사용한다.
# 헬름 차트 저장소 추가
[root@m-k8s-ys vagrant]# helm repo add edu https://iac-source.github.io/helm-charts
"edu" has been added to your repositories
# 등록된 차트 저장소 목록 확인
[root@m-k8s-ys vagrant]# helm repo list
NAME URL
edu https://iac-source.github.io/helm-charts
# 변경된 정보를 캐시에 업데이트(로컬에서는 차트 정보를 캐시를 한다)
[root@m-k8s-ys vagrant]# helm repo update
Hang tight while we grab the latest from your chart repositories...
...Successfully got an update from the "edu" chart repository
Update Complete. ⎈Happy Helming!⎈
# metallb 차트 설치
[root@m-k8s-ys vagrant]# 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.56.11-192.169.56.29
NAME: metallb
LAST DEPLOYED: Fri Apr 8 15:08:40 2022
NAMESPACE: metallb-system
STATUS: deployed
REVISION: 1
TEST SUITE: None
NOTES:
MetalLB load-balancer is successfully installed.
1. IP Address range 192.168.56.11-192.169.56.29 is available.
2. You can create a LoadBalancer service with following command below.
kubectl expose deployment [deployment-name] --type=LoadBalancer --name=[LoadBalancer-name] --port=[external port]
헬름에서는 가변적인 인자를 사용하기 위해서 --set ~~를 사용하였다. 가변 인자는 차트의 values.yaml파일에서 확인이 가능하며, artifacthub.io에서는 아래의 Default values를 확인하면 된다. (Default values의 내용들은 set으로 변경하지 않았을 경우에 설정되는 기본값들이다)
# 파드 및 컨피그맵 배포 확인
[root@m-k8s-ys vagrant]# kubectl get pods -n metallb-system
NAME READY STATUS RESTARTS AGE
controller-85478cc585-phzp5 1/1 Running 0 5m17s
speaker-jqhgg 1/1 Running 0 5m17s
speaker-nqhr2 1/1 Running 0 5m17s
speaker-twls4 1/1 Running 0 5m17s
speaker-vhh68 1/1 Running 0 5m17s
speaker-xrhdl 1/1 Running 0 5m17s
[root@m-k8s-ys vagrant]# kubectl get configmap -n metallb-system
NAME DATA AGE
config 1 5m25s
# 인자전달로 metallb 버전이 잘 반영되었는지 확인
[root@m-k8s-ys vagrant]# kubectl describe pods -n metallb-system | grep Image:
Image: metallb/controller:v0.8.3
Image: metallb/speaker:v0.8.3
Image: metallb/speaker:v0.8.3
Image: metallb/speaker:v0.8.3
Image: metallb/speaker:v0.8.3
Image: metallb/speaker:v0.8.3
# 디플로이먼트 및 LB 오브젝트 생성후 테스트
[root@m-k8s-ys vagrant]# kubectl create deployment echo-ip --image=sysnet4admin/echo-ip
deployment.apps/echo-ip created
[root@m-k8s-ys vagrant]# kubectl expose deployment echo-ip --type=LoadBalancer --port=80
service/echo-ip exposed
[root@m-k8s-ys vagrant]# kubectl get service echo-ip
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
echo-ip LoadBalancer 10.110.150.125 192.168.56.11 80:31859/TCP 5s
# 실습 완료후 파드 삭제
[root@m-k8s-ys vagrant]# kubectl delete service echo-ip
service "echo-ip" deleted
[root@m-k8s-ys vagrant]# kubectl delete deployment echo-ip
deployment.apps "echo-ip" deleted
젠킨스 설치 및 설정하기
이전 docker사용하기에서 정리했던 도커 컨테이너 이미지 사설 레지스트리를 가져와서 사용한다. 젠킨스는 파드에서 동작하는 애플리케이션이기때문에, PV를 마운트하지 않으면 파드를 다시 시작할 때 내부 볼륨에 저장되는 모든 데이터가 삭제되기때문이다.
- 참고: https://xggames.tistory.com/91
= nfs-exporter.sh
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.56.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용 디렉터리를 만들어주고, NFS 서비스로 생성해주는 스크립트
# nfs-exporter.sh 스크립트 실행
[root@m-k8s-ys vagrant]# ./nfs-exporter.sh jenkins
Created symlink from /etc/systemd/system/multi-user.target.wants/nfs-server.service to /usr/lib/systemd/system/nfs-server.service.
# nfs_shared 폴더가 생성(+마운트)되었는지 확인
[root@m-k8s-ys vagrant]# ls -al /nfs_shared/
합계 0
drwxr-xr-x. 3 root root 21 4월 8 15:44 .
dr-xr-xr-x. 20 root root 279 4월 8 15:44 ..
drwxr-xr-x. 2 root root 6 4월 8 15:44 jenkins
= jenkins-volume.yaml
---
apiVersion: v1
kind: PersistentVolume
metadata:
name: jenkins
spec:
capacity:
storage: 10Gi
accessModes:
- ReadWriteMany
persistentVolumeReclaimPolicy: Retain
nfs:
server: 192.168.56.10
path: /nfs_shared/jenkins
---
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: jenkins
spec:
accessModes:
- ReadWriteMany
resources:
requests:
storage: 10Gi
= jenkins-config.yaml
jenkins:
agentProtocols:
- "JNLP4-connect"
- "Ping"
authorizationStrategy:
loggedInUsersCanDoAnything:
allowAnonymousRead: false
clouds:
- kubernetes:
containerCap: 10
containerCapStr: "10"
jenkinsTunnel: "jenkins-agent:50000"
jenkinsUrl: "http://jenkins:80"
maxRequestsPerHost: 32
maxRequestsPerHostStr: "32"
name: "kubernetes"
namespace: "default"
podLabels:
- key: "jenkins/jenkins-jenkins-slave"
value: "true"
serverUrl: "https://kubernetes.default"
templates:
- containers:
- args: "^${computer.jnlpmac} ^${computer.name}"
command: ""
envVars:
- envVar:
key: "JENKINS_URL"
value: "http://192.168.56.11"
image: "jenkins/inbound-agent:4.3-4"
livenessProbe:
failureThreshold: 0
initialDelaySeconds: 0
periodSeconds: 0
successThreshold: 0
timeoutSeconds: 0
name: "jnlp"
resourceLimitCpu: "512m"
resourceLimitMemory: "512Mi"
resourceRequestCpu: "512m"
resourceRequestMemory: "512Mi"
workingDir: "/home/jenkins"
hostNetwork: false
label: "jenkins-jenkins-slave "
name: "default"
nodeUsageMode: NORMAL
podRetention: "never"
runAsGroup: "993"
runAsUser: "1000"
serviceAccount: "jenkins"
volumes:
- hostPathVolume:
hostPath: "/usr/bin/kubectl"
mountPath: "/usr/bin/kubectl"
- hostPathVolume:
hostPath: "/bin/docker"
mountPath: "/bin/docker"
- hostPathVolume:
hostPath: "/var/run/docker.sock"
mountPath: "/var/run/docker.sock"
yamlMergeStrategy: "override"
crumbIssuer:
standard:
excludeClientIPFromCrumb: true
disableRememberMe: false
disabledAdministrativeMonitors:
- "hudson.model.UpdateCenter$CoreUpdateMonitor"
- "jenkins.diagnostics.RootUrlNotSetMonitor"
- "jenkins.security.UpdateSiteWarningsMonitor"
labelAtoms:
- name: "master"
markupFormatter: "plainText"
mode: NORMAL
myViewsTabBar: "standard"
numExecutors: 0
primaryView:
all:
name: "all"
projectNamingStrategy: "standard"
quietPeriod: 5
remotingSecurity:
enabled: true
scmCheckoutRetryCount: 0
securityRealm: "legacy"
slaveAgentPort: 50000
updateCenter:
sites:
- id: "default"
url: "https://updates.jenkins.io/update-center.json"
views:
- all:
name: "all"
viewsTabBar: "standard"
security:
apiToken:
creationOfLegacyTokenEnabled: false
tokenGenerationOnCreationEnabled: false
usageStatisticsEnabled: true
sSHD:
port: -1
unclassified:
buildDiscarders:
configuredBuildDiscarders:
- "jobBuildDiscarder"
fingerprints:
fingerprintCleanupDisabled: false
storage: "file"
gitSCM:
createAccountBasedOnEmail: false
showEntireCommitSummaryInChanges: false
useExistingAccountWithSameEmail: false
junitTestResultStorage:
storage: "file"
location:
adminAddress: "address not configured yet <nobody@nowhere>"
mailer:
charset: "UTF-8"
useSsl: false
useTls: false
pollSCM:
pollingThreadCount: 10
tool:
git:
installations:
- home: "git"
name: "Default"
= jenkins-install.sh
#!/usr/bin/env bash
jkopt1="--sessionTimeout=1440"
jkopt2="--sessionEviction=86400"
jvopt1="-Duser.timezone=Asia/Seoul"
jvopt2="-Dcasc.jenkins.config=/home/vagrant/jenkins-config.yaml"
helm install jenkins edu/jenkins \
--set persistence.existingClaim=jenkins \
--set master.adminPassword=admin \
--set master.nodeSelector."kubernetes\.io/hostname"=m-k8s-ys \
--set master.tolerations[0].key=node-role.kubernetes.io/master \
--set master.tolerations[0].effect=NoSchedule \
--set master.tolerations[0].operator=Exists \
--set master.runAsUser=1000 \
--set master.runAsGroup=1000 \
--set master.tag=2.249.3-lts-centos7 \
--set master.serviceType=LoadBalancer \
--set master.servicePort=80 \
--set master.jenkinsOpts="$jkopt1 $jkopt2" \
--set master.javaOpts="$jvopt1 $jvopt2"
# 젠킨스에서 사용할 PV, PVC를 만들어준다
[root@m-k8s-ys vagrant]# kubectl apply -f jenkins-volume.yaml
persistentvolume/jenkins created
persistentvolumeclaim/jenkins created
# PV, PVC확인
[root@m-k8s-ys vagrant]# kubectl get pv
NAME CAPACITY ACCESS MODES RECLAIM POLICY STATUS CLAIM STORAGECLASS REASON AGE
jenkins 10Gi RWX Retain Bound default/jenkins 19s
[root@m-k8s-ys vagrant]# kubectl get pvc
NAME STATUS VOLUME CAPACITY ACCESS MODES STORAGECLASS AGE
jenkins Bound jenkins 10Gi RWX 21s
# 젠킨스 설치
[root@m-k8s-ys vagrant]# ./jenkins-install.sh
# ===> jenkins가 설치된 젠킨스의 릴리스 이름이다. 이후 헬름 관련 명령으로 젠킨스를 조회, 삭제, 변경 등을 수행할 때 이 이름을 사용한다.
NAME: jenkins
LAST DEPLOYED: Fri Apr 8 15:59:35 2022
# ===> default 젠킨스가 배포된 네임스페이스는 default
NAMESPACE: default
STATUS: deployed
# ===> 이후에 helm upgrade 명령어를 사용해 젠킨스의 버전을 업그레이드할 경우 1씩 증가하게 된다. (helm rollback 사용시, REVISION 번호를 지정하여 돌아갈 수 있다.)
REVISION: 1
# ===> 안내사항들.
NOTES:
# ===> 관리자 비밀번호를 얻어오기위한 명령 안내
1. Get your 'admin' user password by running:
printf $(kubectl get secret --namespace default jenkins -o jsonpath="{.data.jenkins-admin-password}" | base64 --decode);echo
# ===> 젠킨스가 구동되는 파드에 접속할 수 있도록 외부의 트래픽을 쿠버네티스의 파드로 전달하게 만드는 설정 안내
# (원래는 이 설정을 해줘야하지만, 예제는 LB를 사용할 예정)
2. Get the Jenkins URL to visit by running these commands in the same shell:
NOTE: It may take a few minutes for the LoadBalancer IP to be available.
You can watch the status of by running 'kubectl get svc --namespace default -w jenkins'
export SERVICE_IP=$(kubectl get svc --namespace default jenkins --template "{{ range (index .status.loadBalancer.ingress 0) }}{{ . }}{{ end }}")
echo http://$SERVICE_IP:80/login
# ===> 젠킨스 접속시 사용할 유저이름
3. Login with the password from step 1 and the username: admin
4. Use Jenkins Configuration as Code by specifying configScripts in your values.yaml file, see documentation: http:///configuration-as-code and examples: https://github.com/jenkinsci/configuration-as-code-plugin/tree/master/demos
For more information on running Jenkins on Kubernetes, visit:
https://cloud.google.com/solutions/jenkins-on-container-engine
For more information about Jenkins Configuration as Code, visit:
https://jenkins.io/projects/jcasc/
설치시, 사용했던 비밀번호로 로그인하자.
헬름으로 설치 초기화하는 방법
위에서는 성공하는 방법으로 가이드를 했지만, 실제로 세팅하다보면 파드가 잘 뜨지않을 수도 있고, 오타나 설정오류로 인하여 제대로 동작하지 않을 수 있다. 이때 상황에 따라 초기화를 해야할 필요도 있을때가 있는데, 위의 내용을 기준(경로 등)으로 아래의 방법으로 초기화가 가능하다.
# 젠킨스가 준비가 안되고있다..
[root@m-k8s-ys vagrant]# kubectl get deployment
NAME READY UP-TO-DATE AVAILABLE AGE
jenkins 0/1 1 0 20m
# 파드배포가 안되고있다..!!
[root@m-k8s-ys vagrant]# kubectl get pods
NAME READY STATUS RESTARTS AGE
jenkins-6ddf56cd9f-7l6ql 0/2 Init:0/1 0 21m
# 젠킨스 제거하기
[root@m-k8s-ys vagrant]# helm uninstall jenkins
release "jenkins" uninstalled
# 젠킨스 설치 시 내려받은 파일들을 삭제
[root@m-k8s-ys vagrant]# rm -rf /nfs_shared/jenkins/*
참고자료
= 서적 - 컨테이너 인프라 환경 구축을 위한 쿠버네티스/도커, 길벗 - 제 5장
'Docker & Kubernetes' 카테고리의 다른 글
쿠버네티스(Kubernetes) - 젠킨스(jenkins) 알아보기 (0) | 2022.07.16 |
---|---|
쿠버네티스(Kubernetes) - 배포 간편화 도구 비교 및 커스터마이즈(kustomize) (0) | 2022.04.08 |
쿠버네티스(Kubernetes) - k8s에서 Docker 컨테이너 사용하기 (0) | 2022.04.05 |
Docker - DockerFile (0) | 2022.04.05 |
쿠버네티스(Kubernetes) - 오브젝트 (0) | 2022.03.27 |