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。 可以看到實際執行的情況

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

在獲取容器的資源請求數據時,我們必須指定容器的名稱。不管一個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

對於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的角色綁定並且重新執行一下上面的命令。

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

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

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章