如何获取k8s元数据信息
介绍通过Downward API和REST获取k8s元数据
本文基于《Kubernetes in Action》第8章整理。
虽然k8s作为云基础设施,部署在其上的应用不应该感知到k8s的存在。但是业务场景千千万,总会碰到需要获取k8s元数据的情况。特此记录几种获取方式
Downward API
Downward API是通过环境变量或者文件的方式,将pod的元数据暴露给pod中的应用。可以传递给容器的数据包括
- pod的名称
- pod的IP
- pod所在的命名空间
- pod运行的节点名称
- pod归属的服务账户的名称
- 每个容器请求的CPU和内存的使用量
- 每个容器请求的CPU和内存的限制
- pod的标签
- pod的注解
环境变量的方式示例
apiVersion:v1
kind: Pod
metadata:
name: example
spec:
containers:
- name: my-container
image: test-image
command: ["sleep", "999999"]
resources:
requests:
cpu: 250m
memory: 520Mi
limits:
cpu: 1
memory: 1Gi
env:
- name: POD_NAME
valueFrom:
fieldRef:
fieldPath: metadata.name
- name: CPU_REQUEST
valueFrom:
resourceFieldRef: # CPU和内存使用量是引用resourceFieldRef
resource: requests.cpu
divisor: 1m
在配置CPU和memory相关的环境变量时,需要设置divisor,即基数单位。实际的环境变量的值是资源请求值除以这个基数单位。因此CPU_REQUEST的值,在这个例子中的值是250m / 1m = 250。对于cpu而言,请求量可以设置成1(表示1核),或者1m(表示千分之一核);内存可以设置成1(表示1字节),1K或1Ki,1M或者1Mi。
基于卷的方式示例
apiVersion:v1
kind: Pod
metadata:
name: example
labels:
my-labels: test
spec:
containers:
- name: my-container
image: test-image
command: ["sleep", "999999"]
resources:
requests:
cpu: 250m
memory: 520Mi
limits:
cpu: 1
memory: 1Gi
volumeMounts:
- name: downward
mountPath: /etc/downward
volumes:
- name: downward
downwardAPI:
items:
- path: "podName"
fieldRef:
fieldPath: metadata.name
- path: CPU_REQUEST
- name: CPU_REQUEST
resourceFieldRef: # CPU和内存使用量是引用resourceFieldRef
resource: requests.cpu
divisor: 1m
containerName: my-container
downward卷是pod级别的,因此当要暴露容器级别的元数据时,需要指定容器名称。
基于卷和环境变量暴露元数据的区别
- 标签和注解只可以通过卷暴露。因为可以在pod运行时修改标签和注解,当更新后,k8s会更新存有相关信息的文件,从而让pod可以获取最新的数据,而环境变量的方式,新的值无法被暴露。
- 通过卷的方式,可以传递一个容器的资源字段到另一个容器。而环境变量方式,只能传递它自身资源的请求和限制信息。
与k8s API服务器交互
在节点上与API服务器交互
首先需要知道API服务器的地址,可以执行下面命令获取
kubectl cluster-info
从执行结果看,服务器使用的是HTTPS协议,因此需要对API服务器进行认证。当然在测试的时候可以通过curl的--insecure选项跳过对API服务器的认证,因此可以通过以下命令尝试访问API服务器
curl https://<K8S-API-HOST>:<K8S-API-PORT> -k # 注意替换变量
但是服务器会返回Unauthorized,因为服务器需要对我们进行认证和鉴权
不过,我们可以启动一个代理服务器,封装所有这些安全认证操作,我们只需要和代理服务器交互即可。启动代理服务的方式如下
$ kubectl proxy
Starting to serve on 127.0.0.1:8001
可以通过以下命令访问API服务器
curl localhost:8001
此时,服务器会返回一组路径的清单。当尝试请求这些路径时,会发现返回体一般有两种kind,分别是APIGroup和APIResourceList。但返回的kind=APIGroup时,返回的信息主要是PAI版本信息;当返回的kind=APIResourceList时,返回的是这个API版本下包含的资源信息,以及REST请求的相关信息。
在pod内部访问API服务器
如上面说到的,要想和API服务器交互,需要双向认证。因此我们需要一个可信任的CA证书认证API服务器,我们也需要提供一个TOKEN,让API服务器进行认证和鉴权。
k8s中有一个name=kubernetes的服务,指向的就是API服务器。
对于每个pod而言,都有一个ServiceAccount,其本身就是用于和k8s API服务器进行交互的。ServiceAccount会关联一个secret,这个secret包含ca.crt,namespace,token三项内容,并挂载到
/var/run/secrets/kubernetes.io/serviceaccount目录下。
ca.crt包含了CA的证书,用于对API服务器证书进行认证。token是用来获取API服务器的授权。因此可以通过下面的形式和API服务器进行交互
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
其他优化方法
可以在pod中多部署一个容器,在这个容器中运行kubectl proxy命令,通过它来实现与API服务器的交互。因此,主容器中就可以直接和这个proxy容器交互,免去了繁琐的安全认证操作
更多推荐
所有评论(0)