초기
초기 아이디는 'admin' 이고 비밀번호는 아래 명령어로 값을 확인 해서 비밀번호에 넣어서 로그인 해야함
kubectl get secret -n monitoring kube-prom-grafana \
-o jsonpath="{.data.admin-password}" | base64 -d && echo
비밀번호 설정 후
비밀번호 설정 후에는 내부 DB에 저장된 값으로만 로그인 하기 때문에 시크릿 값으로 로그인이 안 됨.
초기 아이디는 'admin' 이고 비밀번호는 아래 명령어로 값을 확인 해서 비밀번호에 넣어서 로그인 해야함
kubectl get secret -n monitoring kube-prom-grafana \
-o jsonpath="{.data.admin-password}" | base64 -d && echo
비밀번호 설정 후에는 내부 DB에 저장된 값으로만 로그인 하기 때문에 시크릿 값으로 로그인이 안 됨.
GHCR Private 이미지 배포 + Self-hosted Runner 기반 CI/CD 구축 과정에서 사용한 명령어들 정리해보았음
1. k3s 설치 및 상태 확인
2. kubectl 설정 (kubeconfig)
3. 노드 관리
4. Namespace 관리
5. Secret 관리 (GHCR 인증)
6. Deployment 관리
7. 파드 디버깅
8. 특정 노드에 배포 (nodeSelector)
9. GitHub Actions Self-hosted Runner
10. 자주 발생하는 에러와 해결
k3s 설치
curl -sfL https://get.k3s.io | sh -
k3s 설치 스크립트를 다운로드하여 실행. k3s 바이너리, systemd 서비스, 기본 설정 파일들을 자동으로 설치한다.
k3s 서비스 상태 확인
sudo systemctl status k3s
systemd로 등록된 k3s 서비스의 상태를 확인. active (running)이면 정상.
k3s 서비스 시작/중지/재시작
sudo systemctl start k3s # 시작
sudo systemctl stop k3s # 중지
sudo systemctl restart k3s # 재시작
sudo systemctl enable k3s # 부팅 시 자동 시작
systemd의 service 관리 명령어. k3s는 systemd 서비스로 등록되어 있다.
kubeconfig 설정
# 방법 1: 환경변수로 지정
export KUBECONFIG=/etc/rancher/k3s/k3s.yaml
# 방법 2: ~/.kube/config로 복사
mkdir -p ~/.kube
sudo cp /etc/rancher/k3s/k3s.yaml ~/.kube/config
sudo chown $USER:$USER ~/.kube/config
연결 테스트
kubectl get nodes
Kubernetes API 서버에 요청을 보내 클러스터의 노드 목록을 조회. 연결이 성공하면 노드 정보가 출력된다.

노드 목록 확인
kubectl get nodes
kubectl get nodes -o wide # 상세 정보
API 서버에 등록된 모든 노드(워커 + 컨트롤플레인)의 상태를 조회.

