service
- 여러 개의 파드에 쉽게 접근할 수 있도록 고유한 도메인 이름 부여
- 여러 개의 파드에 접근할 때, 요청을 분산하는 로드 밸런서 기능
- 클라우드 플랫폼의 로드밸런서, 노드 포트 등을 이용해 파드를 외부로 노출
service 종류
- clusterIP : 쿠버네티스 내부에서만 파드들에 접근할 때 사용
- NodePort : 파드에 접근할 수 있는 포트를 클러스터의 모든 노드에 동일하게 개방 / ${nodeIP}:${NodePort}로 외부에서 접근
- LoadBalancer : 클라우드 플랫폼에서 제공하는 로드 밸런서를 동적으로 프로비저닝 하여 파드에 연결 / 외부에서 접근할 수 있는 서비스 타입 (GCP, AWS 와 같읕 클라우드 프로바이더 제공)
clusterIP type
apiVersion: v1
kind: Service
metadata:
name: hostname-svc-clusterip
spec:
ports:
- name: web-port
port: 8080
targetPort: 80
selcetor:
app: webserver
type: ClusterIP
- spec.selector : 어떠한 라벨을 가지는 파드에 접근할 수 있게 만들 것인지 결정
- spec.ports.port : 서비스의 IP에 접근할 때 사용할 포트
- spec.ports.targetPort : 접근 대상이 된 파드들이 내부적으로 사용하고 있는 포트 (podtemplate에 정의된 containerPort와 동일한 값으로 설정 필요)
- spec.type : 서비스의 종류 (clusterIP, NodrPort, LoadBalancer)
쿠버네티스의 내부 DNS로 인해 서비스는 IP를 몰라도 서비스 이름 자체로 접근할 수 있다.
서비스의 라벨 셀렉터와 파드의 라벨이 매칭되어 연결되면 쿠버네티스는 자동으로 엔드포인트 오브젝트를 별도로 생성한다.
엔드포인트는 서비스가 가리키고 있는 도착점을 나타내며, 독립적인 쿠버네티스 리소스이기에, 서비스와 엔드포인트를 따로 만들 수 있다.
NodePort type
apiVersion: v1
kind: Service
metadata:
name: hostname-svc-nodePort
spec:
ports:
- name: web-port
port: 8080
targetPort: 80
nodePort : 31514
selcetor:
app: webserver
type: NodePort
${node ip}:${nodePort} 로 외부에서의 접근이 가능하다.
ports.nodePort를 지정하지 않는다면, 30000~32768 포트 중 랜덤으로 선택된다.
ClusterIP 기능을 포함하고 있기에, 쿠버네티스 클러스터에서 내부 IP와 DNS 이름을 사용하여 접근도 가능하다.
kubernetes api server 옵션 변경을 통해 랜덤 할당되는 노드 포트의 범위를 지정할 수 있다.
--sercie-node-port-range=30000~35000
LoadBalancer type
apiVersion: v1
kind: Service
metadata:
name: hostname-svc-lb
spec:
ports:
- name: web-port
port: 8080
targetPort: 80
selcetor:
app: webserver
type: LoadBalancer
ClusterIP와 ExternalIP가 할당되며, ExternalIP 항목의 주소와 포트로 외부에서의 접근이 가능해진다.
- LoadBalancer 타입의 서비스가 생성됨과 동시에 모든 워커 노드는 파드에 접근할 수 있는 랜덤한 노드포트 개방
- 클라우드 플랫폼에서 생성된 로드 밸런서로 요청이 들어오면 이 요청은 쿠버네티스 워커 노드 중 하나로 전달되며, 사용되는 포트는 개방된 nodePort이다.
- 워커 노드로 전달된 요청은 파드 중 하나로 전달되어 처리된다.
온프레미스 환경에서의 LoadBalancer type의 서비스 사용하기
기본적으로 LoadBalancer 타입의 서비스는 클라우드 플랫폼에서 사용되지만, MetalLB를 이용하여 LoadBalancer 타입의 서비스를 사용할 수 있다.
MetalLB :: MetalLB, bare metal load-balancer for Kubernetes
MetalLB is a load-balancer implementation for bare metal Kubernetes clusters, using standard routing protocols. Note Despite the beta status of the project / API, MetalLB is known to be stable and reliable. The project maturity page explains what that impl
metallb.io
externalTrafficPolicy
LoadBalancer 타입의 서비스가 때로는 비효율적일 때가 있는데,
NodePort로 들어온 요청이 해당 포트로 들어온 노드에 배치된 파드에서 처리 되는 것이 아닌, 랜덤한 파드로 전달되기 때문에, 불필요한 네트워크 홉이 발생하는 경우이다.
요청이 들어온 노드에 배치된 파드로 처리하면 불필요한 네트워크 홉이 발생하지 않기 때문에, 트래픽의 출발지가 변경되는 SNAT 이 발생하지 않게되며, 클라이언트의 IP 주소 또한 보존할 수 있을 것이다.
- externalTrafficPolicy : Local -> 파드가 생성된 노드에서만 파드로 접근 가능
- externalTrafficPolicy : Cluster(default) -> 클러스터의 모든 노드에서 파드로 접근 가능
다만, 파드가 실제로 받는 부하의 양은 다를 수 있기 때문에, 자원 활용률(utilzation) 측면에서 바람직하지 않을 수 있다.
ExternalName
서비스가 외부 도메인을 가리키도록 할 수 있다.
이는 쿠버네티스와 별개로 존재하는 레거시 시스템에 연동할 때 유용할 수 있다.
apiVersion: v1
kind: service
metadata:
name: externalname-svc
spec:
type: ExternalName
externalName: my.database.com
Namespace
리소스를 논리적으로 구분하기 위한 오브젝트
파드, 레플리카셋, 디플로이먼트, 서비스 등과 같은 쿠버네티스 리소스들이 묶여있는 하나의 가상 공간 또는 그룹
네임스페이스에 속하지 않는 쿠버네티스 오브젝트 또한 존재한다. (node 등)
사용자 또는 특정 용도나 목적에 따라 논리적으로 격리시킬 수 있다.
resourceQuota를 이용하여 네임스페이스의 자원 사용량을 제한하거나, admission controller를 이용하여 특정 네임스페이스에 생성되는 파드에 사이드카 컨테이너를 붙일 수도 있으며, 다양하게 활용이 가능하다.
default namespace
쿠버네티스를 설치하면 자동으로 사용하도록 설정되는 namespace, namespace를 명시하지 않은 리소스는 default namespace를 사용한다.
FQDN 이용하여 서비스에 접근하기
일반적으로 다음과 같은 형식이다.
<서비스 이름>.<네임스페이스 이름>.svc.cluster.local (cluster.local 클러스터 도메인)
configmap, secret - 환경변수 및 설정 값 분리하기
다음과 같이 파드 템플릿에서 환경변수를 직접 설정할 수도 있다.
...
spec:
containers:
- name: nginx
env:
- name: LOG_LEVEL
value: INFO
...
위의 방식도 나쁘진 않지만, 상황에 따라서 변수의 값만 다른 동일한 여러개의 YAML이 존재해야하는 경우, 두 버전의 YAML 파일을 작성해야 하는 번거로움이 있을 수 있다.
쿠버네티스에서는 이런 문제를 해결하기 위한 설정값들을 분리할 수 있는 configmap 이나 secret 오브젝트를 제공한다.
configmap은 설정값, secret에는 노출되지 않아야 할 민감정보를 저장한다.
configmap
# configmap 생성
kubectl create configmap test-configmap --from-literal LOG_LEVEL=DEBUG
configmap을 pod에서 사용하는 법
- configmap의 값을 컨테이너의 환경 변수로 사용
- configmap의 값을 파드 내부의 파일로 마운트하여 사용
컨피그맵의 데이터를 컨테이너의 환경 변수로 가져오기
apiVersion: v1
kind: pod
metadata:
name: container-env-example
spec:
containers:
- name: my-container
image: busybox
args: ['tail', '-f', '/dev/null']
envFrom:
# 여러 개의 키-값 쌍이 존재하더라도 모두 환경 변수로 가져옴
- configMapRef:
name: log-level-configmap
# 여러 키-값 쌍이 들어 있는 configmap에서 특정 데이터를 선택하여 환경 변수로 가져옴
env:
- name: ENV_KEYNAME
valueFrom:
configMapKeyRef:
# 참조할 configmap의 이름
name: log-level-configmap
# 가져올 데이터 값의 키
key: LOG_LEVEL
컨피그맵의 내용을 파일로 파드 내부에 마운트하기
apiVersion: v1
kind: pod
metadata:
name: confgmap-volume-pod
spec:
containers:
- name: my-container
image: busybox
args: ["tail", "-f", "/dev/null"]
volumeMounts:
# 컨피그맵의 볼륨 이름
- name: configmap-volume
# 컨피그맵의 데이터가 위치할 경로
mountPath: /etc/config
volumes:
# 컨피그맵 볼륨 이름
- name: configmap-volume
configMap:
# 키-값 쌍을 가져올 컨피그맵 이름
name: start-k8s
- name: configmap-volume
name: start-k8s2
# 컨피그맵에서 가져올 키-값 목록 나열
items:
# k8s라는 키에 대응하는 값 가져오기
- key: k8s
최조 ㅇ파일 이름은 k8s_fullname이 된다.
path: k8s_fullname
파일로부터 컨피그맵 생성하기
kubectl create configmap <configmap 이름> --from-file <파일 이름> ...
시크릿 (secret)
kubectl create secret generic \
my-password --from-literal password=1a2a3a
# 파일로부터 값 읽어와서 생성
kubectl create secret generic \
our-password --from-file pw1 --from-file pw2
시크릿의 데이터를 환경변수로 가져오기
apiVersioin: v1
kind: pod
metadata:
name: secret-env-example
spec:
containers:
- name: my-container
image: busybox
args: ['tail', '-f', '/dev/null']
envFrom:
- secretRef:
name: my-password
...
env:
- name: YOUR_PASSWORD
valueFrom:
secretKeyRef:
name: our-password
key: pw2
시크릿의 데이터를 파드 내부로 볼륨 마운트
...
volumeMounts:
- name: secret-volume
mountpath: /etc/secret
volumes:
- name: secret-volume
secret:
secretName: our-password
volumes:
- name: secret-volume
secret:
secretName: our-password
items:
- key: pw1
path: password1
시크릿을 생성할 때 YAML 파일에 base64 인코딩한 값을 입력했더라도 시크릿을 파드의 환경변수나 볼륨 파일로서 가져오면 base64로 디코딩된 원래의 값을 사용하게 된다.
컨피그맵과 시크릿 리소스 손쉽게 배포하기
# kubectl --dry-run 명령어에서 출력되는 YAML 파일로 저장
kubectl create secret tls my-tls-secret --cert cert.crt --key cert.key --dry-run -o yaml
# 데이터가 매우 길고, YAML 파일과 데이터가 분리되지 않아, 관리하기 힘든 경우 kustomize 사용
# kustomization.yaml
secretGenerator:
- name: kustomize-secret
type: kubernetes.io/tls
files:
- tls.crt=cert.crt
- tls.key-cert.key
# 적용 - cert.crt, cert.key, kustomization.yaml이 존재하는 위치에서 명령어
kubectl apply -k ./
# configmap
configMapGenerator:
- name: kustomize-configmap
files:
- tls.crt=cert.crt
- tls.key=cert.key
kustomize로부터 생성된 컨피그맵이나 시크릿의 이름 뒤에는 해시값이 자동으로 추가된다.
혹은 kubectl create 명령어에 --apend-hash 옵션을 추가하여 해시값을 추가할 수 있다.
환경 변수로 파드 내부에 설정값을 제공하는 방법
-> 컨피그맵이나 시크릿의 값을 변경해도 자동으로 재설정되지 않음 / deployment의 pod 재생성해야 함
볼륨 파일로 파드 내부에 마운트 하는 방법
-> 컨피그맵이나 시크릿을 변경하면 파일의 내용이 갱신된다.
다만, 파드 내부에 마운트된 설정 파일이 변경됐다고 해서 파드에서 실행 중인 애플리케이션의 설정이 자동으로 변경되지는 않는다. -> 별도의 로직 필요
변경된 파일을 다시 읽도록 컨테이너 프로세스에 별도의 시그널(SIGHUP)을 보내는 사이드카 컨테이너를 파드에 포함
kubernetes API 통해 컨피그맵, 시크릿의 변경 알림(WATCH)를 받은 뒤, 자동으로 리로드하는 로직 등
'Kubernetes' 카테고리의 다른 글
kubernetes ingress (0) | 2025.04.20 |
---|---|
사이드카 활용 패턴과 namespace 활용 전략 (0) | 2025.04.13 |
쿠버네티스 설치 및 기본 개념 (pod, replicaset, deployment) (0) | 2025.04.05 |
도커 컴포즈 (설치 및 개념) (0) | 2025.03.29 |
Docker Engine 핵심 정리 (0) | 2025.03.16 |