Accessing pod metadata / other resources from application
Pod에 대한 정보 (pod의 이름,..) 등은 pod를 생성할 때 사용하는 manifest를 통해 미리 알 수 있지만, pod가 생성된 이후 알 수 있는 정보들이 있다. (Pod의 IP, host node의 이름, ReplicaSet으로 생성된 pod의 이름..) 등
실행 시점까지 알려지지 않은 데이터가 pod내에 배포된 application단에서 필요한 경우, Pod의 metadata에 접근해야한다.
이때 사용 가능한 방법이
pod 자체의 metadata를 해당 pod내에서 실행 중인 프로세스에 노출할 수 있는 metadata 종류
metadata.name
metadata.namespace
metadata.uid
metadata.labels
metadata.annotations
Resource에 대한 정보
note)
hugepages
: node 커널이 기본 페이지 크기보다 훨씬 큰 메모리 블록을 할당하는 리눅스 관련 기능ephemeral-storage
: 임시 저장소 라는 뜻으로, 컨테이너 환경에서는 volume을 mount하지 않는 이상 data가 휘발성이 되고, 그 휘발성 data를 위한 저장 공간을 의미한다. 이 ephemeral volume의 용량이 부족해지면 pod의 상태가 evicted (강제 종료) 되고, 그렇다면 이걸 increase하는 방법은? -> increase he size in the VM configuration or cloud provider! status.podIP
spec.serviceAccountName
spec.nodeName
status.hostIP
Pod를 배포할 때
apiVersion: v1
kind: Pod
metadata:
name: downward
spec:
containers:
- name: main
image: busybox
command: ["sleep", "9999999"]
resources:
requests:
cpu: 15m
memory: 100Ki
limits:
cpu: 100m
memory: 4Mi
env:
- name: POD_NAME. ###### POD_NAME라는 환경변수로 저장하겠다
valueFrom:
fieldRef:
fieldPath: metadata.name. ###### 이 fieldpath에서 가져온 값을!
- 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: SERVICE_ACCOUNT
valueFrom:
fieldRef:
fieldPath: spec.serviceAccountName
- name: CONTAINER_CPU_REQUEST_MILLICORES
valueFrom:
resourceFieldRef:
resource: requests.cpu
divisor: 1m
위의 값을 확인하는 pod를 임시로 하나 만들어서
apiVersion: v1
kind: Pod
metadata:
name: print-greeting
spec:
containers:
- name: env-print-demo
image: bash
env:
- name: GREETING
value: "Warm greetings to"
- name: HONORIFIC
value: "The Most Honorable"
- name: NAME
value: "Kubernetes"
command: ["echo"]
args: ["$(GREETING) $(HONORIFIC) $(NAME)"] #### HERE!
apiVersion: v1
kind: Pod
metadata:
name: downward
labels:
foo: bar
annotations:
key1: value1
key2: |
multi
line
value
spec:
containers:
- name: main
image: busybox
command: ["sleep", "9999999"]
resources:
requests:
cpu: 15m
memory: 100Ki
limits:
cpu: 100m
memory: 4Mi
volumeMounts: ## (pod에 volume 형태로 downwardAPI를 사용하도록 mount)
- name: downward
mountPath: /etc/downward. ### (이 pod의 etc/downward라는 경로에다가)
volumes:
- name: downward
downwardAPI: ###### downwardAPI용 볼륨으로 딱 지정
items:
- path: "podName"
fieldRef:
fieldPath: metadata.name
- path: "podNamespace"
fieldRef:
fieldPath: metadata.namespace
- path: "labels"
fieldRef:
fieldPath: metadata.labels
실제 출력은 pod에 접속해서 etc/downward라는 경로에서 file을 열어서 확인한다.
# k exec -it —/bin/bash kubernetes-downwardapi-volume-example
# cat /etc/downward
kubectl.kubernetes.io/last-applied-configuration="{\"apiVersion\":\"
v1\",\"kind\":\"Pod\",\"metadata\":{\"annotations\":{\"build\":\"two\",
\"builder\":\"john-doe\"},\"labels\":{\"cluster\":\"test-cluster1\",\"
rack\":\"rack-22\",\"zone\":\"us-est-coast\"},\"name\":\"kubernetes-
downwardapi-volume-example\",\"namespace\":\"default\"},\"spec\":{\"
containers\":[{\"args\":[\"while true; do if [[ -e /etc/podinfo/labels
]]; then echo -en '\\\\n\\\\n'; cat /etc/podinfo/labels; fi; if [[ -e
/etc/podinfo/annotations ]]; then echo -en '\\\\n\\\\n'; cat /etc
/podinfo/annotations; fi; sleep 5; done;\"],\"command\":[\"sh\",\"-c\"],
\"image\":\"k8s.gcr.io/busybox\",\"name\":\"client-container\",\"
volumeMounts\":[{\"mountPath\":\"/etc/podinfo\",\"name\":\"
podinfo\"}]}],\"volumes\":[{\"downwardAPI\":{\"items\":[{\"fieldRef\":
{\"fieldPath\":\"metadata.labels\"},\"path\":\"labels\"},{\"fieldRef\":
{\"fieldPath\":\"metadata.annotations\"},\"path\":\"annotations\"}]},\"
name\":\"podinfo\"}]}}\n"
예상 시나리오 : kubectl cluster-info
로 master가 running하고 있는 node IP를 찾아서, 직접 curl request를 통해 metadata에 접근한다.
k cluster-info
Kubernetes master is running at <https://192.168.64.3:8443>
KubeDNS is running at <https://192.168.64.3:8443/api/v1/namespaces/kube-
system/services/kube-dns:dns/proxy>
curl <https://192.168.64.3:8443> -k
{
"kind": "Status",
"apiVersion": "v1",
"metadata": {
},
"status": "Failure",
"message": "forbidden: User \"system:anonymous\" cannot get path \"
/\"",
"reason": "Forbidden",
"details": {
},
"code": 403
}%
API서버는 HTTPS를 사용하고 인증이 필요하기 때문에 직접 통신할 수 없다. -k 옵션을 줘서 서버 인증서 확인을 건너뛰는걸 시도해도 원하는 응답을 얻지 못한다.
그대신
Kubectl proxy
로 서버와 통신할 수 있다.
note) kubectl proxy
Proxy 서버를 실행해서 로컬에서 HTTP연결을 수행하고, 이 연결을 인증을 관리하면서 API server로 전달하기 때문에, 요청할 때 token을 전달할 필요가 없다. 또 각 요청마다 서버의 인증서를 확인해 중간자가 아닌 실제 API server와 통신하는 것을 담당한다.
k proxy
Starting to serve on 127.0.0.1:8001
curl localhost:8001
API server와 application이 직접 통신하는 대신에, main container 옆에 ambassador container를 통해 kubectl proxy를 실행하고, API server와 통신할 수 있다.
지난번 세미나에서 했던 내용처럼 pod의 모든 container는 동일한 loopback network interface를 공유하므로 (플랫 네트워크, localhost로 access 가능) application은 localhost의 port로 proxy server에 access할 수 있다.
https://github.com/kubernetes-client/python
The node was low on resource: ephemeral-storage. Container oooo was using 28Ki, which exceeds its request of 0
라는 메시지를 받게 되었다. 이 때, 징니가 ephemeral-storage의 request를 확인하기 위해 해야할 action과 해결사항은?