노드에 라벨 추가
kubectl label node <노드이름> <key>=<value>
# 예시
kubectl label node tws-b deploy-target=frontend
노드 라벨 확인
kubectl get nodes --show-labels
kubectl describe node <노드이름> | grep -A 10 Labels
각 노드에 설정된 모든 라벨을 조회.
노드 라벨 삭제
kubectl label node <노드이름> <key>-
키 이름 뒤에 '-'를 붙이면 해당 라벨이 삭제된다.
Namespace 생성
kubectl create namespace <이름>
Namespace 목록 확인
kubectl get namespaces
Namespace 삭제
kubectl delete namespace <이름>
해당 네임스페이스와 그 안의 모든 리소스가 삭제됨. 주의 필요~
GHCR 인증용 Secret 생성
kubectl create secret docker-registry ghcr-secret \
--namespace <namespace> \
--docker-server=ghcr.io \
--docker-username=<GitHub사용자명> \
--docker-password=<GitHub_PAT_토큰>
Secret 확인
kubectl get secret -n <namespace>
kubectl get secret ghcr-secret -n <namespace> -o yaml
ServiceAccount에 Secret 연결
kubectl patch serviceaccount default -n <namespace> \
-p '{"imagePullSecrets": [{"name": "ghcr-secret"}]}'
Secret 삭제
kubectl delete secret ghcr-secret -n <namespace>
Secret 업데이트 (삭제 후 재생성)
kubectl delete secret ghcr-secret -n <namespace>
kubectl create secret docker-registry ghcr-secret \
--namespace <namespace> \
--docker-server=ghcr.io \
--docker-username=<사용자명> \
--docker-password=<새토큰>
Deployment 적용
kubectl apply -f <yaml파일경로>
# 예시
kubectl apply -f backend/k8s/deployment.yaml
Deployment 목록 확인
kubectl get deployments -n <namespace>
kubectl get deployments -A # 모든 네임스페이스
Deployment 상세 정보
kubectl describe deployment <이름> -n <namespace>
Deployment 삭제
kubectl delete deployment <이름> -n <namespace>
이미지 업데이트
kubectl set image deployment/<이름> <컨테이너이름>=<이미지:태그> -n <namespace>
# 예시
kubectl set image deployment/gilldong-project-backend-app \
time-to-sleep-web=ghcr.io/hongildong/gilldong-project-backend-app:latest \
-n gilldong-project-backend
Deployment의 컨테이너 이미지를 변경하면 Rolling Update가 트리거되어 파드가 교체됨
파드 재시작
kubectl rollout restart deployment/<이름> -n <namespace>
배포 상태 확인
kubectl rollout status deployment/<이름> -n <namespace> --timeout=120s
Rolling Update가 완료될 때까지 대기. 타임아웃 내에 완료되지 않으면 에러 반환.
배포 히스토리 확인
kubectl rollout history deployment/<이름> -n <namespace>
이전 버전으로 롤백
kubectl rollout undo deployment/<이름> -n <namespace>
파드 목록 확인
kubectl get pods -n <namespace>
kubectl get pods -n <namespace> -o wide # 노드 정보 포함
kubectl get pods -A # 모든 네임스페이스
파드 상세 정보 (에러 원인 찾기)
kubectl describe pod <파드이름> -n <namespace>
파드 로그 확인
kubectl logs <파드이름> -n <namespace>
kubectl logs <파드이름> -n <namespace> --tail=100 # 마지막 100줄
kubectl logs <파드이름> -n <namespace> -f # 실시간 스트림
컨테이너의 stdout/stderr 로그를 조회.
파드 내부 접속
kubectl exec -it <파드이름> -n <namespace> -- /bin/sh
파드 내부 컨테이너에 직접 접속하여 디버깅.
파드 강제 삭제
kubectl delete pod <파드이름> -n <namespace> --force --grace-period=0
개념
기본적으로 Kubernetes 스케줄러가 파드를 어느 노드에 배치할지 결정한다. 특정 노드에 배포하려면 nodeSelector 또는 nodeAffinity를 사용.
방법 1: nodeSelector (간단)
1단계: 노드에 라벨 추가 (Control Plane에서 실행)
kubectl label node tws-b deploy-target=frontend
2단계: Deployment YAML에 nodeSelector 추가
spec:
template:
spec:
nodeSelector:
deploy-target: backend # 또는 kubernetes.io/hostname: tws-b
containers:
- name: hongildong-backend-app
...
방법 2: nodeName (가장 단순)
spec:
template:
spec:
nodeName: tws-b # 노드 이름 직접 지정
containers:
- name: hongildong-backend-app
...
방법 3: nodeAffinity (유연함)
spec:
template:
spec:
affinity:
nodeAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
nodeSelectorTerms:
- matchExpressions:
- key: kubernetes.io/hostname
operator: In
values:
- tws-b
개념
Runner 설정 명령어
./config.sh --url https://github.com/<owner>/<repo> \
--token <RUNNER_TOKEN> \
--labels k3s-deploy
Runner 서비스 관리
# Runner 설치 경로로 이동
cd ~/actions-runner
# 서비스로 등록
sudo ./svc.sh install
# 서비스 시작
sudo ./svc.sh start
# 상태 확인
sudo ./svc.sh status
# 중지
sudo ./svc.sh stop
Runner 토큰 발급 위치
1. GitHub → Repository → Settings
2. Actions → Runners → New self-hosted runner
3. 토큰과 설정 명령어가 표시됨
에러 1: connection refused - did you specify the right host or port?
export KUBECONFIG=/etc/rancher/k3s/k3s.yaml
# 또는
mkdir -p ~/.kube && sudo cp /etc/rancher/k3s/k3s.yaml ~/.kube/config
sudo chown $USER:$USER ~/.kube/config
에러 2: ErrImagePull / ImagePullBackOff + 403 Forbidden
# 1. GitHub PAT 토큰 생성 (read:packages 권한 필요)
# 2. Secret 생성
kubectl create secret docker-registry ghcr-secret \
--namespace <namespace> \
--docker-server=ghcr.io \
--docker-username=<사용자명> \
--docker-password=<PAT_토큰>
# 3. ServiceAccount 연결
kubectl patch serviceaccount default -n <namespace> \
-p '{"imagePullSecrets": [{"name": "ghcr-secret"}]}'
# 4. 파드 재시작
kubectl rollout restart deployment/<이름> -n <namespace>
에러 3: namespaces "xxx" not found
kubectl create namespace <이름>
에러 4: timed out waiting for the condition
# 파드 상태 확인
kubectl get pods -n <namespace> -o wide
# 상세 에러 확인
kubectl describe pod <파드이름> -n <namespace>
# 타임아웃 늘리기
kubectl rollout status deployment/<이름> -n <namespace> --timeout=300s
에러 5: secrets "xxx" already exists
# 삭제 후 재생성
kubectl delete secret ghcr-secret -n <namespace>
kubectl create secret docker-registry ghcr-secret ...

| Hypervisor vs Container (1) | 2024.09.05 |
|---|---|
| Hadoop: MapReduce + HDFS (0) | 2021.12.16 |
| MapReduce: Fault Tolerance, Locality, Large-Scale Indexing (0) | 2021.12.16 |
| MapReduce: Programming Model (0) | 2021.12.16 |
| MapReduce (0) | 2021.12.16 |
문제의 부분
healthcheck:
test: [ "CMD-SHELL", "kafka-broker-api-versions --bootstrap-server localhost:{포트번호} || exit 1" ]
interval: 10s
자바 프로세스를 띄우지 않고, 포트가 열려있는지만 확인하는 nc 명령어로 교체했습니다. 이 작업만으로도 CPU 스파이크의 90%가 사라집니다.
healthcheck:
test: ["CMD-SHELL", "nc -z localhost:{포트번호} || exit 1"]
interval: 10s
컴파일러 스레드가 날뛰지 않도록 제한하고, 코드 캐시를 확보했습니다.
140%까지 튀던 CPU가 3~5% 내외에서 안정적으로 유지됨.