
들어가며
이번 글에서는 Kubernetes의 핵심 개념부터 k3s를 활용한 경량 클러스터 구축, 그리고 Jenkins와의 연동을 통한 완전한 CI/CD 파이프라인 구축까지 알아보겠습니다.
Kubernetes(쿠버네티스, k8s)는 Google에서 개발한 컨테이너 오케스트레이션 플랫폼으로, 컨테이너화된 애플리케이션의 배포, 확장, 관리를 자동화하는 시스템입니다.
자동화된 운영
수동으로 관리하기 어려운 대규모 컨테이너 환경을 자동화하여 운영 부담을 대폭 줄입니다.
확장성과 가용성
트래픽 증가에 따른 자동 스케일링과 장애 발생 시 자동 복구를 통해 안정적인 서비스를 제공합니다.
선언적 관리
원하는 상태를 선언하면 Kubernetes가 현재 상태를 지속적으로 조정하여 목표 상태를 유지합니다.
가장 작은 배포 단위로, 하나 이상의 컨테이너를 포함합니다. 같은 Pod 내의 컨테이너들은 네트워크와 스토리지를 공유합니다.
apiVersion: v1
kind: Pod
metadata:
name: my-app
spec:
containers:
- name: app-container
image: nginx:latest
ports:
- containerPort: 80
Pod의 복제본을 관리하고 롤링 업데이트를 지원합니다. 애플리케이션의 배포와 업데이트를 담당하는 핵심 리소스입니다.
apiVersion: apps/v1
kind: Deployment
metadata:
name: my-app-deployment
spec:
replicas: 3
selector:
matchLabels:
app: my-app
template:
metadata:
labels:
app: my-app
spec:
containers:
- name: app
image: my-app:v1.0
Pod들에 대한 네트워크 접근을 제공하는 추상화 계층입니다. 로드밸런싱과 서비스 디스커버리 기능을 제공합니다.
Service 타입
클러스터 외부에서 내부 서비스로의 HTTP/HTTPS 라우팅을 관리합니다. 도메인 기반 라우팅, SSL 터미네이션, 로드밸런싱 등을 제공합니다.
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: my-app-ingress
spec:
rules:
- host: myapp.example.com
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: my-app-service
port:
number: 80
비밀번호, API 키, 인증서 등 민감한 정보를 안전하게 저장하고 관리합니다.
apiVersion: v1
kind: Secret
metadata:
name: db-secret
type: Opaque
data:
username: dXNlcm5hbWU= # base64 encoded
password: cGFzc3dvcmQ= # base64 encoded
애플리케이션 설정을 코드와 분리하여 관리합니다. 환경별 설정을 유연하게 처리할 수 있습니다.
Kubernetes의 패키지 매니저로, 복잡한 애플리케이션을 템플릿화하여 쉽게 배포하고 관리할 수 있게 해줍니다.
Helm의 주요 개념
Rancher에서 개발한 경량 Kubernetes 배포판으로, 완전한 Kubernetes 기능을 제공하면서도 리소스 사용량을 최소화했습니다.
# k3s 설치 (Docker 통합 버전)
curl -sfL https://get.k3s.io | INSTALL_K3S_EXEC="--docker" sh -
# 설치 확인
sudo k3s kubectl get nodes
# kubeconfig 파일 접근 설정
mkdir -p ~/.kube
sudo cp /etc/rancher/k3s/k3s.yaml ~/.kube/config
sudo chown $(id -u):$(id -g) ~/.kube/config
export KUBECONFIG=~/.kube/config
# MSA를 위한 네임스페이스 생성
kubectl create namespace msa-apps
# Nginx Ingress Controller 설치
kubectl apply -f https://raw.githubusercontent.com/kubernetes/ingress-nginx/controller-v1.3.0/deploy/static/provider/cloud/deploy.yaml
curl https://baltocdn.com/helm/signing.asc | sudo apt-key add -
sudo apt-get install apt-transport-https --yes
echo "deb https://baltocdn.com/helm/stable/debian/ all main" | sudo tee /etc/apt/sources.list.d/helm-stable-debian.list
sudo apt-get update
sudo apt-get install helm
# Prometheus와 Grafana 설치
helm repo add prometheus-community https://prometheus-community.github.io/helm-charts
helm repo update
helm install prometheus prometheus-community/kube-prometheus-stack --namespace monitoring --create-namespace
Jenkins 관리 → 플러그인 관리 → Available plugins에서 "Kubernetes" 검색 후 설치
# kubeconfig 내용 확인
cat ~/.kube/config
Jenkins에서 Credentials 추가:
# JNLP 포트 설정
sudo vi /var/lib/jenkins/config.xml
<slaveAgentPort>50000</slaveAgentPort>
# Jenkins 재시작
sudo systemctl restart jenkins
# 방화벽 설정
sudo ufw allow 50000
sudo ufw allow 6443
sudo ufw allow 30000:32767/tcp
Jenkins 관리 → Cloud → Kubernetes 추가
주요 설정값
https://공인IP:6443msa-appskubernetes-confighttp://공인IP:8080공인IP:50000# 인증서 정보 추출 및 디코딩
sudo cat /etc/rancher/k3s/k3s.yaml | grep certificate-authority-data
echo "인증서데이터" | base64 -d
디코딩된 인증서 내용을 Kubernetes server certificate key 필드에 입력
kubectl apply -f https://raw.githubusercontent.com/kubernetes/dashboard/v2.7.0/aio/deploy/recommended.yaml
cat <<EOF | kubectl apply -f -
apiVersion: v1
kind: ServiceAccount
metadata:
name: admin-user
namespace: kubernetes-dashboard
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
name: admin-user
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
name: cluster-admin
subjects:
- kind: ServiceAccount
name: admin-user
namespace: kubernetes-dashboard
EOF
# 대시보드 서비스를 NodePort로 변경
kubectl -n kubernetes-dashboard patch svc kubernetes-dashboard -p '{"spec": {"type": "NodePort"}}'
# 노출된 포트 확인
kubectl -n kubernetes-dashboard get service kubernetes-dashboard
# 해당 포트 방화벽 허용
sudo ufw allow [포트번호]
# 접속 토큰 생성
kubectl -n kubernetes-dashboard create token admin-user
브라우저 접속: https://공인IP:포트번호
apiVersion: apps/v1
kind: Deployment
metadata:
name: sample-microservice
namespace: msa-apps
spec:
replicas: 2
selector:
matchLabels:
app: sample-microservice
template:
metadata:
labels:
app: sample-microservice
spec:
containers:
- name: sample-microservice
image: your-registry/your-app:latest
ports:
- containerPort: 8080
env:
- name: DATABASE_URL
valueFrom:
secretKeyRef:
name: db-secret
key: url
---
apiVersion: v1
kind: Service
metadata:
name: sample-microservice
namespace: msa-apps
spec:
selector:
app: sample-microservice
ports:
- port: 80
targetPort: 8080
kubectl apply -f app-deployment.yaml
kubectl get services -n msa-apps
kubectl get pods -n msa-apps
자동 복구 (Self-Healing)
컨테이너나 노드 장애 시 자동으로 복구하여 서비스 가용성을 보장합니다.
수평적 확장
트래픽 증가에 따라 Pod 수를 자동으로 조정하여 성능을 유지합니다.
롤링 업데이트
서비스 중단 없이 애플리케이션을 단계적으로 업데이트할 수 있습니다.
리소스 최적화
CPU, 메모리 리소스를 효율적으로 분배하고 관리합니다.
포터빌리티
클라우드 벤더에 종속되지 않고 어디서나 동일하게 실행됩니다.
마치며
이처럼 k3s를 활용하면 복잡한 Kubernetes 환경을 간단하게 구축할 수 있고, Helm과 같은 도구를 통해 복잡한 애플리케이션도 쉽게 배포할 수 있습니다. 모니터링 도구와 대시보드를 통해 클러스터 상태를 실시간으로 파악하고 관리할 수 있어 안정적인 운영이 가능합니다.