클러스터로 묶여 동작하는 애플리케이션은 설정 파일에 "나 자신의 주소" 를 적어야 하는 경우가 많다. NiFi 의 nifi.cluster.node.address, Kafka 의 advertised.listeners, 각종 클러스터 멤버 설정이 그렇다. 파드마다 값이 달라야 하므로 ConfigMap 하나를 공유해서는 채울 수 없다. 이때 쓰는 것이 Downward API 다.
fieldRef 는 파드 스펙과 상태에서, resourceFieldRef 는 컨테이너 자원 설정에서 값을 가져온다.
| 경로 | 값 |
|---|---|
metadata.name |
파드 이름. StatefulSet 이면 <sts-name>-<번호> 이고 호스트네임과 같다 |
metadata.namespace |
네임스페이스 |
metadata.uid |
파드 UID |
spec.nodeName |
파드가 뜬 노드 이름 |
spec.serviceAccountName |
서비스 어카운트 |
status.podIP |
파드 IP |
status.hostIP |
노드 IP |
apiVersion: apps/v1
kind: StatefulSet
metadata:
name: nifi
namespace: staging
spec:
serviceName: nifi-headless
replicas: 3
selector:
matchLabels:
app: nifi
template:
metadata:
labels:
app: nifi
spec:
containers:
- name: nifi
image: registry.example.com/nifi:1.28.1
env:
- name: POD_NAME
valueFrom:
fieldRef:
fieldPath: metadata.name
- name: POD_NAMESPACE
valueFrom:
fieldRef:
fieldPath: metadata.namespace
- name: POD_IP
valueFrom:
fieldRef:
fieldPath: status.podIP
- name: NODE_NAME
valueFrom:
fieldRef:
fieldPath: spec.nodeName
- name: POD_FQDN
value: "$(POD_NAME).nifi-headless.$(POD_NAMESPACE).svc.cluster.local"
$(변수) 형태의 참조는 같은 컨테이너의 env 목록에서 앞서 정의된 변수만 가리킬 수 있다. 순서를 뒤바꾸면 치환되지 않고 글자 그대로 들어간다. 중괄호 ${} 가 아니라 소괄호 $() 라는 점도 자주 틀린다.
Downward API 에는 FQDN 항목이 없다. StatefulSet 이 헤드리스 서비스와 함께 있을 때 파드의 DNS 이름은 다음 규칙으로 정해지므로, 위 예처럼 조합해 넣는다.
<파드 이름>.<헤드리스 서비스 이름>.<네임스페이스>.svc.cluster.local
헤드리스 서비스(clusterIP: None)가 없으면 파드별 DNS 이름이 만들어지지 않는다. StatefulSet 의 serviceName 이 그 서비스를 가리켜야 한다. 파드 IP 는 재시작할 때마다 바뀌므로, 클러스터 멤버 설정에는 IP 보다 이 이름을 쓰는 편이 안전하다.
Downward API 로 얻는 것은 자기 자신의 값뿐이다. 같은 StatefulSet 의 다른 replica 주소가 필요하면 방법은 둘이다.
nifi-0.nifi-headless..., nifi-1... 처럼 만들어 넣을 수 있다. 이 방법이 대부분의 경우에 맞다.파드 안에서 ip a 로 보이는 주소와 status.podIP 가 다르다면 대개 다음 중 하나다.
hostNetwork: true 인 파드다. 이 경우 파드 IP 는 노드 IP 와 같고 컨테이너 안에서는 노드의 인터페이스가 그대로 보인다.status.podIP 는 기본 인터페이스의 주소 하나이고, 추가 인터페이스는 status.podIPs 목록에도 들어가지 않는다.env 를 추가하려고 kubectl apply 했는데 다음이 나올 수 있다.
StatefulSet.apps "nifi" is invalid: spec: Forbidden: updates to statefulset spec for
fields other than 'replicas', 'ordinals', 'template', 'updateStrategy',
'persistentVolumeClaimRetentionPolicy' and 'minReadySeconds' are forbidden
template 은 고칠 수 있으므로 환경 변수 추가는 문제가 없다. 이 오류가 났다면 그 외의 필드를 함께 바꾼 것이다. serviceName, selector, volumeClaimTemplates 가 대표적이다. 이 셋을 바꾸려면 StatefulSet 을 지웠다 다시 만들어야 한다. PVC 를 살리려면 --cascade=orphan 으로 지워 파드를 남긴 뒤 다시 만든다.
kubectl delete statefulset nifi -n staging --cascade=orphan
kubectl apply -f nifi-sts.yaml
$() 치환 규칙과 ConfigMap 값 조합.