Metadata獲取的三種方式

本文的試驗環境為CentOS 7.3,Kubernetes集群為1.11.2,安裝步驟參見kubeadm安裝kubernetes V1.11.1 集群

0. Metadata

每個Pod都有一些信息,包括但不限於以下的內容:

  • Pod 名稱
  • Pod IP
  • Pod 所屬的命名空間
  • Pod 所在的 Node
  • Pod 對應的 service account
  • 每個容器的CPU、內存請求
  • 每個容器的CPU、內存上限
  • Pod 的標籤
  • Pod 的 annotations

這些信息都可以通過kubectl命令獲取,但是有的情況下,我們需要從應用內獲取,例如獲取當前Pod的地址、主機名等一些信息,這就要求我們必須知道如何在應用內獲取Pod的metadata,本文介紹三種應用內獲取Pod的metadata的方式,供大家參考。

1. 通過環境變量暴露Metadata

apiVersion: v1
kind: Pod
metadata:
 name: downward
spec:
 containers:
 - name: main
 image: docker.io/busybox
 command: ["sleep", "99999"]
 resources:
 requests:
 cpu: 15m
 memory: 100Ki
 limits:
 cpu: 100m
 memory: 4Mi
 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: SERVICE_ACCOUNT
 valueFrom:
 fieldRef:
 fieldPath: spec.serviceAccountName
 - name: CONTAINER_CPU_REQUEST_MILLICORES
 valueFrom:
 resourceFieldRef:
 resource: requests.cpu
 divisor: 1m
 - name: CONTAINER_MEMORY_LIMIT_KIBIBYTES
 valueFrom:
 resourceFieldRef:
 resource: limits.memory
 divisor: 1Ki
 

在設置資源請求情況的變量時,會設置一個除數,所以環境變量最後顯示計算後的結果。CPU的除數可以是1或者1m,內存的除數可以是1、1k、1Ki、1M、1Mi。

可以看到實際執行的情況

Metadata獲取的三種方式

2. 以文件的形式傳遞參數

通過定義downwardAPI卷,可以將環境變量以配置文件的方式暴露給容器的應用。

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:
 - name: downward
 mountPath: /etc/downward
 volumes:
 - name: downward
 downwardAPI:
 items:
 - path: "podName"
 fieldRef:
 fieldPath: metadata.name
 - path: "podNamespace"
 fieldRef:
 fieldPath: metadata.namespace
 - path: "labels"
 fieldRef:
 fieldPath: metadata.labels
 - path: "annotations"
 fieldRef:
 fieldPath: metadata.annotations
 - path: "containerCpuRequestMilliCores"
 resourceFieldRef:
 containerName: main
 resource: requests.cpu
 divisor: 1m
 - path: "containerMemoryLimitBytes"
 resourceFieldRef:
 containerName: main
 resource: limits.memory
 divisor: 1

創建Pod後可以查看掛載的文件。

$ kubectl exec downward ls -lL /etc/downward

利用環境變量的方式無法將labels和annotations導入為環境變量,使用掛載文件的方式就可以,我們因此可以查看Pod具有的labels和annotations。當labels和annotations在Pod運行期間被修改後,修改也可以反映到文件上。這也就是為什麼不能用作環境變量的原因。

$ kubectl exec downward cat /etc/downward/labels
$ kubectl exec downward cat /etc/downward/annotations
Metadata獲取的三種方式

在獲取容器的資源請求數據時,我們必須指定容器的名稱。不管一個Pod中有一個還是多個容器,我們都需要明確指定容器的名稱。利用這種方式,如果一個Pod含有多個容器,我們可以將其他容器的資源使用情況傳遞到另外一個容器中。

3. 容器外通過API server獲取metadata

上面介紹的兩種方法可以獲取Pod的相關信息,但是這些信息並不是完整的,如果我們需要更多的信息,就需要用到API server。

$ kubectl cluster-info #查看API Server的位置
$ curl http://ip:port/ #查看API列表,如果是https就不行了
[root@devops-101 ~]# kubectl cluster-info
Kubernetes master is running at https://192.168.0.101:6443
KubeDNS is running at https://192.168.0.101:6443/api/v1/namespaces/kube-system/services/kube-dns:dns/proxy
Metadata獲取的三種方式

對於https的情況,可以設置代理,通過代理來訪問,具體如下:

[root@devops-101 ~]#kubectl proxyk
Starting to serve on 127.0.0.1:8001
# 換一個終端窗口
[root@devops-101 ~]# curl http://localhost:8001
{
 "paths": [
 "/api",
 "/api/v1",
 "/apis",
 "/apis/",
 "/apis/admissionregistration.k8s.io",
 "/apis/admissionregistration.k8s.io/v1beta1",
 "/apis/apiextensions.k8s.io",
 "/apis/apiextensions.k8s.io/v1beta1",
 ...

能夠看到一個列表,通過API的路徑,可以訪問我們想要找到的任何資源。例如查找一個deployment。

[root@devops-101 ~]# curl http://localhost:8001/apis/apps/v1/deployments
{
 "kind": "DeploymentList",
 "apiVersion": "apps/v1",
 "metadata": {
 "selfLink": "/apis/apps/v1/deployments",
 "resourceVersion": "326381"
 },
...

4. 容器內訪問 API Server

容器內訪問API server需要認證,並且需要通過環境變量獲取API Server的地址和端口。

地址的獲取方式如下:

root@curl:/# env | grep KUBERNETES_SERVICE
KUBERNETES_SERVICE_PORT=443
KUBERNETES_SERVICE_HOST=10.0.0.1
KUBERNETES_SERVICE_PORT_HTTPS=443

認證主要通過ca.cert及用戶名,ca.cert文件默認掛載在/var/run/secrets/kubernetes.io/serviceaccount/。

具體方法:

[root@devops-101 ~]# kubectl exec -it img-curl /bin/sh 
/ # TOKEN=$(cat /var/run/secrets/kubernetes.io/serviceaccount/token)
/ # curl --cacert /var/run/secrets/kubernetes.io/serviceaccount/ca.crt -H "Authorization: Bearer $TOKEN" https://kubernetes
{
 "paths": [
 "/api",
 "/api/v1",
 "/apis",
 "/apis/",
 "/apis/admissionregistration.k8s.io",
 "/apis/admissionregistration.k8s.io/v1beta1",
 "/apis/apiextensions.k8s.io",

如果遇到了下圖中的錯誤,需要創建RBAC的角色綁定並且重新執行一下上面的命令。

Metadata獲取的三種方式

接下來就可以在Pod的容器中查看metadata的信息,如下查看當前命名空間所有運行的Pods

Metadata獲取的三種方式

有了訪問API server的能力,就為我們定義容器內應用的行為提供了無限的想象力,我們可以通過curl來訪問API server,同時也有很多語言的客戶端庫,讓我們方便的在自己的應用中調用API server

  • Java client
  • Node.js
  • PHP
Metadata獲取的三種方式


分享到:


相關文章: